././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735242.034269 quodlibet-4.6.0/0000755000175000017500000000000014471213412012202 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919751.0 quodlibet-4.6.0/.deepsource.toml0000664000175000017500000000021114231604507015312 0ustar00nicknickversion = 1 test_patterns = ["tests/**"] [[analyzers]] name = "python" enabled = true [analyzers.meta] runtime_version = "3.x.x" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/.readthedocs.yaml0000664000175000017500000000017714244626671015455 0ustar00nicknickversion: 2 sphinx: configuration: docs/conf.py python: version: 3.8 install: - requirements: docs/requirements.txt ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/COPYING0000664000175000017500000004325414035600052013243 0ustar00nicknick GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, 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. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/MANIFEST.in0000664000175000017500000000155214244626671013762 0ustar00nicknickinclude COPYING include HACKING include NEWS.rst include README.rst include po/*.po include po/*.pot include po/POTFILES.in include po/POTFILES.skip include quodlibet/images/Makefile recursive-include quodlibet/images/hicolor *.svg *.png *.svg.in include tests/data/* recursive-include tests *.py recursive-include quodlibet update.sh *.pyi include gdist/*.py include data/*.desktop.in include data/*.ini include data/*.service.in include data/*.appdata.xml.in include data/*.1 include data/*.sh include data/*.zsh include data/*.bash include data/README.rst include MANIFEST.in include quodlibet/packages/README.rst include *.py include *.yaml include *.toml include setup.cfg include pyproject.toml include poetry.lock recursive-include docs *.py Makefile *.rst *.png *.ico *.svg *.css requirements.txt prune docs/_build_guide prune docs/_build_all prune docs/_rtd_theme* ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1692707619.0 quodlibet-4.6.0/NEWS.rst0000644000175000017500000041704614471125443013532 0ustar00nicknick.. _News: .. _release-4.6.0: 4.6.0 (2023-08-22) - Ah, perfect, the banner that satisfies everyone -------------------------------------------------------------------- Packaging Changes * Quodlibet now requires Python 3.8+ * It also now supports Python 3.11 * libsoup3 is now required (up from version 2) ℹ️ A highlight of the changes in 4.6.0 is below. For full details, see `the 4.6 commit log `_. General * Audiofeeds: enable clipboard when adding feed :pr:`4128` (:user:`Nick Boultbee `) * Fix aggregate units on numeric comparisons :pr:`4089` (:user:`Nick Boultbee `) * Fix playlist renaming bug :pr:`4079` (:user:`Nick Boultbee `) * Remove some senf helpers that are more or less the same in the Python 3 stdlib :pr:`4041` (:user:`lazka`) * Require Python 3.8 :pr:`3956` (:user:`lazka`) * Move to libsoup3 (#4294) (:user:`Nick Boultbee `) * Add Stop command to Control menu (#4213) (:user:`Markus Koller`) * Allow disabling of songlist sorting (#4273) (:user:`Nick Boultbee `) * Add human time tags (#4275) (:user:`Nick Boultbee `) * Nicer prefs switches (#4274) (:user:`Nick Boultbee `) * Fix shuffle history (#4255) (:user:`Thomas Leberbauer`) * Fix pop-up menu for Podcasts (#4193) (:user:`Nick Boultbee `) * Add CLI arg: --with-pattern (#4166) (:user:`Felicián Németh`) * Modernise entire preferences UI 🎨 (#4175) (:user:`Nick Boultbee `) * Allow songlist editing of simple text tags in-place 🆙 (#4173) (:user:`Nick Boultbee `) * Make --rating-up work when song has no previous rating (#4172) (:user:`Felicián Németh`) * Don't make the WaitLoadWindow modal (#4171) (:user:`David Greaves`) * Prompt on attempting to extend a playlist with DnD'ed tracks (#2746) (:user:`Meriipu`) * Stop query date regex from matching > 4 digit year (#4162) (:user:`afontenot`) * Add "edit" button to column tag editor window (#4148) (:user:`afontenot`) * Track List: Add shortcut Ctrl-Return to the searchbar (#4141) (:user:`Felicián Németh`) * Fix crash when using covergrid + default art size (#4151) (:user:`afontenot`) * Disable ordering when active order disappears (#4156) (:user:`afontenot`) * Improve notif progress bar (#4147) (:user:`Nick Boultbee `) * Playlists: log about potential import failures (#4146) (:user:`Nick Boultbee `) * Fix regression of --print-query (#4142) (:user:`Felicián Németh`) * Rename feeds -> podcasts (#3513) (#4139) (:user:`Nick Boultbee `) * Audiofeeds: handle non-feed URLs (#4126) (:user:`Nick Boultbee `) * Fix image size scaling when cover is reloaded (#4115) (:user:`Thomas Leberbauer`) * Covergrid using FlowBox (#4101) (:user:`Thomas Leberbauer`) * Softer cover art outline (#4096) (:user:`Nick Boultbee `) * Disable editing for Soundcloud tracks (#4097) (:user:`Nick Boultbee `) * Fix lots of browser padding issues (#4066) (:user:`Nick Boultbee `) * Make songs heading entries editable (#4046) (#4047) (:user:`Nick Boultbee `) * XSPF formatting (#4028) (:user:`Nick Boultbee `) * Support library watching in the core (#3654) (:user:`Nick Boultbee `) * Write XSPFs with proper namespace (internal v2) (#3984) (:user:`Nick Boultbee `) * Move library: don't force source dir to exist (#3980) (:user:`Nick Boultbee `) * Fix add playlists errors (#3973) (#3974) (:user:`TheMelmacian`) * Fix display pattern not updating in browsers (#3975) (:user:`Thomas Leberbauer`) Developer * osx: fix installation with setuptools (:user:`Christoph Reiter `) * osx: update jhbuild (:user:`Christoph Reiter `) * osx: fix cargo/rustup usage in jhbuild (:user:`Christoph Reiter `) * osx_bundle: move to 10.13+ (:user:`Christoph Reiter `) Plugins * Improve and fix Sonos plugin (#4290) (:user:`Nick Boultbee `) * Tidy export to folder plugin (:user:`Nick Boultbee `) * Unique filters plugin (#4264) (:user:`LoveIsGrief`) * playlist export: prefix relative paths with '.' if the path starts with '#' (#4236) (:user:`Felix Krull`) * Add a new internal tag: ~json (#4195) (:user:`Felicián Németh`) * 🆕 Bookmarks notifications plugin (#4174) (:user:`Nick Boultbee `) * Move listenbrainz plugin to the right location (#4192) (:user:`Felicián Németh`) * the sync_to_device plugin shouldn't delete files named 'cover.jpg' (#4083) (:user:`Jan`) * Album art downloader: improve GUI (#4106) (:user:`Nick Boultbee `) * Album art downloader: remove Amazon (#4105) (:user:`Nick Boultbee `) * Embed Images plugin: allow choosing a file from disk (#4071) (:user:`Nick Boultbee `) * Add plugin for rich presence in Discord. (#3998) (:user:`Aditi K`) Translations * Thanks to all our translators old and new. * These are now listed on the `Weblate QL project `_. .. _release-4.5.0: 4.5.0 (2022-03-29) - What sort of things would you like to know? ---------------------------------------------------------------- Packaging Changes: * Quodlibet should now support Python 3.10 * This will be the last release supporting Windows 7 General: * Allow auto-playing added songs in Queue Only mode (:pr:`3947`) (:user:`afontenot`) * Soundcloud: Better Stream fetching (:pr:`3949`) (:user:`Nick Boultbee `) * Don't clear queue when set_explicit returns None (:pr:`3913`) (:user:`afontenot`) * Waveform plugin improvements: (:pr:`3944`) (:user:`Nick Boultbee `) * Strip blank tags out from metadata lists (:pr:`3914`) (:user:`afontenot`) * Edit tags: Hide multi-line tags if selected (:pr:`3941`) (:user:`Nick Boultbee `) * Lyrics pane: switch to genius.com (:user:`Nick Boultbee `) * Validate units for tag expressions (:pr:`3932`) (:user:`Nick Boultbee `) * Support downloading remote files (:pr:`3926`) (:user:`Nick Boultbee `) * Improve the console plug-in in a number of ways (:pr:`3923`) (:user:`afontenot`) * Wrap 'tags' into a link to the tags wiki page (:pr:`3920`) (:user:`Tobi`) * Add an option to set how missing titles are displayed (:pr:`3905`) (:user:`Jej`) * Increase space between icon and text (:pr:`3918`) (:user:`Jej`) * Icon relooking proposal (:pr:`3889`) (:user:`Jej`) * Plugin window GUI improvements (:pr:`3900`) (:user:`Jej`) * A new option to set how a song is considered as played (:pr:`3873`) (:user:`Jej`) * Rewrite Soundcloud interaction a bit (:pr:`3893`) (:user:`Nick Boultbee `) * New config option for search bar historic count (:pr:`3885`) (:user:`Jej`) * Clear queue icon and config button improvement (:pr:`3879`) (:user:`Jej`) * Less annoying autosave of play queue (:pr:`3649`) (:user:`Nick Boultbee `) * Make current file react to changes on the current song (:pr:`3731`) (:pr:`3871`) (:user:`Nick Boultbee `) * Tracks count UI enhacement (:pr:`3867`) (:user:`Jej`) * Reworked "Stop on pause" language (:pr:`3809`) (:user:`Allan Nordhøy`) * Pass entered playlist title through (:user:`Nick Boultbee `) * Scrobble plugin: autosave cache more (#2951 / #3649) (:pr:`3857`) (:user:`Nick Boultbee `) * Save play queue batched or periodically (#3649) (:pr:`3854`) (:user:`Nick Boultbee `) * Add a keyboard shortcut for rescanning the library (:pr:`3781`) (:user:`Marcin Mielniczuk`) * Make some overlooked strings translatable (:pr:`3782`) (:user:`Till Berger`) * Make link text translatable in plugin descriptions (:pr:`3806`) (:user:`Till Berger`) * Feature: Support description and language in lyrics (USLT) [WIP, comments appreciated] (:pr:`3769`) (:user:`h88e22dgpeps56sg`) * Allow markup in plugin descriptions (:pr:`3792`) (:user:`Nick Boultbee `) * ReplayGain: Disambiguate column heading (:pr:`3788`) (:user:`Till Berger`) * Set empty input shape for hints window (:pr:`3749`) (:user:`Thomas Leberbauer`) * Add autocompletion to console plugin (:pr:`3728`) (:user:`halfbrained`) * New plugin to send a stop signal to the player backend on pause (:pr:`2848`) (:user:`othalan`) * Added a unified and flexible ImportExport plugin (:pr:`3705`) (:user:`Joschua Gandert `) * Add Album column to plugin dialog window (:pr:`3650`) (:user:`Maksim Liauchuk`) * Moved Burn CD plugin commands into custom commands plugin (:pr:`3636`) (:user:`Joschua Gandert `) * Closes #3631: Remove Web Lyrics plugin (:pr:`3633`) (:user:`Joschua Gandert `) * 🆕 Playlists library (#518) (:pr:`3532`) (:user:`Nick Boultbee `) * Prioritise IDs in album keys (:pr:`3617`) (:user:`Nick Boultbee `) * Remove tracks when scandirs removed (:pr:`3621`) (:user:`Nick Boultbee `) * Support .m4b (AudioBook)files (:pr:`3602`) (:user:`Nick Boultbee `) * Ignore auto_sort when shuffle is enabled (:pr:`3581`) (:user:`luk1337`) * Finish up collections -> collections.abc migration :pr:`3800` (:user:`luk1337`) * Follow-up to #3749 :pr:`3766` (:user:`slosd`) Fixes: * Fix Soundcloud auth (a bit) (:user:`Nick Boultbee `) * Exfalso: fix prefs (:pr:`3838`) (:user:`Nick Boultbee `) * Handle missing playlist library better (:user:`Nick Boultbee `) * Fix excess minimum height of plugin window with long description (:pr:`3785`) (:user:`Till Berger`) * Fix string that should not be translatable (:pr:`3783`) (:user:`Till Berger`) * Remove some superfluous tooltip text (:pr:`3784`) (:user:`Till Berger`) * Fix hidden files (#3916) (:pr:`3917`) (:user:`Nick Boultbee `) * fix 'Convert Encoding' plugin (:pr:`3825`) (:user:`Sergey`) * Make missing pixbufs less fatal (:pr:`3758`) (:user:`Nick Boultbee `) * Do not start dragging from empty treeview area (#3538) (:pr:`3751`) (:user:`Thomas Leberbauer`) * Fix translated menu labels for playorder plugins and add accelerators (:pr:`3787`) (:user:`Till Berger`) * Fix RG wikipedia link (:user:`Nick Boultbee `) * Soundcloud: rework API (:pr:`3768`) (:user:`Nick Boultbee `) * Soundcloud: ignore tracks with no URL (:user:`Nick Boultbee `) * Fix info area not updating on songlist removal (:pr:`3663`) (:user:`Nick Boultbee `) * EF: Fix double-calling of header bar code (:pr:`3711`) (:user:`Nick Boultbee `) * Fix soundcloud parsing (:pr:`3721`) (:user:`Nick Boultbee `) * Ignore dotfiles in Playlist dir (:user:`Nick Boultbee `) * Bugfix and clean up for utils.fifo (:pr:`3761`) (:user:`Martijn Pieters`) * Players: Only query song from a source if there is one (:user:`Nick Boultbee `) * Fix icon for library removal prompt (:user:`Nick Boultbee `) * Fix #3611: assert that __fav_stations is not None (:user:`Joschua Gandert `) * Propagate repeat options properly in mpris2 plugin (:pr:`3723`) (:user:`luk1337`) * Tray Icon: Better errors / logging for import failures (:user:`Nick Boultbee `) * PL library: only filter out dotfile-like files (:user:`Nick Boultbee `) * CLI: better error for unmodifiable files (:user:`Nick Boultbee `) * reload(): only migrate actual internal tags (:pr:`3618`) (:user:`Nick Boultbee `) * Various fixes around lyrics and remote files (:user:`Nick Boultbee `) * Ex Falso prefs: fix missing parent bug (:user:`Nick Boultbee `) * Don't throw when no song is playing (:user:`Nick Boultbee `) Developer: * Improve release notes script (:user:`Nick Boultbee `) * test_setup: fix with newer setuptools (:user:`Christoph Reiter `) * tests: don't disable gstreamer registry updates under flatpak (:user:`Christoph Reiter `) * Lastfmsync tidy (:pr:`3937`) (:user:`Nick Boultbee `) * Inkscape --export-png deprecated option (:pr:`3870`) (:user:`Jej`) * Mypy - change directory in tests (:user:`Nick Boultbee `) * Formats: various lint improvements (:user:`Nick Boultbee `) * Scrobbler: small linting / refactorings (:user:`Nick Boultbee `) * Xiph: modernise some Python (:user:`Nick Boultbee `) * tests: skip test_libc on osx (:user:`Christoph Reiter `) * Refactor gettext code (:pr:`3737`) (:user:`Nick Boultbee `) * Fix some test signal handling (:pr:`3774`) (:user:`Nick Boultbee `) * Small Soundcloud refactors, split out: (:pr:`3773`) (:user:`Nick Boultbee `) * Tidy gettext tests (:user:`Nick Boultbee `) * dmgbuild: port from biplist to plistlib (:user:`Christoph Reiter `) * macos: more updates; switch from gnutls to openssl (:user:`Christoph Reiter `) * macos: a round of jhbuild package updates (:user:`Christoph Reiter `) * checkupdates: reduce threadpool workers to not hit arch api rate limit (:user:`Christoph Reiter `) * checkupdates: port to pypi json api (:user:`Christoph Reiter `) * Support flaky tests (:pr:`3695`) (:user:`Nick Boultbee `) * Added ObjectListMatcher utility class (:pr:`3656`) (:user:`Joschua Gandert `) * CI: fix Windows test directory detection (:pr:`3646`) (:user:`Nick Boultbee `) * Remove PicklingLibrary & better library typing (:user:`Nick Boultbee `) * Tests: dump flake8 output better on failure (:user:`Nick Boultbee `) * Update the contact options (:user:`Christoph Reiter `) * rtd: enforce a newer sphinx-rtd-theme version (:user:`Christoph Reiter `) * rtd: try installing a newer sphinx_rtd_theme (:user:`Christoph Reiter `) * Fix copool tests, extract common code (:pr:`3657`) (:user:`Nick Boultbee `) * Tweak `test_terms_letter_case` to account for query-syntax examples (:pr:`3813`) (:user:`Till Berger`) * Fixed Code Quality Issues (:pr:`3583`) (:user:`Ankit Dobhal`) * Add release infos in appdata files (:user:`Christoph Reiter `) * Fix distcheck (:user:`Christoph Reiter `) * Commit .pot file to git :pr:`3665` (:user:`lazka`) * setup.py: add a create_pot command :pr:`3664` (:user:`lazka`) * wininst: stop pinning pypi deps (:user:`Christoph Reiter `) * wininst: remove frei0r (:user:`Christoph Reiter `) * Create GitHub Actions automated testing for Fedora 33 (resolves #3542) (:pr:`3558`) (:user:`Phillip Julien`) * downloads: remove all unstable repos (:user:`Christoph Reiter `) * Update universe (but lock) (:pr:`3607`) (:user:`Nick Boultbee `) Docs: * Corrected description of ~people internal tag. (:pr:`3938`) (:user:`Alexander Browne`) * Docs: Update release checklist / maintenance (:user:`Nick Boultbee `) * Tidy docs around queue (:user:`Nick Boultbee `) * Docs: tidy some images (:user:`Nick Boultbee `) * Update exfalso.rst (:pr:`3845`) (:user:`Steve Harris`) * Update quodlibet.rst (:pr:`3846`) (:user:`Steve Harris`) * Update patterns.rst (:pr:`3819`) (:user:`everdred`) * Update macos devenv setup documentation (:pr:`3759`) (:user:`Martijn Pieters`) * Update the translation guide for the weblate switch (:user:`Christoph Reiter `) * docs: show the translation status (:user:`Christoph Reiter `) * docs: mention weblate in the translation guide (:user:`Christoph Reiter `) * Lots of README updated :book: (:pr:`3625`) (:user:`Nick Boultbee `) * FAQ: where QL store data outdated (:pr:`3878`) (:user:`Jej`) Translations: * Galician * Adolfo Jayme Barrientos (308) * Turkish * Ömer Faruk Çakmak (3) * E-Akcaer (1149) * German * Till Berger (292) * Danish * scootergrisen (17) * Greek * Dimitris Papageorgiou (77) * Ukrainian * Tymofii Lytvynenko (1) * Andrij Mizyk (542) * Portuguese * Adolfo Jayme Barrientos (8) * ssantos (111) * English (United Kingdom) * Nick Boultbee (4) * Tom Fryers (4) * Indonesian * I. Musthafa (31) * Dutch * ikmaak (5) * Heimen Stoffels (96) * Spanish * germe-fur (85) * Adolfo Jayme Barrientos (1205) * French * Adolfo Jayme Barrientos (1) * Jej@github (136) * Bundy01 (481) * Finnish * Kristian Laakkonen (166) * Korean * Johndoe0153 (419) * Slovak * menom (75) * Marek Felšöci (1527) * Chinese (Simplified) * stoodvolleyball (1) * 梁普行 (5) * Pig Fang (19) * JER-ry (249) * Eric (464) .. _release-4.4.0: 4.4.0 (2021-02-28) - PERFECTION IS BACK ON THE MENU --------------------------------------------------- Packaging Changes: * One ``quodlibet/`` subdirectory has been removed - e.g. ``quodlibet/tests/`` -> ``tests/`` (#3238) * Move to Python 3.7 (closing #3433) :pr:`3438` (:user:`Nick Boultbee `) * macos: bundle.sh: clone from ../.. rather than .., fixing #3393. (:pr:`3394`) (:user:`Sam Hathaway `) * win_installer: pass options to build script on env switch :pr:`3328` (:user:`Gabor Karsay `) * Depend on musicbrainzngs>=0.6 (:user:`Christoph Reiter `) General: * Switch to XSPF for Playlists (closing #1122) :pr:`3242` (:user:`Nick Boultbee `) * Renamed "Search Library" to "Track List" browser (:user:`Joschua Gandert `) * Support moving library folders (scandirs) :pr:`3506` (:user:`Nick Boultbee `) * Support JACK via Gstreamer :pr:`3511` (:user:`Nick Boultbee `) * Make ID3 Replaygain ALL_CAPS `:pr:`3475` (:user:`Nick Boultbee `) * MP4: Support description tag (:user:`Nick Boultbee `) * Advanced prefs: use checkboxes (:user:`Nick Boultbee `) * Add comment to track headers (:user:`Nick Boultbee `) * Change None to empty string to fix TypeError in missing.py :pr:`3548` (:user:`Ironbalden`) * Plugin window: don't appear on top (:user:`Nick Boultbee `) * Info Area: Allow space to play / pause (:user:`Nick Boultbee `) * Allow ctrl-[shift]-tab in Notebook windows (Edit Tags, Song Info, Prefs etc) (:pr:`3496`) (:user:`Nick Boultbee `) * Playlists: don't clear on deletion (fixing #3491) (:user:`Nick Boultbee `) * IRadio - do station updates in background :pr:`3310` (:user:`Nick Boultbee `) * Improve plugin window style :pr:`3481` (:user:`Nick Boultbee `) * Query: allow validation from extensions :up: (:user:`Nick Boultbee `) * Plugins: improve query plugins :pr:`3485` (:user:`Nick Boultbee `) * Saved list editor: improve style (:user:`Nick Boultbee `) * Tag Editor: Add smart replacer for colon delimiters (:pr:`3456`) (:user:`Nick Boultbee `) * Improve local cover art detection (#3454) (:pr:`3459`) (:user:`Nick Boultbee `) * Add support for TKEY 'Initial Key' column (:pr:`3420`) (:user:`Cole Robinson`) * add ability to sort by date added to Album List Browser (:pr:`3410`) (:user:`Uriel Zajaczkovski`) * Add originalartistsort (:user:`Nick Boultbee `) * add check to Missing.py, fix #3336 (:pr:`3382`) (:user:`Ironbalden`) * Add support for ~elapsed and ~#elapsed (:pr:`3379`) (:user:`Nick Boultbee `) * Format date panes (closing #3346) :pr:`3349` (:user:`Nick Boultbee `) * Update song order in song list when modified :pr:`2509` (:user:`Thomas Leberbauer`) * Restyle the search query :pr:`3517` (:user:`Nick Boultbee `) * Fix non-splitter EditTags plugins (fixing #3468) :pr:`3470` (:user:`Nick Boultbee `) * Support feedparser 6.0 :pr:`3464` (:user:`Christoph Reiter `) * formats: Don't return lyrics with embedded nulls :pr:`3402` (:user:`Christoph Reiter `) * Fix setting pane mode :pr:`3365` (:user:`Michael Kuhn `) * windows: Fix playing files on network shares (fixing #3361) :pr:`3371` (:user:`d10n`) * Restarting :pr:`3211` (:user:`blimmo`) * Closes #946: Rename cover filename option :pr:`3235` (:user:`Joschua Gandert `) * Closes #1769: Allow multiple entries for cover files :pr:`3236` (:user:`Joschua Gandert `) Plugins: * Add listenbrainz scrobbling plugin. :pr:`3528` (:user:`Ian Campbell`) * First version of Musicbrainz Sync plugin that sends ratings (:pr:`3180`) (:user:`LoveIsGrief`) * add plugin 'synchronize to device' :pr:`636` (:user:`Jan`) * Fix weighted shuffle not shuffling when total rating is zero. :pr:`3397` (:user:`blimmo`) * ext/inhibit: Add option to inhibit suspend :pr:`3309` (:user:`antigone-xyz`) * trayicon: only check for org.kde.StatusNotifierWatcher for the appindicator :pr:`3313` (:user:`Christoph Reiter `) * MQTT authentication :pr:`3391` (:user:`Jeroen7V`) * Add "Rate" to D-Bus API :pr:`3455` (:user:`LoveIsGrief`) * Prettier sync lyrics (:user:`Nick Boultbee `) * Synchronizedlyrics: Rewrite lyrics parsing, supporting >60min songs (:user:`Nick Boultbee `) * Add Sonos playlist export plugin :pr:`3487` (:user:`Nick Boultbee `) * Plugin: fix Cover Art window persistence (:user:`Nick Boultbee `) * Skip songs: rename & naming / text updates (:user:`Nick Boultbee `) * Cover Art Downloader: remove failing downloads from results (:user:`Nick Boultbee `) * Cover Art: Improve Musicbrainz downloader (:user:`Nick Boultbee `) * Cover Art download: only trigger plugin if `album` tag available (:user:`Nick Boultbee `) * Added AutoUpdateTagsInFiles plugin :pr:`3200` (:user:`Joschua Gandert `) Translations: * Update Polish translation :pr:`3323` * Update italian translation :pr:`3405` (:user:`dprimon`) * Updated Dutch translation :pr:`3441` (:user:`Vistaus`) * Update British English translation :pr:`3483` (:user:`Nick Boultbee `) Documentation: * Update plugin development page (:user:`Nick Boultbee `) * Update plugins.rst to include locations on MacOS. :pr:`3562` (:user:`BraveSentry`) * Fixed documentation URLs :pr:`3425` (:user:`TehPsychedelic`) * Fix link to contributing guide :pr:`3416` (:user:`remvee`) * Various docs updates / improvements (:user:`Nick Boultbee `) * Docs: Improve / tidy renaming files examples (:user:`Nick Boultbee `) * docs: fix the windows dev environ instructions (:user:`Christoph Reiter `) Developer: * Various Python 2 leftovers and updates :pr:`3440` (:user:`Nick Boultbee `) * tests/operon: make argument names meaningful :pr:`3294` (:user:`Jan Tojnar `) * gettextutil: warn on gettext warnings instead of erroring out :pr:`3545` (:user:`Christoph Reiter `) * CI: re-enable flatpak tests :pr:`3501` (:user:`Christoph Reiter `) * CI: install MSYS2 packages via the GHA :pr:`3458` (:user:`Christoph Reiter `) * Tests: improve source scanning (:user:`Nick Boultbee `) * Refactor: tidy Gstreamer player code :pr:`3489` (:user:`Nick Boultbee `) * Add .editorconfig that agrees with PEP-008 and our Flake8 config (:user:`Nick Boultbee `) * Refactor ID3 tag writing for readability `pr:3476` (:user:`Nick Boultbee `) * More type hints (:user:`Christoph Reiter `) * CI: Port more things to github actions (:user:`Christoph Reiter `) * Switch from pycodestyle/pyflakes to flake8 (:user:`Christoph Reiter `) * Move the main sources into the repo root (:user:`Christoph Reiter `) * Remove pipenv support (:user:`Christoph Reiter `) .. _release-4.3.0: 4.3.0 (2020-02-22) - Smaug-like figures, lurking on our planet filled with hoarded data --------------------------------------------------------------------------------------- Packaging Changes: * Various installed files have been renamed ("exfalso" -> "io.github.quodlibet.ExFalso") to work better with Flatpak * zsh completion file installation location changed to site-functions :pr:`3300` * Installs a new bash completion file :pr:`3126` :pr:`3128` * Windows: Moved everything from 32 bit to 64 bit. This means QL will no longer work with 32 bit Windows. Translations: * Update brazilian portuguese translations :pr:`3123` (:user:`Hugo Gualandi `) * Bulgarian translation fixes :pr:`3147` (:user:`cybercop-montana`) * Update Hebrew translation :pr:`3164` :pr:`3274` (:user:`Avi Markovitz `) * French translation update :pr:`3183` (:user:`Bundy01`) * Update German translation (:user:`Till Berger `) * Various translation related spelling/formatting/text improvements :pr:`3208` :pr:`3207` :pr:`3206` :pr:`3214` :pr:`3215` :pr:`3218` :pr:`3219` (:user:`Till Berger `) * New Serbian translation :pr:`3245` (:user:`leipero`) * Update Finnish translation :pr:`3199` (:user:`Kristian Laakkonen `) General: * Simplify launcher for macOS :pr:`3101` (:user:`a-vrma`) * Add original date sort option to album browser :pr:`3103` (:user:`Ruud van Asseldonk `) * Option for multiple queries in Search Browser :pr:`3082` (:user:`blimmo`) * Improved `VGM` Metadata Tag Parsing (GD3 Support) :pr:`3100` (:user:`Eoin O'Neill `) * cover: Always scale down to parent window size :pr:`3114` (:user:`Fredrik Strupe `) * tags: Support loading lyrics from 'unsyncedlyrics' tag :bug:`3115` (:user:`Fredrik Strupe `) * browsers: Focus album list on album filtering :bug:`3122` (:user:`Fredrik Strupe `) * Add bash completion :pr:`3126` :pr:`3128` (:user:`Arnaud Rebillout `) * Docs fixes :pr:`3133` :pr:`3192` (:user:`Petko Ditchev `, :user:`CreamyCookie`) * player: Make external volume cubic by default :pr:`3151` (:user:`Fredrik Strupe `) * desktop: Accept all selected files when opened from file browser :bug:`3159` (:user:`Fredrik Strupe `) * Tracks without track number are now sorted before first track :pr:`3196` (:user:`CreamyCookie`) * Add option for ignoring characters in queries :pr:`3221` (:user:`blimmo`) * Disable the file trash support under flatpak for now :bug:`3093` * zsh completion improvements :pr:`3300` (:user:`Matthew Martin `) * Add poetry support :pr:`3306` (:user:`Nick Boultbee `) Plugins: * Import metadata plugin: Fix file renaming :bug:`3071` (:user:`Fredrik Strupe `) * Scale player volume properly in mpris2 API :pr:`3098` (:user:`luk1337`) * mpris: Drop MPRIS1 support :pr:`3102` * Add new Banshee import plugin :pr:`3141` (:user:`Phidica`) * Library update plugin: Update on file modifications :bug:`3168` (:user:`Fredrik Strupe `) * Add "Record Stream" to default custom commands plugin :bug:`1617` (:user:`CreamyCookie`) * Custom Commands: Don't modify command when using parameters :bug:`3185` :pr:`3232` (:user:`CreamyCookie`) * Import/export plugin: accept full filenames when renaming :pr:`3282` (:user:`Fredrik Strupe `) * acoustid: fix queries always returning "unknown" :bug:`3269` * Fix embed images plugin submenu not showing sometimes :pr:`3303` (:user:`Nick Boultbee `) .. _release-4.2.1: 4.2.1 (2018-12-26) - DO NOT WEAR THE HAT UNDER ANY CIRCUMSTANCES ---------------------------------------------------------------- Translations: * Hebrew translation update :bug:`3027` (:user:`Avi Markovitz `) * German translation update :pr:`3036` (:user:`Till Berger `) Fixes: * Fix freezes when opening the shortcuts window with i3wm :bug:`3055` (:user:`Fredrik Strupe `) * xinebe: Fix error when pausing a non-local stream :bug:`3057` * Fix mmkeys error (preventing QL to start) when mate-settings-daemon is running outside of a mate session :bug:`3056` * Fix some panels/docks not being able to match the app with the desktop file :bug:`3029` * Migrate metadata plugin fixes :bug:`3070` (:user:`Fredrik Strupe `) .. _release-4.2.0: 4.2.0 (2018-10-31) - staffed by the living ------------------------------------------ Packaging Changes: * **gettext 0.19.8** required (was 0.15) * **intltool** no longer required Translations: * Finnish translation update :pr:`2894` (:user:`Kristian Laakkonen `) * Russian translation update :pr:`2965` (:user:`Arkadiy Illarionov `) * Danish translation update :pr:`2983` (:user:`scootergrisen`) * Polish translation update :pr:`3015` (:user:`Piotr Drąg `) Codebase: * Port lots of dbus related code from python-dbus to GDBus :pr:`2876` :pr:`2879` :pr:`2885` :pr:`2887` :pr:`2886` :pr:`2901` :pr:`2903` :pr:`2904` :pr:`2905` :pr:`2917` :pr:`2918` :pr:`2925` (:user:`Arkadiy Illarionov `) * Ported from intltool to gettext * CI: moved from appveyor to azure-pipelines for Windows testing * CI: Add junit test reporting :pr:`2960` (:user:`Nick Boultbee `) * Various test suite fixes for NixOS :bug:`2820` (:user:`Jan Tojnar `) * Removed most Python 2 compatibility code :pr:`2957` * Add a Pipefile for pipenv :pr:`2977` * Various minor Python 3.7 compatibility fixes General: * queue: Add option to keep songs after playing them :pr:`2865` (:user:`Fredrik Strupe `) * queue: Add option to not play songs from the queue :pr:`2865` (:user:`Fredrik Strupe `) * Fix non-deterministic ordering of album list and cover grid browsers :pr:`2945` (:user:`dpitch40`) * multimedia keys: add support for forward/rewind/repeat/shuffle keys :pr:`2954` (:user:`Druette Ludovic `) * tag editor: Fix a context menu crash :pr:`2968` (:user:`Eoin O'Neill `) * Remove GNOME app menu :bug:`2846` * cli: ``--add-location`` for adding a file/directory to the library :pr:`2970` (:user:`Fredrik Strupe `) * cli: Remove deprecated ``--song-list`` option (:user:`Fredrik Strupe `) * Update the big cover window on song changes :pr:`2972` (:user:`Eoin O'Neill `) * wayland: Fix the application window icon under Plasma :bug:`2974` * Various man page updates for missing commands etc :pr:`2971` (:user:`Fredrik Strupe `) * Add support for importing m3u8 playlists (:user:`Fredrik Strupe `) * tags: Don't show generic Performance role description for ~performer:roles :pr:`2994` (:user:`zsau`) * themes: Work around redraw issues with the Breeze gtk theme :bug:`2997` * tag editor: Remember filelist scroll position on tag save :pr:`3005` (:user:`Olli Helin `) * Windows: use SetDllDirectoryW to prevent loading clashing DLLs not shipped by us :bug:`2817` * cover display: Fix the cover window size on multi monitor systems :pr:`2915` (:user:`Fredrik Strupe `) * session: Add an XSMP session management backend to improve (but not fix) save on shutdown behavior under XFCE :bug:`2897` * monkeysaudio: handle missing bits_per_sample for older format versions :bug:`2882` * Various other fixes and improvements: :pr:`2998` (:user:`Olli Helin `), :pr:`2909` (:user:`zsau`) Plugins: * waveformseekbar: Mouse scroll seeking :pr:`2930` (:user:`Peter Strulo `) * waveformseekbar: Add option to hide time labels :pr:`2929` (:user:`CreamyCookie`) * waveformseekbar: Fix freezes while playing streams :pr:`2987` (:user:`Olli Helin `) * animocd: Add more preset positions :pr:`2937` (:user:`Fredrik Strupe `) * New query plugin to match missing tags :pr:`2936` (:user:`Peter Strulo `) * pitch: Add spin buttons for finer control :pr:`2950` (:user:`Druette Ludovic `) * wikipedia: Unify Wikipedia plugins :pr:`2953` (:user:`Fredrik Strupe `) * equalizer: Add option to save custom presets :pr:`2995` (:user:`Olli Helin `) * mediaserver: Point out required rygel config adjustment in the plugin settings :pr:`3004` (:user:`Fredrik Strupe `) * custom commands: Fix menu order :bug:`2659` (:user:`Fredrik Strupe `) * random album: Make it Python 3 compatible :pr:`2922` (:user:`Stephan Helma `) .. _release-4.1.0: 4.1.0 (2018-06-03) - Trapped in a holodeck that won't take commands ------------------------------------------------------------------- Packaging Changes: * No dependency changes compared to 4.0 * Various installed files have been renamed ("quodlibet" -> "io.github.quodlibet.QuodLibet") to work better with Flatpak * We've added some new icon resolutions Translations: * Update Norwegian (bokmål) translation :pr:`2833` (:user:`Åka Sikrom `) * Update German translation :pr:`2860` (:user:`Till Berger `) * Update Polish translation :pr:`2857` (:user:`Piotr Drąg `) * Some Russian translation improvements :pr:`2670` (:user:`Kirill Romanov `) * Various improvements and fixes to make Quod Libet ready for Flatpak/Flathub :pr:`2842` :pr:`2851` (:user:`Felix Krull `) * Show confirmation dialog when removing songs from playlists :pr:`2667` (:user:`zsau`) * Map bare performer tags to a "Performance" role in ``~people:roles`` :pr:`2674` (:user:`zsau`) * Add wildcard support to albumart filename preferences :pr:`2814` (:user:`zsau`) * Fix various typos :pr:`2786` (:user:`luzpaz`) :pr:`2750` (:user:`Tom McCleery `) * waveformseekbar: Improve hover time indication :pr:`2690` (:user:`Eyenseo`) * Add shuffle-by-grouping plugin :pr:`2788` (:user:`archy3`) * Album List - sorting by album average playcount :pr:`2794` (:user:`Uriel Zajaczkovski `) * Recognize rating/playcount tags in vorbis comments :pr:`2761` (:user:`Thomas Leberbauer `) * Handle error when writing empty replaygain tag :pr:`2838` (:user:`Thomas Leberbauer `) * waveformseekbar: Clamp seek time to valid range :pr:`2729` (:user:`Peter Simonyi `) * tag editor: don't use inline separators when changing multiple tag values :pr:`2684` (:user:`Peter F. Patel-Schneider `) * Improve the lyrics file search :pr:`2567` (:user:`Pete Beardmore `) * Added advanded_preferences config for scrollbar visibility :pr:`2697` (:user:`Meriipu`) * cli: Allow floating point arguments for volume :pr:`2661` (:user:`Jonas Platte `) * code quality: Fix raising NotImplementedError :pr:`2772` (:user:`Jakub Wilk `) * paned browser: Add shortcut Ctrl-Return to the searchbar :pr:`2745` (:user:`Felician Nemeth `) * Fix translations on systems with translations spread across multiple directories like with NixOS/Flatpak. :bug:`2819` * Fix setting the process name on Linux to "quodlibet" (4.0 regression) :bug:`2826` * Fix a case where a deadlocked QL would prevent new instances from being started :bug:`2754` * Directory browser: fix not showing Gnome bookmarks * Various Python 3.7 compatibility fixes * id3: always ignore TLEN frames :bug:`2758` * wayland: fix errors when showing the seek popup widget :bug:`2644` * Add cli options for setting repeat and shuffle type :pr:`2799` (:user:`Fredrik Strupe `) * Queue stop once empty: do check at end of song instead :pr:`2801` (:user:`Fredrik Strupe `) * searchbar: Don't save indeterminate search queries in the history :pr:`2871` (:user:`Fredrik Strupe `) * browsers/playlist: Make the side pane take up less space :bug:`2765` (:user:`Fredrik Strupe `) * Make songs menu key accels work across all browsers :bug:`2863` (:user:`Fredrik Strupe `) * shuffle: fix shuffle no longer working after one complete run :bug:`2864` (:user:`Fredrik Strupe `) * tag editor: Allow saving tag if present in all songs but value differ :bug:`2686` (:user:`Fredrik Strupe `) * iradio: assume http if no protocol specified :bug:`2731` (:user:`Nick Boultbee `) * tag split: Allow non-word characters around tag separators :bug:`1088` :bug:`2678` (:user:`Nick Boultbee `) * Various improvements to the cover source plugin system (:user:`Nick Boultbee `) * gstreamer: Disable gapless for .mod files :bug:`2780` * gstreamer: Store the GStreamer registry/cache in our own cache directory to avoid conflicts with the system cache :bug:`2839` * macOS: Fix cannot re-order playlist songs with DnD :pr:`2867` (:user:`David Morris `) Plugins: * Add a new cover download plugin using the cover sources :pr:`2812` (:user:`Nick Boultbee `) * headphonemon: fix headphone detection (4.0 regression) :bug:`2868` * plugin search: handle search for multiple words better * importexport: pass a default value for ~#track when sorting. :bug:`2694` * equalizer: Fix scales in the preferences not showing the initial values :bug:`2722` * randomalbum: Various Python3 fixes :bug:`2721` :bug:`2726` * trayicon: hide the (useless) scrolling preferences on Windows. :bug:`2718` * Move the app/system/dependency info from the about dialog into a plugin. * Tap BPM plugin: Handle non-numeric BPMs :bug:`2824` (:user:`Fredrik Strupe `) * plugins: Make random album work on non-album browsers again :pr:`2844` (:user:`Fredrik Strupe `) * alarm plugin: Port to Python 3 :bug:`2735` (:user:`Nick Boultbee `) * Website search: support ~filename :bug:`2762` (:user:`Nick Boultbee `) * Move Browse Files to core (fully) :bug:`2835` :bug:`1859` (:user:`Nick Boultbee `) * qlscrobble: Fix a potential error when upgrading from 3.9 and older :bug:`2768` Windows: * Fix sys.argv not being set by exe launchers (4.0 regression) :bug:`2781` * The portable app now uses a local cache directory instead of the system one in more cases. * Always show the scrollbars like we do on macOS :bug:`2717` .. _release-4.0.2: 4.0.2 (2018-01-17) - So it goes! -------------------------------- Bug fixes: :bug:`2723` :bug:`2721` :bug:`2722` :bug:`2726` :bug:`2717` :bug:`2694` .. _release-4.0.1: 4.0.1 (2018-01-13) - Water as far as the eye can see! ----------------------------------------------------- Translation updates by :user:`Kirill Romanov ` and :user:`Honza Hejzl ` Bug fixes: :bug:`2677` :bug:`2672` :bug:`2671` :bug:`2680` :bug:`2687` :bug:`2669` :bug:`2699` :bug:`2698` :bug:`2704` :bug:`2703` :bug:`2683` :pr:`2706` :bug:`2705` :bug:`2710` :bug:`2718` :bug:`2719` :bug:`2713` :bug:`2668` :pr:`2715` (:user:`CreamyCookie`, :user:`Nick Boultbee `, …) .. _release-4.0.0: 4.0.0 (2017-12-26) - Speculative fiction where everything's the same, except for one chilling difference -------------------------------------------------------------------------------------------------------- Packaging Changes: * **Python 3.5** required (was 2.7) * All Python dependencies need to be switched to their Python 3 variants. In case there is a "py" in the package name it likely needs to be changed. * **Mutagen 1.34** required (was 1.32) * **GTK+ 3.18** required (was 3.14) * **PyGObject 3.18** required (was 3.14) * **GStreamer 1.8** required (was 1.4) * **media-player-info** no longer required * **udisks2** no longer required * **python-futures** no longer required * **python-faulthandler** no longer required Project: * Ported from Python 2 to Python 3 :bug:`1580` :bug:`2467` * Relicensed all code under "GPLv2 only" to "GPLv2 or later" :bug:`2276` Translations: * Update German translation :pr:`2651` (:user:`Till Berger `) * Update Polish translation :pr:`2646` (:user:`Piotr Drąg `) * Update Norwegian (bokmål) translation :pr:`2506` :pr:`2621` (:user:`Åka Sikrom `) * Russian translation fixes :pr:`2608` :user:`Kirill Romanov ` * Update Finnish translation :pr:`2606` :user:`Kristian Laakkonen ` Various: * Allow cover image pop-up to scale up to maximum size :pr:`2634` (:user:`Peter F. Patel-Schneider `) * Draw a drag handle for the pane separator with newer GTK+ :pr:`2402` * Soundcloud: Add "my tracks" category (:user:`Nick Boultbee `) * Workaround Ubuntu theme bug which results in drawing artefacts with treeview separators. :bug:`2541` * Added support for custom date column timestamp formats (advanced prefs) :pr:`2366` (:user:`Meriipu`) * Fix filter function (e.g. max, min) doesn't work correctly with lastplayed :pr:`2504` (:user:`Thomas Leberbauer `) * Multimeida keys: make "previous" always go to the previous song :bug:`2494` * Prefer userdir in XDG_CONFIG_HOME :bug:`138` :pr:`2466` (:user:`Sauyon Lee `) * Fix error on start under LXDE with its "org.gnome.SessionManager" re-implementation * Improve visibility of the active state of toggle buttons in the bottom bar :bug:`2430` * Remove device support :bug:`2415` * Filesystem browser: Allow selecting multiple folders :bug:`2399` (:user:`Nick Boultbee `) * CLI: Allow floating point arguments for ``--volume`` :pr:`2661` (:user:`Jonas Platte `) * Windows: SIGINT handling support * Sentry.io error reporting now available on all platforms Playback: * GStreamer: Fix gain adjustments are not applied during the first split second of a song on macOS/Windows. :bug:`1905` * GStreamer: Seeking performance improvements :bug:`2420` Tagging: * Add option for moving album art when renaming :pr:`2560` (:user:`Pete Beardmore `) * Add DSF tagging support :bug:`2491` Plugins: * Add support for sidebar plugins :bug:`152` (:user:`Nick Boultbee `) * LyricsWindow: convert to a sidebar plugin :bug:`2553` (:user:`Nick Boultbee `) * Fix synchronized lyrics window not showing :bug:`1743` :pr:`2492` (:user:`elfalem`) * Add more preferences for the album cover search :pr:`2511` (:user:`Pete Beardmore `) * Waveform seekbar hoover time indication :bug:`2419` :pr:`2550` (:user:`Muges`) * New automatic seekpoint plugin (seeking based on bookmarks) :pr:`2437` (:user:`Meriipu`:) CI: * Run Windows tests on appveyor :pr:`2619` * Submit coverage reports to codecov.io * Move to circleci for Docker tests :pr:`2443` * Dockerize Windows-under-Wine tests :pr:`2444` Various improvements, fixes and Python 3 porting fixes, thanks to: * :user:`Kristian Laakkonen `: :pr:`2607` :pr:`2605` :pr:`2593` :pr:`2586` :pr:`2578` :pr:`2576` :pr:`2521` * :user:`Emanuele Baldino `: :pr:`2622` * :user:`CreamyCookie`: :pr:`2574` * :user:`Muges`: :bug:`2425` * :user:`Till Berger `: :pr:`2531` :pr:`2530` :pr:`2474` * :user:`Meriipu`: :pr:`2486` :pr:`2449` :pr:`2616` * :user:`Fredrik Strupe `: :pr:`2476` .. _release-3.9.1: 3.9.1 (2017-06-06) - CHECK AND MATE, FAILING BODY AND MIND ---------------------------------------------------------- * Danish translation update :pr:`2394` (:user:`scootergrisen`) * Various bug fixes: :bug:`2409` :bug:`2364` :bug:`2406` :bug:`2401` :bug:`2410` :bug:`2414` :bug:`2387` :bug:`2411` :bug:`2386` :bug:`2400` :bug:`2404` (:user:`Nick Boultbee ` et al.) .. _release-3.9.0: 3.9.0 (2017-05-24) - If you can whistle, you can do this too ------------------------------------------------------------ Packaging Changes: * **python-zeitgeist** no longer used * **python-feedparser** required (no longer optional) * **python-faulthandler** required * **GTK+ 3.14** required (was 3.10) * **PyGObject 3.14** required (was 3.12) * **GStreamer 1.4** required (was 1.2) * No longer installs icons to "/usr/share/pixmaps" * Installs more icons into "/usr/share/icons/hicolor/" theme Translation Updates: * Czech :pr:`2175` (:user:`Marek Suchánek `) * Danish :pr:`2185` (:user:`scootergrisen`) * French :pr:`2206` (:user:`Olivier Humbert `) * Czech :bug:`2209` (:user:`Honza Hejzl `) * Norwegian Bokmål :pr:`2232` :pr:`2354` (:user:`Åka Sikrom `) * French :pr:`2240` (:user:`Jean-Michel Pouré `) * German :pr:`2388` (:user:`Till Berger `) * Polish :pr:`2391` (:user:`Piotr Drąg `) General: * Windows: Use native file choosers :pr:`2324` * operon: add "--all" option for the "tags" command. :bug:`2335` * Queue: Add checkbox to stop after queue is empty :pr:`2340` (:user:`Fredrik Strupe `) * Opt-in online crash reporting using sentry.io :pr:`2313` * Allow resizing of panes in PanedBrowser :pr:`2301` (:user:`Fredrik Strupe `) * Plugins: Add UI for plugin type filtering :pr:`2218` (:user:`Nick Boultbee `) * Add accelerators for "Open Browser" Menu :pr:`2305` (:user:`Uriel Zajaczkovski `) * replaygain: save selected replaygain profiles to config :pr:`2279` (:user:`Didier Villevalois `) * Allow ``!=`` in queries :bug:`2056` (:user:`Nick Boultbee `) * Add ``~#channels`` :bug:`1686` * songlist: make "space" trigger play/pause. See :bug:`1288` * Add ``--start-hidden`` and remove visibility restoring from the tray icon :bug:`814` * Add non-python crash reporting on the next start :bug:`1853` * mp3: include lame preset in ``~encoding`` Fixes: * Fix queue height not getting restored in some cases :pr:`2330` (:user:`Fredrik Strupe `) * macOS: Fix URL launching from labels :bug:`2306` * Windows: Fix crash when the 65001 code page is used :bug:`2333` * Windows: Fix crash with French locale in some cases. :bug:`2364` * MPRIS: Fix metadata changes not getting emitted :pr:`2359` (:user:`IBBoard`) * Tray icon: Fix rating menu :pr:`2355` (:user:`IBBoard`) * Player: Fix "previous" not working with radio streams :bug:`2198` * gstbe: increase default buffer duration. :bug:`2191` * macOS: Fix meta key for accelerators not working :bug:`2271` * Fix error in case stdout gets closed before QL :bug:`2205` * Fix icon size of app menu embedded in gnome-shell decoration :bug:`2320` :pr:`2334` (:user:`Vimalan Reddy `) Plugins: * Windows: Enable crossfeed plugin * Add a plugin to export a playlist to a folder :pr:`2307` (:user:`Didier Villevalois `) * Add skip by rating plugin :pr:`2201` (:user:`Jason Heard <101100>`) * Advanced Prefs: add a configuration for the window title pattern :pr:`2272` (:user:`Didier Villevalois `) * waveformseekbar: add hidpi detection :pr:`2261` (:user:`Didier Villevalois `) * waveformseekbar: smoother drawing updates :pr:`2289` (:user:`Didier Villevalois `) * Add a tap bpm plugin :pr:`2264` (:user:`Didier Villevalois `) * Add plugin for changing the user interface language :pr:`2154` * Add external visualisations plugin :bug:`737` (:user:`Nick Boultbee `) * EQ Plugin: various improvements :bug:`1913` (:user:`Nick Boultbee `) * Add a plugin to toggle the menubar's visibility using "alt" :pr:`2263` :pr:`2267` (:user:`Didier Villevalois `) Further Contributions: :pr:`2282` (:user:`David Pérez Carmona `) :pr:`2284` (:user:`Jakub Wilk `) :pr:`2294` :pr:`2326` (:user:`Fredrik Strupe `), :pr:`2270` :pr:`2302` :pr:`2280` :pr:`2385` (:user:`Didier Villevalois `) :pr:`2308` :pr:`2314` (:user:`Uriel Zajaczkovski `) :pr:`2331` (:user:`CreamyCookie`) Development: * tests: use xvfbwrapper if available :pr:`2287` * gdist: relicense to modern style MIT * Use docker on travis-ci :pr:`2269` :pr:`2290` .. _release-3.8.1: 3.8.1 (2017-01-23) - LET'S TALK ABOUT BIRDS ------------------------------------------- * GStreamer: increase default buffer duration. :bug:`2191` * Fix acoustid plugin :bug:`2192` * Fix new playlists from menu :bug:`2183` (:user:`Nick Boultbee `) * mpdserver: Make it work with the M.A.L.P Android client :bug:`2179` * Waveform plugin fixes :bug:`2195` (:user:`Nick Boultbee `) * Covergrid context menu fixes :pr:`2197` (:user:`Joel Ong `) Translations: * Norwegian Bokmål :pr:`2194` (:user:`Åka Sikrom `) * German :pr:`2188` (:user:`Till Berger `) .. _release-3.8.0: 3.8.0 (2016-12-29) - Maybe it'll land somewhere cool eventually --------------------------------------------------------------- Packaging Changes: * `concurrent.futures `__ required (usually called python-futures, python-concurrent.futures or python2-futures in distros) * **libgpod4** is no longer used * Testing now requires py.test * Installs a new zsh completion file General: * Preferences: Add option for changing the duration display format :pr:`2021` :bug:`1727` :bug:`1967` (:user:`Nick Boultbee `) * Locale-dependent number formatting :bug:`2018` (:user:`Nick Boultbee `) * Fix updates across browsers on changes to ~playlists :bug:`2017` (:user:`Nick Boultbee `) * Don't wake up when idle :pr:`2068` :bug:`2067` * Covergrid Browser :bug:`241` :pr:`2071` :pr:`2115` :pr:`2125` :bug:`2110` :pr:`2130` (:user:`brunob`, :user:`Joel Ong `, :user:`qwhex`) * Play order (shuffle / repeat) rewrite to be more modularised / powerful :pr:`2043` :bug:`2059` :bug:`2121` :bug:`2123` :pr:`2125` (:user:`Nick Boultbee `) * Improvements / additions to Information window :pr:`2119` :bug:`1558` (:user:`Nick Boultbee `) * Search: Fix error when query divides by 0 :pr:`2025` (:user:`faubi`) * Fix crash on tag edit abort :bug:`2081` * Library scan: ignore hidden files :bug:`2074` * Remove iPod support * Log the filename in case something crashes :bug:`2143` * MP4: Handle empty trkn/disk :bug:`2143` * Library: support autofs mounts :bug:`2146` * Various small GTK+/Ubuntu theme related updates * Fix crash when parsing feeds :pr:`2144` (:user:`Peter Schwede `) * Song list: ctrl+drag will now force a song copy :bug:`1952` * MP4: round bpm to nearest int. :bug:`2028` (:user:`Nick Boultbee `) * Songsmenu icons improved (:user:`Nick Boultbee `) * Basic zsh completion Translation Updates: * Polish :pr:`2141` (:user:`Piotr Drąg `) * Norwegian Bokmål :pr:`2031` :pr:`2064` (:user:`Åka Sikrom `) * Danish :pr:`2169` (:user:`scootergrisen`) * Czech :pr:`2173` (:user:`Marek Suchánek `) Plugins: * Discogs Cover Source :pr:`2136` (:user:`qwhex`) * Add register-date filter to lastfmsync plugin :pr:`2127` (:user:`qwhex`) * Wikipedia plugin - search instead of direct URL :pr:`2112` (:user:`urielz`) * Notification plugin: add option to mask 'Next' :bug:`2026` :pr:`2045` (:user:`Corentin Néau `) * Waveform seek bar :pr:`2046` (:user:`0x1777`), related performance improvements (:user:`Nick Boultbee `) * Add playlists to tray menu :bug:`2006` (:user:`Nick Boultbee `) * Random album plugin fixes :pr:`2085` (:user:`draxil`) * Custom commands: minor improvements (:user:`Nick Boultbee `) * Some Auto Library Update plugin fixes :bug:`1315` (:user:`Nick Boultbee `) * Seek bar plugin: invert scrolling directions :pr:`2052` (:user:`Corentin Néau `) Windows: * Switch to msys2 :bug:`1718` * Allow opening audio files with quodlibet.exe :bug:`1607` * Enable pitch plugin again :bug:`1534` * Windows regressions: crossfeed plugin missing (will be back in the next version) macOS: * Allow opening audio files with the bundle * Really (really..) fix TLS :pr:`2108` :bug:`2107` Development: * Tests: switch to `pytest `__ as the main test runner * Tests: ``setup.py quality`` speedups * Tests: All tests pass now on Python 3 under Linux and Windows * All magic builtins gone :pr:`2044` * macOS bundle and Windows installer include everything required for running the test suite. .. _release-3.7.1: 3.7.1 (2016-09-25) - And then you're doomed. Doomed to to have not ill effects, that is! ---------------------------------------------------------------------------------------- * tests: Use dbus-daemon instead of dbus-launch for creating a session bus. :bug:`2022` * Fix 100% CPU when no song column is expanded. :bug:`2030` * Fix SoundCloud login with Ubuntu 14.04 :bug:`2034` * MP4: Fix crash when saving certain bpm tags :bug:`2028` (:user:`Nick Boultbee `) * Windows: Make lastfmsync plugin work :bug:`1777` .. _release-3.7.0: 3.7.0 (2016-08-27) - Yeah, this is like one of those scammy "name a star" sites! -------------------------------------------------------------------------------- Packaging Changes: * **Mutagen 1.32** required * **udisks1** support removed * **PyGObject 3.12** required * Add Soundcloud browser :bug:`1828` :pr:`1990` (:user:`Nick Boultbee `) * Make F11 toggle fullscreen mode * Add ``--refresh`` to the man page. :bug:`1914` * Add ``--stop-after``. :bug:`1909` * Remove support for loading browsers from ``~/.quodlibet/browsers`` :bug:`1919` * Added shortcut of ``Delete`` for moving files to trash :pr:`1921` (:user:`Victoria Hayes `) * gstbe: always use pulsesink if pulseaudio is running. :bug:`1926` * Remove udisks1 support * Add a "Check for Updates" dialog * Windows: Port mmkeys support from pyhook to ctypes. Fixes accents not working when QL is running. :bug:`1168` * OSX: Enable multimedia key handling by default :bug:`1817` * Add selection tick (check) for rating(s) that are selected :bug:`1891` (:user:`Nick Boultbee `) * Support composersort :bug:`1795` (:user:`Nick Boultbee `) * Rework application menu :bug:`1598` (:user:`Nick Boultbee `) * Add a ~#playcount equalizer play order plugin :pr:`1626` (:user:`Ryan Turner `) * Fix too large cover art border radius with Ubuntu themes * songlist columns: handle font size changes at runtime. :bug:`1420` * Fix song list column label fade out in RTL mode * Fix seek bar getting stuck when releasing the button outside of the widget. :bug:`1953` * Add default keyboard shortcuts for browsers/views :bug:`1540` * Restore queue state. :bug:`1605` * Add a queue toggle button to the status bar and remove the view menu * docs: Clarified function of the queue :pr:`2004` (:user:`Bernd Wechner `) Translations: * Updated Polish translation :pr:`2009` (:user:`Piotr Drąg `) * French translation update :pr:`1932` (:user:`Ludovic Druette `) * Fully update British English "translation" (:user:`Nick Boultbee `) Tagging: * AIFF support :bug:`1801` * Support musicbrainz_releasetrackid :pr:`1992` * Support musicbrainz_releasegroupid :bug:`1896` * operon: Fix image-set when passing multiple files. :bug:`1729` * ASF: add WM/AlbumArtistSortOrder :bug:`1936` * MP4: Support saving replaygain tags :pr:`1916` (:user:`bp0`) * MP4: support replaygain_reference_loudness. :pr:`1928` Plugins: * lyricswindow: Restart WebKit when crashed :pr:`1923` (:user:`CreamyCookie`) * lyricswindow: Prevent alert windows. :bug:`1927` (:user:`CreamyCookie`) * tray icon: Improve unity detection :bug:`1999` * musicbrainz: Add option to write labelid. :bug:`1929` * musicbrainz: Write musicbrainz release track ids :pr:`1992` * Rename Force Write plugin to "update tags in files" :bug:`1938` (:user:`Nick Boultbee `) * tray icon: Use App indicator when running under Enlightenment :pr:`1941` (:user:`Jakob Gahde `) * replaygain: delete tags written by bs1770gain. :bug:`1942` Development: * py.test support * Some Python 3 porting progress: 47% tests passing :bug:`1580` * OSX: build dmgs .. _release-3.6.2: 3.6.2 (2016-05-24) - It seemed like there was a lesson here, but nobody was sure what it was -------------------------------------------------------------------------------------------- * Fix queue not expanding with GTK+ 3.20 :bug:`1915` * Tag editor: Fix error message for unrooted patterns :bug:`1937` .. _release-3.6.1: 3.6.1 (2016-04-05) - GOOD LUCK OUT THERE ---------------------------------------- * Tray icon: Don't use the app indicator for Ubuntu GNOME and KDE 4. :bug:`1904` * Tray icon: Present the window when showing the window through the app indicator menu item. :bug:`1904` * Paned browser: Fix crash with numeric tags in patterns :bug:`1903` * Paned browser: Fix missing "Unknown" entry for patterns * OS X: Fix TLS for real * Lyrics window: Also support webkitgtk2 3.0 (for Ubuntu 14.04) .. _release-3.6.0: 3.6.0 (2016-03-24) - It is altogether fitting and proper that we should do this ------------------------------------------------------------------------------- Packaging Changes: * **Mutagen 1.30** required * **GTK+ 3.10** required * **PyGObject 3.10** required * **webkitgtk-3.0** → **webkit2gtk-4.0** (Lyrics Window plugin) * **sphinx 1.3** required for building the documentation * New optional plugin dependency: **libappindicator-gtk3** + **typelibs**: for the Tray Icon plugin under Ubuntu Unity and KDE Plasma * **python-musicbrainzngs** (>= 0.5) instead of **python-musicbrainz2** * **python-cddb** no longer needed * **libsoup** (>= 2.44) + **typelibs** required * Add a keyboard shortcut window. :bug:`1837` * Add ~language, which shows the language name for iso639 codes * Allow cross-device moves to trash. :pr:`1782` :bug:`1339` (Andrew Chadwick) * CLI: allow backslash-escaped commas in --enqueue-files. :bug:`1773` (Nick Boultbee) * Fix custom accels read from ``~/.quodlibet/accels`` :bug:`1726` :pr:`1818` * Fix determination of tag patterns in songlist :pr:`1830` (Peter F. Patel-Schneider) * Fix ratings not being stored if they are the same as the default :bug:`1461` :pr:`1846` * ID3: read lyrics from USLT frame, make ~lyrics read lyrics and form files :pr:`1810` (Ivan Shapovalov) * Make test suite run (and fail) under Python 3 :bug:`1580` * MP4: support conductor, discsubtitle, language & mood :bug:`323` (Nick Boultbee) * Paned browser: Allow filters to be reset by clicking heading. :bug:`1284` * Paned browser: use sort tags :bug:`1785`, :pr:`1796` (Peter F. Patel-Schneider) * Patterns: Allow proper escaping in nested queries. (``<~filename=/^\/bla\/foo/|match|no-match>``) * Player controls: use a normal button with two icons instead of a toggle button. :bug:`1814` * Playlist browser: implement scroll to playing song :bug:`1426` * Playlist browser: Make display configurable :bug:`1780` (Nick Boultbee) * Playlist browser: Improve usability when creating a new playlist :bug:`1839` (Nick Boultbee) * Playlist browser: Fix bug when deleting playlists :bug:`1882` (Nick Boultbee) * Remove rounded cover preference and make border radius depend on theme. :bug:`1864` * Search: make "ae" match "æ" and "ss" match "ß" etc. * Search: numeric expressions and query plugins :pr:`1799` * Song info display: show delete option to context menu. :bug:`1869` * Songlist: Highlight the current song. See :bug:`1809` * Support sort tags in song list patterns :pr:`1783` (Peter F. Patel-Schneider) * Various GTK+ 3.20 related fixes Translations: * Updated Dutch and Norwegian Bokmål translation :pr:`1784` (Nathan Follens) * Updated Polish translation :pr:`1898` (Piotr Drąg) Plugins: * Update icons for most plugins: more and (mostly) better chosen. :bug:`1894` (Nick Boultbee) * Make songsmenu plugins only enabled if it makes sense for them :bug:`1858` (Nick Boultbee) * Remove cddb plugin; it's broken * Remove Send To plugin, in favour of Browse Folders and k3b plugins. * New plugin: Pause on headphone unplug. :bug:`1753` * New events plugin: Shows synchronized lyrics from .lrc file with same name as the track :pr:`1723` * Add a seekbar plugin. See :bug:`204` * lyricwiki: port to WebKit2 * tray icon: support Ubuntu Unity and KDE Plasma (using libappindicator) :bug:`1756` * musicbrainz: port to musicbrainzngs. This fixes tagging of multi disc releases. :bug:`829` * Make LyricsWindow an events plugin; Add zoom level preference :pr:`1709` * Add authentication for MPDServer plugin :pr:`1789` * Custom Commands: add support for playlist name. :bug:`1685` (Nick Boultbee) * Playlist Export: convert to being a playlist plugin as well as songsmenu. (Nick Boultbee) OS X: * Add a simple dock menu * TLS support (https streams..) :bug:`1895` * Add option to enable experimental mmkeys support in the advanced prefs plugin. :bug:`1817` Wayland: * Fix seek bar window position (needs gtk+ 3.20) .. _release-3.5.3: 3.5.3 (2016-01-16) - Uh, I GUESS that'd be good too?? ----------------------------------------------------- * Fix crash when opening new windows under some DEs (Linux only) :bug:`1788` .. _release-3.5.2: 3.5.2 (2016-01-13) - This is because dates are arbitrary and friendship can be whatever we want it to be! --------------------------------------------------------------------------------------------------------- * Polish translation update (Piotr Drąg) * ID3: don't write albumartistsort twice :bug:`1732` * Use the stream song for ``--print-playing``. :bug:`1742` * Fix background color of some context menus with the Ubuntu 12.04 theme * Fix adding new tags failing in some cases :bug:`1757` * OSX: make cmd+w close windows :bug:`1715` * Fix a crash with numerics in tag pattern conditionals :bug:`1762` (Nick Boultbee) * Fix tests with newer Perl (through intltool) .. _release-3.5.1: 3.5.1 (2015-10-14) - HOW TO SUCCEED AT SMALLTALK ------------------------------------------------ * Fix volume / mute state resetting on song change with some configurations :bug:`1703` * Fix crash when G_FILENAME_ENCODING is set :bug:`1699` .. _release-3.5.0: 3.5.0 (2015-10-07) - BETTER ANSWERS TO "HEY HOW ARE YOU?" THAN "I'M FINE" ------------------------------------------------------------------------- Packaging Changes: * **Mutagen 1.27** required General: * Add --print-query-text to get the current query for browsers that support it :bug:`1634` * Support conditional patterns with QL Query syntax :bug:`1604` (Nick Boultbee) * Playlist content search in the playlist browser :pr:`1593` (Nick Boultbee) * Disable app menu under Unity :bug:`1599` * Allow users to optionally bypass the trash even if it is available on their operating system (Eric Casteleijn) :pr:`1573` * Try to prevent fifo timeouts for slow operations :bug:`1616` * Fix border drawing with CSD/wayland * Use float for ~#length :bug:`1483` * Add a setting to enable/disable rating hotkeys :pr:`1625` (Ryan Turner) * Display all tags in tag list editor not just the non-default ones :bug:`1660` * Add a new ~codec and ~encoding tag (library reload needed) :bug:`9` * Add ~bitrate tag including the unit * Asymmetric search improvements e.g. 'o' now matches 'ø' * Various custom column header dialog improvements :bug:`1660` (Nick Boultbee) * Prefer txxx replaygain over rva2 :bug:`1587` * Support reading RG when ID3 tag key is in uppercase :bug:`1502` Playback: * Implement direct sink volume control (e.g. for pulsesink, directsoundsink). Changing volume will now control the PA stream volume and result in less delay :bug:`1389` :bug:`1512` * Allow muting by middle clicking the volume button. Controls the pulseaudio stream mute property directly. * Increased GStreamer pipeline buffer size to reduce CPU usage :bug:`1687` * Hide seek slider when not seekable OSX: * Replace "Ctrl" with "Command" in all keyboard shortcuts :bug:`1677` * (already in 3.4.1-v2 build) HIDPI support * (already in 3.4.1-v2 build) Support for more audio formats Plugins: * Add a plugin for editing ~#playcount and ~#skipcount. :pr:`1624` (Ryan Turner) * Advanced preferences plugin :bug:`1050` (Bruno Bergot) * Allow to configure cover size in animosd plugin :bug:`1049` (Bruno Bergot) * Add plugin for removing TLEN frames from ID3 based files. :bug:`1655` * mpd: fix state sync with mpdroid 0.8. :bug:`1636` * Fix screensaver inhibit plugin. :bug:`1692` * qlscrobbler: fix offline mode check box. :bug:`1688` * lyrics window: use mobile wikia version Translations: * Update Dutch translation :pr:`1618` (Nathan Follens) * Updated greek translation :bug:`1684` (Dimitris Papageorgiou) * setup.py: add a new create_po command for starting new translations .. _release-3.4.1: 3.4.1 (2015-05-24) - Apparently, MY problem is a poisonous basement ------------------------------------------------------------------- Fixes: * setup.py: respect --install-data :bug:`1575` * Suppress deprecation warnings with newer glib Regressions: * Fix error when invoking a plugin with many songs/albums :bug:`1578` * Fix main window sometimes not showing under Ubuntu 12.04 * Fix search not working with non-ASCII text in some cases .. _release-3.4.0: 3.4.0 (2015-04-09) - She knew every of the things ------------------------------------------------- Packaging Changes: * The main repo moved from Mercurial (Google Code) to Git (GitHub) * The build should now be reproducible * **gtk-update-icon-cache** is no longer a build dependency * **gettext >= 0.15** is required now at build time * A complete **icon theme** is now required (this was also partly the case with 3.3) and an icon theme including symbolic icons is recommended. **adwaita-icon-theme** provides both for example. * **Mutagen 1.22** required, **Mutagen 1.27** recommended * New files installed to ``/usr/share/icons/hicolor/scalable/apps/`` * **quodlibet.desktop** now contains a **MimeType** entry, which means calling **update-desktop-database** is needed after package installation. * Improved Gnome 3.16 compatibility * Fixes for the list tooltips in combination with GTK 3.16 scrollbars * Include symbolic icons for gnome-shell 3.16 * Album browser: faster cover loading * Devices: fix detection of Sansa Clip+ with some setups :bug:`1523` * Prefs: restore active tab * Songlist: support patterns in the filter song list menu * New shortcut ``ctrl+shift+j``, like ``ctrl+j`` but refilters the browser always * Make build reproducible :bug:`1524` * MP4: include codec information in ``~format`` (needs a library reload) :bug:`1505` * GStreamer: fix a deadlock when seeking right at a song change * Queue: don't decide the next song too early :bug:`1496` * Song info widget: provide the full song context menu :bug:`1527` * CLI: ``--run`` to make QL start if it isn't already. Useful for pairing with other commands like ``--play-file``. :bug:`67` * Add supported mime types to desktop file :bug:`67` * CLI: ``--play-file`` doesn't add songs to the library anymore :bug:`1537` * Fix QL starting twice if started in quick succession * Tooltips: don't span multiple monitors :bug:`1554` * MPD-Server: Fix a crash when changing the port number :bug:`1559` * Fix short hang on shutdown with GStreamer plugins active :bug:`1567` * Fix setting an embedded image in case the file doesn't have tags :bug:`1531` * OSX: add a menu bar for Ex Falso * Fifo: Fix commands failing in case QL is busy :bug:`1542` * ... Translations: * Use msgctx for message contexts .. _release-3.3.1: 3.3.1 (2015-01-10) - Reduce, reuse, recycle, RESUBMIT ----------------------------------------------------- Regressions: * Fix occasional errors when closing menus (with the plugin menu in Ex Falso for example) :bug:`1515` * Fix operon info :bug:`1514` * Fix operon fill error in case a tag doesn't match :bug:`1520` Fixes: * Fix HiDPI DnD images when dragging multiple rows .. _release-3.3.0: 3.3.0 (2014-12-31) - PARALLEL UNIVERSES. Travel there and THEN go back in time, and you can mess things up as much as you want. ------------------------------------------------------------------------------------------------------------------------------- Packaging Changes: * New optional plugin dependency: **webkitgtk-3.0 + typelibs** * **Mutagen 1.27** recommended General: * Support ``--query`` with all browsers that have a search entry. :bug:`1437` * Songlist: Scroll to playing song when replacing the list. :bug:`568` * Songlist: Scroll to first selected song and restore selection for it on re-sort. :bug:`568` * Consider all songs in an album for finding (embedded) album art. :bug:`924` * Support ``month`` (30 days) in time queries (``#(lastplayed < 1 month)``. :bug:`706` * Support playing a song that is not in the song list. :bug:`1358` * Support numeric date search e.g. ``#(2004-01 < date < 2004-05)`` :bug:`1455` * Playlists browser: make delete key remove the selected songs from the current playlist :bug:`1481` (Nick Boultbee) * File tree: Show XDG desktop/downloads/music folders if available * File tree: List mountpoints on linux * Show the filter menu in secondary browser windows (filter shortcuts work there as well now) * Add ``alt+[1-9]`` shortcut for notebook widgets to jump the a specific page * Support loading ADTS/ADIF files (\*.aac). Needs mutagen 1.27. * Search: New regex modifier ``"d"`` which makes all letters match variants with diacritic marks (accents etc.). Enabled by default for normal text searches. ``Sigur Ros`` will now find songs containing ``Sigur Rós``. For regex and exact searches use ``/Sigur Ros/d`` and ``"Sigur Ros"d`` to enable. :bug:`133` * New ~people:real tag which filters out "Various Artists" values (Nick Boultbee) :bug:`1034` * Prefer artist over albumartist for single songs in ~people (Nick Boultbee) :bug:`1034` Fixes: * Update for theming changes in gtk3.15 * Fix seek slider not working with newer gtk+ and some themes :bug:`1477` * Fix playing song not restoring on start with radio/filesystem browser Translations: * Russian translation update (Anton Shestakov) :bug:`1441` * Updated Greek translation (Dimitris Papageorgiou). :bug:`1491` Tagger: * WMA: support multiple values for producer, conductor, artist, lyricist, albumartist, composer, genre and mood (needs mutagen 1.26) * APEv2: Support reading/writing embedded album art for APEv2 based formats (Wavpack, Musepack, Monkey's Audio) * Allow removing and renaming from tag names which not all selected formats support. * Allow toggling of programmatic tags in the tagging UI Plugins: * Various translation related fixes (Anton Shestakov) :bug:`1442` :bug:`1445` * New simple lyricwiki plugin using a WebKitGtk webview * New Rhythmbox import plugin. :bug:`1463` * MPD server: make work again with newer MPDroid (MPDroid crashed on start) * Trayicon: add option to quit when closing the main window instead of hiding :bug:`619` * Theme switcher: add option to enable/disable client side decorations * ReplayGain: add option to skip albums with existing ReplayGain values (Nick Boultbee) :bug:`1471` * Notifications: Make cover art display work under e19 :bug:`1504` Operon: * new 'edit' command for editing tags with a text editor (``VISUAL=vi operon edit song.flac``) :bug:`1084` * new 'fill' command for filling tags using parts of the file path (``operon fill --dry-run ". " *.flac``) OSX: * Multimedia key support (Eric Le Lay) * Global menu support / OSX integration. (Eric Le Lay) * Various fixes / improvements Windows: * Newer mutagen (1.27) * Newer GTK+/Gstreamer (Tumagonx) * Fix loading cover art from non-ansi paths * Starting QL will now focus the first instance if one exists * quodlibet.exe now passes command arguments to the running instance (quodlibet.exe --next) :bug:`635` * New quodlibet-cmd.exe which is the same as quodlibet.exe but can be executed in the Windows console with visible stdout :bug:`635` .. _release-3.2.2: 3.2.2 (2014-10-03) - ENJOY, THERE'S NO GOING BACK ------------------------------------------------- Fixes * Fix a crash when seeking streams in some cases :bug:`1450` * Fix a crash in case Windows Explorer favourites link to a non ASCII path :bug:`1464` * Fix playback stopping when playing chained ogg streams :bug:`1454` * Fix context menus not showing sometimes with GTK+3.14.1 Translations * Russian translation update (Anton Shestakov) .. _release-3.2.1: 3.2.1 (2014-08-16) - BAKE HIM AWAY, TOYS ---------------------------------------- Fixes * Fix Ex Falso not starting in some cases. :bug:`1448` * Album art download plugin: Fix image file extension (Nick Boultbee) :bug:`1435` Translations * Russian translation update (Anton Shestakov) :bug:`1441` .. _release-3.2.0: 3.2.0 (2014-08-01) - WHAT KIND OF GOD MADE IT SO LIONS HUG BACK TOO HARD ------------------------------------------------------------------------ Packaging Changes: * **Plugins got merged** into Quod Libet. This means the quodlibet-plugins tarball is gone and plugins will be installed by ``setup.py install``. For distros that used to include the plugins in the main package this means all plugin related packaging code can simply be removed. For distros that offered separate packages the installation can be split by packaging ``quodlibet/ext`` in a separate package. Quod Libet can run without it. * **UDisks2** is supported, in addition to UDisks1 * **Python 2.7** required instead of 2.6 (might still work, but not tested) Tags: * ~people and ~performer don't show roles anymore, which makes them more useful in the paned browser for example. Instead ~people:roles and ~performer:roles will include roles and merge roles like "Artist (Role1, Role2)". Furthermore composer, lyricist, arranger and conductor will be merged with performer roles in ~people:roles. so "performer:role1=Foo, composer=Foo" will result in "Foo (Role1, Composition)". (qjh) * ~#rating in the song list is now a numeric column, ~rating shows the stars (Jan Path) :bug:`1381` UI: * HiDPI support (start with GDK_SCALE=2, needs cairo trunk) * Various display fixes for GTK+ 3.13 and non-Adwaita based themes * Seek slider width scales with song length to some extend * Seek slider shows remaining time * Play order plugins are now split in random/non-random and the UI was replaced by a toggle button + menu. :bug:`1411` * Removing of songs from a playlist through the context menu (Nick Boultbee) * Song list columns now remember their width/state (qjh) * Song list columns provide an option to toggle if they expand. * The multi sort dialog is gone, instead it's now possible to sort by multiple tags by holding down ctrl and clicking on multiple columns. Plugins: * New MPD Server plugin to remote control QL, e.g. through MPDroid :bug:`1377` * New acoustid.org fingerprint tagger (basic functionality, but works) * "Show File" merged into "Browse Folders", it will now try to select the files if the interfaces allows it. * Exact rating plugin (Jan Path) :bug:`1383` Player: * Improved GStreamer error reporting. * Error recording is gone, since it was just annoying. :bug:`1400` Windows: * Fix slow startup :bug:`1389` * Windows Explorer folder context menu entry for Ex Falso Misc: * Keyboard shortcuts are now documented: https://quodlibet.readthedocs.io/en/latest/guide/shortcuts.html Developers: * Due to the inclusion of the plugins into the core, the symlink from ~/.quodlibet/plugins is no longer needed. Fixes: * Fix tray icon crashing or not showing under Gnome Shell 3.12 :bug:`1429` Packaging: * UDisks2 supported, in addition to UDisks1 * Plugins are now included in the main tarball and will be installed by setup.py, the quodlibet-plugins tarball is gone. (Load path switched from quodlibet/plugins to quodlibet/ext for system wide plugins, loading from ~/.quodlibet/plugins is the same) :bug:`1396` * For BSDs: setup.py has a new "--mandir" to select the man page location * Packaging guide: https://quodlibet.readthedocs.io/en/latest/packaging.html .. _release-3.1.91: 3.1.91 [beta] (2014-07-22) - Pumps, powerheads, lights and filters! ------------------------------------------------------------------- See :ref:`final release <release-3.2.0>` .. _release-3.1.2: 3.1.2 (2014-06-20) - Dang it ---------------------------- * Fix 3.1.1 regression causing folders in the file browser to show up in reverse order :bug:`1390` .. _release-3.1.1: 3.1.1 (2014-04-28) - I've shown that you're dealing with an Alpha here, baby, not some weak Beta! ------------------------------------------------------------------------------------------------- * Fix a crash with GTK+ 3.12 :bug:`1384` * Handle invalid flac picture blocks :bug:`1385` * Fix "setup.py install --record" :bug:`1373` .. _release-3.1.0: 3.1.0 (2014-04-10) - Olden times, man! NEVER LIVE THERE. -------------------------------------------------------- * Windows is supported again. And it should be in better shape than with 2.6 in many aspects. Embedded images work now, newer GStreamer with more codecs, operon is included etc. The file browser and EF now show the favorite folders from the Windows Explorer. The installer will now uninstall any existing installation first and as with 2.6.3 there is a portable version available. There is still an unsolved problem regarding miss-placed context menus with multiple monitors :bug:`1319`. Thanks goes to Bakhtiar Hasmanan for providing a working PyGObject stack. * Initial Wayland support is here (only tested under weston). This was mostly fixing weird usage of GTK+ that just happened to work under X11 and not using the screen size for calculations since there is no real screen under Wayland. * Piotr Drąg, Rüdiger Arp, Diego Beraldin and Dimitris Papageorgiou worked on improving the translations. * Nick Boultbee worked on a plugin system for playlist plugins and moved the duplication/shuffle actions to it. He also moved the rating configuration from the plugin into the core. * Simonas Kazlauskas worked on a plugin system for cover art sources currently supporting last.fm and musicbrainz (exposed as two plugins). If active it will fetch covers in case no local cover is found. In the future we might implement the album art downloader on top of that. * Thomas Vogt made transparency work again with GTK+3 in the OSD plugin. (fake transparency now also works again, which was the last known regression from the PyGObject port) * operon gained new commands (image-extract, image-set, image-clear) for manipulating and extracting embedded images for all formats supporting embedded images in QL (id3, ogg, flac, wma, mp4). See the manpage [0] for examples. There is also a QL plugin which allows removing all embedded images and embed the active one. This should get better integrated into the tag editor at some point. * Display patterns now support specifying the markup using square brackets to not need escaping in the common case. "\<b\><artist>\</b\>" can now be written as "[b]<artist>[/b]" (the old way still works). * In the radio browser the radio list now contains icecast and shoutcast2 stations in addition to shoutcast1 ones and only one additional mirror is included for each station. QL now shows ~4100 stations of ~30000 we know about. Use "Update stations" to get the new list. Other changes: * QL now remembers additional open browsers and reopens them on start. * The main tool bar is better integrated with GTK+ themes. * We use symbolic icons in many places. * Added a simple GNOME app menu. * 'albumartist' is now used for album identification. * <shift>space enables "stop after the current song". * Warning before opening too many plugin windows (Nick Boultbee) :bug:`1231` * New --unqueue-all command :bug:`1234` Fixes: * Config gets saved atomically and handle a corrupted one :bug:`1042` * editing:id3encoding option was ignored :bug:`1290` * album browser: Fix sorting by rating :bug:`1352` * search: Fix results for "&(foo, !bar)" :bug:`1327` * Various crashes caused by code not being ported to PyGObject properly. Dependencies & Packaging: * No dependency changes compared to 3.0 * We now install appdata.xml files * We now install a dbus service file * ``setup.py build_sphinx`` builds the html user guide .. _release-3.0.91: 3.0.91 [beta] (2014-02-28) - You'd have to be in space for that to work. ------------------------------------------------------------------------ See :ref:`final release <release-3.1.0>` 2.6.3 (2013-09-25) - The one that can't even go naked into space without dying! ------------------------------------------------------------------------------- This is a Windows only bug fix release. Windows: * Fix library saving [1230] (Sebastian Thürrschmidt) .. _release-3.0.2: 3.0.2 (2013-07-22) - LATER, THE OCEANS BOIL AS THE EARTH TURNS TO FIRE ---------------------------------------------------------------------- General * Device backend: Correctly detect udisks1 if it isn't running [1200] * mmkeys: Really make libkeybinder work again [1203] (Hans Scholze) * Fix play button not starting playback if no song is active [863] * Don't forget newly created bookmarks in some cases * Fix "Refresh" in the file tree browser [1201] * Fix menu separator drawing with PyGObject 3.2 (Ubuntu 12.04) * Various fixes Plugins * Forward library events to event plugins again * Fix bookmarks plugin, playlist export plugin, HTML export plugin * animosd: Handle multiple monitors (Nick Boultbee) 2.6.2 (2013-07-22) - 256 Pictures of Cool Bugs ---------------------------------------------- 2.6.1 skipped to keep in sync with the 3.0 branch. General * Device backend: Correctly detect udisks1 if it isn't running [1200] * Fix play button not starting playback if no song is active [863] * Don't forget newly created bookmarks in some cases * Various fixes Plugins * Fix HTML export plugin * Fix Bookmarks plugin .. _release-3.0.1: 3.0.1 (2013-07-08) - *gasp* --------------------------- * Fix a crasher with some PyGObject versions [1211] .. _release-3.0.0: 3.0.0 (2013-06-15) - THE NEMESIS HYPOTHESIS ------------------------------------------- Requirements & Packaging Changes * Python 2.6+ * GTK+ 3.2+ & GIR (instead of 2.x) * GStreamer 1.0+ & GIR (instead of 0.10) * PyGObject 3.2+ (3.4 highly recommended) (instead of PyGTK) * PyGObject cairo support * libgpod 0.5+ (instead of python-gpod) * libkeybinder-3.0 & GIR (instead of python-keybinder) * HAL support removed * New `operon` script + man page * New .ini file for registering QL as a GNOME Shell Search Provider Translations * New: Czech translation (Honza Hejzl) * Russian translation update (Anton Shestakov) * Lithuanian translation update [1079] (Naglis Jonaitis) * Swedish translation update [1117] (Daniel Nyberg) * Spanish, Basque and Galician translation update (Johám-Luís Miguéns Vila) * Greek translation update [1175] (Dimitris Papageorgiou) General * Improved rating visibility [1070] (Nick Boultbee) * File system view: DnD directories to external targets (Nick Boultbee) * Support GNOME Notification Sources * Bayesian averaging for set (album) ratings [1085] (Nick Boultbee) * New command line tagger: operon (see `man operon`) * Hide songs on not-mounted drives on start without library refresh [984] * Preferences UI for managing masked mount points [984] * Support all patterns as song list headers [507, 1121] (Nick Boultbee) * Save/restore queue position * Documentation is now Sphinx/reST based and hosted on readthedocs.org Fixes * Fix unwanted re-filtering of all open browsers if the search history changes * Fix crash when re-adding devices while QL is running [1120] * Remove EF directory mime type again (too many problems with file managers) Tagging * APEv2: Add disc<->discnumber mapping Plugins * New: Custom Commands plugin (Nick Boultbee) * New: GNOME Shell Search Provider plugin [1147] * ReplayGain plugin: Parallel processing [807] * CD burn plugin: Add Xfburn support [1173] Known Regressions * GStreamer output device selection is no longer supported. (GStreamer 1.0 has removed the property probing interface) * No multimedia keys support with non-GNOME DEs in some distributions due to missing packaging: * https://bugzilla.redhat.com/show_bug.cgi?id=963476 * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=710254 * Animated On-Screen Display plugin is missing transparency support * No Windows build (work in progress) 2.6.0 (2013-06-15) - Someone's attacking us from... space? ---------------------------------------------------------- 2.6 is the last PyGTK/GTK+2 based release of Quod Libet / Ex Falso. It contains most of the changes that went into 3.0 and will only receive bugfix releases from here on out. Requirements & Packaging * Python 2.6+ * PyGTK 2.16+ Everything else * See 3.0.0 NEWS with a few exceptions 2.9.92 [beta] (2013-06-05) - alternatetimelinemetarhyme ------------------------------------------------------- General * Fix the main song list resetting while working with multiple browsers * Fix various widget redraw/positioning/jumping problems * Various fixes regarding GTK+3.6+ (seek slider, tv hints) * Nicer about dialog * Fix one-click ratings [1170] * Fix various crashes with PyGObject3.2 [1172] Plugins * New GNOME Shell Search Provider plugin [1147] * Support Xfburn in the CD burn plugin [1173] * viewlyrics plugin: Fix key handling [1171] * Fix musicbrainz plugin [1162] * Fix replaygain plugin in Ex Falso [1163] * Fix fingerprint plugin [1174] 2.9.91 [beta] (2013-05-13) - welcome to a place where incredibly terrible things can happen to you and your friends for no reason! ---------------------------------------------------------------------------------------------------------------------------------- General * Spanish, Basque and Galician translation updates (Johám-Luís Miguéns Vila) * Tag editor: Fix context menu not showing * Album collection: Fix crash with PyGObject 3.2 * Fix search bar text color * Fix DnD to closed queue * Fix hangs during unix signal handling * Fix 100% CPU in some cases * Fix library refresh pause/stop handling * Some speed improvements and fixes Plugins * ReplayGain plugin now processes albums in parallel * New dark theme option in the theme switcher plugin * Fix GStreamer equalizer * Fix theme switcher plugin * Fix GStreamer mono plugin 2.9.82 [alpha] (2013-05-02) - One day Marty McFly got bit by a werewolf! ------------------------------------------------------------------------ PyGObject/Gtk+3.0/Gstreamer1.0 Port - Alpha 2 release: * Fix lyricsview plugin (Nick Boultbee) * Fix replaygain album gain/peak writing. * Fix crash on one-click ratings in the song list. * Fix crash when playing a song while editing its tags. * gstbe: Increase operation timeouts (for spinning up disks etc.) 2.9.81 [alpha] (2013-04-27) - Because my hypothesis is: it's rad ---------------------------------------------------------------- PyGObject/Gtk+3.0/Gstreamer1.0 Port - Alpha 1 release 2.5.1 (2013-04-23) - Yes: MY COMPUTER IS A PERSON. -------------------------------------------------- * Fix various widgets not showing with pygtk/pygobject trunk * Fix QL refusing to start in some cases [1131] * Improve web browser discovery and fix on Windows * Fix various problems with playlists + masked files [1095] * Reduce debug output if loading a file fails [1080] * Plugins: * notify: Don't set notifications to transient [1103] * lastfmsync: Fix loading/saving of cache [1093] 2.5 (2012-12-19) - Reading on the floor: literature! ---------------------------------------------------- * Greek translation update (Dimitris Papageorgiou) [1064] * Russian translation update (Anton Shestakov) [1072] * Lithuanian translation update (Naglis Jonaitis)[1079] 2.4.91 [beta] (2012-11-23) - hello and thank you for installing an internet! ---------------------------------------------------------------------------- News for packagers * setup.py will install png and svg icons into hicolor and a png icon into pixmaps. It will also try to call gtk-update-icon-cache if it's in the target prefix/root (make sure the icon cache gets updated on package install) * C extensions removed. QL is now Python only. * PyGTK 2.16+ * Python 2.6+ * Support for libudev.so.1 (>= 183) * New: python-keybinder needed for multimedia keys * New plugin directory: gstreamer * Optional plugin dependencies: * Removed: python-indicate (Ubuntu sound menu), lastfmsubmitd (old last.fm plugin) * New: rygel (DBus UPnP MediaServer), python-zeitgeist (Zeitgeist) News for translators * QUODLIBET_TEST_TRANS=xxx will append/prepend "xxx" to all translations so you see what is translatable and for devs to check how, long translations will affect the UI. * "setup.py po_stats" to see how much is translated for each po file. * "setup.py check_pot" to see if a file containing translatable strings is missing from POTFILES.in General * Search: Handle non-ascii values for filesystem tags (~filename, ~dirname..) [227] * New internal tags: ~originalyear ~#originalyear. [966] * New internal tag: ~playlists (Nick Boultbee) * Shortcut: alt + left/right -> seek +/- 10 seconds [981] * Support startup notification spec * Support newest thumbnail spec (v0.8.0) * Basic Unity quicklist * New --stop switch to stop and release the audio device [1018] * List tooltips: work with gnome shell, never shift left, support trees [778] * New --no-plugins switch to start without plugins * No wakeups if nothing is playing. * Directory mimetype for Ex Falso * Shortcut: ctrl+left/right, left/right for treeview navigation * Some UI cleanup, less padding in the main window * Remember window size & position for properties, info, browsers [106] * Device selection for the gstreamer back-end * Use lyricist for finding lyrics if available * Click on default cover icon launches album art plugin [2] (Nick Boultbee) * Fix: Work with Compiz window placement plugin [871] * Fix: Queue widgets not clickable in some cases * Fix: Double-click on album will plays song from queue [231] * Fix: Filter on album in album browser now uses the album key * New: PluginConfigMixin added to core to simplify plugin prefs (Nick Boultbee) * Fix: --status (carlo.teubner) [1045] Formats * New: Monkey's Audio * New: Ogg Opus (needs mutagen 0.21) [1012] * New: MIDI * Basic SPC tag parsing [282] (David Schneider) * Add m4v to valid mp4 extensions Tagging * Limit path sections to 255 chars instead of tags to 100 [915] * ID3: Write foobar style replaygain tags. [1027] * VORBISCOMMENT: Write totaltracks/totaldiscs [929] (Michael Ball) * Shortcut: ctrl-s for saving changes, and configurable standard accels per locale [697] (alex.geoffrey.smith, Nick Boultbee) * Updates to tag splitting (originalartist, performer) (Nick Boultbee) Translations * New: Greek translation (Dimitris Papageorgiou) * German translation update (Rüdiger Arp) * British English translation update (Nick Boultbee) * French translation partial update (Nick Boultbee) Plugins * Removed: lastfmsubmitd * Removed: DBus mmkeys (moved to core) * Removed: Ubuntu Sound Menu (no longer needed) * New: UPnP AV Media Server plugin (needs rygel) * New: ViewLyrics plugin (Vasiliy Faronov) * New: Filter on directory [922] * New: Zeitgeist plugin [717] * New: Mac OS X mmkeys plugin (Martijn Pieters) [967] * New: Telepathy/Empathy status plugin [478] (Nick Boultbee) * New GStreamer plugins: Compressor, Crossfeed, Pitch, Mono * New: Filter on multiple tags [1014] * New: Squeezebox Playlist Export (Nick Boultbee) * Browse Folders: Use the default file browser [983] * Equalizer: add presets * MPRIS: various fixes (for the GS plugin) * Notify: Dismiss notifications after some time * Duplicate Browser: expand/unexpand all button * CD burn: now menu-based * Updated: Auto Library Updater (Nick Boultbee) Browsers * New: Album Collection - provides a tree-like view of albums similar to Paned. * Playlists: * Delete shortcut [942] (Johannes Marbach) * Shuffle playlist (Nick Boultbee) * Remove duplicates [685] (Nick Boultbee) * Album list: more filters Windows * Make Browse folder plugin work [993] * Multimedia keys support 2.4.1 (2012-07-27) - Man! If I were a robot, a lot of things would be different ------------------------------------------------------------------------------- * Fixes: * Fix skipping one song during a song change [987] (This also broke the random album plugin in some cases) * Windows: Crash in file system view if 'My Music' folder is missing [1008] * Fix --quit [958] * Fix playing of files that don't match the file system encoding [989] * Workaround for mutagen ID3v2.3 update bug [mutagen 97] * Various fixes [1013, 1002, 962] * Plugin fixes: * lastfmsync crashes [957] * Various Duplicate browser fixes [999, 954] * Notification crash [975] 2.4 (2012-03-18) - He decides he must become... Abe Atman! ---------------------------------------------------------- * Fixes: * Support xinelib 1.2 [904] * MP3/ID3: fix some rare crashes; prefer main embedded cover * Vorbiscomment: * Ignore coverart and use it as cover art source [910] * Fix deletion of metadata_block_picture * album art: update coverparadise, disable discogs (API changed) * squeezebox fixes (Nick Boultbee) * German translation update (Rüdiger Arp) * Various fixes [890, 909, 899] * Fixed regressions: * Python 2.5 / PyGTK 2.12 compatibility * Restore saved play order [891] 2.3.91/92 [beta] (2012-01-16) - Players only love you when they're playing -------------------------------------------------------------------------- * Fixes: * Don't remove periods from tag values in patterns [368] * Don't jump to playing song on stream changes * Fix wrong path encoding in the exfalso file selector under Windows * Fix error when controlling playback during startup [810] * Handle invalid header patterns * Don't lose the radio library randomly [645] * Handle non utf-8 and invalid filenames in the song list [798] * Fix a crash when the song list changed during a gapless transition [799] * Tray icon doesn't appear in KDE panel [881] * xine backend: Fix equalizer value range * Plugin Fixes: * Fix "&" in notifications (xfce4-notifyd) (Anton Shestakov) * Fix animosd config again * Fix Amazon cover search (API change) * General * Improved startup speed * GNOME session shutdown fixes * Hide all windows on shutdown * Handle signals during startup * Correctly push signals into the gtk+ mainloop (no more segfaults) * Cyclic saving of all libraries not just the main one * Rename the process to "quodlibet" or "exfalso" [736] (Nick Boultbee) * Queue keyboard shortcut is now Ctrl+Return not just Q [747] * Add new songs that match the active filter to the song list * Focus search entry with ctrl+l [666] * Fix reverse sort (sort by album first) * Custom sort dialog [820] (Philipp Müller, Joschka Fischer) * Make the paned browser the default one * Focus the first row in all automatic list selections [835] * Select next song in the song list after song removal [785] * Speed up song removal in long lists [785] * Delete keyboard shurtcut in the queue * Add menu entry to rate current playing song (Nick Boultbee) * Make it possible to override quodlibet/exfalso icon, by placing an icon in the current icon theme [614] * Close buttons in all dialogs (since GNOME 3 has no close button in the window decorations for dialogs by default) [772] * Make main window resizeable with only the queue showing [657] (Florian Demmer) * Make the paned browser prefs resizable * Search bar: No delays for any keyboard/mouse actions except typing * Estimate FLAC bitrate using the filesize [342] (Nick Boultbee) * New ~#filesize tag: requires library reload (Nick Boultbee) * Enhancements to the ways album art is detected (Nick Boultbee): new tab in prefs, new option for forcing art filename [328], new option for preferring embedded image over external ones * Allow numeric ~#replaygain_xxx tags (Nick Boultbee) * album browser: Restore search on start * album browser: Move sort order in the preference button sub menu * album browser: Load all visible covers before showing the album list * album browser: Fewer redraws after filtering * album browser: Add sort by genre option [340] * radio browser: Genre filter list * radio browser: Use the default search bar (with history) * radio browser: Remote station list with 4000 stations * radio browser: Properly sync the song list play icon with song changes * radio browser: Prefill new station dialog with last URL in the clipboard * radio browser: title falls back to organization and artist to website (for the song list) * radio browser: Buffer process shown in status bar * search: Stricter numeric value parsing (only allow valid units) * search: Don't require a space between number and unit: #(added<1day) * search: Support GB/KB/MB/B units for ~#filesize * Gstreamer: * Fully support playbin1 again (QUODLIBET_PLAYBIN1 env var) * Allow setting of stream buffer duration [696] * Sync replaygain volume change with track change [652] (use track-changed signal in newer gstreamer) this needed the removal of the 500ms queue. Can be enabled if there are problems with gapless (QUODLIBET_GSTBE_QUEUE env var) * Don't add equalizer if the plugin is disabled: No unnecessary conversions to float (flac, mp3 decoder), less CPU * Don't use the fluendo mp3 decoder if mad is available, less CPU * No video decoding/playing (mp4 files for example) * Properly emit song-started/ended for radio stream songs (so they get counted as auto started by the new notify plugin) * Add button in the prefs to print the currently used pipeline including format conversions (only in --debug mode) * No more jumping of the position slider during song changes * Better parsing of stream metadata [750] * Translations: * Russian translation update (Anton Shestakov) * German translation update (Rüdiger Arp) * Italian translation update (Luca Baraldi) * Tagging/Ex Falso: * Improve support for language tag, with ISO 639-2 suggestions (Nick Boultbee) * ID3: handle TLAN [439] (Nick Boultbee) * Ignore zero TLEN id3 frame [222] * Allow performer to be split out of title (Nick Boultbee) * Ogg Theora support * Ex Falso about dialog * CLI: * --debug (colored output, yay) * --enqueue-files=file,file [716] (Nick Boultbee) * --print-query=query [716] (Nick Boultbee) * --force-previous [441] (go to previous not depending on the current position) * Plugins: * Removed old plugin import fallback code: In case loading a third party plugin fails, set the QUODLIBET_OLDIMPORT env var. * Show an error message instead of the stack trace for common plugin loading errors (import errors) * Improved notification plugin [588] (Felix Krull) * Improved scrobbler preferences with account data verification * Trayicon: Use custom theme icons [614] Prevent the main window from showing on startup * Musicbrainz: Only write sort tags that are different * Titlecase: New prefs switch to allow all caps in tags (Nick Boultbee) * NEW: Website Search (Nick Boultbee) * NEW: Inhibit Screensaver while playing (GNOME) * NEW: Pause while the screensaver is active (GNOME) * NEW: Acoustid.org fingerprint plugin (only for submitting atm) * NEW: Duplicates browser (Nick Boultbee) * NEW: Mute radio advertisements (di.fm only atm) * NEW: Watch directories for file changes (using pyinotify) [270] (Nick Boultbee, Joe Higton) * NEW: Theme switcher plugin * NEW: Squeezebox plugin (Nick Boultbee) 2.3.2 (2011-10-17) - It doesn't matter! My beats are great! ----------------------------------------------------------- * Fix crash in album browser [781] * Plugins: * DBus multimedia keys: Make it work with gnome-settings-daemon 3.x * Album art: Remove darktown, fix discogs. * MPRIS: Various fixes [776, 817, 827] * Translation Updates: * Lithuanian (Naglis Jonaitis) 2.3.1 (2011-07-16) - YES It works in BOTH temporal directions ------------------------------------------------------------- * Absolute path renaming on Windows [506] * Fix dynamic song removal of songs not matching the query [713] * Fix "--print-playing <~#rating>" [730] * Fix search not working with an active pattern column * Fix hang with newer GStreamer versions and sinkless pipelines * Some minor fixes [682, 724, 704] * Plugins: * Fix MPRIS not handling invalid dates (Nick Boultbee) * Some OSD fixes (Nick Boultbee) * Translations: * German (Rüdiger Arp) * Italian (Luca Baraldi) * Lithuanian (Naglis Jonaitis) 2.3 (2011-04-01) - I THOUGHT THAT WAS PRETTY CLEAR --------------------------------------------------- * Various minor bug fixes * Some small translation updates (Anton Shestakov) * Update of the 2.2.99 news entry 2.2.99 [beta] (2011-03-13) - I can imagine that one day there could be aperson who would read that -------------------------------------------------------------------------------------------------- * Quod Libet now needs Python >=2.5 * Drag and drop in paned browser * Speed up adding many songs to the queue * Smaller volume, seek controls * Ask for playlist name on creation * Output playing progress when using --status * Use current icon theme icons everywhere (for DAPs etc.) * Floating point custom tags * Audio streaming fixes (buffering etc.) (Andreas Bombe) * Treeview hints in paned browser * Cover art now only uses the available space * Support embedded covers art in WMA/Vorbis files * Set composer, albumartist, sort tags when copying to an iPod * Natural sorting in the song list * Many song list speedups (sorting, filling, scrolling) * Split up pattern results in paned browser with multi-value tags * Only consider a song played after half has elapsed * Undo/Redo support for all text entries * New framework for showing running tasks, notifications in the status bar * Text markup in the paned browser * Restore maximized state * Restore window position (Felix Krull) * Make size of the queue adjustable (Florian Demmer) * Mouse scrolling over the play button now changes songs * Support alternate home directory using $QUODLIBET_USERDIR (jkohen) * Make the default rating changeable (library reload needed) * Drag and scroll in the song list * Faster context menu opening * Display playlist size (library reload needed) (Nick Boultbee) * Support queries without specifying a tag name * All queries in the album browser use a standard operation (avg, sum etc.) * Support ~rating, ~#bitrate in the album pattern * Support separate song collection patterns in the paned browser * Don't jump to a playing song if it was selected from the songlist * Faster local cover search * Support FreeDesktop trash spec * Lower case option for file renaming (Nick Boultbee) * Various bug fixes, speed improvements (Jacob Lee, Johannes Rohrer, Tshepang Lekhonkhobe) * Bug fixes: * Treeview hints now work with GTK+ >= 2.20 * Search history now gets properly shared between browsers * Fix udev crashes * Paned browser leaks * Respect global filter in all browsers/filters * Don't lose tag values with differently cased tag names (APEv2) * Fix --set-browser (Carlo Teubner) * Properly handle the case where a playing song gets deleted * Fix redraw errors using compiz * FSync on library save * Fix crash when ~/.gtk-bookmarks contains empty lines (Felix Krull) * Correctly identify rockboxed iPods * Windows (Uninstall any previously installed version!): * Fix translation under Win 7 * Fix cover art plugin saving * Add all partitions to the file selector * Fix various crashes with wide char user names * Fix icon under Win 7 * Support multi-user installations * Fix freezes after opening certain folders * New plugins: * Follow cursor play order plugin * Equalizer plugin * MPRIS 1.0/2.0 plugin * Ubuntu sound menu plugin * Rating reset plugin * Track repeat plugin (Nick Boultbee) * Plugins: * Go to bookmark plugin now menu based * Fix some album art plugin backends (Aymeric Mansoux, ..) * Improved "human" title casing (Nick Boultbee) * Fix queue only plugin stopping the current song. * Only use allowed HTML in the notify plugin. * musicbrainz: allow writing sort tags (Michaël Ball) * Translations: * new Latvian translation (Einars Sprugis) * new Basque translation (Piarres Beobide) * French translation updates (Nick Boultbee) * Brazilian/Portuguese translation updates (Djavan Fagundes) * Russian translation updates (Anton Shestakov) 2.2.1 (2010-03-27) - Fewer than four out of ten people respect my promises -- and possibly more! ------------------------------------------------------------------------------------------------ * Fix for importing some mp3 files. [220] * More fixes for the device backend (iPod, multi partition DAPs). [410, 412] * Fix editing keys with multiple values. [440] * Fix weighted playorder algorithm. * Save songlist column patterns. [447] * Some small fixes here and there. * Plugin fixes: * Title case: Improved title casing for English text. (Nick Boultbee) * Random Album: Algorithm improvements. * QLScrobbler: Fix preference pane ordering. * Album art: Some images weren't displayed. (Tomasz Miasko) [429] * Last.fm Sync, Musicbrainz: Minor fixes. * Translations: * Galician, Spanish (Johám-Luís Miguéns Vila). * German (Rüdiger Arp). 2.2 (2010-02-02) - I know you are enjoying that song but a woman DIED --------------------------------------------------------------------- * Saved searches extended to Album and Paned browsers [41]. * Human sorting is now used in Album and Paned browsers [190]. * Windows is now supported (for real this time). * foobar2000's broken TXXX:DATE now supported [220]. * Warnings are now printed for many missing dependencies. * Fixes for device backends. * Lyric downloading disabled until it can be fixed [273]. * Editing both key and value with multiple keys fixed (extruded) [393]. * Plugin changes: * AnimOSD: major update (Andreas Bombe, Christine Spang) [387]. * MusicBrainz: major update. * Random Album: Changed algorithm to increase fairness. * QLScrobbler: Custom patterns for title and artist. * Last.fm Sync: new plugin to sync stats from Last.fm. * Notify OSD, Album Art: Minor fixes. * Translations: * Galician, Spanish (Johám-Luís Miguéns Vila). * French (Bastien Gorissen). 2.1.98 [beta] (2010-01-04) - How are you going to convince people to use it? ---------------------------------------------------------------------------- * Christoph Reiter is now a maintainer. * The GStreamer backend is now gapless [49]. * Win32 is once again supported [248]. * ID3 tags are removed from FLAC files upon saving [124]. * File extensions are converted to lowercase upon renaming [66]. * Thumbnails are now generated for artwork [140]. * Inline searches in the album list can now match people [239]. * Embedded album art is now supported in FLAC files [255]. * Bitrates are now reported in kbps. Library reload required [79]. * Additional ReplayGain settings (Nick Boultbee) [132]. * Tag splitting setting is now order-sensitive [74]. * Paned browser now supports patterns for panes [45]. * Numeric columns have been given a few tweaks (Johan Hovold) [81]. * New ratings column options (Johan Hovold, Bastien Gorissen) [82, 83]. * Renaming when symlinks present no longer raises error (Philipp Weis) [353]. * Xine backend uses software volume control (Markus Koller) [370]. * Song positions are now saved and restored when quitting [218]. * DeviceKit-Disks (UDisks) supported for device discovery [252]. * Plugin changes: * New playlist export plugin [30]. * New queue only playorder plugin [43]. * New Python console plugin. [229] * Updated trayicon plugin [158]. * Updated album art plugin (Eduardo Gonzalez) [139]. * Updated qlscrobbler plugin (Nicholas J. Michalek) [376]. * Updated lastfmsubmit plugin [292]. * Translations: * Russian (Anton Shestakov) [274]. * Turkish (Türerkan İnce). * German (Rüdiger Arp). * Many bug fixes and performance improvements. 2.1 (2009-07-04) - My God, Utahraptor, that's THE PERFECT SOLUTION. ------------------------------------------------------------------- * Bug fixes: * Installer fixes [15, 27, 88] * Right-click on menu causes crash [14] * Removing a pane from the paned browser causes segfault [131] * Null bytes in tags are now stripped on load [177, 242] * zh_CN translation updated [156] * Support .oga file extension for Ogg Vorbis files [52] * Support libre.fm scrobbling in qlscrobbler plugin * Get Internet Radio channel listing from yp.icecast.org [18] * Ignore errors during playback for ~#skipcount [37] * URIs supported for --play-file and --enqueue [17] * Many minor fixes and enhancements. 2.0 (2008-09-14) - Once upon a time there was a radical guy! ------------------------------------------------------------ * Make Escape a synonym for Ctrl+W in QLTK Windows. (I#8) * Actually fix playlist error. * Fix Xine backend "Stop" behavior. 1.999 [beta] (2008-09-09) - It has been a memorable day ------------------------------------------------------- * Fix playlist error when loading songs. * Unlock device when "stop" mmkey is pressed. (Javier Kohen, I#6) * Restart song when rewinding and > 0.5s in. (Javier Kohen, I#7) * Updated Galician and Spanish translations. (Johám-Luís Miguéns Vila) * Make requirements consistent across all documentation. 1.99 [beta] (2008-09-08) - It is impossible to know if my dream came true ------------------------------------------------------------------------- * New distutils-based build/test/install system. * Multiple audio backend support. * Xine-based audio backend. * "Null" backend for Ex Falso. * Tag Editing: * Tags From Path: "<~>" will eat a string but not save it. * Track Numbers: Allow numbering up to 999. * Show image files in Ex Falso. * Direct output to console and to a debugging window. * Functions are accessible to plugins as print_d, print_e, and print_w. * default_rating configuration option. (Robert Muth) * Many bug fixes and performance improvements. 1.0 (2007-05-05) - Yeah they just showed up one day -- staring. --------------------------------------------------------------- * Use Mutagen for ASF/WMA and MP4 support. * Add IsPlaying and GetPosition to the D-Bus API. (Mickael Royer) * Default "No Cover" image. (Jakub Steiner) * Add --unfilter to reset browser filters. * Sort --enqueued files, and add --unqueue. * Basic SPC (SNES ROM audio) support. * Paned Browser speed improvements. (Robert Muth) * Errors when playing a song are now logged to a special ~errors tag. It is visible from the Information screen, and can be reset. * APEv2 tags can now override Musepack stream Replay Gain settings. * Numerous bug fixes, especially in media device handling. * Translation Updates: * Hungarian. (SZERVÁC Attila) * Finnish. (Jari Rahkonen) * Galician and Spanish. (Johám-Luís Miguéns Vila) * French. (Guillaume Ayoub) * Dutch. (Hans van Dok) * Japanese. (Yasushi Iwata) 0.24 (2006-11-19) - One wonders if our conversation today would be an appropriate epitaph. ------------------------------------------------------------------------------------------ * Media device (iPod and UMS so far) support. (Markus Koller) * Delete removes songs from the queue. (sciyoshi) * Per-browser window memory. * Use Mutagen for WavPack and Musepack support. * Keep filenames when given invalid patterns. (Markus Koller) * Don't duplicate performers in ~performers. (Martin Bergström) * Python 2.5 and GTK+ 2.10 compatibility. * Fix Rename Files support on MP4 files. * New Romanian translation, by Mugurel Tudor. * New Slovak translation, by Lukáš Lalinský. * Updated translations: * Traditional Chinese, by Hsin-lin Cheng. * Japanese, by Yasushi Iwata. * Galician and Spanish, by Johám-Luís Miguéns Vila. * Finnish, by Jari Rahkonen. * Hebrew, by Roee Haimovich. * Polish, by Tomasz Torcz * French, by Guillaume Ayoub. * German, by Rüdiger Arp. 0.23.1 (2006-08-28) - UNPOPULAR LIFE GOALS ------------------------------------------ * Multivalued tag renaming. * Fix crash when ~/.gtk-bookmarks is not present. * Disable 'title' completion. (hopefully temporarily) * Parse "performer:role" tags and offer a ~performers synthetic tag. * Updated Swedish translation, by Erik Christiansson. 0.23 (2006-08-14) - THE NARRATIVE OF LIFE. ------------------------------------------ * Bug Fixes: * Updated files no longer incorrectly appear in the paned browser. * Disambiguate 'filename' string for translation. * Hide unreadable files in Ex Falso. * Avoid (harmless) race condition when filling album list. * "Select All Subfolders" menu item when browsing directories. (thanks to Alexandre Passos). * Scan the library in the background when starting. * Ogg FLAC and Speex files can be loaded. * Plugin configuration IDs can be different from their names. * Rewritten library code, many resulting UI improvements. * Scan directories are used as File System roots. * Replay Gain mode is chosen based on browser/play order. * Internet Radio M3U support. * Ex Falso runs on Win32 (thanks to Ben Zeigler). * Song list headers can be changed via a context menu. * True Audio (TTA) support. * New Japanese translation, by Yasushi Iwata. * New Traditional Chinese translation, by Hsin-lin Cheng. * Updated Translations: * German, by Rüdiger Arp. * Polish, by Tomasz Torcz * French, by Guillaume Ayoub. * Galician and Spanish, by Johám-Luís Miguéns Vila and Javier Kohen. * Korean, by Byung-Hee HWANG and ChangBom Yoon. * Hebrew, by Roee Haimovich. * Portuguese, by Alexandre Passos. * Dutch, by Hans van Dok. * Hungarian, by SZERVÁC Attila. * Swedish, by Fredrik Olofsson. 0.22 (2006-07-06) - Man, forget television, books, films, short films, to a lesser extent plays and other theatre, and the remaining popular media! --------------------------------------------------------------------------------------------------------------------------------------------------- * The tray icon is now an optional plugin. * A D-BUS interface is available. (thanks to Federico Pelloni) * Tag editing values are autocompleted. * Library Browser windows have more useful titles. * New "~lyrics" synthetic tag. * Python 2.4 is now required. * Updated Translations: * Galician and Spanish, by Johám-Luís Miguéns Vila. * Italian, by Filippo Pappalardo. * Hebrew, by Roee Haimovich. * Finnish, by Jari Rahkonen. * Dutch, by Hans van Dok. * Polish, by Tomasz Torcz * Portuguese, by Alexandre Passos. * French, by Guillaume Ayoub. * Bulgarian, by Rostislav Raykov. * Hungarian, by SZERVÁC Attila. * Korean, by Byung-Hee HWANG and ChangBom Yoon. 0.21.1 (2006-07-02) - Dude! It's not like you can't just make your own! ----------------------------------------------------------------------- * MP3s with POPM can be loaded again (Thanks, Hans van Dok) 0.21 (2006-06-10) - Faith, AND the possibility of weaponized kissing?? ---------------------------------------------------------------------- * Bug Fixes: * Queue behaves correctly when randomizing two songs. * GStreamer error messages are properly localized. * Tray icon is more resiliant to panel crashes. * "Jump..." distinguishes between identically-named albums. * application/ogg is recognized in audio feeds. * .pyo files are removed on clean. * util.unexpand caches the value of $HOME. * Fix plugin function call ordering. * UI Changes: * Improved tooltips in Preferences. * The Paned Browser shows song totals, and has a button to reset all selections. * Saving play count / rating tags can be turned off, or adjusted to a different email address. * The last-entered directory is used for Scan Directories configuration. * pyvorbis is no longer required if you use Mutagen 1.3. * Event plugins were redesigned, incompatibly. * Test coverage data can be generated using trace.py. * New Simplified Chinese translation by Emfox Zhou. * New Hungarian translation by SZERVÁC Attila. * Updated translations: * Finnish, by Jari Rahkonen. * Korean, by Byung-Hee HWANG and ChangBom Yoon. * Galician and Spanish, by Johám-Luís Miguéns Vila. * Norwegian Bokmål, by Andreas Bertheussen. * Italian, by Filippo Pappalardo. * Polish, by Tomasz Torcz * Lithuanian, by Jonas Slivka. * Dutch, by Hans van Dok. 0.20.1 (2006-05-02) - Thanks for the eye-opener, dinosaur zombies! ------------------------------------------------------------------ * Vorbis/FLAC tag editing works again. 0.20 (2006-05-01) - Feelings are boring. Kissing is awesome! ------------------------------------------------------------ * Bug Fixes: * --play-file will use the queue. * Audio Feeds remember download locations. * Song changes don't revert tag edits. * Browser song activation takes precedence over the queue. * Albums drag-and-drop in listed order. * Only reset relevant parts of Information windows on song change. * Deleting files not in the library removes them. * Non-numeric disc/track numbers sort properly. * Paned Browser no longer adds incorrect entries. (Debian bug ) * Ex Falso no longer loads WAV or MOD files. * Allow more headers in Internet Radio and Audio Feeds. * New process launching method, util.spawn. * UI Changes: * Indicator to show when songs come from the queue. * Rating submenu always appears in the song list. * Album covers hide when clicked again. * Select current song when jumping to it. * New translations: * Norwegian Bokmål, by Andreas Bertheussen. * Swedish, by Erik Christiansson. * Updated translations: * Polish, by Tomasz Torcz. * Dutch, by Hans van Dok. * Finnish, by Jari Rahkonen. * French, by Olivier Gambier. * Galician and Spanish, by Johám-Luís Miguéns Vila. * Hebrew, by Roee Haimovich. * Portuguese, by Alexandre Passos. 0.19.1 (2006-04-04) - It's our secret! Our secret IDENTITY! ----------------------------------------------------------- * Work around broken Fedora/Mandrive GNOME bindings. * Fix global plugin directory scanning. * Add originalartist to ~people. * Updated Italian translation, by Filippo Pappalardo. * Updated Korean translation, by Byung-Hee HWANG and ChangBom Yoon. 0.19 (2006-04-01) - i'm really thirsty you guys ----------------------------------------------- * Simple X session management. * Require Mutagen 1.0; drops Pymad. * WAV support. * New plugin types can be enabled/disabled. * Album List can search and display any tags. * "Bookmark" time offsets within songs. * Song menu plugins require minor but incompatible updates. * Searches, tagging patterns, and file renaming patterns can be given aliases and saved. * Tag Editing: * MusicBrainz TXXX, artist/album/albumartist support. * Added albumartist, originalartist, originalalbum, originaldate, recordingdate. * Ratings, playcount Ogg Vorbis format changed. * COMM tags in Ex Falso are deleted properly. * UI Changes: * Drops from e.g. Nautilus add to playlists/queue. * Clear button in Album List. * Horizontal scrollbar when absolutely necessary for the song list. * "Random" options use filtered lists. * Album sort is once again and forever default. * 'Add to Playlist' resorts playlist properly. * Enter in 'Add a Tag' moves from tag to value. (Debian bug ) * Standard context menu for all browsers. * 'Delete' key works in Edit Tags. * Type-ahead search works in the Album List. * Bug fixes: * Double-appearances in the filesystem view. * FIFO misses some commands. * Stupid 'refresh' signal finally gone. * Error when seeking and keyboard can't be grabbed. * Updated translations: * Finnish, by Jari Rahkonen. * Galician and Spanish, by Johám-Luís Miguéns Vila. * Polish, by Tomasz Torcz. * Dutch, by Hans van Dok. * German, by Rüdiger Arp. * Lithuanian, by Jonas Slivka. * Hebrew, by Roee Haimovich. 0.18 (2006-03-03) - "Babies Sporting Monocles"? ----------------------------------------------- * MP4 iTunes metadata can be written. * Alt+s switches between search entry and song list. * GStreamer 0.10 port. * Album covers can be switched off in the Album List. * The Album List text can be changed with a pattern. * "Limit" in the Search view can take ratings into account. * UI Changes: * Alt+Enter / Ctrl+I shows tags/information for selected songs. * DnD to playlists/the queue from the File System view. * F2 renames playlists. * "Add a Tag" autocompletes tag names. * RSS links can be dragged to the Audio Feeds sidebar. * Bug Fixes: * ID3v1 tags no longer interfere with APEv2 tags. * Playing albums with one song no longer skips forwards. * 'totaltracks' Vorbis tags are read properly. * Adding songs to a playlist doesn't unsort it. * "Tags From Path" patterns are no longer greedy. (thanks to Decklin Foster) * Internet Radio supports the ~people tag. * Word-wrap in lyrics pane works properly. * Ex Falso properly opens an initial directory. (thanks to ch.trassl) * '~format' is usable from --print-playing. ([2810]) * Plugin errors are captured in a dialog. ([2817]) * New synthetic numeric tags, ~#tracks and ~#discs. ([2828]) * Ex Falso no longer depends on GStreamer. ([2837]) * New Lithuanian translation by Jonas Slivka. ([2780]) * Updated translations: * Bulgarian, by Rostislav Raykov. * Finnish, by Jari Rahkonen. * Korean, by Byung-Hee HWANG and ChangBom Yoon. * Galician and Spanish, by Johám-Luís Miguéns Vila. * Hebrew, by Roee Haimovich. * German, by Rüdiger Arp. * Polish, by Tomasz Torcz. * Russian, by Sergey Fedoseev. * French, by Joshua Kwan. 0.17.1 (2006-01-19) - I'd like to have some nightmares, please! --------------------------------------------------------------- * Updated German translation, by Rüdiger Arp. * Updated Russian translation, by Sergey Fedoseev. 0.17 (2006-01-18) - the grizzly icing on the prospector cake! ------------------------------------------------------------- * Lyrics plugin merged into Information dialog. * "Edit Tags" now correctly removes all copies of multiple values, and displays "(missing from...)" for all missing values. * More FIFO commands (song list and queue visibility). * FLAC support no longer depends on pyflac. * Load audio feeds without author information. * ~#year, ~year internal tags. * Numeric searches are rounded to two decimal places. * New plugin architecture for tag editing dialogs. * Korean translation, by ChangBom Yoon and Byung-Hee HWANG. * Updated translations: * Russian, by Sergey Fedoseev. * Finnish, by Jari Rahkonen. * Portuguese, by Alexandre Passos. * Italian, by Filippo Pappalardo. * Dutch, by Hans van Dok. * Galician, by Johám-Luís Miguéns Vila. * French, by Joshua Kwan. * Polish, by Tomasz Torcz. 0.16 (2005-12-19) - would it make a difference if it never really came up often? -------------------------------------------------------------------------------- * Context menu plugins can make themselves insensitive. * More command-line and FIFO options. * Read-only M4A support. (thanks to Alexey Bobyakov) * Wavpack support. * Audio Feed (Podcast) support (requires https://pythonhosted.org/feedparser/). * "One Song" (and repeat) play mode. * Improved and configurable tray icon. * New install system that is more FHS-compliant. * ~laststarted internal tag. * Accents are stripped when renaming to ASCII filenames. * UI improvements: * Ex Falso lists are searchable in GTK 2.8.8+. * ^W closes transient windows. * More DnD support. * HIG-compliance for strings. * Double-click files in browsers to enqueue them. * Rename Files error dialog has a "Continue" button. * Ctrl-Left/Right changed to Ctrl-,/.. * Playlist imports have a progress bar. * New icon that is not all black. (thanks to Tobias and Fabien) * Paned Browser entries have context menus. * Volume icons follow GTK+/GNOME theme. * More memory and CPU optimizations. * GStreamer error handling. (thanks to Zack Weinberg and Bastian Kleineidam) * Musepack, MOD support migrated to Mutagen/ctypes modules. * Updated translations: * Galician and Spanish, by Johám-Luís Miguéns Vila. * Italian, by Filippo Pappalardo. * Dutch, by Hans van Dok. * Finnish, by Jari Rahkonen. * Portuguese, by Alexandre Passos. * French, by Joshua Kwan. * Polish, by Tomasz Torcz. * German, by Rüdiger Arp. * Hebrew, by Roee Haimovich. 0.15 (2005-11-14) - Maybe I will. --------------------------------- * An 'artist' tag can be stored in the library for MODs. * 'All Albums' remains on the album list after a search. * The Play Queue displays its total time and has a clear button. * Songs can be enqueued multiple times. * '~people' includes more people. * Files can be added from remote URIs (e.g. HTTP). * "Dumb" searches match any visible tags. * Ratings are now searched with values of 0.0 to 1.0, and the number of visible notes is configurable. * Useless columns are not displayed in Internet Radio. * A single album cover can be refreshed in the Album List. * Playlists have been rewritten: * Songs may now be in a playlist multiple times. * Playlists can be reordered directly, without a special window. * Songs can be added to playlists directly from the context menu. * M3U and PLS playlists (along with their songs) can be imported. * The interface is much more attractive. * Drag-and-drop is generally more usable, faster, and attractive. * Many optimizations, especially during startup. * Updated translations: * Russian, by Sergey Fedoseev. * Galician, by Johám-Luís Miguéns Vila. * Dutch, by Hans van Dok. * French, by Joshua Kwan and Fabien Devaux. * Hebrew, by Roee Haimovich. * Finnish, by Jari Rahkonen. * Polish, by Tomasz Torcz. * Italian, by Filippo Pappalardo. * New translations: * Spanish and Portuguese, by Johám-Luís Miguéns Vila. 0.14 (2005-10-22) - I'm almost certain! --------------------------------------- * Internet radio / Shoutcast browser. * Album List separates albums with different labelids. * Ex Falso displays all available plugins in its menu. * Useful ~#lastplayed/~#added/~#mtime display thanks to Lalo Martins. * New Album List search keys and sorting options. * New translations: * Galician, by Johám-Luís Miguéns Vila. * Italian, by Filippo Pappalardo. * Updated translations: * Finnish, by Jari Rahkonen. * Polish, by Tomasz Torcz. * Dutch, by Hans van Dok. * Hebrew, by Roee Haimovich. * German, by Rüdiger Arp. * Russian, by Nikolai Prokoschenko. * Many bug fixes. 0.13.1 (2005-09-15) - People will fall for this for sure! --------------------------------------------------------- * Fix playlist creation. * Unplay when no song is playing. 0.13 (2005-09-11) - So, um... let's- fletcherize? ------------------------------------------------- * The GStreamer backend is cleaned up, and is now the only backend. This results in lower background CPU usage and many fixes to our audio processing. Gapless playback is gone. * A play queue was added. * A file system browser has been added. This can view, edit, and play files outside of your library. * The Paned Browser has a search entry. * Search Library lets you limit the number of results. * ``~/.quodlibet/browsers`` is now scanned for custom browsers. * Synthetic tags ('''~dirname''', '''~basename''', &c.) can be searched. * Similarly, synthetic tags can be used in the Paned Browser. * New synthetic tags, '''~people''' and '''~playlist'''. * If the tray icon is visible, closing QL's main window will minimize it. To actually quit, choose '''Quit''' from the Music menu or icon. * Search Library and the Album List search entry have tag completion. * Ex Falso supports plugins. * Updated Russian translation by Nikolai Prokoschenko and Sergey Fedoseev. * Updated French translation by Joshua Kwan. * Updated Finnish translation by Jari Rahkonen. * Updated Dutch translation by Hans van Dok. * Updated Hebrew translation by Roee Haimovich. 0.12 (2005-07-31) - focus ENTIRELY on the sexy bits. ---------------------------------------------------- * New Mutagen ID3 reader/writer. * Experimental GStreamer backend. * Drag-and-drop to playlists. * Weighted random playback. * MP3 and Musepack ReplayGain support. * Larger plugin manager window. * Automatic mount point detection. * Support for multiple soundcards. * Localization enhancements. * Translation updates: * Dutch, thanks to Hans van Dok. * Finnish, thanks to Jari Rahkonen. * French, thanks to Joshua Kwan. * German, thanks to Rüdiger Arp. * Hebrew, thanks to Roee Haimovich. * Russian, thanks to Sergey Fedoseev and Nikolai Prokoschenko. * Polish, thanks to Witold Kieraś. * The usual round of interface tweaks and bug fixes. 0.11 (2005-05-10) - spicy burnsauce with a side of ZING! -------------------------------------------------------- * Plugins (either appearing in the right-click menu, or triggered on a player event) * Browse songs by album, with a cover display. * "Library Browser" added to search/edit files without disturbing your playlist. * Played songs are automatically removed from dynamic playlists. * "Background filters" for the paned browser and search entry. * Create/remove empty folders from within Ex Falso. * '0' to '4' keys or mouse clicks can set song ratings. * Depends on PyGTK 2.6 (as well as GTK 2.6). * --status to print the player's status. * Russian translation, thanks to Sergey and Andrey Fedoseev. * Partial French translation, thanks to Joshua Kwan. * OSD moved to a plugin. 0.10.1 (2005-04-04) - What if I said I'm not really kidding? ------------------------------------------------------------ * The main window stays hidden when the song changes. 0.10 (2005-04-02) - As it turns out, my life is NOT THAT INTERESTING! --------------------------------------------------------------------- * --seek supports +/- prefix to seek relative to the current position. * Added Ex Falso, a tag editor based on QL (without audio playback). * Switched MP3 genres from TIT1 to TCON. * The library is saved automatically every 15 minutes. * Tag by Pattern/Rename Files save patterns used. * Adding tags with specific formats ('date') is less prone to error. * Several display bugs and non-HIG windows were fixed. * Pane-based (Rhythmbox/iTunes-style) library browser. * Tag by Pattern/Rename Files previews can be manually edited before saving. * Kind of browser (none, search, playlists, paned), song list sort order, and what you were browsing are remembered when you exit. * At least one lockup-causing bug was fixed. * Song ratings, on a 0 to 4 scale. * Masked directories work again. * No more dependency on Glade. * A new icon and website. 0.9 (2005-03-04) - I don't want any trouble, cephalopods! --------------------------------------------------------- * Major updates to the Properties dialog: - A new detailed 'Information' tab was added. - Middle click pastes current PRIMARY clipboard text in 'Edit Tags'. - Text in the 'Rename Files' dialog can be conditionalized. * Non-UTF-8 filesystem encodings support (via CHARSET/G_BROKEN_FILENAMES). * New numeric keys "added" and "skipcount" can be searched on. * The --print-playing format string syntax has changed to match the one now used in 'Rename Files'. * New query language enhancements (ternary relation operators, string comparisons, and Lynx-like case-sensitivity). * The tray icon now pauses/unpauses on middle click, adjusts volume with the scroll wheel, and skips forward/backward on buttons 6/7. * This release depends on GTK 2.6 for its new media icons. * PMP support was removed. * Updated German translation (thanks, Bastian!) 0.8.1 (2005-02-06) - Our story takes a sudden dive... ----------------------------------------------------- * Fix a crash when encoding information is not available. 0.8 (2005-02-04) - I make jokes about whomever I please! -------------------------------------------------------- * New/reloaded libraries take 20% less disk space. * Double-clicking an album cover displays it in a larger window. * --shuffle, --repeat, and --volume (--volume-up and --volume-down are deprecated and will be removed). * Any tag name can be written to (and read from) an MP3 file. * Playlists containing arbitrary songs can be created. * The libmodplug Python wrapper must be downloaded separately. * The MPC/MP+ format is supported (with a separate wrapper). * FLAC supports ReplayGain. * Internal changes made some things faster and others slower. * Polish translation, thanks to Michal Nowikowski. * German translation, thanks to Bastian Kleineidam. 0.7 (2004-12-18) - I'm going to ho-ho-hoard all these nuts! ------------------------------------------------------------ * Default to proper 'alsa09' driver (rather than 'alsa'). * "Random Foo" searches are now anchored with ^...$. * Tag By Pattern values can be edited before being saved. * Right-clicking on the status icon brings up a menu. * --play, --pause, --seek-to, --query, --play-file. * OSD (gosd) support, thanks to Iñigo Serna and Gustavo J. A. M. Carneiro. A library reload is needed to use it. * FreeDesktop-style .folder.png files supported for album covers. * Playlist/search UI elements can be hidden. * Dragging playlist columns reorders them. * Library rebuilds no longer lose play counts. * Configurable menu accelerators when gtk-can-change-accels is set. * Delete songs (or move them to the trash) from the player. 0.6 (204-12-02) - People laugh at typos in heaven?! --------------------------------------------------- * Many new filtering options (top 40, not played in X days). * Mass-set track numbers. * Tag by Pattern can replace or add new tags. * Maskable mount points. This lets you add files from an NFS share or portable device and not have to readd them if you unmount and remount it. * Support for sending files to PMPs from the context menu. * --next, --previous, --play-pause, --volume-up, --volume-down. * MOD/IT/XM/etc. support, using libmodplug and an included C extension. * Right-clicking the status icon will pause/unpause. * Seeking in FLACs. * Bug fixes (including at least one crash). 0.5 (2004-11-18) - Everything's fine, CEPT YOU GOT NO LEGS! ----------------------------------------------------------- * The ao audio backend is back; see the "AUDIO BACKENDS" section in the manual page for instructions on using it. This should let ALSA users use software mixing. * ID3 APIC (embedded picture) support. * VorbisGain (https://sjeng.org/vorbisgain.html) support. * A context menu for common operations was added to the properties dialog. * Tag values can be set from filename patterns, or vice-versa. * Dates can be saved in MP3s now. * --print-playing option, with a format string. * More UI tweaks. * Translation template update. * Many bug fixes; please reload your library. You can now reload your library from the "Music" menu. 0.4 (2004-11-09) - The Power of Language ---------------------------------------- * Many bug fixes, primarily due to unit testing. * Tweaks to cover detection to pick 'frontcover' over 'backcover'. * Tweaks to song display, including proper support for the 'author' tag. * Remember size between invocations. * A freedesktop.org-compatible system tray icon, using the Egg status icon code by Anders Carlsson and Sun. * Multimedia key support, provided they're mapped (e.g. by Acme), using the MmKeys object from Muine by Lee Willis and Jan Arne Petersen. * UI tweaks to the main window. * Button to link to a song's website, or a Google search. * Infrastructure is in place for i18n/l10n, but I'm totally new to this, so I could've done something horribly wrong. 0.3 (2004-11-01) ---------------- * Handle mono MP3s correctly. * Crash less, especially when editing tags. * Many smaller bug fixes. 0.2 (2004-10-30) ---------------- * Song properties dialog, featuring mass tag editing/addition/removal. * Build/installation scripts. * Interface tweaks for HIG compliance and accessibility. * Try to save the library when ^C is pressed. * ~/.quodlibet/current interface to currently-playing song. * Save current query and song on exit. * An icon. * FLAC support. Writing to FLAC tags could be *very* buggy, so if you value your tags, please back them up. 0.1 (2004-10-30) ---------------- * Initial release. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.034269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/PKG-INFO����������������������������������������������������������������������������0000644�0001750�0001750�00000000526�14471213412�013302� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Metadata-Version: 2.1 Name: quodlibet Version: 4.6.0 Summary: a music library, tagger, and player Home-page: https://quodlibet.readthedocs.org Author: Joe Wreschnig, Michael Urman, & others Author-email: quod-libet-development@googlegroups.com Maintainer: Steven Robertson and Christoph Reiter License: GPL-2.0-or-later License-File: COPYING ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681762534.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/README.rst��������������������������������������������������������������������������0000644�0001750�0001750�00000005271�14417324346�013707� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. image:: https://img.shields.io/github/actions/workflow/status/quodlibet/quodlibet/main.yml?branch=main :target: https://github.com/quodlibet/quodlibet/actions .. image:: https://readthedocs.org/projects/quodlibet/badge/?version=latest :target: https://quodlibet.readthedocs.io .. image:: https://img.shields.io/codecov/c/github/quodlibet/quodlibet :target: https://app.codecov.io/gh/quodlibet/quodlibet .. image:: https://img.shields.io/github/v/release/quodlibet/quodlibet :target: https://github.com/quodlibet/quodlibet/releases .. image:: https://img.shields.io/github/contributors/quodlibet/quodlibet :target: https://github.com/quodlibet/quodlibet/graphs/contributors .. image:: https://hosted.weblate.org/widgets/quodlibet/-/quodlibet/svg-badge.svg :alt: Translation status :target: https://hosted.weblate.org/engage/quodlibet/ Quod Libet: an audio library, manager & player ============================================== .. image:: ./quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet.svg :width: 128px :alt: Quod Libet logo :align: left `Quod Libet <https://quodlibet.readthedocs.io>`_ is a cross-platform audio / music management program. It provides many ways to view your local libraries, and supports streaming audio and podcast feeds. It has extremely flexible metadata editing and searching capabilities. With over 90 plugins included, you can extend and integrate with almost anything, or `write your own <https://quodlibet.readthedocs.io/en/latest/development/plugins.html>`_ in Python! Quod Libet in action -------------------- .. figure:: https://github.com/quodlibet/quodlibet/raw/main/docs/images/album-list-2017-08.png :align: center See more `screenshots in the user guide <https://quodlibet.readthedocs.io/en/latest/screenshots.html>`_. Ex Falso: just the tag editor ----------------------------- Ex Falso is a bare-bones tag editor with the same editing interface as Quod Libet. Getting Started --------------- For information on how to build, install or test Quod Libet (and Ex Falso), check out the `development documentation <https://quodlibet.readthedocs.org/en/latest/development/overview.html>`_. For how to use the apps, consult the `user guide <https://quodlibet.readthedocs.io/en/latest/guide/>`_. Contact ------- .. image:: https://img.shields.io/mastodon/follow/109620111805015448?domain=https%3A%2F%2Ffosstodon.org&style=social :target: https://fosstodon.org/@quodlibet .. image:: https://img.shields.io/twitter/follow/QuodLibetApp?style=social :target: https://twitter.com/QuodLibetApp .. image:: https://img.shields.io/badge/discord-chat-blue?style=social&logo=discord :target: https://discord.gg/9A4RKFEm3c ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9509354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/�������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�013113� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/README.rst���������������������������������������������������������������������0000664�0001750�0001750�00000001167�14035600052�014605� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Some info on the file formats contained here: Man Pages (``*.1``) These are autogenerated using rst2man and the source can be found in ``docs/guide/commands`` Desktop Files (``*.desktop.in``) and AppData Files (``*.appdata.xml-in``) These can be edited here, but will be changed to include translations on installation. D-Bus Service Files (``*.service.in``) These depend on the installation path, so get changed during installation. GNOME Search Provider (``*-search-provider.ini``) Gets copied as is for GNOME to know that Quod Libet can provide a search provider (currently through a plugin) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/exfalso.1����������������������������������������������������������������������0000664�0001750�0001750�00000005111�14035600052�014632� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Man page generated from reStructuredText. . .TH EXFALSO 1 "" "" "" .SH NAME exfalso \- audio tag editor . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .sp \fBexfalso\fP [ \fIdirectory\fP ] .SH DESCRIPTION .sp Ex Falso displays and edits audio metadata tags. Supported formats include MP3, Ogg Vorbis, FLAC, Musepack (MPC), WavPack, and MOD/XM/IT. .sp This manual page is only a short reference for Ex Falso. Complete documentation is available at \fI\%https://quodlibet.readthedocs.io/en/latest/guide/\fP\&. .SH OPTIONS .sp Ex Falso may be given a directory to open on the command line. .SH TIED TAGS .sp Many places in Ex Falso allow you to use "tied tags". Tied tags are two tag names joined together with a "~" like "title~version" or "album~part". Tied tags result in "nice" displays even when one of the tags is missing; for example, "title~version" will result in Title \- Version when a version tag is present, but only Title when one isn\(aqt. You can tie any number of tags together. .SH RENAMING FILES .sp Ex Falso allows you to rename files based on their tags. In some cases you may wish to alter the filename depending on whether some tags are present or missing, in addition to their values. A common pattern might be .sp \fB<tracknumber>. <title~version>\fP .sp You can use a \(aq|\(aq to only text when a tag is present: .sp \fB<tracknumber|<tracknumber>. ><title~version>\fP .sp You can also specify literal text to use if the tag is missing by adding another \(aq|\(aq: .sp \fB<album|<album>|No Album> \- <title>\fP .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/renaming_files.html\fP\&. .SH BUGS .sp See \fI\%https://github.com/quodlibet/quodlibet/issues\fP for a list of all currently open bugs and feature requests. .SH AUTHORS .sp Joe Wreschnig and Michael Urman are the primary authors of Ex Falso. .SH SEE ALSO .nf \fI\%https://quodlibet.readthedocs.io/en/latest/guide/\fP, \fI\%https://quodlibet.readthedocs.io/en/latest/guide/faq.html\fP .fi .sp .\" Generated by docutils manpage writer. . �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692734603.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/io.github.quodlibet.ExFalso.appdata.xml.in�������������������������������������0000644�0001750�0001750�00000004563�14471212213�023100� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2013 Christoph Reiter --> <component type="desktop-application"> <id>io.github.quodlibet.ExFalso</id> <name>Ex Falso</name> <summary>Edit tags in your audio files</summary> <metadata_license>CC0</metadata_license> <project_license>GPL-2.0-or-later</project_license> <translation type="gettext">quodlibet</translation> <launchable type="desktop-id">io.github.quodlibet.ExFalso.desktop</launchable> <provides> <id>exfalso.desktop</id> <binary>exfalso</binary> </provides> <description> <p> Ex Falso is a tag editor with the same tag editing interface as Quod Libet. It lets you display and edit any tags you want in the file, for all the file formats it supports. </p> <p> Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI. </p> </description> <screenshots> <screenshot type="default"> <image>https://quodlibet.github.io/appdata/exfalso_1.png</image> </screenshot> </screenshots> <releases> <release version="4.6.0" date="2023-08-22"/> <release version="4.5.0" date="2022-03-29"/> <release version="4.4.0" date="2021-02-28"/> <release version="4.3.0" date="2020-02-22"/> <release version="4.2.1" date="2018-12-26"/> <release version="4.2.0" date="2018-10-31"/> <release version="4.1.0" date="2018-06-03"/> <release version="4.0.2" date="2018-01-17"/> <release version="4.0.1" date="2018-01-13"/> <release version="4.0.0" date="2017-12-26"/> <release version="3.9.1" date="2017-06-06"/> <release version="3.9.0" date="2017-05-24"/> </releases> <url type="homepage">https://quodlibet.readthedocs.org</url> <url type="bugtracker">https://quodlibet.readthedocs.io/en/latest/bugs_repo.html</url> <url type="help">https://quodlibet.readthedocs.io/en/latest/guide/index.html</url> <url type="translate">https://quodlibet.readthedocs.io/en/latest/translation/howto.html</url> <update_contact>quod-libet-development@googlegroups.com</update_contact> <content_rating type="oars-1.1"> <content_attribute id="social-info">moderate</content_attribute> </content_rating> </component> ���������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/io.github.quodlibet.ExFalso.desktop.in�����������������������������������������0000664�0001750�0001750�00000000440�14035600052�022326� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Desktop Entry] Name=Ex Falso GenericName=Audio tag editor Comment=Edit tags in your audio files Exec=exfalso Terminal=false StartupNotify=true StartupWMClass=io.github.quodlibet.ExFalso Type=Application Icon=io.github.quodlibet.ExFalso Categories=AudioVideo;Audio;AudioVideoEditing;GTK; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/io.github.quodlibet.QuodLibet-search-provider.ini������������������������������0000664�0001750�0001750�00000000300�14035600052�024444� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Shell Search Provider] DesktopId=io.github.quodlibet.QuodLibet.desktop BusName=io.github.quodlibet.QuodLibet.SearchProvider ObjectPath=/io/github/quodlibet/QuodLibet/SearchProvider Version=2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692734558.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/io.github.quodlibet.QuodLibet.appdata.xml.in�����������������������������������0000644�0001750�0001750�00000005353�14471212136�023431� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2013 Christoph Reiter --> <component type="desktop-application"> <id>io.github.quodlibet.QuodLibet</id> <name>Quod Libet</name> <summary>Listen to, browse, or edit your audio collection</summary> <metadata_license>CC0</metadata_license> <project_license>GPL-2.0-or-later</project_license> <translation type="gettext">quodlibet</translation> <launchable type="desktop-id">io.github.quodlibet.QuodLibet.desktop</launchable> <provides> <id>quodlibet.desktop</id> <binary>quodlibet</binary> <binary>operon</binary> </provides> <description> <p> Quod Libet is a music management program. It provides several different ways to view your audio library, as well as support for Internet radio and audio feeds. It has extremely flexible metadata tag editing and searching capabilities. </p> <p> Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI. </p> </description> <screenshots> <screenshot type="default"> <image>https://quodlibet.github.io/appdata/quodlibet_1.png</image> </screenshot> <screenshot> <image>https://quodlibet.github.io/appdata/quodlibet_2.png</image> </screenshot> <screenshot> <image>https://quodlibet.github.io/appdata/quodlibet_3.png</image> </screenshot> </screenshots> <releases> <release version="4.6.0" date="2023-08-22"/> <release version="4.5.0" date="2022-03-29"/> <release version="4.4.0" date="2021-02-28"/> <release version="4.3.0" date="2020-02-22"/> <release version="4.2.1" date="2018-12-26"/> <release version="4.2.0" date="2018-10-31"/> <release version="4.1.0" date="2018-06-03"/> <release version="4.0.2" date="2018-01-17"/> <release version="4.0.1" date="2018-01-13"/> <release version="4.0.0" date="2017-12-26"/> <release version="3.9.1" date="2017-06-06"/> <release version="3.9.0" date="2017-05-24"/> </releases> <url type="homepage">https://quodlibet.readthedocs.org</url> <url type="bugtracker">https://quodlibet.readthedocs.io/en/latest/bugs_repo.html</url> <url type="help">https://quodlibet.readthedocs.io/en/latest/guide/index.html</url> <url type="translate">https://quodlibet.readthedocs.io/en/latest/translation/howto.html</url> <update_contact>quod-libet-development@googlegroups.com</update_contact> <content_rating type="oars-1.1"> <content_attribute id="social-info">moderate</content_attribute> </content_rating> </component> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/io.github.quodlibet.QuodLibet.desktop.in���������������������������������������0000664�0001750�0001750�00000001562�14035600052�022663� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[Desktop Entry] Name=Quod Libet GenericName=Music Player Comment=Listen to, browse, or edit your audio collection Exec=quodlibet --run --play-file %U MimeType=application/x-flac;audio/aac;audio/aiff;audio/dsf;audio/midi;audio/mp3;audio/mp4;audio/mpeg;audio/mpeg4;audio/mpg;audio/ogg;audio/vorbis;audio/wav;audio/wave;audio/x-aac;audio/x-aiff;audio/x-flac;audio/x-m4a;audio/x-midi;audio/x-mp3;audio/x-mpc;audio/x-mpeg;audio/x-ms-wma;audio/x-ms-wmv;audio/x-musepack;audio/x-oggflac;audio/x-speex;audio/x-tta;audio/x-wav;audio/x-wavpack;audio/x-wma;video/ogg;video/x-ms-asf;video/x-theora;video/x-wmv;x-scheme-handler/quodlibet; Terminal=false StartupNotify=true StartupWMClass=io.github.quodlibet.QuodLibet Type=Application Icon=io.github.quodlibet.QuodLibet Categories=AudioVideo;Audio;Player;GTK; #http://live.gnome.org/GnomeGoals/NotificationSource X-GNOME-UsesNotifications=true ����������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/net.sacredchao.QuodLibet.service.in��������������������������������������������0000664�0001750�0001750�00000000112�14035600052�021642� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=net.sacredchao.QuodLibet Exec=@PREFIX@/bin/quodlibet ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/operon.1�����������������������������������������������������������������������0000664�0001750�0001750�00000020710�14035600052�014475� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Man page generated from reStructuredText. . .TH OPERON 1 "" "" "" .SH NAME operon \- command line music tagger . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .nf \fBoperon\fP [\-\-version] [\-\-help] [\-v | \-\-verbose] <\fIcommand\fP> [<\fIargument\fP>...] \fBoperon help\fP <\fIcommand\fP> .fi .sp .SH OPTIONS .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-version Print the program version .TP .B \-v\fP,\fB \-\-verbose Verbose mode .UNINDENT .SH COMMAND-OVERVIEW .SS Edit Tags .nf \fIadd\fP Add a tag value \fIremove\fP Remove a tag value \fIset\fP Set a tag and remove existing values \fIclear\fP Remove tags \fIcopy\fP Copy tags from one file to another \fIedit\fP Edit tags in a text editor \fIfill\fP Fill tags based on the file path .fi .sp .SS Show file metadata .nf \fIlist\fP List tags \fIinfo\fP List file information \fIprint\fP Print tags based on the given pattern .fi .sp .SS Edit Embedded Images .nf \fIimage\-extract\fP Extract embedded images \fIimage\-set\fP Set embedded image \fIimage\-clear\fP Remove embedded images .fi .sp .SS Miscellaneous .nf \fItags\fP List all common tags \fIhelp\fP Display help information .fi .sp .SH EDIT TAGS .SS add .sp Add a new tag \fB<tag>\fP with the value \fB<value>\fP to all files. .sp operon add [\-h] <tag> <value> <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .UNINDENT .INDENT 0.0 .TP .B Example: operon add artist \(aqThe Beatles\(aq song1.ogg song2.ogg .UNINDENT .SS remove .sp Remove all values from the tag \fB<tag>\fP that match either \fB<value>\fP or the regular expression \fB<pattern>\fP from all files. .sp operon remove [\-h] [\-\-dry\-run] <tag> (\-e <pattern> | <value>) <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the results without changing any files .TP .BI \-e\fP,\fB \-\-regexp \ <regexp> Remove all tag values that match the given regular expression .UNINDENT .INDENT 0.0 .TP .B Example: operon remove artist \(aqThe Beatles\(aq song.ogg .UNINDENT .SS set .sp Replace all values of the tag \fB<tag>\fP by \fB<value>\fP in all files. .sp operon set [\-h] [\-\-dry\-run] <tag> <value> <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the results without changing any files .UNINDENT .INDENT 0.0 .TP .B Example: operon set artist \(aqThe Beatles\(aq song.ogg .UNINDENT .SS clear .sp Remove all tags that match \fB<tag>\fP or the regular expression \fB<pattern>\fP from all files. If \fI\-\-all\fP is specified, all known tags will be removed. .sp operon clear [\-h] [\-\-dry\-run] (\-a | \-e <pattern> | <tag>) <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the results without changing any files .TP .B \-a\fP,\fB \-\-all Remove all tags .TP .BI \-e\fP,\fB \-\-regexp \ <regexp> Remove all tags that match the given regular expression .UNINDENT .INDENT 0.0 .TP .B Example: operon clear \-a song.ogg .sp operon clear \-e \(aqmusicbrainz_.*\(aq song.ogg .sp operon clear date song.ogg .UNINDENT .SS copy .sp Copy all tags from the file \fI<source>\fP to \fI<dest>\fP\&. All tags in \fB<dest>\fP will be preserved. In case the destination format doesn\(aqt support setting a tag from source, no tags will be copied. To ignore tags that aren\(aqt supported by the destination format pass \fI\-\-ignore\-errors\fP\&. .sp operon copy [\-h] [\-\-dry\-run] [\-\-ignore\-errors] <source> <dest> .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the results without changing any files .TP .B \-\-ignore\-errors Skip tags which the target file does not support .UNINDENT .INDENT 0.0 .TP .B Example: operon copy song.flac song.ogg .UNINDENT .SS edit .sp Shows all tags in a text editor and will apply any changes made to the text to the tags. \fIoperon\fP will use the editor specified in the VISUAL or EDITOR environment variables and if those are not set fall back to \(aqnano\(aq. .sp operon edit [\-h] [\-\-dry\-run] <file> .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the results without changing any files .UNINDENT .INDENT 0.0 .TP .B Example: VISUAL=vi operon edit song.flac .UNINDENT .SS fill .sp Fill tags based one file paths and a given pattern. .sp operon fill [\-h] [\-\-dry\-run] <pattern> <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help show this help message and exit .TP .B \-\-dry\-run show changes, don\(aqt apply them .UNINDENT .INDENT 0.0 .TP .B Example: operon fill \-\-dry\-run "<tracknumber>. <title>" "01. Was Ist Ist.flac" .UNINDENT .SH SHOW FILE METADATA .SS list .sp Lists all tags, values and a description of each tag in a table. .sp operon list [\-h] [\-a] [\-t] [\-c <c1>,<c2>...] <file> .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-a\fP,\fB \-\-all Also list programmatic tags .TP .B \-t\fP,\fB \-\-terse Output is terse and suitable for script processing .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-columns <name>,... Defines which columns should be printed and in which order .TP .B Example: operon list \-a song.flac .sp operon list \-t \-c tag,value song.ogg .UNINDENT .SS info .sp Lists non\-tag metadata like length, size and format. .sp operon info [\-h] [\-t] [\-c <c1>,<c2>...] <file> .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-t\fP,\fB \-\-terse Output is terse and suitable for script processing .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-columns <name>,... Defines which columns should be printed and in which order .TP .B Example: operon info a.ogg .UNINDENT .SS print .sp Prints information per file built from tag values. The pattern can be customized by passing a pattern string (See \fBquodlibet\fP(1) for the pattern format) .sp operon print [\-h] [\-p <pattern>] <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .BI \-p\fP,\fB \-\-pattern \ <pattern> Use a custom pattern .UNINDENT .INDENT 0.0 .TP .B Example: operon print \-p "<album> \- <artist>" a.ogg .UNINDENT .SH EDIT EMBEDDED IMAGES .SS image\-extract .sp Extract all embedded images to the current working directory or the specified destination directory. .sp operon image\-extract [\-h] [\-\-dry\-run] [\-\-primary] [\-d <destination>] <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-\-dry\-run Print the found images and resulting file paths but don\(aqt save them .TP .B \-\-primary Only extract the primary images for each file .TP .BI \-d\fP,\fB \-\-destination \ <destination> Save all images to the specified destination .UNINDENT .INDENT 0.0 .TP .B Example: operon image\-extract asong.mp3 anotherone.ogg .UNINDENT .SS image\-set .sp Set the provided image as primary embedded image and remove all other embedded images. .sp operon image\-set <image\-file> <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .UNINDENT .INDENT 0.0 .TP .B Example: operon image\-set cover.jpg song.mp3 .UNINDENT .SS image\-clear .sp Remove all embedded images from all specified files. .sp operon image\-clear <file>... .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .UNINDENT .INDENT 0.0 .TP .B Example: operon image\-clear song.mp3 .UNINDENT .SH MISCELLANEOUS .SS tags .sp List all common tags .sp operon tags [\-h] [\-a] [\-t] [\-c <c1>,<c2>...] .INDENT 0.0 .TP .B \-h\fP,\fB \-\-help Display help and exit .TP .B \-a\fP,\fB \-\-all Also list programmatic tags .TP .B \-t\fP,\fB \-\-terse Output is terse and suitable for script processing .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-columns <name>,... Defines which columns should be printed and in which order .TP .B Example: operon tags \-a .sp operon tags \-t \-c tag .UNINDENT .SS help .sp operon help [<command>] .INDENT 0.0 .TP .B Example: operon help list .UNINDENT .SH SEE ALSO .nf \fBregex\fP(7) \fBexfalso\fP(1) \fBquodlibet\fP(1) .fi .sp .\" Generated by docutils manpage writer. . ��������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/org.mpris.MediaPlayer2.quodlibet.service.in������������������������������������0000664�0001750�0001750�00000000122�14035600052�023257� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.mpris.MediaPlayer2.quodlibet Exec=@PREFIX@/bin/quodlibet ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/org.mpris.quodlibet.service.in�������������������������������������������������0000664�0001750�0001750�00000000105�14035600052�021003� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.mpris.quodlibet Exec=@PREFIX@/bin/quodlibet �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/quodlibet.1��������������������������������������������������������������������0000644�0001750�0001750�00000021021�14327505043�015165� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Man page generated from reStructuredText. . .TH QUODLIBET 1 "" "" "" .SH NAME quodlibet \- audio library manager and player . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .nf \fBquodlibet\fP [ \fB\-\-print\-playing\fP | \fIcontrol\fP ] \fBexfalso\fP [ \fIdirectory\fP ] .fi .sp .SH DESCRIPTION .sp Quod Libet is a music management program. It provides several different ways to view your audio library, as well as support for Internet radio and audio feeds. It has extremely flexible metadata tag editing and searching capabilities. .sp This manual page is only a short reference for Quod Libet. Complete documentation is available at \fI\%https://quodlibet.readthedocs.io/en/latest/guide/index.html\fP\&. .SH OPTIONS .INDENT 0.0 .TP .BI \-\-add\-location\fB= <location> Add a file or directory to the library .TP .B \-\-debug Print debugging information .TP .BI \-\-enqueue\fB= <filename|query> Enqueue a filename or query results .TP .BI \-\-enqueue\-files\fB= <filename[,filename..]> Enqueue comma\-separated files .TP .BI \-\-filter \ <tag=value> Filter on a tag value .TP .B \-\-focus Focus the running player .TP .B \-\-force\-previous Jump to previous song .TP .B \-\-help Display brief usage information .TP .B \-\-hide\-window Hide main window .TP .B \-\-list\-browsers List available browsers .TP .B \-\-next Jump to next song .TP .B \-\-no\-plugins Start without plugins .TP .BI \-\-open\-browser\fB= BrowserName Open a new browser .TP .B \-\-pause Pause playback .TP .B \-\-play Start playback .TP .BI \-\-play\-file\fB= filename Play a file .TP .B \-\-play\-pause Toggle play/pause mode .TP .B \-\-previous Jump to previous song if near the beginning, otherwise restart .TP .B \-\-print\-playing Print out information about the currently playing song. You may provide in a string like the kind described in the RENAMING FILES section below. .TP .B \-\-print\-playlist Print the current playlist .TP .BI \-\-print\-query\fB= <query> Print filenames of results of query .TP .B \-\-print\-query\-text Print the active text query .TP .B \-\-print\-queue Print the contents of the queue .TP .BI \-\-query\fB= search\-string Search your audio library .TP .BI \-\-queue\fB= <on|off|t> Show or hide the queue .TP .B \-\-quit Exit Quod Libet .TP .BI \-\-random\fB= tag Filter on a random value .TP .BI \-\-rating\fB= <[+|\-]0.0..1.0> Set rating of playing song .TP .B \-\-rating\-down Decrease rating of playing song by one star .TP .B \-\-rating\-up Increase rating of playing song by one star .TP .B \-\-refresh Refresh and rescan library .TP .BI \-\-repeat\fB= <off|on|t> Turn repeat off, on, or toggle .TP .BI \-\-repeat\-type\fB= <current|all|one|off> Repeat the currently playing song, the current list, stop after one song, or turn repeat off .TP .B \-\-run Start Quod Libet if it isn\(aqt running .TP .BI \-\-seek\fB= <[+|\-][HH:]MM:SS> Seek within the playing song .TP .BI \-\-set\-browser\fB= BrowserName Set the current browser .TP .B \-\-show\-window Show main window .TP .BI \-\-shuffle\fB= <off|on|t> Turn shuffle off, on, or toggle .TP .BI \-\-shuffle\-type\fB= <random|weighted|off> Set the shuffle type to be random, to prefer higher rated songs, or turn shuffle off .TP .B \-\-start\-hidden Don\(aqt show any windows on start .TP .B \-\-start\-playing Begin playing immediately .TP .B \-\-status Print playing status .TP .B \-\-stop Stop playback .TP .BI \-\-stop\-after\fB= <0|1|t> Stop after the playing song .TP .B \-\-toggle\-window Toggle main window visibility .TP .B \-\-unfilter Remove active browser filters .TP .BI \-\-unqueue\fB= <filename|query> Unqueue a file or query .TP .B \-\-version Display version and copyright .TP .BI \-\-volume\fB= <[+|\-]0..100> Set the volume .TP .B \-\-volume\-down Turn down the volume .TP .B \-\-volume\-up Turn up the volume .TP .BI \-\-with\-pattern\fB= <pattern> Set the output format of the --print-playing, --print-playlist, --print-query, and --print-queue commands. You may provide in a tag-pattern string like the kind described in the RENAMING FILES section below. .UNINDENT .SH ALBUM COVERS .sp Album covers should be put in the same directory as the songs they apply to, and have "folder", "front", or "cover" in their filenames. If you want to store multiple albums in the same directory but keep distinct cover images, the name of the appropriate image file must contain the labelid tag value, e.g. COCX\-32760 cover.jpg. .SH TIED TAGS .sp Many places in Quod Libet allow you to use "tied tags". Tied tags are two tag names joined together with a "~" like "title~version" or "album~part". Tied tags result in "nice" displays even when one of the tags is missing; for example, "title~version" will result in Title \- Version when a version tag is present, but only Title when one isn\(aqt. You can tie any number of tags together. .SH SEARCH SYNTAX .sp All of Quod Libet\(aqs search boxes support advanced searches of the following forms: .sp .nf tag = value tag = !value tag = "value" tag = /value/ tag = &(value1, value2) tag = |(value1, value2) !tag = value |(tag1 = value1, tag2 = value2) &(tag1 = value1, tag2 = value2) #(numerictag < value) #(numerictag = value) #(numerictag > value) .fi .sp .sp .sp The \(aqc\(aq postfix on strings or regular expressions makes the search case\-sensitive. Numeric values may be given as integers, floating\-point numbers, MM:SS format, or simple English, e.g. "3 days", "2 hours". .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/searching.html\fP\&. .sp All internal tags begin with a ~ character. Non\-numeric internal tags are ~base‐ name, ~dirname, ~filename, ~format, ~length, ~people, and ~rating. Numeric internal tags are ~#added, ~#bitrate, ~#disc, ~#lastplayed, ~#laststarted, ~#length, ~#mtime, ~#playcount, ~#skipcount, and ~#track. .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/tags/internal_tags.html\fP\&. .SH RENAMING FILES .sp Quod Libet allows you to rename files based on their tags. In some cases you may wish to alter the filename depending on whether some tags are present or missing, in addition to their values. A common pattern might be .sp \fB<tracknumber>. <title~version>\fP .sp You can use a \(aq|\(aq to only text when a tag is present: .sp \fB<tracknumber|<tracknumber>. ><title~version>\fP .sp You can also specify literal text to use if the tag is missing by adding another \(aq|\(aq: .sp \fB<album|<album>|No Album> \- <title>\fP .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/renaming_files.html\fP\&. .SH AUDIO BACKENDS .sp Quod Libet uses GStreamer for audio playback. It tries to read your GConf GStreamer configuration, but if that fails it falls back to osssink. You can change the pipeline option in ~/.quodlibet/config to use a different sink, or pass options to the sink. For example, you might use esdsink or alsasink device=hw:1. .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/playback/backends.html\fP\&. .SH FILES .INDENT 0.0 .TP .B ~/.quodlibet/songs A pickled Python dict of cached metadata. Deleting this file will remove all songs from your library. .TP .B ~/.quodlibet/config Quod Libet\(aqs configuration file. This file is overwritten when Quod Libet exits. .TP .B ~/.quodlibet/current A "key=value" file containing information about the currently playing song. .TP .B ~/.quodlibet/control A FIFO connected to the most\-recently\-started instance of the program. \-\-next, \-\-previous, etc., use this to control the player. .TP .B ~/.quodlibet/plugins/ Put plugins here. .TP .B ~/.quodlibet/browsers/ Put custom library browsers here. .UNINDENT .sp See \fI\%https://quodlibet.readthedocs.io/en/latest/guide/interacting.html\fP\&. .SH BUGS .sp See \fI\%https://github.com/quodlibet/quodlibet/issues\fP for a list of all currently open bugs and feature requests. .SH AUTHORS .sp Joe Wreschnig and Michael Urman are the primary authors of Quod Libet. .SH SEE ALSO .nf \fI\%https://quodlibet.readthedocs.io/en/latest/guide/\fP, \fI\%https://quodlibet.readthedocs.io/en/latest/guide/faq.html\fP, \fBregex\fP(7), \fBgst\-launch\fP(1) .fi .sp .\" Generated by docutils manpage writer. . ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/quodlibet.bash�����������������������������������������������������������������0000644�0001750�0001750�00000036772�14327505043�015765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# quodlibet(1) completion -*- shell-script -*- # vim: sts=4 sw=4 et # This file is part of Quodlibet. # # Copyright 2019 Arnaud Rebillout # # 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 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Quodlibet tags _ql_tags_make() { command -v operon >/dev/null 2>&1 || return operon tags -a -t -c tag | tr '\n' ' ' } _ql_tags="$(_ql_tags_make)" # Quodlibet supported extensions (as bash globs) _ql_audio_glob_make() { command -v python3 >/dev/null 2>&1 || return command -v quodlibet >/dev/null 2>&1 || return python3 - << EOF from quodlibet.formats import init, loaders init() exts = [] for k in sorted(loaders.keys()): dot, ext = k.split('.', 1) exts.append(ext) print('@(' + '|'.join(exts) + ')') EOF } _ql_audio_glob="$(_ql_audio_glob_make)" _ql_img_glob="@(gif|jp?(e)g|png)" # Quodlibet completion _quodlibet() { # Assigned variable by _init_completion: # cur Current argument. # prev Previous argument. # words Argument array. # cword Argument array size. local cur prev words cword _init_completion -n = || return # Quodlibet commands and options local opts=(--add-location --debug --enqueue --enqueue-files \ --filter --focus --force-previous --help --hide-window \ --list-browsers --next --no-plugins --open-browser --pause \ --play --play-file --play-pause --previous --print-playing \ --print-playlist --print-query --print-query-text --print-queue \ --query --queue --quit --random --refresh --repeat --repeat-type \ --run --seek --set-browser --set-rating --show-window --shuffle \ --shuffle-type --start-hidden --start-playing --status --stop \ --stop-after --toggle-window --unfilter --unqueue --version \ --volume --volume-down --volume-up) # Completion per otion case "$prev" in --enqueue|--unqueue|--enqueue-files|--add-location|--play-file) # For these options we complete with audio files, even though # it's not necessarily what user wants. # --add-location=location # --enqueue=filename|query # --enqueue-files=filename[,filename..] # --play-file=filename # --unqueue=filename|query _filedir "$_ql_audio_glob" return 0 ;; --queue|--repeat|--shuffle) compopt -o nosort comps="on off toggle" COMPREPLY=($(compgen -W "$comps" -- "$cur")) return 0 ;; --repeat-type) compopt -o nosort comps="current all one off" COMPREPLY=($(compgen -W "$comps" -- "$cur")) return 0 ;; --shuffle-type) compopt -o nosort comps="random weighted off" COMPREPLY=($(compgen -W "$comps" -- "$cur")) return 0 ;; --stop-after) compopt -o nosort comps="0 1 t" COMPREPLY=($(compgen -W "$comps" -- "$cur")) return 0 ;; --filter) # tag=value compopt -o nospace comps="$_ql_tags" COMPREPLY=($(compgen -S= -W "$comps" -- "$cur")) return 0 ;; --random) # tag comps="$_ql_tags" COMPREPLY=($(compgen -W "$comps" -- "$cur")) return 0 ;; --open-browser|--query|--print-query|--seek|--set-browser|--set-rating|--volume|--with-pattern) # These options expect an argument that we can't guess. # --open-browser=BrowserName # --query=query # --print-query=query # --seek=[+|-][HH:]MM:SS # --set-browser=BrowserName # --set-rating=0.0..1.0 # --volume=(+|-|)0..100 # --with-pattern=pattern return 0 ;; -*) # Other options don't expect any argument, however user might want # to provide more options. So we don't return yet. ;; esac # Initial completion case "$cur" in -*) COMPREPLY=($(compgen -W "${opts[*]}" -- "$cur")) return 0 ;; *) return 0 ;; esac } && \ complete -F _quodlibet quodlibet # Operon completion _in_array() { local i for i in "${@:2}"; do [[ $1 = "$i" ]] && return done } _operon() { # Assigned variable by _init_completion: # cur Current argument. # prev Previous argument. # words Argument array. # cword Argument array size. local cur prev words cword _init_completion -n = || return # Operon commands and options local opts=(--help --verbose --version) local cmds=(add clear copy edit fill help \ image-clear image-extract image-set \ info list print remove set tags) # Check if a command was entered already local command i for (( i=0; i < ${#words[@]}-1; i++ )); do if _in_array "${words[i]}" "${cmds[@]}"; then command=${words[i]} break fi done # Completion per command if [[ -n $command ]]; then case $command in add) # <tag> <value> <file> [<files>] nargs=0 for (( j=i+1; j < ${#words[@]}-1; j++ )); do case "${words[j]}" in -*) continue ;; *) nargs=$((nargs+1)) ;; esac done if [[ $nargs -eq 0 ]]; then comps="$_ql_tags" COMPREPLY=($(compgen -W "$comps" -- "$cur")) elif [[ $nargs -ge 2 ]]; then _filedir "$_ql_audio_glob" fi return 0 ;; clear) # [--dry-run] [-a | -e <pattern> | <tag>] <file> [<files>] case $cur in -*) comps="--all --dry-run --regexp" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) case $prev in -a|--all) compopt -o default COMPREPLY=() ;; -e|--regex) ;; *) nargs=0 for (( j=i+1; j < ${#words[@]}-1; j++ )); do case "${words[j]}" in -d|--dry-run) continue ;; -e|--regexp) continue ;; -a|--all) nargs=$((nargs+1)) ;; *) nargs=$((nargs+1)) ;; esac done if [[ $nargs -eq 0 ]]; then comps="$_ql_tags" COMPREPLY=($(compgen -W "$comps" -- "$cur")) elif [[ $nargs -ge 1 ]]; then _filedir "$_ql_audio_glob" fi ;; esac esac return 0 ;; copy) # [--dry-run] [--ignore-errors] <source> <dest> case $cur in -*) comps="--dry-run --ignore-errors" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) _filedir "$_ql_audio_glob" ;; esac return 0 ;; edit) # [--dry-run] <file> case $cur in -*) comps="--dry-run" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) _filedir "$_ql_audio_glob" ;; esac return 0 ;; fill) # [--dry-run] <pattern> <file> [<files>] case $cur in -*) comps="--dry-run" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) # no completion for <pattern> nargs=0 for (( j=i+1; j < ${#words[@]}-1; j++ )); do case "${words[j]}" in -*) continue ;; *) nargs=$((nargs+1)) ;; esac done if [[ $nargs -ge 1 ]]; then _filedir "$_ql_audio_glob" fi ;; esac return 0 ;; help) # [<command>] COMPREPLY=($(compgen -W "${cmds[*]}" -- "$cur")) return 0 ;; image-clear) # <file> [<files>] _filedir "$_ql_audio_glob" return 0 ;; image-extract) # [--dry-run] [--primary] [-d <destination>] <file> [<files>] case $cur in -*) comps="--destination --dry-run --primary" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) case $prev in -d|--destination) compopt -o default COMPREPLY=() ;; *) _filedir "$_ql_audio_glob" ;; esac ;; esac return 0 ;; image-set) # <image-file> <file> [<files>] case $prev in image-set) _filedir "$_ql_img_glob" ;; *) _filedir "$_ql_audio_glob" ;; esac return 0 ;; info) # [-t] [-c <c1>,<c2>...] <file> case $cur in -*) comps="--columns --terse" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) case $prev in -c|--columns) ;; *) _filedir "$_ql_audio_glob" ;; esac ;; esac return 0 ;; list) # [-a] [-t] [-c <c1>,<c2>...] <file> case $cur in -*) comps="--all --columns --terse" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) case $prev in -c|--columns) ;; *) _filedir "$_ql_audio_glob" ;; esac ;; esac return 0 ;; print) # [-p <pattern>] <file> [<files>] case $cur in -*) comps="--pattern" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) case $prev in -p|--pattern) ;; *) _filedir "$_ql_audio_glob" ;; esac ;; esac return 0 ;; remove) # [--dry-run] <tag> [-e <pattern> | <value>] <file> [<files>] case $cur in -*) comps="--dry-run --regexp" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) nargs=0 for (( j=i+1; j < ${#words[@]}-1; j++ )); do case "${words[j]}" in -*) continue ;; *) nargs=$((nargs+1)) ;; esac done if [[ $nargs -eq 0 ]]; then comps="$_ql_tags" COMPREPLY=($(compgen -W "$comps" -- "$cur")) elif [[ $nargs -ge 2 ]]; then _filedir "$_ql_audio_glob" fi ;; esac return 0 ;; set) # [--dry-run] <tag> <value> <file> [<files>] case $cur in -*) comps="--dry-run" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; *) nargs=0 for (( j=i+1; j < ${#words[@]}-1; j++ )); do case "${words[j]}" in -*) continue ;; *) nargs=$((nargs+1)) ;; esac done if [[ $nargs -eq 0 ]]; then comps="$_ql_tags" COMPREPLY=($(compgen -W "$comps" -- "$cur")) elif [[ $nargs -ge 2 ]]; then _filedir "$_ql_audio_glob" fi ;; esac return 0 ;; tags) # [-t] [-c <c1>,<c2>...] case $cur in -*) comps="--all --columns --terse" COMPREPLY=($(compgen -W "$comps" -- "$cur")) ;; esac return 0 ;; esac fi # Initial completion case "$cur" in -*) COMPREPLY=($(compgen -W "${opts[*]}" -- "$cur")) return 0 ;; *) COMPREPLY=($(compgen -W "${cmds[*]}" -- "$cur")) return 0 ;; esac } && \ complete -F _operon operon ������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/data/quodlibet.zsh������������������������������������������������������������������0000644�0001750�0001750�00000005171�14327505043�015641� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#compdef quodlibet local browsers=(SearchBar Playlists PanedBrowser AlbumList CoverGrid AlbumCollection FileSystem InternetRadio AudioFeeds Soundcloud) local orders=(toggle inorder shuffle weighted onesong) _arguments \ '--add-location=[Add a file or directory to the library]:file or directory:_files'\ '--debug[Print debugging information]'\ '--enqueue=[Enqueue a file or query]:file or query:_files'\ '--enqueue-files=[Enqueue comma-separated files]:files:_files'\ '--filter=[Filter on a tag value]:key=value'\ '--focus[Focus the running player]'\ '--force-previous[Jump to previous song]'\ '--help[Display brief usage information]'\ '--hide-window[Hide main window]'\ '--list-browsers[List available browsers]'\ '--next[Jump to next song]'\ '--no-plugins[Start without plugins]'\ '--open-browser=[Open a new browser]:browser name:($browsers)'\ '--pause[Pause playback]'\ '--play[Start playback]'\ '--play-file=[Play a file]:filename:_files'\ '--play-pause[Toggle play/pause mode]'\ '--previous[Jump to previous song]'\ '--print-playing=[Print the playing song and exit]:pattern'\ '--print-playlist[Print the current playlist]'\ '--print-query[Print filenames of results of query to stdout]:query'\ '--print-query-text[Print the active text query]'\ '--print-queue[Print the contents of the queue]'\ '--query=[Search your audio library]:query'\ '--queue=[Show or hide the queue]:on|off|t:(on off t)'\ '--quit[Exit Quod Libet]'\ '--random=[Filter on a random value]:tag'\ '--rating=[Set rating of playing song]:[+|-]0.0..1.0'\ '--rating-down[Decrease rating of playing song by one star]'\ '--rating-up[Increase rating of playing song by one star]'\ '--refresh[Refresh and rescan library]'\ '--repeat=[Turn repeat off, on, or toggle it]:0|1|t:(0 1 t)'\ '--seek=[Seek within the playing song]:[+|-][HH\:]MM\:SS'\ '--set-browser=[Set the current browser]:browser name:($browsers)'\ '--show-window[Show main window]'\ '--shuffle=[Set or toggle shuffle mode]:0|1|t:(0 1 t)'\ '--shuffle-type=[Set shuffle mode type]:random|weighted|off:(random weighted off)'\ "--start-hidden[Don't show any windows on start]"\ '--start-playing[Begin playing immediately]'\ '--status[Print player status]'\ '--stop[Stop playback]'\ '--stop-after=[Stop after the playing song]:0|1|t:(0 1 t)'\ '--toggle-window[Toggle main window visibility]'\ '--unfilter[Remove active browser filters]'\ '--version[Display version and copyright]'\ '--volume=[Set the volume]:[+|-]0..100'\ '--volume-down[Turn down volume]'\ '--volume-up[Turn up volume]'\ '--with-pattern=[Set template for --print-* commands]:pattern' �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9509354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/�������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�013132� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/Makefile�����������������������������������������������������������������������0000664�0001750�0001750�00000000563�14231604332�014577� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������all: python3 -m sphinx -j auto -b html -n . _build_all watch: sphinx-autobuild -j auto -b html -n . _build_all guide: python3 -m sphinx -j auto -b html -c . -n guide _build_guide clean: rm -rf _build_all _build_guide .PHONY: clean guide show linkcheck show: all xdg-open _build_all/index.html linkcheck: python3 -m sphinx -j auto -b linkcheck -n . _build_all ���������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/README.rst���������������������������������������������������������������������0000664�0001750�0001750�00000000675�14231604332�014632� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Quod Libet / Ex Falso Documentation =================================== Dependencies: * sphinx (http://sphinx-doc.org/) Development: make watch Start a server and auto rebuild on changes Build: make Build full documentation make guide Build only the user guide ../setup.py build_sphinx Build the user guide and put it into ``../build/sphinx``. This is meant for packagers who want to ship and install the user guide. �������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/bugs_repo.rst������������������������������������������������������������������0000664�0001750�0001750�00000001774�14035600052�015660� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������====================== Bug Tracker / Git Repo ====================== .. include:: icons.rst .. _bugtracker: |bug-logo| Bug Tracker ---------------------- We use the GitHub bug tracker: * List of existing issues: https://github.com/quodlibet/quodlibet/issues * Create a new issue: https://github.com/quodlibet/quodlibet/issues/new/choose .. _gitrepo: |github-logo| Git Repo ---------------------- Quod Libet uses `Git <https://git-scm.com/>`_ for source control and is hosted on `GitHub <https://github.com/>`_: https://github.com/quodlibet/quodlibet .. _RunFromSource: **Running from Source** (no installation is needed) **:** :: $ git clone https://github.com/quodlibet/quodlibet.git $ cd quodlibet $ ./quodlibet/quodlibet.py To get all the dependencies needed for running Quod Libet the easiest way is to use one of the unstable PPAs / repos listed on the :ref:`download page <Downloads>`. They pull in or contain all the needed dependencies for the latest code and are kept up to date. ����././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/changelog.rst������������������������������������������������������������������0000664�0001750�0001750�00000000056�14035600052�015612� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Changelog ========= .. include:: ../NEWS.rst ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/conf.py������������������������������������������������������������������������0000644�0001750�0001750�00000003536�14343330263�014442� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import types import sys dir_ = os.path.dirname(os.path.realpath(__file__)) def exec_module(path): """Executes the Python file at `path` and returns it as the module""" # We don't care about MSYSTEM in the doc build, just unset to prevent the # assert in const.py os.environ.pop("MSYSTEM", None) globals_ = {} with open(path, encoding="utf-8") as h: exec(h.read(), globals_) module = types.ModuleType("") module.__dict__.update(globals_) return module const = exec_module(os.path.join(dir_, "..", "quodlibet", "const.py")) needs_sphinx = "1.3" sys.path.append(os.path.join(dir_, "ext")) extensions = ['sphinx.ext.autodoc', 'sphinx.ext.extlinks', 'contributors'] source_suffix = '.rst' root_doc = 'index' project = 'Quod Libet' copyright = u"" exclude_patterns = ['_build', '_build_all', 'README.rst', '**/README.rst'] html_theme = "sphinx_rtd_theme" html_title = project extlinks = { 'bug': ('https://github.com/quodlibet/quodlibet/issues/%s', '#%s'), 'pr': ('https://github.com/quodlibet/quodlibet/pull/%s', '#%s'), 'user': ('https://github.com/%s', '%s'), } linkcheck_anchors = True linkcheck_workers = 20 linkcheck_ignore = [ r".*groups\.google\.com/.*", r".*keyserver\.ubuntu\.com.*" ] html_context = { 'extra_css_files': [ '//quodlibet.github.io/fonts/font-mfizz.css', '_static/extra.css', ], } html_static_path = [ "extra.css", ] html_theme_options = { "display_version": False, } html_favicon = "favicon/favicon.ico" html_show_copyright = False def setup(app): app.add_config_value('const', const, True) ������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/contact.rst��������������������������������������������������������������������0000664�0001750�0001750�00000001457�14231604332�015327� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Contact: Contact ======= It's easy to find the email addresses of Quod Libet's authors and maintainers, but please don't email us directly unless asked to, or if it concerns us specifically. If you contact just us, it means no one else can help you, and we can be really bad about replying to email. If you have a question or want to report a bug please `open a new issue <https://github.com/quodlibet/quodlibet/issues/new/choose>`_ on the GitHub issue tracker. If you are not sure if your issue is a bug you can also `start a discussion on our GitHub forum <https://github.com/quodlibet/quodlibet/discussions>`__. You can ask questions or just chat with us on our `Discord server <https://discord.gg/9A4RKFEm3c>`__. Quod Libet also has an IRC channel on `OFTC <https://www.oftc.net/>`__ , *#quodlibet*.�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/�������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015454� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/contributing.rst���������������������������������������������������0000664�0001750�0001750�00000012134�14035600052�020714� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Contribute: How to contribute ================= Testing ------- One of the most helpful things both regular users and developers can do is to test others' code. The easiest way to do this is to run the development version of Quod Libet. Development versions are kept stable, and the developers generally run the latest code to play their own music, so this is a safe and helpful way to contribute. Please keep in mind that Quod Libet is not forward compatible, meaning that if you use a newer version, reverting to an older version could lead to errors and data loss. So always backup your :ref:`config files<ConfigFiles>` if you plan to downgrade at a later point. You can find development packages in the :ref:`download section <Downloads>` . .. _BugReports: Filing bug reports ------------------ Useful Links * `List current bugs <https://github.com/quodlibet/quodlibet/issues>`_ * `Add a new bug <https://github.com/quodlibet/quodlibet/issues/new>`_ Writing a good bug report It helps the developers to format bugs in a standard way, with a short summary as the Issue title, ideally: 1. **Steps to reproduce** (how the bug can be demonstrated again) 2. **Expected output** (what *should* happen) 3. **Actual output** (what *did* happen) Also: the more logs, system details, and insight about the library / files the better the chance of a speedy resolution. For more general tips see `"How to Report Bugs Effectively" <https://www.chiark.greenend.org.uk/~sgtatham/bugs.html>`_. Look through existing issues Quod Libet is a mature project (in its second decade!), and there have been a *lot* of features and bugs discussed over the years. It's probable that what you're thinking has been discussed at some point, so please search through existing open (and to a lesser extent closed) issues before creating a new one. This reduces noise and saves the maintainers time. One bug per ticket Please do not create an item (ticket) in the issue tracker which contains reports of multiple unrelated issues. Even if you are reporting several very minor bugs, each one deserves its own issue. This allows each issue to receive independent discussion and analysis, and to be closed separately. Viewing Debug information If the bug you have found does not raise an exception, the debug window won't appear and the dump won't be generated. In this case, run quodlibet from the command line using the command ``quodlibet --debug``. It will show additional information that might be useful. Testing the latest code Some problems are fixed in the development branch which aren't yet fixed in the current release. If you can, try to reproduce your bug against a recent checkout before filing. Filing enhancement requests --------------------------- The most important component of an enhancement is the *why*. State what it is Quod Libet doesn't do for you, and give as much information about why you think adding a feature which accomplished this would be a good thing. If you have an idea as to how a feature might be implemented, suggestions are welcome, but be sure to explain why you want a feature before explaining how you envision it being implemented. Not only does this make your feature more likely to be supported, it allows others to enhance, generalize, and refine your ideas. As with bugs, please check for existing feature requests first and refrain from submitting multiple feature requests in the same issue. If you have related ideas, file them separately and mention the issue numbers of previous ideas. Translation ----------- Help us :ref:`translate Quod Libet into other languages<Translating>`. You don't need to know how to program in Python to do it. Getting started as a developer on Quod Libet -------------------------------------------- On an long-standing project it can be daunting helping out for the first time. The `newcomer-friendly tag <https://github.com/quodlibet/quodlibet/issues?q=is%3Aopen+is%3Aissue+label%3Anewcomer-friendly>`_ has been added to (some) issues to indicate where the existing developers feel there is an opportunity to help out without too much background (or risk). See the discussion around this in `Issue 2516 <https://github.com/quodlibet/quodlibet/issues/2516>`_ The other area perfect for newcomers is in the rich :ref:`plugins ecosystem <PluginDev>` - at time of writing QL has >80 plugins. These require less knowledge of Python, GTK+ and the QL architecture / codebase. It's best to examine existing (and past) PRs, keep an eye on the mailing list, and especially the Github issues list. Reading the unit / integration tests is usually instructive too. IRC can be a good place for more immediate questions. Submitting changes ------------------ Patches are always welcome, and should be in the form of a pull request or by attaching a patch to the issue. Please work on existing issues where possible (there are a lot), or at the very least make sure there is an accompanying issue for your PR. If you follow the :ref:`CodingGuidelines` it will be much easier to get your changes included quickly. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/devenv.rst���������������������������������������������������������0000644�0001750�0001750�00000007635�14343330263�017512� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. include:: ../icons.rst .. _DevEnv: Creating a Development Environment ================================== This will show you how to get the latest and freshest Quod Libet running on your machine and allow you to change it as you wish. The main task here is to install all the software which Quod Libet uses and depends on. |linux-logo| Linux ------------------ The easiest and recommended way to get all the dependencies needed for the development version is to install one of our unstable repositories. By doing so all the needed dependencies are automatically installed along the way. See the :ref:`download section <Downloads>` for a list of available repositories. In case your distribution is not supported you have to find/install the dependencies yourself. See the :ref:`PackagingGuide` for a list of dependencies. Now clone the Git repository and start Quod Libet:: $ git clone https://github.com/quodlibet/quodlibet.git $ ./quodlibet/quodlibet/quodlibet.py |macosx-logo| MacOS ------------------- On MacOS (formerly OS X) all the needed dependencies are included in the provided bundle itself. Download the latest bundle, which is guaranteed to work with current Git ``main``: `QuodLibet-latest.dmg <https://github.com/quodlibet/quodlibet/releases/download/ci/QuodLibet-latest.dmg>`__. It contains a ``run`` script which passes all arguments to the included Python with the right environment set up. :: $ git clone https://github.com/quodlibet/quodlibet.git $ ./QuodLibet.app/Contents/MacOS/run <path_to_git_repo>/quodlibet/quodlibet.py On recent MacOS releases, the OS Gatekeeper will complain about the application not being recognised. It is easiest to just clear the `com.apple.quarantine` extended attribute from all files in the bundle rather than try and open each and every component that MacOS will refuse to open: :: $ xattr -rd com.apple.quarantine ./QuodLibet.app/Contents The bundle includes `pip`, so you can always install additional packages (such as `flake8`, `pytest` and `flaky`, which would let you run the test suite): :: $ ./QuodLibet.app/Contents/MacOS/run -m pip install flake8 pytest flaky $ ./QuodLibet.app/Contents/MacOS/run <path_to_git_repo>/setup.py test If you want to run the tests with your own Python command, you'll need to install some additonal software and packages: :: $ brew install cairo dbus gst-libav gst-plugins-bad gst-plugins-good gst-plugins-ugly \ gstreamer gtk-mac-integration gtk+3 libsoup pkg-config pygobject3 $ poetry install $ poetry run pip install pyobjc .. |quodlibet.modules ref| replace:: ``quodlibet.modules`` moduleset file .. _quodlibet.modules ref: https://github.com/quodlibet/quodlibet/tree/main/dev-utils/osx_bundle/modulesets/quodlibet.modules This will *almost* cover all the dependencies that the bundle will contain; at the time of writing the brew gstreamer plugins do not include the wavpack (``gst-plugins-good``) or game-music-emu (gme, in ``gst-plugins-bad``) plugins. The above list may be out of date, check the ``quodlibet`` metamodule section of the |quodlibet.modules ref|_ for a more up-to-date list of dependencies. If you want to build a bundle yourself or change/add dependencies, see the `osx_bundle directory <https://github.com/quodlibet/quodlibet/tree/main/dev-utils/osx_bundle>`__ in the Git repo for further instructions. |windows-logo| Windows ---------------------- On Windows we use the `msys2 <http://www.msys2.org/>`__ environment for development. Check out the `win_installer <https://github.com/quodlibet/quodlibet/tree/main/dev-utils/win_installer>`__ directory in the Git repo for further instructions. Poetry ------ Across all environments, we now support Virtualenvs with Pip dependencies, managed by `Poetry <https://python-poetry.org/>`__. Installation, once cloned is just:: $ poetry install If you want all the *optional* dependencies for various plugins:: $ poetry install -E plugins ���������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/faq.rst������������������������������������������������������������0000664�0001750�0001750�00000003566�14035600052�016765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Frequently Asked Questions ========================== Why don't you use SQLite for the song database? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although the song data Quod Libet stores would benefit from a relational database, it does not have a predefined schema, and opts to let users define their own storage keys. This means relational databases based on SQL, which require predefined schemata, cannot be used directly. What about <my favourite NoSQL DB> then? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This gets asked fairly often. MongoDB, CouchDB etc are indeed a closer match to the existing setup, but there is *significant* work porting to any of these, and each comes with a compatibility / maintenance cost. There has to be a genuine case for the benefits outweighing the migration cost. Any environment variables I should know about? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ QUODLIBET_TEST_TRANS When set to a string will enclose all translatable strings with that string. This is useful for testing how the layout of the user interface behaves with longer text as can occur with translations and to see if all visible text is correctly marked as translatable. :: QUODLIBET_TEST_TRANS=XXX QUODLIBET_DEBUG When in the environment gives the same result as if ``--debug`` was passed. QUODLIBET_BACKEND Can be set to the audio backend, overriding the value present in the main config file. Useful for quickly testing a different audio backend. :: QUODLIBET_BACKEND=xinebe ./quodlibet.py QUODLIBET_USERDIR Can be set to a (potentially not existing) directory which will be used as the main config directory. Useful to test Quod Libet with a fresh config, test the initial user experience, or to try out things without them affecting your main library. :: QUODLIBET_USERDIR=foo ./quodlibet.py ������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/flatpak.rst��������������������������������������������������������0000664�0001750�0001750�00000000500�14035600052�017621� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flatpak ======= To share the config between the distro package/development environment and the flatpak symlink the config directory:: ln -s ~/.config/quodlibet ~/.var/app/io.github.quodlibet.QuodLibet/config Our official flatpak is hosted on Flathub: https://github.com/flathub/io.github.quodlibet.QuodLibet ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/formats.rst��������������������������������������������������������0000664�0001750�0001750�00000014274�14035600052�017667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Tag Formats & Spec Deviations ============================= Deviations ---------- Quod Libet deviates from several of the standards it claims to support. We'll document them here, but most of the time we won't change them; we had a good reason for violating them in the first place. General Deviations ------------------ Since we translate to and from many formats, sometimes we're forced to accept the lowest common denominator among tag formats. Don't worry; if it's too low we'll figure out some way around it. * Dates are restricted to YYYY or YYYY-MM-DD formats. Blame ID3. * = and ~ are not allowed in tag names, and tag names must also be pure ASCII. * Tag names are always case-insensitive. * Newlines are not allowed in tag values. If you use a newline in a tag value, it will instead be treated as two values for the tag. ID3 --- UTF-8 and ID3 Tags ^^^^^^^^^^^^^^^^^^ If Quod Libet finds data in an MP3 claiming to be "latin 1", it won't trust it. It'll try UTF-8 and some other encodings before it gives up and actually considers it Latin 1. On the other hand, when it writes tags, it saves purely ASCII values as UTF-8 and any non-ASCII values as UTF-16. This means it won't try to "guess" when it reloads them, and other programs shouldn't either. Using a format like Ogg Vorbis, FLAC, or Musepack, the tag encoding is known and Unicode is perfectly supported. Genre and TCON ^^^^^^^^^^^^^^ The ID3 standard is ambiguous in its specification for the TCON frame. If you try to use a numeric genre in the form of 02 or (23) (for example) it will get translated into a text genre. This means there's no way to have a genre actually start with (xx) for MP3s. QuodLibet::TXXX Frames ^^^^^^^^^^^^^^^^^^^^^^ ID3 doesn't let you have frames named whatever you want like Ogg Vorbis and APEv2 do. However, it does let you create "TXXX" frames which are text data with an associated "description". Quod Libet uses these frames with a *`QuodLibet``::<tagname>* description to store tags that don't have ID3 counterparts. For example, labelid is stored as *`QuodLibet`::labelid*. RVA2 / ReplayGain ^^^^^^^^^^^^^^^^^ Quod Libet implements ReplayGain using MP3's RVA2 frame. Unfortunately there is no standard on how to read RVA2 frames to support RG properly. If the description string is "album" the gain is treated as the album/audiophile value. Any other value is read as the track/radio value, but an actual description of "track" will preempt other values. I've passed this information along to the GStreamer guys and their RVA2 support should match this, once it's completed. foobar2000-style TXXX:replaygain_* tags are also supported, but migrated to the proper RVA2 format on save. COMM Frame Language codes ^^^^^^^^^^^^^^^^^^^^^^^^^ Language codes in COMM frames with empty descriptors are replaced by \x00\x00\x00 on save. These tend to contain garbage rather than valid language codes anyway, and empty descriptors are usually a sign of comments migrated ID3v1 or other formats that do not support language markers. Legacy Stuff ^^^^^^^^^^^^ Multiframe Hack: Since versions of ID3 prior to 2.4 did not support multiple values in a single text frame, we stored multiple text frames of the same type with one value for each if you tried to save more than one value per frame. This was strictly a violation of the ID3 spec, but we never encountered an ID3 reader that had trouble reading the tags saved this way (and still haven't). Now that we use Mutagen, we store multiple values in the standard ID3v2.4 format. Old tags are migrated when you edit them. QuodLibet:: COMM Frames: Quod Libet used to use COMM frames instead of TXXX frames for its extended tag names. It will still load old COMM tags, but clears then when you save the file again. APEv2 ----- Naming Conflicts ^^^^^^^^^^^^^^^^ Since we turn APEv2's ``Subtitle`` tag into version, you can't edit a tag named ``subtitle`` in MPC files. Similar problems exist for ``Track``, ``Catalog``, ``Year``, and ``Record location`` tags. VorbisComment ------------- This is a list of Ogg Vorbis tags Quod Libet uses that require special handling. They are presented here in the hopes that other applications will adopt them. **rating** The rating tag has a subkey of an email address, and is formatted as e.g. ``rating:quodlibet@sacredchao.net``. The email is used as a unique identifier to allow multiple users to share the same files (it need not actually be an email address, but having it as such ensures that it's unique across users). It represents how much a user likes a song. Its value is a string representation of a floating point number between 0.0 and 1.0, inclusive. This format is chosen so the application may decide what precision it offers to the user, and how this information is presented. If no value is present, the rating should be assumed to be 0.5. Example: ``rating:quodlibet@sacredchao.net=0.67`` **playcount** The playcount tag has a subkey of an email address, and is formatted as e.g. ``playcount:quodlibet@sacredchao.net``. It stores how many times the user has played the song all the way through, as a numeric string. If no value is present, it should be assumed to be 0. Example: ``playcount:quodlibet@sacredchao.net=3`` **website** The website tag stores an absolute IRI (Internationalized Resource Identifier), as per RFC 3987. The intent is that it hold an IRI suitable for opening in a standard web browser (e.g. http, https, or ftp scheme). As it is an IRI, and not a URI, it should be stored in unescaped form. If an application needs a URI, it should follow the procedure in RFC 3987 section 3.1 to convert a valid IRI to a valid URI. As per the Vorbis comment specification, the tag must be a UTF-8 representation of the Unicode string. This tag may occur any number of times in a file. Performer Roles ^^^^^^^^^^^^^^^ This is similar to the ID3v2 IPLS (involved person list) frame. Quod Libet displays these tags by putting the role after the name, parenthesized (e.g. ``Béla Fleck (banjo)``), but in other supporting programs the role can be associated with the name in any understandable way, or simply ignored and treated like an ordinary performer tag. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/guidelines.rst�����������������������������������������������������0000664�0001750�0001750�00000006021�14035600052�020333� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _CodingGuidelines: Coding Guidelines ================= Getting started --------------- Before you can start making changes to Quod Libet you have to set up a development environment. See ":ref:`DevEnv`" for further details. Source Overview --------------- ============ ========================================== browsers/* Things in the View menu ext/* Extensions to QL / EF (i.e. the plugins) formats/* File format support library/* Library management code plugins/* Base classes and structural enabling plugins operon/* Operon, the QL CLI tool qltk/* GTK+ widget subclasses/extensions util/* General utility functions and setup code ============ ========================================== If you want to get a full overview of QL's code, good places to start are ``browsers/_base.py``, ``formats/_audio.py``, and ``library/libraries.py``. Code Guidelines --------------- We try to keep Quod Libet's code in pretty good shape; when submitting a patch, it's much easier to get it included quickly if you run through this checklist of common-sense code quality items. Make sure your patch: * Passes existing tests. You can test this by executing ``./setup.py test`` * Is commented. * Adds your name to the copyright header of every file you touch. This helps you get credit and helps us keep track of authorship. General Guidelines ------------------ We prefer Python to C. We prefer ``ctypes`` to compiled C wrappers. A good way to get a new feature applied is if you include tests for it. Stock strings and string reuse are awesome, but don't make the interface awkward just to avoid a new string. Unit Tests ---------- Quod Libet comes with a lot of tests, which helps us control regression. To run them, run ``./setup.py test``. Your patch can't break any unit tests, and if you change tests in a non-obvious way (e.g. a patch that removes an entry point and also removes a test for it is obvious) you should explain why. It's possible, indeed encouraged, that a changeset was for no other purpose than to *improve* the testing / test coverage, as there have been plenty of bugs that have slipped through. As usual, any fix associated with a confirmed bug should include tests that would have found the original bug, where possible. Printing Text ------------- All terminal output should go through the ``print_``, ``print_w``, ``print_e``, or ``print_d`` functions. These will handle Unicode recoding. They also let us capture all output for debugging purposes. Translations ------------ All text that could be visible to users (with debugging mode disabled) should be marked translatable. You can do this by simply using the ``_`` function which is globally available (through __builtin__):: print_w(_("This is translatable")) To handle plural forms use ``ngettext``:: text = ngettext("%d second", "%d seconds", time) % time It is good practice to add a comment for translators if the translation depends on the context:: # Translators: As in "by Artist Name" text = _("by %s") % tag ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/index.rst����������������������������������������������������������0000664�0001750�0001750�00000000310�14035600052�017305� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Development Guide ================= .. toctree:: :titlesonly: overview devenv testing contributing guidelines plugins tools faq maint formats flatpak ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692734482.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/maint.rst����������������������������������������������������������0000644�0001750�0001750�00000004450�14471212022�017315� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������===================== Maintainer Guidelines ===================== Downstream Bug Trackers ----------------------- Some bug reports never make it to us so check these once in a while. * `Fedora <https://apps.fedoraproject.org/packages/quodlibet/bugs>`_ * `Debian <https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=quodlibet>`_ * `Arch Linux <https://bugs.archlinux.org/?project=1&string=quodlibet>`_ * `Ubuntu <https://launchpad.net/ubuntu/+source/quodlibet/+bugs>`_ * `Gentoo <https://bugs.gentoo.org/buglist.cgi?quicksearch=media-sound%2Fquodlibet>`_ Tags & Branches --------------- At the point where no more functionality will be added to a release, a new branch gets created. All bug fixes pushed to the default branch should be cherry-picked to the respective stable branches and vice versa. :: . . /|\ /|\ | | | | 3.6.-1 / <--- "quodlibet-3.5" branch |_____/ . | /|\ | | | 3.4.1 <--- "release-3.4.1" tag | | | 3.4.0.-1 | | | 3.4 <--- "release-3.4.0" tag | | 3.5.-1 / |______/ <--- "quodlibet-3.4" branch | | <--- default branch 3.4.-1 | /|\ Release Checklist ----------------- New stable branch ^^^^^^^^^^^^^^^^^ You can now use the ``dev-utils/new-branch.sh`` script to help do this. New stable release ^^^^^^^^^^^^^^^^^^ * ``git checkout quodlibet-x.y`` * Cherry-pick stuff from default branch * Grab title from `Daily Dinosaur Comics <http://www.qwantz.com/>`_ * Update :ref:`News` with a list of all bugfixes and features since last release * ``git commit -m "update NEWS"`` * ``setup.py distcheck`` * Update version to ``(X, Y, Z)`` in ``const.py`` * Update version to ``(X, Y, Z)`` in ``appdata.xml.in`` * ``git commit -m "release prep"`` * ``git tag release-x.y.z`` * ``git push origin release-x.y.z`` * Update version to ``(X, Y, Z, -1)`` * ``git commit -m "version bump"`` * Cherry-pick ``NEWS`` commit onto default branch * Create Windows builds / tarballs / macOS DMGs * Create checksums / signature, attach everything to the github tag * Update ``release_db/make.py``; run ``./release_db/update.sh`` * Update stable PPAs (ubuntu/debian/OBS) * Update the flathub repo * Announce on IRC / Discord / Twitter etc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/overview.rst�������������������������������������������������������0000664�0001750�0001750�00000001530�14035600052�020051� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������======== Overview ======== Building and Installing Quod Libet ---------------------------------- While Quod Libet uses distutils/setup.py for building and installing (``./setup.py build install`` etc.) we don't recommend it, as it doesn't provide a way to uninstall the application again and it might not do the right thing by default depending on your distribution/operating system. Instead we recommend running Quod Libet directly from the git checkout for development/experiments and use one of our unstable repositories for everyday use. See :ref:`DevEnv` on how to proceed. Testing Changes --------------- To make sure that your changes don't break any existing feature you should run the test suite by executing:: ./setup.py test For more details and options regarding testing, code quality testing and test coverage see :ref:`Testing`. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/plugins.rst��������������������������������������������������������0000644�0001750�0001750�00000006121�14343330263�017671� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _PluginDev: Plugin Development ================== A Quod Libet / Ex Falso Plugin is a simple python module or package which contains sub-classes of special plugin classes. These classes can provide special methods that get used by QL or can take action on certain events. At the moment the following plugin classes exist: Plugin Types ^^^^^^^^^^^^ Event Plugins * Are instantiated as long as they are enabled or QL is running. They get notified when songs start, get added etc. * Can also (3.10+) listen to selection changes in the main songlist. * Example: Last.fm scrobbler that watches what you play and sends the information to last.fm. Tag Editing Plugins * Can extend many parts of the tag editor. * Example: Title case your tags. GStreamer Plugins * Can inject elements into the GStreamer pipeline and configure them on the fly. * Example: Tempo adjustment to play music/audio books faster. Play Order: Shuffle Plugins * Can decide which song to play next or what happens if you select one. * Example: weighted shuffle, which prefers higher rated songs. Play Order: Repeat Plugins: * How to repeat the songs * Example: repeat each song a set number of times Songs Menu Plugins * Can be accessed through the play list context menu and get passed all selected songs. * Example: Album art search, to search album art for all selected songs. Playlist Plugins * Similar to Songs Menu plugin, and in fact derived on the same base class * Can be accessed through the playlist context menu in the :ref:`Playlist Browser <Playlists>` * Example: remove duplicate songs from a playlist. Cover Source Plugins * Fetch covers from external or local resources Location of Plugins ^^^^^^^^^^^^^^^^^^^ In older versions of Quod Libet, before they were moved into the main ``quodlibet`` module, plugins could be placed in ``~/.config/quodlibet/plugins`` on many Linux systems, and in ``~/.quodlibet/plugins`` on MacOS. Whilst this still may work, we recommend installing from source (see :ref:`DevEnv`) for all plugin development, which will allow a fuller integration experience (debugging, etc). Creating a new Plugin ^^^^^^^^^^^^^^^^^^^^^ #. Assuming you are running from source, put it in ``quodlibet/ext`` under a directory according to its plugin type (``events/`` etc). #. Write the following into the file:: from quodlibet.plugins.events import EventPlugin class MyPlugin(EventPlugin): PLUGIN_ID = "myplugin" PLUGIN_NAME = "My Plugin" #. Restart Quod Libet, or click the ``Refresh`` button in the plugins window. #. In Quod Libet open ``Music`` ⇒ ``Plugins`` and search the list for "My Plugin" Tips: ~~~~~ * The best way to find out what is possible is to read the documentation of the `plugin base classes <https://github.com/quodlibet/quodlibet/tree/main/quodlibet/plugins>`_ . * The easiest way to get started creating a new plugin is to look for `existing plugins <https://github.com/quodlibet/quodlibet/tree/main/quodlibet/ext>`_ that do something similar to what you want. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/testing.rst��������������������������������������������������������0000664�0001750�0001750�00000002716�14035600052�017667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Testing: ======= Testing ======= Quod Libet uses the CPython unittest framework for testing and `pytest <https://docs.pytest.org/en/latest/>`__ as a test runner. All testing related code can be found under ``quodlibet/tests``. To run the full tests suite simply execute:: ./setup.py test For checking the code coverage of the test suite run:: ./setup.py coverage Selecting a Specific Test ------------------------- To only test a subset of the test suite, pass a comma separated list of test class names to setup.py via the ``--to-run`` option. For example:: ./setup.py test --to-run=TMP3File,TAPICType Similarly the coverage report can also be generated for a subset of tests:: ./setup.py coverage --to-run=TMP3File,TAPICType Selecting by class name can take a long time because it needs to import all tests first. To speed things up you can just use pytest directly:: py.test tests/test_formats_mp3.py py.test tests/test_formats* py.test tests/test_formats_mp3.py::TMP3File To just run code quality tests:: py.test tests/quality Some helpful ``py.test`` options are ``-s`` for not hiding stdout and ``-x`` for stopping on the first error. For more information check out https://docs.pytest.org/en/latest/usage.html Abort on First Error -------------------- By passing ``-x`` to ``setup.py test`` the test suite will abort once it sees the first error instead of printing a summary of errors at the end:: ./setup.py test -x ��������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/development/tools.rst����������������������������������������������������������0000664�0001750�0001750�00000010235�14035600052�017345� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Useful Development Tools ======================== Memory Profiling ---------------- GObject Instance Count Leak Check ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Requires a development (only available in debug mode) version of glib. Jhbuild recommended. :: jhbuild shell GOBJECT_DEBUG=instance-count GTK_DEBUG=interactive ./quodlibet.py * In the GTK+ Inspector switch to the "Statistics" tab * Sort by "Cumulative" and press the "Next" multimedia key to quickly switch songs. * If something in the "Cumulative" column steadily increases we have a leak. Performance Profiling --------------------- cProfile ^^^^^^^^ * https://docs.python.org/2/library/profile.html * bundled with python :: python -m cProfile -s [sort_order] quodlibet.py > cprof.txt where ``sort_order`` can one of the following: calls, cumulative, file, line, module, name, nfl, pcalls, stdname, time Example output:: 885311 function calls (866204 primitive calls) in 12.110 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.002 0.002 12.112 12.112 quodlibet.py:11(<module>) 1 0.007 0.007 12.026 12.026 quodlibet.py:25(main) 19392/13067 0.151 0.000 4.342 0.000 __init__.py:639(__get__) 1 0.003 0.003 4.232 4.232 quodlibetwindow.py:121(__init__) 1 0.000 0.000 4.029 4.029 quodlibetwindow.py:549(select_browser) 1 0.002 0.002 4.022 4.022 albums.py:346(__init__) ... ... SnakeViz ^^^^^^^^ * https://jiffyclub.github.io/snakeviz/ * ``pip install snakeviz`` :: python -m cProfile -o prof.out quodlibet.py snakeviz prof.out Run Snake ^^^^^^^^^ * http://www.vrplumber.com/programming/runsnakerun/ * package runsnakerun in debian Wheezy :: python -m cProfile -o prof.out quodlibet.py runsnake prof.out Example: https://www.google.at/search?q=runsnakerun&tbm=isch Gprof2Dot ^^^^^^^^^ * https://github.com/jrfonseca/gprof2dot :: python -m cProfile -o output.pstats ./quodlibet.py gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png Line Profiler ^^^^^^^^^^^^^ * https://github.com/rkern/line_profiler :: # wrap all functions of interest with the @profile decorator ./kernprof.py -l ./quodlibet.py # creates quodlibet.py.lprof python line_profiler.py quodlibet.py.lprof > prof.txt Example output:: Timer unit: 1e-06 s File: test.py Function: a at line 2 Total time: 0.001528 s Line # Hits Time Per Hit % Time Line Contents ============================================================== 2 @profile 3 def a(): 4 1 134 134.0 8.8 print "hello" 5 1 12 12.0 0.8 b = [] 6 101 628 6.2 41.1 for i in xrange(100): 7 100 696 7.0 45.5 b.append(i) 8 1 58 58.0 3.8 print "world" strace ^^^^^^ * https://linux.die.net/man/1/strace :: strace -c ./quodlibet.py Example output:: time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 81.64 0.013274 9 1444 178 read 7.04 0.001144 0 4041 3259 open 3.81 0.000619 11 54 getdents64 2.80 0.000456 0 1004 fstat64 1.84 0.000299 0 2221 1688 stat64 ... ... IOProfiler ^^^^^^^^^^ * https://code.google.com/archive/p/ioapps/wikis/ioprofiler.wiki * strace GUI * Shows read/write to files (how many reads/writes per file, which parts of the files were affected) :: strace -q -a1 -s0 -f -tttT -oOUT_FILE -e trace=file,desc,process,socket ./quodlibet.py ioreplay -c -f OUT_FILE -o OUT_FILE.bin ioprofiler.py # open OUT_FILE.bin Example: https://code.google.com/archive/p/ioapps/wikis/IOProfilerScreenshots.wiki �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/downloads.rst������������������������������������������������������������������0000664�0001750�0001750�00000005524�14231604332�015665� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Downloads: .. include:: icons.rst Downloads ========= ================ ================================================ ========================================== **Linux:** |flatpak-logo| :ref:`Flatpak <flatpak>` \ |ubuntu-logo| :ref:`Ubuntu <ubuntu>` |debian-logo| :ref:`Debian <debian>` \ |fedora-logo| :ref:`Fedora <fedora>` |opensuse-logo| :ref:`openSUSE <opensuse>` \ |arch-logo| :ref:`Arch Linux <arch>` **Windows:** |windows-logo| :ref:`Windows <windows>` **macOS:** |macosx-logo| :ref:`macOS <macosx>` **Development:** |source-logo| :ref:`Release Tarballs <tarballs>` ================ ================================================ ========================================== All files are signed with the following key: `0EBF 782C 5D53 F7E5 FB02 A667 46BD 761F 7A49 B0EC <http://keyserver.ubuntu.com/pks/lookup?op=vindex&search=0x46BD761F7A49B0EC&fingerprint=on>`__ ---- .. _tarballs: |source-logo| Release Tarballs ------------------------------ .. include:: tables/default.rst For old releases see the `full file listing <https://github.com/quodlibet/quodlibet/releases>`__. .. _flatpak: |flatpak-logo| Flatpak ---------------------- * `Quod Libet <https://flathub.org/apps/details/io.github.quodlibet.QuodLibet>`__ on Flathub * `Ex Falso <https://flathub.org/apps/details/io.github.quodlibet.ExFalso>`__ on Flathub .. _ubuntu: |ubuntu-logo| Ubuntu -------------------- :: $ sudo add-apt-repository ppa:lazka/ppa .. _debian: |debian-logo| Debian -------------------- * Debian Stable:: # deb http://lazka.github.io/ql-debian/stable/ quodlibet-stable/ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5A62D0CAB6264964 sudo apt-get update sudo apt-get install quodlibet .. _fedora: |fedora-logo| Fedora -------------------- * `Fedora Stable Repo <https://software.opensuse.org/download.html?project=home%3Alazka0%3Aql-stable&package=quodlibet>`__ Check out the `official repos <https://apps.fedoraproject.org/packages/quodlibet/overview/>`__ first - they usually contain the latest release. .. _opensuse: |opensuse-logo| openSUSE ------------------------ * `openSUSE Stable Repo <https://software.opensuse.org/download.html?project=home%3Alazka0%3Aql-stable&package=quodlibet>`__ .. _arch: |arch-logo| Arch Linux ---------------------- :: $ pacman -S quodlibet .. _windows: |windows-logo| Windows ---------------------- .. include:: tables/windows.rst .. include:: tables/windows_portable.rst For old releases see the `full file listing <https://github.com/quodlibet/quodlibet/releases>`__. .. _macosx: |macosx-logo| macOS ------------------- .. include:: tables/osx_quodlibet.rst .. include:: tables/osx_exfalso.rst For old releases see the `full file listing <https://github.com/quodlibet/quodlibet/releases>`__. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/ext/���������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�013732� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/ext/contributors.py������������������������������������������������������������0000664�0001750�0001750�00000001527�14231604332�017047� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������from docutils.parsers.rst import Directive from docutils.nodes import paragraph class ContributorsDirective(Directive): required_arguments = 1 has_content = True def run(self): role = self.arguments[0] roles = ['authors', 'translators', 'artists'] if role not in roles: raise Exception('Argument must be in {}'.format(roles)) const = self.state.document.settings.env.config.const if role == 'authors': people = const.AUTHORS elif role == 'translators': people = const.TRANSLATORS else: people = const.ARTISTS output = ', '.join(people) return [paragraph(text=output)] def setup(app): app.add_directive('contributors', ContributorsDirective) return {"parallel_read_safe": True, "parallel_write_safe": True} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/extra.css����������������������������������������������������������������������0000664�0001750�0001750�00000000703�14035600052�014765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.wy-side-nav-search { background-color: initial; } .wy-nav-top { background-color: #404040; } .wy-side-nav-search input[type="text"] { border-color: transparent; } .wy-nav-content { margin: initial; } .rst-content div[role=navigation], footer { font-size: 0.85em; color: #999; } .rst-content div[role=navigation] hr { margin-top: 6px; } footer hr { margin-bottom: 6px; } .rst-footer-buttons { display: none; } �������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/favicon/�����������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014557� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/favicon/Makefile���������������������������������������������������������������0000664�0001750�0001750�00000001467�14244626671�016246� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SOURCE=favicon.svg DEST=favicon.ico all: $(DEST) favicon-16.png: $(SOURCE) inkscape $(SOURCE) --export-filename $@ -w 16 -h 16 favicon-24.png: $(SOURCE) inkscape $(SOURCE) --export-filename $@ -w 24 -h 24 favicon-32.png: $(SOURCE) inkscape $(SOURCE) --export-filename $@ -w 32 -h 32 favicon-48.png: $(SOURCE) inkscape $(SOURCE) --export-filename $@ -w 48 -h 48 favicon-64.png: $(SOURCE) inkscape $(SOURCE) --export-filename $@ -w 64 -h 64 $(DEST): favicon-16.png favicon-24.png favicon-32.png favicon-48.png favicon-64.png convert favicon-16.png favicon-24.png favicon-32.png favicon-48.png favicon-64.png $(DEST) rm favicon-16.png favicon-24.png favicon-32.png favicon-48.png favicon-64.png .PHONY: clean clean: rm -f favicon-16.png favicon-24.png favicon-32.png favicon-48.png favicon-64.png favicon.ico ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/favicon/README.rst�������������������������������������������������������������0000664�0001750�0001750�00000000126�14035600052�016243� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������The svg is based on ``quodlibet/images/hicolor/scalable/apps/quodlibet-symbolic.svg`` ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/favicon/favicon.ico������������������������������������������������������������0000664�0001750�0001750�00000103276�14244626671�016730� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �h��V������ � ���� ��� ���F��00��� �%����@@��� �(B��D��(������ ���� �����������������������������������������������������������������������������������������B.M5M5M5M5M5M5M5M5M5M5A-���������B.)))))10)))))A-��������M5)))))Ъpٹ)))))M5��������M5)))))Ъp+))))M5��������M5)))))ѫqͫ,)))M5��������M5)))))ѫqа˧)))M5��������M5)))))ѫr׶,*))M5��������M5)))))ѫr׶*پ)))M5��������M5)))))ѫr׶ƘQ̣e)))M5��������M5)))9ܿ׶)))))M5��������M5))*ֵ)))))M5��������M5))*9)))))M5��������C.)))2ĔK*))))))B.���������C.M5M5M5M5M5M5M5M5M5M5B.�����������������������������������������������������������������������������������������������������(������0���� ������ �������������������������������������������������������������������������������������������������������������������������"���b���f���f���f���f���f���f���f���f���f���f���f���f���f���f���f���f���b���!���������������#W<oMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMV<���!�����������aW<))))))))))))))))))V<���a�����������foM))))))))Ӯwճ))))))))oM���f�����������foM))))))))))))))))oM���f�����������foM))))))))3)))))))oM���f�����������foM))))))))Է,))))))oM���f�����������foM))))))))׼0)))))oM���f�����������foM))))))))ѱ*))))oM���f�����������foM))))))))Ѳ)ˡaϨl))))oM���f�����������foM))))))))Ѳ))))))oM���f�����������foM))))))))Ѳ))ҭu))))oM���f�����������foM))))))))Ѳ)@.))))oM���f�����������foM))))))))Ѳ)Ъoˡa)))))oM���f�����������foM))))))ƗPӰzԷѲ))))))))oM���f�����������foM))))+ͪѲ))))))))oM���f�����������foM))))ճέ))))))))oM���f�����������foM))))׶ŖN))))))))oM���f�����������foM))))/ɤʦÑF)))))))))oM���f�����������aX=))))))))))))))))))W<���a�����������#X=oMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMW<���"���������������#���b���f���f���f���f���f���f���f���f���f���f���f���f���f���f���f���f���b���#������������������������������������������������������������������������������������������������������������������������������������������������������(��� ���@���� ��������~��~������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��������������������������������������������������������������������������������� ������������������� kJe f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!e kJ ����������������������kJ))))))))))))))))))))))))jI����������������������ݓe )))))))))))ƘRŖN)))))))))))e ����������������������ݔf!)))))))))))Է)))))))))))f!����������������������ݔf!)))))))))))ո)))))))))))f!����������������������ݔf!)))))))))))չʞ\))))))))))f!����������������������ݔf!)))))))))))չ/)))))))))f!����������������������ݔf!)))))))))))չֺ.))))))))f!����������������������ݔf!)))))))))))ֹ5)))))))f!����������������������ݔf!)))))))))))ֹԷ1))))))f!����������������������ݔf!)))))))))))ֹ)@Ĝ))))))f!����������������������ݔf!)))))))))))ֺ))2))))))f!����������������������ݔf!)))))))))))ֺ)))Ɵ.)))))f!����������������������ݔf!)))))))))))ֺ)))ʥ))))))f!����������������������ݔf!)))))))))))׻)),ٹ))))))f!����������������������ݔf!)))))))))))׻))ѫq/))))))f!����������������������ݔf!)))))))))))׼))׶ʟ])))))))f!����������������������ݔf!))))))))+‘FēJ)))))))))))f!����������������������ݔf!)))))))Υh)))))))))))f!����������������������ݔf!))))))ѫr)))))))))))f!����������������������ݔf!))))),)))))))))))f!����������������������ݔf!))))).Φj)))))))))))f!����������������������ݔf!))))))ÙЩo))))))))))))f!����������������������ݓe )))))))ɞ[Ӱzˡa.)))))))))))))e ����������������������kJ))))))))))))))))))))))))kJ���������������������� lKe f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!f!e kJ ���������������������� ��������������������������������������������������������������������������������� ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(���0���`���� ������$��?��?����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���~���������������������������������������������������������������������������������������������������������������}��� ������������������������������� ��������� %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ������������ ������������������������������b ))))))))))))))))))))))))))))))))))b������~������������������������������c ))))))))))))))))))))))))))))))))))))b��������������������������������� )))))))))))))))))))))))))))))))))))))) ������������������������������%))))))))))))))))))׷ճ*)))))))))))))))))%������������������������������%))))))))))))))))))ˡ`)))))))))))))))))%������������������������������%))))))))))))))))))ճ)))))))))))))))))%������������������������������%))))))))))))))))))ٺ)))))))))))))))))%������������������������������%))))))))))))))))))پ)))))))))))))))))%������������������������������%)))))))))))))))))*ĔK))))))))))))))))%������������������������������%)))))))))))))))))*7)))))))))))))))%������������������������������%)))))))))))))))))*2))))))))))))))%������������������������������%)))))))))))))))))+;)))))))))))))%������������������������������%)))))))))))))))))+D))))))))))))%������������������������������%)))))))))))))))))+ÓI)))))))))))%������������������������������%))))))))))))))))),ͤe:ڼ4))))))))))%������������������������������%))))))))))))))))),ͤe))@ܿ))))))))))%������������������������������%))))))))))))))))),ͤe)))>))))))))))%������������������������������%))))))))))))))))),ͤe))))۽4)))))))))%������������������������������%))))))))))))))))),ͤe))))Φi8)))))))))%������������������������������%)))))))))))))))))-ͤe))))Ϩm))))))))))%������������������������������%)))))))))))))))))-ͤe))))ƞͫ))))))))))%������������������������������%)))))))))))))))))-ͤe)))0C))))))))))%������������������������������%))))))))))))))))).ͤe)))ղ~ٻ)))))))))))%������������������������������%))))))))))))))))).ͤe)))-)))))))))))%������������������������������%))))))))))))))))).ͤe)))ܿǙS))))))))))))%������������������������������%)))))))))))))))))/ͤe)))))))))))))))))%������������������������������%)))))))))))))țWȣոͤe)))))))))))))))))%������������������������������%)))))))))))6չͤe)))))))))))))))))%������������������������������%))))))))))3ͤe)))))))))))))))))%������������������������������%))))))))))ͪͤe)))))))))))))))))%������������������������������%)))))))))0ǙS)))))))))))))))))%������������������������������%)))))))))6ؾ))))))))))))))))))%������������������������������%))))))))))8))))))))))))))))))%������������������������������%))))))))))ŖOŝ1)))))))))))))))))))%������������������������������%)))))))))));عʦܿѬt3)))))))))))))))))))))%������������������������������)))))))))))))))))))))))))))))))))))))) ���������������������������������c ))))))))))))))))))))))))))))))))))))b ������������������������������������c ))))))))))))))))))))))))))))))))))c ��������������������������������� ��������� %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ������������ ������������������������������� ��������������������������������������������������������������������������������������������������������������������� ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(���@������� ������@��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���p���������������������������������������������������������������������������������������������������������������������������������������������������o��� �����������������������������������������������1���������������������������������������������������������������������������������������������������������������������������������������������������������������/������������������������������������������������ N6kJoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMkJN6 ������������ �����������������������������������q������, v&))))))))))))))))))))))))))))))))))))))))))))))u&+ ���������o�������������������������������������� v&))))))))))))))))))))))))))))))))))))))))))))))))u& ��������������������������������������������N6))))))))))))))))))))))))))))))))))))))))))))))))))M5��������������������������������������������kJ))))))))))))))))))))))))))))))))))))))))))))))))))kJ��������������������������������������������oM)))))))))))))))))))))));ؽԶA)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ЩnѲ)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ъo)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ъp)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ъp*))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѫqǚU))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѫq˧))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѫqŖO)))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѫr7))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѫr6)))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѬsB))))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѬsƗP)))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѬsɝZ))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ѭt̢c)))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ѬtƘQڼǚU))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ѭt))+Ӯw.)))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu))))ÑFִ)))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu)))))ĔK)))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu))))))˜-))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu))))))ÒG@))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu))))))*=))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ҭu))))))5*))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Үv))))))̢cֹ)))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Үv))))))Ɵˠ`)))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Үv)))))0ֹ))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ӯw)))))ղ~@))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))Ӯw)))),׷)))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ӯx))))ɞ[,)))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ӯx)))).عÒG))))))))))))))))oM��������������������������������������������oM)))))))))))))))))))))))ӯy)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))))))))/ɝ[Ա{ֵϨmٹ)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))))))9Ɵ)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))ͥg)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))))Ѭs)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))ƗP)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))))))))))))))))))))))))))oM��������������������������������������������oM))))))))))))5ǡ)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))<?)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))),Щn))))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))ٺЪp)))))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))+а׼ÒG))))))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))))ͥgҳոٺÑF))))))))))))))))))))))))))))oM��������������������������������������������kJ))))))))))))))))))))))))))))))))))))))))))))))))))kJ��������������������������������������������O7))))))))))))))))))))))))))))))))))))))))))))))))))N6�������������������������������������������� w&))))))))))))))))))))))))))))))))))))))))))))))))v& �����������������������������������������r������- w&))))))))))))))))))))))))))))))))))))))))))))))v&, ���������p�������������������������������������������� O7kJoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMkJO7 ���������������������������������������������������2���������������������������������������������������������������������������������������������������������������������������������������������������������������1��������������������������������������������������r���������������������������������������������������������������������������������������������������������������������������������������������������q�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/favicon/favicon.svg������������������������������������������������������������0000664�0001750�0001750�00000024420�14244626671�016746� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="135" height="135" id="svg2" sodipodi:version="0.32" inkscape:version="1.0 (4035a4f, 2020-05-01)" version="1.0" sodipodi:docname="favicon.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"> <defs id="defs4"> <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" id="perspective10" /> <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" id="perspective2897" /> <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" id="perspective2450" /> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2474"> <path d="m 0,450.7086 121.89,0 0,153.071 -121.89,0 0,-153.071 z" id="path2476" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2484"> <path d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" id="path2486" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2494"> <path d="m 0,1802.8342 487.5601,0 0,578.1658 L 0,2381 0,1802.8342 z" id="path2496" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2504"> <path d="m -1.5e-6,-2.94433 2.3255315,0 0,3.88873 -2.3255315,0 0,-3.88873 z" id="path2506" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2514"> <path d="m 0,1802.8342 487.5601,0 0,578.1658 L 0,2381 0,1802.8342 z" id="path2516" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2532"> <path d="m 9.806,537.3086 104.874,0 0,28.203 -104.874,0 0,-28.203 z" id="path2534" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2542"> <path d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" id="path2544" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2552"> <path d="m 39.2241,2149.2344 419.4961,0 0,112.812 -419.4961,0 0,-112.812 z" id="path2554" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2562"> <path d="m -0.0935124,-19.05134 2.7028824,0 0,21.10663 -2.7028824,0 0,-21.10663 z" id="path2564" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2572"> <path d="m 39.2241,2149.2344 419.4961,0 0,112.812 -419.4961,0 0,-112.812 z" id="path2574" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2612"> <path d="m 0,-9.1245 291.968,0 0,462.668 -291.968,0 0,-462.668 z" id="path2614" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2618"> <path d="m 0,0 283.5,0 0,453.5436 -283.5,0 L 0,0 z" id="path2620" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2628"> <path d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" id="path2630" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2638"> <path d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" id="path2640" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2644"> <path d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" id="path2646" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2654"> <path d="m 8.716e-4,0.0203769 0.9688584,0 0,1.2848631 -0.9688584,0 0,-1.2848631 z" id="path2656" inkscape:connector-curvature="0" /> </clipPath> <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2664"> <path d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" id="path2666" inkscape:connector-curvature="0" /> </clipPath> <inkscape:perspective id="perspective2777" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 526.18109 : 1" sodipodi:type="inkscape:persp3d" /> </defs> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="15.493518" inkscape:cx="70.514307" inkscape:cy="32.488051" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1280" inkscape:window-height="674" inkscape:window-x="12" inkscape:window-y="34" inkscape:window-maximized="0" showborder="true" fit-margin-top="9" fit-margin-left="9" fit-margin-right="9" fit-margin-bottom="9" inkscape:document-rotation="0" /> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title /> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="Ebene 1" inkscape:groupmode="layer" id="layer1" transform="translate(-74.24472,-374.35257)"> <rect style="fill:#000000;fill-opacity:1" id="rect3079" width="117" height="117" x="83.24472" y="383.35257" ry="10.173913" /> <rect style="fill:#2980b9;fill-opacity:1" id="rect3849" width="108" height="108" x="87.74472" y="387.85257" ry="8.9513502" /> <g id="g3855" transform="translate(0.7466894,0.04879762)" style="fill:#4e9a06" /> <path sodipodi:nodetypes="cccscccscsccscssscccssssccscccccccccccccc" inkscape:connector-curvature="0" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 125.7562,397.97838 c -3.75201,0.11817 -6.86751,2.28335 -8.4611,5.18277 -1.69326,3.08079 -1.66177,7.17185 0.91489,10.28464 2.40976,3.52887 6.26746,6.23305 10.55846,7.50265 3.25328,0.96256 6.81723,1.07759 10.08238,-0.084 0.008,20.33728 0.0903,42.71605 0.0903,62.80942 -7.5e-4,0.90761 0.61217,1.70095 1.49058,1.92934 1.49213,0.38695 3.30675,-0.1216 4.15429,-1.23852 0.84756,-1.11691 0.96988,-2.2747 1.06114,-3.37323 0.0913,-1.09854 0.0695,-2.19071 0.0903,-3.10873 0.0208,-0.91804 0.14692,-1.68486 0.1867,-1.7862 0.0414,-0.10596 0.0737,-0.21528 0.0965,-0.32675 0.83315,-4.02208 3.29815,-7.15269 6.48508,-10.19439 3.18693,-3.0417 7.04187,-5.88943 10.21929,-9.37287 5.52161,-6.03468 6.25776,-15.26308 1.39722,-21.97272 -0.44728,-0.61745 -1.80181,-2.84019 -2.86289,-4.60864 -0.53056,-0.88422 -1.00448,-1.67375 -1.32877,-2.19383 -0.16213,-0.26005 -0.20489,-0.36511 -0.44809,-0.66906 -0.0608,-0.0759 0.0783,-0.12709 -0.59125,-0.51344 -0.0837,-0.0482 -0.34167,-0.15539 -0.34231,-0.1556 -6.3e-4,-2.3e-4 -0.63431,-0.11203 -0.63481,-0.11203 -5.3e-4,-1e-5 -0.96118,0.23628 -0.96156,0.2365 -3.9e-4,2.1e-4 -0.74035,0.68729 -0.74063,0.68771 -2.7e-4,4.4e-4 -0.26124,0.61551 -0.26138,0.61614 -1.5e-4,6.6e-4 -0.0465,0.28875 -0.0498,0.38899 -0.006,0.20047 0.0106,0.31427 0.0249,0.40142 0.1156,0.69728 0.15691,0.52664 0.21159,0.64728 0.009,0.0199 0.0183,0.0396 0.028,0.0591 2.68494,5.44925 5.64548,11.00067 4.30366,16.11001 -1.73468,6.19078 -8.18578,10.41317 -15.03018,11.55426 -0.0293,-0.3107 -0.0293,-0.39049 -0.0934,-1.33808 v -45.23063 c 3.3e-4,-0.26043 -0.0504,-0.51839 -0.14937,-0.75929 -2.93098,-7.10825 -10.95166,-11.5581 -18.68039,-11.36756 -0.25553,-0.0107 -0.50915,-0.0125 -0.75929,-0.005 z m -0.67216,19.38832 c 0.052,0.0347 0.12463,0.0437 0.17739,0.0779 0.0378,0.0179 0.0616,0.0573 0.0996,0.0746 l -0.27696,-0.15248 z" id="path7097" /> </g> </svg> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656278102.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/features.rst�������������������������������������������������������������������0000664�0001750�0001750�00000010051�14256146126�015511� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Features: Features ======== Audio Playback ^^^^^^^^^^^^^^ * Multiple audio back-ends (GStreamer, xine-lib). * JACK output is also supported explicitly (via GStreamer) * Rich Replay Gain support. Auto-selects between 'track' and 'album' mode based on current view and play order * Applies clipping prevention whenever available * Configurable default (fallback) and pre-amp values to suit any audio setup * Multimedia key support * Real shuffle mode, that plays the whole playlist before repeating * Weighted (by rating) random playback * Proper 'Previous' support in shuffle mode * A configurable play queue Editing Tags ^^^^^^^^^^^^ * Full Unicode support * Make changes to many files at once * Make changes across all supported file formats * Tag files based on their filenames with configurable formats * Rename files based on their tags, with various filters for troublesome characters (especially on Windows) * No ugly ``%a``, ``%t`` patterns - more readable ``<artist>``, ``<title>`` instead * Fast track renumbering * Add / edit bookmarks within files * See full instructions at :ref:`EditingTags` Audio Library ^^^^^^^^^^^^^ * Hide songs on removable devices that may not always be there * Watch library for external changes, additions and deletions * Save song ratings and play counts * Internet Radio support * Audio Feeds ("Podcast") support * Deep playlist support with import / export (XSPF, M3U, PLS) * Soundcloud browsing and streaming, with login and native favorites support User Interface ^^^^^^^^^^^^^^ * Simple user interface to Just Play Music if you want * Themeable, modern, Gnome-friendly UI (dark and light modes supported) * Useful as a small window or maximized, no feeling cramped or wasted space * Optional high-resolution waveform seekbar (via WaveForm Plugin) * Paned View to group / funnel library data with arbitrary tags (e.g. Year -> Genre -> People -> Album) * Album cover display in variety of rich layouts * Full player control from a tray icon * Recognize and display many uncommon tags, as well as any others you want. Especially useful for classical music. * Rich CLI support (with ``quodlibet`` but also ``operon``) Library Browsing ^^^^^^^^^^^^^^^^ * Simple text-searches (unicode-aware) * Or... regular expression searches across tag values or free text * Or even... complex structured boolean logic and arbitrary Python code * Constructed playlists * iTunes/Rhythmbox-like paned browser, but with any tags you want (Genre, Date, etc) * Album list with cover art * By directory, including songs not in your library Python-based plugins ^^^^^^^^^^^^^^^^^^^^ Quod Libet has over 80 plugins contributed by devs and users, including: * Download high-quality cover art from pluggable sources * Automatic tagging via `MusicBrainz <http://musicbrainz.org/>`_ and CDDB * Configurable on-screen display notifications when songs change * Last.fm / AudioScrobbler submission * Plugins for web lyrics and synchronised (``.lrc`) lyrics viewing * A selection of audio-processing (pitch adjust, stereo downmix, EQ) * Custom Commands to run shell (think ``xargs`` for Quod Libet) * Find and remove duplicate / similar tracks across your entire library * Intelligent title-casing of tags * Find (and examine / remove) near-duplicate songs across your entire collection * Audio fingerprinting of music * Sync playlists to Sonos devices or Logitech Squeezebox devices. * Interface with dBus, MQTT, and other desktop apps too. * Scan and save Replay Gain values across multiple albums at once (using gstreamer) File Format Support ^^^^^^^^^^^^^^^^^^^ * MP3, Ogg Vorbis / Speex / Opus, FLAC, Musepack, MOD/XM/IT, Wavpack, MPEG-4 AAC, WMA, MIDI, Monkey's Audio UNIX-like integration ^^^^^^^^^^^^^^^^^^^^^ * Player control, status information, and querying of library from the command line * Can used named pipes to control running instance. * Now-playing is available as a fixed file * Rich DBus support (once enabled) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/�������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014227� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015530� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/album.rst���������������������������������������������������������0000664�0001750�0001750�00000006166�14035600052�017371� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Album Browsers ============== Identifying albums ------------------ Throughout Quod Libet, albums are grouped by examining the ``album`` tag on individual songs. To support distinct albums with the same name, groups of songs with the same 'album' tag are further inspected for the presence of one of three tags: ``album_grouping_key``, ``labelid``, and ``musicbrainz_albumid``, in that order. If a song has any of these, it will be used to identify the album it belongs to along with the ``album`` tag. In short, if more than one album in your library has the same name, use one of the secondary tags to separate them. The MusicBrainz plugin will add ``musicbrainz_albumid`` tags automatically, and may be the easiest solution for adding identically-named albums to your library. Album List Browser ------------------ .. image:: ../../images/album.png :scale: 45% :align: left The *Album List* browser makes it easy to treat your music collection as a set of albums, presented on the left, rather than as a set of songs, via album-centric enhancements to viewing, sorting, and searching. You can (configurably) display the album art next to each album to allow faster identification of your albums (plus *it's just prettier*...). Extra features related to searching, sorting and presenting albums are detailed below. Cover Grid Browser ------------------ .. image:: ../../images/covergrid-plus-waveform-2017-08.png :scale: 30% :align: right The cover grid is another album-like browser that places more emphasis on the album art. It has a search similar to album list (see the section below), and configuration of its own (including a flexible per-album display area). Searching --------- After creating the list of albums using the heuristic described above, the Album List browser then computes information across all the songs in an album. While the browser uses sensible defaults as to exactly how this information is compiled, it also exposes the choice while searching. This is most useful with numeric searches. For example, to find the albums with an *average* rating of 0.6 or greater, you can search for ``#(rating >= .6)`` This works because the Album List averages the values of numeric tags by default. To find the albums with *any song* with a rating of .6 or greater, though, you have to add something to your search: ``#(rating:max >= .6)`` These tag suffixes work for any numeric search. The options are ``min``, ``max``, ``sum``, and ``avg`` (the default). For string tags, the values which get searched are created by joining all of the underlying songs' values together. The albums in an Album List also have a few tags which are computed in a particular manner. A few of the interesting ones: * ``~#length`` is computed as the sum of the length of the underlying songs. * ``~#tracks`` and ``~#discs`` are the total number of songs and discs in an album. Also useful, though not strictly album-only: * ``~#filesize`` is the size on disk of a file in bytes (but can be formatted for humans) * ``~people`` is computed from all underlying tracks, with duplicate entries removed. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1664110870.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/audiofeeds.rst����������������������������������������������������0000644�0001750�0001750�00000000144�14314050426�020371� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Audio Feeds Browser ------------------- This is now known as the :ref:`Podcasts Browser<Podcasts>` ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/filesystem.rst����������������������������������������������������0000664�0001750�0001750�00000001077�14035600052�020451� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������File System Browser ------------------- This browser lets you view songs based on the folder they're in. It can play and edit songs inside and outside of your song library, and adds an item to the context menu to add the selected songs to your library. If you try to add songs to a playlist or the play queue that aren't in your library, they will be added automatically to it. .. note:: Since ratings and play counts are usually stored in the library rather than the song, play counts and ratings will only be saved if you add the song to your library! �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1664110870.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/index.rst���������������������������������������������������������0000644�0001750�0001750�00000000311�14314050426�017364� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Browse: Browsing Your Library ===================== .. toctree:: :titlesonly: overview playlists search album paned filesystem iradio podcasts soundcloud �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/iradio.rst��������������������������������������������������������0000664�0001750�0001750�00000001356�14035600052�017534� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Internet Radio Browser ---------------------- This browser lets you listen to Internet radio stations (a.k.a. streaming audio or Shoutcast). It supports MP3 and Ogg Vorbis streaming, and may support other formats (AAC or RealMedia) if you have appropriate GStreamer plugins installed. *New Station* accepts either a direct URL to a stream, or a URL to a ``.pls`` file with a list of streams. Radio stations cannot be added to playlists or the play queue. You can edit the ``title``, ``artist``, and ``grouping`` tags, but the rest are filled in by the station when you listen. If you don't know any good stations, the *Stations...* button will let you select some. If you do know some good stations, you can add them to the Stations list. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/overview.rst������������������������������������������������������0000664�0001750�0001750�00000004042�14035600052�020126� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Overview ======== Quod Libet has different ways to browse your library, called *Browsers*, which are selectable from the *View* menu. There is always one (the *primary*) browser active. Secondary Browsers ------------------ .. figure:: ../../images/queue_2browsers.png :align: right :scale: 30% Multiple Browsers - Search & secondary Album List You can also browse your library in a separate window (without disturbing your current playlist) by selecting one of the options from *Browse* → *Open Browser*. You can have multiple of these open at once, and they will all react to changes to your library underneath. The Song List ------------- The *Song List*, as the name implies, presents a list of all the songs that the current browser has found, or filtered for you. The columns are configurable, and can generally be any tag, or even combinations of tags from your library. For more information on tags, see :ref:`AudioTags`. Sorting: * List columns sorted by "disc" and "track" are actually sorted by "album" * All songs are sorted by the column header tag and with a special sort key. If there is something wrong with the sort order check the tags used in the sort key: *"albumsort or album, album_grouping_key or labelid or musicbrainz_albumid, ~#disc, ~#track, artistsort or artist, musicbrainz_artistid, title, ~filename"* (see :ref:`AudioTags`) Filters ------- Filters allow you to remove all but a subset of songs that from a browser's song list, typically based on a tag. Different browsers implement these accordingly; in the Search browser, these become searches e.g. filtering by Artist might produce a search ``artist='Beethoven'c`` Some filters are not available on all browsers. For example, the Search Bar can filter by anything, but there's no way to get a "top 40" in the Album List. Note also that when using the song context menu (a.k.a. "songsmenu"), QL notices which *column* the mouse is in when you right-click on a song selection, and will offer this column as a quick filter too, if possible. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/paned.rst���������������������������������������������������������0000664�0001750�0001750�00000011647�14035600052�017360� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Paned Browser ============= Overview -------- .. image:: ../../images/paned.png :scale: 50% :align: right The Paned Browser offers a convenient way to quickly drill down into a large music collection, by narrowing selections in several stages. Some users may find this reminiscent of `RhythmBox <https://wiki.gnome.org/Apps/Rhythmbox>`_ or, to some extent, `iTunes <https://www.apple.com/uk/itunes/>`_. In Quod Libet though, you can have as many panes as you want, grouped by any tags you want, for example the popular ''genre/artist/album'' and ''artist/album'', or ''artist/album/part'', or ''artist/album/artist'' in case you have a lot of multi-artist albums. The songlist is presented at the bottom, and the panes, which run from left to right, are above. Clicking on an item (or items) in a pane will restrict it to just songs matching those (e.g. those artists, or dates, genres etc). This will update the counts and choices on the next pane, and the filtered results will be updated automatically in the song list. Pane Configuration ------------------ To change the panes, click the *Preferences* button all the way to the right of the search bar. There you can choose between some popular setups or set up custom ones using the add and remove buttons. You can change the order of the panes by dragging them to the desired place. Unlike elsewhere, multiple values per tag for a song are split into multiple entries. Tied tags also result in multiple entries. Tag patterns take multiple values from tags and from tied tags and produce multiple entries. Entries are sorted using sort values for tags. For tags with multiple values, each value is paired with the corresponding value from the sort tag. Quod Libet tries to do something reasonable when a value (e.g., "The Beatles") sometimes has a sort value (e.g., "Beatles, The") and sometimes does not or has a different sort values (e.g., "Beatles"). Examples -------- +-------------------+-----------------------+ | Pattern | Result | +===================+=======================+ | ``~performers`` | Julio Inglesias | +-------------------+-----------------------+ | | Frank Sinatra | +-------------------+-----------------------+ +--------------------------------------+--------------------------------+ | Pattern | Result | +======================================+================================+ | ``<~year|<~year>. <title>|<title>>`` | 1993\. Summer Wind | +--------------------------------------+--------------------------------+ +--------------------------------------+--------------------------------+ | Pattern | Result | +======================================+================================+ | ``~title~~performers`` | Julio Inglesias | +--------------------------------------+--------------------------------+ | | Frank Sinatra | +--------------------------------------+--------------------------------+ | | Summer Wind | +--------------------------------------+--------------------------------+ +---------------------------------------------------+------------------------+ | Pattern | Result | +===================================================+========================+ | ``<~year|<~performers> - <~year>|<~performers>>`` | Julio Inglesias - 1993 | +---------------------------------------------------+------------------------+ | | Frank Sinatra - 1993 | +---------------------------------------------------+------------------------+ Using Markup ^^^^^^^^^^^^ Also it's possible to change text emphasis using the `Pango markup language <https://developer.gnome.org/pango/unstable/PangoMarkupFormat.html>`_ =========================================================== ================================= Pattern Result =========================================================== ================================= ``<~year|\<b\>\<i\><~year>\</i\>\</b\> - <album>|<album>>`` **2011** - This is an album title =========================================================== ================================= Aggregation ^^^^^^^^^^^ On the right side of each pane you can see the number of songs of each entry. This can be configured as well by adding a pattern/tag separated by ``:`` (In case you want to use ``:`` in your pattern it has to be escaped using ``\:``) ============================ =========================== Pattern Result ============================ =========================== ``~~year~album:(<~rating>)`` 2011 - Album title (♪♪) ============================ =========================== �����������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/playlists.rst�����������������������������������������������������0000664�0001750�0001750�00000012672�14231604332�020317� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Playlists: Playlists ========= The Playlist Browser -------------------- .. image:: ../images/playlist-browser.png :scale: 50% :align: right Choose the *Playlists* browser by clicking on *View* -> *Playlists*. The usage is fairly simple - a list of songs in the right pane, and a list of playlists (with summary information) in the right. Any file in your library can belong to any playlist or many playlists - it's up to you how you want to organize them... Playlist store -------------- Playlists are stored as files on disk, typically under ``~/.quodlibet/playlists``, depending on your home / XDG directories. Format ~~~~~~ :new: Playlists are now stored in `XSPF format <http://xspf.org/>`_. The names are partially URL-encoded - that is, they can and should be URL-unencoded, but efforts are taken to make them human-friendly names where reasonable. As before, these playlists are editable but it's recommended to leave them to Quod Libet. It's good to back them up (``git`` etc works well here too). Creating playlists ------------------ There are several ways to create playlists in Quod Libet. Choose whichever suits you best: * To create a blank playlist, select the Playlist Browser and click *New*. * To create a new playlist with songs in it, select the songs in any other browser, right click, and select *Add to Playlist* → *New Playlist*. * To add songs to an existing playlist, either use *Add to Playlist* in the right click menu, or drag them to the playlist name on the sidebar. * To import playlists from `pls` or `m3u` /` m3u8` files, use the *Import* button. In addition to creating the playlist, any files in it will be added to your library. Context menu support -------------------- The "songs menu", a context menu presented when you right-click on a song (or songs), has in-built support for playlists. Just right-click on a song, and select *Add to Playlist*. This is a convenient way of adding a song to a playlist from almost *any* browser, and even better, seeing *every* playlist that song features in (they will be ticked). Library Changes --------------- The Playlists Browser, like many other browsers, listens to changes in your library. This means that any changes in tags will be reflected in the song list for each. Playlist entries are indexed by file path though, so *any changes of name or directory will remove a song from its playlists* (There are, however, discussions to changes this: Issue 708). Please be careful with mounted media (e.g. USB / network disks) as when the library is rescanned, these files not existing is taken as deletion, which will provoke a removal from their playlists. Please keep backups if playlists are important. Drag and Drop ------------- Quod Libet has extensive drag-and-drop support in the playlists browser. You can drag and drop songs from other browsers (eg the search browser) onto an existing playlist, or songs from one playlist to another. When you drop a song into the left-hand pane in the playlist browser, but not onto a playlist, a new playlist is created, named after that song. Importing and Exporting Playlists --------------------------------- As outlined above, you can import playlists from `pls` or `m3u`/`m3u8` files using the _Import_ button. In addition to creating the playlist, any files in it will be added to your library. You can also drag and drop an `m3u` playlist file from an external browser onto the left-hand pane in the playlist browser to import a playlist. To export playlists to `m3u`, you first need to install the Export playlist export plugin. Once installed, you can export playlists to M3U or PLS format by right clicking on the playlist, then *Plugins* -> *Export Playlist*. Dynamic Playlists ----------------- You may wonder whether Quod Libet doesn't have so-called "dynamic" or "smart" playlists as you may know them from other music players, that is, playlists that automatically update themselves for example to always contain all songs from a certain artist that you have in your library. In fact, QL does have this functionality, but it is implemented via the search functionality and hence located in the search browser, not in the playlists browser. Creating a dynamic playlist: * Go to the search browser, (either using *View* or *Music* -> *Browse Library*). * Enter what you want to search for (see :ref:`the section about searching<Searching>` for QL's powerful search options), for example `artist = radiohead`. Optionally, click on search to test your search and modify it until you're happy. * Click the arrow next to the search box on the right, to open the drop-down menu. You will see a history of some recent searches (if you have searched before), followed by *Edit saved values...* ." Clicking on this, you will be presented with a dialogue box. The *Value* field has been pre-filled with your current search. If you wish, enter a name in the *Name* field (if you leave it blank, QL will name it for you). Click *Add*. You have now created a dynamic playlist, via a saved search. To play, just go to the search browser, click on the arrow to the right of the field and select your saved search from the list. If you want to create several of such saved searches at once, you may find it more convenient to edit a text file instead of clicking through the GUI. To do so, you can :ref:`edit the configuration text file <ConfigFiles>` ``~/.quodlibet/lists/queries.saved``. ����������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1664110870.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/podcasts.rst������������������������������������������������������0000644�0001750�0001750�00000000743�14314050426�020106� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Podcasts: Podcasts Browser ---------------- The *Podcasts* browser allows you to subscribe to podcasts (syndicated feeds with attached audio files). Feeds are automatically checked for updates every two hours, and emboldened if new entries are found. You can right-click on a file in an audio feed, and select *Download file*, to download it to your hard drive. Note the browser is for the remote file, so changes to the downloaded file will not be reflected in the browser. �����������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/search.rst��������������������������������������������������������0000664�0001750�0001750�00000001235�14035600052�017526� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Search Browser -------------- The *Track List* browser (which is the default one) lets you enter search terms and play all matching songs. It also supports :ref:`complex searches <Searching>`. Finally, it lets you limit the number of results; right-click on the text bar and select *Limit Results*. To display your whole library, don't enter any search terms. The browser remembers the last eight searches you made automatically. If you want to save more, you can right-click on the text entry and select *Edit Saved Values...*, which will let you name and save searches permanently. Saved searches will appear above automatically remembered ones in the menu. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/browse/soundcloud.rst����������������������������������������������������0000664�0001750�0001750�00000007027�14035600052�020445� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Soundcloud Browser ================== *From v3.7* Overview -------- This browser lets you interact with `Soundcloud <https://soundcloud.com>`_ and play tracks from the millions on offer. Where possible it aims to keep the look and feel as familiar and integrated to the Quod Libet experience as possible. .. image:: ../../images/soundcloud-browser-2017-08.png :scale: 50% :align: right Connecting your account ----------------------- If you have a Soundcloud account, you can also: * access your favorites * rate (like / unlike) songs. * list your own tracks (QL 3.10+) To do so, click the Soundcloud connect button at the bottom right. This will then take you to. If your operating system is configured to process ``quodlibet://`` URLs with Quod Libet (see `the instructions <https://quodlibet.github.io/callbacks/soundcloud.html?code=CODE_GOES_HERE>`_ given to you there) then this process will happen automatically. If not, you can enter the code manually using the same button. If not, you can copy the code from the web page that appears and click the QL button again to enter it. Once you are logged, in you can log out by clicking the same button again, now a disconnect button (seen in the screenshot). Features -------- Higher quality streams ^^^^^^^^^^^^^^^^^^^^^^ The Soundcloud browser will use the download URL, where available, for the highest quality stream. Note this may require that you are logged in, and is usually *not* available. Support for Quod Libet queries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One of the more interesting features of the soundcloud browser is that it can *translate* simpler queries in standard QL syntax to something that can work across the web to a library that isn't yours. Obviously, there are many limitations to this approach both conceptually and due to its implementation, but nonetheless queries like ``&(#(length>300), title=dubstep)`` get (roughly) what you might expect. Favorites ^^^^^^^^^ These are supported as ``~rating`` (see below), and unrating a track will unfavorite it in Soundcloud, if you are logged in. Tags ^^^^ Supported tags * ``artist``, ``genre``, and ``title`` translate as you might imagine * ``website`` translates to Soundcloud's current URL for that track * ``genre`` holds the genres (plural) tagged in Soundcloud (these are rarely useful but YMMV) * ``date`` is the *creation* date in Soundcloud * ``~#rating`` is translated to 0.0 (not a Soundcloud favourite) or 1.0 (a Soundcloud favourite) * ``~#bitrate`` is the highest bitrate available when playing the track (normally 128) * ``~comments`` translates to the track details in Soundcloud. * ``bpm`` is the Soundcloud BPM if provided. New tags * ``~#favoritings_count`` and ``~#likes_count`` etc represent how often these tracks have been favorited / liked (note that there currently seem to be inconsistencies within Soundcloud itself as to how these are populated) * ``soundcloud_track_id`` is the Soundcloud ID for the track. * ``soundcloud_user_id`` is the Soundcloud ID for the user. * ``artwork_url`` is the (remote) image URL for the track artwork on Soundcloud. This works well with the corresponding ``Artwork URL Cover Source`` plugin. Comments ^^^^^^^^ Comments in Soundcloud have been integrated to QL as read-only bookmarks, as they are also time-specific text to do with a particular song. Unlike bookmarks they have a lot more metadata (notably the user), so this is rendered as text. To see them, access as you normally would bookmarks (e.g. view info, right-click the time widget or edit the bookmarks). ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9542687 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016030� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/Makefile��������������������������������������������������������0000664�0001750�0001750�00000000176�14035600052�017472� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MANDIR=../../../data all: $(MANDIR)/exfalso.1 $(MANDIR)/quodlibet.1 $(MANDIR)/operon.1 $(MANDIR)/%.1:%.rst rst2man $< > $@ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/exfalso.rst�����������������������������������������������������0000664�0001750�0001750�00000003545�14231604332�020233� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������========= exfalso ========= ---------------- audio tag editor ---------------- :Manual section: 1 SYNOPSIS ======== **exfalso** [ *directory* ] DESCRIPTION =========== Ex Falso displays and edits audio metadata tags. Supported formats include MP3, Ogg Vorbis, FLAC, Musepack (MPC), WavPack, and MOD/XM/IT. This manual page is only a short reference for Ex Falso. Complete documentation is available at https://quodlibet.readthedocs.io/en/latest/guide/. OPTIONS ======= Ex Falso may be given a directory to open on the command line. TIED TAGS ========= Many places in Ex Falso allow you to use "tied tags". Tied tags are two tag names joined together with a "~" like "title~version" or "album~part". Tied tags result in "nice" displays even when one of the tags is missing; for example, "title~version" will result in Title - Version when a version tag is present, but only Title when one isn't. You can tie any number of tags together. RENAMING FILES ============== Ex Falso allows you to rename files based on their tags. In some cases you may wish to alter the filename depending on whether some tags are present or missing, in addition to their values. A common pattern might be ``<tracknumber>. <title~version>`` You can use a '|' to only insert text when a tag is present: ``<tracknumber|<tracknumber>. ><title~version>`` You can also specify literal text to use if the tag is missing by adding another '|': ``<album|<album>|No Album> - <title>`` See https://quodlibet.readthedocs.io/en/latest/guide/renaming_files.html. BUGS ==== See https://github.com/quodlibet/quodlibet/issues for a list of all currently open bugs and feature requests. AUTHORS ======= Joe Wreschnig and Michael Urman are the primary authors of Ex Falso. SEE ALSO ======== | https://quodlibet.readthedocs.io/en/latest/guide/, | https://quodlibet.readthedocs.io/en/latest/guide/faq.html �����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/index.rst�������������������������������������������������������0000664�0001750�0001750�00000000145�14035600052�017667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Command Manuals =============== .. toctree:: :titlesonly: quodlibet exfalso operon ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/operon.rst������������������������������������������������������0000664�0001750�0001750�00000015165�14035600052�020072� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������======== operon ======== ------------------------- command line music tagger ------------------------- :Manual section: 1 SYNOPSIS ======== | **operon** [--version] [--help] [-v | --verbose] <*command*> [<*argument*>...] | **operon help** <*command*> OPTIONS ======= -h, --help Display help and exit --version Print the program version -v, --verbose Verbose mode COMMAND-OVERVIEW ================ Edit Tags --------- | *add* Add a tag value | *remove* Remove a tag value | *set* Set a tag and remove existing values | *clear* Remove tags | *copy* Copy tags from one file to another | *edit* Edit tags in a text editor | *fill* Fill tags based on the file path Show file metadata ------------------ | *list* List tags | *info* List file information | *print* Print tags based on the given pattern Edit Embedded Images -------------------- | *image-extract* Extract embedded images | *image-set* Set embedded image | *image-clear* Remove embedded images Miscellaneous ------------- | *tags* List all common tags | *help* Display help information EDIT TAGS ========= add --- Add a new tag ``<tag>`` with the value ``<value>`` to all files. operon add [-h] <tag> <value> <file>... -h, --help Display help and exit Example: operon add artist 'The Beatles' song1.ogg song2.ogg remove ------ Remove all values from the tag ``<tag>`` that match either ``<value>`` or the regular expression ``<pattern>`` from all files. operon remove [-h] [--dry-run] <tag> (-e <pattern> | <value>) <file>... -h, --help Display help and exit --dry-run Print the results without changing any files -e, --regexp <regexp> Remove all tag values that match the given regular expression Example: operon remove artist 'The Beatles' song.ogg set --- Replace all values of the tag ``<tag>`` by ``<value>`` in all files. operon set [-h] [--dry-run] <tag> <value> <file>... -h, --help Display help and exit --dry-run Print the results without changing any files Example: operon set artist 'The Beatles' song.ogg clear ----- Remove all tags that match ``<tag>`` or the regular expression ``<pattern>`` from all files. If `--all` is specified, all known tags will be removed. operon clear [-h] [--dry-run] (-a | -e <pattern> | <tag>) <file>... -h, --help Display help and exit --dry-run Print the results without changing any files -a, --all Remove all tags -e, --regexp <regexp> Remove all tags that match the given regular expression Example: operon clear -a song.ogg operon clear -e 'musicbrainz\_.*' song.ogg operon clear date song.ogg copy ---- Copy all tags from the file *<source>* to *<dest>*. All tags in ``<dest>`` will be preserved. In case the destination format doesn't support setting a tag from source, no tags will be copied. To ignore tags that aren't supported by the destination format pass *--ignore-errors*. operon copy [-h] [--dry-run] [--ignore-errors] <source> <dest> -h, --help Display help and exit --dry-run Print the results without changing any files --ignore-errors Skip tags which the target file does not support Example: operon copy song.flac song.ogg edit ---- Shows all tags in a text editor and will apply any changes made to the text to the tags. *operon* will use the editor specified in the VISUAL or EDITOR environment variables and if those are not set fall back to 'nano'. operon edit [-h] [--dry-run] <file> -h, --help Display help and exit --dry-run Print the results without changing any files Example: VISUAL=vi operon edit song.flac fill ---- Fill tags based one file paths and a given pattern. operon fill [-h] [--dry-run] <pattern> <file>... -h, --help show this help message and exit --dry-run show changes, don't apply them Example: operon fill --dry-run "<tracknumber>. <title>" "01. Was Ist Ist.flac" SHOW FILE METADATA ================== list ---- Lists all tags, values and a description of each tag in a table. operon list [-h] [-a] [-t] [-c <c1>,<c2>...] <file> -h, --help Display help and exit -a, --all Also list programmatic tags -t, --terse Output is terse and suitable for script processing -c, --columns <name>,... Defines which columns should be printed and in which order Example: operon list -a song.flac operon list -t -c tag,value song.ogg info ---- Lists non-tag metadata like length, size and format. operon info [-h] [-t] [-c <c1>,<c2>...] <file> -h, --help Display help and exit -t, --terse Output is terse and suitable for script processing -c, --columns <name>,... Defines which columns should be printed and in which order Example: operon info a.ogg print ----- Prints information per file built from tag values. The pattern can be customized by passing a pattern string (See ``quodlibet``\(1) for the pattern format) operon print [-h] [-p <pattern>] <file>... -h, --help Display help and exit -p, --pattern <pattern> Use a custom pattern Example: operon print -p "<album> - <artist>" a.ogg EDIT EMBEDDED IMAGES ==================== image-extract ------------- Extract all embedded images to the current working directory or the specified destination directory. operon image-extract [-h] [--dry-run] [--primary] [-d <destination>] <file>... -h, --help Display help and exit --dry-run Print the found images and resulting file paths but don't save them --primary Only extract the primary images for each file -d, --destination <destination> Save all images to the specified destination Example: operon image-extract asong.mp3 anotherone.ogg image-set --------- Set the provided image as primary embedded image and remove all other embedded images. operon image-set <image-file> <file>... -h, --help Display help and exit Example: operon image-set cover.jpg song.mp3 image-clear ----------- Remove all embedded images from all specified files. operon image-clear <file>... -h, --help Display help and exit Example: operon image-clear song.mp3 MISCELLANEOUS ============= tags ---- List all common tags operon tags [-h] [-a] [-t] [-c <c1>,<c2>...] -h, --help Display help and exit -a, --all Also list programmatic tags -t, --terse Output is terse and suitable for script processing -c, --columns <name>,... Defines which columns should be printed and in which order Example: operon tags -a operon tags -t -c tag help ---- operon help [<command>] Example: operon help list SEE ALSO ======== | ``regex``\(7) | ``exfalso``\(1) | ``quodlibet``\(1) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/commands/quodlibet.rst���������������������������������������������������0000644�0001750�0001750�00000016704�14327505043�020566� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=========== quodlibet =========== -------------------------------- audio library manager and player -------------------------------- :Manual section: 1 SYNOPSIS ======== | **quodlibet** [ **--print-playing** | *control* ] | **exfalso** [ *directory* ] DESCRIPTION =========== Quod Libet is a music management program. It provides several different ways to view your audio library, as well as support for Internet radio and podcasts. It has extremely flexible metadata tag editing and searching capabilities. This manual page is only a short reference for Quod Libet. Complete documentation is available at https://quodlibet.readthedocs.io/en/latest/guide/index.html. OPTIONS ======= --add-location=<location> Add a file or directory to the library --debug Print debugging information --enqueue=<filename|query> Enqueue a filename or query results --enqueue-files=<filename[,filename..]> Enqueue comma-separated files --filter <tag=value> Filter on a tag value --focus Focus the running player --force-previous Jump to previous song --help Display brief usage information --hide-window Hide main window --list-browsers List available browsers --next Jump to next song --no-plugins Start without plugins --open-browser=BrowserName Open a new browser --pause Pause playback --play Start playback --play-file=filename Play a file --play-pause Toggle play/pause mode --previous Jump to previous song if near the beginning, otherwise restart --print-playing Print out information about the currently playing song. You may provide in a string like the kind described in the RENAMING FILES section below, plus special tags ~#elapsed or ~elapsed. --print-playlist Print the current playlist --print-query=<query> Print filenames of results of query --print-query-text Print the active text query --print-queue Print the contents of the queue --query=search-string Search your audio library --queue=<on|off|t> Show or hide the queue --quit Exit Quod Libet --random=tag Filter on a random value --rating=<[+|-]0.0..1.0> Set rating of playing song --rating-down Decrease rating of playing song by one star --rating-up Increase rating of playing song by one star --refresh Refresh and rescan library --repeat=<off|on|t> Turn repeat off, on, or toggle --repeat-type=<current|all|one|off> Repeat the currently playing song, the current list, stop after one song, or turn repeat off --run Start Quod Libet if it isn't running --seek=<[+|-][HH:]MM:SS> Seek within the playing song --set-browser=BrowserName Set the current browser --show-window Show main window --shuffle=<off|on|t> Turn shuffle off, on, or toggle --shuffle-type=<random|weighted|off> Set the shuffle type to be random, to prefer higher rated songs, or turn shuffle off --start-hidden Don't show any windows on start --start-playing Begin playing immediately --status Print playing status --stop Stop playback --stop-after=<0|1|t> Stop after the playing song --toggle-window Toggle main window visibility --unfilter Remove active browser filters --unqueue=<filename|query> Unqueue a file or query --version Display version and copyright --volume=<[+|-]0..100> Set the volume --volume-down Turn down the volume --volume-up Turn up the volume --with-pattern=<pattern> Set the output format of the --print-playing, --print-playlist, --print-query, and --print-queue commands. You may provide in a tag-pattern string like the kind described in the RENAMING FILES section below. ALBUM COVERS ============ Album covers should be put in the same directory as the songs they apply to, and have "folder", "front", or "cover" in their filenames. If you want to store multiple albums in the same directory but keep distinct cover images, the name of the appropriate image file must contain the labelid tag value, e.g. COCX-32760 cover.jpg. TIED TAGS ========= Many places in Quod Libet allow you to use "tied tags". Tied tags are two tag names joined together with a "~" like "title~version" or "album~part". Tied tags result in "nice" displays even when one of the tags is missing; for example, "title~version" will result in Title - Version when a version tag is present, but only Title when one isn't. You can tie any number of tags together. SEARCH SYNTAX ============= All of Quod Libet's search boxes support advanced searches of the following forms: \ | tag = value | tag = !value | tag = "value" | tag = /value/ | tag = &(value1, value2) | tag = \|(value1, value2) | !tag = value | \|(tag1 = value1, tag2 = value2) | &(tag1 = value1, tag2 = value2) | #(numerictag < value) | #(numerictag = value) | #(numerictag > value) \ The 'c' postfix on strings or regular expressions makes the search case-sensitive. Numeric values may be given as integers, floating-point numbers, MM:SS format, or simple English, e.g. "3 days", "2 hours". See https://quodlibet.readthedocs.io/en/latest/guide/searching.html. All internal tags begin with a ~ character. Non-numeric internal tags are ~base‐ name, ~dirname, ~filename, ~format, ~length, ~people, and ~rating. Numeric internal tags are ~#added, ~#bitrate, ~#disc, ~#lastplayed, ~#laststarted, ~#length, ~#mtime, ~#playcount, ~#skipcount, and ~#track. See https://quodlibet.readthedocs.io/en/latest/guide/tags/internal_tags.html. RENAMING FILES ============== Quod Libet allows you to rename files based on their tags. In some cases you may wish to alter the filename depending on whether some tags are present or missing, in addition to their values. A common pattern might be ``<tracknumber>. <title~version>`` You can use a '|' to only insert text when a tag is present: ``<tracknumber|<tracknumber>. ><title~version>`` You can also specify literal text to use if the tag is missing by adding another '|': ``<album|<album>|No Album> - <title>`` See https://quodlibet.readthedocs.io/en/latest/guide/renaming_files.html. AUDIO BACKENDS ============== Quod Libet uses GStreamer for audio playback. It tries to read your GConf GStreamer configuration, but if that fails it falls back to osssink. You can change the pipeline option in ~/.quodlibet/config to use a different sink, or pass options to the sink. For example, you might use esdsink or alsasink device=hw:1. See https://quodlibet.readthedocs.io/en/latest/guide/playback/backends.html. FILES ===== ~/.quodlibet/songs A pickled Python dict of cached metadata. Deleting this file will remove all songs from your library. ~/.quodlibet/config Quod Libet's configuration file. This file is overwritten when Quod Libet exits. ~/.quodlibet/current A "key=value" file containing information about the currently playing song. ~/.quodlibet/control A FIFO connected to the most-recently-started instance of the program. --next, --previous, etc., use this to control the player. ~/.quodlibet/plugins/ Put plugins here. ~/.quodlibet/browsers/ Put custom library browsers here. See https://quodlibet.readthedocs.io/en/latest/guide/interacting.html. BUGS ==== See https://github.com/quodlibet/quodlibet/issues for a list of all currently open bugs and feature requests. AUTHORS ======= Joe Wreschnig and Michael Urman are the primary authors of Quod Libet. SEE ALSO ======== | https://quodlibet.readthedocs.io/en/latest/guide/, | https://quodlibet.readthedocs.io/en/latest/guide/faq.html, | ``regex``\(7), ``gst-launch``\(1) ������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/config_files.rst���������������������������������������������������������0000664�0001750�0001750�00000004166�14035600052�017415� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _ConfigFiles: Configuration Files =================== QL stores some of its configuration as plain text files, and in some cases it may be convenient to edit these files directly, or to synchronize them across different computers/ home directories. Like many Linux applications, QL stores user configuration in a hidden directory, in this case ``~/.quodlibet``. (Note that this may not always be the case, see :ref:`the FAQ <MetadataLocation>` for details). Feel free to explore; but maybe make a backup of the directory first. Saved values for search, tagging and renaming patterns ------------------------------------------------------ For :ref:`searching your library <Searching>`, :ref:`editing tags from a filename pattern <EditingTags>`, and :ref:`renaming files based on tags <RenamingFiles>`, you can save the (search or pattern) values you enter for later use. See the relevant section for how to do it using the GUI. The patterns you create using "saved values" are in fact stored in simple text files: * ``~/.quodlibet/lists/queries.saved``: Search patterns * ``~/.quodlibet/lists/tagpatterns.saved``: Patterns to tag files based on filename * ``~/.quodlibet/lists/renamepatterns.saved``: Patterns to rename files based on tags You'll see that the format is very easy: Each saved pattern consists of two lines, the first line contains the QL pattern, the second line its name. The name may be identical to the pattern. The next saved "pattern -- name" pair follows immediately on the next two lines. Here's an example of what ``~/.quodlibet/lists/queries.saved`` might look like:: artist = schubert All by Schubert artist = radiohead All by Radiohead &(genre = classical, #(lastplayed > 3 days)) &(genre = classical, #(lastplayed > 3 days)) ~format = ogg All ogg files Or an example of a ``~/.quodlibet/lists/renamepatterns.saved``:: ~/music/<artist>/<album>/<tracknumber|<tracknumber>. ><title~version> Music from an album ~/music/misc/<artist> - <title> Stray song Just edit these files or synchronize them across computers or home directories (for different users) as needed. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/editing_tags.rst���������������������������������������������������������0000644�0001750�0001750�00000013206�14327505043�017430� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _EditingTags: Editing Tags ============ .. image:: ../images/tagedit.png :scale: 45% :align: right You can edit a song's tags by right clicking on it and selecting *Edit Tags*. In addition to manually entering the tags, if the song's filename contains information about all or some of the tags, you can use the *Edit tags from path* tab to populate these tags automatically. Please see :ref:`editing tags from path <tags-from-path>` below describing the process for several songs (the process is the same). Editing tags in-place --------------------- As of QL 4.6, for plain, textual tags (not internal, and not *tag expressions*) you can edit these in-place in the songlist, by navigating to the column within the song's row, and pressing F2. Changes are immediate. Editing tags for several songs at once -------------------------------------- To edit tags for several songs at once, select those songs (using Ctrl or Shift), then right click and "Edit Tags". Note that in the tag-editing window that opens, you have several tabs available. The default *Edit tags* tab will apply the same tags to all marked songs, so it only makes sense for tags that are common to all songs, e.g. album or genre. However, the tabs *Tags from Path* and *Track Numbers* let you edit tags that differ across songs: .. _tags-from-path: Editing tags from path ^^^^^^^^^^^^^^^^^^^^^^ The tab *Tags from Path* lets you batch edit tags that differ across songs, such as title, by using the filename as input. Note that you can customize the pattern that the tag editor uses to extract the tags from the filename: just imitate the pattern you see for your files, putting the relevant tag name in angular brackets. Example: * Your file names have a pattern like this: ``01 - The Beatles - Yellow Submarine.ogg`` * Edit the pattern to show: ``<tracknumber> - <artist> - <title>`` * Note that you can omit the file extension in your pattern. * Click on *Preview* to see how your pattern would be interpreted for each song. The preview is shown to the right of the current value; you may have to scroll right to see it. You can even include information from the entire path in this pattern matching: * You have files like this ``~/home/username/music/favourites/the_beatles/yellow_submarine/01 - Yellow Submarine.ogg`` * Use pattern: ``<artist>/<album>/<tracknumber> - <title>`` * In that case, you probably want to check the boxes for *Replace underscores with spaces* and *Title-case tags*. * Note that QL automatically digs as far upwards in the folder hierarchy as it needs to given the pattern you put in, so you don't need to enter any (potentially complex) folder structure that is above the needed info. You can see recent patterns you used by clicking on the drop down arrow to the right of the pattern input field. Additionally, clicking on *Edit saved values* in the drop-down that opens will let you save patterns and optionally name them. Use this for patterns that you apply frequently. If you leave the *Name* field blank for your pattern, the name will be identical to the pattern. Batch edit track numbers ^^^^^^^^^^^^^^^^^^^^^^^^ The *Track Numbers* tab in the tag editing window lets you batch edit track numbers ascending across the files. If your files are in the correct order, you simply check that you like the *Start from* and *Total tracks* values. If you put in any value greater than one for *Total tracks*, QL will use a tracknumber pattern `tracknumber/totaltracks`, e.g. ``2/12`` for *Total tracks* = ``12``. If you only want a single number for the track number, set *Total tracks* to zero. If your files are not in the correct order, for example because they are sorted alphabetically, you can drag and drop them into the desired order in the *File* field inside the *Track numbers* tab of the tag editing window before (optionally) clicking preview and then save. Rename Files Based on Tags -------------------------- QL also lets you rename the files of songs based on tags, either for one song or for several songs. Edit patterns the same way you would for *Edit tags from path* (see above). This feature even lets you move them to a different directory; for more info see the :ref:`renaming files guide <RenamingFiles>`. Splitting Tags -------------- If a tag contains a value that can be regarded as multiple tag values, it is often possible to split the tag. This can be done by right-clicking on the tag and then selecting the appropriate split in the ``Split Tag`` menu. There are in general two types of tag splitting possible: splitting on a single character and *subtag* splitting (extracting values in enclosures). The separating characters for both can be configured in the *Tags* tab in the preferences. Note that the "Split on" values in the configure dialog are space-separated. Splitting on a single character - like ``,`` or ``&`` - will split a tag into multiple tags of the same type, but with different values. An example of this can be an artist tag with the value ``Foo, Bar``, that can be split into two separate tags *artist* = ``Foo`` and *artist* = ``Bar``. With *subtag* splitting, the end of the tag value must contain a value enclosed in some pair of characters - like ``()`` or ``[]``. Depending on the type of tag, the enclosed value can then be extracted and put in a new tag. An example of this can be an album tag with the value ``Album (CD 1)``, which can be split into *album* = ``Album`` and *discnumber* = ``1``. The enclosure can also contain multiple values separated by a single-character separator as explained above, like *artist* = ``Foo (Bar, Baz)``, which can be split into *artist* = ``Foo``, *performer* = ``Bar`` and *performer* = ``Baz``. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/faq.rst������������������������������������������������������������������0000644�0001750�0001750�00000023407�14343330263�015540� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Frequently Asked Questions ========================== Why don't all my songs appear in the song list when searching for them? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do you have a global filter in use? Check the *Browsers* tab in *Preferences*. .. _MetadataLocation: Where does Quod Libet store all its metadata? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The short answer was originally: in ``~/.quodlibet/`` For newer versions of QL it's more complex: * On all platforms, if the ``QUODLIBET_USERDIR`` environment variable is set, this will be used * On Windows, it will be in your user's ``AppData`` folder under ``Quod Libet`` (except portable builds) * On OS X, it will be in ``~/.quodlibet/`` * On Linux / Unix systems: * if the ``XDG_CONFIG_HOME`` environment variable is set, ``XDG_CONFIG_HOME/quodlibet/`` will be used * else if folder ``~/.config/`` exists, ``~/.config/quodlibet/`` will be used * else ``~/.quodlibet/`` will be used still Under there you'll find all sorts of things, separate from the audio file tags themselves, e.g. * ``songs`` - the pickled songs database. * ``config`` - the main Quod Libet configuration file - edit with care * ``playlists/`` - a directory for all playlists * ``lists/`` - a directory for saved searches and so on * ``stations`` / ``stations_all`` - the Internet radio stations lists Whenever I type a space, Quod Libet pauses ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Users of some keyboard layouts, including the popular French Alternative, may hit this bug. In these layouts, the spacebar sends a non-breaking space character, which GTK+ interprets as ``<control>space``. This is a `known bug in GTK <https://bugzilla.gnome.org/show_bug.cgi?id=541466>`__. You can work around it by changing your keyboard layout to send a regular space. How do I add custom / unusual tags to the columns in the song list? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Refer to :ref:`editing tags<EditingTags>` if you need to add any custom tags. 2. Right-click the song list header bar and select *Customize Headers* from the context menu (or click *Preferences* from the main menu and select *Song List*) 3. In the *Others* field, click *Edit*, then *Add*, and enter the custom tag name, remembering that they are case-sensitive. Lesser-known (but useful) tags here might include ``~#playcount``, ``~#skipcount``, ``~#bitrate`` or ``~playlists``. How do I use a different soundcard with Quod Libet? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ See the chapter on configuring the AudioBackends in the user's guide. Why does Quod Libet sort my songs out of order? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Music metadata, like music, comes in many languages, and sorting multi-language text is hard to do. It depends on your language as well as the text being sorted, and often is still not well-defined. `Unicode Technical Standard #10 <http://www.unicode.org/reports/tr10/>`_ outlines an algorithm to sort multi-language text, but even then it needs ordinal data for each character for each language. We don't know of any Python implementations of it, and any implementation we use would have to be fast since we compare thousands of strings when sorting. I have two albums with the same name which are merged in the Album List ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tag them with different ``albumartist`` tags. You can also use ``musicbrainz_albumid`` tags, which several other taggers and our "MusicBrainz Lookup" plugin can write. I have two discs of the same album, and they don't get merged in the Album List ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make sure they have the same name (i.e. without "(disc x)" on the end). If they are still not merged, they have different `albumartist`, `labelid` or ``musicbrainz_albumid`` tags. If they have different label ID tags, delete the incorrect one. If they have different MusicBrainz album ID tags, add a ``labelid`` tag that is the same for both albums. Where does Quod Libet store ratings and playcounts? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default these are in the internal database - and remember this is indexed by filename, so renames will lose data. For this and other reasons, some users prefer to save save them *in the tags themselves* (under an email address), using the most appropriate tag for that format (e.g. `ID3's popm tag <http://id3.org/id3v2.3.0#Popularimeter>`__ for ID3). See the configuration under *Preferences* -> *Tags* -> *Save ratings and play _counts in tags*. Note that some caching is used, so changes aren't written all the time. Try the *Update Tags In Files* plugins to control this explicitly. Can I show more than 0 to 4 notes when rating songs? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Close Quod Libet; in ``~/.quodlibet/config`` find the ``ratings = 4`` line. Change it to ``ratings = however many ratings you want``. It's best if the value divides 100 evenly; multiples of 2 and 5 are good. You will need to use the ratings right-click menu to set ratings above 4. How can I hide incomplete albums from the Album View? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One way is to enter ``#(tracks > 5)`` into the search box above the album list - this will only show albums with greater than 5 tracks. How can I list my tracks based on their ratings? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Right-click somewhere on the headers bar (below the search bar), select "Track Headers" from the menu and add "Ratings". Now if you click "Ratings" on the headers bar your tracks will be sorted based on their ratings. How is album art handled? ~~~~~~~~~~~~~~~~~~~~~~~~~ There are many ways users like to keep their album art, and Quod Libet supports graphics (primarily `.jpg` but `.gif` and `.png` also) in these ways: * Files in the *album* directory with fixed names eg ``folder.jpg``, ``cover.jpg``, ``front.png`` * A file containing the ``labelid`` (eg *COCX-32760 cover.jpg*) * Files of certain other names linked to a given album in a shared directory: ``<musicbrainz_albumid>.ext`` or ``<artist> - <title>.ext`` * Sub-folders of certain names (``covers/`` or ``<labelid>/``) with compatible images in them. * Embedded cover art in the file itself (incomplete support in some formats). There are fuzzy-matching algorithms to try to determine the most specific match if multiple of the above exist. If you're adding new album art, the *Album Art downloader* plugin allows you to do so easily and is compatible with the above. Why do songs disappear from my playlists? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is due to the way the library works, and that playlists entries are based on filename. One of several things might have happened, before a re-scan of the library (on start-up or otherwise) * The songs have been renamed, moved, or their directory moved. Note this includes using *Rename Files* from the tag editor. * A removable (mounted) media device - USB disk, network share, internet folder or whatever is/was no longer available (at the time of refresh). Note if you're using the Auto Library Update this will happen immediately (There are ideas to improve this: Issue 961). Can QL read my ID3 tags encoded in euc-kr / cp1251 / windows-1252 etc? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can define a custom list of encodings to check. UTF-8 is always tried first, and Latin-1 is always tried last. To make your own list, close QL, open up ``~/.quodlibet/config``, and find the ``id3encoding`` option. You can enter any valid encodings here, separated by spaces, and they will be tried in order. If you have files already imported into your library with incorrect tags, you'll need to reload them. Quod Libet saves ID3 tags in UTF-8 or UTF-16. What does the name mean? ~~~~~~~~~~~~~~~~~~~~~~~~ *Quodlibet* or *Quod libet* is Latin for "whatever you please" or "whatever you want", which is the kind of attitude we want to convey with QL: you control how you fiddle with your music. A *quodlibet* is also a type of musical composition, an improvisation by several players or vocalists at once, which is a pretty accurate description of QL's development. *Ex falso quodlibet*, or "from a falsehood, whatever you please" is one of the properties of material implication (*if/then*) in classical logics; in standard notation it can be written as ``∀A (⊥ → A)``. Finally, the initial directory imported into Subversion was named `ql`, because I was experimenting with a syntax for a _q_uery _l_anguage. Where do the release names come from? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `Daily Dinosaur Comics <http://www.qwantz.com/>`_ at the time of the release. I like <my favorite player>, so I won't use Quod Libet! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Okay. We think Quod Libet beats other players in the areas where it counts (where exactly it does count is undecided; 'tag editing', 'massive libraries', and 'regexp searching' have all been cited); we didn't like the other players. If you do, continue using them. You still might want to check out Ex Falso, since while there's an awful lot of media players out there, there are far fewer choices for tag editors. You could also :ref:`help us make Quod Libet better <Contribute>`. Changing the volume in Quod Libet changes the main volume! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Since version 3.5, Quod Libet will control the PulseAudio stream volume directly (same as the application slider in ``pavucontrol``) which might have an effect on the main volume and vice versa. To restore the old behavior disable ``flat-volumes`` mode in PulseAudio. See ``man pulse-daemon.conf`` for more information. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.957602 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015474� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/browser-window.png������������������������������������������������0000664�0001750�0001750�00000111372�14231604332�021200� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR�� ��e���a{D���bKGD������ pHYs�� �� ����tIME68_B��IDATxetɖ.zfΝ?3wf sg{3oOvYff&m2 KF`Ѳݶ[6~RRk}2#"#"#bcG/ 7Yi`0 }D^VCQǙi`�%M& zALp*|?)M=׊D k  tL;o/Y =@dJu3@u}Mg< PCJt$Sf|Cz\=/L^餸B6-:qs! ^y:H9Gl( YpF/Ny[M1x" \q:< ڸsqxY]= {cb}Y ׻{^™ +IBT´}4lIA?>~$~oHå\ZiQzg9@CQh|6x>|D?zKOQw{R1q_PgV4 (o\򒟑oxq>yqu:qX3/IëI)Ax.).({P/-za$|=JsykH!/RUmm롦PDޤIuGu*Wl34'扼3ӔM(*PęQYegϱj7~N>+={#4Eܷ(GW9݌" mIU`82^v&4deB䔿+2]Ng<fs}b3QFɏ4z)ͼ�& & <0b�pK wt^ǵja]gSѣgss./;#O>d|lEG r粠IwCսP~VkqsyWC|3z'ǠǤ8M]KN<:i(yFgW+)BW=k`-yB3Ҕ=\}KIŽNE#Wp-'_e>32ke$K&D\//IëItFcl!#q"8@0:\ϱq<rc9&$Nd�0R䇭 WcTѶx{VeM_Q|!b2לC-N!^-_G۹ˬCK,4 f4`QI]i 醮L#h3u>*\LVZSHz>R$>.=A 6[w82UwtJw!,>E>o>!k.{uڡel4qV^2IPf1H/~a! `jS�2| }tϊpv:byD)w>LkV t ,2. Yry.>LeO~TM#c[Gr[YFD]0,q J)k[%ll E{RiGnaNkt:4i@B@L)C\J>f).SҀc®>ȣz.ZuwIe~*i^*(AOrQWY:ȎZy)ɀs 7 QViAΓ*Ж[bj<x?|cQDI{,ےU,c8|:LCi|lh[Qܶ ԯF媕~m0<Ja?yJXti{r@2E YgU|%!H|86ݝ\}w}37_8bܓ# e<@)gé?Zp^^2 p3y pMӒgșV^y3I`x3IP}eȦi@/F$O1Cٌ&HS"1"ޱ$H)- 4r>umG2P.!qjQj1 xFJ#+[;qbɾB}@w\%aP7Zkmwg<;z#6ݠ5GnX=TGWYG-xXS~H'+c\otټ$h0I`x5IS0~g8 _'7aˢW7`9eYI˦p8 ~ã)Z}Y-[ p> A.щX4r>uTS62e yIEM=-BIy?aF@Tn:K GM4G+]y{C,<@fm ʶlCW$ YzBzV>|.Ze9e ɀY*zYOc$ q}mVn XyBҋV7h0I`x5I�C$FtC0g.[ `^* ^D}CiovGyЏJD#CAB8^tJ4f/5V7Ok]K9GYPL(u@}uGoPfcz'ش"Z$ͷ$zU8@ z-i$#y^!ȯЀ'h(Su{[̱<LaTQP!^V5kXVFྻoy< sO$[]QNVƸ6R7bK8; ۯdh0I`x5I(u>;„4XG9h"HuQ|r>DU]feYHwY1ZmVzw9Q2ߡCܪo�t?X}ˎrz3BtqߥgiH4rm;t5KI5u\ʬ}x]@>ȡ^i)! ;a q0I`x5I@JCF1{}1'b"1b-G-ޫm@:y=/IëIQX0WaܮHQ>擷}O˛#ҋeWtL *`8 4ޣbf0vg$`0Wb< X^G_? ar& & ```0 & & L I$`0$0L I$@eeenk&  :m g0jAAAt1… TQQAϞ=}ߥuDңG$0$gp+/| (?o޼0~:UVVjO>VW!ߵkD1I`0I$aBzk,:! >|oߺ/^3gЫWtIҸ $0$sR$VW�yׯ_kYpu=<ru0I`0Ir`nHH@fI+ᩐۏIII~B}8P$OK�y% z;o ݶY 8Wտ!& ,5_@G_э)+`0? I ]3${z&(::Jk StL]J{K72I`0IpS׷߹IdeY3IHROy}¶˛ꒄwя? o$Ait>*//,.L -ߎqHp6w~LLL=olׁ~ۨ 9$8YY֕ePs8.-Qd *_RqC�/zW Iwca%� MͧB:Q@ˎR3)l4;vm}Z=h΂Բ}GsremڈIII5n^rrsFBܥq&3I`PIBQrOz^O'2O I7ׂ49.b>v o$nߠa-h*kJkz TtN H7n^SwJdT^ݪUm_I²eˈDCkڜJJJu[o۹wFMZy QiII4g&5iՆ6oIP^~w ؙjw+ԅhE{J j׹+}۸) :?jMHBBD?#1>}"ZOhpWeMJأa8޽AdY' ψ/֯}nL7C;SI͸+*OJgwkkɐ$`ֻyj]͒zIF 5[^Ie??⧯(GSH34H{vQZӾc5wLCn?I:ÇzR0thZj5%%#Ǝ4*(,YӪ,=[TV^NEEEl*Zxw锕m ۶s =SRD+׬J?itJMK4xH- "yD_]uiQ˖DҀHi DS]Q;#{G$[7"]ꪨa/KjERNT\LԼfص+IΖYE3ͣTތ9= a$@Iag`\ՌïfHj OPt~e?ŠT>~I%/|Dm,w&z`zaJɪP;RRSfέ;ۡ⫐R?T;/^b;QfV%Lƈ2 P}Wa l?O3kE 'i˖Sg̙gлM IVԵ+R[Խu�'!i jJv yD Gȿ QFƗ8 hVQ;#YD?Ǘ_9 QwtϟRYʊg*|r(+"R/~Oi&C�%vZؼu V ï޵ۈ$K/Z=$J$b_#啿GSSVlZdw̥LK|; Dw`(tփbTG,P ;mdI :%Ó<m ß ?l"hĘqœ8�iJ0jAH#~ $s?I$.U@UwJ9VY:#xLA}x3uTN7!|G~BЇ>`7ąSfx:gn!Iz|ɷ(0됷I@?V~ˆWi(PBYAV9ESXR!]˧YnD'  ˤw…EѶqA%u@z3ar" L '&K %Fٟ҃:}FTj SWHD6T%*h7(yXd`kIHI>I%ќޔϦ x"~K?0 Aw 5,I!Fb23tz]̡yZH)t)<s.ߥW.+Fy(!1Q3}鄟0/rXF=(*:Z5?jarE`EIWΨ<�Y4?oiS$a)bE<pZq Äiٖx,t%H0~hD-FbR'A$8: ?WA[[5/q!DԷt4_*NO_�?oKH¢EDmT$�2ޞO$S <*@:}"L$L~_鑷I@:ze%/BbX~,n;i?O<IWII Z&M@I1fD ~] Ӆr{cRTBxDRq?c[mddfftӫWtI0Zߐ*uԻwYfĉ]QHJ/+ugwVj1gg\\%$jp ڴ +僇ѷ?] r}5amacqFJ1mؼE. 0óPm[՜+KGV,�_ohIxhܸ YHBqr7*I Ϧ ݍe7eC& ϟ?wYH Z p+:F &O Z{KȨڶc 8y;LF p|^Æo~m-pd޽o(ֻD [/\$|߈t,-+e`% a=CMpS R4c ;wPvv@\]Y:_G-/g+cǎ"sYwt?RHBf_Ӭﯨ ʼnIe-ǂATބ>02R"M@F$P1ѴcVIߗb@QQ4O7CцMkB9:t�Lu=&CM,h/Z0\Vr4a`x%pB2eB&??8@ӧO\^9F]t/^,`pfz囁ZeNK,sҤIohhfڼy%?& L$7?FJQV_ kBq7T%)M+CQbSAD o#Q= :v0n$p)2eegсC]N4wڸi= 6eTmd7IBO9shkNezilΞ=+Ρ333Gr'O[x|Ve[Ҁ #p9~8 4]=0{OHq<o<-Je$I}]=)\O1D#MPeqJ()=-h$`.77%@F$gӑz3]vO Fv0 t 9sO0*sqFŹ.SK[YʶkLL8If˵fHJJ2]F&kL$8&^SyT(o0 $;LߺMz$WS!nQe}d +q.eYq'OsQc {sz6�Rd\tz{qF3c$D䯫mz$fuWS!_ЦIBFFF¶mD ?se 9e%_#[ Xq>|K̭Qc {s,(W8Zm:ރ=ut$ -bmRg$K_'͐WS!C$5Vtt0ScyuJLLQݻwE:<g F޽{E>{i9F-썗ϑ ON#+-[@5kX`z�ϊIb'X,uB@ܫWtczx*sh>6ۅl1�Az%ͭ[J�هA 9 K=zTaڇO|A+&M-Ԧe,tR:uڵkQ,DA~f`͞ULp+/eR'$�AgI`W vlu: eV%T0IBt#:q6�*ŋbǔ}1Xse< h? 1EMe >$;`��_ 4&Emrrr46Ѻ$̋t0I`0 ǡI.t0I`0 3& dr 7I`*$`0$0L I|p!pK(*8dIIIx`$0nB޾}`0n-ȨH HS.]+$ov$p (H}Zz~>~gCy3-D$~ƒ]w"pBA-Wq5?iؘ:vA~nkϴufѱ'E|`0 Z$({(~{+CRmaxL==$Q6ҕ *))pב;RjZZp!nK˗/=qqqO?yL} 9H `ApT޾{+zz 8sH68/[nXa7oݦѷR]鸟j:iVj۩ 5nъ?2V5Sڶs'ҍlM$\ZZjuMU ,:rf<6Xz h^� >P#ǎQ0t?нw{+W)M95O;h嚵Q2! x=¡y<09" /CMy IHMM} E~PBB]$K"IȠ۶sR`\PX(\I䈱D[^ͧUkY]3qt6uώ$%##S3k񔑙)0|XڼuU='M.F 9P4|NlrSCzt\ C#$[κjY2O)KYZ֩A(ѹG/ϣ>7ϡ1=TCBI@]Lc&L2Xam:u*8eN{PnеWoJHLѸtkQ`gÇs%-Va0z֡q95W},a2! r@jGLLziYjΨ_}g! }#"\nBm$!++C@/M7o yv1mںDz GtPX|! z}]CܑF6Ȗ3\#KB6m?X}NZfKVPٰI)=x,(Ix&C?/uR;x2Md:c&5iՆ6oIϠ<ўllI52h Fy.{Ҏ{hѲ՞ٛy7o[OO} @4;?a~8t4yh@L6O[8BS Iɉj$TX0l;_>ϖFj§e.$C_FU(E{O<kbIЫڽ]S`t:}m! xZؼuDӕW5 *̬,KX~2(+Et*1 #::޼ycWYZSh)T sЌʭ0z PFp0go<0=y%,w-ѽSٳ;.O"DL>q/8Y<G` cbJ75͒'tn/I BbRQuF@c`?2gT̠0[u訚]Oxu䓀?tX#Og-CkrЗ R+}F'̒*v͆;V> ߭N' W&$+t� AWz�uR=K_(㭥Ѧ2,**J,A|>L30zg_3|]}FVR?`Ys0nweI_>RX>]9}31<Ui {HBjj E�A@XDlӻIHrS<S!P|`Vްy<& pR /oR=Z {vwplj˪:Ըe+)lu9ig.#8lZ! kF[E @kIyvRƇ 'һ-)1L)OSVzZShf՛a LDO[ĈS=H1UU]ϡ°}5xǍ /9=13p^$(q" I`0 1f�Lpl:�ڱ L0׌ nM!OSZ:Cxx'H=W_ ҥooTmNaz6FCm/]B-ڵ׽?vz{F!2YΣcb$'t-$J,0Es @X._󣰾a6]xx8UVVUZXm)*:Z3NXj =03{F=̹Ϟ@82j=ȨgdQл?7ݰF(uL13K  o! .:cpL)NLam0,04<moP|X0֭w_:{|C1WCB_F=|6F)n|+=?&ks}mpw?'hgkag&I&$wOGV<~p=s<>ˌ͚ <iT 'uDȊπ | CF_$`nj bˁLL̒|ip]O7?[wV; YsQjjS7*VXV ]ܹsGSgϡE �k� _`Hk@优$0$  V" `0n& p+hRXx_!r3ݼfzy0I`0I0I`0 Z$ν;tm)w?O?|YQ?k'l`aa~" g/G-5*LL$xIJ?8O o% bp2瓿?;vNh1׭uc$3H[SmǏko޼{\vMԅV1I`$i$̙3zm�{jfl!u,|ncrZl*pC8cPgymύIILPvP6ꠦn׭HӐwBb%k>" ۸aG{%A#$teԪC'0S6\janԶ$̶:w!f_?{LZi<GFҘMuNlj12##Ǎv/FPyg# O<:FP[f/IϏ]{OWC]Ħ' 4#F҃u˚`T8ȴ`eqNPyDW :Ђ%Kc- tO?I9NcO$a[)OVOgkݡJʪ! qH$9ki[vMaxݥ+A4lԘjdJp |/_a;I¤iӅ3@K3(Ξ` R/c'DKISVn!HyyC+V;}#sTq̹aԄosr-xw֬ F@ G碼fΝ'hE>s抭|#&V ){A ;A!{ajz@6l"a|N ;)0uփjCKV?5{ m[-m8P̬lԣ1²uPx+IWR?oߵVfmY nj^ի:Eu3_7# ;M%`Sg=LHkH%֎nt))&Ҵԥޑ6mLEsh�DMEMBR[>1G}x˗/iM|XFDEkƐgIi)0>BOeyA]޷*fcpK^4Y; ,b|bvVaICQ^rF10tK޽'Zzk'UA)3CV$.Voԑ";խ.Q|O öחAQci CG<!MƴDx<7 F H[4C ]1e$ Cr# Fz=H)+T`A!o*i3gۡt}8uzbk[QOD^iA}'F ^AXsd9r3\3g0p]y'IV3{  tm<`9�?$ NVvì ζFu:px?<G)TTT$Pl7GI#az~ p^EV s:l~Qǖ2IP :F`IЋ\9׍ce|jZpiZ~2k| v]tn=QmCh7"2T}̧}a h/g+Aicy3HlE2K.pX01CO+i+X=MbE':jzi Iǂk,lp6J?9P"֪[vv6]JthY8C))T(1CnunuMdZUΎIU+6o)~-#F1IИ;22ȱ=$֒W-rU b_e<FXGyˌ3, wZqQ挨' 86y 8P^f0ѥgoߠB`ГڍŠnkpQXn$dYa)H]@VvJӶeee PGz OvUd@b[][]/HFiPaZ!윰a\_I#j )d71yf! 0eI�hy -<#9Gq;vI8vk6:MpTLaCs,- ֖~cy)˅JP'S Va).%K\R[QoFbCS'j uf5U$tFJkPęi�b0zNoZȣTlQ"Vz$x\(ɓ zߓ:'$᷀0#u=^qϸwxJ+lkխI{ 2߁5pn4lXxz*IP}C�0JH3(=$0Yخn!F0%S?}Zps]IҁO# h| {$H`b\(`�((O8A@@+&0E)$A2ZÞw!ea+%^Al;/y.x\?4ix<8*Q 3XsI³g !yueQݻ,;-=D1:\=#u=^qϸw1oƟe/.ֆ` b,O`KOO r\IIPҷCoю[~]KmAzXnUy>yZAyV((̥*-+;wo pV" #Ff#u {G-&hx3moT7& L\-X]6*XXX$`dm잿xfQTPDӡ% Q.]Ek); $ *);'CyYT\R(p+mݾBPOYq{&6@[MPQ<X֍IWl//caa'$R ¡*_'&%nLFbODxa[El{rDkAFf.ө0 ƭkP1V#u {G-&hQZۛ& ,,,LB0jg~lPTQ8~CӮ)<" H]V@xi[Fl�Ȋe%BzF eSnn]Lwl˗/ZMn7ܳ|h m62G[+ޞvSsLtwuLXXX$IsV"99Y(*'-[7JJɦ&Z0y OrP6ꀺ"/ȥHYBejݺ.](ZMn7ܳm;mFh+xenPz9$;qR,c$HJ&;J] !v4"O01N�sHc<m1mLK9ZHL~ i\(AS'3ZMn76A۠ʶ\=WYe*Ҳ}GnLXXX$!I~(|F&Ƌ_IJTmKwnJ(3emxa[FPu 3#+DAB,%K#t#y1B8O111z5{j;Z7pϸw@mF6jmonj |מԼM;p f96(P U% XkuXC#K/m;wR.ݨI4o"zc'H+0I`aaaP$P4HN[ YQEFX>LwX}wp/;R4RۖQ@)뗒$DL\%$Ä8-_R  "Z5\/3m@mjmonj |񔉏3ImEҕhݖnܤ8dIVӰ�nP􃇏8Pjj 'TǗ!LXXX$1Ig~L8C +=dI]/޶ BRb(acif Dz1`䬖ng;�eM6zfިnj Çs쥀/8%%vb+ |U9ӠqSy^)!gsrsA c}LXXX$%Ig~ +a>66N9E{Jc/efT)<uGF?!aO!G{Ľqx3mW75\&c|X>:czj 0y:yhj"H]$IB((tV0+/~qn"G٨ҼlT7 .jn?:& ڴe=AxDǃnjכ#u=^ebboٶת%Dz%[ 9qQ:#at:}D2I`aaZܧ^]BpX&G98w$EpyB]խ.MMY?Ⓚ[YF[C]B v1&NڈYuiF4d";SʛեuZI¹sTPX5מxu$fnYa. +;Şasv:qݻOC u]l7 XYdJ*J堫b73|$S ѷTfaY 4p 1fX] |AAi`{@JV`g?YRfR2CSV(RjxB ͞P3~"I<x*IŨᑑbr[wDV`z$~}vӻޙ?(Z2BhЉCP6ꀺS7X 0ǻSe^qI5~\Ne-Z\+pQ,@))0<{ΣXt YʧZgdf`\$,Fuab+ʵh ]$@wJt.pHP4H�Fd:׭fuܣ`=kJp&ZSν{�4kݖu&V ,?~N q??qpėW}?cy"F-ZϜIֶ>Z#(c8v]ƆE9_jzQYSFfFlEӧO9G6 ZQ,ްŷZ[DQ^KfV( %zymWo! ?VVRݤ{u5}߬SI2ybltT]R\7f1:;toB`:g157ЫWKÂ@>G#yƜy^XO޽_DWqh>7|XK={i4z)SRTuA kɂB)-X6nS  m-KeKjٮ3Kcb-Q11l�k'Unt/w7o^ �0pZ2" 0^uY|XxH"1b䒔B_ˣpo5వ܅1Om.|΂E'YQi1Y޾}K 41/(KB{~b*S݄AKV X* ,*3\?R7AlN0,+r{HB40ԽU6{i(Y$WZf_ݼIzXUDd]vtrb� 4|edfQ㖭-d` X% z0գU{ I a ض i8T"L^r>9?fOz W=$ 5ڊ}b3Q: 0U$Nodu89sٜXި$AY>DR:0'$ޏV:RTtK ]A 0�)lO1˒)i Zϵ&$- zaUuFLPPp86y S:XQc6h+ _nz I[%n45Gb, X-P X$K+9$;pPX)jG*�4X6H|�#RĨp$m0u]$*pT�4E Fd9tK;JZi\!@iJ<Ԟ;xH ~q~Z}$rr,PwpXEUD^A( `M@хHsknQ C8cF?'o�'*=*͖WV^.a'߰# Z#,K\ZxٳV,pn:Hӧ5?:QWV7͊5kEEg� �'f((/eXр rQjV0 (o$ Zcs-6Wkɪǒy3 &G6լn8:O!k>4%b"[ Ln*Ώ?a<(Sψ#G[}(_ 0o& # '&dǦ/8a⤤q=XeWJ$xD҄ez ,,L$0܌$a6kIeq,i~k"_X$x`K,1ݰbIG+쓀L9 sfe$IMI];J$c=8;h]bh& ,,,L$.<e{Zxu]7w^9$�gΟ˳6o)0vdvi|K=^ $IB]ᩏ, |vZtu]7w^g$0IpI{P]�sj$j7& LXXX$8$t Ei]�ej$j7& LXXX$8$k}P4ׯ(ur;͝nL$0Ip:Iu3$`$IKIhJ A6<utz:u&h& ,,,LJ ۃ$ڳo[rn 7# ԭ>@ݘ$0I`qFEix˛EfV-\:oS,~S),>0/3$0Ip_Ba7?|vYr I>]={B͎p!7((q}iU;]MI$w;i)vNv]ML6;SE =sA(*)$A/*Kwc3yHx`FPM:u7Q㖭A7oa7?{p5$DڍIBݓcҥ+ATT\L%UhFgH0Ժc'*-+ qZ[h鬺;y3Ip;2Lx_PXHt ѼE$hɊy@?}KfY_D&\0|KZ`o'}IwZZ�O;mE~A!v]$sJK˨Af8(vF 1EܧO;v!F7KVKbs~'cQkZERCŵC)]gTnMm9aS|owE9yc4۩GOQ.0;$9k9!8sֻY_(0z3{]CaG}:U<sdHէw]|@/?e6[75`A|s>g/dpjkڍI{|1t瞽4~S$V"LQ|VYR쒈~~bKel0zYd)mfb/ D@(;6#%ۡbdlj$A\gf}uvIлWg (dI0t'KB黦ͩpZ({ dy&cA<]{Y붴hr켖$<Z<}􂕈7o_SRr` [NܡWlZr$\?H/Y"t6CW�|K.e'Q3yLJ$I<:Cǔbqq t cE{~_Ph{yNeGCX`0a>?}ZW(r! eVY$A^7#ZΞ+o' iL b5Sƃp ђ+$`^(|-=ilcW4nWBDž%hhqiyuF٨H�3da82ؓ(Y�I�.]5LnL˒PRR",E0I% e@'}:1aKmA(Y 1Jn֦uZ|iIuήIP=#W<o`/F8G3o(4l~1:)-bdI@3E<^E` sZտH#!+'4d@]Dީ:)GbqRV1-7FPG-YYbhz{s2I)(V1IxD&N{@̙+ૂ/Ծnf1*?[<Sj$O/O3u `\1G~Iax<d=ҳoֻǒGR?)G}'B$RxfkaӦyfF,ݿr6M|EߋϢٻ㰇9xn([$M  FAsï6nfk'0&HX533S̑I%ADmq,S4n#`iNs蘮a2Ų$ FSΞ:I0zFzC FydCb<8?pf׶=)�6Yqf,nXe ҍˊF } jԬԨkiIuÔlq<{u:p!ZyHkOD-+;őH&cx1iGzb* Fݘ$=Ip7@bv" F2Rhw3ۨ 0B3IbC^ p97PZ1qJv=u `\aI @9%caF{^QE_7o~mйG/ڱ{S$l!Rf۩ V,\aAZ!5-U" gtzie+"ZO<LETPXL\{yl5Ŵb1gZNxIo_l\EkuZ$^$EEEGt&߭[AƖ̬\v6:&^ .懲QԥuD`=4`uZ$I ((tVq=jԼPǤԌlj9 ]`XTu/j7& LXXX$8$8//.ӈ1c'dPq{i֋Az$h& ,,,LBLE# %;.NQu&h& ,,,LB`ww�n͝nL$0Ip IϷluy#'j7& LXXX$8$`n[zzz@ޣAgw3ڍI& Nn &55N�w̙j#bw;Cݘ$0I`aaa4K?Qrrr�.88;͝nL$0IppB6EBbgCw;Cݘ$0I`aaa o5<泲j999bZV7wQ1I`$)$`$7$q$IIꇎ^p?<Bc+WN^UNbg=l|~W�-8S1H/ԌǖHj`&4JRFoXw 䎝bHm.] m & p4|$!3+ZmOܥoPqI -YHSimTj޿8<RئuNTZVV-aSne$9rJ 5ưg_CQIi�_P0I`0$XvBRg`/I̹NAa!͜;n+.3W p}MiQk/)57[HGXYI%rÇR$zKu=uuMӧOaح.YhijqFy. zaYٺyYJ$kߵV9$`Ps,Z? % ᔪ%}xz|nDW|fQ((ez4*|TQAc&Ltt#Q4gvTT\lw=Pa(/DVv;׾hb `RM5%5,/e"(/~\C7UdIXv=qR J"L:IB)P'GH ʫW]Vdy-5hrܼ<9FrGWRR*FZCV[O!o$HP㖭i%S+]n.Qk׾#Ue;%mY;.%/Y+XΞ+o' ))b3$ZOڅ0& aᔐd9wȒ $5-L$LDzXyͣDƱ2~ּ|0YwWX7t=I#fmQ^}Lꓠ a}ʰo[%JǏB<ra}Ga'R οicH L7[ & .g=> z^\J/8FEUvTFJ֒g(Aq|S0[Or@D@xԜA!!",wޢ”:fҳouֻG9jXaV4 & uJ]݀yлnXEBib$`s=$a}4aT�?c @Llfh%#;v ?*gE` Цcg" 'O6Cs,-D ΚfR ?(m@`F'K\A(s_ݦ&T^`0Ip;�Q~'8,RatS/LӘ$@i��pW7(@CQ$�fU|pE8I${/�ڦA>͘,LUʕFyft=eix.Ŋ Lx+IIؾC �#IW}(|H[aaKa`0Ix0Yc*aaa$$IL|yz9,,L$0$0I`aaa$t uӭ3$0I`aaa$c`ث;_ҍ)+`0GL$0Ip=I7w^CO}/] 3cGw_Pɾ4?Rt~m& LXXX$$&JKK o ˗/(~%UaFqZ $>:.-Oz22VN/j5V[@s,@2I`RIMpeeHf= aFqjuWvLI0<&6ސ]$�K<5ʃ'[W7|t /c"nje$>L##HoGNNP-7/K�3SӴc֊Q)R*aحmΝԾK7jҲ5[HXLu+3o,k.=:s F+ n YH=׈8VNS?\뱵m+_l9& @2p08:A1gddZx5;>FbUk9zW(=2âqy4*қQڝ?5RS2c?yf;RKBc>l,#m*埑)Q6ofΓMԴ4Qo;q2& @)J 1Œ:Hf|^ŶkGn:zi$ +)7:N:Nԋ4{<S*\:"oަحO+]N#V|W^YFŠTVVF 7>!!I w" |k IxTQNIp$ ZqX)Y%#-Q_g]l<ȡT܀>0>=O}En* t*H^COVʒ-۶Ӑ4DEk@mS|%Ss Fm L̋+7q zJܩ0I(KBffPE !V�3'aL+EeC* v+9[kzS}RNoQF3zS>>>*HaȌ<ίo_|״)!VΌ%A$x%Amw8{H:8PbbQM܆ZИv5gW=W+^8^. 5g_ Ҹ$C+'{/bRjݱ-^JR;]^`KK$葄*L1ŒW7ĊNpeI9lecN~NR4aBUTTP\|<M5i;s!76W%Y^V4$dKI|.{sYrO9 =OlI1f30Kp'$$Aϟ-jKmW$AW_ӁÇ3i}R*rr(Rib+C0Iwl̄t;UV8v]QPHXY)Ih1=.~rjED1Œu%)~<d+1:EG&{9v̙÷� =AANY{Б+B~i?dwgYMZ! /R~Ľԅ-[NϞ`cnZM/,[ڲ# .$A(WHEfΝGZF-ZϜH]'Araiڪ -Y޼yc}-sU7R5-[tͥwGy>|ӡu.srw(  8Pf;);# ّu}$ 9[E4c~x�fgo{oBfدiVk[Y[Ėc HoB~LHo$JKG{'ȏY#KO޽[-ݸZz-4YLU@.X6n3mI8tPm6%"*̨SK,hCB{mվx_חbqFy?dEZ£bb,V yK'}/ Pf{k>a*<;% |={V2~ JgZ2џ].FeF&%|CO[қє<ŷWa嚵븈)h1r:|}ʌVj+,`j]>(r9[%`Y#$e+G%%b3,USuJ@d^@6k&%#Zm$2= b#�VT\l u -`EdJ% oAm({mπ08ޟAz(ceGeE4~<)gWm3n?FnP :7̋l,w^ԮWuʴzRq" 5)[M+30쨟;$ޡx?~(O><cyTk6=轤\s|.S>MZ6d|9)@`Z `o� kTEQA8ʊG0 -<$dfeQvB:E S)~7SYr\<FЖѩ4vfٶou 1Uk.${pA!l^r1G~IaG%F#7z_SQE20+J ~10I`0$&H\XjSHBd 3<HS4n>,`iK?xj<L\7i:l-A tѺ6HA[<DKY.Qp3jwEŹWϢ�8 phu7kNH,Q$`6 +V2I`0$K"(RNt2 X- Ӛ$cNk$=S~ `7:[xâ�SsV=;{] ((/e(W:i% DA^Ʉ_LbSH/�Z-1c,u\v)ez? v\d0$gYwNn& & .,Bz,,L$0LX,f`xKXX$0I`0$0I``0I`aaa$`$IEGDQ@ 8@Ξ251Ѯ% 8`$J>=#޾{k:?|\rъ($0Ý$I…K(#3HKI>|wD]o$ 6x<\J^~`5$x#IVYKI6`0LXXX$It w]}o}B~*q@j$ ++\=겾fghI;I]oTuaqI8z0ݺ}j#3z;T($x%^�gL~z52}? Hbi]ԪCG:y]@hج8p+ߺR,TRu�ά׹ 4{B4n#3yhTۍ){uNljw$޹M7k׃Q@Dح7w9IpU'#<ͦsU]mFyŻ<$$%'SN]̹sTXTD4c\~58| #v7M(ҲjqCr+c& ΑKWhب1u?y*ED7o鿊0_XdpF8QPKrયEGGsf)8Hm:v|/F3jC }J|ιqVgռ#zIH}yنَ:Ԯy)m۹wFMZy Qii)YыBp1l;/tBȂߎz}여X)]yV[OZV;ґcǭ=ve 9sr7֨^zyw# zi|W6lag꒙MzR 8FXVvnf[HԾk7/( 7kP#2QXa&A� Jlz<0ĩӤ?ֳ_y`؅Et*x%~]bWPP@+֬ԬM;$Zu׋y1vzΜ;VI Ui$Ey6Aj_HE[Icq~~4vd*%:KJy%~瞽4i=~D`”$g4|Xͦ5'Y(=VزTV:82cb-Q11<%'N^BS;!2*""tӸ$i(lz< qJJnz(XsXͼ>"a5Zu׋ҳ7=xr"ԮsW=olk<k|BpC> _BzF%{~b$$S1#|!KT=�"& 4ifWٴF$wFVV@G‚03y 8sʿ fv"C=$!=3:uI{Gbx@raa4ljܲDg,۸i  k\_e=$ `*qusxIts$#Q&X w i_9Gʷ'(Q<'Af|lǏÇBra}hԢ><cٓF^ 8ac! CG"f߯xLSS7" T5I(++s """ lz<0cȻD*7!:vNwQ} ׋,&$ݽF%|[�IzWQKBm{- /y"I0z>j3g.PPp86y S:5v J/D}=VkŊ\qCƥ;oDIo^;|OYbau0KXF텳:ظ8᳠L9!R8fca"ujuSADDFiڳWXD&_mbz�O# X_t:pG- 'OPC-a87iV`4Cs,m3R$^O#& R߄goql6/eC Fy;xHR ~qiܺz6~V99^oo$;@:2kOW\SaaKp}flz< c V1�&`1P ٹG/=H} %L}Z_ 6j"gΞssxw@ZA:.ʀNq)OsJPӔҌ]x,\W$^jpVupG`|RR *T:Fy` L+&0E$AZcem�y4aQkFP.*YW޽{b~U'k&0`kXX-Z$/06ӸVe$!77%{n|O```=<򷍾[ݢtzIp&\B\;w2\}o}=$`0K222 Y`0 '4í$`0$0n & QG$K w#$`0$0I`0 & ,,L I ְev3ianGiw& ,L$0A4b8@Ůi5شuʶR2<$\ &iپYrrs-)4~Toc9lg6#3S<¢"& ,!ąI^7]RͣE˖ӸS8MAZdi;69xP%%b<|XKai_ߴY}m-\DeP 1'QE뎝h٪bG{={v';廦ͭ m.dy߼u[있>]bD9ѣGb2c)Ñ'u~/uK$I6]{YGl[`fXQjJktzed~{gIi!U>1y[ūgΝI\J;v;މ;w56znuiߥ5JT?jp?IB!3ZvMQFLނAA4l0XvoJb"% 32w+7^~zURI`85-Mt>MN,�tmfm IMI^}տ_#0qt){:AWXΘ)Pْ6E=.YR~@.]rg`ͺ뵍{+&4A\g͛O$ecڥD֘$8Q^~M7kQcŇ}ڱ:oKF8C<joաݹwOnK$Ci5[3e4Ϝbl5냙kl˲L@tL ڍ,a4`83 MtȬסkwz#KJŐc9/++ҨPy}B—y>ze775& F5_#Eh.KxfVe8#!HSPP`<ytm&ukGHB^5KQϿiؘI3%=O1Ice 57ЫWKݸrS#i5[嘸xz|R|z2I`8C)L9*1_TF 4*:F $֩{O \^^n9v(Uq2^l5KҡY> FNE)3>Vp 9K> 3{zFJ _P�/H1zlIpgfƈs|~f^HVIkT> $`L]co=$0sU9"՚'1%Al5p%I0_s#DAcEkO+HV_ݻF#$8Yb195)x e ~;'Qf럚.:1 wz{$,`W8%*oM}f]t -V> Xz9q[$LhWy$}\=1>q4f[@T 'An [6lb+P[$AyXi{>cJOUPϚmyc:IB ڍ›sarާ/Ju" F嚭rUa�~iz&dpR35(QRg_#>i~+4܎S?Fi.]&<a6޺c^ٶ<;Ҙkq+LG1I8xz/t*�I4f$'t)}j$އ ڽbE(y&} G[3q& 5̍Âʙ^'OиIS(/?޿/LKs,r9I0*l y]1pHTE2칦&d`@qU}qqǑ:~ϙ�Mzn?}Z̽g�,N& F嚭1;G<mBftMM$Q_rZAa_J8n`aa4C1݀U@J7I `$`0$0I`0 & ,,L I `$`0$x I`0 `$`0LXI `0 $+I`0& ,,,,,5HJJD:u5y /$`LXXX6ժug$I v.9n؉uNx z*ݿ=fmTXTFg*si/i\d䡕3I"nj#<2LD6n*eVӋ/T]& L$H2fDz*+_ҫׯiOH'?ۮh.5ySYj,O?Z4L_.] aS),"^yC?<{&�ve$^is;)MR8>s<u]0!#GQvNn+>cԴUZb%K5ݰŷZ[DQ^KfV6uӪc1²uP8Jfjֺ-jߑ?au{=O:w|_E<W[%c=xXYIvBZ0I`0I0#P=ʬMvݹg/ >Ҵ2=GP6:ֻ#Ik~~4vd*)- `wjϟ?˗0XZ 0GЀMYvٳ�4*~QE*7Sf'O,ax'Ma)S=$pIv6лhLLtb�:עb4QO>}2ZOeG>BY#ѵ^Aehafp欕Ξ+gvܣYaeP^oeVZ_P`9GDSR4(LԽ'2I`0I0ez{JVFg'|*S{ZV}$ zaP_WK@j ?~H>|g% C#̞<77J7 nLA(},plOVy<~BJc=INM1I`P}@*GԪC'1ׇ!F%9Cq{[YLfDWQO|̥ fR;obaUb%K¿A)ֻv$nj{%Ao\qtLiv[~$0Iw$ae/F`=79 ˬy b>_<鴙,& a'OwmgМtI:RCıټJP'Ѣm{':(vn�|�ɞvSnte{}=Fc-& $\y LmԄu&W%-0g ma>}7$y>- 33geFy)Eǎ7Iֺ$D7JLmy%V.wHmu{UN/X֒'7$AZc1I`@,,,,I0%g>ca$,,,^/jK(7nFa$I K/>X90I`$II & & ,,,,,LLXXXXX$0I`$I& L$0I`$I& ,,,fŝ6aL$0I9nݝVzWw^9҂3ݹ 4{B4~I}cZ2ޑx& L-It%1$sGz7q뎝Z4LܼJ[mq1I`$A!?VVR(%$?t:v!_b%dW)i-Ԫ}G#L-9w:tN6nJCF\1ݘ$=/E){ ęy2SV;P8?1jfjֺO9~)Uq& _g`DYv=qҡ︟؂TK&mViϚM<ڻMB**LH\}fGtPGe $Ay/JyPn/_UV;"̻?dEZ£bbh_gOe?%('j?۹g/M#€ Sz,Is Fΰ0I`$$iB% zϐ} +,OhIW Fqyys:ٹ>}rn4iڍI2z_le bT- F3AΜo?Csv .xmXΑX$0$8SmI’Z8*`nU'aZ#r# 5y_lX(Ï?҇̾{o><cٓFb@)8acpLQ/<=E""hY5$0$8$tWչL/{- L$/j3g.PPp8vݛhvUb%K¿A)ֻv$9  vJ IIBt5% 'OT1zɡ9 c^k)' F$HtC!ؑw~Pڀ?(mW3sʾhqBc_8|tO>I�P'gϬ|NoׅaIIB;>-LmԄzDw恎t͖ 8VZ$x/I0z_FRyбce�`Vu9L(�?~S$fE^ pT[lŚ<QG)w$ V_==VU& LgaaW)N{rC& L_L`UV>` F߭(L$0I`aaae0ݰbI& ,,,,,LLXXXXX$0$0I`0I`aaaaa$I & LXXXXX$0I`$I& L$0I`$I& ,,,,,,L$0I`aaaaq$ 7o8woEL$xIpedf8lMHHˁL$xIW. eYy"& LXXXXX$D�L ( & ,,,,,^F & LXXXXX$0I`$QO7DDE0I`$+u\ĵJ$I ^$ILI yef$Ip& LXXXXX I{/Sq,l3I`ROHBD.]@I ARrK!L$#�%A& �AxI K=' JG$0I`aaaa$!IzH& ,,,,,^J>I& ?k23I`aaaaR͙I#SFlt7xbu$A*:-=MX0 Af$ (`�fI/" 7& `hIB=& `+$0I`0 I`0$0I`0 I`0$0I`0 I`0$0I@呿?;vbRyy9wX IӧOA(++?2\7oPXX]vM;wZ I' gΜ>۷o6bEM{ho& IǓ'OkvF{ݹb0L$x IxpI(//Ӆ2mQ9$H}]4PZ?UVV%~_m{HwӁ;!]r:w^-۶d.] 6;J4m:n$SHBPp0uӗiX^ q{;qJ@9ۆك�WӧO;OMN@;ׄ$?L㨸H`:x+on6ggԦMuur qVԤekZiWPm(++۪?dSkkKSN^X<W[FfxEELܝ$Q6`*..R$BT:g0__ЩSD;0<<<jRwL<gQyE.3 {tF*-9Ew<BL+l9s&}7^G?A}4xAZdictBKI;߻vp<rIi3gǬ=JgͶza9 /XIMZm}^,v]^R<! 9+7mDK@o·FFnhÆ Vaׯݻ[j*k#9r$)/hџɟD7Og#(8D@+~h皐SGOUPDjL-+n4vo4M9D>$E$٥ -~+60` ~k,Y"H [FPΝŵGD;vFY,  k-8<|fnSM]Vk1”#)u~/u/[nk+#Ǝ׫)&ש{OMY=槄Z~8F?KMvJUڱ{6:S蝻4=E׶j4lO{^hLװyK<݇M[M%�'0Ipw>##$O:4đS9t4|Xh#@g͛O֮ {ŋ}z:t~ܹj $qa8{<۷o/S%lԴiSJIIdjԨU=VXAM4/ynn.Ӈ&L+~ ,EZqUꈍp.ȏ^*>#Sni",4,FBh {u! OȱkC3f̠t 9sL?/ /uFĒ\A hoپ#^$WzF_w*g7of\qjZ7+ F',^+V*ՅK /݃fsc>℟?}״9-[r>ͨgK_ŽןnRDDnK+KI6jRMOҭ:vA$,%*_zSBb V$^ t4GHCa8B'H2?? |~}z?EEEYӥ{uC/OW`V(\_jJ._;K^ isP6MIsFQAtvM=A>sM˿KюCGGG+Hohss<]oa rI(’fz>R޶Y/ E?-K+})r_!W+0GHܷ؞+f4rֶfZw/U܋-?*aj.Va1IK|HDcKqi<-+J YX/L�2 0(NjL?|ce9 &{'"zy ` J L3O3ܾD~zGwK\[h{p9@ G3hX1@K-eEw(>>4h 06W^NKف9Fߺu7n,"d`I#88lP~lÐVImzeYdھk7YAzIKoOfO9FfmiϽDJcƉiyZAI>ͼ 5yؒQ> T}ૠ[G]z&g;ƠC2x谔@v&sk׮ [f uEzXݻg9{U*WN�̄2AQz3[TGzHcRmIF9AvEo&GNuIe51~_ CŻvҒc%zݵk Y$^9|17mhgI+['j5Ͳ`h&5%(I0ӜIjΑשg9*cY+X=V5`r2 �StaH9N:C:B05P\J#Dc07nܠ??ygff_#\ӧ9m�Ft˗/a P`vT\[|̤E;-p/;j6ß펤n[hT:⍈CO:FD'.:8^Z<H1P6oⓀYfY⍮9~SY8DZg#vn=GtܪC/>3W#c$ ?I\o0aU^j-Z?}͘3ZAb>$Os&I2:÷0HIMNxvsF1=$�/n_[7ntnZV7<zOjL2�J(ZX/LC=|pl `t  __T@;(O곛=M% KCv8NΞ=K!FF bĉ0e0bĈj2Y<ߧimU>8c5�۸Iw b /V9Mi^j#6O"- ;VDU!j>:݃-lv[`Vi$ 5}VFYEܗ^մ~xxp�eev*< Z% )X܊(?7SOʗ?Rbj|CTK}qqe=;qIK:1\ 3ڻh>$奔BIit,2Ipo\VxW�~+u�2wZFC03\ yCB'I<a_Ltԡ`$%\�rp-2 $Io oL0>rp-`+3 & nkI s"õ5̙3lI`0L$x%_(sg ;.2 & ׇ dpk�"~ `0$0ISlv.t!aL38`0I``0 & `0I``0 & `0I``0 & L $a@ T0I``0 $ hX`0<LL &wml����IENDB`����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/main-overview.png�������������������������������������������������0000664�0001750�0001750�00000130766�14231604332�021010� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR�������H���sRGB���� pHYs�� �� ����tIME�(]#���bKGD�����vIDATx}uxG﻾{NPۖB)R\SwBABB'D!݅o΄MlKH0{]wݝٙ3g7s93{?Mlb&6Mlb&6Mlb&6Mlb[LX70c3)% $|n• a* Xe缴oe3Jz@`yo:I[P~9Ed\'\[Z ,?Q_?oy 4 A8ҺKZm)^.g'Mׂ}0m-\{CWSz}:/i}Uyԥ)^MyyːEzѹP2I,&mu m0Ô70b9X}m2Uy`wNT%!M,‚Sn\%W 4�V>W`WTx;R׵Awbϛ)}UײHϓWMbtj64L=} 5 6ڋ^ RKv^+DYyrΉ9TnXIePAdHʒX*e)Aߋ/=iϏexeL 3\ℛ:!<m._:Fϫ+^/?a!+AVFk6^=w0Y7HR.tH:nƘ"UUeK ̬ OmFbl43.ZA]_wݫsus8tŖD&aܟUy?hYU5ϼ/G}]uSQ;K_gYsZsހk`,OSSyԤKmhg=mq֐ȍWUݿ<ڔ(8sмC<<BS,Pgҥ^~AϬ,#Lc:}_{s5FGC*;7y N8".%%e7 o8qk7cfCq֍|Qzԥ-)ڨ*&8zI(bƧfᄱ#? UkdQ0v'm3%/.H[dB:V /ݫ ^ݶW{4ɩ~FH]OMpt~f ?EfN]0ies[E%%q+4yDhz)?mS\b]}RT=;ʞGM&촳$#ڌKF׫*Kն,`:"^u&_`ufMzY<ұDR@W9`71uF։gJHeף)]Àju\4uìwfaqpғ++zV,K Lgn\er.˴6<.Yc"@"UmЦ'}/9b 0s~\k95/\t#0+<ߌp% Kcj]6{&K�zc9~5\z\]f\{iy<yqeU;Lެުl貶ϛ)Ŋ UVDnt$UVk[BjD]EYuMeY:.(POrmXu+͢;ut۶!TT<v w>X@VD9`VgFONI9JHeף)]V#1-0˚ϑDP'G[lrRG?:]{[OdY0йRLtP %yi?)1=R 0Oǎ(VNuPJʱ ppDI䆦&@;v8+ÙuWk;66UۜCzv:F}TOg?$ruR$W/?,¤70e%%#+_hΤKӠyeV/9/9ZeRt)O u|%eUgU! <JHeף)]X^7qw6zɠtM*_U~yY=x=KeiT&ɣMWȩ~ e~0{CK ?* hԺK猭}/M�1/Uj[>3[\)|Qfkeݞ7mAaE*r[~KO˟zueIJ)k~KUX^2UE3* .P?͘h;xSvR]wVujL7? RGBfI+v#2Jˮznt\-]<R9rtX7Or^6ciWYQť/OFD<ڴ,]3HMKW95ݯeg=9ٓ|!nսωo̺ހT{*՘M10`ΛUKgƽJu{޴}ꆵ~UTCqX'],uemfLWUY:.u /pƬ xܤz&u{lw?s[N SwV<teTF$TWS㒙;.E ?.7֦Jor&6{U&rԵai7nh_.kWzTA1ݛv~\6rjY{+ɓ,_7\V'Y=z?fh\{iU=" JauYcfV#],u#0nVώ\~mtMm4)ۢZ.ȍQe%WYwݩ"˪"ԙtۯY4%Yz>eƭGnt^e;i;j G34iиx]gd<3bTe)OuQ'Ju Tױui((*f9lXGyO~uiҵѥ2k6hj?@^FNm'* M}Ƙ!~?bl#TJކiVp&G9[uU03{9`S@LrOj(ӻ&]jG)ņUफVe']"R,oa;~<U3 QYΤ= ǝx0|9MfN3QƟ!YmSvqP[CuQ MyʑCC+OWꚰ[[`& dq>h]>Y(DuimX]*+S~N]4daϮ̴Wmt?nD<3-yyձ{A 9='z6,<J. g.&6S@߰JwR'E3C/ìڅ{y9 ݼvՀ)]3"j,39e>;Clf1>Or@}*rnKq'Yt}S/Pg]xUz'CĴq)OrQRVl>&?+Xƒτon)7\9g僬Ii�mAgmͤ:. ':b5(*;#Z֤pBf hH{KKP3 +HW@@@@@@ ݖvzh\ҥaVQ4tC!W~S} K4]zaȨu[Ί5ԤťW}R%Gm+ H30u:ӫ9w^(' wM͐@lss#CqPPtҒ%HW@@nHwϾadlen-wh$*s67y*CCHGb�>{t֯"&<y:'N` 62KLLv4l:]cnE*SRRs_7x9E9z<cCڦM=#ǎc_{kz(M^31aa aa׏7.20vFjj^}8;:7qtYՆt:}.CBiVtNV4Yp1J;ކ$]U0ҙ=ɵv&޻55N;$$Te:Y!ǡ:\b%'6k(o6<O;9UeDD&Cپ{\d_6=-`Dϗ6Ϗ>^X^ҥWp1oyhET zb>:$˫);Z"DDFrkQjרks]c^,J9>>UǤKU3<"8)) ?1tmӦm;qJW꘬?:u^_{¥˫Ǝ-{ y~֧n^}`m]LՃZ;zĈ7*GVH}ՇKC䞤<UFhtCU\U RՔ.o[]-91sƇ蜲:ݟ$&k,fr y7m/m}ux Hm}<ɒ:1阬)e]KcA,ڐbg(aoNцdyt%h]-]u+kk^KXrs h_\ygN> ,d6Ϗҥ}a .i| i܊ъ֭M!0tr<t?n1][- z|lS<r:uk^{f^ި0{#Zg[GjMڮ욺S<tr}Uri?Sab)ݳ/Cr Ҿx ]nLXi.MPQL7yS:u6vvJ!7CLYrҬM4fNgRMcs4:f$N|PN]护CҬbWtUj"]emWvM]+̜šiv{xzUбg/kTh[8H% S ҭ 骛lfSu-xC[Ct+ HW ]Att-RhdMr̉XV2MHM@tr@ o lbKuXU-ȗDOaH7"ak(Z7.<~xCEH[pC (HέXT@@CM F&ݲjV.ubM˃4ANj q0KXMtb[&JtoR@e@h k .YCQ Z;8==y+.o-x%6M6a/&AիWqҥF۷.iF炂pi4 M^oHW L(Zڐk0w\<~/FmtiO"_8 KKK.lp燀�0nBnnnכ ]e*J.˾Y/tXPTT(fr HpBeozSE:^ARl?Нss\K1xHls3^ 9q#ƌŏ={Ͻ8mzacXjuտdJ9v!]r2tѨKJ"T7 ']S%?w3!<<d(((hzD56Vk_͉t_N:` a߁>}HJNFLl,a-J1=pWSg̙[#q2 lJ!\ظti\SF/.npp~7O#O6*RF#]$Dwii)'�M2',IKner�###_8nSԛ&;x~փ썏鼲N5͞zO6k?S}.̜;^aѲUhL:b΂ѧz폩3g㾅eg =[Mu[[JHH[ UDغ &Ln޾So'a<OLLVHҍ6iomisAy3yYu!F׹lEҊ(l޾ .g㟛qKIeeFFfrF޻;`H9L"2*ő3BԄ T<UMCsdՒtҍxh){9eN �3 uAL!!|)tIܣtns5Z\vܽ'TenU"峱$yϬZ'Vejy-df^zٶs7O342NjvS*e ˋ:~�f\R;CBB#]j6_%]�|5^O_[`E/%ZZ㞅l`?�fV=yNL׏Y9ψhR)yӸNiBgJj }~%_%&1$&}Kx ]+<CeZe:!NB\<Rbs&kk{~cbbҸec@6ErSԛ&%w%YedP)yy,u=ttȊwN $$5eY%t5sί wxXgӕ@zROΟ!kObNjaCs, ZUseNOHWͧڨ>sů'✞^>AC)ݳZ=33̜;ڹHyIW: g7ܥ+{(`x.7 60fDƐ~mqr0{f/<\</rD&ec\0WLؾ .]t%%%kPݚHCCC9h#ݦ7M:v䖥c@-:GiNpǻ"]`U|Db䩋ZdmʭpŚEqKy{??wrG,<͓un4N]KאUY;ZV&mm>mdES;Օ@kJ%'4A]}n2j4X_"F/G/# yy36m3 wMa^h-lìCS KbdM\5+W-,m"'7Y/pɕY&#}8OSrEfa^cȍNTDYLc@"i_9e"]MLī"GYn4Y^PFMQoڐ.Ya4 ]Mt5n %ku[r9 $ _KD’u}NZ<a/Tw!:%]i"]M6_KVih~TkO{\pf<etµgVɭZ_ıg)Y4刍G>9+sccF%k"7gʗL' ,7M%= 5O{Ӻ'q�vpgo4\ #ݦ7mHp^bi$i/5uE(G>:]^Vtcj^V"BcS:Gを=<^;Rn]Jl|VeLL ^V+ůl"hvq?5WsmrMi/󘮦iM (zơ8#oqFJQPdG8;OQ^Z?jt%DCE-:;;c߻cǎ0T䫌t޴%]m:OiBX0CDU4GVG#*T|"M!Y4M$gnbO&Ϙ߸-A%Lf[ʵ4v4^+'i ;UCVy;霵6iomՕti2E[wT='4s|m'Zi d` A2*Źx,yѮ(d(ɌB^0EiNDNɐ.}E"h4T:!YO(TSԉөnuK@i2"(*nn^d!t|n \juLoFj+.O'Tk{t}z,4YZ=Cn~*>M; T@c4GM98(ddٲW k1j+6a#dx|DT&MN%{;d4 0jxV%#'Je .D3UmM.YT2DFS^>K^ 骲%<M2([Ar*GEi>ʊߊBn ?(b�\nmI+:{"4 tNl"wnyjy4KІtTT"9ɖx"-=N|e}u d1˯HWިf>ڦk{ez{@UD۸&+g5h S>|wVj)"U]H%nMt)Q ʣұ"!fkg'rty=T:ҥPDb&UÇydMGqǰv8׀5tE$./Gԑ:QE³~u^Z:R@]4( ;A2dtLydegVu! +#]9hJWEIWՂd$Qd;{J5k|,HWQt)tLI>0ewR$"] eB{zr ҭْ.Ya 'uipO!$4YYɜ22yMT VOxDRDF!>!"_rO{zz]HN: ]NH7#MtIoHW,l- HEB8HLZ\kmt%:n"&PZ?ZXcpvqB\| 'ʥ<ҩLy=T7ɠ8iBtҸ."h?*Y.U fobb`em#˫FeިRݤ t)t{mtE$ H \4KKJc)FS.;QMؠ"pÏsfq21!>>Vc:Ae롺IE钵Kī;;Jrb8_+TEs^5+/tYtDҔ{mФR$&aJA"賘 XO!),Y]r+)>$:xA *XFDd[ |Q‚|yXV+6+I侹t| �yr hJ2h"]@%Ɔ @0fY{`{:4*Q.H'ґtҵ[C.}g<ogyȉG@z2odSƜ* HnDeehɚ(r%o^N.E#1f^oJ㦰*ptkF8vt˵mSzndQF4JKcrX[[?CL`jvE 0*eu(#]mFmH Hn'KW{MzSGZpR)QsA߂* F/EbR ;Hm;kՏkZy _MY(}S+?st }J9CPi<oM)UkxYD:xʿŭr A. |n.)*q93<.r+sAK\f2.2QMaS"HKU W#tϟaI881 GSdHȓ.)AtC‚޾xݛ8td?'[sJqa |2Fofj;tA:!hJ'+ӽ&#]C�OH5wƱ9 E< KOaB4g7.^Ƃ[wK]6_1͂R@xEaiǖm*IFt;OMt#*$6;3LΜLnҹq2F)A!SS,b!-9().Q;dH JJJΕt,ѧ-dx!1Pǥ.]^խti1VVV NPpt?}=q1ޏ ̌_GdnWYPGFmHҍtmtJoH~UtR)0?EUњ&7o)}ɭLGOfARt"9նӠhRCrkyq\E9T&HIB [vtKV*ҥmaM )ҭqR}D)Rdqͬ-GAV$OEQa'`^K'%˸Y =[WbT$:VL0(uk8{ZMndQFGY"^9,--+?UbV#7GWw'xs-}{߸w<-_(AUr(#]MzRzBtmtLoHWhQ,_7or7.EwJ"Wr?)_,]ADieXZM]H@Upuj:umfIr3,*,-o~^.'Z-XTT]9H uFR|RE˯-,(lYY͇t󦎛 %"r1/(0EhڦS$Q骂'%/o78?r#7'_d{^,h۪+O:Qfj{mӵս\oZ/YҺx�M`fir*$TNRi_uDF/\cE"ҧXҪ>t6 qb%+@I},ْ9IFeާ @7L/qQ D䄤Zh2o Ko PH[)v2ܿrNjt gqNCUtԑ.-_&:C jmka^L2M4w UZi"$Z&x6&w--x z|ʦ `%DqŞ%]hELvz+ HI k)<Ydf<y'QFƉ?78da gk{ܺveD񄻧[S"Z1 Glt `!dK ܾ]E B6Ei5{@lٱF{ff|S=Jx(,-8f k")9&.YʹxI&Z~v1&qyti]W)$oK p.2+-D(c)`bcɬD<t…gpx{-ZeνpwD˂,ފMtɕF7uld&(#]�i,V4V"u?1[r#H)y@g0{ *U2DyQP(-DJ#LOc~YbX;m$ꍥbzNs`<<>W~9(+JAEy9.钛:n$<<Q@u 2$U$["SE840H)꭮KcV[T@@e ݊gߊBX-*TÐn #|冡8? eũ(AyI:ӽlwġ8| -k0iؽx"άcøuN#2<A4VF5eTD* u۔VҕfSD(щ \[QQfq堤 OvjotPVV'SSX$$�_o8BY^ nV0o/,;ڏXv]pήHO3i|\N46(ͪm H!SIWp)>2mz ҭ 閕#73 ORe,$'15Cphߵ >c p#!я  o{D ;N|50Q ]XC5eԑDB~PGMIoMt[b@'ݧ(Bfj"ғƈIr2q~T5/fY p}Y3z< 0뗭0Nu/0<q�^HEAV \,<!'+y9YJ-݌$x6D*K.JZ>1@ߠp/#%¥pEEi?M^oWD!Ӌjkmʳⳳ) I!ðiVvϪOtus_uౠ)6S@yIIJ<"Ԅ%2EVj#TE.f"ǔx BO<6و#Ga/p 3^Uc n݂{z!q J/S@8;6{UNl֒} YO(ӧy$)8if򋄮.nJߏ5uitY5d[kS6dniH^ߚb8zOZLE!  xn-eS')H`DĆ#.Vt#(N9,OiQA[TX2^018\cڴg?ņ31\,967_ź`bG+;Ą#'#&ᖔ %.nplԁ `"rWHqP(h@ј%}cddɗܼ/dREV[߿^Ǩ9=j*#B9UV< Η6ShG ai@mEV"Ҵ<rK+T-GMA<ɋ0io{Tm'"^ ^"HFyI7/;YDc_x!$ G #0$tr7<ICY|bUj.ggVZ*|]aezNv0u&`cn ;ww=p>L2]~ [7lŠ~(#rtcܼju 3)~pd}K\  R%W<X Oƒ{U_$Nדns[mIHw4i!:&nֆtBS*&7tԯ[P|gZ^OkHKWJDV9q3C@` _h_{kmfn(K*Ʊ&R U x^ҥ1M { ow'x92sB+}[QoVJQZ)$<:e%Hb#nΌx\0ٲ|-+G.]OнkLm,k7c߶=g|vVcmet"և?IG@8=056j|h-eK!8$$yErQ tC]>EeQE@/tթnu῎QV.wA_#WerswǐQ-342NH656r%jNϸsnzr878X2³aAeb # G 5oZw5Yfr&梬qiQ>KP^Foj fS^lMo߆k}:޶Ɨ 1yd|WCgL7[�1`<+/b8~8DLNA,.; 3F&qACc"w>.D .st0o^k-QRB4)YŊK,ز7xrU;?zTc"^IzD$WCzZ<KIPl]HsY4HwYLUߊC(:(3@aSQṅS<e(qa Y.(qGya�ʋ,e(e̚>z p#$EFz;;`Y蓎$a;j6^y |Wҹ >&\c?~3~Ǔdd3Lww8 Μ0x^@.͖dJKIEQJrّ ,]yՅH?,]Yçtu5rmnoy iu8+.!ϸs&";uh\!!oCȎ4Anr,Ð(LB_e?/fivGQJ$'9(͍BiA<#4f ?f?# NeyHAFb|alX.w}֌l۽._oa?`i|;vfBd%"61BaEFO+8K408!&Yѹoq_+D%Ȣ_J> J?/t5.DWJS5KcĴXSUA AW#Ɩ/x\Doxt"opw#GKZ܂6 '[ x8NvCC >9><Ekq|F #{`p�W/ĵKgq�Vo]ば ?D2r@q^#}` G~J̜:?w_':U7? [m0qh?ZG�:`2n<m° 7>dƘ+wU5ekʐ뭶KYD|j&nXZcw)|U%]Z͇H̴h]d'%5&iX]q^rn_N?Qo""ruW^V1s##P/c&H <#uA~&tk |b?φ!"b!6.b!ڟF|½o_cnطvK`~8}v-KfZ= O/ۭ}t8�C ,dGx^ĩ]j~ t?o_Fo>`oƖUsѭkڶiӇ2 ..k-ƥt%RRB+5lM&@6? UENx�nfs_w.�fW|nsAbC⍤`z9 n#1p; B? :}5 g6~,/+am8k Do?;A|CN6>eWͷŻoF>`Vx7[ouFM'W'ٹ AH"w؋v.}YVVn gA$2mlٚ2z+ HWz㱯;ƒ}`}N, ~s@)^+ 8zh?؇C[n4`N=[6ahCz5^eVkZ+Yo>:|>>l۞hqG|̎W{^7v3%sǣg㧟㣏:o:#Ɏ?W_|ESڵA6we=Ň #= 9NMDth0 +_dkt%W%YO[Z֔!כ ]AHW>fy.?䡽<nAiiqpز[6ĜӰ~ ,Y:?vƸFaŘ5s2-'74VF 3kͷ-}vmH6mЉYG%m0z_~%ƍ'2~uZo>o~}+ V7qŝ"/ '݁_?xVK4k:|BM2#R5ٚ2z+ HW:[CjJ7SЯs||]|X53f ~ûᗞп7FAC#?�my [wZ1k7Vx筷&#fom?ݾB;` "6 F[akL dվÿ orj6W5qw?x^[kQb%(+՝LNxdxC1 6lMtֆt˟܀\98;Bg]w|=FFoW_A/}7am =#|ܱ->~>i?iNtGᅨ m}}my5#h;h>Gcpbb817VtDo?F>{5&#{o˜NpxFx^is+GFcbof%x4e7.Rqgpu~d YZ UG9x`u۷oF{wzOq@A(^yyZ|ofV[o[mֻh׶~!Z3K?g3SNpAX߾H ~ ǸB/5#pB7{|Vowgx@pqwǰ}pdn 4o: .66~"s4 -..FNNNӺ:5G&02Ҫ[Er hyLhu5ZP~ԕtKrGkL2_?׫_0(_a<}C|70p�&N9sbĨQ٫z/C~3'cذl6Z]pn0^F{xx-a(ȈAQf#GwǮuS1Ѿ][fkt >}?w]#ct ׬Eġ`|70q~n{aa(eJ!] -BBuXfaq4z= 'peiCe ]AV0|p|t#| _ D᷺Y 6Wfa矺]ѿ@L2k׬07{ksx:ÝV榰4avGsc=</?2׎DNX!1 RcQDf"3^&{G`ճ'#OѦ͇ܚ0v`WlY<f0 1u4ؽM?7cs2p;t):u #9%pҕG%G-0fndy^%<(V.SߊݜǞPu_VJW nPWoaLv! K:Rez+ @>+[@8 F`h{ <\:"ǃG `V7}hx 0ۄyn,욊 +Fc!X;aV͘�H&Y?+NGI~*J R@{?�3qh  Cw_2>n~v޹ql#q?`irիطc;Κmk7msc7̟6.u;7/+)~!0OycԖ j#2\|L ڿnŠ%%!2rKG[W8sefnQuڟo ^!G;;; h?aq6iz㮎ぎ8z(|}}k_O "3Y5ǵ0snNrE/BUꏄ`O< Cmepћqu0xm#ɎƢmZ\eVc¼<*De(/-EYi!U2Q,�WܺzGmÂ31yL7}'mc|I#5#&U p@5\AF|4"`qmڀ⡥{ןЃ;o߸KuݧXn 6 NN6* Qsbux=eS$<Ô`niYuLfi U|H+C7*bժUr h~ #}AWW.\d1gX1ct 6"7_;716AvwA;"Ę&"axnAg(Y4 Ʋ#u87]5B|ψ/35E9(/Ei# gGI#|>߹;Vª1g0_u~%:_}Ŗ9qND#.#')I^p{p7ûp6ANߣO?7[7%ׅ*,] �x)ܶl5G}[plڲ!]u׫CYuL+ciU3W㼦CG%'Qx VСCq j+ *a Ř}hh(_=ޖZMOE|tRU$% 1aCعp$F"-!)DDՖ>myccXbۃF> GLxYYi)̺EEEt(Ȉq@>]a{ma[ 5:})Fu{gĘ_cpbr}Q'ȉqFb<Lࠏ^}=6*[uln*9w+~⢡w `lE:|?6!+Ϻ}r3o䥶ld]l@R919Sյ.;pttaÆ*4h8\ot/39+ﭬt/舱cݻMe%(D^v'L>ƐZ')qs~a98{RNoJ\29q&0kyVz2 rPZRč2 سfe&!*1ܝ`iz /_Eݓ8uo ^=Fo>z}3g/+3DҒ@磘 ~Px8=Dc$3bڼA.+7\N@k vnFZz*ϞӃ}~D<6]aqGmT7 wh+"':1Y(}t5Ɔ/F쨪G[jt:0>ֶtNf,כ ]AκViOXx1׽i*K81栤d(7ia̬X}=]8ZeAj8ZUgʷbd?IBlX�]%ϟ<][7b)'tv㝷A:`.�7.Q&#-.AlG^ԱOMt)YLУwo:t<r’e q~ l)u}'l7pS[6խt5ɦg=3cڟ2ck1`082UH2#G9үsKHz+ 2|ry1f8q5>uDr>ZQQ*2G)#bf fg0 8YqHO$\ˆuEy17헗+frRP݀>,^ڹ3'+}Ѿ=|o>-rDǏ?m!:Зɛ_W[#;9iHgDGyu/KԱKF*< z}͛F{Z'0;fse 좶l<HȦ.`}|8h_Q<8}[j˕_8pH%_y"r h[?ԩ"Kz`ԨQؽ{7_Ƴ>>R;FeU$ȗ\dr+PZ Ou&E<V^^"f椇#1 ~𳿂Gatz=lÇNMx6x7moW^iʀ-lwf&%"6б㧘;u*:].PMh_=f<֭4Z?.CtLbb1q-<Q[&M2+j+2ЃJ ן霔^xBceUU6 J\=..q~N7A͗p6ےn9r$vVQi*a+RKع:F2+( HBj |l `kN,-1H|}Ĭܷ}ІBB~uȽ G)N:8d&2nINFx/\0s4L`/1_vqI:n @Lm!#G矫·ET\ďr}w5Gu $aUeHe``g8&HW@y[o".`X~=ݻ ?,dnl4[^bffF!> &p7[c;b̯xW|>hÈ#tڼ.vuCJx <q!;#"0� E'bټyүW.uqS@a=.gqH8/<KG_e L>dki Fz+ @3UFz7y?1he%]J3Re@<~ Kíؼa N_۶k>~@x7yF$FD 9& 7\sz8s ~AHLBZlPer"Ι4Hj3ss̞7y ^pU9T:ҭl-B&r$߿?x"A4'C.]5ukPY)xQ1v孫8{ٍ+a6d>৮7ߢ]ONJ}'o ]uƓVf6srQ@k<r%]ޓybZ秺Iek.Pt)5(ha sիWc#~a|$áTkX?^OєBrl4"OG'ؘ݆n<zރ[aۦMXl9Ms:gPRTҒb�_TW. 'ѬF%]r_J+ՐeV"Yl&Ze&Z ];^iE366:G/^n.,-.Dan33MD"<^znBaW(|[r4.Ҭ8)h>uލiah|MAB@@�nݺ%K߾}W^OH 4o%,YeH||췢 e̺1xt5)ƀcYr6% dR4*ٳ@De |xyH~Fw/S m"8Z,1@$CndkLP2ڵkUzSEO!!5AtR-?MڒMxoEZV"K1@knn^c"US)C7e(W@ lܹ/=H:p333Np} ⰰ+-[S2IwFJ UrhgHexvҁz#ݘ'.$MY'% , !LndZMA UFo-mmnGU|@mVg;*ZʈWcSʕIJAZXbfיt uX5k%h,\E+EpE HCFpҖQU$_U&],mí]e@B5OBxKݐ?"-7! &H' CrMÓ.AqM=9F^-z |t TU* |+ r*#z']bx9Fߘ. p=9e*d}@l%]E+WgYQN ۫<EX>!ήFYn+ʭ\ڧfx@@@@@@QA+) -B<r}[wo!(8xZӄ¢B#mj2kHWby{/ PETZKZ8@yլJtL ks%%% V.x3Ҡtnq [Qq/\ՍN999 7XIvk6zx9L5O^3]ϳQMtPTWS]u*2 4_h3Cgϖx{UE&?fo͚t7sκ~6gm#؆6cD̨Q1bEAhkw+bpgy:ũt:[ߪztuC>=u&쑤7߸E۷n;Rpczh}C\K3B>"$9%ŭz::t)uC>gI@6C_[DVm_>rn*wF}{m>dg9sCԶsW>{[^^}p/"nRinKӈ}Zl9mI[%W)ѭ+׮#Wt(&VW/YZNi(3?xHthʼ{϶ӧtJaGM#w}zT3N9!A}<t?syFw 6Ӑskt.Xԙȶlа/A-[L Y^ί~ԑ7ٗrrsE! )xZ#}/(i,c#ڻ8uZ'/?. ݗeѽ6=oڬٔGUUUq3ζ>,|#M:M$d?SOjJ2%Dx=t={}xh "I8Wo~͜ 7V9 ۾K3׫<4˲^Kӈ>;~N͏azl[w+׌޲,2FId*σ$Hީ<�/{m>#)ۧwLX!lp,G"cCCRSS{Wf]GU =nrɓ'v듒gdjߵ-'m^年ί sC!~uXFi1cI^t]=6ҭTk5Ξ;/K){md{ a<_YYeE+{3t1#1y,"III]>l&bʹpM˂[UWW_vfˠz1R5KR"w;g>K23#ݒygΊ޾,-GtŒ1mg拉Y}FBwc^ C%ﲶ>@ 7Ѵ,]z'D#SjLۙ^GW.Խ'ݾsGs=6s;?miDOnAs[pXgFԫO޾,-Glcdք)~#d)lAZ+Cn$񲳻DGӲ`p m$ھsg^+m޶uyM=GvhtFi'=}2]Po{0M=3ҭÇ,ՠa R#=Fai).^B%=ԣp`S2YZsܺuKea}bajJ(b51>-3R(ea}bajlYlDHD>w t=PAa. hGnII[͛egw_/  TcKĖԭwrF@Z>7vg.ޡrܸqC]o:Dt ⅷ01fbA1<t XXXXXX\H#H7//ɥUnNN KITx\1a,,,,,,M-Z <u7EA{Sz׌0 AFs+`0y: =ɤˤ`0 #En8..`x2"?+@222 n2..`0222 .ns#]e+gHW?JZC5Bzu0\i ߸ɾx+>;">_W}G3a"]vctvF@lݺSn=(b6;LNMIS ާ/-^-%1OҕeS4ZMy 0eLڰ)K}GtJR^ёcgRdr3\:n5;~=`SvB߼$jZ002"]kjӡ .*o@0e2ƈ^gwڳ =Ġ͛7=+Ȑ+aDAVO;uȌa Ӂm!w(&VH}ͧe^ <oГ^R{+*hn +.y3J<tA203q[xtty/_BxfГOLJwmp z '""`L M6]_Ңe~c9Ou.5m ~3fڭz mBk6У vٛ?⼳\.ĩX [o>Ƕ(-#SS{nEp& kMt9OtitҴpf"M2II\N" \_AԶ-z?'O;אaTV^aG=+aDؿ6c)[V6v*۟wN #:x"HWCl'GCIkz41k"]e}ax[ZVKн6i,sB5HDEtt =]ʪ*K׮S;LcM D|>. #RVWÈtp4Wz s@ _?xV!ՆM}-zyb B2᫏oVMتsngM̤Rvn汘ttBnÔILJy 5 6uTMؼ˰ZVys\r> K=3F C$0"Z&]r$3QNԣO?=.1`e{}.U#?*#pA`I^$H'#/7X_\RB-d^͐?CNo�aYv^+Cˈ&Cشe*VEbrS"l4KUEڍ"bRUU-:LН&C7zc *;L-tw*ܾ# bQØVy/\,< xŌ&2 ߋ\rc (xҶ+Cֈ Ψ=aN_+C|\#䄨H!<gDRjdO:v! Uҽ"tz#s16O|xOwt"Bgma.<ŀh,02*o^`ū%a7`0LLL�r~x啫C^1 ...`0222 III`0ttt III`0LLL ˤˤ`0 &]&]&]`˗b<.`0t@ ܨ=;T^Q.> 228>"Hٳgf]0gіm/*47ҽx2+*¥AT^^aJ i=HU@v"֨5O-PUwo% 5">_k׹pbN>95Ud>}iyjzt^7|EwRRo]]iҝ0ŏ.\DՏ,_ASϰD#Lm+wK4yLI6Eگ `3afc2J5fI~ Q z;J֬5tU7q4T/)%5)2 -ި҅L8 5Q׮I+ ᶚ2qPlC}[ԹuԻݵg/-j\% +ωԽ8-]*BQZܳߋz_9hW|uTOSy/ +$4L^wtFmd^ᄌzY#`b:v8+^S2:o$&RԾ?23 Gۜ^c љ3"_})5`jjVMڼuD'lZjDg؉,.z?g6v -r'NAO>2o*m߹8ca"wGɺʎ(C-#liw15y{ IeCFLzH7 [O+C:L޻϶m;=ZֆmGׁ~*/;vvxFmd44w@ׯ30{^#岐u}ia,qyeDO7nc9 6/HsH??mJLQB&]<¢<;)*ΧGeTYYA7n^[$=#Jqs ݴt#{mtYsD[4uz {=,-ͣs㠓"t褫^Cޣ $( [&#O y^d|UUբm/\p?ٷ?]^yl7/ 3*);VK[D=pD !VYO aUrr(yTQY&5`9/{Mٯ?޶4zYViiŨ1jCLi0 :RF!RUl_s*®8kһx,&ٖ!Ġ'ey 5d8~ǥ<k-h}q'{CyV jæy#0uh器y" Z=e_>gfNyvnZ5閖{ivr/+]zr$ɥsl}'g}4˯ ){Bd[Σ{CuÆt@O`_g_>7A Z=]Lk{md @K=?tIyi)1s4ԣO?=W&݂<ɳKBJ5KzNlO Tiw(f{z@nHGլ~='qL,@h9r3gY&#Ow/iݸ)ka 9`xniAvbͦ-[ESyO9]Lfh}cwFSXT,6EdJ;JF<xCG+A0{-qU[5"|+߽M{L<mڼ6Z=1BԐ # G cZgʉ0zdnl\!6xH1AyΕ!kDHFwgm{פk| [)c9 ׇ\n`7O@#y2굡Fm#M�FݑDЩ׌A0OC޼n06\rU z3Gh&]d?Wl|$Hո(*.xd佹6 FC&ݣ)|SdˤxB<+!a75ٵ@G*BL I׀tcڻw=o/{.C8ؕCD>) VWX Iœ.ޱr!`0r=]&]`eee0 ...`0222 II`0LLL ˤˤ`0 &]&]&]`eeҵ`026kEQuZ]QigŢ>Yŧ0/[.J*$JrXjOZ!]& #}rԮK7}GW]<3 2-$Vй} Wd Խ'uٛvͤIgd:}6UVRUu_:niҝ2}&m!ꔢj¸0|3a6{(Ŗ%, K@g @۶ez"J}%Uk֊2V5zԙL-tՂ:ktQQG0m5k1,QjמgCrѹvFCO`Dnc8ߡXQ<6ږax<o$&RԾk e޽gۿB:x ||]KQ^C=~(hzs׶yM2qzdlH|#9=Lt?~L[wDJIwQ#lIfГOLJwr+jGtG-#ؒxOKT-t=/@xe!B=q0k懏mi;Q,ۭ]AgdV = {efD8e~|щcm+{+dJv۟wN ރDXz?%V39]gHk0*+vx ρ>9C(#35K[DG=#3f-En[Q"hz6BLB5HD=d`¢B|ڎIxUUUY w0϶ 145 ,\pO *eW65][}|h: j<2eFH̤Rvnrt@ v'RLteEW9 g<]3@ʂ 弛;0,}5rѱuH7<tL9ad?ƯQF39݋/S>(/?fmpeI7mQXX([b$Fƒ~F^NFt> .r\u!<ܬvݔ},@ _-HW#B*,*Oactng.k7n3^1AGI#adOwvv}Xxe2"ue1�O`m ۶y43VQQatŻ_ ˜< 'c`<zp apxȫۭc@zrl\z)60<F辚!$S@^3<3L놫{+9Exx`q.&懊Ghbd,G"?yxy_-02`0<LL `eee0 &]&]&]`0222 ...`0222 III`0ttt ˤˤ`0LLL ˤˤ`0 &]&ݖI|^P4?`0tt=BP dt\9fIJl.eE)<TAš[I.@AaMOtW]͝GSVWdqVQ9 #n$P&FHq-tˊp?PlæQgQ[d<,tQ gDiItr3\:nYǎ/F5!>~nK']Ԉٯ?ݗnbCnyEک{OCQr~G㏋Z<P5rexȺP?;xHWaC7b6 Իky fp1twK}z #h*zPLHQS2/Dڷ_,g޽gy0l0<|SG%]D\RRl8I. ص[L7122ݻw+ZV0?-rwz| S7UWEc[y;wqaZUV6XKBp0&&O.(haw\a]]8uZt1>3N:gzΒH#(H@LZF'Inrj+tՀ!;o߾6:yNKKm 9[8nkQϾ}piP= Rv12+r55t˗Hz9i+σg9^niY){}v1eL-tGl EPISPlh?2ՔzXƤ|s6'U ő #Fk`l0Ϝ3~55O<Yt[!:]EVH^晄sp ~0>Խ~-¶2| {XW߼ A!By+{YR_s<t[{ b` ލEXZ>+9Z3EN|ٲ=>+y[wD2jF 9b2"�6m*JlHOFaQ#\{;-nGW\RB-i0ҵ<0z6;c'L2e/�t Ø0ǣt-QSa{@dX`C8pdeLxLĤdn. XBr20 7#]R#;'Gt5cP Bi>܃7t<L tw.]*AsK=[NCt[g  ˤ`0 &]&]&]`eee0 ...`0222 ...`0ttt III`0LLL ˤˤ`0LLL `eee0 &]&]#]t3BCWR|ƻtLx9-^\CeTJ=*(,EwuL\1uy@;Zem늧ې7s]|IcaS{򎨭 t<,!/=ղ$??Veu{t#632Z' Q SzwixlLF A)7|(0m5w1պ&Yݵg/-j\Eo޼a&ka(p1>|bbW^Om˰3HQ  e޽gypU-t{*n ']6:a{>stQ9-#޽{G^5aiEp2SE" {eas[N6<}*dTھs5hiө^Ңe~c[7׆mG ҳ#=gw�)+ ::q0@c|z>qIOtL#qæF+N:{Z`m!+SR=U!k< C/ e}Vt HaIx zXZjsk2+l7x:ٷ?ڝ. GtV'mEHّl>c55t˗(z9igh|PhFC^喖1ҕw2B&M&BuBV^޺Q.GNi|1ezLJuˢ +ImNs<}Ƽڰ9j< =Ȑ><WOJIsˤBI2ƒ<pNNr[9/E]x&V<]G5dah>Խ~-¶zȥFlF捞& 0>1DLt;€EtS[ek7nJUU0|m}C) E@… "4\e{}NW<ԽG>XZ%%46n 9b2hiVf DiivgWIy`m\Dt֡# h' ͤBH> N Fno'OX"]GJo%ög0KC:(!r$v%CG/cZnvtMJp!G7xH~3,E[`ANə-dNf jA:-=}vt&KWAqD/БW=N¤BE*<022 III`0ttt ˤˤ`0LLL ˤˤ`0 &]&]&]`eee0 ...`0222 ...`0ttte .GnzF&M2UT_Y>|4>/[.J*$JjTR3ˤY0'gWAaMOtwK\ΝCeTߌbU>3&Vй} t[ >Φ}xxH2N4g~iҝ2}&m!ꔢV(j¸ybcּ`OϒcgZd%=g0z(ue',YI))J֬5ͮgm ݻe0!R~6emk^Q߷cr9ѹxDQik$vuSw zCOE2 `b:9S,> Fb"E/9=;cXo78cN_qg3ҫ,@"$c3_2P*+M. 0<qtg  *<m:UUW䢠e~cӤ0?F4rwLy-znIfk Ĥ۰pFХgoqO`sBօR]]8uZ5amضE!LzzJl"8)=d4`'E`t,_AL'#z&BҖ-XHB.^b>+?wN 3LFnאaTV^aw%] e}ty-z$]Wm^L gqyfuΑbً/mQ<rҚDCFBʠLg~a!$άgm!۶sW*-+̓xуsf2_?KV(,ΒnP-,r&]>9*esT}-zyb B2᫏oUV%2Bzf&0ssZϤۂHwԸ h. =u! א ]tj}V\jta{ksftKot&?Ưzh:LD˗(|30As,`t1#La`Ȧ-[E^Φ'rSȗ͚`h`!i3YEKtlWtgbc0'x +W<0z9)a$ fιJhuM)&h*R;`u+t[ B0 m)`"KŻ_ ˜` Kxȑxqq"φ>R 0hj Y#B0;Їm۳%j@F 75srDx^3GG:-=ôιJS7 }Źt'%[S7J}L-t3ΡX |`0 wIIU"4|Kc$+^1 ۸`022UW$`0LLL ˤˤ`0 &]&]&]`eee0 &]&]&]`0222 ...`0ttt III`0ttt= xˤq ۛ%]~zP¯ݤ;!BаwQPo%ܖE4}(BWc&L+׮s'a>:TQ :׽O_Z^x{<&V^dȺPK+CB-t$eG 8lPS&QgQ[dJ[<,>r,^AFFC [xf]}NJIPw՚f3̤BIcD:gH5Kepnn4)?\EowQQ/P (:jRwK}z(:FQNZ:}1jStj=ĊT?X=gktQ-Q+Ft :Fw#QWyA}_x7N@{Hw/TGϑ3,OO%1ׯ#n+'ݳӂ%K-tz'ۖmIfГOL*@+OՏ #;n3Jcnq(|~(|2|{EAhz}cEg�A]?Vw"f rքShmzTY`Q.={ ҃hWt<q0k懏m;d(JȤwѫWv+C4IW`xB̊~^HL۾tL#qȤJH^nt-+g̙KUU}R<z?y<(צC'KFSCey.EȀWGO<1<ץ+WDHҕv׋ZFs&]G=]¥A#I[RvfuD뾾xS#'H Yt xeeI7z QGܼ|ѹBn&V@.]",^62) Lo2s(k{ g ._Q?�sV os[<]+:bàb@ B2᫏o`4=Μ3陙{@Q/+t[CII Nf<]c3+.{1C Ë�71)Y紼>mW/eX9[;903rѱuHG<tL9 #|_-e|`=ԣO?7)+Kam{53Ωt9]uGi/EQyc3EN)}X`UqI _Ķ>pAX-]e ?=gkh<F�y^4¢b1z9)9BvZ%qtѩv#VUU�ntgI!l<ܲrAI6A0P"y25cBin; :)vȳ >R hqe L 0 #GkG9[O XBnzmisrD^3 daZG\%[)~ض08n:J0G"x!pRI3 `ee0 ...`0222 III`0ttt III`0LLL ˤˤ`0 &]&]&]`eee0 &]&]&]`02265 IIє3}nB0e Ue Dvu]vݭD.rԫx+>b8}ԮEeƏx9-^\CTB{zܭ[Ik=@HE*<y}h,Q&L(^UV .56<9O_>{&[eIJ??E.Xy B|Qq1[3 SϤ "D[lDD+1t:P^QA em(;`T#I%n6_UU%JPNBԽ(.1#N\XfTսIe�jڳ 5zV7(@.TW\r_#G+~(&z@U5x5Z~nsG˰3HQ =aμ{֗^+=~(thz`+1g<=xI9gQ{OwMb(;z [O+C4^Ǻ-r'NAO>2o*m߹˴'kEӦzIy];vׅE.vQ2dwM׆mP3et,Cg N\>SAgdf<�:հC%WPm+C4贡&Bk.{...i2 ?i+~zރaim~ޟ78z Fey:uhנ.vAR<<5=iF mv۟wN #:0[F=/_zSe}VDM:d_Ix X /I.< i9],stsii"T'8(UoDy|xbZMV A0pVYuۜOWy,{螨EoypFOV%r5""z`m!F" wtI8'zȗWO={|#OHނrGQG˼ 5 Gy_.rEޑ kջ_F0[F =L>|*#" AMO"P&V@< (.\qS٪S<"<oe{}NW遘8Y俐CGb�7E>"΃$U\Rb7I x r_ ΉQbrRr6D3ˈ`Ѧ-[EE~2箒<׃-UW^.0Z{$y[q &FA^@&ON9HѨ[){m{=` ';bZz]l˘Vub'<^Ή2ij y>Io&j^7 )¸G/ m_>Gws X^л_fHk<06`&[<x\o }TJ=bD'N:N{tI&]"`0HNA99TVDr`~)c$=SLL 0 ݬ,JMv;Q_ӃS#|صD 8LL 0 L]ZWth:y$ ~jaee0 馧S}Q5+օzDҁ ^K5ѹsI322  Ƞ'NR ` 0Z`ൌaÆQtt i&]&]`8Aݣ$:{,>}.^HW/%)q$eoiРAtJKKcee0 3+/<Xu>7m1 ՃfϞ-tt $NMGGwEaEi]<zI`0IW~Oz;-[F#;ŕDOC0�ˤ`0 + ȑ#%lakRAAXE*&]`$]^ gq%*l~eiĉlWo/32 $"G0އJRc>= }*ܨ?3f %&&#] Pm mob0Cb~*34_; _RamA9 Sn=S4>ssm2[*2'Oޠ%fJ8^>".rR܂RxC(@E%-TB+׮q@V={nRjo)'WtӵYҤIرcc>Ǥ۔zEvys)ҍڷ_ד ;G( ʨX8(Wv m(;͒B,3iæQ%Q[d(yX*J.9O_>{&zh+ plkVn +}$=zd*飏?]: Μ9Ceeet9ڻ?~ǤTұ{*V7VK&ԵE(@t }$y'y `9PpG㏋Z6P5peWTۃQD!sG=B-p};b:%Dxn|Β~zQ]7yԳoQl] +CОDgh՚k}CBF1Qcn_yc*`  ^صg/-5(LFq8ߡXo�S2UAۣ}{HwmzhZ5+L顕$<x  /nݺE7$ qJN6t5]v^F!|fTQ t!|_-~1ֺUngT7t7,_QH]Lt0jR:|<ULOF ~׋3ymOt3>xFkACFR 2Ңiv4w#b~uX nݩ2n Z>FfΥTcvcc>y-Y_Si,S m$<!bmڨl(K, ۥgoA:HCTUW #(haw^t)+ ::q0 #cvȈQ)ލRl"8Dt}5ØF"<?PT:{Z"]&:prődCVP¹3]B\tXޭ;wxmˣEkТٴpE;Ls_λNUKnj=$0Lp[Go-={Jm-b~4UZ/owDhoy~ihuX}撷Qʹhczиx9~zQmov2SZf.IS1ec鵁Q5=|f]P׾zDgn#o!yx"ܲddi*y\SSx)P#'3f-En[h<�Ha!L,`ˆtW{eeN#"^,ẝtGh@C|YXX<Pdp||U rVm r>7/_ CZ&|k�y`�^Yybv9g!] v2&nV{n힮Z|no׬ w s WHSOV<M_LP| Ͷqb\tzDp7uCD'RL Q>vt89*Xrs eۦt9!c;ڦgU75Vk|A|=^=C{@*kM-ci|}p$nzX*9{iM枦i"dp# *wg9{tEhY:;mp5'=Q3it|.$3<r.rsTT5ɥҵ[&fVߪh|J GTUoҔ١.tiMON$s(4v.Ro%hN>i.9[6R_Ѽ2zQ<ᾇV,>WK^Υ{ЗS@z,eߓ0 zS6~xا$emsg]H_O~W@%#kM-ciz13cߛ(WW%̦&,v &S]7eћ⹂_|<\p1*~u}0uMGi?Ѧv:/h4bf[)5d(}ضg]0Rbj<2Fb(F"eeVˆi~A;%gf[m]o2굡vJ(=.? CBΝBx{Aޕ rWVKRa3?,zh 5W&]ɖ=.V Z)TpZ?&8U>_8<^I^.ˤLd.r)ۑ-qVN7Qum&7DH޽̔9'ͻwԖ}Mʤ o4&]&]F"]i,3-EP-#EY@,b_v}1J&]xIr #V322<te <H:N9G&^**RlN2۵\/( K k{x^yאׂ/湭XZtAwte|}[UxJoWxA,,,+xmˋ/a~1mܧ>/<>u*ɗqC5x^y0F�baq]Լ>`-U_ K >T/ ҕ~1/ȯ3V,, #/+faaaONt9] 2ҨҴ:( %`ۊ=¤¤ˤ¤YRZZJt7ɓ'P&]&HD}1,n7oPRR]xQ;?L,,Lt=J=} LL,,Lt={&ž}~͂vF{!eeaamŤ[WWfi(ҭy+m<ceeaa5'n?HoZxY3Y=ɿO{c-%1iO6JwlK1&m:ϤI7<b3MƟ3mlڸyn5d(}ض=wǓw˗vS/"G_7..Ωz$hgWH7^AՏt%1#:/=OQWkCu^rYhcYzAapM EO*QEԡ[Խ `,ʩcTTTlg?Ԣܧ#ECڮư鵛DBߠCMNiԩG/:{<UVV |d=Qٞ>}j#] Q zY(ݿۿÇv�c>99\OtܯGwRǺYXN}$˹_D#ܥAL[qq1͝;>G[?`><|(d�9|˝hQ2K#pfMAx] $ڷIwe{}{m>_U٥goھs]`k֭Ի@еպǴBY.@c^~=?3ٟ}@8BCC햭[LH =yƏO?hvׁvXp!˿ _1tВpvkG;BO_=R)V!{5&GޡЯ&GSʃRKVQQAn+|#7((Htpp"ퟖF_G؊yFktgLE Qkk4xH}Go�\"WLL;xHL(_|i[-&҅K,Px*Vǃ jߥuM8G[ߣo?~s딗iyFJ۹tooD=C- FcԆN+((wť5ԙBAB3q]DJ+77%8oB ^Vf7 $wH 1?3w0k_{SmY@@�uؑrrr(;;ڵkgw+W:P2C !???c#w6d(ZC;O/Ͽ+R̸LeStz)M?T@6^_NCY%ɒ3g{\gLϟ?=կ~ENƦ&L@Fr `}@:0fZڻ<}ZܯZ4ȶ,Wݰ)C+7/O7FDjaN,L[-) T>?m:t"!h޽v@Vǃ(&>ؙ 1JtAtC+mzftDlFc'NlU!kL8Ǩ I,uG:3GoAy[ (`)?އ1.z]JSNI7OǃOH,e<&H\Ϳۿ Zuu;ݾ}6/gxztl$z𫵟{1{.gUϧ 4mW*M%k%4`Eݥ;f~h:uh;w(:͕4@ ?mhH;Hw{,@ d4 .jzig=x_qOYYm8;Z>RO\XR[pocaHS!]#{hlvJzb?zyy Zö]%eێHd {eJqKU aZySXVX #;:WOj u79[& *r+ǍSnR 1<菄X_cKЫ*A;kݷfv5ˤm>_D!qw/;7S'M$t(33ڴi#˴\/HÍ(Uj߾=ˤmA5W mET똷 o^a_At%gc dm/3wnG. ^[Qz L+mh@tTC+mg$vJzb?:fVOo?j#Ge!sxsEW1:{ aN@¸zJ�9[& rtk֬[Bnbbm͛vjΫwMxdŴhg[@.8IwhR&lML=@eO),,ߧ]=n:WbZmm&x0 BeU7g^³ 16䰔d{N<]s;鞻ppi"]�L#{ȟunVmk1 iW<]kv9cM/_nWMNZ | G?:vvee O.CFԃQ 0�!Ec*E`zd|28v<?{lMRnb d B4`�S. (̶hgrI}d{GĒT(y6ܤos+ AիW{*! S۹sg[Nͳ7~A^6:l�-[(CȵkzfIwۦˆUcOП2a3gg}~J\S7Wi>.7n޹^^dik!mZ"]oo3ԙ~C3Fft nNnns~G6~ߊ۷@IGQ}.~n5m$cew4z9�N~Ag\&] |7>Gz˔g?cw^1h/REm{B??)**55hwgHv-Rf!_CS8F"biwt;FG!_Er8z!q?^+?'z0Ch6@/tҽ!L;ii27o #9JFG1GbZIlxr3iV޹,ohа/W#Ö] Zy "Ex׊=k;#hnFZ!<}pV ?G~"_/]Ne6V8z}CG?iQ@ BcqWfȃܻ;|VKRomj_Cfs(*UhS6HxKs"WpTJچtKw%(zeddN4#HdG#ۀ^A;b:_SME9 ﮮeml ]ܶϧM4s,v]TkRv^#"\&<@^vu$]|WMq։w˞ AE�?B,D*,Ӝ]pϧe+WdիW ]:Dx_rv KC"GUYs)`Hѽ#I=Mw@A&]\-`Y+Y2\r7erK ]OyN]IWЬY%Z11Pzh{Ejf~7GΣkŋtYX(.! cHY/^4tP:{L&=ݓ'O#Žodb+. #1gˤ۳gO1I&]ן=txʿg<k'4߾`5Ɗ ,Y' ;=x+6VOЖr؞I5}]JrNRNv&dSU z[2Z<? >Ju5q2@C|dqp/\ B6f… +ϤZgWkT_"EA|[s. <^|;OyC-vZ"Bɨ_lQm۶L,, e>H9GSm9'dTo߉Ǝ+R:  :>L~!-],, N<ʯˁ_|!>׊(#tYXZ &X&]|Hp!t#mQd{9RFVptYXZ` /Jg̤¢O8P$ b̌Cip]-Vaai"mp!rX2WS|C}W^| Wx<.pnd ;CrHW24,:z֜&ᾧm A4 KӋ*\,;}/ "?c5ieaaQ? z> {,,, 'Kr"ݑENWpx,xVqhXXXNg ϛ:E}Pna-- ˠYXX<P|<I 2Cg p)faaqsM Z"]l N]⁂S~Vd ax7/c0 `0 `0 `0 `0 `0&NZ-h ����IENDB`����������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/playlist-browser.png����������������������������������������������0000664�0001750�0001750�00000335273�14231604332�021542� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��`��������sBITO���tEXtSoftware�gnome-screenshot>�NIDATxX߀SiЛ{oҕjD VD6 { * ({' )T۩wMϻ<egw~SBיY۶&N-у@ BLu?GB @�$ Tʍ{}{AEc @ zZό uP"ei1T1@ ?f*?mޅ;Gĸ�i'S[A K?xܣo/Ԟt9@ =t?a>~D�yA6T> .˼J_X֟}]UC\~g?a�8 f@jgFղr}Dΐg7:ChiW}֢_>_H>߀o7G8>bU՟w4? ooh>?@^ U{t.3 o9hWw4?^m5sr&�\ @G>_=^pv@rpA笻mYv t^AZ6*:t38\=No8QAjE觏w-3ֺ>4s! f? !GU^_pxl�yA~BB 3陋N`)"m5)7W6ǽ0 l7ۊRw^=j{@^7,!,=V_eyg+YX~ًK2ӃqaŒƼ/$boasV䲣+ZCF$ Ds 5&Ŝu3S͵V85*@-]۲~N;zH9j$ofw^N o 6$n}eIԣQӛ[Yy[njb9}#},,.}F^*Y59#h_]l—:gh|>gBMQ_>̚oĺ~e>?3 v؃kjY@TxWO3@̝|#,:S_>!{w>A ǚ#/)k?@^_(Oտ3g@Ap1O26]c[831oEj\:F ՞zCY.D;4q7",]=, d5&ֻIOL wOc r/K6*.7F fm8gv[�Mm*~vۇX_^gRpȲk"uyy/OwjF#S*n?/+z*+f[=^34bLmnZz'iA*KֲXV[e k2/\9ZǾoi-i7Oc[SIIvB2_ߟx+?1&(VGUqur?5^hݵy'o]q]޳9I?~YHyf ~ d|޹O~{ ِ-5WsRuZң\SrA ~Sp%?0+.޵%u$en _w .; zիz*%5jѫ(lo69/y+jMq g[:NkMkهXXŲų_<:\o]s= ;ѓG[.dO1;ؙڛпmy;Fn̿d,ַ꩷g͆YQ'@A+6[QTՙv|}JXcl弪(K|8ZeYdlnbol֤v3]"2QǓStn?+ sU۶e#]믒ό*D=lo:))Z\mD[O-~ E.ʌB�'>+TF>[+/-ˎɾ�efޕQz\\byϯi \\t?;_~SGFbTib_e2aپLn9S%[9*CWgqVc+SSc:NTMg1CƱI&A3Lbw翃֚ND O0o9zף:aο^ܽHGeu "訍u$a=rv%4W|t !wTsߜW/6;NSKg/::#\:Mg\~~Fce0C\?#d1\dj+>`<0ESg(fGMxOi̻cCbB ><Q6=qpB-w W3ogR71t0lQ,g\<{6yhbB"k<iAoA:qtc%QvjzBfQ>qwT=MoKo]i=jDLjD?ݛ"] ›ҏMrYk(C-5װ5ɋg;9K{u{{?<:K{mՓv}G>vL1Owaw'61#_OEҘfLěGPy J7;} :ĢXzс:w>|՗7Ǭ]Vj)Vj }j9'{Ǣ\ q՜f932uCٺﮩ>%Qo[s7Rjhz{{|!Nw,;\ PsjWCq| 3P-  J٠͓s ~>X iѻBwy}a%K{]]|YGM'׏?FG DwϬ)5f΋Ρ.eI}'~b޴T!g6NnAOWDz1 ki8QvJWc7Ab_ Nݸ|f]{yPyeX G+B&jNR6`K :ztM5+=es&Kg㬤kH%}ktR -Lۜ^nSڵșqtFLuݚ1xV.A|cIihnZ]n2nhXOޱRmOM7Aޱgy= 3Hk94t޳;wOj7]Vmz`VѦn 5,rN>rN9�D%rP^=pZ-EgDhj Es&> �N@Rjx[=Uic.Bqqvw%~kjb_-T&NyHfMCR_f"eڏ95gkv<ECt{{iF[\U̪/ur/l0`-xC=PY26:»_s3k\׻}5΅!=x׎agzh&̢ĨeE4m|_k9r�$?L|3{[ .ޱ Zٱ.0^)_w-|ϻ.K}n*d>?5\:|ݤ\v~n',8 BO.\CK-NۨŏsKUvRM�xAb/Y wTr.},!66zuV{ںE9C'n^1ą4[4㗦mǪh,#l郼&<W# j=@ԄzXwpfZO:�EbR/ߓ\ԧN*.uIṛv*ʙAw▖Tf߈ג~9{3ǛE/ԹU3vt#U/7 &bO6L<vqM;K?4k32j*[N\T)utнcm oΫic{o/g2U7|#~ݵ‹̧C_T|`#مzCvpE@ɒqR.R�?2Tgƞ)<C_IJEi½u*�oaC :3lLd .EĢȖ7ۃӣkObla1Ns>2<Aw uث3*6<܎>=[B9i 8:kep!Bk.v\`SYqh5F)TI'S/~VF AlM&k-{!\"*!:#Qa:{}tocKFgviֱV3uOG3s7aQaPShu_ض:nkW[0SzX=:6rsU[ {L ۿZY/ݵojXh ND!·2,/вKt;Y, W@^:Kg.V 8KA8+Z T< 9Ho^}Tgwz͌InG/f~:mVfzggz.�vΕ4_kަ\kerU J</^6Ia'E,~u_/[oZ n,wD ;H;% ωtE27j_ B_rԻo,׍Uur]3[QJ\MH>L<^|{#t#2 m^^vݱZɫtEx"=JYɿKtt|g4 ·_1O@T*?s':bMI|葃MOլ\Xbni6Co g bTʡeWCt "̡";6ʾ @~Z^Ek `.ʆ}mNzֹ|/+'JL9 *cc _,آ @ 2/ȚZ=N3 B\<TfT oՀ@ yֹ9Y6@ z@ �1֖۶7L@  U/BA@ D@ ? /Ala@ @- @ H@ g%^+)̖Y?E}!44q"͙m5}F4Gu Άy/5co4r½ldF鏛FA][_0^42ߖܷ\9,=j{͏8IH&V39k,U'Ϧ FG} DJN):vsPz�@ �/Al A4R^8,Jl=6JFEbJ]oyhG)ݢgo=J/k[} EDgMT>rZzWtt>^LJ@Y|s �AJN "~@ )|aqWp_5UEoZ$Q4Idb@jRW]9RyAru;vjȨL<oF/n#gYb$\"nt*VL22̙P_VZ}o(/bA=r1#XrS $Hb V/*M u<F.3 ݲYK$j{D[ٙrbv{^tz+#sb,Z3&4Qιk" Tq%\G?3kܙ "+ Ą jtoMW,qQR[veS{@ ȏ?89j:KiM-E Σwf5AlyZBmEEn=xL0J]=|v+}mOKv+Sm=Iھ3N&}NfI $oyYwMAT fuŚLIѾCۛ*nVR@c%9It*5_C2hrzѫGÝGM:VHna-m�%&#*H{HCbuO5z";-Mg$M7/@ 0AlcR(>(-{u mS NAiHF\9;K-"菃udd"Y\o'>bIk/TH:j{jn#^Ί2BTiArU5}1Ium*—}F)͹UFBqkf+ler8ZԏS7eց-&HO9YQe3:ؘk"mw ZWfBba+AI*qW1&RVۋh}qx+g&yqT1@ x DO 3.m 6"k9\p)%ԻJbvD9bv':7 RیHfvzRu٩y D!h'm Vi>f0e%=T�f!w6++O:_YZ7$ ; iQTV[%Fo~5O/@ FAdf7i<V]qrJswA\!5ˣXNi}$8+SŭѾҵh L-]:6Li}~W=ZѢ-&K8 r$e} &/STu(="+,y  D3gS*CA@ ' _E)f*Ȍ4#=)My; .{X\C~a 5@n36+Qw+94(,hm|D\N1_(n_|uTVgz]mI#wbrV"EP1Jb~;XEBYkcn ћ1Y/kEk3+zabQb2S{edFHϙf`T&kMwӐv8VП 7 ]w|PAg Fttm-x{>b@ LX1nȨ7_U6Y.:1u˚eR3zVM&hEWUH.=Op)M"SDIFƟŽ^]6t'>4i4xMF= 2J.O((h⺌_Ƭx1$uъS#:=~''7;'ܾK<A+{ +NaH/)D!$I-7rҮE8ɒ6V/@ 8A$KwbqbR#5mqWNw) IZ!S*ژD:R~2x4rMNoK5Rmq#t3H Yhx݉ ׳/* QT4/{E}1013+,9کhXs]"Ex;2ƜDRYpڿ|CWb9*{iYUoZ3^Hv @ /A MF۳`W@ ρ AW/�?m4LO@: B } "@ A5@ @fZ=@ ? /Al@ g)u@ ,<17@ ? A@ ǁ@ @ @ @ @ 1ƠɃƤ" mojdRjRZ @ #b/oZԚ Il E?qeʹڲ'  l _޶-@  o?+a5Ƥ^9s4/?~p>}OiAǂIt7UŔҁ\U᭫pR@ ? b~ ຃>K[}q_~/}u0}B\$PFC垭eb W8*P{[&# 1:#IKJx#)em[^sE jE?ܽTE$m>7|A@ ("dH'A-,^_+6VWXJ ?~;þ$^[Yll)#nֿU&KP'~s)C DކNw!)/_>}<@=\ULolۚނc[iTԻAZ2'o'\m9@"ɥ]t\Al);5u( Go?Lyڅ+<ID1^x׽^,8/K~k^@mT@ D, ۗϟ> <V_LkheR[ʡm>{,YWV{K;4W٧z, U_!m&EL7Se ݮ:%К:re4̧F$Wn_j,îEoDFF>b~(9+iZŲkϾlx] 1/v`Sl㌐oW=gv^ y*SҞ<CH}YTG7 >Vב$U^S*LXͅ@ (܃ 8 �ޠlMi_?2xDtA x mi'ڳe8%ߖp# V$Y(kJZm=FNq\W4:zͅ:=.ڝF~IRT<pM\tԁIa-/{VCD*YI9);qMi,Z(tdWD4VT"ɺ]WɈtZTgH[mx@e7@ "cȋH X@ @' ~x?xĊƺƺ:y0+?4]M.q)3@(CYҺaϩ:%n@o+;5K=u:U:Jlw_{6J-κ{6ZS3ZZYVa;QAdoR|憫5;lS:IlO.nQKChLB>:/lɺtn9sZqndF!ȐUEZ$9dJӛŤ]5ؐ7/RDI47@낈xp8<bq!,A� VĮ)M<x b=r&0Ҿ bzWDmG4-M:S3ٜeuGj7ٹd*ΈeӦMuźV;4W1Zi)'[mjzDd1vU>8b[3T5O\}REg* 9ğEfSI'>~|5J$1W Q8eК򶘋;ܻ y~$'^s!?-vx  8p"^DdG�4d/jqO!_>G @"ZL x niћX7nH 1؋b,X}qCYTI{\ e"snW-! [5YNo7g:N!M>PLzZvLtMM9;6uW<iB9 boy+'U1\ )D i�CY;<^ZSʠT75qQQ23ecCUϳoA-)g5[^t_҄,RX`'ZDn*~V_WifGY-n�xuT\[ʙX`kRl҅jt]9r7j¬;g7mͺ]RtCL ß:ǵn|{K5CNf7@낈:G0oh+#1fZJC8\"kD, ~m{'\<x\_]YZP3gXWO)Z.962Ƀ҂Zk oARPaPmPyt4_^^119۩ڵާ67oj/ SFmm r܃(9vU M䢬˻)ޚ?T @gi.:9o#e]7Ɵvi[GB٫]פ!Rn/`cJz#m̻--?ZX˲ң,Zd4ZnUDUdTt_r׼xKI& @ 0Arڞk_k,؎U[@ XZܻy,4lMF JD,?Aڵ=㒁ϟ>`?3�;ߵkssvy_z'|Pɤpy8gO*r@{\ <gKAAڠ !9<[5j7&g01Q7qb>ߵȗsskII98y]Y%ܜJuޭ8,Z;(Y-Y0m1'YL:zHM]v'O'+Ds߃~dI_6yIo^W_6Rc}& @ (AbpjVXtB<9(خ磀B 2 Hb0! ņt:}n=HHIb+d5X,]ka4۽hX{t8 7`2O{H-.={&gƙ3?S9x biGe?q@ G7ܩO*&~"wKAAڠ !9QyvN/-s!.p<ˌ$9Q{mmY؄nxp k6$IVncn@ K̊8Mo 6Vۺ{{aTf,WOf(>JuNhoiQcFbwGuyݍwީko8:h#fGzƎ+J㱊(7Ck7曷Mee\#'"Aaa;/c } `<'% Ex3M.٘~Xݳ4F荒' ap8Hdf Q�0_t '+9 3 ܻhӦ: 8/3 ֖摫*.2QA$Sy:[b,qUe= l)D6DFK]9_0kۻ΁m8Rk.{cx@ ?A8NSRFv58ET !b0d] k'터.8#47T?TN@Z_PqIWM5V FUFC /&b)xQAH$}@NXrgiKJJJJK߸_:M�|1ĺrzC%ϟ>d ç&]yje֯yNguE=3rG[*(QЊʊ˗Dff<e?q+szoi_ {L_ dh/?rnzsՕsbǨ@ ?N;98doa,^`,:DA? pC Udxj2M[Z~4%#3J\J($'#G]懸#@ j#Cj޳@?}xϙX̢ǎ?nZꚪ;woݾ{ѓ7o^s[Kr* A:'AF܅W_|+у/M̂‚ 2+Gv<gKAA4Z㕫ݿ �rѢH\HwMoC:;- V~j@ mx,K ; 5`1@B0(:H b,DpD#0$H!/8gL4uI:hu21 @,QHO 8D: 8J;b,F p` @^1UT@?Iz_~@vh�XU8b Iq*'gf}Y\RD߾}9ϜJ(Ϋ,S{4IΫe iM9٥%靝ՖB "2 bq�PC�(x2<!WbDX?>fqaTW*v׿譟8Q$ɤbd J,m!`qx HDD!v(ػ Zy txL:y|yYٙ&ʪrJ~_:XdނXU}EACe!鏒AgSf/V[WJ}hi/5T�)=[ JJiT>7k͛EPSIՖB rrr .X}kD�'@ DB q7RD]Oa<ą(L&XP#G'7)Smؑĉxa!"T>YX�'@@]Dkjp|u"qN0/+eŊ` [ A~ g4V$<8bw2{Z=OyXK@4zٙ -qb hWGPy М۷!?L[ @A@  3,::#dԏ!Å0ÈXYAuNM_?EMtifK,dtIm#&RJ D�R/ BD"*fbGBߴ:a6;onlhs_f,Z N1xsF욒|.^>UZV\]S*Cm�5 ZtjmScgvGKYAo :szoi̬XcIy*y0b 5Oyŀ{?o(/Dd/ :LHD #`ep:$i:ݍ,Ut=D@v$#}3q^ۻk(ꏒTN! Zj8o0BA ň"Xd%Qp)ߴq>v:Pfڻ׭ݟ3Xs[ sj�yLihkoi7lRSQDԔ OARP6<hhhN/:_K]86zi>zj<W|wZKiqEU6ShI[_+R|ALnƾ-~B|{f@P!2H#8tk2+'e!6HV q̣-6W3 `PSPe:~:NnVv^zN*沣te$$x%̜a�QG' `Ⱥd< n5<xcC ;Q6ӒNuKDtJpbkmmimm0aUʹjMi,=#\-mjʃ&Kl� n5W>{, |UdF*zYՐ}(*>~o̗R6C_$?%e 6klamMy/,#;!+^bG_mhe2 B D+T5"8ddf84ZXf/3|aaR5Ԭo cfn"p"eN6d%d䆑W&*072skfh YapBXd[!?RQk;iojD s47ֿnko:/S+򳪊^ԔE}U)?77n^_pɈ֖gKۛAA%ӻ wՒ T헟kmﲒ^1^XwkHU67RbI;|L'+[/Nerέh>E+Ae;/Al֚$g*'QrvqG -2& >ޑuXw}id'۠x7 rJlc5\}%@Db^697$FAC:n8-YIH=X $I55mh\U5'i,#ްoIt( "լ^ bX0VpV@bj*q? C^ x!$A1QkFUQ00w2dkg:si֒SBrARzmO# t]b&-M_GËp8!vD#]*""Qw-}zq_+,3pD. "`JrlSc}cm9pWOA-.$άEɉF>wV_~29E <y "4xή/_q=SxRugeiW7)XJ 5l IM\''EKj-GGĮ8MNpɧJ-p)zNIdyk7'+c6^\Te*OľtzI˵7 [Z茺 4I@^$c}vx<Mfp B>aEwWJ.< @~~A$vߘaC0ÅDCܰMYokP_Sn0!a Aʼn&OtR*.F$I gٴ̆]2NYIRZZLBl#KՀYcvh 鹫]n%a6?cYcu[ Kq"F]ˌc-gFYÇ,;a{V@߶7ADeMI,A<?ZWI-yW)?\(5%5ڜRL=!dYyh)99AFmQ28*=4]^1 젓À-2ķԛH;xm ZS[n[qutQ=;ޘm,`,Z7%s$e7~C9>tz4~XA<_g@~M=f=U4j=(7f)(ҡ B ȿ@B,G<><jD% HB&\2m =% y9o5S 0T>ZwX#'NfFcFȈi3ncT%<=mK�7*J"x�-"Fa 5XYYU]8"ԚҦ:<(n9ýȩUֶ0Wf((nhj/ *(a;fenWk~)Xb嫂H Hc5+;.]ĸ uםsb 򾞫 ̔ 9Mne{mmܞ(6&Ʒ|ľtz=E67rȬOr ͤ7m,:l+`t(/D"y> FH `]Q%zMzp %*2c5dIVN&ݘzvߋAI'o۸g{ް^.Klgڛͳ1-6aE[ehFZ+|fm_tD%fvJCˆ p,쇻` X� ""mA|^Q "V m7b[͹*f^*+e)/ȱ&1Wk)M,g|u s~IJrv.U[(O~ī^rA܅֝&#隔v~eۚ3B 5}@T?"ʯ|Hu}x)-U5 :!@VOP!   "F<Ԩ-O4^w/?[iqW^ؚthkVc':p0\cnѫgrn|/ L4(Y;zʭt7#IG #ס�?aVHI A|ʤU 1:ˌ܉8RS̯v[=`tcI,| $؋˸*{'Ad-RzќBKL k d%Iq]6s-3{,:.<8FLqjWe-94֘ar qŀjߜR|˶uHoe B ȿUxxaC 1W:M 4 ' owoy[3Vޚy@p3Ƭ Y;kbW|Ͷ9<l+;k`E1}IA5M1C+i G *80H Kt #XV@`�G65֕< ":\Y=ҞT|&gގ/G2xFa гT|ķ-Ud'=,(O|`]p *mnr?~xq_(I~*M{١qJg ژj ,KȊNNWpۛ|C>2] "빛@}4T kCĖғNT&~5,tVYYC]}[_;_ȷ2P!_*cqa#-uumTLϴ00e%H;??S}ڮo2=ݛ&+jzѝjd4Vwzx3V9r킇^Ιv*LVr_-c;T�+(H#裙YOg "!GEc- jmOYYOA-fþu5ā)]@f&GQ.AyXwi Qss ybZ6A{tnM)8`()e}H''-i5I 빠ߛtr%ogu|G+xל_|&=-]Ws>tHoe B ȿUX^BIv֌'O;iP)k8]~uCs!+nyp';nm qZ3r0/.֋t}t'h,\8zS􄤤Ykƞ?[DD[Zǖ|替qzjȄ+ bCpXaT ;S$b} ԔR <!.ơM=[K_e!̃Aea6(?-Vɋe&%P!_ 8ARX@mƓ{:'8~J=\Y[XuM-ϗwmC'{0wamg;[7<<T9v<"spõsG)c)7HVi5}U"ðX+b; bz%A�MK}qz}ejVjGܼP "8YO߸v. G--:4zMavg9kLE@ O1"ȒaAV4D5-4eo櫓%>:nLCKLm{a{vqF>ܲ@pplns}MZ4oy]fNukj5"+Z_Ytc31)}l8q0aD9)P쐡X*(%X)~77- rU"lp@؋ז1(7ӘK+6la/>嗷moK嚧 $az0 "@AdDGÇIZw27٪ .lkZxwDءK`>-Zyu):6FfFj &Z& vM]|gnbq?acǝ8rɷ'\}''+I$ bI8) #3+5 +1 '> '6 G&$bDd5` AD y0V[8ЀV~޶/g3v(}ru2LjcDpQk2yʎ^~ stv=XYe繀IsN.3FFL[TLABLNjx;9-;F}6C-^is79eV{$ ) Rb&h3WR4W2)/7DSBpP FDn`@ ,_, c1"0 bCX!@ X"a(v۳<Rpu÷8}>}']Y5XDOaߌq"'.n j<٬hqd68<ZaurR#&"ṠLZ8l[aM\nJ\'.2^^lQA�;B�#,DB >@ qA1XA F�#ie!,f3 Ŋ`BZKܶ_R(y/>4]"Nй5Gn}sr,ݕ3l'*o䢧=NKsD<Nl[j?2A;JBI.ǝ7Ҍ)DUB셗9 0,e7XqFl3lY$ FK^(`I*Ȏ*-f[^[K&E]7 d q3 cgzV H ↈ`G xA<^'25/imNrtcƶwxvu;Os͏{uݨrU\:V>fi2//~va$ٳs/)e8uy<?m {! N৲wOHg aG-EjX1"2GvjDF="dCAiIEBM8wЏK ].4~0 .lw2TG e}֎׵vY<Wб#{szձrv8U=ΛN$/4` "5y"WqnWjgsX+N>S\~nL#eka#֑!#JK%0o_j5  t6YD<%`0 kY,H&&)"!`.ci$7@{˹{1;6o*8?+3\mqS[NW(?bskp[aeƽ7mL=cy/P4F>^=oyϹku|Ŗ-R=WqN櫚4[,$ݞZFz IԆ`%- x` ıj3BҡX yāP+ogKZ4z%IOg1)֟VkbihG'{SYPt6&'J3|C$1kq杵dAj揧ٓgi2$7RÌ*JV&c"+-SJv)S,v0v72R8ni$܂  pADGX#q BFU%4]93?y 1&^=Zh具UteAɟYrޢen1U *cYTVUrZ=')}MV:ग़4ࢧ!KF%* ˆ Q8POGZc1D@x'|}O_>}V [R`ACF&/.v0Tf[ɔUYȒHZqyL7Ng |x=cdl4fŵ^TxidMeC"=\TxowpQ<m;� ΣCD .W;PPHDDzwP<s;;3;fvfQKœOk  ?6h\)zh)/)I:O $?RrrKJ�D�"ϳՕu2:' 6ۑȋXW-cTA޾r^Qx[>GuG)d6g2Jً8~bz yVKw.ۇ eyԾ nFJh8MC/jx*"{dξBEEV Z#^[񨳴+d79:R̀ȢWˍ V7Q FĐ!bG $$ {B){A2*tz?}%O }cx Ϟz{y ڳZ?Ծ_V 53DS:3uAGm?[v>K'saXI'[_5g{V$"x ND,mQ1z~ڟ_5?*0-'<VqTL fBқMRWS6srmk7YKy F+)P"B{U`(@,E} &U!|ĞAR$hlD)v ړf9tp_s5)隘Wl g\IMgBbR/^N > 8Ν2VRaT@2 >Hoad^]sTu' ('U6o0cА>$ڱEa019[o}[[/a]~+\[c>xxd#0v&AsexWLԭcGoƶ�"%3qgc[~toj[^7W@,ˎ Yh!;q6A( +Kc`D0b>!"^LIXJ5ƻ)͚t|2;pk<zoYds`ݡnP^j+5֬;^wH2B%z#=721ܣ5j¤ +F2FkI,G[֗ )aD18qvbAyVX$, w,f먿~s`~IL[,K2rʋsǾys.ڻDj~B~CS%vڣߜ\D Fa팖d_v?)AfKP"; 1҈1H w)=+²ل޲ȜÑd=ɠ e%r̋;RL~)/}9zsooEQ<JKƔӂG�JcϜpNzr rS/=~@ _<0|=\<&7{e^+h *2r:e .2cCRr1q|]mLО"ok~[Ch^5XI YKU'hRljkc%-p FBʺbZzbz$amEtN20X_ 2VDC~%vVQ$YB,ʗM e- 7=_i3KWa2tWp==q ^Wq XC"B0L_?$8'Ov"%)t >#u=)`"ޒ0 Vd];̀2y2 11ͻK uJBKfȪs~"'T}Mtr) =bt\nͽlS ^7@sIi\裷Il59�véxV_ \jK+|^gifyҙhUD1E^T$@\ȑɺ\�F$Ѝ~YOduɅ T jc.&[i." t<?'"? |y"C5I M{".2P+ AX-A}JČŬڐ6d36ši`]Z<\䞁2[ZZw U;e2J^q٪R%eJI׫G-_pC}$UscIz`:]jH`: 1"x ]yC!)T: jkNu@ vM@qNi֎g]< u3UԠ%G.g&71\Jw6 1 n& hLr$O1&;)|f_YKHZZybal TiA~bbI W?ܒʸ;@e9" ʹ9 x\΄?"ZD~'%( 2 rzQ�WÛw޾*(+O=Cw^}CjvYI5EtxUm [cǠ#K[Ė+|dGw">=QF+I(H1Wҷds)~h*⦋oa,4}ږCma[[䞷>uBޏœƭ~<#SVN:IvPuo8\wQH#H`!a!FX̫B0# !JYPX }tfx,�N'O: 2?$G++!fUݛbJޥOept` ׍q%h}={W>N01XF)-ȼ26`z2>Q/?v^3ns( QK)7鋃}yu²wyn‹C>c6iu@sq} 22c|~<r)[XgQ6bVp, ?: P(?LFq ٪IEC??1E*w'42-v!}7ļ/թ2ZN,bI1J{] rʹ 19g?@ހ(:E B‰bı"HXOH\ PHB~Β %fJ nM3ijRjpZk/=mةҶ[t]pk7+֙32uZMGA3A n{xI@:xHL>  60bD1eBM`.Ī6<u4�<vN3|[L^iVNqQH9Qh݂R&>g){^3i(˕ e՛֞L" ׅAcPD>20e^ R�߉Ii-Kϡރi;c8fPѨl1}1*7zl'<¨vƃ}lMRA6;'K.dD޵PQݑxT2IEZP$N/ eI/6B,oϿz:ɷ&kT\ } I*ώՑ1q%φCz;<k!Wk֔eD?4F`s *rl]?zpIeB!g& Q]FY+ljA0 b!H $W#qo; e=줝,{[230qAϙdmFκo2q}N}l#ķ pւ &S*'d-QIAx=|Xt/A"2"Nވv+"@y"27A!歾/S,^$++((x]Hm�Ċg[#�d/:ں5@,*Y>4?2 "ki ct@ИxSsKiy} qw`<MX!ZGAU|}{simE9MsqO|̇:V_ )U3%b~%V;ђw&"e˹ @J,1x@U[( S1O-pVw.j7h,-s2a+27^T(pŵ a4NUVAECv̖]#Օ5 Qx;'uҜ#e-iL싆&w- 9頣JbsXGI2+ȯw-CR6<XDX(bfE+H İqګJ \/.lj aoٺU= Im#a mHXNɵ0/FZ?9RƋD4BeP.K)ħyHORcQ KA^G@ caL-a"ߒҜI!ЍX: kkT~mU'HWOW}+||ܙS%Eg!^Sp=+ hO@$*pb3}<v迤S}?� "?a a/B=$+!!5 <I_d,l(PDYU]%f[)KMk8{#da^R95C-1X,ic@2#�R0m;[[]331^QozY]]2\RRy8w@l-ѮEY.{_ ?\޾+3,}@D c8(/ I09 ц5zkq:X1ju2560RP"u6ۑT]j}qd ̈B6TCIq-Ə !WM--.̇fQP||,g o QR//f6Z퍥 \9x$224r&4LT6uPH] Ah!N< %Ha{D`FHaT1f# k5UⴵtDI8}=Ҷa${O֞oF[u4 +%$1dN2!D}}@n߸.//r| >~H͋Fb^KHHٹyzw7WÔɓ`qF$ʤSKul0e՞"!))'X{^@7lӡO> 4B@[\*@,ڴa=,@f>(" aB8tAj00N\ *@Lh>4@x ^OU*;a}{jN\oéoǐ@1k\F#946QVI@8y'4E ~Z,k+KCC9f9qBݺvтܸ~E\\<=W¼ ttt` @HX+@y!$ᗆ€8Py/E'J ¦  �(!kƈɉTT՗1wP쩳da'iWX#6\ zBJX_1" SL6Z4Ǵ^s.]:w({I{-M|^B8zP o̲2~锭DяB޸r;yLX}g~X;! "Bd W@L(/@ ~8A.pN1!0 CQƹACgROYׯ&VC@v`%1$#!?Hb2^bfNljJifO'Y6C#d"c "l#*->nύ=tgF3 hci8dD @VFa9'9࿇v̟;6m$W/EGf @ KbɌ-)'{~I?}Ol[uqkR2kՊe#_?�D LT#"$0I$+ D59!iiDHO(A/z` )E!EaHCo,$$6Tn.wze^8C!ix/dCHE:/10"k4!JfFuwq4lڿ{]ia@8?l>Ç,-ϝ9`"g*\3Q>󶃒-Κ~@;b*s[,(duu5# � B:d)DQu|V X^PX/ I@Xq+D KczcD@b81u1PH/m뭍tw8`p/Oa;Wa<I\J^HL1DU8dmD6A@V^Z,3iclMݜnXj9w- yy -_h0SAo{d W@LԖ6sW9w N% Rijq(/S] ukV �#DX^5VDHE]xLO!'VPOpOp//`*g[Dz CX)%!y^/-SAH^Hho%$$ e@^QVR,G 26$Y[̛5MX,vmp#}͙PUUq5٣{rrlQ Qcdp*J ܤ nEM(*)xg_O/]@f0"#ˆ aD1,$0L$ $ i#a:2XB'D8HU!ai$/ljAXZ?Dr6 e }eGzd"%/0'CMUjqBB#.?Kbw@ɩ䗑O>>:R?|苧O2Kșƹ ^"5|JPYgY< J^CD^|$Q6\VC@~V<;<}1C"$`$zb! A}p p8;VDJ`D&DCLX, ,VE靗 "^g1kU;mxXZ(ARVRHN<_EY9/#ֵK> E[7,ȑ(Wqc{_IiY#擄O�83%+TAe̅kW$0�D <":Đ? =^ )JxdG�'a` !"QV!/Wk)%?>ǽwsuճ0/wf@}='pq~'<\`.g$\OJkW-%``�@@@@@@�!( a *xHŊ v@,)%rv% {H9�QQX*I >wJRR&܌/Rs%E��mDӓ6NTbԀX^\_]pFANbDbaNqo?_J~f QD� @dD) FDee�"+=ʊakUDZZki(+d[r?&}?$|PSSݱu#v-@(IBX T2|,pA30 6XaK'S 3 b¸NeQvjMμKq똛Q\QD� gQ %Dd3VY 8H+À#Kp B¸kZ}_R 9+Epg&3]0wֺ+2 3.!�@@@@@@�%p$ xB8d/%,d"2|L<�&O��8 X(WA�� À-,,:9 ~-)UiI٩K IM>Ӷ+ I �"�DP, Aǩ )bI*V'%zaV hD�� Ben NIHḏšx<Lxd.KOt. byqAnzҟW@Ӊ@"tXzLHBPA28<O u aZ8!42@>D!,+E@,>s}NZbỳ'<S ͣ b2^ 38#iDXx, XHb Dr$n .b�|';5!6O3ZD\?`끎#8\o�˧\`sғ>D)P'n"kdJ~&9K~zR^G \R7'u@@@@@@@Y0Euc;��"�D �@@@@@@@@@:�Խ; r2B. ܹC A� .z;y̛g5?TZjmMmMu?Wœߺ|�"0`?u 1PUYYOgMuϪUˋeEy%9YE_b�=@%|; ܹW-@,NC@7{P�D`  Eh_$Γ"3@Ǻ3O@}i)6#N=d鼺 VUG毝t:ON�r?*+fΘN M �"5 ԍ]Ƭ򥪱AC_$JVv ޜ P9A鯪:9Zx_W3-|_l`X~mȪ.#z׾H:D''@]Egu9Y3f\xڔɔ? :fVtL4^�D6v=J�ĦF` ԝ{ULU'16]o( 5uDd!v3Q PW c]N�qYNNl"3>;M'qEj9_X}D7cHօPcM΃S!Iv#wV÷rʃv4PVO� dJWƪ -5у\G{Lk%-N[" Fc}w?p>;c7 -{N҆zvR1lkצ2#0{j忨x,#Z͗Ns%)|HK4?j/=Ɵ=Qb^ѫ-Dq|�eFn!85a7ا8p.l|J6Vb&i5Xtim=kck5X1?mcv`NJYxvsuu5{_�8EE/NB[�^x3za~n$s4 6RÖ7f+`_o]%ס&hdhkgs0X?o`序̀xkD-Uƍt2P$:M7gqn -7&NNN?@ "_^{ -S(Y:!;j"5`zRzzJ cD,'sikNxlsp Zw7e:SjсtH&zlgg&]ߢ`hE|�bL,7 (e,< >T52|~Cl`+Gs;.}זn5;[ށ9nښ[J>I,o)L|::$8ki~凜*c1O`e^ڒm? 'C *me&-;Fl<RoQw>ЃIJsk|,դU\F{I+bX\t/CAw;Y "6&lBv+7F3jsbmM ڸwSjaDjV~mh(J~t9T!z^/fQyC[lKJ먙A]s?Q>iN #3xbM:wMb.roW@RCC| 9ZɵM %|VǮ3CqعljS}i" ,WAz"*""ߢ+'D o*i|j"+hU[PN]S-݅G]ɧ65V]ʨ; gd0^!Ut~X^ћ?q^DEzxK`N8봂b4�B(OIwn*n'4%낗3_Zݟ.eS:{+INVW`QTf-;DS R2#c^{ɕ#އߕvH/ךd<7mbbo_lW]m躧<ː{/|WSD3++ #G <l풢+DbВcTX2+ R}:xM^s:M>(k-7% Qv> QGɂG J>m@�j�bN#_v@|lkȧ` 6f-ڌBz~֕aZ SL2jge 10, [j[AvpF+@h՟jgD; 5A ~+/nh�ُKQeC2"7#%Bi< wKL=:}g'T(I]l5Ǽ6愶$6!gڻ7FmӜ]hH8?֣w>N-QAJZ6Vd^Eq>[ؒ{BqgǦ8kp,GTĜm$¯OSC(y-HƈzM&* Ҫ},m_EwKl3if5^zIk̿ )gyr21I=S[}`6#,=/rrh_ `,5-O.d,qʘ=v A%a6{f{Q:>[Aq\~mD3MZ·3~1nɦWgg*ybU|LmnZviD�Q6Č ~{4Z*o]<a c\t |oI* TqnDmc3w! W9: +X6"ª"hĺ-n>%y4r3 ay�"Ku 5ڄM m!7x"Tv@lb=7<dѱVs^dv\IIAa^z'n 3Y9 CJRh<7] }譸2XYˊn1Sw669m)h'gm]箒i$SbCW/äKSC|Ԭ)cٞqx -LJ/Q 8Y(?j}o}NHz}+IElNHW]^EaRYiNa*}</L^Z/5&&suwcE) QN*~1 }ݳcSHҼ'E9Z) 3mDNn4Lq"WST,W*f S, >WV/clMe֛}< {lSČkk7sa_H-Ox&>wd_bj=Fÿ#"pL%hҖڦuB*@ׇ^.U|29ƛJiJhƝvpu9ny˰)2ĬKȯ`yG=v-:Ĭ778֟[ 17L ?y"O)F#lފcy^C_(E[̻᫢7?2,!EFylHW�ȱv_j`0)8!]9m|<oJ&zWL)Ǯ}Eҏ*zBX|9[75MVeKt-y3C'򊓵( ܂,q24vꤻi*FJ},ZQkxP@;$XI3YO|&!J$Q6h9 9QL}ڳu5U #^j1AJ2Z};d-|* W*Iv1jʽ=HSʔI^*cQUy{j\ՆclM%DvbDg5w~ÅQMukoH>c`<CXGnldgoI"*ܯh~T;cӶECt Pi,06OfȀ cטM\uv4/*GޥixӘѲbSCI|�y ɘc 7@/+X>RzUGLw cПaYG!Vi6I*, Vk{35[Ѝ~-!}Fˁ2.g + *OPs5ÀX(@cڗ 8EWND>{hUDq)99]V·8dtFxfln!G&e(sƕ<m=#ghH: B}1 ;R%˹� )ˇzyG _At3㡢0󬛜(2GNW@̹"?s&yCe9îٽ"H !<+?@VmD^>ͽ"9˔M&[߼|H{'3Aj}v3RNx8툝䁆wqUUˑtk85Uq*fCW=9Fw"f*9m]ZG43|hLh�W~g>.s}5F"G2ç`FK-|)Y=9OM@$3H[f3m Ϲc[mHAj Gw{c%Fle 80|ߕ1IܻT}nޛ&|*1%Xi]_*$3'-oYl~Y|c-g=cW NA|!<}I7sJZeD }l>qm7U@Нr;9#o.*,Mildݟ0vuo|_ PdY)gMt)L}:]ShrrvWQ}|c/g%: vENoAd`UMJ~l6aX2͋_e|h!AaxpVSV<v_tخ_ţ` X[C9/FLW~ 柿I>6%pݕt٤l4X]r>wQ_W2Z~Ao ړږ7h;Y|~ ciS)|!jS1ג-h%9*iKZD̢$$w KvVt3=7ԦKf'YO|JC_?Ely2Y)g|D֚q77ZcG;))Ra7Qh٩'@̵q@ղ%]׹,Lr"W8D f95nEjE׍}SܛN�&lV"{7ۑ6 >\L'�Drv{Dox`ބM]EW;HuAa쒼 U~x*z`-Ǧǝ-?6然%5n(D_/ϟwݜEݘw1/Z:@d*sQU='^ "+N"{u٦cã>||`4l;3T`^ǰ+ f"3ً$#vu/I>5oH2Ƭ'+ dD2?R[߿`y l47L*N?M M ~ tKTD #2r|ey {WJ$6w/z1_:g!W V%H~UԸ+}]w1wAq\͌J˚ـmwҪAt@,&gGw$fg؈zQ])1G۪*(ڌܸGMiTd%3~Ș̳0 2s[MlAȧ6愶%7z?Ά _3n֗C yWVqVԥeC,A ecәbNk~s3H&7o'k9@Y† 2hXN>[CVE`wHlE:[[rB;sgٴ|)/G3?ZV+..48KZ&\^_[VZNI~έ.7GUFLA1<3K ʏ=24)H[2os"WSGk$MP][mԸ+=]TgA\ /?InJN ;A!�uQ| H@@/"%/=5팤Cr7?uB� \  _Ģ܌3Q PW c]N�k1Γ"3@Ǻ1 ֗Ew5%ikijYB[S~/W`?#ϝ 5MO:^6X{#]I[So3J g-:&:4F^q\3~\0-baNZ{DkI . B&´S_v@0N٭47ʈ~!zd 7ۛrĆoFtB񝩆F_W pFDK:Nz�ya=/+.٩k_$Γ"3@Ǻ:sub3՟jZǩOG&X;:9KByRsgP[skks 'b+T>Cr\fdQNΧ1d\eC7p9c ٯ/;Ikso:qm;т6c1W@]  R: R٭> fhg4z u*^[WWc5;hǂS-WFQpw4  i<B6Bmh(!匐~D5s;AIr7h0ߜJ$y߯0gH<n1M5 .e/ֺ BCƚꆦ_cY_G<kl`J'y\4yn_ ]Yf3y>>wiUp u & SȻZ6\:jvmŢW0q?#bceL#/zo8rЅ�13K�b}IZWpƲZΓ١{λ.15 MC 7@_A{j\3(=9"dM̑ͱ ff;J%񊶡8=̑4_X[�uk@+~tTP6TdUVẇd4~d~_ckS :<jtyJ3; Q2bb挐5]άO/rÈ *2ա7gL}VZ hsw&v_ƺV"0`og�k6YDu/:$%0ՑCf8_4L=IqO;+[;KaCx͹r봠I*Uڥn&Vn#Z-Bl&mwvۛBO.#i#:V1pi:&$mM-ci_#O@r=#gE]zs㯔g� 0`u@HA9\G?u_�=quK~k UVm%rp^�ިT^n{^ H]j,IО/*s2lťAObuNN6ffӂ 6W֝73:A]Mw2�ĎTJ+ Zgǧv͌o`״HtD£/k5J6k0EIݥrN] 9ף-ʰ$xZ_xm9urPjam*1--j( .|m2h> /񊧃߿y5e@dwib)_}:G* >;o2Ŷlg �"0`�WZçw蘆cq_xuVz&s»wOss\̶Su�QHQuˀHƪ @W! AڄM6zwQDQ{jjk:3 _]M 9]ZBljjrRl ')u.d>W֞v�"�D`�;[t]Q!EӞsjbdGڮl ZcITtxz;xsUŭS./0UA;O9&wl]ood]w^BTҍmuSCe9 c<"S5*3ے4w:We&;t(;-$b=iG~(NjQU:rGfsUqce4] PVubcҤgߺ (؋UO&-G+.J~~Ze6 cՈ�ѢbxUe.R\MM<\ (}c?7NG>?.XfQ}pt'M=/s>Ɯ.mQOvkl9eO{8sZ !Ca,÷':&U�bz*w^en:qwXG^'mmNF7jQp78D95@tE>ͣ2%9>wS? ;% |HXuux= oӳ ݕTåכ|S+ttE7TD,6۴'{}Ic2C} 18* 5S$IO*Xr[լ3�mElw;hy_*mh4 rjn<|Wnٯ j W/R/>FSuܼ͝=`XC�\)o̙~7| [`B(>;?;1?c-ykȭ-j nHWp0ˆ1MWICvS|J??0{u�@ �bcIljЋ!T{)۟m6nk/UMֵ\74^akmi ED?2zgQSHx֦.@%yS).п.yluy<t^9M}˂SԌ@g OSJc7"֨vڌ4MHg[IGȇ] Eo&E~OT,7ӛO"-uy�"ԩygDBMFK. ?^M&"Lz{?hk>֜7mQOvwo8XmM;lc4tn5ڀu<v�uWu@l(I$jDr&Eoc'Tkt?/:4q*8=Ո*Cw)2<(z FSJSqϿbvGbMmCn6\&ʃ/7pz~z#oS- }u""̇h-| R4H Xd45 #O%*Lg=�MEEn> J& EWyj<�Wo諎hEQOA0z9 ,~@yȍƿcyh7x8|3Ǖ<Kewk �q;PwUb>Y.ITm3A1U?C-V7+,g}cӏu"h|K ~S"rYDEsȭZsJ%<@6pm葅IN^73"'UL< Ůbu*j!utlj5)a]J(\=kȏĚO{$^x>WO<Ru9AnD*> 6O[voMRio Ӱu*gžכ񲪉Gut@]e�|CI }Hb&jAJQLRinj7X6H.T?;#H3^8@;OXV3v T2x&32oq؅Hԙt#07蘲w[�TVźk͌lB ~Q0x@" ⟬Q83%dDU*}$> =3)D庼y^{2s<cC\Z+ )bf'H3]6j!Gw(Sm~=6`ưlir; n:4=GsMjFܽMU]~iJՉ=U$g$~I|vettav YN`ƽB*|H)D&8$z< %řJ}R; =3.8GIe|~sI*E?*+kїe25T/6%j vcf~^Fl؅Υb2\Ӧwtݍa7[RvyMnTMU4?'oO'L�~꧉ 2s*cfuVTYfՍ!̈DC{roW/=I{uFkf$궻4Lʗ׏/,%3 Sf_ _|CI~! n2vb "Wx]V5 {ɯxW[.g0X:RP:zuqo7uWu'7�}Eng<Xc�S5ҾEpk3-觧kdo$q~n- Yn9lM?[1-s~hj66?̧ `xe}Wޣui;ch#}Du^ 7\zVy,ah.( 1XEk^YJוF5SUR# ^|3S}\sʲv<&geU_jX5tgO2^g]ZIrUK"0e5,sy{t~5S27ԴDڄƲ[hED"Sƣ-j nJ3`hGc5ʘԜ W"h$瀸  j#o[YPG"o(g eFM~2s4bldS9f9x)7w+9Bur@iI'TJV^_RpoיyПti`i@|Y7FM$94r֐FkS�"0`:? ~Zilw>/]: kGi@1~y@NZxc]ģOY >sjSfּ^[7=%t]wT8yjj樃$2`X@ 0`�k늇&~Z˼3hTG[ʐf?mfE!tCZ/6;}qI=WVqIM 0`� 42 ]L\yȖ4f|MӋt#9 In 5buV覭W [qF7䳫%*k5 |N50e = 0`� V7% 'Yl UFϐ-43 ^C?jUV"7kōl5e˲T,G� �Ķf<6l:1qE j J:祳�+?}f 8{~ 箥Q-D6e.W /@ 0`ujegORbR޳M,Fߡftes&@dU{%zȂËh#%)]Q=g�"S@@�D`�mY5W6*� Im>*b5Othn9!ظ{bd 2 >@ 0`�/ޤ V h`G9˚MfP *!fܛeݏ Qtb$ @ 0`�K�  0�m%@@U�;Ҋ?Wu=XL]@+M:Sɟp}mOtt�@d@@U] ߞ^moK{CDAb+iR3 {Cs=e5t<וf+ã"Y"S6t < l_3nNZi4ᐳxpIIω䑲 [eF4}ufƻ)hDf鱵*n~-K==Ps键g�fuWu!@,0MU.? xzĥm5!OD9yYV\;`Sv`Ug|:,dt%1bin(ԞU'o>%C�QQxc_Mԙr?WP^f+(ֵQQ(|)(kWĢ7gH8lB*B/""( SrvXQp RX(R^TTPCvJB�Ay ݙ73<;3;L_P7!fך _bkA+"qz蹻O%qbg{Ҋޝ/ Ac\%�qLxg)jSk|ts?l+",H f[Me_؝Ot8^w g_!S :[/`k %hQK? terU JZ 36TՍ�<NQFLBB˨rϽyz}uyϔ-nZL? 닚 喀TAE\.Qnr38 Zo3vcC'O8M A^Ug=!'!g%8FpK3MxŇV`Ƅz 7ſh a#% 66b d 9Q}UvIjNĩ!?6e�1#Eں7ؖK'QUMoKhG;l^j?ރ dMI-|^cCmα1I9ʞdD/7&sCџș$bn`ZdRW6+%y/NX"JqY7nA2E)ȨlkozʤK0, ˝_̥>${³<|7^ #hd \y% ]P?U&TG0'Xgea%9V\ +?dbNii nLˎ$"J y\UOGRi[JR6lp\·76r̷홆h!"A3;(Ut߿n↍%�73 wmEpbN^5fJGcZmoD)u.9guvfMꟙMX>֧KM٫ݿ<:؜}݌?TH0< Ϋn+h7L6RI2 (VwjÔtAI~T谘'cDY4$A4UO3a㦇EnEpkI}1X/eA5N( ٰsI~~Cx)Môӑ^{sٍ0q !l5@4WgˬՙS�1pо]qb4TWb%C#=)=$*IzVUjxR?:' W[ gShOGt4OL=_pcN&NRMl`F4TYKÝ;2{SwhɥTD6Bu+rо`lGDX{\mh:摂6Mm(g)ڇ7އjҝF ՚IaX@{`+- Zd >Ҕ^|% J#nҀ8*{ҘC\=XįA}Z.s3k#upQ^T Vcn vG[\9 KD7bD:]k6.ɍ^Db_𐻞heD)]ZplzE6yΞ3�1#@ e2lt1_`N=Ivβ*ߛvѽ#=�'IMf68-v%soO?::3^ޖtx~auy {[ѤҼFoSznu*o=ӓy|{ٿwt~vAQ6eܩbL&&֍}xoy~eքUMw lds;0)fO&$W_GiڢZ9Ili,R) rY$ڜ}iCZ :#N#nü2xġ8\,'ObH([lCn X"$\><| l |[ݫ-6~z9`g"&{LO)/n;"-tДĢC(9yG-1y-#v = e-if%)A߷ۍii::QQX*=umm]:}^oֳP uY.%(f鞉64=8wR6}y[(*"%zwŹj4wa8tDtT_KIou=e;j2s0kո)7 ۔Dދtr6}{IŒ@_ N%9gyWiP�q\\OanPߵDZ3=Y<ʏDS6Ds\%4S_͸%0, f� ] 6J֏xRpD^ |n\@,=bN1=ld@:c s^$rwArY^I$7zA?]7RFTdP$x3GJFFB�'O>3af'>z?_ʙtѧz?G멨ntU7Ujioq&»6ƒ_7F}$ƻ;ݷnaA_O\gg7VZ73-lXIޤA#p._MP[ 9xcӘy |^oTAHK{yě*tsUbG˶#G_,2] !(ك:9.G h+x:^hI&L15Kzmnkwrf%lns#:gR9>KD{" w!(_5ⴝ[Ļ]Ha9 2!"%,&�񫓂5J$vq;)QLʌzq3U�Wq~ 䓦h73�34%ҲEo4i ө7U 49ogՑm^R[r:$K*rTK hA%bCIY񇗠e n\sɉJ#[)!?}-#k>EǓ&6&ϓ|{R|H !Y!C ;hoDEsXdr<bޫ|۶2Lӄ'ܚ7*ׯ &_Ǝ胞2myc2 > [5۹tpFcW=>ЍEY/>-<ƽJh)5pd#w<ܙGAl=ltH z\a[3Hܻelbl*mͯ98S<n(fy:Ƨq35)eLy"k]sљ,2e'AIぶz l=gYV op6Un"A׵[z0u۰7@FJ#\Mu{\Km db_G׳)<_#�"^�"8`㬧LUpͼwOYޱH"fűtYM?!g.Evpwk=hM&@hYٽHs>T=eW\G/~ l#|[I CWC-&"f.(y)!?|Lpvʞh/G7k Lf+:P]6t]EaF_Iq9edխ[2o7:說^ݶM1mVc[0@9[E燨N]dͰmyn Wep2"vP_hiKe;o^⿞emLOL[G>$]_;ud]�MZ wfD%7DoIaWxK.;wөT N]i]-􈓞'w]u}kF _cmY=,r nyܜ-DU Lh՛i+^ J['é-LNt26ۦ6zgaPp?PGĮJqM[p(fRU9掞 Ueб({ʔ9D�"~jD'U)˹q K (3[Q}__.瀻c6Mild'֤kՔ$=m0GJi8 = JƊ =|pt2RQ%/Aq,WX؅p5{:LZ;|v ;x{qtiܟII΄Tؚ Wį|͋B#=L@KNΦp̥3\gZqLM @?jRm4*Q6rVK o^u%x|lء7Eȗ|`okT<w/ @ �qLx3G,miT-= ]o3/NXxuue/oj� @ R<~W@@ �� w5�D ~W M@\ �"�P?䎂@ �"�"@ �D�D�@�� �O|yG}teL]7h]֊bvJ�EH3�DĞ>LA?/){luC4rXun׾ %'P? SrK5Z{FZoe;eK->m "z4sU9U۸+ x_q;� П ݍW=̝8Q{ ˜.v~;q{,LVKn�'ǬQMyXg/߹|x ݓQ6'TsT&O|n…_~ 秮RTgP.2 NV; (=/mw�QPmK$XEKtfm{4c{_t0@qi̊Fؘ%ar]szIw{dfGxv:J^@3tٞ 0r"!DuZk]a#*zmxy/q@ߋ0i_zQ묈[m% 8f~g|ïSq@X&5Q;D[?瀻(`Οs~M,w֌7!+ߌ?~5ΏTzSNc4EI^,�qG4v⫝̸\ާ17="yx_x}Hwgh=Rdy68]Ϗ�A? gj?U%@bw+'8 AV۳vw~(9{RvqkL Ѿ)n'pw_d zcUVCCL}Ha MeOkBcwWpiB0^S[rsIJGDy bwk4ejaEӨ&z</rF�N{yI>fމX\(s{+1ە.56`iB'oJ(+Kێ)'`Fy!l#h+^{ΞhG,o{)_lLM}Ï G4v\PfQOT~|"Ȇ[KGϮ'*nu{-7\y,}Bզwg� ПDsDbWZu` yC †ܙĎ,쁸햫Og4͵> g:AmuA(YOYs{d(/k4 qֈ( F=ڈf2p,8B6Ұ}P|�}lXHs_KM""iU՟uef4?[\(~ 1d:HO%})gH \OA@[io'qsZ݀0o#Ð.1݂fYg뻿4_\l)xiF\�D�mi8[ $󨚁^󯿥pF(} ɰYegIvPtD~磕y]Oi*^lBӵ(]Enw('/kѼTI \!Չ2<m=METo51gS\.ޯ7l I;Cϣ #Õ*;9w)++GWoBH}7(iK;XMukq-O}D^b((")N悂gώhk ̊s\S7hKb*ho� @�CS'dWܩ76z*T=YVpDǜuOz[i+J{نWE9/!s-eRFWFbV1"CE-Asv}p#>4DhY- 6�s}yIPt EOeoڥ?fw}.BqU`9[SZp[672E1Iv7!|Μj[fe,㰃|pޝ @ |-9gY'|x h}B_6|_#t[hK6w=ݠp<1loYUCINs-66H߿o<3 ǫAay8YG 3aG/Γ+vVk肭6JIlxS{b/l>Q_8P!>×{:o6ڝC c xZ$I\V_Sr'lժm~ {/Vj�"�t5ηuMFϤ,-̺7P}dÇHFU JjSCPC۩R- 7XXU"m\%#4Ǹy]r}M7  7rIkZaY. f{Rvjћyu--Տ[A4=J0| %1>9dG7rgj +t_J_lϣsFtc_y՚L_r D;?bM]L,Vۋ$U�Q~QERKqHbO\DF?<R^E𴪾ͳ؝Ͻ6 �@#V&ť l�z~7MV]Yi&X:AUb5zo΅Fގ,9XTm69 ڞ܃*TEÎʜ" ^d, Jqw@܊9Lu篻rH#b�<n(ZĨ;;x.{,lg)k) |,9bp]Mo1O#ޔ0ARW[`sd@+qH8E)%ERUPe ;܈nݞf,Q|h)�"⯣΂0.Z+hIPq`inpug#7�D�' >7E9(3AyDv<UVƫ/IfG%9S#�A' tt }|Kg;}|xo}k  8}KCqp|tRXrRy*wi{_v~ԁF~s}[cMK]USMeۊr�D�@�� �"�A �D  @�  �x@|@ �"@ �"@ �"@ �"@ č �@~aʎYPL⾵>mL6?Rʃ*@D�D�⯧G1:Eױ8Ԛ]mE.eـpRv-u:ŋKsGju^ɿfC_XgT(qfMR|TdgIU%o [v\iib~m#^T\4l �  @ >?>N6 :w;ޝċ.>i{jMQU99Y ۼ͌3$ʇ 9?Q2 9x0nB̮5.2[J'5=y*9Tڼ k=D[�'{Y^P'R㈄O+G)^1+ gEwCN\0 ^ä;!}T[q`@lC[ /p6 !=hjAsƺ!WE1ș$&~F% h7<n0 Ț֫.A\(/lIEք A]2ޟ.4d쥙bXl$dx- BPYiW|!%D8hw~w>* כQ=c5CTL˨ra[ǯ`!C[)Eȁ$7Zwi1*kX?PѸuw6'Z{0 N3X${mtUt񶄊1/@H /WA7DKMI-|^cCmα1I9ʞdD/7&sC0F෵4P8m^ylfhvc%'ev@J-tx eG bQ%{k:v'>yܤ'5 }~t_W'sd>)-ɻÞ,#o.aD# :yEEiAƥRa*uo,d[xRpSnx !wp\ 7WSK@U\pUAtOf>}aKEmk6R͈nw%6_U5vxCǘxv~A /UDu,CIgp{Mp9�A �I+bϪ\É9y֘)!&q )k*%_3dɻ;S;ظcK{:>R̯s.KNGU_�o'u$OX#&[{yF08PHE*bh1T�Q|;guvL0Ovk3󚪯9s,ګkq\CqTq/ &y,ZQ- Wi&d6g.QDxg%q}K=<Ghmȇ<}? L1@�"6Bu5`hAJDX{\mhR?uw7MSR74d&վ㽈hAЯ:\_}=`}"d#!sh{RqF*; ]Sn mt9t7D0#p4ulnWvܒ(m}zhu%Ui@D,*+KD75۔JhuHS/Y+(DM]Ƣ7^gw>i.8 4:@"8)Kr1]X[X7)f)+.T Ox2*"@佺⯦4m:dRT+GZ#@o'lCn �7lD'9Jma�0)fO&h$W\^sݙJvwږi #5n2dOZЂ4 =H,EprN$n:s`+%S812mO l�Dy({� � ݼ89Hw?rcA^R$-JuC/ 9ȳ/$4�(Ҟ60,٫*w3& > uAU3Ō6:6UM9UefSL>~Z| ̊˓VDfU="~OQ3Z6^ш煮5_^_[=ISe-%%G Kt\ӣ:^ :H @�!W]a!Z'3=ђLј2swېݚ>J#Fݬ83Tކ^$CAhhp4"3UV^?!4m--ɸhr9ogՑm&,QC؋v])~Q|fa3 W'k"9/f=H8%c ]T^śj}2 J+*ߍU#NXZ Dc]9|2eᕷxsۋ ~Jz˯@GDo鬢k/7q4g{r-[)x({� �$!b]α…ZtE7ǷTi\LMFS^l\tf9Lej>a'6Hos3pIlЅFjo(wcEmVq{Sхz )֫` W(Ƕ r;Riyz<V?P:D~y A,1kW"7p\٩ɺ*#te^9[Xzˆ1']K?՜A`^1@q@@�AbjAt  (S[}{Loa{l@�AT!/@ �@@ �@@ �@@ ��@ D � Bɀ@ hvge*?,}<A �D  @� @@�A  @ ��@/"OF%]֊bvJ0{k/*h<s%<<lI& GߠB!�A[}暨)!b~Z01mʞ�[:i}cI]|DBa~a@ij{y; ٕ3?|n ((9p}eʿ !K) yT@ApG2nd@;Ug1&Y0!:DڷPud2cMϾ"&6�A �mvGF3%=aY};EI᝸&;%zD~7vbN *#͕52גlw}ӭ2%֝ԡ]WD�Vni(𤅱^*/{{;vaƾkؤHD %}=4 2�"�"� /6q r@h)4ږH,h�> ۵ۣrХ#MFtz~Loitw'xB:1H{|g{N4h.=j{m�{;R%_ ]6s8x AG>tG/1F�4z.;":6lUӍP-x{œB�*?{gj w[PcN:Y /,wИgΑ\*,Jz`JA9N10nTrg4v@)~wC}v}@َ}^ g:+VqFy#D>4ǭӰRC\1q߾Y1׈)]԰ 9W #Mh{0޶lu͕QnRa<>Ս-ʰ5~Ł!ݝT�"#BrIn7px:[mn2֞]D-T8;@t:ߗK|ؖZ[rÕGj/d\mr]` ecaOMO<QeuY94tOٗ\<|Q輿>nITviœ+!ڈ֦"ą{?ʒy|pǟNG =?AxZ5{ |4e/ql#S�9ӗ.}<y%֋T<)r7- tՅN2ߔPR[WPlxl{qgkgqO[.g `jqu}uiػM!߾w=r)m}5&dxB@ddp6>V9\ϲʍ5U`q,ax/E ?:[> X@*\|!oFخ1=o{n*$z]H\賜f]b ɡt$?=xJ3H3K-Jk?",#F9+t`AI j%mvѳ3IO}+gdFImXc2phsn0481%L[h \)H@d.;^ ϸJųbwn�"}qfI믁/ "a 298B6$Q4^Mby7i16Y>,-'1qV(ҜcͻXWs^ qG`_K&mdE:[PuԌ2l}�@�'Ib16Pt6kK+۾I# TV&HC)|4:oWzNSbs0YSGOYdNEnQGd́KFlȆ=Of26'|/5j$1@SA 0\3�_g.NN, EQnw>z+}_(t7- +9dǡ獎 WPl OP;%߻^MAHsxsRU{oblз=-5r~?/1 9Cwd/*hD|G;تs;j5|3+.QsMpa�@(#N1KIo>mE6bͺT:쫭ңH+U)N;FD{َW2Y Mgr#܃~:gK֍(z`'wjThY j0,gKJ 4mď <@O +tz0wn"}!)[&zdvH/P})rK\.{;8[/?Cj's ާ ~VDŽ9}#%{o497\/t5 Xa=:�A � 5mD4dGt6Ptٿ"6QDw'J [~cs9kj4)Q***=hvdwoxOgAf O�0u/倊7PΡ]cI1?VfT)vgѫB@LvR&^M11VJbSS בB&Ju// zy|ZCݵіxb] a`Ï TD3+5.wZμmC_/-x�DĞW9ԢmHck;K&#Lg J_f](ܘC^GClLTM0, ~}('iU}ݛgY;7{M4˛8o6"\,y{K*tE{UHvh>b%q,Ln \P]+; Iє?dx(3.5ѥ5Tc/::/B5 qn /n_R{wg:[u/Rҩ@p+m%X3_N8z3K4^ TB4%5 5f5 P8l⃥_DPwEde o&Tՠ$4q~jB�1 _{[@W*2`94p'."LW�"Gdɩ6h? cg]~}COoOGs.4(<4< bPӌ%Zӣm7= mpణ67EYrNn L*hyÙi?&7̻V|Fr=Cr>CmoŇQPנ=0I3]rTkߺlqVcmnd\JhߵPL0lW>"b.ùvmn ( S֞^k) Ys6s[s ]Eڄ |рpa^2A^X?.e"W FcҾ}Zue%LcXWeOBRb "^R9�SK-;AM�D_Qa\|sBmaU 41TFyxЯ؝ @�=n$X3HOK搣%aG.qadzqYemmvT35_#A� �⟨O|iB21g⇜-Tᬤ4wv @�  @�  @�  @�  @S߁@ 4u @  @  @  @  +j,&!;5&*�D�D7ĶW61=\1Ut5Ǖ4Bc5/gWz[iфa`lbYsuɿfC# y�ī?;D)͑LI5ndz5MX5<LUޜe+ycD],[„3tU5}VL��%ƵNqfH�"<*d']@7o{6MQU99Y ۼ͌3K\!@�'cY^P'R㈄O+T PFbWV>D^[2^יN#"ܥ0F- "Y^'6y'h5,  OG(q|�D�DhjL17_I!6CYDOJX)#=,m5 {5(  ;Z6&Ot8^&^\x$V}$Yϭo7a GE81IerUq)퍅JJlE-_ i~ eTp,_{?2Pn_xǥ�$8U,{cj\a&C؈>2ޟ1ңD}bs78:)@OEKc '@6CKJWe7I=^!xܬF+Yf^uўHq9m-" [ Z[ BؔT5Al=7&)YYٓdnhV@DmMb\tNj|ES$ y%3I+*J 2.ܐQ�WqU <y^|-5 ȀSR>fR>U&sd>)-ɻÞl9 KD!N^s7 ewzE20ÒҜ PNgIb[ўiF�+bDjң3;(U7Mܰĩz� @" =?hJP[9J2ʒZ1I榬ޖ|yx9, 2-]X{˝I d\7("Yݜ^:; D^1K";0} DXDahOZX*xL^Ep #&T<;K/gRGtk<\su9Ue3Vi L)aZHN Ffܰb -[ 2 Vh ,@$ 4 ޤ2W# v4z9S3"KyiҝB6DI3t Dl?6MXN:]Qs'3(1ieK;^Kޘ3$}h̑y5p{b@DkC\=xJ% !w=vB5uhA8,߻)z� @0CɎWO1ĺ$75GNUW\[V55dUܓP  %*BYH-c& Djh'b8#M1VT+8La.6g_AD)2lysscRazWDelsV%ZoQTy3y<[�D~I%T%qbI Z/׿H`!z`WzĂG) hg_oyu,8cMd#sqK"gwRS8ߍQ4@T(1l4J H+a2/K"L~ģS̒W~ցhIf-4<Z�D7D^󼜜g}؈^X زҨyT5<}ϑg6da;rbhXN?A BWq:W񦪺\*RyhU S$ k߅Ҋw|Ոv>T~$ tVQI5Td<* *L~uR&BbvQYiу[Ž?1w,q|vNLw67T'47E9ZrqؤKt2j4'BnPM�抽Ҧ?.3DuUǽQvӸl1K&R\ȅrߵ7w֥ nsStf9Lej>a qL,nyz<VuP: V!X@y݋7:Ls_6͍"n } a&CKi| SNk-5~l*ak`y^U?zT{tٍJ}L<w%j{K.{#x� 1 @ �"@ �"@ �"@ �"@ �"@ �"@ �";]``````S�AIĂ @M@&󷂁M@&#)iMUwE~  �@,eWgY[ZZqudOCaYc%]؃uv؛h E/z_q �@$e,C155>/6ʞ6Qv%-2l<iv]s㠡C&tXl7a}hY0dƮ#{F{ვXGB շ]s9Ii.'mL~EM@DnTw)C% !_.Vv;sUՕ,TZ6=2VȏMœ3>(V\*pv[/r0J/+QT8OSR]R8d(YJ*sfDg%,6TW%͟ h=crB (]kM l y`sml=ðKű" ZAȺR֏9s<oHǽ&n[Dv# Hڭ f (8ra˄u'10hIc02%O c=}omZ-'2!!lYd:vuo{0zse2WWTqBUr)8a, ×Ske t2Y׶<`A}&FF\>HV8OSAX|cm]-mG=*rK/\s]#qZWDMVxq SDri~0gB�"4)pU\^bm]M^Լ]:d_Uw~~O_FK&-5%0滽0EƳ˳ď}HޠFR,8ޗL=/{7_ˎRB*jaBglRe:ӰQ oEõLrAOҌ_!~u_@(!Qk不&m$d;=؃5[MDJTOlD{ h©_aXbLԐc4[Plld|(Ϙ#; 4f#5QQZt( _:-}܍}�mxZ0qKuu&SW^3R^/pµ9 0S=|7_nk=ViM10'7_!YvDʺ#2`[H&848-β 4O}NH ǭ==hy 9ژfi1~(<9 m0+j�@|&eDV̬O [Z=^{+jc׳^5&:ۂ@ 9j)t_B.Bd0L_*WWa|?-ݠúB<prXT߳5& r! o,)=0HAh&KGX:aQ3zb֗JF̖ygKvnF3 et\ [}]JZw?ImC\_ԯ^Hۏ35(ʐhnIuUf-^J`sc BpܽB"2#WL CK e3Y45k KcFV%Cq)p/HP8zou;A46dk3]ۧ +E9x噽xe-uڏP! .h7p'ZUDJܟ[8K c#ښ0_ `nE|mze8sŊ@�AIk[[[*(/-+y[]֊&}yKWM*f cOtuDeg*9 eCRw,RI3wVaDݳStZ[2u.9kD4[(g+Ϻ_}5J-mL oB칹{azJ.q9s=楛Md2*n۽hG+)\[za:}/SD}pq=ۮ^4 Zk]ѦʎR"y&:{c@s0@] fxិ3ho]bFV;:c2Ʉf;Bt ) 3?pxYe2@Ƚ ~C)foM=_Lu9@`x6Q5K_]|~]ifTe=i㰕 Nה=p'ZAt@b.u+RE!q<*Aͼ8sMg̲ivTKQg4;v"ܢ)�Dhr�qM܀b{;Iu5v~qɳCn٫~ezoQC |G"]L�Qη٩{ϛCVrf%v<kgGTi^8$+ЖK؟ΨiDkR HC\?m>=98i\\STeXaS"<w遈طxLBMuv$9缋ͷ!=~b_w=Gkm1vdS,dt/!Ь?X4!T ↁ jDut#3HW㳃Kr7\qT&9 7M2m''2/!2bg\Ǎ(Y&.ĕ7,\NQ2�GpEYXԹ%(u0NQH5k8C*V4>Kc.=D`eG\+j@&JY]&;::*߼yuu7lߓ}}!L}<f0/h<X!D~rOH^I6Mx&< ƬIuQr=ߗuB=㟏ծݐH'ahuB`sh:)K/T4KOs ;ÿHQ7ʾ3^"`#[3꜅YկTdxb=ZO}!8̴T(ԅ4Ja} ՙDve @&fĿLS%빵o=" 3cěKF,.J4Ӓ$9, qvrr)UJIX,"mө@Q-Ow[N8l3GU, 0nQHeBtgES=YK15R55Ð\5N� @wHY˝'n >P߽U'OeݙG"[פ/tز"Ux=O<h[tf!Dߦ $OmgIחuƐh=}b+ח:$7EjYE;;yd&b>l?>=R'9&vNύ$Rпr9|CqtC3Ƅ@0H"OO>ߗOh[T}VJ|hkdD % fE`0fvV:P?/"Xڥ@q)t/HPD,򮳁_ϛ#Ge@q;KP y2t_b䗧Te-Y?1@4mWvL|/:B&\ix%[RfxN#:3 I^RYRR1OYE@�A�@){ܜ>^h5Mu_BS0>E&! 3=g3iۮ­ۢ._czIM@3Un EDE^緗݋ٝ?uv>'z§6Lk%.3�+}ˏv-^x}&!]?{cR( UBU RTDE,(^ bWb4 *])"(Eo6 "4&3g<;3w{v"T#K[ budۂ[Y hg_mǿr_1!͵J'ފk_vI|eD)x/[C,=N)!. \JΜnj^Imv _# %'V ; cFVE/$u?;S|t2PoC+.XM2.(p[ؚnc]2ח kTxE{}X5Q!R][+v}4V^e4a]�=/6}Spyt_lkޡhS=Lrƭn79J@Hn{Wt "85}S*ܠ*x>yFVEwlUS! �[1~֙w/w:>^}gOD֍x⥐cA!\e^õu;f[׾Z' % MI<{_̳:MG=:ז0T#*R ۡN[OzvH:hknRX9¥9f qg٪tKڻ߶ŭw2h:k_v_ Ag< '7o-8dKك0G]OP&4MX(S]\+W~ٯE8' pcF2>ܞfB *km3. x:d`7q-\8錍E_ܙJ9(]QAfn(bZf5D0UO=O8"#zy[LBKc 6Sa<tۚ8sal߃4%qG-jXvj�~ ĭz?-ޓoOl[N %]La[wu+QwF| `zA"L'oRU{dԭ&bcAmې"�A~zn<)YKǔ` mA#` 6`o@bll-"�Aq 6` eA"a 6`o@wb3����= �"���� �"���� �"���� �"���� �"��Sxɂ2T[qS&G1�Hy! G1퍕j+=etwmӑ <�x'PWDՌ{.8oF1;VH@ NF !nl2e9Wa-=?3g"�LQAlʻH<k`~oSvDv[Px|jFjRDf>cpNnSz8 qѐo(^|:"ν?q&D�ȫ8.QHdY ']UVWr" /7d_5'j[V?Q_!d7AZ`iJ Ysk"\HQ1^q4C 9DNy3ʐ܆!Ҝ]L$n{4(Nx}&|GֵoPD�X^du褏-CD՚pDɨCBZcnlRǼJ87ufVڥ!Q7ۓD\-G7r9ulbyi낓JJYB3P{ /:SYA|~Ôu4Tl]@| q8/J FDyyiQF�SQyewl]ƪ;͔YG2F7V-@Fi̹ਢ3K/޲DSDhHc@]R, <){ ǫ y3ck@H|`P%S6 A^M Rx5$StFQ9iA`* "-W+u>$D^3xΗ'Vk*{ 1 ` "N`2P%}ەn 8�ApjOCq2&"J<ԩg]y<7HfCWeYDd'l$)Ts �0%kܩ](K-BqН`F;;rJyi+FGTCY^s]{tm3,₈hUeGi ѕᦘ <1B]Q IjNð!PAT^Q �Q9'x*iHo8D�KTƜ Ge=zE7dPAAC_Dy9e\HwI587 L^-FJ<C FA`"n:jwY F}4 $1-3-)"'V7f5V2D44qxTMl?{h!2TD% dc+g1KJ^_[My=Oz檢zzɗ:|Y{ NNn<MHN{Y!^,`{ku6?Aț[AXzij[W_C* �W "?դ^)xMǘx=R%9STϼ``&Fsu2gyJMD@/ Əmh;T}m>Ё^]iC knp/@'_er6 m֝‘3 חkg)ʙ0}Mν]�Ez#x "����� ������ ������ ������ ������ ������ ������ �0ij���K3D��A����D��A����D��A����D��A����D��ABWYleHMD(Lw-+.Idk*eW~M?鬧 &&s( ĶڈiY_s䢁])э=5N>sD01ͯ>0G) 14mZs;F-ޝy,gR].}1'Ciۥ׵?~ $*ƵsOã|2=U9WA쮺nA1Vեk-}~d =]Kc:؊d/[6 >jMH'=lcYʹDDH&v^SyRETUeIhU~{鑜Vᦞq7U6cizGOXCՏt "}/6 ��(D|!ŵOやKZ[ZZ\zӄB+:߭pKE\2C]ǒrc6vW-&DN#>-֊>^J4q2^tёwf*N ;b֎qޮbw-[<A v`OF4<z[T{u%D+6*9{eX5_O;Q-SԮ%*K 㭯%mY-s6t7Kuه{$DiQ8!)t N)(oS`݂ �b '}WHР%?#<M~?KB8l|o3WsNB~ϫ2L 2nWt/3kٌ3X"H6wYmɽcE@fyYןJxQWЂHoBR_B.svg$v~WK)k:۳~cFoHfko~wUlK$XKYW7vk(js~ B}:9bĮKVWsVnىsZs;i`$Iskf~IXBM;"aŒn͍BtvUK`Iΰ8T0;xy"c-52Ea_d:\ꪺXYa]wfg|S5օ-M'CƿʣT٧L1cq1[K~s{IA` 6D{%8cp ̅p o|b޺ 9sFYd=٭ 43쮾+U"ؽz"ng_WV2fu~M١jQ皪¸KjY=ä+i̲—앑9' ;Dt#Y}Ȓ,,%o|/hvt"uki$O؇ʆƚh)1oRknZ!$hHks~VGY-EWW0Y|rM:}щ Vˌ JxWd e\<lhrq7,~#C&ttn7 =US1h7 bv,=\Q*C*Vz %3c9rcVU^)jH8dlSq/mDg݆k̒|9*=T"�LMA|~Ƴ䬏ٯuBJG=Zy!תdsK\qw5O<,㭷֞{ Htįi/X*'u} 2S^w]s˚mKjAޑ& 7$~ܒO1~v TV)/| c~:ڳAs#.g[aXbW`IJ#ߘu]zk'~x2 b8 犓:uBE,x; bÚbIj^[s2cvDYGY:ctXw]d CUWutLpoz 6?>k%BGsny~0U}:kȊoLVlgqDeի>QD Gޫ_ Dd.8LAv_zr7?D nT+*L+enRrx–mY۵VRs[VM%y$({œ$"Ah?8c˖K6u /?. $C=gݘ3q5EP(̊Ek70.=MҘ<+N{-/Ź'2ux!�rXt5$p.&Jt~[P܏7^jM쥯铭Uv2/8i.8Of 1"n ׂ:ea;|rOq#R_pW;}MX � CD)k#F;Tm՚E&xA̳hw<[>]iAtS+œ$,l{G GR;rI 4 u$AЁ 1K;Q03KvÝbA]W,vb/v)-~$s{1ĉ (8+Sw2Scb2 / b{? (NjA@*k$7gkFb|̮h "D_)OA� 'w:Z Ub_KƿF v|Q]l)zNw=PI<smkxȧq7lIWח s-S+vr")Z'󯮪6$Rq[i聊}#}_a7jw[f'҅~xSC sM%J3qD37Rّhq$]+!*uwhmzd _zG,= }ѩ'q4.A3F /BAa"}[n1k]A榤(/k,}Uk}W_簵2 K}! ꪘ)CЇTw0EX^[%7)WMzHeO;!Q A+g(M ֌TKھoCm v^< ӈsΕv>2~k|,bf'=8aks`W,z-wZ_VCFн$U$2?H1[[*mŽkkTWA3Ўh-wE_^5SB| lffegT' Ǜev7v\6X]O}:2%%̴g'4%U]--Cv:MɎg{uԽ>RtK̮Dx � aʚy eD M4f8copj?jAVV1\xK> /(~yxnayy|pړIMæޖ,5嘾pl^sݛ[)AR=2B׳qㆫ`tĆv?.} VXyl|E~Ww1?vyxI+G~4$`,}9W9AkͿnLy qD~?9n-XצjjZx!hb*  Y<ns enفeN' peAz^daDM(hg.t%"kpxֻ (Di/D I[fknɮ �0Qb��LVqw b`���� ���Ge�/0 ���L �yE3�����W=�����0 ��� �5x����@`n$r ����3����)fb���@A����DD�)e֩T*j}y]7Yp@++MP}Joa"s4("�L)fvѣ}ZDA'jv3D-3E!*~4Kם^4)<屇7G|k~rTژU$g⛋4 8b+jwmP`aXM~88Yy3ٹ|Eݷ~XS\Q鎛NG6& F&xy sN?'?oX# 0D�)?w MRk_nwlhdBr܃uǦ1uJW߼&.wc|5q݈ p}oY# 281G63bw}F˟T& *c(s({SYYMM\ɿ2OQ5mAIWO AeCHDhjd�M <܍F&  s] Jg'.Tz1Ga=:�.5d_5 -_N9IQI4~D YzdCN�#*gVW./STT%R?'uQHGV]T8_P7[}:B0Rc=M TIc.sz6,0.b5S27a`b5]-\ &hV<883A3ٔmIBp! )ilLH(ojiZ>B#؃X "j@?G}e`=pw",NdI-qDqFKjFq JnLk_081q_ xBww4.egnCDDDZ2|Cx@n|-TCS5,9R"�L)fy+y `K'CRs ?o6%3'ՉHQ /cX!ntefnŋ:S Ңn],f "9ŷ(+~*p|~ VD)Gg;keQEVF0TwL,HHS]r)G.89 SfW#at/$CQ̫XIS[ߠ8~1̸ѝ$YMTnqckF7-X<B3 J{>sU!8~l?˩c=/Z %yXs mC,|A;:ޕ"O׾Dac 6/)D v&-SbO |4o@q##0~ϣ ~Mj:J6ڗ?%V6]U4@`O1/ʘDjx b=U~_wӻ+{'];StF!̋~)"a۫бqC|mEZ e&yEwv3/c眘E )a1.bȶ1 9M锰5ͼ4*n3uȋë& $">u!9߅6'ne{<x "mMT0#iWZbOgh!F21-1ΚD7\)rխ<K+汯qaXO^^ockyy>} f A=8�kHo^CFhY^`r9fQ]*`7"�DBK?먪b:D\p9_^Xe=0eS+e$^UuUE'l$)5%X?ߨA^4;ϜxXOg瑴}bk$QEODdA`e J+܈ɫa,'=_SЁ'K[U>]A@\dmDQQ?I[b)d5- _A$+y0BJ+>V1Db%o!Zݐ^ GU\)rխ<K +汯qaX?CH{m3C?7}D/# 0.V]U53Ry [-:REæ D�S̼N4\O!TGTCY^s]{teרu)/S1~82AlUn&;!DUУ*Ū^NUvTȉ]]ɕYujuVd='螑JS�PDsxD궑 N] AZ'SZgSdGŜ D. Jnk_vA䠘8|^K ƬC4S[] < wD `w^uֲ )aeKCS`ç D�S̼ '@|%WX%ېGྨ0P%3,gCM1׋l)* QEE@TvLtr+HwUUwqʡS͜OWz~w]UDWO�UKG~FO]=s\3Ť>3GĜ2lΨR3h4(!"C<$-Oe7>TxْAr)f]))q=R{Y4L/M9'g#ռfIA=LD1Ϥvҝ^FT; D�S̜׷<5#ԬOuƜKimɩ7B>5!$3?1-N}UA1/=Dy(jVDlF4{)?-R!覓_X0>kz|AlnM / QEVF"*O)d漍zFVO݋b佾F8{MvP6_+/a H–:CWIc]6?sn}GQ3œi+FF3)ꙫڲ%_+8:~uz>Z~Lf?SڡZ«O;nCFhv;/>ILLK9)x͍! 7r 2 '2q}`<ė[^KJ]6cE6lu3nyi'^u u \[yÕWיɑ@`O1W=rjC xwd}:{<5y;^!Fsu2gyJMڐօ"ޮEp ]m0^sCNylR#5[.-VޜJ=ABX_TTMnF KƏmh2R "D3MIװwR/JpCT_Vҍ0 ,|ߟyy\H~LRq{*=*ՐW.եv1fPs/d'(hǕOn`v?{ӥ_s6nuJ p½R"Sڗ( ^c\AM"uq!-aսZKCLQFzMj "qe"sl,|}!-y,xE;}E7 D�SS�ܠ_{[ w&׏ι?A+eWʸF&0Q�AI><U H/,R`|*b,@~NG?tc)<RF~cd ��S̀»ltUD �\)�"�3���� �L1����"�3���� �L1����"�L)f���/�Ab���@A ���DD�)f�����0(b���@A�㊂%ݵ(f˻dGWYleHM7T0n5 kR~<ȏ54-ƅp4ٰP`s dĿdGу=NFʂnXNۨGnd/$aR2ޝy,g[wu .ˉKOã|2=U)Ohi]y<~-*>?BKmƢmآtW[ %U󾵴w!Mp9g? uuZ6 vz WĜXgk"8KӶKk )Ϊd3ˑ>dc,H - ---.M =iB@hnAdtܲh3Ķ*)̎ ZzAۋ.ؓͥuu%D+6z 겸!KXZ̊:7bwKEaPWed\ߘ}ϓOۋ.:R،Oىa'Yڑ�a-[]uYxCB6{k.@%![L!i6?γ|}MXKڇ?M=>ߏߝ+Z[F]6IyuׯIͭm.՜Uzۆ΢3|a,6~Mٞ$lC$M7t‰޽0bz>Zδj1Bi ;+d%ze7gz}Wv"P1BkпhZꨌ_fK=#D=`fUlK$XK{t}cULaCPQf/^dF:심F@A)"s[ą$I w=d޺ 9sFYd=d [He&ꌣVii_zB2QP]S}Ў|5A7HfE$)E{aqY|rM:}:zZg#%Y=8]< PXS0"D;6iY$W<lhn\͠.o&{۪_N`eFo4hshfYecȜC}]`WU]|(ڇV=+X5eGk N/>ZqFrCOߴBH< «(&.Hy=c*)-#Lz ĉ?Gm/ gAB8A[ V%3cՒnx {/Tu+{—(3[3?'.;hka?В9qӑoLw{Z[.= GRdV!ʎ'ޠqgB)hn]8P,x; Jj%[ފUyՂoC|4 0mٻhR& *'׈v} 2S^wJ!D FrCў2N,wĩ(&,Լ^zdS'=DD`ަ >QWͷ-}AS x/I=e9m`We4A,WO]{8ؖU?ƻQoI {+ Npڲwi呜^"9~_)/-ߖJ *+?. $C=glV(LkKr2h ̭JO9bOW~wϵHK2#xGW1j-k }HX B2A8 GFpD܊n2b*\@=HgwI ""0E/b,;8O'U,GBK/7Cjw"5}&M奄:t8v +"aiF#QuPY8v4(-~$2ҡ]H7tɫiAD$AЁ 1Kڋ!ޱFHK_L1pYh^A `#yV-C1-+D+$'#�Sx{ m#8L1ݰq+J:`C sΗK{?AqAA O1ԅUWlj~2+t%_#Dgya(KwW[JI^}9d7\b$1Ŝ/9Ō)5!+ ktEbN-Lhh ϕ(>eJ{(7Ak\j/'™B_UA<@ ̿X:!iDhZ]{ۚ+^f90yYrT)f [;ZA^fɹIW Z_‡T*JfM f1Sd*֮+D$G@A)"Cr_@ |B3JE&DѻH_=}rkn7QG~}[ *YUC*\TH`~9,zH J[q ўPljtS{%I W秣3H日p 2̀4TKھoCm v^< ӈsΕv%~1Hֲ=~_\5_3%DW9sS2'"]ҵL]^qT0>o_NSw%l" m kkk&vi0s&1t;*YNzp[j2bR!YYY'UdB'=DD�q" nm/XjXklO1Li=?VK k^Zt3?wTC)wps+x괝_k%wc f `O8R~4$ȬnlU!D7ǖ葉7\S̝eϠ1\1s% /~r\[pLqմ.񨏼N_a`knrnlmñv}oLuW ۬==AnfpIJck3(eodf1e~nѶS#Lz �" K[CɈߧUrf&iލ*�72pI�@}]?x9לTսySl_KðZ6 l@�'=D��AHY $S4[ `HmC��AqA�D�����A�D�����A�A����D)D{����+jp7���"� ����"� ����"� ����"� ����"� P_51^:V`C} ,�L�@flw4u*)SE=f`«qΔ%72HVB29tm#Jk$Vp r ΛQ1-=?33VCaFtda*t M�@%iʻH<k`'(9^}}V܍ qLKV͹zý,Ed?rSZE>+-AB[]͛2OQ5mAIW+Pܦ&B7^ ��("<*NK8 +j>3@K'͆ ޶4ih+Gp;^sY%Wc=MIp1bsNQ-Φ<XNglK'Ms^w1=p[.մz2Ag1QYIgrٲ] M: MFK ~2*+/l 8fO'Tpk"\Hc6%1Zba)b$<`%dE$XȒdWqeylYz˳9+#ӀjcB=f)E*"�LIA_N:tǖBjY~8@A6#gUܓvdHTjnaͦd$~N/nOM=X.Z\'畔0<cb6f6QQĩDQ /cX!ntefNI*aw{;P}xA�A6daoB$䞛b}5c^z-y(5 -OneC|̈́̂4%9Ì rd3̊o-QVT&340~.BZcB/~Z[bԼ¼[W#/-G7r95eQ^)i)"�LEAݱE#Sn4SBflP 6z"f27/,YEkS\-K,lA3`Cꂐ!6Y{ ia\/ھOw\yɒ%VIۦ!tyq|b "" ?+b켳f-!?jh})8ܿrsb&;BA ~)+ֻ mI[S0e(<#*\SeWL9+ܯ)i+"�LEA~e T ȷ]C < ژ|:_*s큉eZ|,]cMTu35[6DIv1yuI[b)ސ4 W<27)2V]e5 5I+ſ w58g#UVٙomCX~#NhE\{m:D%5c7>}4YGF&XaQ(63F' 7l$)/#Dθ ^@`JN1DS%r'K-BqQs~_AWsRE|,gqxuj›ؚhO,9Srb.FWʬVIgDzJAf4 FT{nM;bU)q< Dڮ{MGlh7 eistPsP1 qM1aL1eqqrwupG�SR9'x*2iHoD.ae܆=zEY 2Gb⧴ EGwg8xEgT˫|N'gI}gDq2#:'n3bϳ�AZ 47Aj%QsxT2x -Ϣ6De`Ns6 s*L1QAl3C*M8۲S_3pciH �0%[S[w5}λ,Ʉc[(|䚿tTuTMf^`-QW@e~,){}m6qMRL[Q-Yc#%39l/ĝjtX<+'x:#,@%'ѲF_6Lۊ hÍ'`}D"*O)d漍z{~#W=sUQ[v=KyeGr"餬d,xZJ= 6dfĴ̴Þ^r+"6h#K=M}bl#g\~MqWH N@`j "?դ^'X{2}=,1۫?uGWL7hNҵ=[IPM"/{7 T}mLvoj$ { 3ddF#bJUd8HeeY�Ud jʾ#%\CPFN _s9vC˼榑6.\Kʰ8Qo9^]iCu$Cѣ,5BnRbI,h?=R/9SԈ?-7{ `Pt=-q5]M#OXEA*Diʋr,ESv inP< �⟺gזsTzV�&ALW H/,R`|*bO,�""� hw*fdY�B^LC"&.cy<� �"���� �"����  ����� ��� �"=���03D��A����D��A����D��A����D��A����D��At&[t!~inIoݵ(f˻d,?HkC(\X'CW$&T {" ��8>,m%A̯TJn깕3U{Vt }͑~FBF([P̯UuM>b~噞* uBN>QkF:aS_w'wKjyoΈv"-+i} ;t.#G]񮮩|q)+bN5PTiۥ׵?@A�*BR]{o Ulϟ^_p#&r҇HKBsKK sbCz[hEއuܲh3P zd((oIoWW ˉt7J׏jTuER|uITL{EG B ;1:Y;2@A` v0voeP;%7"R2גB]!He&h%aRfY.f{c=ɝ40`5ڇYF]6{^=(cJ{}: !J9#Ä;+pRW%se9Qve)L%VÎ!8kڛ_:ݕ B}"d10+|1l25~]hm$oPWw骸bN2(VIi+_68n=+#GmɽcEIy둗u]y ..E VAR#]حx !OC N݋]}5]r[wՍ$N_�A Ǎp"RZDYt܄`rxe0PBqk}U˽2?TƝ^BWs}b[$W~9'{A7HfE$)Eepv%-L:JuUo{L X}Xgə[R6il~}*x>8=a|M d#ɬʛn Xj5G =RUu͒d|)4ľo^t8?iq\A ?x8DO4hshfYecȜZ. ܴBH< kyZx$c<EU݀<TOy⭇Ahýܨj>oZ`�A0UyŜ0mWB6 ߌQN2cL;o5ZUgCGӓ%LyF^%S@nvFߐ"L-hӆؕģ?zk]sZi??ef }XG1aeX ՗W  |#X=CV>f%Mow=x>`c_ȜpSV^.\(U.)oYCIև⸂(+yD-oEUyՂ#LkťAlG~S';4< -8q5"_od[/ζ4tMKul3D��AT x߇]jڮ5H{8, Lz}##k"Q'ٕ`2hލjos ~ۖU$^.` re[X3PWe)O (kϙo*[~ +fOP-$6 im [e!2xQa2 Sknڐ kj:+Iة8 }<[M%qMܭd{G5gAmyZX+%9>%O|%Swמbq� P5 " z4F;Tm՚E&p~Heyb\m[V-ʲ}$P܇2] DZADw$AЁ 1K;"ȜtdžYᣩ 6V:O y?jؑ4q&koے ۛ_{ mp[G|E«.y!h^;"S)f3nCBAsL\~:28T0|Oա{Ʊ+oXM{DD�q !=(!eޞ{ T_Ȯlo@^! _o=|Yrt,HL~өv,(D;cN3]XR3c DS}L.ԎlgjRZnqA 9_vZb픞b[5aC Z_,)7vk^C)fx&$Qwvy^}9dAA@;=-{k"{_P\>]sw UieE ż榤(/k7q,kkk&vi':GZ9l6sxUڊ{ n90]!|9M=s{__ǗlDϔ]tt }Bz5nFsk,W# u<,C*ov;.NXM6Ҕ6D CoAd5SIGH?xQY$g#.긃C*C l}md,f3;IoknB?QdffegT' o? 73AA@�ߢgrɺ)X'{Q6f8copĻ|;k^_i.\odR?3,Rc`>]CZ/S$1t+v}oL8OR]' )eϠ@v?GjHAīN>}O2q9"x=AdvHFES{Ur#?kqAr 'x:DoK΍MJplmFk%[_[Y䱵񋲷_yS߉4>'8ݞU#|$߫k3D����(]-ˏwb("� ���/}]?x9לTս& �"���0#e2L}k&� ������ ������ ������ ������U����@�����@�����@�����@�����@'M/092s /YPfaCAx < l�D��A^mfvG*G?~{G! ,]w^xU4]pތbv. 8DIb͙ ΈQTl˽RkcVUboGf eeg`M"8<fϜsN'?oX �DyɻH<k`%y>+M\Djn#"0\̼JK|आFW& r2Fz}oYcڗ]9r8 C~ȼdEќG1ܛNDhjd�hTm2""�8O:{ꊨO ++/l ڱ> )jȾmkL:j[V˷Ƅ*�̎=89K =fTO)G4J[%bY }&i YzNNxE rDjd~霽?Q_!d7I[ωF]R$;F*P9mF8`9->AB =|:WRSA#P?\"y s鰡LxZ P97/8a/(ޜ]L$x �☨_N:tǖBjY~8b [Q8P\U5s+}*;n&|`? p.K'CRs ?o6%3'a "+(*GITe\)^@ݞ\/=zLUc]L5t rO& [Vبh8/<50/-b6^xEpJ!W>楇RY#[*nr<^}}tDƎZiAۡ|CeF4f6QQĩD~pee8͹ " 7 gOO3ؙB#%Ğn*hހ ℽxjvel+7č"pA�qLs[F*025=N3%d֑ bs]*bXb<pvΉYTLV Dښ(cur5 :- sV; :[LdAD$X'Vcto)nD(E}%Q;FSvY3Obh^15VR_[Vb{ɑDʣ1 $Ԁ*VCsM[υ3H B7F?ې<]9Qly8l^ocq`\D|((x6Ɠ&@A�q,p?߲Ak0 ^}-k AYՉ>,//O2QVD?ٜ*"j Ye;& &Pz *<`Ab?<N+68 *lHGiIP( ߦA!@@f2ggfWT$!`4g{SDnJZvj+;06joH Fx0N,l6hCJE N],["PHDEt3FU b&8`a$vTWs2 zԕ-4-1eIh)G ;twZn$c޲0VDU`o̓ꈄS֚ B?/%OeotX �Ⱘt%#&SDKC'U쥗sZ 5g] =9)Ng2XU=M*~PuICnt(Jm>u08%f *«ODu҂8rn|F.F]Ӊ(+A%L=:7Pn7CSJsfFt,SL#0#MvԥiIrWe "fb� Â0p6iRg78px+xUP1{ o r[#d [ v#-Oyh| +0eVIl]ͻd^/ږ&< IZ. gi )$`KP\&}DŒ4<>A4V>fp?A�Q^d.ﮉ |ϖ;=Է}pcn8ڜ?ne3"z_ʨ=V؀tD!6V>tQp' 6&a›#9%洄SޖFGE}u-&Yu2nR1Y%637M*"j1hy)T'ƦÚyR)e^ZBA(NDIVŕ.VP&*V2/:f4T1j9 "f؃ �U=Ϩ-yT8q4 l.:zTck3n$:~gVhSȭI<lL̍"XS�~8>Q|Oq[pZ _ʼk $[ 2N17kSi ϫ1+)G`#3z&b'5- { V" *\$'kJc^111æw!G|"F؃ �"0\1^zo|:���D��A騆겂3j ���"� Qd!Ay����@�����@�����@�����@�����~\A���p� ������ ������ ������ ������ 㑎SUJ?BYwj_WQ7'7a4 `u3"� jSYi4>B5/8v(݈ b7Gc뻆S^w v bOkckGX%v@udždX!Ӵ/MвpXs2=x74z?Dd:y}x@ nGFD]  c7;L,ܰGXCa^Vҳ#84|5mwt(&UI:ӍHr!ZpPzz|)-Jeo-o2ByUXsC5 RSN<lUU8#N[l|t6 H qQEFPT<xV(~Arn-�Aab8/0+Q H^?Lz~≏:Z[zFXK'Qxij;Ň.N69'ۜa{Yk#m+ <ׂʟԛuGGw_!)'htꫥܶ좵]@f[QIߗoݍ)g,h:Bn,/Axt|jh38\Iy߸.J J}SE2s+oD{nIm"j@DKւ{wSO;_k:dAsix5u*"AlK#-ygԉZHr\~W6Pqn$<Uv60Z I7;7`wj*uUǞWVj96M0882"� G+-2OY:j(]S5ӷ mM-{yrUڳv7nG~SQ]A+NQ5x_uc )?dGiKP]р*i+{қe"*vűڻ; 4wuUɑwd\˷xQw⦷8JnZ~g:?]u\5pٕG{maGKJ;!(!Y<]{.jCTQRT۵|nYg1*2he5Pp)\)G+(ɦԒG"S}!Z^/h&޷ל4c@A\ ) X$CV6ZIXȴ=:ݜڞo~^Y<4 @� C4Б zFF5@l+k8YݳQo:;yk6#9]!-TͶ<a .̓&M1S7%IOJ5źkiC?AnL-Du^K~9>ԥyВ@kuhFKΪk3Uv|ܒhJ bkΉّ|YScF-o_KJJ~.*+XjUkIZSw Kag7'"=E &7d22ؖuy*o (C~{')a*P\2gH/U5Tw6h2yiJ7)} �fK.:-Z&FH$Eʦm:6u[(UGeojx\j<~{hc\tϭ[NS[KA$􍔭gg5{N~S,c"%}H 2.{I+ Q6P5e%uaQG?=w"i M[Rh?뭢dART۵`TA\A|e ]_^]>B!:ҜE[e(UovĔ6d]Z򠾣f`Ad IDzIC{/212,`Jl`VzͷsHFs\ yiJ3Ŭ� SB9U%@?ξW/}=TZ=R6byN,Av8[i֜Y*^ Jn*Tp\{MZR.\0ZɩWQ5,WL\: b~S,aU%fw \V592}[ ~k/<6:eM)K\fq+)QF |$,%Ydd ɸIsDˆ+vD WVf96M|̍"� *:sQX "<<2# oyDqC7oQOEԖ.9hZ|ӌ@[c;#XETD$꺷&1zr^aFv& ޺ؐ^tҲpGY8 EmJݤS[b.1c~S,aU$~|@e5: ȂUguzw[bݟQz~P6|$;At.1Q;12<AT" $(^C3>SVJ~ĻZΣ#Jo_ ��8,xMQAv~yY&xMǸ4D}˪JbCqC;v/=D{ٗ5{!b7|yF0׷pdG_{wYg]$[OKqj]Q@{QraU]]Ezg>tHtOQĊ;C{s2l| _Ft )nZR q~v6:"^@O ;:F>^U&o*%*)MV^-SWw TV]0:{2^TDOzxl62je3e/ʹIE�ܦ6ޘ.!ߚSv.o0@]M* " +D| I8yv ? *V#.Ji_ ��8voO17(QAUVXi 6Z}<o}=_\l{Ds-om~!Z$<z[-ZDU͉Fѡ %71TヌJ"FP_Rrީ-1DL&v5 St m֞:X][J]=F=x7oҏy{rׂHoDv4\t5%k#w PV LsaAw3*^lKIl~v2l'otY܈Q$[ED<j`Jcn$+JD4@Wż-msCJ/D/D��A~F:NM"Lc�NK7Mmn( ��@qEOS֝ؼvuna2qJuU.33p(��@q6J<8F/}iLr=͗UB x@�����@�����@�����@�����@`b#����@�����@�����@�����@�����@�ǣ:UC#fefXg]!M>0E7S&ߗ~DߩFmTp* �~RAdڠHBpzbj9} )F.;ο(9A}"<gsh,:_?[NٳÛ|"l54S3n(}u.AJ{-LNYL[2%\Vֽ?WCb䓼ZDn\Jб/ĩ'ʟxNA_5�A�D,8̂D  š% *o22Ғ߼ 8jC4dՍAa^fTtn6qI1v$i$㽉,zJ=@B4G'$F^ie?Gq~ Eh+(ᖅ/u �[bfk=*o2gZjWnuNy)}UnKe'eySᥢ5Bfa_kCO6Y?<Gz(قJ@^r-FC)D9llN[HrXIXΗ?bxR?qe"]Vda˨p&)imx(Kz}+ϘThil -蚲*MjlIDCeI +V"FY˞:K}Ml-޸3N'[l+5?s"ŘDïM?aoJ.ڮT*ԥtL'Z9iT| \t;8�V;ip}6OPYck&"� 6di{^wV6r*<ijۯzGM~HQ_t:(Ygum.=v+Ӕ#\AqEEd]tkb}vr=g2K0#otIv 3X:)ҏdUcȭXAX�vy-@ 0+1nqhe"N]a 5+lFgUCA-LY<B\>kYn',㰙5 ܾy 6aѝ25sٱ%M"U;o'wΠb[qeFv;?0Zwxbv^vR䵀' #c}ykd%]<.:h%-fDu3ǫ9T۳/ U`qtlUQ+x2d_"Xq[՝+w � b]ڟf8gٜ`Uý2M& .jx~9Z8QU=FeqZO!o�YK8Xԝ񲆍mdet,^1 FJ>6k)? L.q1Em)!IA#bhi2Vf`J5sٱ!l&va ;^Yob[ԸbNRGTpG-z&y.+pWkx'%<_A}{YL1?w@AD&7Qw[d"tvCɤ t � "+a 1wEEyqӕhG|.㩍HcWZ6hTҩ _H7JEBT Wl4;ڠ) ĞR/NmAEA_): ir oȖS(GŊݤ"LT&0cдDRJkLYZYA$X8+nh/+r.-yMLi-j\N6jopG/z.}~wkݾ\U < 2ѐ3]pZsAHq} b|8�]jj{`mu]_Y|#Y8;:` �? VG{ WzG9k]1ڬk8F;YGo&-ke'�7+#rGC H ̯#MdepO"2 "tndF*C)UO=4FMܫmbX\K-𗘉XbƌU,AnbQI۸7Dk/yuQ'3}mp^ "oeƒbirDM*wGsȦ\\J;<3-MՍt �S "2b%o{>X9[E«:GuDST�Tk.wYS,=DqV3]kmQ\b#ce[j艫Fv~L.ꚫrW$w7h82]ЕBq Kۄ<ZlykY "oE4SDt-rnJmmOJߤRXK̘M ^l9QĬk\XT^b[mBgPxbXy| h|6 "JE0$$Sx3z=u<FMD�SD& mbHO}}? h,<NS驏v\f=3!":yO֠:cq̠嚈\Ad%;pVt(u*]#Ȟ`+)%oR#cf[h?\jһӝ9{,]+9v]=Q\_Ekm49ŭ|8GeDʤ7CRVH̭֥4Q:\EMҲYb07M$8rWdR 6Z=LED(;.܏IJM> Vbߤ .TUM7Sp s豍ٸ2#r#"ZK>HIkkHӭ=cmwyKdЏ2 Hx |MEAL?W*2`s^{"p喅. M. m O,pkְ{< .=t2Ufv8[;5iV+}{MK&ރ?ᜭP\8x5M ϫs.H,\H.If@$'W؅\Zld:F)޸:Tm^Cos&1 17t]g'Qhv4#D:keqO=(ӂ:X&w ne ?Xf)zxk|w̭wwG,ڗF-5/VSK?6 k3n$:~gVhSzqH'-b!)s"sxƟHLBӐs E/%&"�7�#s8L~Y;l6fO LFm`�� ^"q$FQvWs!2"JJ /6@���b]˺ODE ������ ������ ������ ������ �0^J���"� ����"� ����"� ����"� ����"� G:ّ.u@Q�ÌG-bįhoNnjg] T"�}d]A/Wt i|2Ej2m_pRP=hl}HHOGHeU|NG[KT~O ; T,l,/UAaDn7vWcC ǕIɉpi+E,x^;ή~uZRh#j]A!�Ʀ VJDׇ,8¢ 󲒞q!!cZ !"K|&d? <U1K YVdiJm8 iC^gg9PDMH ˆ"4lW"aq, bGYʴ=y˵3.onaɊ>nAA1.Bfd CDʸ}4aEǯO|,yZk/6F֞4=Ajv^x՜c}rAQrv QI5+A 3`\uf\(j}Lܑ3Y)E@UNMg&*>MxT]z^Sk^i˦!:q[Z  Z^2䩭(x\ *Nou:O?Ǻ&h`K '%' 41嬛 bwX7@iA&+XqUxZOBfPVƬ ϊA�D4 BrcvCu۽wS*^\Dp Ay*L]!9vG29Ҡ%D8JnZ~g҈n UscBpz‘k6A`$O+R_{|\@G+(ɦԒG"S}A(dQKIa+{қOaB{L +»| EwXJUUg]}F]j+Rq*B^huwDj N+v#ݭV> 㴢A�qD[[ &JuvX]k<e:^ La51+zBࡩ)Mfn>b&򧧋p{mNG?sys{:koNhc Nw;* dIZSބw Ka_ou4>U0{to2Su<VN4Tv|%}7]jw \qeaP~i>0 ?x)BU:'m㳢A�qdKZTlJۦHcy5lB0fϩo*y -)[}ꕅD+ Oԗ|&3 de jU'lg߭b Q9/w/.lfiN<VoXm/VׂTD̤E8ap{2޿MZ`!,YϝHmT�F]*NMفfxA/v!F>_:ӃҟʸhD��A%@Ph,kv秢0;ch\%frjbd'(#7f"%rŖ19i7&K k>qA(g09bĉr ;-v|kNެMY_j('>1"*đ@vwICroM1U8&�(C~{Wd񹾚lM:WїÊA�đI yk'Iuo%v*bK9K\_}{e=7‡~ַnR vV_z+}K',Iw+Uv8D }"1d *ؖd}\.T bIɉxO-dʙ6E- E'-K̃j89ɺDF Ok=3kU4"�TqC1yfNnaMsׇ,‡d'鷚etNC񾬺4+6?£ªSy@μF>^U&,$-D{os 2zY ^^ IunR1^Vo&o);[zzZJ7 .b_X2:{2^TDOzxl62je[duo=-šuD/>ESʫes?6wbbV,)@mt_3D;M*(!ŭ==_KCWj!T�HIfq1?ӫ}U f8N+�~pAPrz}ؗb<moP؃۫l)3xl}g{s̩ dsܼ=̌{4ׂ̝-ar/Z:n H|5)F[rfNU wED<j`XbЃfT.5ٞؼo+V9v5:T 4\t5%=FVP)&%%2XniWs 2EfEOKQ �J 4ީXʼn b:+H6kup]w˞e_cӊA\:NM"LR E���� ?S֝ؼvuna2qJX���A�ğY?%M#u4&Ԃ�� �"���� �"���� �"���� �"���� H ̂����D��A����D��A����D��A����D��A����D��A.ڐ&l9r򈮁LSϒh}!33vet�~JAdڠHBpzbj9} )F.;ο(S&?gA{3P=q'y[NsKM[N)б *6NŔQ O)fAZCS0:bc7/Yuc[c!?$D~xtbJblDV[QQiu,iI1a 5(wܔ"�K케Yx GauU}0eKIaefd!d$;Swϳ2�a_kC_&,_}-iu.'Gi"v[.;a㘙Dʞ:R|I29SO?g5B&hLr8ci,W+Kj8`8v}Z})/xd־:iv螅j4V|şؑYwYdH}PQh nEmޗ|>Ȫ|15KzPfN� "vӖN YT$Jrd canAj7�? 6di{^̎sY!$燕+ĬwA,m51A(<.<KI{uwDgUg"㮮!n]tkb}vr=g2Kv .++x)UmMBq^7omBŔQ".HUeۉtz3(ٹ zkⲋiaV-~!,Sƕ=iȤwYڔ<2j_v5r*<ijۯzGM~HQ_t-/Dge<9⨎Wj-V`>lu: T<h/ VV}up"L9`cQicSCYk$!r+#VP4?Aw,&6׫~l"�X=䎸晻:bu6ؕj+AdxAR}LeА}ڊ8$~6-^pg Sv]Xp;Ue |Ղ["؛ZODf ;^Xj{ )&1"1~::U]*RX茈eZhmY/EDݐyl2yVpKf'- +`眳m ڤ&nrk]c{n<14b[>p >FL%p_(ͬ[ȕBq}Tɕ8E;]$;c�? v?zWTW?]vr%]ֺ^Si`&N.z_N<N0-=ĿZ):WvWuibjNU;,U/$)4؛y'VEo"^.&Sf"!*+^y]ÅazH hoצUuČF1+NfW|*7r1B秚/t[]GWu++HJ5̜@| KXěݶ% [`9{+NE1=Md$e7  D�:S|};bvY+!ީqg6D{hiFUK ο<4X  C#u'OTD0PE&-|{s6#‰(XX%7WGn ^Q0L\|kYFm*</[yu:Yҿ PlߘC6=b"VIhiC30sicՎh'U~ QԱԼ"01< � "2b%o{>XܙwgXVǀ8 tk<AD;n[gϑ\bEFO.\%fc}"~/|(\OSz{> ([DuM*kS}u.g^YM}u'Ĝ{?qk\V(slyB)K.$J@N0É$x?颮JEry(K5O$ղI +0'2aNp[`1%=m@73D8 }3W璵 wAn::An6Y%637M*2= s; Z`ؙDvՅ*VޡI{f n`8q+:^T:p.~ґ KEv0fÎ cRb#zM)<b/9ڜ?ne3"z_ʨ]w7\yt:bgr-f`2KA- ]@D$@fN 8(XM3T=Q\_EkSIޤ2%#=-!*pT<qq"�. K / -(#{ tE|M ֚D2U m`xx5|M ϫ(K&d mJ_j=([*XK9,//P˪{ބm8g5t߇M'yiAvm*</s>pg4[زN?̧ymrF#3 !,ǿɪ!>CJ79P i$`44=nlUqXDq[ppWD�oRA}a. PG��� Pf' Ay%yafrׅ:�DD��AYdꎺOD� �"����� ����""� ��� ����� H " ���0N3D��A����D��A����D��A����D��A����D��A#tV_#Y](SI?1/6PADuU:JN!Wu-kAC7%eTR\~껕OR ��84؉N$ %rWd>ҋ d۾Za/}{|.D�#fKilHց NFx_,SNjJ0ڻ Ffy}`oN-'QιZ G^YnN54/cEX6~_+l&I b^gA p:"21yG)�@4RL1p-43 ȔS u؃=($Ǽg!G-peiHyr C 0f>"O:Q^ Ef^6 =IgPQ, ̜˩5qA쬏3YE&Z .8ʜARrscB=s߻ Yy6OUA h ~l*⢊L9VD��A _s|p ;stp+M) eh.ީG\n DS r[SK{GrzfCv7 {RѿZB7-eb**(t?#AжZ}s X̴E]*T~u% [!nʺi%CjL"hK?\F^2C^좵]@fEㇷͣ4 7!omEZPSzӿHĀ-B ιZS+jNcѥ~V:*8;B ɸ͸PWchOd⎤>6PqnzkVD��AܔÀlTJʒC/_ ԩ/LF88zѻ^Glqډ6?o7T{72ET {ʠg車ں;U08b<ؚ3Uh1ZRUd<M#;E+6딍W%.ha ORwlߨ;qRO%7t|-BSZʷVaq9);& 7K-B b\N ,䆧!NsYPaKpBp1 !8=H~*TğZA�qEA˵Em|poo=4~#oMJY jhiyOXZ8wޙK~*eR+au9>&X]c^%x YlA쬺69Aj Nw{Z`>NDSMIX9?OoJ]uo-i VӛhK!Ib5f}0[DA9vt^koJ;'"fGenۭI"\})#'?~ �Pn6%n]Nu LA "@ N>#\D#Eof-Zol# oK%mN=gg5{N~Sa9fgي n&idb bKmآ�@P_vm/\/C 2לCeOdӯ0DɢKZ f5z}Kj|\ED̜cךO$W{uDgUXEğZA�q(3BW!=9¯`Xd/1 dWMn調14տT?rp N=W"[3'J "o9:?Ņ\7 !2Ǧ Ls&MWѱ vNf jb小 lCe]OBKDiŖpZz5'o֦#[W~DcךO9dau`B\*sLs,1:8~c\bw]+" #Ğ&c[pD/[wXbfޚ�ɎXL{ >6 O5L}mΪ`[rKguzw),ƐH{>FRBy:L-Lj8/Bh_ [1nw"$Q^αkMOMNOk;y7\&+8܌ ݤ}oRu "pX8(<Xl I*,͊<2WN2¢7VsL𘛡 "B4Y{5Ȕcy7m!x_V]Urڿ{QraU]]Ezg>]*c|0+.k<Bەe5)MV^-Y6+M*f^*_U&԰|J OQĊF{sq|duo=-šuDM$n(7rjMIU1 ]=-qizzlqcn?9),xex)17ZAqȌ>:UScG_l<xޠDу(Dc7}݅ÞGҮ뚫|5Yw\<ǜ|.1*tf)mD4\t5%a<&F[Xd3Q2OC>F +^~\=9d<QEi&YvwQUskt&1pD9oî5.NxOuĒ'GWϠDv S ^=_ rS7uT/9*?X (_X�3#R(CD8�AA�`cŸ3LKED^p p �� "����X_fV6TYf1⅒k��� z&8?ڥ3G sBS���_AQ Y{!1ھvuvģۘgwoWAɏA���Ƶ vwwuwvvvttu}mcsS珜ύ&n'NYq`[kKG[[V8{|i;X]V%? mf����0~/<KSs/NmUQʪ( T9r8.ɃS��� * mm-pāoA��� ,m_6c$%] ���1A=V5WK跮+SQc$h ���1s)S&0*PA,+Οdif'8F/PߥvAd]!M>0Vϒh}Ά`\3:8^E UGjhyD@c1 K[4mXFyخv{]uG8FHGmXePcV٥Ϗg vbq<t bdz_9eo(sY(8zqn: 21ؓAOHƌAxTȫGnMƭKtP7v㘉vs_gs5^(f }^Vr+.X!/% L=ٗ؝ k5ӆW% uĆV8-qzꮁ SNf KSt1Sكq: &]Y=m_[C N/q^TZV%DN%d⋴7l oZ0{c7/YrSԳ7$Yɉ|^,"#> ߒ2z˩ Aĩ9K:.REv=R&&;aGhG"Z<u5q(V\iLE"]G(ľ~[B%IAW0 O }MM:^{MtȪnjM o\\ W[4}Ƚ|][TZ|~cY꾿-)$|R俳ﱾoƆ} RA}X]ՎZ)qΘjv2hXDVw _#^aD{!%9C'ԅǵc {{(ׇj 6-&71鼇)kRR0.+;tb _3)b첨=V+j ϙz*SU&]Ȭk.1#6]fɋ *y:v}2z5mnyͦ_G 4|&eU#+~iF߰Maσh5= MV+O*督HU/$l|RqaS|RbJF_նpI Pp1ݟʜ[ 5'm L,lW;MY&Wh.E:,a@P]e~<O^xrTϪ{ڑιbE|]_[yGciPC-K"C aqtJ^\ TYTD \{ le<D#[zQ\eW\[c<{5*Br~XOQ;YXa3g.dمAu0'uOuRi0/L{ɒH[oh-;<1;/;)Z†!]h%` WO' .*E?׃Ӎ dVb?2)}%ve[DeRQ6q!J ɃhiTDyԬ_}בZ![([NQ}:UŅO,Ag#(Ygum.=v+24e 溇-xPmϾ> 2M be[3h,:̯UKDoYceT.Ҳ#ssZt^`\(%-mͳ4^xNVz!.^Eȸ㈣nzBO+ '弓+7b|/?(yqAT.PA|DO5P"&LEgꄓn&x"v?+mf&[m2˯^78>VƜYaAo켗=dױ3o$$Q(1z +IKj2rgv?AyZ%sSXMgK޵1Íy䉛_4*$}iJ]~?vJ`5 Bq g^zM64byvp!<DjE r].#bV։ج]G2Zq ɃhAUApcɳXGNKB;m GVşQĖ[\Y#|b"V>m񺛣ޱ[ׅ@Gj@a/͠ξBϽ<xA bh*}VH ΆwG-q]W4?Ym/ܲDBr.1 D\ (eYMyp>HtcV]Xl z <2;8==&'2Mܲȥĝu1){euKqTJ^B ?ץNbLDJ . gN]vQ\F TcYQ#0l/>IUM n^伽o0Eb*+ڊSfV=^$ߦ%G3C0`=NJ<O }[UjU#;?ОdпD4n۷[7jop*CpdD=T| g"!*+^y]=i5 rEMX}q՜",%ᐙE('2V"Vlv}Mqu%|GM:`nW^q%/bCYj6NEo/$ib "DwuD)k!CDl ʈzT|J(䵗.n.3wD2;֒4vU9W1 D\^K{E *K^=}v}XS=v- F2K︑~9) b5iL\risw6zGfN=T'dm|AXXX1kָ{XZV]נ?&&z~[|#ךc&f OùW RϹbƗ5٧&~Q=^Tu{X#<?4O9Uh38ubW.@~3( |i; oM ":VED:ZU HgF.#WD0OV[ 5yvutvHtđ(˝K&&IOx@E5QV]^Jf'?qOOv8&ͯ:;kIe Tϴ+Iv%Lꅧ\?&<.ٯ}|p|(*_>q,<97lC!hpo-~wVH9\A~o(m'ؓ7J$,{P𝿑/#Q Fʟ@~'=_(.aό? ~1?RST?8hگZ[TNx0/גcu11Zqӂ”#7{FdI‡8āGɊɾ ޯe'JκQƬ}߿9Ffn?,ho$: HǺj䔤dʲ%.˜x޴NV]Z\3ɵ?վ;1\pڄ_ )0[}M\ _2+Hk" mJ>eok 88@ĚyTq7Rxu *uqZzRڋvn8U޽4Ԕ@jEwFc`A<,sux}j*џ+b~, Ti%, W| ~t9 #67/~unXo2djr8nΩ7?Bvo\u8{$ )|1  6sw;PA$_)|$&{R+eF^fs~Y7eo<ؚP)W, }a_׶kYwu]u*6TlXEDC IQw& @&u_\ə3ϙδa?ѢA4J 3 Y.XYydiΓɥo_Ex0L]]zDF]'v|bA)B c0΁6[òn5M !F+{7xW?h���0&hzb O4OJ J @W_y$KJ.^%N&?U {m~M&���`4о4/ &(su V%n޾Hh7 %ߋy~De>BS/$h|ۆA5EU���٦Gn yDD bNnvAaeHy&B6wo^kS67-Q..$6ݷuo����aREƺׯd(2u ]A'cǶ+~X|ɆR>A66Կ~L]mMNj"QdCCvy�Гٽm�|A je6yϛWc Xe@W_!|kh#y]N}P_LTS�_H&� ¤Q;!p>wĈ|VWG! )"'67kHY/o^>n.$A5QJ&/T�aZHv؎aW.G *X. j&IRaNzRRL\"l.$!jR)%B�"@:H5�_&%./>l躟($6;Q.T]A7i(R*j;C�iRM�i V>,-4qºQCe"GAwGuj % mvRP���#cR®^YS+"_^y!P`}:"}'6H߰Q(���#cZعT3 *kAܲYA!e$D߽qg@{T?I���Fä3?rIE%qK ï =ux/A!ub+W!A{TCSc9Eybn~ol2���aRHқ̔ćܺjTAT .qvZx i*#o\>{t2��ȝS@gBU1؂������ �������"������������� ������ ������J+D<9t *|"X����0ATD lgy� Vh�����LBbiI}hCݛԤGׂdB6����� E3u6{*W7�����FAĹ} @ +4�����&$66ԽZ~wB$�A����M׊F h�����SׯVHA4D�����LN6VhH +2K#TIa#���� ^ Ɔ7T><6LAMg*0EE˫a/K(IdHAz>V޽-kس'6w ���|鈒5lSRA76di 1e{y?3P_$;)b<#dw lxt4Bj\AJ 85ax_HOWLDˁ?/ąx5TcV;xߓtODo\ D𱂈K666|x56ԣ 5]^Gx+f)`w�@]뀵~Yz)ά׾'"|V֒"Sm1Кl3hNY,G/yo͈ݷEF { ~]8u٘c9$m]$=kwG*8} 8T8{)om XErȀZPZق4uHbυ/Rm-HV+R bJ>g[Y͹)8>|X]qgtHAl_~9i=-| wz_ Y|siFZZ0o.2 ��|8)$5vso4&8kиY1fA̶Yu(,:w+vVցq6A_dȥqqq-ar=Ay~Ǒ~Uu]5^pD(>nn6/ o&;b[A`MV<jq�Ja67,qJM=Rk_T1bkxڅChat/&mRE[]s5ՄQ'ݜQFΩH^1RD"ξadM(Wh M NO4Q U DB_=C0uzGyo6yrzlh+ Upv[W+*,[ad2��)5% fӎ' 򲨥sJUs.bާ9Yt"WDWV:/hvq3w!4a*5L4WƵ̽<<6?OG[Za/ETs矘`9p[J*o-[Qo:$ogO=L-LAo8NgܣaFu$8|,>wƖmO1S (h)R*(pr[pɂp,^+jakbEEwŔp'7l(xe<fobu帴—?g Akd\ѱX^[AS[S%k|:6X\]^#84 G<y/=+WKy7$5c"j{D|x5U<}˫ϹӇxIHhZQ턟C⟳O#}{H DX0mGZʓ4JPM;h3JlaR!(f�mo*rPpN Jbf?:368A�(7sXSє7x noki<?#/M8&+0=fPx} |\:3%l56tD5uCBey{DT-e̵”;V{Ⱉt"]*BgѬGT[qTNsVn1Gs|[8)N'"2÷O"Q=*ʫu GtuԪǞ]9{~xԓoID]COmr"EJqETZMO*bvZݚiMXc<J퓓-}Uj٣J:i3tfvF[{\̯})sτmͫjT ^ŃCp_%Faj =j:jAV+OԂ(P+κ!Aq!A?hff_PժK)`tA>j^Tm7]qi*ec<NU .=p+J �`<a.42%W-WPO%v{e8 LX))Aӂ[#ҥêrRM9Ǜ9or>>5>NjXybE_5ym:l?HVUy-Bmtjuch⛼} n /fS<`D-\tGtu]_Yau\!,mKAl?D,r{ڬە](ŭraasQv'qM[ͮ&ׯte'>wlךC1I_hov񊬠d#p&jAhH,E?ӞH# HJe<{͊v t0ʇ3F#8UTʘK][|�>?6d'CoJsA/zoaRYI;b~y,nJB,L[q{LLMS3nb(yYLh#mfK.gϷRxK6&T|Ʊ~fJT;g{K9e&s`Aԑ)O-;&T ]UL8Iڅ:>x{s R`QǯuҎGb Y̹s)+FDnƹeM "<"'\pJ Ḅh0q�s&Xhb }vKS<|A/% qiO_Y8r)3>l_jZ 0-8@ !-t5 )OKFb$gB_Uv?VSvGqr pc1 ��!Je] uź{`qeBkl.x:w)iYVԹ~Y2NS&-r`md9 jGK2 96{9:ϠJ;gŸYl6y•6tWr QGp)LتV{\..*&GY$~)헮j) "E Fq>&ɋSnff^Ie}M*C ݓ9){g8y *SZ&(dagPq`h,!1PI;~T].:<amL/yլled0gf AA9'[# QD.xMTIE^767QhsT5*8pBe�mrrS Nb֤ v; �@"/Zbg>x~ (ٙO3HNN7&f)/Ϲ.sp#_K̦-f+&;\KP0O>Мbx-va̱OkTrdS^|Ir8þ}A &qz>%HsC3 "++TK:'R({<Fs#$:)3Qѕc,Տi<ģ{:-σ5XV fy9vm $kkU ӌ8;pe{O>|NȮDZ~Bd͊], YkXM--Y4Zd$3V$iS8YϻF|}1/Egee]?}㩧]2R<iTBBw "Rgۇ`e \Oo-6ro jP.̰r\vPEĥ *mtSɆ�@QUem9=(OӻZmo-qEVifQrt_!9EYIg1u0CbAa{jߤs-m,zwM*ݍ쒧 yB$1#pf7HTi>*67N;gu"H18z2׷ %bI;!d38b'<}VuF)`'c/V_YÜt "e(j R-E뜨Hkwv6<+ D);Ǩ ~D!@e^Clz9wl܈r"ӛjۢ?v (b~RHf$ 6y3'0y;E\LYMbX>9ÅfNsȡ9D" VrAQ֣HUMU?ڞ~-!ؾ�:>iMiPA{ VK_v3RgvGANC_hNv\+&8Ь{;p]wt ?tx ��] ^ii5/TWUZ9Q}渔,+`1',wUg5doH}{@>ͱqR5w/ϵA޾*Bm*SIHy蛐yd fS`){f?"yO1Svj? "RΉcntT5DŎX4p[20AN4X%+VHAֹ3'---_-|OEB HS{G~sH���ݛa9>e'oL0p8QzvHAU5+b_sՈʮϤ>hڱ bz_FL+Z!̔[XA"{Qo^t~�A��2ĂA V 4ww+lj|IggW]߶/~P.˙m{/[ѭxc&.u5m+*U AVJEܲR icѨ ��,.V#vc {JxwYc/~D~hH =Z�����AA$Z- ����`r_+ "�����'2�����SD/P+A����DQ!G\ bv0޸K`����$Q%qK ï =ux/[W/Vr"�����  8XX�A19%rf�����LH������D�������������Q������h0{4wpD������ÇA������ j1i W�����0A5D !~i<MMd23�������MA$q ������ZOZ~����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/plugins.png�������������������������������������������������������0000664�0001750�0001750�00000115306�14035600052�017667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����P���>>��� pHYs�� �� ����tIME� )ݫ.���bKGD�����SIDATxXK'vfݙٙvv̳3wn6ksFPQ1`Ί(Y((DE1(s1[>}�<twuWUWy뭪w1:E,bX,):]J=n%jbX,ˤ`GP)jObX,iEr ,/)R \P"*bX,4+>-P?SԃK{<z>_V77_w, p83Y�55}c?p,먳n-ݕbڠ.5ϼ1k%;]xyeSS%=Kʦ% y?Y}Xhgs|UubX! M@a+ӛC K"sX,VӬ4j'Mϧӳ1i}}vW!57^m[~/^5޼GqiZdmY,˘\@H~.36+ҎUb@xezMr+, inhʛw{iɖ4hA:#~LFyᶅ&{ ¨�&*Y#Ƭ;@A2h"/䉼y%ҀۥR?m5rs)*X?',AS}\bpS`0fFDP/ q,E7gjct^+;#-'Qo3 B )6M^K'%W,cXmG#WII4ZaYwpl^0±ƶX69M7Mڲ7 /Ӑt )DANG)c7 " 4ti(sC޻NQYuz(&Eۍ5@8ZUr*euܟ>{N%Ս4;JN^)=|L<*Zx%sb!n!Kuٟ[KL X:K/2v{nݸ}_�)؎_#\uO,h21nGh˾\ �hk<0a QW&g`:p&y%ߨdxF rȄb@xcC愞 D9ä"ĝ"Ҍ?,q^ҹnO}XeJunm+Sy/.\K~.XYt`l{z0WuKh9q I`5KbڎL JN4[zI`;~ Yd`yu>M%hRTMI4fyWPsSjjoGNǰ+ב2D&VƊ� ‡kfS*gM㭗"q+whQ˶Tq]_B싗nNAt##4v3bA`)5rv*#BqxwL<8ô%X#�;t 2}K>}Y } �Ѭ*CcyԠY|=fagF1,a>ju<P[gF҈WXV^tl9U4ZJX6VY42psbٖ˙4~cIeO@{Z'%W,3j;"Z4"<A#Ќ >$x!�R*,lWo鬑O[,>B,}t hFjKe(_Qw ;h\p1@.MZX"neKs9L4;5_yW h^%X<`5K#fXmG~gh _˅~qҋ$X+tnQl|N?2Z'|u!_XK1iXq}t h dT=>C*g(z*-FsB˥Wi=QvXٌeiX;yI%>g]tb,_C\XmGaKxG,#e^^OKL XBY,V$S4vNM% Mhxa-#zc2hȒC4;u3fxh&kaLжg4d"oYEaǨ*X\n%-yq >>n3ol9hN{ei#VI�]T#z_%Ն`G,n>+$K&x\Ʊt0_l+kӤj{MkN0$: 8N#]>L_0Rr:[i AX`T}# JPoj]r[ G߂XBTNpOŏ^/,Zg Zn rosXq̝ǻvk2`b-aIdT͒g%^b,mkI_[toH4Аt2F/^ 7(X,vIg6&Q8^^?bX.ekdd7GIv?}FWo Kvi\G,قrZqaZM/*bX,Vvi7!XX,bXK&Y,bX,-S ^*tubX,KU2?^pbX,`bX,bdX,b1XX,bX ,bX,KbX,%bX,bX,bdX,b1XX,b,Y,bX ,bX7 eeeI۷ogP111T__7.bX׮]PY[[KϞ=cH<JHHu7/o~,RzkR#XFGGӧOÇ,֭[neQQ8qŲ𧦢Y/uNzаcZXZ_ii)v8bÎ]Nǘ,HY :566f[%l, uEtYweJuuuVl\G0,|JK{0&L"<9 Pi/į` [Y ր'O޽{, u,a]u[*ȰeӵWo,//L^M=F A :I ԹGO}G=a"]xh~jZoP <tX?hC=o|8}I8(ʈ~Ԯ?Ql yڳ/t*)Y|塥@cbciݾsWrpI99zF+_.cy&%Sy'5n7c_L77އҰ<]#bH|1[zl,ԩV8XʲPĢPj8c޲eӡKW?d(lt񇨪(L�´B>yy_ ` ێ<dfSYYf8g~]Zj ?x\hb= R Px#$X\2)Rkݍ4Ybp޻Ld1j)rq^m8'y?\3Iz'N?NLW+uhБEw4,=OSuX-,q waP2X]4Y2Xr4&m`cnS7_{ڗ;Աk7= |-;SII?  2ldKbL`ݱXΜ3W .NYs'g\|ɴdP;ӧ6X1-;Z )m`SRSu۪kt _ԗTG6kgf^6曖n<އҰ<M]#-חjq`#}zw.n:e*)?(gPZ87Ź)XsUX.X;g̴,m|nm(V,KJvK/~JFӶp09 AS8K0*oC\bR~[[,Lr`M՗/އҰ<Mաbă %Lwve-X*_6 lRR̠c% U圲9Xͬ\N|>\%W˶急9-Mঢ&`\pR߫,C%`iK,Kڜij?-חjq` 7nՑ#GeT&-n:e`P=nERд]#t;Ƃ-#>x|&S~&-MK�N;=w(:sD^H>5uJXZwJSc&Tm,peSqb ܇=O-b88;v,-]ThܸqzqIc˭E l2u`VŋT#*=s"=9X5Bn ŰE555&>xh3{P=;IG2t3ӄDZ)iv %$M|^zD~._z ;au2c,uh=pIMaZZRN,+Sw h8[QDZ܇=OSHeZ X Gn(я~DelƖ[<7ѐ%x<d2ƎRmZGKZղB*H9KW "AjH˼6K;hCX;p*V͈IbXL}|=&a�7-2bn1l9M wt�DϥKpCyB-ѹpdp2v_K_'X*B]pS|PΞ&!QvzLJ {b%s}Ce`رnC[L[nM�6:uUYKT? HPIy*L͡ڜtȞNUpu cm ̃X- ,a}�lЬ`Ν;͛u~~~ԥK:`rkKT :Eݢ,9X=Ne>+=D*8GuSKV,-<Y.) - ,V K˚Rh-Q)lCr5[XVu`*?uٍ,VPaY,Y-E7)3�,w*X- ,XVj4x&ۇ F+VˀIyrKH˾S-,9X]q3|FGЍ^_Y+gҵ %bsM1́Rӟ(**h,v2J)4x ̅~T}e~Gn^ԏnc[$XbZ9X�?weCNQcK3ҵ.Н*.^DGQC^{zz}姼K/^<9XrSbh先^:YkY,RX6u[2%v?ԟ eեPQQNv2�K]ͦc-Xb蓽caLK;o,YJk׻glKZbXo,aY:Q"gNSmʜ '*bd?QՅtj8%vkn,;cVVK[0lѱ :\#|D m3(oƹ4l1E1c2r<Ę)(bۛb Xb6-**bPS-G\03Xr0ϣ\V 0y MQL[gдA#"R1'1, f8l04 p:#"+N Cc=*\`bXVveCe⦄[8ضPUeffZt qXqJ")M޻F/f٤wDN%,rҷS bbXo)XDz2277ӧLCl`5D3ڬOj%S(o4Xj |Gb-|HK4KC 1ccbXo)<&&F�e;eeeԚ!4gddPRR�ZKoaj�毖a~gAOƆzK:KX¢bDI/ WZWw8bedd]reC*>+bX, M0tj�G|]gbXV bZaDslaa!*..MbX,VKbX,%%bX,bX,`bX,bdX,b,Y,bXo+XX7(xet/Ob6|աSXxyo n.BXƶ''x%b,- ѱ 5,jj| ayJ8zb%𼒓ͤ+<~bbhݴk.M¾cc,Y,ր%va /&&?~  c3ٹgBNJkÏ_Kگ2,T U=xı ,z;PYWWgLNNDՏN<GAq)ݢ Wsg"fS3ڻ?Jݻ^vXI{?kORfß% w!KK!�hi1.0XX,�˨(] J4}ۻz*oMՍw)ƹ:辞bPՒt/O"#ͦk?c&yx5<?yBJ1۩K %A@!Ä.]f`3D6,ֆ4,Y,VVK-mp['r҆#t|])TK'/VX ܳf)EsgQڵtKKsᓎ_Hfqpԭu%lt'?*e.vYOa)d[Yj,A[}.:{*9Y䉴G.22$%bZXzxm8A]&Ae)>GA1T\R@^WRH/e]Hk(y>NjOnTYUe,Nw^ ,o IS8,v!,?6Zax ޽{@�nc3BbX,cFť%. [FMNPUu߆Ev+S4zkR*Z e>ԮSZl9]mlRzqI)0&`y41Q4x4n:K9-L;{RR`ɲVbbğek>ZڲZ,Xig BɧOJ TZZDA~)vPzzj减 mZ~{Фz@쵎u X—3z#4dzZˡ<jZ7X?qL-n\GLg 8wN4>gGO1>`.Gg3ZtZR7y~o*k`L B!Ksy 8QN*EA~1mY?={fGؔZ,UK|f4,>>:k,, #b\6,ikv*,,D$?U S;>g>Kۂ%ƨT Zz0hSeuUUR{_*Ywz$C@rxOE&=ay&y K%p986b?0H,>ee& eV7پbZi4ms?uB<5w>%eX<y*?9%ێHls!|?A>~~ԽO?jߩ -\j{X+@8Szf-9>Pz6-a%R]%U_)$?AGeDY:gs/iw/.:_t֫zZEc ,cVr:o岹rgLZ)gU~p-Ʈ9!A+VcyZrOX{,)5 Z^TkY`!"۵Wo:9zל5cYQQaTr4|Pa)(sU'ϒ @ߥK˧3bJ&`!tcsh 9ef6:jѴ͕L$n}S޽ M@1,|X*}NLPiM>v9f"<99T./-\Dk׻ܧϚ-<xm'ZtT6pp:~>JZ)[lُZ>MH mS笖f7y e_"Z^<O%L (ʩvr5un q͠z[sͱ VPX(eOMh-䞰ukn5R'u]z UUU #>χ>TvZk`f9tw`Tjyw5\ӛ&j =*ew$)**˄SX. ,_|5ax9s79,Y򶾃S֥˺a!PST\[?Pghja)![Q~~d,?Jㅋg\9Վ5W.K59fe}}|-g 9&fe6Vwnͭ[CZİNܿ:9~ל)>~׮_sN^Kx_FY?�t)Ee~UK /j�((RZ>ZGөgi”U]O<AGX7:t*}ᄣ&E-<(\)8,Sn3WNc͕RTG<<{ͱMތ-'luݚ[j%e6V޿ֵ<ǯ3X ߹]OBCeeeO h|,90XZ 5r3pr5j+*ZXBůr?%hGwbjZ,eE^X+Z.[U{FYoXҫo,'slYM-Z,-3K-՞7y,[�X ޟ~P8ڴj -H:Ӛu+E7H%%L4Xb:X-t8w^8·͕pK<rƌP}%gfy5ܭ9؃rsES �VK+S|gB>{4Y/jo/g x >aA6s^i켵˖`stf{-MU7Vw͹n[Cԙk X=Go3X e`?vηjG1q12%5U|<Q4vdJ<qB1jn$?>m'zx!jI>{i޻T`NohJ=<sUٜr:]Z,+`BU0:)6WNc筵\Kϒ+Ec:PWͽgt=t1*%՝%Ds-P殹5uvZjћ 8ZLH`@Qkx8" yu|p|;Ǚd1Xr:qV%/E(&W.ZN![K%m,m)~y^GW4c.^Bc CU ,K,,Y,`Ɂ k@SXx& ȫ*KKE PS[Mq),<7y ,c[TW_˔c䔔6ej=t[b�_y12XZchkXTI^m!p0Jy%'I%M?<pכ.e9OKW:Wyeh+<dkz {cdv: <(Qy80X%,}hl'*-+ l !|O9^z8cZmԍg'bZVsэey;rj! 1֡<&bxDEc+0@CEO&%5IXӰ|ƎW7@Y'1\dܚsRsv-kDykW횛{SKY1V&\Oml*]?yj6 J |j*�()11Q㉹a =x.Sn5*EDͦ=gw4ՕҋwUŋvы>z!tU`ijqāCkˁÆk@ee%\/[Aǘ|<HxOMb̚Y:O,t ,#m9ll jS+>yhr\]! QUUE;""8y}њ͕S\a�k1 fpU cɹh)}Ԝgo'ʕ&3Xz6N9[ G:Fo {ɶ QQQŻihw?FyTpRVI#s9$=u}=%_B7EFM~LqS_'t^Sl@dV%Bxz:=] ,џ3Mm$?1'lI2\L8Z\9\afKuV9kEKy<+zxkޜ{SKY11oj`R~ ?_DWJ%ɋd`gRD'gϢk'>Lf]$nDPsVJK-}Ot"ϾLN ͛_[y׺n_rH8GGMx8`2Y1#!὏?} ւa:*�X>x<M aХ$pQҒ:u|͕ZK6@&B*UKEKjQsô-WsXzoj)?3jy,5ᵑ 3FfPjvŤJD kJ ^$5<n~tawuJߡ):ݑz ߖ6!#GSL1iZ]ߖ�DWgߥg/J<qR�h]]KX"vEE +PtגxZC.bX,M׃#⏱#?KZTr@e)Xbi4kCKXycTG�|Z,ծVޛXWb`J>^nT\ZBҰiXڴUUWmXD^iZr9E;NDZ},(-)T^\RJ ze`iݻ'nk@*^8r@ٔwӏ"Ŀ; o, �O,`YLSt=8w_t�(tSD"'fβˎ]Ŭ,4 3̠p8Iͷ X+}Ԝgefc8CK|ծVjaZX:LcdlXig BɧOJ TZZDA~)vPzzj减 mZ~ФzЧ쵎e{U`GSM5y?V4ţ<x^} T&/7$?>m'}n^RZVnҴS:<MÞ}E~x_/:(-D=-�i֕`4ͬf2vZ%% Nq6KcQ44\=v]zW7 gM>l<}D=11XZ [($4rssa={n 7W 'J]I@>T2</-ѳg,H߻_]XbYր%Ҏ?Dnߦϟ_eR/^3;Kґb;Ih`1*Ղ^&$`'{2.<T4Iʁ."?M`4GdOfz%QIJ`*X ,'N% duuȣ7IC ,F�K``bZPRkF8f?Oq,KGVں*:r2WuP,iʺt]*O)u$|Q|&A:(OuM%m߹ŽOIC 3?_R�^-=`( *Ñh@pt``bZ/ C /_f9tw`Tjywϩj՜L5QSy֗Pܟ.;K%ITQYF< _OM`ٜ5oC(,*90X2XX, |<%T{xɋ{ (ǔ@._" ,^O[)XnN阡n ѣ%%b,5P *)+-$Oq!J999TVV&$^mm6m˝v}h <>dbddX,PV^J۶RJ({mZ5wKiͺbG7H%%L,,Y,`ɁKb1XrbX 80X2XX,KKb1XrbX 80XX,KKb1|ݾ}[u]΁Kb!DyeĨ ظ*(2`o,Y,`i1X*L~ɔhH7sٻ `>2Xb%uы>=MJɧS,h1X2XX,-˨(Տ"Pm?,ݻK7o^4y=�~Lky<~K2ce;KKb`Rm?,oݺIUzltO$`rٰ:v:wIw聛1SnCYBR~C箴|z\<14߶ԩ[Qnn<tbiy8ˏ,{.3XTwܡϿ. SBv QGa4f$**.HL oy&b1X,]JeB%T[WMuu5t:%6yI_הĩAUUF K}CMqfXGDT]S#k9^Uk42CXyІm8D\~A! 6B �oTQYiqݭwstgu9wZ!4~n[i4Ӌ鱕et otOXN|;TVV&!`W j4p@,׿2XX u5TP¢< |ʨN%M`ƾ; J_뺁ՇuB-R~r=`aY,&p^~iGt9[/VEc%<k&礌J#"6ZUw5@E~Gӕ/G; gz2((HPppp;x`vZm61!!!bۚ5k:}ٳ8fΝ?ĉb8Y,Vr2l*<cg(%ʹMۆZeu,[�>T'Wk<@ VCXu2<̝2dR2 :\aYyu7o":p^x!Pz葦:3, _~�Xۭ[&�ӿ~3^puu?}?n %$$,wK9EGGti1rwwݻwÇw}WhȐ!b3ßggO6l ' 2e(oNN}uJnelaaѺ2ub1XeiY]Y(/:t ymrqTUUbiݿ/|MY,a3 Xܔ=-CE`.JX*/JuXb%p߁;JoZ[wW (K_ X4-m�,T@iiio}K,Y~  �xCܺuDl:R 87̂kQ,G]v)|Fc,qވ~@ zԨQBh"۸qD9sIʳdզy=l0|},,7P_h}ZbZ!XbJ[ /̥)BRR ^(.W@+Rģ%a!Cgo_?;Gtp篨 Gy5w^]1h⥚c{oRf4X}(|},M'-:�WtQcDԝ)Sf;, K4eK777=+eNm�0aD\vvJB ,},-9Ļ>2,`Y8Xi:IPey~ߚ,?O,OD[l*\ݶx+-FܵRJDZ3�:%OsR Kޛ<�%“S aD R]]}^ֆaYCfX.wo^~cQYK^T G׹ngMt# Dz <v^p;Y[zD ,EדCˏ>H�, ,-o[lmr<'7'h,hNch)XGϱGb'bwfeeHLeSa^ƚ gXԛСC_Jܪ E? Viucxk ,μwPO'%`lڻ? P6wtKl=`X!/_?K=!=4Ql3gMbo~Sl.\bz�]Ǐŋ_bkNMUV# G%KCۿUynwtt/~gΜis^KX,V+K[,"Oo7 \~u<` -]Tcۗ-[f._Ai~v!|/ L ͥ3;vL%~ Kn4 OFˣ�Zc� _Qy;ʥ<F/E}Vݻwz2c,ϢELO>=W{Ϫ OOOas^KX,�aMM`S}\ M?I7r;ֱ}m� 3KlGgXhE`X>L_Dڻv>LX0;*r^�':h.<9ܴs5<.00z:wL{13dWtfByPgN0JJJX|U2X,K>wK&KbZ8XrbX 8p`dX,%% ,z`k6zbdX,V^, bX ,bX o,Go8D /h<rΥЂ94ZFg`1X2XX,Ҹ.㧎Qn^6ReU954`>FR**ΧSIi΂ ,KKbtAwƸ'v<iuv Y;*7?fΞJ? 7,Kb1XbTސN#C+jx`1?z= rO\6yBZⳛ`_Cg:( *y RV~#`L˒tkn>z[@X٭'c*3%j0|dd$m߾FC- ,?M#B*M~;]ν伧&M: `YPKӧ(_O{3oЈ껩+)]IU7 9lu�aKju5bdV׃(%%o1`aED?vY/y1%TeӦ_eQO6'i_71@FyynR PSѽGυUtel m;(z)͏l1 )ξE[SE.ҋSHD>?8.s(76wދVQG j͖]l\Z0m (O^C/;xnP8W\/= 5gt46 PIWSzFj1 ,N8bR***4ett4=}>|j#u떸-,A{ǹRTϠjΤ,Zv'uGhK-ߚ֤[B ,'M0vv`ҶRb}\"i^I6ױzO^/jxhuS8 P3F²Rr}S̅8*{I/5}SZ{F76|rY wi|h�psj#ӯӹ{4*D(S:oA^/GyNݦ}7O++;KgϞ/wXL0ޓi` Km׿Ež"ܒ*ڭJlk7vm"NX!3Χ X$9II47,95iFxiY1%%I̦&pX}i=;G f2ݺ}xz?tK i-X׊|ypN=˝RuR]ޤF TX e%H5[D;)a_+[y<'`T?.IԮc,Y"RUUU ,<yBczH8 e_(zo<)3칗h{fIӷd4i?q 0&N+j@,,~_[ ,[ xX(?PM)8rnsVBXIqhYLc͕ZZ~JK.֋ zʴ\nZ;5{N X>~جlz^B#K(5 [rzH8?t.�%;\ ,QjiUKk#-ZSO<>7j%Enbes?`BB`U{E!N-nRT Qse׷X>b\bZj%ם% M ^g=2X޹sǤVZ#e ͦz{c`1*o.N{8W@}</>S@^8JYSNehƍlfG7}k9,0o+'z4,]~r<|=ْM&SkesZփgd�C/01vuDx/#үXfUZ;)tXX\|,͔U.C{z|vSKߒVfuKo~`ɁR=۷oܑ=\JHk.-6=nq`q,;8)"Tgaf?WӦѤ)idhMꚾ;:Hpy>|@ߣ3~ٴE�3Ғ^rg &{G1:],4HFҮg2&tNDrp,+v{ZaC<z/PXٕ* z>gu(ATbkTӷ3X6O2:tJf΢\M`Ɂt` _Yh^{4{u0ٯ`)wU~I3fҕ}FZ=`4>mlה%[*,q[;N 69,J̼cOs7Т hmoC C >:oYz\ -Zl`B} :r$;0+7niMsQOHrGZeZx 6JYns»I~OI5FYyWIК5nq`i+M]G^@>ڶ=X4ujmfM~詍i~g|rɊ翅|%-],>,өK^U7uӏwB ,*]G*uڍJJJ,9h46}ؐ`UGZju5}ԮMYP]/`^zƞs6#FчRyKMZD2m\6 hF6Ct aْoV(k4+;&1X`ĝ_P edF--X>,^q񺸀`7U4%=o"ZUĭ\6mp,ple%),+1'Рy;C(uf5iASHL χ#<hb}KPx4^^^Ns|aݜhg/hB?N/=岱mjwޓ}Ѣͦm(A^ 2KotQ'hC;x{*`Zfݾ Gzi`ii[X9r)q7tl]`/&&MuЭc}1Xš+W4ehXuѓRš9+ezqId`//{�/[`ɡł% q}1,y iSjg͏>v5iVv1s^ZֿN{Е+9"tbn¢"=tΟi(VeM-={SpV1%<x7%ۻ?=?/gkq![Qg ~SRS̝l񞪓KWuW@U%j`9u ڳW;zx)kT}w&qh{O'b_3̥}Ŀ~k-x13Xrxs0p_YT<43]8}2u'}dޛ֤[H;m=I8!:%O`/I6Sϛ|,uXSm,?-IM`iD'AXͥm)ӦSdTn=rwM9 s/S0Nw&<ןbzO>kb6,Ѵ֫�᳥,<5F':-X;ph` a%!ci8mO7:,v_tNz�x0=#C~6=C/۵Mznn^ZPqEm�5s|O!ع\< ӳ�v^itIpqx\,pfXo@,xI .@)`"pYYL=o}>vdJMZ*X˲fϙi~}h^Zx>YNu ɳTQQ!,NsuwhޅdK9~g.^xve\Ll ]:]ߖ�V7qW$H^>4qECGV%Lh`9pp&OJAG ,b;hyz[¯ |֞ ׹:|/% 0n޼)Ke:O[5q\breeh5[CiϾ}`\$lEgсϩ2= 3lP:~㩌WK?b.!]:}&kP!$h;d1乫Ս8@uDk9/I} ugC˷]wn<% �6KѬmC`l-�׫L-?ֹugJPPX`ɡŃ%g�1-ihwu#|3333zI"Eؖt$%+c[ö;ZXz,lcHc_屯Zx_g~-M{j�zI<O^!TS5!,oB GSWr-UZZ%0m_JJ{R4yKQQNA4t*euo1`;vxS~B� A(8Kuu@etTm>nk CS{͢~6"y*2ԏo=X*1V�LNNDՇ]X'C˔[qn+3rs)znzMueB*`8R tѣmT]So< mPNO>囗+ ]j3`1"mHʳEeTTꍏ&!-M(#nSu]*iq. )6�U-YL(2R3L1T)Sǁ P$>,8,ZCچ(::e5kԲu,'m8BѕjItbm<,e�=kR<':9{խ]K$ʥb`T_@� u 1f0޽{I/4cwDD?ላq+Œs13zaz׈ͥǁj*22R+WXmDÇ^KU\\@'52R$,%((&K kJ Ku 9ϧ|`1X92gңGEu;Z뢋h1jcL`XNӔŌG]z'ʵtqd7}hj}-^ܽ|̦ǁj�/�ͣ-@#G(??_LIк4l~&6:AUUF~zڽ;V\NюqllaaO r:RKe/q\՚1~?0` 5i.= ,V拆nVb|ƎM;#vP@J>}66QF]=Ah*v[GiVAєiES }.Mа*gIS2/^'p,:aT]G;eiI%%b XnCa={n 7W 'J]I@>T2</-ѳgϬK̨nݾ-|񫌷bi*eX�brܣb9jjkH'% ,b|e`^fjAKpLrDS( ؟*˨Rɚ$*RûT|*}KډSI*Y]]#:(} |,gβ,2v%K>Xv[sn:ݑJD|Qq19/^```bX C Oq,KGVں*:r2WuP,iʺt]*O),y$|jX>*,uҟQ.Eun=(0$Tk Xe#Gc$4kgiQt2)bX-,w!R 2fo S:9jܭ/2?]vxJ"L iX6'Qp80XX,%),׮_sN^Kx_FY?�tI`y_" r=17Kb1X ߹]OB#J8W6PWZ2bX 4^B>d`bX,˖�e奴m{(_bѦUSh|GZԙ֬[)}tXOTRZbX 8p`dX,%,Y,``Ɂ%%b,9p`ddX,%,Y,``Ɂ%b,[X߰V',,Y,`iU<ƍk80X2Xzw.X,`YPQOyc\Ljs!Rx?:Aw@_77ÏZn,_Xp}ߠ4qDP0ֿo}rtt,Y,` !FVb~lE= piM7,oߦ}|nYpdJo;<a%+VR|:j8\,,m W4sL>j(%1ݫ+}{ߣ7TXX`bX-,{!ë#+h Gt.3jJ4R9y؆_cVKc6ÓCפ .N``ik*--?m /_.7jkll?Qrqq-GOVV .4YS(?!M2CbZ'X{\X~zP9}g9y͠;v~7ÎK-`w۟>lׁLDE_As *:wЃG|]eTr2l ]n}Q態2 t3p0WzOQC(+/s6fExm}sؾ3¦u#"+ǁԯ,3?ӟj\n <ydpd9+WЯk U=@9O4I/%Kb^?^Ef,!R\Pf-v6\KS`4ߙjjkv>kj;x r;eFw?+`pn}2 ړUVU5=娽{[)<xVl?E6zzٴnfϛ^e!lwc5Xl]]c-G]vmr|[tH_o[бX O rHsvUNP>Y( 2l :PW8ֱ` _F9<|>jQ0eP=Ju [oe4W7RkZM|,^}].hr¥YNGsЙ4M` ˦ i뺩c*dY~YyGiѳb|~"^nnaے}|'?IOK0:jreAP ri Ɔ@^x*+؎x[X*S_SǛ[WK\~ㆰN =zD Mhsh~iǚNyWQ7<$Zmկ,˥K6@5k}|vEߧ]<z#^D9[,Y,�ǀ*&gv7&MIvS6;[fwcX;#*:bu.*iJQAAAAz"#<{{r:s}_s@'.H:RaYpJ(1%(nײ.raj(<Me޻ڵ6mL?�[>̚_<GCMX6oC3g8ƍCnnB͚5"a`ev+Wte^em_gO>:!) $|jMαԿB^Ma9 ak^5q9 (AlXoHA[@ɓ'`rw`V^hly?~X#r`Q qZ .=UUUظew5O_5D]pr{x=zkWcWͱ,))qeC64 ˚o(\VO뿫.NO~z ci,X@ ʐ˲e˪$a>q~m5ؽ?U"SB^},.@oqdBD lcYainK!驔aoϟx.RV>P2_rȈQ8Y'ai./C:" gϝiP*tEE*99ʝ}9G__o}?[P+eH]Vq7oC{%^ Zyg2t\wdY/4w%FaIaIaI!-XX65K’’’B^#a)*\LUx^Qڮ (,), !f>kWL9j64 K KB!4’B%F$BaIaIQXRXB(,), !PXh4 KB!4%! ˗JXlw>jch4 K KB!FӧJ4q:qkMj?’FaIaI!Gm<#ΠSXx!ACy.JIiڠߺ U ² )+/EdL8ܱs(// B^ea)h(222aaafCa…:|NDvC&,o/8t4{)±&Y_ay|4V:8DD4¥8;Q<s OzlBbJ|=p�~_4w-~mk77/Rg)�yمFΝ;f=P1bۿ:Zџӎ56bX͉ĆٗsйG/>sGqI *FaYIU#"CYX /(zѳ Qq.JHW‰'^EuK~[u4wԩNiѳgf qA Fν4p@�Ka#'m0f(7m:vR c1nq+לKX}~ϥaoaDǮݱel8o4S:w\TUU/]cѺ}GXY#ueK gNashq<9~'3x=, 5~G̹EŅ7ׯ/9sѱWee%~Q޾Nig̘''' �B(,[VXb<L.0y$[ )0En߹3֭_ ',- ?)v(ѼXoݾ`&WQQa4|шOÇU*uzJ]x}v:?Fyy._Q{QXday:*GCcO4~e,nP]{m,<vM=FDHXQxGlٲ?epY{|*nZZ Cg[}я~֭[#""B]'?.??Wօ-RG^%/C=zT|w6m̙3?CԽI2|c/tŋk}/<]׉ӧXf _VV y/## �~b͟?_ݫ\GzTl_رc0<Yő}t2mܸq^ /f'4vlt[tM Ǝ-M3l0cO4;tּRX95$:(Qhݽ{=Z=oⴶBlRz<s1oω@UXp[9Uؠa*=rmWf]E9XjpO<ۿٳQPP�777%w߾}޽{ǏLJ~sOQVV6tR\|Ycǎե())Qp^YFj̚5 ׯG^^z+o.r."E]\\'^^^Մr/;w 50V{cbb秄 JKAD<WFFٺ ػwzvQL֡ &ظq'NԹTk 3VVVHLLDqq1Νv "), ߧ2ʕ4DV5C'|ئ J<N ekU8 ࡈ(,[,(G oO/&cb S[k"(m*UK*MEeE}z0oF[ċbʹyUKuV 2D疞5SCr (bgggt__U+**RI{?O_K~zV8F!9sދgv.\P'\_"XWZY2QꃶЭ-\TaԹ Gplli(, e9'Ҳ2's,*cq-5gR5w}ȨjէBlRap?S0*1r_E5&{]UawSSU2Oz+#GaG[z>Su޶m[>|Zz?OKQĨV5I?S[ҪUV;.Kh8/~"Djgچ*HjvtnQ]-IV{12D,"W{dh8>�7o6pǰeZg?ïkXƔk 3WgDԊmӥi(,+!,eJsfɪzFd=={~l-%]C KY-=zAy1r4/Q^OVwg#_E(ʊq./))U y7w"k޻oFab¿d϶>띅5nj 'Lk竉 <xֺ.\[[[{%"zd8Wv55?GQ˩St=Zr }2&r^O@'MB>ZdxT҉rJ4Ϫ\2T&=A^=R2_Spt-Czq@;5L,s'ZXZrj#,cI^}, M62eai}g u\SIWiRⲡ,еU2Q7!#F)h7hW Ǐ۶G/)r U:\^h-uNr%$ck|` Ujn弣2G4O8{iDX0xHHH$2P떞0퐰 :)ȑ#o(M+yIv#Y#"HQBB'N^ĕy|Hz+s"qUbKo,<BĆi U֭߯J3Z$Nx.be?P{=%@%kkkU/B -,M]TXmϱܹ3%yu#/"c_ߑET VJ,.}NEGe`{K.,eeL|$*b0 tG6�# 啥?/ ",E,/>;9Yq^3~"wNE8iݹZ!" t|BY#=t"T!CԲF^{LY\#Sĕ7ߨ!{~g><Õ߲"^e&us. -+EKDžd[,-1,)*/Bk 2O2WQ�~+\ggz*n/h4 ˗|$^DU Ah\s~JwHđ|=oA(, =?6ҤFaJ}ұ(./ĽcŽPR</f@Iccc $%%CB(,i4 rd#;7C#a|+VN2>f h$BaI(, !PXRXhB(,i4 K KB!4’B%F$Ba˂*{]m\֠um5h=z+xED"~eʃFaIaI!²=}V>?\qˎbE΀,? '-OěPX(,), ! RŒ}'\K``o}`<�mv% +_y&΁q< 7}Wi!,o݆FaI!²>RDeyyQ|4,,l;ٸa*칈;c9|,f`t,>G  }M3Fs K{Խ'gE d KB!لFΝ;f]qoހE{b`9 [c%Xrݎw?߈nv{1cJ4M X=)j+,vMl۹ c'NQXBys/[?}fz`(|$EIn0aJAx\.> bLZ9;IXʹz||Pa!fϝNz]pt>}D`/е1L},ow':gϞu;z]c7pji?.=}\Ǐͥ7٣K$Bad²W(,=[x MRlom< YɫC,,g~9W] 9q xe]_/>o7wwL: %%u6npy!sQܣ"FZcy؉&(OOLGIiƂKeS6vԔ ;\tқ{F J KB!`5'�V;6"(2S.ue&憪ĻwU <y:"-=9B}PZV W uqk~{+ܹy;pm.g$B^za;5(�]fx{ Ior,C׳LLf6muw4]8m>9n NGQ~2$.bxֿ9Қ枑’²)+/EdL8ܱs(// B(,t6XF' XpǻaxYx7#9:ʿ[oaihw,rԏg=xˊJիGȔWU5raKci{,zQ;ߔFa\JM :!89&$7ȵ޳ &,eʆXhI|:a7:v3'�| =lpT B|L]M.ȹ\e"N9GT-rяWͱ0cs,eΦ{jZ#&\Qrrrs`Qus,|.W]QJZ!,u> 'N@ȩ 4,,xqVh 2>){<jDd(b/F!9= 9'!0HAaI!/>&E/o Xө<Ws~ݩ柇;`=v.ᘿ3 p*#uG+Qqj巗F { lߡ$P*)ׯcص{2:B"uedv0dĨj W=XVDUқ{FY#+9$r3g4(Pw sVhnaYX\=^p&R㑝^#I 8s$z@Qq|#`=x\y KBysq_ߑJ|ygP|0r+US[/5C`Ħyc#ࣰ–.,OGha'"JIRӓT܈f]d)j?-Fag@$%˗t˗s;))Yy7wpë;~3Ul%wɹ6ʫyy ?GFBa );oD[% ?T|<D[0S#@`Ь(,i>'O@z%䉘J8DE9򭨨@nݑs3K\FD�8sb:pGD$tr,j<4pOw0;.z#Qu̬,j1)BeSKGbmUxxZM܇ۣvO6kVcPRc-,57R3PTr%e&8i*?0mlu 6S5~G^'BOb\u>e=VuT=cgXm/&iS)~Ly>}}/8B(,ZXj-:V9ΓwᏃwk|L򹰬0xK"_-5IiE1.e4&=|ܲϬQ_XJ|Ju EEj G&\bdG.m~g!+C%]8͘zLeY6R &4׿d夡Z}{$'+'QFG{c'aw&ک/`MSz:-=8">}�׮]SG<1bj܅j?~"D-c#E(,KHLǷ7 HĴHNd4n` }]0Ca)km׹<e /q6£Aj }BÕO؉vq.%&R ˮVHB(,),i4 ƜgsI+KN#ʍ' mkVgb/˔Tq;%5MxH▭d>NCay,8XͻI̵t(HV 6R K K²)(GRETUko#q[W%B(,),i4 f~q/{xރ{(xV_|2Ud#D(,[K_QUff(ry$%peH\6Vw߷ !e,AQXz’Be4vq:ַA(,), ! a]XϦG1+2rnܾ�Yٗvu.];۪!i4 K KB!QwST#wb,6qYo顼u0i:[M nOc?H$BaYai5}+F.Kv8xbs@>n <Ri򓣸M%(,iB(, ,e}X)o\MT,8'ΩsWKcO=<гZ)VPXsSNsQUU[oԹ֞<yoo0yOb]evGc ګBO?C~6W3a"rr(,), !r{x1F/|ԊO4_fz7ci(,g~9W] 9q x!ܹUŭ}.nt882{TܤP\R .06vTL>%| W7i U%%!WWX9DP#]\)zoUBC?!U[.n񯫰,+/7ݻGST:JOkrȧ܌28y:ē OiC', K KB!(R+.)Q)(WgմK(**&:-^ai gdb4;t]6mu_Λ'UCMsב!G0L\Mߤ$J K;Oĥ鵴?XV[*,k^%>}z(nPX >nٳg/5- ODQ_2c=xhz,),iB^a9 ak^5q9 (AlXoHA[@Gث臕W4jϜU hd[7mlw1ޢȼLc)αܲ}g9uN K%!wˮK"[# E\n8YQ)~BgVXRHz*e[;<.,nX sm۫^/ċ8]J%eFe%jUr?4NaI$}yg2t\wdY/4weCle+’BeKVxcαD C(, !PXpa)*\LUx^Qڮ iWʡQX6"e奈 W;xnSx#2:e|Be>kWT},۰h-CX^JM :!89&$%O!41}R-Ǐa=[5"2d_xdtl~20|HB%Fai ,PPXP^KIĿمeaqxmÙSHJGvnz$&̹EŅf$i $ KfNX;aRp=8?,((Pi%Bq40R{%$I*nDI2A3`*++kM[WХ-\RO�W.'M]nѽw_|ɧl!4ZIIIFЉ  >R+$*"<s1R ǂ<HH5Ҝ%KȫIXb ϶._Z 9 auqOcfi1mL\BaIaI²iUyE9Nx#53 E%WPRVhTTVyyEE/KCskw޾}1{.l/otkddf1"PXRXhM0deWKMRZQy*MRؼm;VY';m0еѶuA+WZqj*BaIaIxa)ǘ Zm WDFW2uG +' *p۫&8Y9鈈 h(ޘj"4F4wjإ9gq:."PXRXh/Qp4�YxW$q܋w/!1-޸7L"q."9R=ġwLĤ$'>!3Sm^e߁-ͥ$PXQXJ 7F``E{t8u8{5{.MK" ݐKlna),c#Qqw6Iye)bϡB6Re_KU9uaq,8Z WJGaIQY^^nA0Mq=<|@۷w1[wlV?f2!#F"5=] ;v'O$|ȈQ*6MVv֚MVF|̈́ ipJ/6H/(GRETUPT7n~DM=!luع q]ǭ[Uw7޽*)۽wV;׹SRӔJMKr^L<5D>ScM)G)h|>X\ZS\^{?2?yJ*%O!t%ۭz,7ysN:_bo|KеWo<}TTCW<=[%Ϟ=Sszz5Ls^� ʵΪTk.bhݾHȑњkڧ:k^fϝ]ptj饶Pծj]evS~C~L<*B Zs5_QUff(ry$/xB(\l*ٸ_LsչרIbQ0)v()-ŭ۷`sTM<9R rMޭwP="T._aPk,آ7th'Eң,_/_Ye1UMC57wwL: %%*ϵ\w㤄X@zܤ)T ,]4҄%! G;:𗕫Ԑw;qc;tļ`=쇹 sZEEzN :0s\)(~湥N_<ܹyjz/__mX s,5"9w_-&kݻwU=̝-VBj{�tDE ldRRyZz 3OaI!AtNvqww}HXi{PM pofv6FFJݼuKnz,Xx_.2 ,kש{OXhkooPml-/=#٩ar yVckz&λlaG 9%IK '%!WRXv5qr$ %`X:±/@XB!c 9pM l HRi͙ G%\lUn[{/z\S T{,\RwHevM"K;gzky'},2SįeS=-gXjť ".9N!E K٣!Vw9n5F$l*,D:cb[zz.Ao5oR>&rrrsPPuc)UpMI+RkY{R7s64Yj% JF`y'j>hIIZcNXUs,%~Ms,),[4%*), !}, M6">cq;D`3,6GcM0Atka2]I-G++eO!eoˈ5 +VULk!'OB28&% kdUpS64#+BU,4?Y$qj5',e-wj²e |9Ka*%!ǏT4vŪY} քUt%-FaY7$beCYq;0tI, Β:UZuϾ{FaI!RZيV5\;4i$-: K|֒>H!’F5 <̬: KIHaI!’F{݅eLl  #3C\ʰvJSp_JIMaI!’F{݅E\Jϥ i|IKZQ͋’B% ˆ/OB!M&, !%!WFXB! K KB!BaI!B(, !B%!B!B!’B!ʕ+KN`` ***\XX!)aӼׯ_WZVVO#** \YXZ!)`F“'OsMUu Ҕ’N\X^vMuJ%/7RRR u i} Ǐݻ%Gʱ’uuBRXi} GΝ;F^"Y ÍzGjc}eCԅڐ[o\O gp*z_Yd97A] M}߈Rh "{i\im}֪ڣ\],-,?\qˎbE΀,? xcf5JX.BHSmuSvVURf@̙pMp$,>|[nՙ�Gx,iɧ땧~6uBʱ²unjD%ll|噬;:f`,^] gl{ >q{m\u>uBRXֵݹy.M0h:j'H ᯊ&oߠ²RWNh\.nLs8h&Af_ ѥZ뀱&Dh.\ UG5QKʵYꂅ8=NS\?s\p֜o>G3H:L?ξJX+z`t[t/V|tt֧.BHSPvҴi6H0U9? 8WҘ3) >ڶG{o4a)ohT|](ۍBnxh)N<:<yߴAiɴbŚWq,ltRul(+,S,!J)<h=퉁(o=0bI ZنwmDi{1cJ4M Xʬ7n/Yt?|zW>է.BHS ˺;66+Vt\Z^ќ_y(_Rŕ4Ϻı` x}P} KY^=V"coq{0<rwŧ])Ȝ#}uIt %%Få@Ͼhݾ#FkeoVDr}πHJNQٗ/+qrr'%%pc4m>ՊLݛ4a1d(<=kURu lg(mQ|Iv6 A`x":߆_^{b&田̊KJ7iVt<KTNcb*sf7 Ҕ²Dшe_}3Qx1.衐GGvKw_a]0צ4B-kP-菧 [0kfͰ poo/!ی3a.[åfDzzFe7^e#&L̬,ŸISIRA]R<w|kzf 6}Lݛ4]zF(//GFf&/Z\V|کuR:M܁_Őa^3c+J+U}g{nin0L^͕|y ;\0~˳�UwMb.Sf7 4DsMG̈s%NNBF? 8T^=Y#33doio]0צ4<̽{2pmw3z##ρ R)󸜓EKF7>h׹ f9EVv.\ 񲦁׺Ku[Y@|%b|<zΏ'u>yVY {喿JNxOXKe0Lcgތ^2=ֶ<)G)O)צ j1X 'PxE<’2 ii~ 11ZӚ+Ksy*7suO] ڝ|h+qМIsZp\o]0צ4r3tֆ\_[>Әex\&'><=lzDI7+Wā:?)Dx~ Y\\s˹=?/V_PX]!??vCQQ*@t7.3uoҜQevGtDDQSʵ)Bmj Y.3a`=dW23)9YQ~">lV!CWʻr1r3WBi ݩ(-El9&!g„hO$|Dgdmk,iM ڔ|7}DZJY^&R WudzMx g<Wx} ~I?Af'.n qq:w JLjݲ8hmZ,ISi.&?sf:R.Gs^*) օɨ-N>ZwCj~BD_FJy2B~;O}VbҴ5<LO] iwʊqf�2G9R6h0#qM8 {0ƛj,mS}R&>Hrn);&ʗ?33,axY<'dž޼ Ǹ:|&کW Լc0z]a}Ukռ'c:]]hYlپ]7oۮ2سtMs5L51PXXGڔg]&׵.ԖYk7tugN�]&oۡHxEc`LX~+JåZ GT9z]HF֔<LO] N{_?z-$$++u đX~Q<'$y?L ڔ|7^r3UUUj <Ǹ=xm<f?yG~vn:l?ܚ$1 3%Õ5tCu_JLԅK!^_O)ZkME詐sӆ_\TrGR>9ޓVSOooeZ{ |'jiRRRMQBt|:=f§S=y0>̷m?8`SXqQTd aj]_RF֔<LO] N8H }ݕ;wo w[ҘS 9>n^@;Q'a]0צ4ܐ܌$2Q`TO䓀~x6O'I(9<Jhd~gؽ-=RRRMQʌ~xt姶^jeGM9F<>!,& Է 0�Ab۶UkOB\b۵ӅKQXjs٦Rbm:H+CjkSԅv0POǓ=jAՈ<5t3z۹!r.˸!4nwrsҭ 9?oxa)JWnFAqoҨԎq?DbCjkSԅ>MUxg&? &QM+!=3ۄuBiw._FBk\XƜ䐗)G)O)ח.G]:?b 0polg?9 uBj7.TgKXڮqօBi 4фlI^rǪd]`] lw}(C၁222KNRR:TpBiʡp;oK///DEE!--H:qDV..BHSXi}l`UҕJ^Nb ++K}uuuBjt;opaV[0'/_&/)\Z续 Ҕ g|FB!’B!PXB! KB!BaI!B%!B$B!B!’?!B$B!B!’B!PX(, !B B!qxB!Rt’B!Et&e����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/images/queue.png���������������������������������������������������������0000664�0001750�0001750�00000027425�14035600052�017336� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����������� pHYs�� �� ����bKGD�����.IDATxyTW'$Ϝdf~3g33s&D,F QAw]K4qCAeѠ ddi}7TĨjM]U]m|=}nݺu]~~0mڴ'Ot<:Aa8-,,@MvgK(P@*%)etPG8 (P0<@Q9]h\_C  L|[t%lxZV (Pw+*4%m*j~j>]aL  lUh, e6_& {=ټXٹAFQ^"gj,S~$z񿷏 5 ^^%?qgm SjKE0Pfݚ0qԎ*+n0߷,vFC~m<+`~wyA!:RVQ~0$B3G*-b6OIHvCsӧOkmZ/yϘ9zLb+/<mɳqoi;ge:{'gN6k GD)(= @.Rĩ6xTQP(:p4B>r5d0FGG? yԎ~'"/pmll"j5wMᰦ=<45ilcOm3sOxUI7o D"|e+6S6|m.|Eľk}dOk{D9!_%l .x!$$znXXm QUUUG54jc/hnEQ޿#mvvvعels^*OKffxu݆])./\5nB?[!ãcbubà. /�r" YkWv.x'Vo7ΊMgg*LLJ:m<5pttǵ+ok|X1>k^Zooo_v{opųÐgCBwXg7TR.* *̀tU jXYd Ѱy´p/Qh(Qft(cW (z%\g*9\rC&Oۺ}ks)q åo7cJU�!c,Kjjj9 Ϭ] 949koZ/_z8E~cKuD8|XBp6G~:BJJKk+1p+WK7 BbJtdw1)^t$Oe^R.&C)2:QA_~ ݖ w ^Ve)Z';UQ3&L)-!0y"oZ`p¢". ck<---XC+W8d,{ٴwh] [E]yZa[t奯`3<}{w$Bkdܓy ή wksÏiBX XdWTBXn*hc/ȱv0%-cwD|WWo*7vܪ ̬+n`'Mfj(&9y읜<G&}GV.H]q fVk|GYUXp_mv)}0@O٧Ϟ]nS=z$¹M+[p#,-+9y [fZAb''[YY a~f@:" @|a#G ̽V_A[IńiOe:j ?ڗs BUF Y&&վkkumTzYOqJKOW˦GIKYȑ]vo@pׅ>tPOM_vX$$²[QQamkoͻȣy|M IOd\B<+;ۅ͠f|Ɯl퍌фN<i^.(p~^[)Т4UgN''Ev#`bLT\qmAlV*߯N '<b銕ZM휵i6ωsAhp.* &yk' r.H̼K:9>t|SgPPb*[ㆡTpq$$/Q^^amhI HrLBǨ1x:HBc*82}702cƞNH/~\-tm,�[G7"\eb/'`zGp!%=B/aϭb* 32ٷd eg.KJK}ϴ�}f}ǟXL<g-kNSoÜt!W٩=w~ Oh(`afZe#&#ٵZٍ]NvkbABvUfSϮQ;ܮ^aJl{EMJm^@'Wj%]7EŊlY[[+!G$5hf_aVU(8 |rhk<[?ʬm~U柚[B|`+7\mXU]]^QΨoY-BP*El[SSsqe Ohe };J*rQ[U_ VܾQQήx]j5N ޓ]B>-9ue+2~ Ehk:OB$$A$A$A.A.AAKAKAKKa!I7`WRRRlnAcY{ є]|fdǟ;w! 'Nbzm#v4e 1-(}w~wEeƑݻA֎΅BU�ِ9Lqd`._.b u ,Mٍ;;l!Ƒs߇&DCXkə{=~ 88{`ܥ AI+Xr 4n)p Q!݉Žwkm=f\a00KA~"B vZQ*IqgddBFfQuqI[[+_vUJ]F]-ZuOx?zZ钒 ?0k^w;::m6vjd: u%\5]عeW47-"w;$t5cCH_8jΥttL`&,6s_k\sˎ΃ #1s: --+9uBIi^npM/"3UTOǞxaVw5ioIii]] IL<ԙu`g׬`:ϿL,Y~㗝V{GJD)8:S8bيU }Y9s<)(8ddo.} 3SM#\AT^nܻwO:څEyNn\cD^~f!Q]\323u;feӇUXT߸v&C?7c=~Bpu"ὑr@tkBNRs=ar3Wp>ZeW(4{WͲ~ndgg߽{W:څE`IS}mG~1֮Q7mֵ욕Lǣ j=ⳍ0b};}fla.s(VČ̬sLvq&!Q03aҹb3K|&5֙+Ze75-')Jhm1;wHACE8p7}Od{afhRRZ+T:mG,rlxDfou"Gssӧ vLt.<sr\j?0"Cdddܾ}[:B-pW_<c\wyOAbEe媵yܶ}:mpkwlp쪭̜00};K) . ݭٛb8;`AVv6zDI }Yb3tWOǔG:s ,zIOOut4Zx|<4;PWAjG|i6uP;)ܱs Gͺա23`c1j̑ !w$$&S=Gٛbx &COǞILLt2/1fhuuC8|PHw&enݼy֬XB;;q)5u0qpn8`RSSoܸQcV,Y:0'73)+]8uRY)}W8W8*tRKA}G}gtC]\8 ^diiY#f+ ٌ7A֎e9)#v,Kv A˕K &O Mم<sR/5dfKKӗA}PvK >(FADߔ]'~R -),kHvVv_:Xƍ/U(~kCnMF9jdBXQ3[c'-\3}Ѳe,8Ds5A$"y+/)-C ee[6T1n1z\ݚ[ZD"vZ$L+}y_Lٶ#dRdQvNC.A[8 2̣HXLKGG!lcbG [[,Yq_ X͛siڤȑcLJgkϔ }_G ^`"ܴuB@,!LQǏh#`Zی_ #6m ⧠(vS\*#.^<DDBvŮX|0D`%*kMp䘑]].=j%<^};:Hv,w8y`rq'kizf"PU "^y zzzܹr֬ sE!3q;w͜qs=3g#Ng/<o"&_+YMWÌ_ qSͮ;C"Q@c?ϥqD]]+ڽ7} 8;ƒZ6cFmrjրy0pC]˒[osy~qG-|"ήmmm݆!xOvÂ/\pqSuu\U14p sqK#>a[Z[u5y~eW~&\ 6%w([^l9ƃC]+B'8;ƒf6c.J`]<|Sjm-ɮeɮ8DXT#9awReĉwL<1eW0)ݧXD,^9e+J;S !R=z!Q)q W2b � F6"{|{~Gm^jRKلF8e*[t9 Hj.5(d'A!Nip:!/>5UUmEUʴv5%]1jGYʬa% IɈHJ^b%ga&/[Jt0l(UUT<F"[]sU땪#a9fZՑQ.*.&}eS2)gϝv9ux)6ESS%K5G.[{DYWfܹ;̸{PǵLzRptQrָ+JIXz}䜼<H$[;D쉈z¢'QhW؞wt tZTM1bobUKGgM+V ɮqn m====ܮ,xZkÚ#;:&IM*aNݰp2=j]шFc.y\O؍7!%5dWN 56d%cZz@`SCt(l^<sod`x*7dX̦uB?MIv -s$AcXl7s %]´<7}8 ~ %] ]] ] ]] HvIv Hv HvIv Hv HvIv Hv <`d1[/nݺug׸Gf}dZg#y+ggfOgc<+׬~Kojj="$5fʺ}ƍu0Zm>.bH9w)ܽw/,<2ͥO25$4 BIk4 `p*QXk9u5#~X"RĬ}{Yvsu{iC?!Ϗ{Դf*W= k ǽf}͌}{Yvsu{m5.]ѹ|l s$l@]R%J{֚AZ]AVP63:e%V9Xl 6 +R[ZKGZHvC~ApRB19n_Z3q^Yef3s_3`+go?nf{PM]q9gW xU?ٕV>bjRlF羖 9:<:l7$Z5 11 q^CZ^eεV%9Xl@\>Y6nv'NsnHnJNkII~e/&Vǫɮu9X\]l&8ߜ0z6vCy%- oh1gn9MM$ALKDo@Iv Us0.A..A$$A$A$$A$A$$A$A$A$$y&Hv{1 _`F^sp_]LsK.!7ɮ9 :X7h:{jYlmޒ3 ]wa]w*gB9GUb3ẎU.yny;wa]4T-ya^}EMЇU.yn0`8D߫k'5i%B)!j>\_^vs{.-+4tNkBԜJwlcSd_)EMkY~}jm<[S.LkrU[֑mC޻*iM%9XM$ 12'¥ˎ?1y_XxDwwwSsVI,o.yb}͏K'5>bNCeNڬܱM]3)(y1CT 웲Ksٕ.,m&K`] zLKDBIv HvIv %% % %% % %% % % %%us0Ak6$JVc _VǛZ r#3d8H;%b)v :nܱt>鋲cQ.kվ׼Ks0kO{GIeĩJoEeE(E]X\eo]lݞ9.ᦢN{I)X 2>'bEu]"|VAgS}ٛye<[`d"lܱCGId@6}Kv;[:x`rڗX.y2YYs/o[W՛>$2ʑ]XZ$f]luUT\L LH]eWViת$ 9j<'M? ]|fd_dbzM*Zdd<[`i'9XkBsO:!+5dүy]z cB.\ cB.8 d wBKa4MMK)-+ G<$AF]%W8#e<!&%0>y/%" E .S^A%%0Ap.AeW] dwIv zIv'q0AA:B:=+3W8A.Ǐy;qw?A*:9}o ]s:! MvR_' Z E"%%0Ps+ ME2yq� (P/pvsS#[R>y2 ^&(P@AWThlGGK ~j𾜕 (4V]vTaL  ܂" 20 (P0<dbzjll [[[bx%xdxFwwwFFٳg24 d${ȑ'^p- .A욄k׮oG�6AЀ&]]nkk``ZI ╕Ј5<x~e5&{8*64`Hf ݕ]T8z{tM3mG͜;/(8h9z31)\s.yaGz^** . \qskK ~_8;;@za.q&vmmJUm&󍷯?[{e+Waoo@h}~`c+Z k!}kT*#n^C$&566BϿ\}-d[o:tWE<33S΁:7d-# imo :iƇ\,UUU ,xCvM'1z'<bls455\]lQ<3ЦƦ&؆d0]Av.XkX%0J]'֮st4%tV;w spB*߿El?7x74شiꫯ<==ׯ~ka?~@v\Ųe?Ǐojj<4k5tC:_ChlkR4qqlEڋ/VWOY%W*`}}O~nٝ5˸qpWcWZZ^1˟?O]]]U*߾Wb G�s.Ce0&+j_Dq'+pdW3ztC50d虄Đ8{JjڥUL&&{:G6 R\"'mKvٽ7\.4KNLJ:mdSYސT `u1g{ ڶ#R{bXxBQf]t_ .1:nA@dСEEEK,ׯf %%;ӟ... \h}YYYii ;ڵkj555G>}. D|eFkMظʱ[owް_˱R\)Wg WwkFŋɓ'1gjkkLeQ.OBkWTVaKĬƀh;XQ3Sr`yM7m1 Sxa+X Ҁ &n=3KSv+&(bYq: ͷa·+'Վ\eeH_a~]&ib\]S3pd;FZ^/# 8n?;ˑN,R^^1`uj믷Ma!lןg\<==w079MoS3{ѻ U3f/ٟ:!b;qWni>7MѳF澸%WYX欬,.|X~>uuuxz(مo=UU|A+Wg|#vsDh1n㘹2*X1+6Gz:Kʚ0ɛ{]/O$V+7hջ4Maɭ]c,"~nȖ�Ab޽R-"Ɂ `eXlaA3~"Z) 6䋧z6$ՆÅ+7*dh cSYXf _6Ѫ\\, lmm|MN֑d7'7֐Ȥ~T m?AԬ]o.\rfv֚ dTt,8Z-ns$'w4JN j%ڝ```yI~Ν6jMww7 6 6L0?ݴ4.,YtG!Ns˃@0iʅG|aiOvY9eW{3my)9Q\\_R23kfG]vUWWcⓝ^pILJv2T$Xkˉg_Z:85#)d>DlVK/HVD]4K6n^~> IOd@xsHRR!Oc{FFaX ͐=ŏnr;w% Q*D)͛goo_ _l5k !4>| g  h \A+i98 kkkwZ\}:܇ ۲e_|Ά-28[Ed…\X~xtt4aJ[oeXy)ca�c @n b ޾Kl~mw 3 Xb%9LWe\?PϘ3ccڲbYqsJssf+x"Z 4շLeb&Xo2X $$zz.>_N5d@U2cƞNHUv 17ol䁙dDFF;?я%g?&^-믿-""Bt6AȔt:ց:xw{ļN]dѣ׿` 1Mo8pڛ o7MB? o2&]jcd=~VQ&\HIaOG]FWrd{NE*!h655]va8^~/m9jȂ#֒Ot,}En%Z HVPM[9q3ӯ4M&5T8kv27n/@kM XZ)QɔZׁfםŊ#vYɾ_.`ߑh2k^~@WjfxZm  UYIy`P"ɮnUuuyE:}WOvaqRC{z'C+(<u%Hv@]]*T.Ak(x~[I4@ɮr0x9B.Aڍ(#^�MJJA$:IHH JrC$6oUU}A$A$$A$A$A.A.AEv AKa>-$ Ls% zݰ]α����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/index.rst����������������������������������������������������������������0000664�0001750�0001750�00000000421�14035600052�016063� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������User Guide ========== .. toctree:: :titlesonly: overview tags/index searching stats_rating.rst browse/index queue editing_tags renaming_files playback/index shortcuts interacting config_files commands/index faq �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/interacting.rst����������������������������������������������������������0000644�0001750�0001750�00000007367�14470736246�017323� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Interacting with Quod Libet =========================== In Python --------- Quod Libet supports :ref:`plugins written in Python <PluginDev>`. These plugins can interact with songs more directly than the other interfaces, changing or reading metadata using dict-like !AudioFile objects. The plugin interface has not yet stabilized, although we do not expect it to change drastically in the future. The Unix Way ------------ Querying the player ^^^^^^^^^^^^^^^^^^^ Quod Libet writes information about the current song to ``~/.quodlibet/current``. The file is in key=value form. Key values are in UTF-8, except for the ``~filename`` key, which has unknown encoding (but will point to the file being played when interpreted as a sequence of bytes). There is a ``--print-playing`` option which can use the same syntax as the RenamingFiles interface to print information about the current song: ``quodlibet --print-playing '<artist> - <tracknumber~title>'`` ``quodlibet --status`` provides player state information. The first word will be either *playing*, *paused*, or *not-running*, followed by * the selected View, * volume setting (0.0 - 1.0) * Playback order & repeat settings * Current song progress (0.0 - 1.0) Controlling the player ^^^^^^^^^^^^^^^^^^^^^^ Quod Libet understands a number of command line arguments to control a running player. For a full list, see the man page. * ``--next``, ``--previous``, ``--play``, and ``--pause`` should be self-explanatory; ``--play-pause`` toggles pause on and off. * ``--volume n`` sets the volume to anywhere between 0 (muted) or 100 (full volume) * ``--seek <time>`` seeks within the current song. * ``--query <search text>`` searches in your library (if the current browser supports it). * ``--play-file <filename>`` plays that file or directory. Quod Libet can also be controlled via a `FIFO <https://en.wikipedia.org/wiki/Named_pipe>`_ , ``~/.quodlibet/control``. To see how the command-line arguments map to FIFO commands, refer to ``process_arguments()`` in https://github.com/quodlibet/quodlibet/blob/main/quodlibet/cli.py; as a simple example:: # Sets volume to 50% echo volume 50 > ~/.quodlibet/control Integration with third party tools ---------------------------------- Quod Libet in Conky ^^^^^^^^^^^^^^^^^^^ `Conky <https://github.com/brndnmtthws/conky>`_ is a lightweight system monitor for X. It includes builtin objects for many popular music players, but not quodlibet (yet). That doesn't mean you can't use conky with quodlibet. After installing conky, add the following to your```~/.conkyrc`` file:: ${if_existing /<path to your home directory>/.quodlibet/current} ${exec quodlibet --print-playing "<artist>"} ${scroll 50 ${exec quodlibet --print-playing "<title~album>"} } ${endif} will display the current artist on one line with a scrolling display of song title and album on the next line. Conky will only attempt to display this information if quodlibet is playing. eSpeak: Speech Synthesizer ^^^^^^^^^^^^^^^^^^^^^^^^^^ You can use `eSpeak <http://espeak.sourceforge.net/>`_ to hear the current playing title. :: quodlibet --print-playing "<~~people~title>" | espeak -s 120 -v $(quodlibet --print-playing "<language|<language>|en>") In this example Quod Libet will use the value of the language tag to tell eSpeak which language/voice to use for the specific title (Use ``espeak --voices``` to get a list of all available languages). You can also lower the volume during speaking:: VOL=$(echo $(quodlibet --status | head -n1 | cut -d\ -f3)*100 | bc) quodlibet --volume=$(echo $VOL/3 | bc) quodlibet --print-playing "<~~people~title>" | espeak -s 120 -v $(quodlibet --print-playing "<language|<language>|en>") quodlibet --volume=$(echo $VOL/1 | bc) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/overview.rst�������������������������������������������������������������0000664�0001750�0001750�00000013312�14231604332�016630� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Overview ======== The Fundamentals ---------------- Explanation of the GUI elements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When you start up Quod Libet for the first time, and have configured your library, it should look something a little like the screenshot here, which is show with annotations. These are all explained below. .. figure:: images/main-overview.png :align: right :width: 350px :figwidth: 350px A basic view of Quod Libet, and its GUI elements 1. Player Controls ^^^^^^^^^^^^^^^^^^ Provides buttons for seeking, changing volume and changing the currently played song. By right-clicking, they also provide context menus with advanced options: * The volume button lets you choose the active replaygain mode (album, track, automatic). * The seek button can display the remaining instead of the elapsed time and provides options for interacting with bookmarks. * The context menu of the play button has an option to pause playback after the current song. 2. Current Song Information ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Displays information about the currently playing song. Again, the context menu contains more options, like rating and tag editing for the current song. There is also an entry called *Edit Display...* which lets you change the :ref:`tag pattern<TagPatterns>` used for display. This typically includes the people, title, album and maybe file format, bitrate etc (including :ref:`internal tags<InternalTags>`). This also allows :ref:`text markup<TextMarkup>` for styling of your display area. 3. The Song List & Browser ^^^^^^^^^^^^^^^^^^^^^^^^^^ As the name suggests, the song list is a list of matching songs presented by the current browser. Double-clicking a song in the song list will start playing it immediately. The browser consists of a way to filter your library (songs), e.g. a simple search or by a list of albums. In the image above, no browser is active, so only the current song list is shown. You can change the active browser by selecting one in the *View* menu. 4. Playback Order ^^^^^^^^^^^^^^^^^ The active playback order affects the selection of the next song or what happens if you manually switch to a new song. Note that Play Order Plugins add to this list allowing QL new ways of ordering songs, like following your selection or adding songs to the queue instead of playing them immediately. The *Repeat* checkbox can be used in conjunction with the playback orders, to repeat the currently selected view of songs after all song have been played or skipped. It's important to note that the playback order will not affect the queue, which has its own playback settings. 5. Song Information ^^^^^^^^^^^^^^^^^^^ The area in the bottom-right corner shows information about all songs in the song list *or* about your song selection if more than one song is selected. It also shows progress information of background operations like importing music. .. _Queue_Overview: The Queue --------- .. image:: images/queue.png :width: 350px :align: right The play queue and the song list determine what's played next. Unlike the song list the queue consumes songs (from the queue not your library) as they are played (unless configured not to with the toggle). That is, once a song starts playing it disappears from the queue. The queue however, takes precedence whenever it has songs. After it's empty, playback will continue in the main song list where it was. To add songs to the queue, right-click and *Add to Queue*, use the shortcut ``CTRL+Return`` or select songs in a different browser window. For more information, see the :ref:`Queue Guide <Queue>`. More Browsers ------------- .. image:: images/browser-window.png :width: 350px :align: right Besides the active browser in the main window, you can open as many different browser windows as you want by selecting one under *Browse* > *Open Browser* or in the tray icon plugin context menu. In a separate browser, double-clicking a song will result in it being added to the queue rather than played immediately (as per the main browser). See the :ref:`Browsers Guide <Browse>` for full details on browsers and the various implementations. Example usage: * Manage playlists by dragging songs across browsers (eg Search browser to Playlist browser) * Edit the tags of some songs while the ones in the main song list get played etc. * Check out other songs by the artist currently playing without disturbing that list. The Library ----------- If all your music lives in one folder on your computer, adding your entire music collection in Quod Libet is easy. From the main menu bar, select *File* > *Add a Folder* and browse to the top-most folder containing your music. By default Quod Libet will scan your selected folder recursively, adding all the songs found to your library automatically. Add more folders if you wish. Depending on the size of your music collection, it may take a few minutes to perform the initial scan. Note in newer versions, you can now *move* a library folder using the button in the *Library* tab of *Preferences*. This attempts to move any given music root folder (aka *scan directory*) to a new path, migrating (but not copying) all the tracks that are in the library under that path, preserving their library timestamps, as well as playlists containing them. Make sure you **take backups** (of files and QL metadata) before attempting any of these operations (especially the first time)! Plugins ------- .. image:: images/plugins.png :width: 600px The image above shows the plugin manager, from where you can enable / disable / configure all available plugins. Note in newer versions of Quod Libet you can filter by type of plugin, and view problems with loading plugins (e.g. missing Python modules) here, too. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.957602 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016015� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/backends.rst����������������������������������������������������0000664�0001750�0001750�00000006224�14037102221�020320� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Audio Backends ============== Quod Libet currently supports GStreamer and Xine as an audio backend. The default backend can be changed in ``~/.quodlibet/config`` by setting the ``backend`` option (``gstbe`` = GStreamer, ``xinebe`` = Xine, ``nullbe`` = no backend). Make sure Quod Libet isn't running while you edit the file. GStreamer Backend ----------------- JACK support ^^^^^^^^^^^^ Quod Libet now supports JACK via Gstreamer's ``jackaudiosink``, if available. To select this, check the *Use JACK for playback if available* button in the *Player* tab of *Preferences*. There's also an option to auto-connect (wire up) the Quod Libet output to JACK output sinks (e.g. system devices) or not. Custom Pipelines ^^^^^^^^^^^^^^^^ It's possible to attach a custom GStreamer pipeline to the player backend under *File* → *Preferences* → *Playback* → *Output Pipeline*. The pipeline syntax is equivalent to what is used in the *gst-launch* utility. See ``man gst-launch`` for further information and examples. In case the custom pipeline doesn't contain an audio sink, Quod Libet will add a default one for you. Debugging Pipelines ^^^^^^^^^^^^^^^^^^^ In case you are interested in which GStreamer elements and audio formats are used in the current pipeline, start Quod Libet in debug mode (``quodlibet --debug``), go to *File* → *Preferences* → *Playback* and press the *Print Pipeline* button. It will print the whole pipeline used for the current active song to *stdout*. For debugging GStreamer related issues see the official GStreamer docs: `Running and debugging GStreamer Applications <https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gst- running.html>`__ Gapless Playback ^^^^^^^^^^^^^^^^ Gstreamer supports gapless playback for all common formats except MP3. See the following bug report for more information: https://bugzilla.gnome.org/show_bug.cgi?id=620323 Selecting an Output Device ^^^^^^^^^^^^^^^^^^^^^^^^^^ If you want QL to output to a different device you have to pass the device option to the sink by setting a custom pipeline. In case of pulseaudio you can get a list of available devices by executing:: #!/usr/bin/env python2 import gi gi.require_version("Gst", "1.0") from gi.repository import Gst Gst.init(None) dm = Gst.DeviceMonitor() dm.start() for device in dm.get_devices(): if device.get_device_class() == "Audio/Sink": props = device.get_properties() element = device.create_element(None) type_name = element.get_factory().get_name() device_name = element.props.device print "%s device=%r" % (type_name, device_name) dm.stop() which should give you something like:: pulsesink device='alsa_output.pci-0000_00_1b.0.analog-stereo' which you can use as is, as a custom pipeline. Xine Backend ------------ The Xine backend needs either xine-lib 1.1.x or xine-lib 1.2.x. Since most distributions make QL only depend on GStreamer, you might have to install xine-lib manually (*libxine1*, *lixine2* in Debian/Ubuntu). To enable the backend, set the ``backend`` option in the ``config`` file to ``"xinebe"`` while QL isn't running. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.957602 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/images/���������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017262� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/images/replaygain_force.png�������������������������������������0000664�0001750�0001750�00000027423�14035600052�023307� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������ƒ��� pHYs�� �� ����tIME 7ܗT���bKGD�����.IDATxP37dҝ82$_2i-;zCޭ^Po$˪$B&;.^.H:Yo{)>sgOsw"+ߓEF\YdeEF\YdeEF\YdeEF\qYdy uwwwAHYLeb[ZZBBB ųgϞ Y$Fa |0v64ya`` Q){ƌF $,|d5#d6J2/<_Ysh w1>4ioom4d*=wLJj60ui3>۰)4<_(Ie+=q򜅋}|:7Ν562!)vݸʃȸ6HGL34F*-#ѝPTdν GwTDhV@vc>?qjѯRE* a7:6N׬h@Í!@.^n#̌Zhkj߰-ۤՁAL)R#@Yd/r$Dvƭۤ*<h�Nv""c>n"!](FfF))؉yrQA===1 fФKoWUUiZycjMuPRU | \H[((̾2S666w [�(n}}= HI3 .8̌{Z(?MMM gBVVV:8/,,F@ZSqJz .~qC;c^qȶI8 dÃD2".tT ·&~~~\ڸ]|.%5E|F5A8%[w꙱y;cyn`]ŏ;*RqVY )�uT N=hzF`-šAG$}}}LKKKo<hNJInu?j2HjMau}70l,6p�&%cwt~ts4-<n2 nB$?_^Q!AG T@[II ~nqE!?q8G⼴2 G VSmnnljnHJNnu+_l&3EQQ`gQ5Ton@byzr $5-}??`֜/</(I.]fzDR/<i>۰)"2:\f-مü]8X ! aG|EEEwl!!= o4V\*شZucc]CC]Bb@T*"GFQD׋4oȨ~Gt<H"LaBF[Y[$&œC0rzfjH6V p8njME]}Mm6.>P䕗ÂVb(6 *"*ūiLećqXD- Ba>Hwtih8$gxL)X e*VQY`4yy]K(<:HVH`5x2Ʀzҋ ⶟MUIqcc=,8$xz/S'0تBޭXT+#<^ufJjb*R82c^̐B_uaַ,SjXSctfjHO e ! "V*,( ny58.(g%%1SRSA&GYSF:: 8zSF+zn]0-*APA7V#)8RPPӫʂ\HQZE fav^ VR3%5E@P5TPHOGgM}9~ʴیsZ?pѤvs]t9q:o`R{?4,յbU"?7W 1 q:35$K[wUBRn"UAp]s+;; gaJJb(sQT UңAh NZZ[;no؊ΝT@KsOLpqrj₈ËEǓ�<_"gegyxw⢕yi>zL f�PxҢt֖_@.AaGo{fdd >wFS(<GEPT UczVg[6 29KBL54|\�3ߌhhZ~CVv{69:ƖƇCu 'Ϙ7 4軷D(�srySYgL--fMI�#՟'T!̔ͭLJJuO!Ԑ8/mL!"%[FVZ2;7/+k^>=p#&Z]+ 3%5EQxTAuP)!=8♲Rl\n ,oG';V7oG߽̎@aQ pҊ>D$;UIƭh|{M [.^ڷlF_AA_MYgIL^3޵mݱYܽW$Yq\OZ_=ɖ#9T]]ͫgF^eoBDliIٹ~>׮xy{!\vX>H̔FQ$RzʔpOI<+((t|r/ P'xz;,:7>ƟdYBI04!;}̅EDlز 8B+ oaXJf:K?O=qdR$9*̹!5!Lp `;333߲A 鉐'̿fJIONLMOܞ^))8 ;ZQQQ-A$f(6 *"z͔~"`~<Wc9CH3nX l0ky<$,|up�ᯎs⦬$=p.Z|ќqx Cp},"ŽU())'Og$'%y]垜 =Sj$LQT RTȊ#@HNIYnCBRҗNϱpR#qǠKaWCX ;P* 7;p8ItZq"=T n4bCeՠ Pq37@p{&%%ACLgI|q-CacbEȃst4K"f,hvpʩ`77/#:?v4800g/^ V[+TB\1g⽯N<xY@!JGU e&Laoܴ ÈtPk{GFԙBB }ќ:?Y'%rdQ# ?xɋWB:qyLP{ór DCQB%* =~kRr OĽ~0O /q@ۦ靦g ML+YY,|0<e&P]]]j(TH/;!MEMۅ"'A gL<+3n5Ssriu#B:^5hB:nd*пi.G `ѓ~o^N*4|ݽbfڇ~?7'rh~F\ACBB߿T*<=%,(t"> [1¢cXǮ K@@A|f*ԯLIVOI烣W7e%K\\pn|98 t٘i{5͔nnnvtvYt'_əCvGB{D! #{'{<z}bd*ᯎi4շ@B ͡_alz.n_;A7 lfN9:!lr$E|׾=dغzya4#ar/A所^wV0#d›2S`qy ˍ0yMER! f//Eʈ;ĥ8K0iO))wL54"o_WL ^!y\O^XnNę.mڶ}2# QK  25wq+Loj8G}<| 55a[w☟!DK-)M''Hn`a4npQ(ᐈE %"^|V]7a lƻaxl\U??{)3dim [e;*f7G`T6%%r]&ː!V8$"#>[O_J!F-[<mHDF|8"Esnx'ÕDėe(S~uBS?nwXY솬\8d[WWGW[[7ߴ]Ȫi~!C4_n݈csRӇjʪtV~-6Ťݑ P}}=~5MkA }Sv ( ˉ4/%^f^Yq5j FSʫ=7 u(Z]UU�.))o!lkkK.$Q9c \a㇟l0# s1ק#nb\̚T W ړOX'˔뱜KS&Gy_<?v@boWkЫO&d4cWRǥ leeC9jzOOmD+|쒑ٕ+S +yXXZ錉0k!).G#ߖЉ'##΃8] +Ϗ>r`rZFW^xC-g-̓念{'b#dÈ---SSS3_ 477ǡL=Ę >1)?oMf__hי5!e4& KXBS)cDwΚ>xW|#Л~nf O)6;.=y( |/-- ('&&ʕ+ߏ{-_p!)))NO?SCu_;t8sLΞjOHH@ʸrѰ`]T1`Rʉ2 *ew߂ouu'BZ,AUYծ1({-"^\ DD`Fa//^xE=$Ғ0(Lʉ!Aw"KW-;&'mZ}a>|,u ,JtRց!"җz-u./zXeBj^a XĐˈ#N\0e f&޻t٪%ЛDrIXB`x۾!q{JB|sV'7,Y|sU$>3l3[r/LMFF(}(J�c*W瘏'Lzұ_Y8saE"]RlfX"PWb)8,INNF/'*2uh95Ѐ<AGMl:k{+=E~ %IJeEG\^+{yHyxɖƒa`w\F;"& K`-f͟w'&a.2]C0Ϳxw{Im~ ȢE QMM|kE(|)mu}@ii)|,qAԺ$>!a[1265;;~lUn:?[,]M|I䃱x uBT/vů@Rl3A$,,,..&FP;d4EаMی#f1ɓ֜vݻwtD$O\|%<GA!Yz M_j[\YSm1 111UT*c8d }bAAANNľ`N`=<<ęT52 jFdirᢃ35%эpy`l`03 fύGSg~j4afV69#_B9q=KOϞ=`!tqyEd))gJPPPdd$|tDqq1]d#޷`30I}tt4 gggc.Ȧ ,t=tvuM54jhlG�&LԘV(߸eckŶuNPH?Ç:G Z~#9wiO<Ayflߩnkol~{oσ&]tDaa@ADx)7OGڱg|Si)@, xIYy9c|IiټK!Dkmk#fC?;q2#=T@ѼD(%q/YE^{˜" xxyy8dTvZZ;HVMV#;xhȞae!Nf:0TNSF�\Ri/(ܺsC2p%utt2;yh Q.2{}vHH 33ną;zۇ1NIIt'44#Nc:Fvo2}qf7/ݦfBU?ϴeWjř( 3^0,=lx$K+.v/eĥ"އ˓ 1DK{Ӎ7H&@&Lκyx"q-;ǏWk>?DoMtL ַaUy[ ☆ޏTc =9>+jmÇY"O7y侮ZOF\˴}pN,--MMMϞ={17 >Ü/#+8vW|̵6Ö^Ϗ>`&q;:.^1#wTB_'Ḅą˖<aҬ =)4} t:;;-oeoA iE*}J-'Jpp0\;XB&\-V.4%5T$N7n(=$!CvDkMѲh_2-.Rq$v/%PL"2e]�\tw.I 1ećq =uUB4L/482qV"5,0SŚ*y![ [!C\cDY((Lyr?WIoTȜsuN=2qG^$8B�˂riZq^g]ď')aT8*oUKptT�YEĔk@>UtN:;*/>|qvtBFkAc~7'#䢰,%w \-[GS"CBy{z$">P}3 ^ly{(x񢅅+?(((,,,222f 8eVmkk�yyy%%%Ս cG'&&斖<y5,3P*ɈˈSjY% v > 5gF*M3x!µp SsܷLeܼpϯ>XyOO֜V|@xIYsFy$#7)w(i>kolۃxq͏l+H,i{yri۲ mƇ]t>a%ۥg7ke4\ "'ʃsYsMs[?Æ�v~iν&zrsBmC{7#- sG]OcLql/ 'qzWӍf8y-!a7dayfe7)l�o)XbL_y弹_ԨwB55JlyGuDԣGƷ!A!FTd/f^E<!|Oz[_i o�n___oپ 1qqwg<Xwm4v(&bU ǵX$ԲvS噕Y׵unRHzcݷVJ )+;|݄g�C:I[ݮ_xşt_EMVS[777_a=k3f~yD8 r̀߸u[LL AOq#~K1,%<j/^$0Dwjx._z7<)kx2f4.y]J $w ?Dʇ⨪*2nL٘3B?} t=|=_eg65x2.^&%+WGDݯT*ٱ{@WZ(0G/=Z#`KcEҁJ)V|탎uPYo$r#x:)>7U$5x>mxjQ/,@%w5k]u*?~,8yd|Ҳ2dYBI[uTL: #Ƽu4>Z7C3:K}H"bc>jXWܪcƌD겝_Sm*M&lEzViJa]aPKَğT !BYn8J [ݱ7l9D?+`? #~ܷvx O:s%+9|h-\x0.uz!'Nv�uNp6#'ݬ;*(<g_V5= dԩp4O^~*V!GU9j u?`wvMuVrIrq}˗BûhgW7`a16\݄bOo!ښ毭¢"n9 {xyeS_ j#;կ̙;xe8!ʇUekTM{Zy> v~ywM\"+P;nl."PYOOOسFKfDoxGn^eeg8tTYUi�"__?˗gqƾr;C8 pխs{ME8pkEE<q= _y؉=yqQqpvGCWJs-2UD{ޏ~{ƍ;::6u<!D\Fo]=([Ziz)co9?~_gϞΕ{!D$ҙ%ɿ~T |kSxxr=^|&8hMEF|#/ˇ~xPg!O~S`ȵR~_;i֊}PMCߢ"#>?1~xP>g $JN7uV7k.Wd]۲?is&?Ү*NiCєjSqAgEe/\f͠OG}4mڴ+W`i|ᕂSã'eR*] qc[ .}EpO\O|5o\>^%RP <z"yw~ߔtJWR0QQQƒ~ !O}XfV E=t.Dp_?ɓ'kkk윜<<<RRR`G4‧߂D/"]'B߼}ky5رMB?{?hZ[[04)hċ-uuuCਈDEo!Dhќf޳x?R%n =JѰp7O8_LRjJ6xG$!p؆#:m˧HyN sÇa1gh$~*OOO5H|}}Z1OIuc}H@"e._i$2Bw^pp0R໲رcnzz:h@|C51Hߓ7泝!"/X e]duW ΋<+19^T⶜:7!!(O~FDD~␵uss[eھy\MRhJl e>q^+.2 Gk6l_[wϑ;0阑0KOѪ7oބ'JAF|( װ\r%Bm Sg~z)cfY:8N6i0{nl|3N40;'[D6F΍OL:w2ͺU]Y#p$ ;pzwpS&g-?UA׍zDniiWcFS !]}Ʀ&D@=3[p'hMHxV\[SlR6nRiR6ȱ۶nڑPR$Vx:mvz7񑇸Py=HDޏN7+*+Ir⥔NTގ�dzgc'N蘸]0Sx &ҲrdM0jUY&f/XgeG"S8N!a{~εBMWISX].f)22V]j݆4yuUP쒳DWDLNoMF| wݺu… O>zs |ϏO t.,ĩGRp28dUX xyEQWZq , +NMh|t:݁NA8VD/R>{F^(--MLL `n'Ϙ05Ϟsbiv!~Vc{PQauI6<aۮ7nP%EBvA?ȱ:n kfde15+>[ŝ]f͞b`xҕ 'ISӊF.;*i:w2ʃR;*=Tmx,6>a@L"M-++KNN=EdϏ6Q_d8. *Ckd V,f9 "55522'\r?/I48.@G;dE\za=V%¢h|t:BF| )][[[CCCUUUQQQVVV||@?0o~AtɪYFRap@N)J1d_x1hv4>N`ěZ-|A o qi^ȁB fG 2xgg'E]]✜WAAt"#>0x񢫫 " b4(,,,((Q>  fDcyhj48,@wS#Ϟ=#+|C^RRqMz@tmY$]hF4& E#ĄOʣ;)28y=YPӂn", 09aIthL4)͋F&|_t6#Nq + : `cIOCјhR4,L&G##.#>CN)9 iJ***B(\Y$h:4 &Eâyhj48囘QS6 j����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/images/replaygain_plugin.png������������������������������������0000664�0001750�0001750�00000043130�14035600052�023500� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����$���ܬ���sRGB���� pHYs�� �� ����tIME���bKGD�����EIDATx|Uׂe-kǾw-X]mkyWWW}u(JH $$%P?Ý{-In|3̜9s2s~=O~rNqp!v6ZahI!==C\y^B#GHXX<z[9g)TaCT~r9,P6&@x%55+.T8!,g:Z-br "0ŗBie#_ cnz`҉(.RtThhB2fIG;7˟Q1EBi>gˇty 8t:UQrr!&Dk%n?{$V6m.B6hvAn-sp.0⃘@brZA:0V2)BF{ddt^YrŽȪݖ<}#m/oӢ.+`0sV=t7r|Ǡ 1Sd̄ y[wr/w= ;z!3ϕ,~AaXfCɿ_)/~)4\/DHb|2~۞Cp.0i?(qJgG%A&E^\W-Kjv\y9s ;qB`ٔ[%~3ZXVdɫ,+bg=v\l̩ו0dH +SɎ: ֱ~CL9N<..;ⵘt0仨B{e{SsZ>c^omߧkƱY#/^ OWFn?#oKTr;vzE?9.S-LgKiƱgkpD7JvJ2tZyyw|5ilߡ[Yޮz g|9-׳2b2zqI0>k 0i'(~:u07ީ]L/N9p-Gs=G_  \"7Bcf*]1Бc@^HD7΃@EmtNȞ{hyXgK/3ۃcwׂad|o ֐v~"WzM(_WOz"wM{y׸{j:!▾YN11ǙUH 1A8Mbϊ?*Vg//d{!>h^rei!F-- ]d%n(ZMoOZIW-s< a OȐwGlt-\ۈD>'ϩqBGN Bw% 3y3h]WH"f9WkDJL_{͓S6D4>Cd;d"'Eϙ1q[L/R]S׿!?.s<} C,Mmtims@G�eޮ}@7 ɪUw3zoTX=&iA@  !y\|l3]I^ɨr;vއsޓk=<K1y]Ku71dK+Z{q�}~ 1G՞z{>C( Yz{TyoTr]kwb>&=.Rw.^n/bE^_'j`בmnε3D1(")&߄giusb8q-&x}WHDї//eeJ! ± e| UVW @uP5L>U�,2ht-|3y51Y+gi `cP}?/E~[S\˛/>C3Ĥy3�c 1A8p/~%w\|JHI^EJ@k}􍑵[ӒU'3ANI=ob܎,XyrdNb=tYkkiomlL<Yffh!2`}&ƭiEPiz9뵼"ĕ!_,E\?>O 1A8|c _sKZFIݭ8Hõp>BUK^*J~*E5Ղ/Ҳ++UP^9[ &Jt8kAzOX?A>H _ }<q6%>@?~B&x){m`kyOE+Ӷjgao1rFOAG0a,߲sIx@WQ}F& #"pzg1_Wy<^ c\ĵ|ɧtI%6{|J>\6 Χky3ã өqOө s~ ^@_8 J\BULg6鱗B"`q˴(0I(30"OXuX|<q-p,bK5w|>GH0p`s90lw!o|&JY}bBH-Q%>1T]|~?n&B4>ɿBB!Ob۽k'!ْbB!bB!bB!bB!bB1!B1!B1!B1ʏBif\ 2akK𢡊!'&4Fk>s )2r0&r9|RuR߷OIK=yƴÇBi\dȠry;vL:9xCDe{uTUVHeyC !4b2׺ErQ~ȖBOLTSBH*& 9~޲+&E)W-o_aWL0NUvln=bRw@l"}B#&jkeuJ 1U֮NUCL <aogvir-e}%c{9ӟT̘1Um{&&uʚUpo 1Q dm*(}19PHw)$Fҹsvq1K.J<Pݵs$&,|f.:vP..lMN }1ݿH.SN9~p饗ʜ{յx,*,;S&N s{mB(tk~ses~V;t wulۺy<~8vM7g%|w&?/Wӟ3ΐ뮻N9<iއ\y2}'gy7OS;<袋@*s+obRTBW1�_Z%Eb4HIؘԩs#<"q8333nys^``:k< 5X|A?#yᇝazg: x{g|d1p;~X^fثb+}uOu!k'ܽӮiS+ U{(\Ғ3g*o>P2[6kFƎrHb:AootҞs<>KBabx{g>w|[nv-@(YٽoQ>lNjX U{(ڴ@]AF[7/~!?h~ 8gL]KH00 NQ1:i<0qw碛7H~}w˳>k;}<VlN[ݛU*߽sSWmZLXW _0r֛ y衇[*91lnڄQX=vЕ'gL>e=1ޙy yIߴI{Yg6nLFl"ݵe'}ccӧMӅ&JNJjNwެ4Vn瞃]^i1ASdu!C?_3CcSO w&$PB깶~Z㷿wqw%%_pfW9C˸2-<ƍu :D.2rʄmٽo0kL[Pp}Lwڪ<PZ{fyNL%GH[(tZ[%:y*&!d2oZfVT%S2 [Z*eb[$8/Ĥ6Q4uAkFwA'1J&/2~i+х2la| _EJ97<;t}q%B 5ڴKB!MO|B!ibDB!MOLqL!yhb B!Dӷ-I2w[.'#ce?ʔq} u}ڬ6앥23Z.8~\l/Y!?%AS/\Q;JG1U סO.['mEqq_$o^^MBL}ڬI@+kr )qPf,/u.SXMa ۹]s}ln7n S.'U<|'NHuMJ·霖dƪ*Xad\W(o!_[&1]|ޣ)ꫮ1^թva /P:v(cF!_.APڬ|:9]^4L:d<p<%HzOGoɓm%{mG"VA2lM. ymmu{ɒJz6qIsa7˂e:*a(9-Pn #s4(1->$'ҿ>iaٳ ̚5SB} ZTÇeOC6i^>Aοq-wq9@-~JB1ߨB:b;~Bv;$UzޜTǹ~qZWSrv}6wբcRZ[Z]f m-25vbN?�-D;<%v8y\PU6}`:jVXb{2XU +e^Hek0.@ՠHOgnl|MZLbr-X ScZ`IS .mVL>ɋǻIqqU[N<fkq^nM21._ת0ɐՃZ!60gR!SqU۶KS_6UkKbzn -Ua=[.}[3F?I.]u1sa;ybwQˤFx/A@q.]sX"~??./# dHDV˛ ?3UP%Z0޷#FpȑrmI؄ A3Ylb xqrIP6 :Q8f3a,l'La܁qviuKޮKt(/ׅ- **qM;aN͇w)rw|=s]eλZT\#|<}7<ޫ�%^8/ZiZ~ K F.**M>*W)&ܹd;#tU <Hw 0@o{{&M[0R1xY=GrmVLڈg>dzmwybs(dPǹ#UդcUacn),S`tsAxmZ6?SKa% jUg'3HDr_mm;=2cYQ}V6kd @'V~7Ō*t˷96\ĤI1߯\{AyLuʙjCu]\?<ڬkt[ysޅzo^[ 'lM~%3I/#wʧ[za(L1ˋࡣ2}Yޞ8mNyݕm52"2K>T5dRUdg]lK%*$d0kZs{V�AzL5VɗeLd7[}Vi"K%zǥ~7ŕҕAu#?EʿVH 7ܠݿBPBW_Vq@Ť6+&#o2u5UPŎu hxߥ ΰJg7~sUm,a}{%H3> >t[x]UJi\io;7Xv{̓O`b{ML˳q >{7kaizKlvcː .2[^Ғb|eܒ9|O6GÁI+izڬt~P/yNgꖗ7ϒה- }ڬZB<?ZJm14B7GL}ڬ5y_T(׳2Ͷvnfn.C6+&oXCHgDd x73JɩmpT5Ч͊[W3e _{?z9it;O k5L}ڬ]2!f͊ Fњ(&4Z+6_2ceLI,=c">{H 9E;6ńbB5 li^ßkIŅ]6h^]6ńbB5wB| *\8{b)&j^zi_#UAýpqQQx)&8wi&hXؼy䪫 J y衇$--b^}q p%$ +U/W أ-ڰSU>{a_d֭JNo߿wpĉrwe]si>|+RW A+'VSS#_u9޽{4bJj1|.α'|R%-0y(&!l5Y1*:W/ j+̲QZȔPACJdM7 ¾?Ez٧Osʒ'N ^-^Xn&y/z)}e^4bJLn߾][***tM,Xiˈ9lrwꚚq_|QKRRRPۅ& Wkf?Mv 3oxwIaӖ+<Ju{Ȃu5X_S{T&,uo}<(`X~eҥi <M!&{9 iBҔaco}Iɖ-[wcp>쳲aIlӟ#G4j O?]v92gDﳘ2d9t 4AU4m/u [c.-gC 8ݵVlZw;,K7o}'OB2e]/Ϊ6wS8KMMm1=zTcicˤɀ4ގts0<f48/9N⋘eݷo^f?Mv۫1}=JɩY &XGQ1:N,fu]Cvh1٩un ý>ӨX5..? I&9>x2gؼ^__/ƍ@ ŤY/Z'ގuuo�Cᅲ+&Vo0}5˘\>vQ&8׾GeJb^]W FDAYZq:%(d^߯Mܣ;]fWLc>a7$a@}]{ァͻx|_C6{饗t9*~/5wl-deZ~3}^O8 kiT@db\bb.wÀyvv@W<hFB#<|gصe2aW?`92-w- <α--&wR@ &22-[oUwÍ1AXAAKi^wf}] xA[Kv0,a|U ʌ%:ިuenk˼6|yso31C.=k00Ww'Ǟv4gϞ=4cz2bZ >Ѽn{@8!Xu~\4Zk?zqK0Ӂ: bFĄ--D_@+|Nu 梘PLh&5ۤߜ@LǷ䛙{aL1hMhu w+aI\ H& FQL(&4Fhm趗F1h(&-p1^ńbBjtFf5L|!'h4Os$a{>`III>VXR#͕0ml111zTQVf嚗n{鶷U[o]b61c4rn{+1͛Yжc[Ohl3\ ƆDH 3ܹc\m0IZmml-ΰp\4<8jVXxL>@Ex1%xܹ &͵;C=!XF 5 BLrK(&!h};r۫ atd5)ܒ8POmuyW+Ҡ;ɛ & ;~YF$Vݔ~jmdhI‚۞5/z ̙Z_K~G$>S`v Q@a.\(/m1qu-MǣB}.wSCn{?<n8¶U5/RLZeUer:VK^}/w嵊=Rn6t+zJgSC0n{ ;ѭjQk^e7Wxt'$-S<fhƛw<u|d6O>t_Virw<Zmނc::itԩS'<k^F1 sע@LKj&bӏ<u 07ڵk~x<ݗU?m4e7)`#6- hcipW+׼t=bVht6etK h趗F1h(&-`^ńbBltKPLh4bB1h4ńFkF4 ńF 趗F1h (&hi(=PL<òjժװ)1&( %{|(|+`'66̡yY7\3RL{=)++37 /SN[NOՎ &/[{Mή+`'66T >}x<5/x趗bҤ 3n{1-hx̸ U9گjg]t3f4yc9|p=߮Ebf%KtM;t5+WV\at6!=kחx趗b]+�{іr Wc!OEk Sw= U9(h1<G}`Тm\fskuMob>];נSmo#;0yd-�g3{rK<tK1 C_,jO?s_K#&xa`֝\u>cңGYr}^VxML<]լ\[y mog+]Sx _Oy}n{)&!c(̃-\V{;c04SOInlm5s[\7m{ [<tYL)퐹k쳒dʲr#T&%2F OXt -䰖tۋ.$\P AAO0Ĥ{ċf/15!&\[s m{`:ư0=7׼v^b/m֬YV7Tn{aG- s L>]<Z^Fא%<�oWL<v`7Wܹs+ftnɻK,5U<FS͛$s۸C1 ڊ^ZB(&4ZkQL(&4ZF4 ńF 趗F1h(&FPLh4F1ڀm/bB16QL(&4ZbB4 ńF7򹦘PLnK50ٿC(t8̆x[拻]+j}&ګ^I3ݖpkďO1<b! Kl!66_ZV11=4ysn{e4wu 5>i TBc:<fRŌ1#^*~w|G,˳t<O7FwBޝloam/Ť̛ݖrkGS-7xCOGk&&&.�JkzZosfpq~wΤ$>*299 Ν /՝ C@n{/v͕WF3ov[my5-C|ٕ-\Ч9N:0;{֛olr}鮞΃Ba` mo`n{ s:NatK1i1nZ=E<FѮ;_+1:ζZ26ov:n/bbtZm]vՃ ϼ h2\z沊n:W)Æ iB7{lsN[!&t:[m/$$Ť%Z{n=Z=j+OsQs1~d:�g?bb7''G M_|E.r[ ?;u uu0W^IHZ[sʟ+kرP6QLhVL,Ƨ6n:ńn{i m/bB16QL(&4ZF4 ńF(&FQLh6`CG)a3ߖQL(&4Zg#c$7;L1hMl _^t bB1 ]t&~_?:; l(&YL͵Rn{ ;=]4[%4γWSMi}pS A :-,#=Q˅^(;v1bcbe Ť%Zm/ S`զ,ۂnCML0aRQ^&´X; .Ą4^ }2bpL(&PtO'QXMK.2cƌĎ]oq&oRX Yn..L,7|�ɜp=[ Ť-^y)++s@kVk]}]V{p+//>v'qpnA5M73$6b7 Z%I3r-(#ue]d3PLZl ]Z2%KL<5_c=&=z+Wen1'MVRLIqQ3Oc'M(rR1\b ^l G1 6t n{‘=Sҭ[7cn׮:_d>IdPL|UYQ.gq1Bz֬2a˄bpuk!&ݻw{"—cV-+oױrӋ>[q- [-Eeq'u=]܎PL(&h !&ӧO[wM5u_ | 4MVl׽pi,18\|rgj)-)pTF(tbB15AhF1Gkb2 bBPLh@[&ќF1hٻp`ńbBfCLh FQL(&4FhCg ńFkb;jd|L1h`?F1QL(&m誗bB1PLZ&Nt鮅qKU$חsz衇$--]k0$?/WɅق,ϣ^Ť5Ŵ㶴"&08 Ω(&ѵkWKyY^fWQLZ<YKzSNzFݔa_~z|9#_"O<ݩ<' Ə/wyQȍ7(wvnIygw_9ŤS+eCj^njW^ŤW?hiIVݿ2g}DnOb2dmZ^~eK/spCo!ka~ڵkwĈۺg;[tA*:gxpE4Ijѓ&M5joX(uqxru8a +&\sܽ{z=3A9 <?##C;C,uU'nKbB]JKC7V]]^2ۇ)&YgHY`^Ak\tKKH $X>#zu.1FZvsk@V\.ue.;\vìҿh"=F=^PtM4I+0ԾQPb`]4[nCm}F!ýޫk<�_PP.u c@>Xbb~tou]tYzϮ۾ bǃн%>^Ť[[p06G4 ŤMńbB1PLh4 ńF1Gk/Yi џ bB1h4 ńFh\QL(&4i 4 Ť]Ӟ{PLڋPL(t̸N*n{ ˓W^yEy-{CLf m @H1^Zz;{CCR__'}d[Gj=vQL58c#'^P9R;Œk֬11+<0,M1 m/)"?uur앝;*R2)/-"I r>==Pqkf5<]spዙf&&>u%!fDnz1?bb+>>~wy 4ȓ.]Ȍ3BVL趗F1iի塇j%z,~AEWe˖5rkM.}IRRnerr;Y6sL֭nEO݆x Tn|'VYvN{yyvbB4I+l Jn{ͶsNYxBQ1C(F;]`7|27ƒͅtVyǤGrʐдULfϚ%ee $';K&MPtYjjj% N̂єbt(-w5섄Z~7Aܟz)E4^7RZR$WUnV_ղ&O,? 5K.`;v <5k>]G Λ#Mv[?bVₐ۶XOݥL͕ؒbBtqnޑZ^VNI ˮ090> oPx[5  !716mn%:tm1ӧw߭D NvtKkMc&BTz%3iBk n{P]`EZkN+cnjуZxxx (&m1D㏾Ia~>bB5q`ZɐA$!>'1ϣhlgB U1Iې*#m}BߘZbB!yq-!(ƍZp狐4BiPL!PL!PL!PL! ! ! ! !B1!B1!B1!B1aBBBB0!PL!PL!PL!PL(&B(&B(&B(&B(&B!B!KLW-'J 19v!V !p̄BńBńbB!bB!bBHfjr#ȷUIqa[? !!HuUlܐ"S'OÆ~0qR[[^˶tI,N| 2bηm[6KM !"٘" y9rQ9qÇ%';K&-׮i"F/b;?Dl>)*̗E DP2 :e+!8OnNn١)E4.V I.!& >RTX uRL P[FW [$P|,*GW'EZx !$&Gxq�\K1ACbBH*>r ܯ#)&ŤV(&!1P|?jʞ=o/b[LꕘtWU$I]F_ńj3d 37YgUyvŤ^ L ={vKyy8Y Ta$X.zy#;w|PbBHB2{=\)*yuR٩^zlBs9:ܮL6Mn&93k'Q1DyY^Ai8BBlenUz{v*KK%;+c|x-p5]/MgSA1! B hy@H.L k+K._B60-(1)ιsW_-+V:ɑmVLER /``T HNI^׫*u륬T*++dӦ4-Z8_7nPt@Q{5MkS@1!$AWV/-+2%,Ew(')gp<g.]$&&(e ,hO>r/Uz LFX~~riefV_/+Wlݼ0c[Lʾ5Q\DJ*P$/[&UٶE.+dl )7{xj؇V lS5 #H^NڹCϙ%;wlwuC)!nn,⢂ۀbBH@8)U\|<?UgV%&8Λ?{6~q(W]uU¿gϞv^#fjc'|a/FCM<::Znf:%EŅrV/-S5+KֶtYDcߦubn]c|Tqٲ<!N֭I]\ÇE󵘭^B2n<7p܊xتb"`zbBH<)Pn-{lUTL"##uo0N9mm^?tP:Kv(s-w񅺘i1YDc]JY:I2lTbY6]-7d _ǫ[m |ay9YZ@̜l/Ο_gn`֎q9F1!- ^~Y$g?YJ@v* !ISYL<y]wITB]tDDcUf^w>쳥Bݣk|؏ݵ\㳋]1HBF6Ux@U_(ghlLYױaB,[5^tOgn->G%/7[9,G�CXER\T([7K\l |]-{願b, 1XHgVUߦrj&Ղؠ dg†xsirWIBR-[nW^3<%TK,5wyGFyuG?HJk>橧_~YPggg /1>4lV N o1JHk\+P/,&U%)j<gVDLVfV-!dlݬq@p_ "qiPbBH(?nPKSOMJ0 :Z#p&Gw„_Z:t \s;6r=QG][0vƶrw˩*]I?䓺SN2y$Ŷۧ-$>Ek"IYIW\2U>hQQQVRC8T D%ej FWcZ.RY !|| !!*&|s`w&8g®X~Zݕt! GjiQí!&0vb'< w9�: 0!!Ahw@1!$D{EM 󝂂 _ }I!y %iN1Yf[6KaA‚%>j2}F-4uܕ`bBH J1V yNA47qqFl!9)IW׮F`\`c^.7 4bBHɁ+y9z,ݬ[A?FSLWIjJdefƴ4vINNՊu)1OĄ7 1Q_#1?î`�_L<;XLlc1~uC !*&WASL;BBPLnmر MLn_YU?Am/!!~P0ٲicPolټIM,E󺴸HJvV. Y(&a`0vlV/WUeyH~  oaUaW1=mf]𤠔P|A O5K1!$Z'ܚdBjO6eLnW'%ŅA? !9T_sO1!)Z(۫IEyߟ][V-WPF o mPL! ! ! ! !B1!B1!B1!B1!B(&B(&B(&B(&<B!B!B!^Lp"!b೘B!P:w(:+T\8(~\qVE:"zBHI :trnlŅKMo8"x!Ҿxġ8tC'.qن8KqVq. !;~Ё8tZN\Ѝ: M;.Bw8tCpDGniɩ3M}`r(UΎ{B!ʡ ry8á#u9q@GGW:""Ҿҡ8tC'q醘htph\#_Biw\Ё pC'tiNu8d91rC}u0BH\Ѕ3:qC7N5CT a1tBinLZahO?@ U'#����IENDB`����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/images/replaygain_pref.png��������������������������������������0000664�0001750�0001750�00000011172�14035600052�023137� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR�����q���B4���sRGB���� pHYs�� �� ����tIME)cw���bKGD�����IDATx] TU6eRTP| -'rUb\.R2M+54DPI+S@4 r|cY3ַgsϹBЍ\@ m @!6ц@ m hӭm3A Y2+Ҧ۝fч4mg̘aooߣG'')S X'NNJJdHhUhcYi H :Ԅ:|蠵Ï;ZS]uYO=e@wa[o-` !2̜͡9Ӫm{Gg A7EΎ嗕̛\>}3mڴ ?Fpء1c 6n8lچ޸8|L0?H/Sr f۽޻52RPZq]wC8κXTXYwmHPyvqvTyyCΓ|c>}:N@,\YȯB{bb ҽ{w.7}t2pCݜ9spxGڱ# ̙4n۹sҏ=O_|ݟ 8gϞWUV*/S|ysr $>徾QzZjZi$pLP(J.(WiDgR>'ذa=>a7|TarT4Dݒ˹k6l߿NN6Ǹ#|lUez+!~-,X&Ftd^4hB fFhS]PdmLcUV}A ~vNT&IWϑ8 H02fm$ Ch‹hrZA~spEh#ZY_{  ڗMZ..Ғ6lPi2@ΓБ;Y=m$ 0PƷTp8w\_υ ۷/ҩO_)?2#F`xx�=�c-&=M:|,{m\DM锔M"e'7*fϞnTL:Uc&gSv8x [>m[4FbJ_yeF$sr/lrV9{F6>IWWWe@^9JmSOq+r~![>QyRp[Q(r3ΞABRe0 2z-%riA�w+|||@ګ5LMg` ˧ >t=gC&@ DhC 6ц@ DháH#z5h@%,wFzefމ~I 01mB/|[ر9ru?=iý"/z?'Mz!m wO @L)b;;;'''~in{{ÆÇ//))qwUVZR'hҴsqqٲe Kdӧ_~{vLk.'x={z{{e=#(˗lll%'LUeNSJ"mF vO|.,j__ݫ< Z ?"ѷo_d?cmm=v {~fxx%;::ҷ`9p�IKbbQՠA6o$Pt6UvE=Mcc#GEaټy3;T{ ˗-(/۵k/ܙ+BB0Z/{ݩS <{kd$zxcfԃ*\\ض wu>߼{)CϞvb9[96 [+WҋH<#0ƿtiӴ j(ekkjDGo%[qnԒ6{?^κIn&66...=;yf6̄gm$oF!=0AMf$i1r/K^\64�H=}J6QC ᐜ|{3$RRY]BrjQo%[97jI =_)<SS%4m@k2tм<nс64&}`f(/+;Z7#RnX UIچ2w܁䓁1V˵T9|!\^HttZd+i#i sڵ7ik4OrEGms<==: P NL1c'yC_ R]\m${1qOA?L4TK >۶q4f<B#q6p@*rVў6}+ Q\%rLÇqL/eb;�ci#7)"3,e]R<{&]p Ĉk1"�Ϗ׭eW)W$ig̘!:AQȵTKڠ tqȭn \=r4a-=m4Vp(wK@ҒM"@'{XcfKdΦJ/C更9<ƚm, VN3u:88tǝͼǝ*ϙ&ǝݤ6ˠ {D eچuE$~PqMҁ:lC Zl--kц@  @!6ц@  @!6цTe%ڨϙeŕWkihChT8~ut MO֭ODoKK=ތ b9q?}2C{I�z)fGnل}sSц`z 6&@[n!dD違bBsMzSƼh$換7o2~ɓr�C1fj:fhkuOϚ%Z]' Xrt)wĉVi mF�&dr6z76 C .((b5}hsƍ /HLhcgIͼy%&ЦU={8M\kMFFF``… %? inn><<\/ڴ475*hcH(k~K $,'b8*+>>>ۣ%%Ժ3] 8;;hd2mT*̙3ʞyPmZZZ@1p-YX\ӧTW%L"Vh*9`gg mz!p>Mkk>t@@dw7oD{N/\ޠW�`FoARh+˨n j=jm8Xwa}TQ3VUVYz=i|g g#F06mvEo՚jh71mTŴA0'Ъ6z\LV686i jm F5A@\iK,i#*V2yrh Je}RR"K+cYv-v rKd~hh(wK�i}hVcU�`^[|K/I.Y ƍ޽m_ns?aH=}%?JTai9pYYY3X>nF|K@6tmm9s M}l ̝;7-4#2%7?1NUvǝXU}ai m,mm~ww_~\.ڀ% OŞ6c06u% P5_@OLBګ5%Er(*ȧ_@S5mN;jzlzΘ?}yY|b.ME<1 IKeow655mGslvDG37o -[n )PO%6ц@ DhC 6yIV:atJ'ty$餕N?xtJ't:^:҉6im *NZJңG޿SguK'%%M24\:iw4m׭xgutoo$tJ7mmZVVV\Gkָ8;3=/_ qww?|¬%3wrrڽ肎{$59XtzCCj7'i65Uj~vHt Æ SX6̗/[6eHO\g07.XHϤn u =;I|rN=]NΜS1T42x!ti ^Q Q3KF(5i$Je!t͓Ob5\\T$>_Y\6bu>,C:=""B3K'tMA~7BDW3WXsːN9Gcc1I+<a IV:Ѧ}!tJ'oH+hCtKV:Ѧӿo餕NowF:҉6N'tMIV:ц@ DhC mц@ DhC X  B&����IENDB`������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/index.rst�������������������������������������������������������0000664�0001750�0001750�00000000116�14035600052�017652� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Playback ======== .. toctree:: :titlesonly: backends replaygain ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/playback/replaygain.rst��������������������������������������������������0000664�0001750�0001750�00000007137�14035600052�020710� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _replaygain: Replay Gain =========== `Replay Gain <https://en.wikipedia.org/wiki/Replay_Gain>`_ is a common standard for adjusting the loudness of songs/albums to the same level. Quod Libet provides tools for analyzing songs, saving the calculated values in the song's metadata and adjusting the volume. Audio Analysis -------------- .. image:: images/replaygain_plugin.png :align: right :scale: 85% For calculating replay gain values QL provides a replaygain plugin. Simply select some songs, or some albums and activate the replaygain plugin in the plugin submenu. The replaygain plugin has to go through every bit of song data so this can take some time. After the analyzing part is finished you can save the calculated values. They will be written into the song's metadata. The replay gain plugin calculates a peak and a gain value for each song and for each album. The *gain value* specifies how much the volume of the song has to be adjusted so it equals the replay gain standard loudness level. The *peak value* holds the value of the loudest (or highest amplitude in fact) part in the song/album. This is needed because the range where the song volume can be increased is limited and pushing the volume over it would lead to sound distortion, so called "clipping". The calculated gain adjustments are relative to 89 dB. To find out more about how the calculation is done, read the `detailed summary <http://wiki.hydrogenaud.io/index.php?title=Replay_Gain_specification>`_ over at the hydrogenaudio's knowledgebase. QL uses GStreamer for this operation, so check out `rganalysis docs <https://gstreamer.freedesktop.org/data/doc/gstreamer/head/ gst-plugins-good-plugins/html/gst-plugins-good-plugins-rganalysis.html>`_ for more info. Setting it up ------------- .. image:: images/replaygain_pref.png :align: right Under *Music* > *Preferences* > *Player* you can activate replay gain adjustment. There are two configuration options available: *Fall-back gain* is the volume adjustment that gets used for songs with no replay gain tags (which have not been analyzed). Most audio files are rather high volume these days and the difference between an 89db song and an unadjusted song can be quite high (e.g. >9dB). So to avoid a sudden volume jump, try setting this value to the average gain adjustment in your library. *Pre-amp gain* simply gets added to each song's gain value, i.e. it adjusts the default loudness level (89 db). The problem is though, that if it is too high, Quod Libet can't increase the volume for some songs because they would exceed the volume limit and cause clipping. Applying volume adjustment -------------------------- .. image:: images/replaygain_force.png :align: right In Quod Libet the gain type is tied to the active browser and play order. The "Media Devices" and "Playlist" browsers will only use track gain. In all other browsers the "In Order" play order will switch on the album gain adjustment (it will fall back to track gain if there is no album gain). In "Shuffle" mode only the track gain gets applied. It is possible to set the active gain type manually by right clicking on the volume slider button and choosing the type in the menu. The chosen gain type will then be active until Quod Libet is closed. Querying existing Replay Gain values ------------------------------------ You can perform simple or complex searches (see SearchingGuide) using RG data. Here are a few useful ones: Find *all files without track Replay Gain*: ``replaygain_track_gain=""`` Find *really loud albums* (best in AlbumListBrowser): ``#(tracks>5, replaygain_album_gain<=-11)`` ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/queue.rst����������������������������������������������������������������0000664�0001750�0001750�00000002247�14231604332�016113� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Queue: The Queue ========= As described in the :ref:`Overview <Queue_Overview>`, the queue is used to queue up songs to be played. In recent versions of Quod Libet, some new features have been introduced to the queue, which is described below. Disabling --------- With :ref:`release 4.3.0 <release-4.3.0>`, the *Ignore* and *Keep Songs* checkboxes were replaced with a *queue disable* button and a *mode selection* menu. The queue can be disabled by clicking the padlock in the queue header. When disabled, the queue will not be played from - but you can still add songs to it. Queue Mode Selection -------------------- The queue also has two different modes that can be selected in its preferences. In the *Ephemeral* mode (default), the queue consumes songs as described in the :ref:`Overview <Queue_Overview>`. The other mode is the *Persistent* mode. In this mode, songs will be kept in the queue even after being played. Furthermore, the queue won't have precedence over the song list unless it is explicitly being played from by first double-clicking on a song in it. This allows switching between the queue and the song list without having to clear or disable the queue. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/renaming_files.rst�������������������������������������������������������0000664�0001750�0001750�00000012124�14244626671�017762� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _RenamingFiles: Renaming files ============== Basic Syntax ------------ Quod Libet allows you to rename files based on their :ref:`tags<AudioTags>`. In some cases you may wish to alter the filename depending on whether some tags are present or missing, in addition to their values. Quod Libet allows _pattern_ syntax for this interaction, as well as plain text. A pattern is some text surrounded by angle brackets, typically containing tags. A common pattern might be:: <tracknumber>. <title~version> You can use a ``|`` to only insert text when a tag is present:: <tracknumber|<tracknumber>. ><title~version> You could also specify literal text to use if the tag is missing by adding another `|`:: <album|<album>|No Album> - <title> A reasonable use of albumartist would be:: <albumartist|<albumartist>|<artist|<artist>|No artist>> ..which uses the first of the following: Albumartist, Artist or "No artist". You can also move (rename) files across your filesystem to another directory by mixing path elements and ``<pattern>`` syntax:: /home/*username*/Music/<artist>/<album>/... Simple Renames -------------- Like tagging by filename, renaming by tags uses tag names enclosed by ``<...>`` to substitute values. To rename songs as their artist followed by their title, use ``<artist> - <title>`` (The file extension, .ogg, .mpc, and so on, is automatically added). Other common patterns include * ``<tracknumber>. <title>`` * ``<tracknumber>. <artist> - <title>`` * ``~/music/<artist> - <album>/<tracknumber>. <title>`` * ``~/music/<artist>/<album>/<tracknumber>. <title>`` You can also use tied tags to rename, e.g. ``<artist~title>``. Creating Directories -------------------- Note that if you use ``/`` (a directory separator) in your filename, you ''must'' start the pattern with a ``/`` (or a ``~/``, which expands to your home directory). To see why, consider what would happen if you tried to rename the same file twice with ``<artist>/<title>``. The first time it would go under ``Artist/Title.ogg``, the second time, ``Artist/Artist/Title.ogg``. When you specify the full path, this can't happen. If you don't use a `/` in the pattern, the file gets put in the same directory. Conditional Renaming -------------------- Consider the ``<tracknumber>. <title>`` pattern. When the file is missing a track number, you get a filename that starts with ., which isn't good. So Quod Libet lets you use ''conditional renaming'' to avoid that. To use conditional text, after the tag name (but inside the ``<...>``) put a ``|`` (a pipe). Then after the pipe, place all the text you want, including other tag names inside ``<...>``. That text will only be added when that tag isn't empty. To avoid the original problem, only display the track number, period, and space when the track number tag exists: ``<tracknumber|<tracknumber>. ><title>``. Quod Libet also lets you change the text if a tag ''doesn't'' exist: Use a second pipe. ``<tracknumber|<tracknumber>|00>. <title>`` will use the track number at the start of the filename if it exists, or *00* if it doesn't. Conditional tagging example --------------------------- Remember that the format for conditionals is ``<condition|<conditional tag>|<else tag>>``. You can also embed conditions inside each other:: /mnt/musik/<genre|<genre>/><artist|<artist>|Unknown>/<album|<album>/><tracknumber|<tracknumber> - ><title> Let's dissect this: * ``/mnt/musik``: A music partition * ``<genre|<genre>/>``: If there is a "genre" value, put the song into that folder (creating the folder if necessary). If there is no tag genre, skip this level in the folder hierarchy (note that the trailing slash of ``<genre>/`` is inside the < > that delineate the conditional "block". * ``<artist>|<artist>|Unknown>/``: If there's a tag artist, put everything into that folder, else put into a folder called "Unknown". Note that the trailing slash is outside the < > that delineate the conditional block, since we always want that folder level. * ``<album|<album>/>``: Album folder as needed, else skip * ``<tracknumber|<tracknumber> - >``: Prepend tracknumber if it exists * ``<title>``: The track title (or empty string) Nested Conditional example -------------------------- For songs that don't have a genre tag, perhaps we'd want to use the "language" tag and sort into that folder instead. But many songs would have a genre *and* language tag values, and those songs should only go into the genre folder (i.e. the language folder should be ignored) QL can do this, by expanding the ``<genre>`` conditional block from the expression above to ``<genre|<genre>/|<language|<language>/>>``. The pipe after the second ``<genre>/`` introduces what should be done if the first condition *isn't* met (i.e. no genre tag), but here instead of putting plain text, we introduce a second conditional block, ``<language|<language/>>``, which adds a language tag folder, if the song has a tag "language". The full expression now looks like this:: /mnt/musik/<genre|<genre>/|<language|<language>/>><artist|<artist>|Unknown>/<album|<album>/><tracknumber|<tracknumber> - ><title> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685718382.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/searching.rst������������������������������������������������������������0000664�0001750�0001750�00000020206�14436402556�016740� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Searching: Searching Your Library ====================== Pretty much every view in Quod Libet contains a search entry where you can enter search terms and save them. Quod Libet will search in artist, album, title, version, and any other visible columns for what you enter. If that's enough for you, you can stop reading now. But what if you want something more powerful? Combining Searches and Negation ------------------------------- You can combine search terms using ``&`` ("and") and ``|`` ("or"). If you want to listen to Electronic music but no Ambient:: &(electro, !ambient) Or you want to get all songs by `Neutral Milk Hotel <https://en.wikipedia.org/wiki/Neutral_Milk_Hotel>`_ including the solo performances of `Jeff Mangum <https://en.wikipedia.org/wiki/Jeff_Mangum>`_:: |(mangum, neutral milk) You can get all songs that don't match the search term using ``!``:: !electro Lets say you want to listen to you whole library but are not in the mood for classical music or songs by `The Smiths <https://en.wikipedia.org/wiki/The_Smiths>`_:: !|(classical, smiths) While these searches are easy to type in, they depend on the visible columns and the active browser, also the last one might exclude some songs which happen to contain "smiths" in their album title - see below for how to perform more targeted searching. Searching a Specific Tag ------------------------ To search a specific tag, use a search like:: artist = delerium album = bargainville The search terms can't use quotes (``"``), slashes (``/``), hashes (``#``), pipes (``|``), ampersands (``&``), or bangs (``!``); these characters have special meanings for advanced searches. See :ref:`exact matching <exact_matching>` or :ref:`regular expressions <regular_expressions>` for how to do searches including these characters. In QL 3.9 onwards, you can also use `!=` to search for things not equal:: artist != delerium genre != /.+ Jazz/ You can also search :ref:`internal tags <InternalTags>`, e.g. * ``~format = Ogg Vorbis`` * ``~dirname=Greatest Hits`` - search for all songs in Greatest Hits folders. It's also possible to search in multiple tags at once: * ``artist, performer = "Boa"c`` .. _exact_matching: Exact Matching -------------- If you want an exact match, use quotes:: artist = "a girl called eddy" If you need to put a ``"`` inside the quotes, you can put a ``\`` before it:: version = "12\" mix" Other special characters can be used without escaping:: title = "Concertos #1" You can put a ``c`` after the last " to make the search case-sensitive:: artist = "BoA"c artist = "Boa"c artist != "Boa"c Combining Tag Searches ---------------------- As with free-text searches, you can combine searches using ``&`` ("and") and ``|`` ("or"); either grouping entire searches, or just the tag values. Although the examples below use simple keywords, you can also use exact matches or regular expressions:: artist = |(Townshend, Who) &(artist = Lindsay Smith, album = Vat) The first finds anything by `The Who <https://en.wikipedia.org/wiki/The_Who>`_ or guitarist `Pete Townshend <https://en.wikipedia.org/wiki/Pete_Townshend>`_ . The second gives the songs that match both, so you'll find songs Lindsay Smith's `Tales From The Fruitbat Vat <https://store.cdbaby.com/cd/lindsaysmith>`__, but not her other albums. You can also pick out all the songs that *don't* match the terms you give, using ``!``:: genre = !Audiobook is probably a good idea when playing your whole library on shuffle. Note again that in QL 3.9 onwards you can use the alternative syntax of:: genre != Audiobook More complex searches are of course possible. For example, to select all Disco and Jazz-related (*containing*, technically) genres, but avoiding Acid Jazz, you could use:: genre = &(|(Disco, Jazz), !Acid Jazz) Numeric Searches ---------------- Using ``#``, you can search your library using numeric values. Quod Libet keeps some internal numeric values including ``track``, ``disc``, ``rating``, ``length`` etc. See :ref:`numeric-tags` for full details. You can also search any other tag as long as the values have a number format like ``1234`` or ``-42.42``, for example ``year`` or ``bpm``. For comparisons you can then use typical binary operators like ``=``, ``<``, ``>``, ``<=``, ``>=`` and ``!=``. * ``#(skipcount > 100)`` could find really unpopular songs, or * ``#(track > 50)`` to figure out who makes really insane albums, or * ``#(bpm > 160)`` to find really fast songs You can also use chained comparisons: * ``#(10 <= track < 100)`` to find all two-digit tracks. Times like ``added`` are stored in seconds, which is pretty cumbersome to search on. Instead, you can search with semi-English, like: * ``#(added < 1 day)`` for very recently added tracks to find songs added in the last day (if you think that that's backwards, mentally add 'ago' when you read it). Quod Libet knows about seconds, minutes, hours, days, months (30 days), and years (365 days), kB (Kilobyte), MB (Megabyte), GB (Gigabyte). You can also use ''HH:MM'' notation, like: * ``#(2:00 < length < 3:00)`` for songs between two and three minutes long. Of course, you can combine numeric with other kinds of searches. * ``&(genre = classical, #(lastplayed > 3 days))`` * ``&(artist = "Rush", #(year <= 1996))`` Playlists --------- You can use the ``~playlists`` internal tag to search by playlists. It is populated with a list of all the playlists that song appears in. This is surprisingly powerful if you're a playlist user. * ``~playlists=chilled`` will return all songs included in any playlist with "chilled" in its name. * ``~playlists=|("Chilled", "Jazzy")`` for all songs in either (or both) of those playlists. * ``&(#(rating>=0.75), ~playlists="")`` will return all high-rated songs *not* in any playlist .. _regular_expressions: Regular Expressions ------------------- Quod Libet also supports searching your library using ''regular expressions'', a common way of finding text for Unix applications. Regular expressions look like regular searches, except they use / instead of ", and some punctuation has special meaning. There are many good tutorials on the web, and useful online regex testers (such as `Regex Pal <https://www.regexpal.com/>`__) Some examples:: artist = !/\sRice/ (or in 3.9+: artist != /\sRice/) or using the default tags:: /^portis/ Like with exact matches, append a `c` to make the search case-sensitive:: /Boa/c Regex searches can also be used to escape special characters not permitted in normal searches:: filename = /\/Music\/Alternative/ Ignore Accents and Umlauts -------------------------- Appending a ``d`` after searches makes it's characters match variants with accents, umlauts etc. Both ``/Sigur Ros/d`` and ``"Sigur Ros"d`` will match songs with the artist name ``"Sigur Rós"``. Now you can search anything! Pluggable query expressions --------------------------- More recent versions of Quod Libet allow queries to include pluggable expressions. This uses the format ``@(plugin: body)`` where plugin is the ID of the query plugin (e.g. ``saved``, ``python``) - see ``quodlibet/ext/query/*``. From QL 3.10 onwards, the Python query plugin allows some use of external modules, notably `time` and `random`, as well as a few useful variables. For example, here is a way of simulating an album Spotlight in an album browser: ``@(python: Random((int(_ts / 60), a)).random() < 0.01)`` Here ``_ts`` is a current timestamp, and ``a`` is the album data. So this generates a random number seeded on the current minute and the album key, so we randomly select 1% of our albums to look at. Reusing queries --------------- Complex queries can be split into simpler ones. Also, a query can be reused in other ones. This way it is easier to change and administer your searches. In order to do so, the ``Include Saved Search`` query plugin (see above) must be activated. If you create a saved search named ``Unrated`` you can search for unrated songs from the Beatles like this: ``&(@(saved: Unrated), Beatles)`` For creating saved searches, use the "Edit saved searches..." item in the drop-down at the right of the query text box. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/shortcuts.rst������������������������������������������������������������0000644�0001750�0001750�00000004050�14324322342�017016� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Keyboard Shortcuts ================== The following lists describe various keyboard shortcuts and actions for their corresponding interface element. Many more can be seen in context menus accessible by right clicking on a specific interface element or by pressing :kbd:`Shift-F10` while the element is focused. :kbd:`Primary` stands for the :kbd:`Control` key on Linux and Windows and the :kbd:`Command` / :kbd:`⌘` key on OS X. :kbd:`Alt` stands for the :kbd:`Option` / :kbd:`⌥` key on OS X. Main Window ----------- * :kbd:`Alt` + :kbd:`Left` - Seek backwards by 10 seconds * :kbd:`Alt` + :kbd:`Right` - Seek forward by 10 seconds * :kbd:`Primary` + :kbd:`L` - Focus the search entry Browsers -------- * :kbd:`Primary` + :kbd:`Shift` + :kbd:`J` - Reset filters and jump to the playing song. Queue and Playlist Browser -------------------------- * :kbd:`Primary` + :kbd:`Left Click` on song(s), then drag and drop - Add a copy of the songs to the playlist / queue. Song Lists ---------- * :kbd:`Primary` + :kbd:`I` - Open the information window for the selected song(s) * :kbd:`Alt` + :kbd:`Return` - Open the tag editor for the selected song(s) * :kbd:`Primary` + :kbd:`Return` - Queue the selected song(s) * :kbd:`Primary` + :kbd:`F` - Show the inline search entry * :kbd:`Primary` + :kbd:`Left Click` on a column header - Add the column to the list of columns to sort by. Tree Views ---------- * :kbd:`Left` or :kbd:`Primary` + :kbd:`Left` - Collapses the element or select the parent element * :kbd:`Right` or :kbd:`Primary` + :kbd:`Right` - Expands the element Text Entries ------------ * :kbd:`Primary` + :kbd:`Z` - Undo the last change * :kbd:`Primary` + :kbd:`Shift` + :kbd:`Z` - Redo the last undone change Paned Browser ------------- * :kbd:`Primary` + :kbd:`Home` - Select all songs in all panes * :kbd:`Primary` + :kbd:`Return` - When the search entry is in focus: enqueue all songs in the song list Track List Browser ------------------ * :kbd:`Primary` + :kbd:`Return` - When the search entry is in focus: enqueue all songs in the song list ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/stats_rating.rst���������������������������������������������������������0000664�0001750�0001750�00000002535�14231604332�017471� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Stats: Library Statistics ================== Play Count ---------- The internal ``~#playcount`` tag is incremented when a song ends or is forced to end by the user, and the playback time has exceeded a certain proportion of the song's duration. This proportion is configurable in the config file or with the *Advanced Preferences* plugin. In case of radio streams, which don't have a defined duration, the play count gets incremented whenever the stream is played. Searching for all songs that where played more than 10 times: .. code-block:: text #(playcount > 10) Last Played Time ---------------- The ``~#lastplayed`` tag gets updated to the current time whenever ``~#playcount`` gets incremented. See details above. Searching for all songs played less than 4 days ago: .. code-block:: text #(lastplayed < 4 days) Last Started Time ----------------- The ``~#laststarted`` tag gets updated to the current time whenever the song gets started. Searching for all songs started less than 1 week ago: .. code-block:: text #(laststarted < 1 week) Skip Count ---------- The ``~#skipcount`` tag gets incremented whenever the song gets forced to end by the user and the playing time was less than half of the song's duration. Searching for songs that where skipped between 5 and 10 times: .. code-block:: text #(5 <= skipcount <= 10) �������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.957602 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/��������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015165� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/index.rst�����������������������������������������������������������0000664�0001750�0001750�00000000141�14035600052�017020� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Tags ==== .. toctree:: :titlesonly: tags internal_tags tied_tags patterns �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/internal_tags.rst���������������������������������������������������0000644�0001750�0001750�00000013276�14343330263�020564� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _InternalTags: Internal Tags ============= Quod Libet stores a number of tags internally, that are either not stored in files themselves, or are derived from the values in the files. String Tags ----------- * ``~basename``: The last component of the full path name * ``~dirname``: Everything but the last component of the file path name * ``~filename``: The full path name * ``~format``: The file format (e.g. "MPEG-4") * ``~codec``: The audio codec (e.g. "AAC LC") * ``~encoding``: Encoder name, version, settings used (e.g. "LAME 3.97.0, VBR") * ``~length``: The length of the file in H:MM:SS format * ``~mountpoint``: The component of the full path name that corresponds to the file's immediate parent mount * ``~performers``: A list of performers * ``~people``: A list of all people involved in the song * ``~rating``: A string representation of the song's rating (e.g. ★★★☆). Note that in most formats these are per email address. * ``~uri``: The full URI of the song * ``~year``: The release year, derived from the ``date`` tag * ``~originalyear``: The original year, derived from the ``originaldate`` tag * ``~playlists``: Comma-separated playlist names in which the song is included * ``~filesize``: Human formatted size (e.g. *4.5 MB*) * ``~json``: A json-formatted string of all the non-internal tags and some internal tags The ``~people`` Internal Tag ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The internal ``~people`` tag combines the following tags to one: ``artist``, ``albumartist``, ``author``, ``composer``, ``~performers``, ``originalartist``, ``lyricist``, ``arranger``, ``conductor`` in this exact order. For sorting, this means that all album artists come first followed by all artists and so on. For song collections / albums, the values of each included tag are sorted by frequency. Variants: ``~people:roles`` includes roles e.g. ``"The Parley of Instruments (Orchestra), David Thomas (Bass)"``. The roles are either derived from the source tag name (``composer=Joseph Haydn`` → ``Joseph Haydn (Composition)``) or from the performer role (``performer:composition=Joseph Haydn`` → ``Joseph Haydn (Composition)``). For the latter see the ``~performers`` tag. ``~people:real`` excludes *Various Artists*, commonly used as a placeholder for album artists on compilations, etc. The ``~performers`` Internal Tag ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The internal ``~performers`` tag combines all the artists specified in the performer tags to a single one. Example: ``performer:vocals=Brandon Patton, performer:banjo=Béla Fleck`` ``~performers`` will then display ``"Brandon Patton, Béla Fleck"`` Variants: ``~performer:roles`` includes the roles as well. For the above example it will display ``"Brandon Patton (Vocals), Béla Fleck (Banjo)"`` Song Collections / Albums ^^^^^^^^^^^^^^^^^^^^^^^^^ * ``~length``: The length of all songs in H:MM:SS format * ``~long-length``: The length of all songs in "H hours, M minutes, S seconds" format * ``~tracks``: The real number of songs in the collection in "# track(s)" format * ``~discs``: The number of different discs in "# disc(s)" format * ``~rating``: The average rating in music notes * ``~filesize``: Total Human formatted size (e.g. *4.5 MB*) All other tags return a list of values retrieved from all songs, without duplicates, sorted by their number of appearance. .. _numeric-tags: Numeric Tags ------------ * ``~#added``: The date the song was added to the library * ``~#bitdepth``: The bitdepth of this song * ``~#bitrate``: The bitrate of the song, in kilo bits per second * ``~#disc``: The disc number of the song (the first half of the ``discnumber`` tag) * ``~#channels``: The channel count * ``~#discs``: The total number of discs in this song's collection * ``~#filesize``: The size in bytes of this song * ``~#lastplayed``: The time this song was last played through * ``~#laststarted``: The time this song was last started * ``~#length``: The length of the song, in seconds * ``~#mtime``: The time this file was last modified * ``~#playcount``: The total number of times you've played the song through * ``~#rating``: The rating of the song, as a number between 0 and 1. * ``~#samplerate``: The sample rate of this song * ``~#skipcount``: The total number of times you've skipped through the song * ``~#track``: The track number of the song (the first half of the ``tracknumber`` tag) * ``~#tracks``: The total number of tracks in the album * ``~#year``: The release year, derived from the ``date`` tag * ``~#originalyear``: The original year, derived from the ``originaldate`` tag Note some numeric tags have string tag equivalents (see above) for human-readable format. Song Collections / Albums ^^^^^^^^^^^^^^^^^^^^^^^^^ * ``~#tracks``: The real number of songs in the collection * ``~#discs``: The number of different discs in the collection For all other numeric tags it is possible to define numeric functions by appending ``:numeric_func`` to the tag name (``~#playcount:avg`` for example). All internal numeric tags use a default function in case no function is given. For user defined numeric tags the average value is returned by default. * ``avg``: Returns the average value (``~#rating``) * ``sum``: Returns the summation of all values (``~#length``, ``~#playcount``, ``~#skipcount``, ``~#filesize``) * ``min``: Returns the smallest value (``~#year``) * ``max``: Returns the largest value (``~#added``, ``~#lastplayed``, ``~#laststarted``, ``~#mtime``) * ``bav``: Returns the `Bayesian average <https://en.wikipedia .org/wiki/Bayesian_average>`_ value (``~#rating``) Being most appropriate for ratings, the parameter is adjusted globally under the preferences for ratings. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/patterns.rst��������������������������������������������������������0000664�0001750�0001750�00000006742�14231604332�017571� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _TagPatterns: Tag Patterns ============ Tag patterns allow more complex string representation of tags, with a notion of if-null defaulting; whilst this sounds complex (and it can be!) it's very useful where libraries have wildly varying tags. Tag patterns can include strings (e.g. tag names) enclosed in angled brackets like this ``<artist> - <title> (<album>)`` Which might produce: ``The Beatles - Drive My Car (Rubber Soul)`` Usage ----- Tag patterns in QL can be used to change the information displayed in various places, like the playing song area, columns in the song list and the album list in the album browser. They can be used to group songs in the paned and the album collection browser in more complex ways. And, of course, tag renaming based on tags uses tag patterns to create the file names and folder structure. Conditional Tags ---------------- A simple if-then-else concept can be used in tag patterns, testing if a tag is non-empty. The syntax uses the pipe (``|``) character as a delimiter, in either of these formats: * ``<tag-expression|non-empty-value>`` or * ``<tag-expression|non-empty-value|empty-value>`` So using the full (second) form, a Pattern of: ``<album|Has An Album|No Album>`` produces *Has An Album* for any song with at least one ``album`` tag value, else *No Album*. Note that these can be recursive, i.e. both `non-empty-value` and `empty-value` are themselves tag patterns, which could contain a conditional. A more useful example now: ``<albumartist|<albumartist>|<artist>>`` This will look for the ``albumartist`` tag and display that if available, else use ``artist`` (nearly always available). Examples: * ``<~year|<~year>. <album>|<album>>``: *2011. This is an album title* * ``<title>, by <albumartist|<albumartist>|<composer|<composer>|<artist>>>``: *Liebstraum no. 3, (by Franz Liszt)* Conditional Tags With Comparisons --------------------------------- In addition to checking if a tag value is empty, the "if" expression can also contain a value comparison using the same syntax as the :ref:`search <Searching>`: ``<sometag=test|the value was test|it was something different>`` or more complex ones (note the needed escaping): ``<artist=\|(Townshend, Who)|foo|bar>`` .. _TextMarkup: Text Markup ----------- In some situations the resulting text will be displayed in the user interface like for example the album list or the area which displays information about the currently playing song. To style the resulting text you can use the following tags in combination with the tag patterns. ===================== ========== Tag Result ===================== ========== ``[b]..[/b]`` Bold ``[big]..[/big]`` Bigger ``[i]..[/i]`` Italic ``[small]..[/small]`` Smaller ``[tt]..[/tt]`` Monospace ``[u]..[/u]`` Underline ``[span][/span]`` see below ===================== ========== The ``span`` tag can define many more text attributes like size and color: ``[span size='small' color='blue']..[/span]``. See the `Pango Markup Language`_ page for a complete list of available attributes and values. A complete example might look like this: :: [span weight='bold' size='large']<title>[/span]<~length| (<~length>)> : [b]<~rating>[/b]<version| [small][b]<version>[/b][/small]><~people| by <~people>><album| <album><tracknumber| : track <tracknumber>>> Note also the literal newlines. .. _`Pango Markup Language`: https://developer.gnome.org/pango/stable/PangoMarkupFormat.html ������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681489057.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/tags.rst������������������������������������������������������������0000644�0001750�0001750�00000006171�14416276241�016672� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _AudioTags: An Introduction to Tags ======================= Overview -------- Quod Libet supports free-form tags for most of the common audio formats. This means you can name your tags in any way you want, but using common tag names for common purposes is advised because it helps QL to write the tags in a way that other media players can understand them and also helps QL understand certain tag values and make use of them. Quod Libet also supports expressions using "tied tags" in several contexts - see :ref:`TiedTags` Sort Tags --------- Tags ``artistsort``, ``albumsort``, ``albumartistsort``, ``performersort`` (including roles) will be used for sorting if they are present. Lets say you have a song with an ``artist`` tag *The Beatles* and want it to be sorted as if it was named *Beatles, The*, you can add an ``artistsort`` tag containing *Beatles, The*. * QL includes a basic plugin for creating such sort tags automatically. * The musicbrainz plugin includes an option to write sort tags if found. Programmatic Tags ----------------- A programmatic tag is one typically added by either Quod Libet / Ex Falso or another program and not designed for human consumption. Examples are ``replaygain_track_gain`` or ``musicbrainz_albumid``. Note that to see these, you must turn on "Show programmatic tags" in the relevant preferences window. Internal Tags ------------- Internal tags are tags that start with a ``~`` like ``~people``, ``~length`` or ``~year``. They are either not stored in files themselves, or are derived from the values in the files. See :ref:`InternalTags` for a complete list. .. _PerformerRoles: Performer Roles --------------- Quod Libet supports performer roles, which let you associate a performer in a song with a specific instrument. To use this feature, name a tag performer:role. Quod Libet will display the roles alongside the names in ``~people:roles`` and ``~performers:roles``. Album Identification -------------------- Quod Libet uses various tags to define what songs are in the same album. For songs to be in the same album, both ``album`` and ``albumartist`` have to be the same. In addition the first non-empty value of the following tags have to match (checked in this order): ``musicbrainz_albumid``, ``labelid``, ``album_grouping_key``. Common scenarios ^^^^^^^^^^^^^^^^ ''I have a two disc album and each disc is shown separately.'' Make sure the album tags (and ``albumsort`` if present) (remove 'CD1/2' etc.) and albumartist tags are the same. ''Two albums have the same name and are merged.'' Add an albumartist tag for at least one of them. Common Questions ^^^^^^^^^^^^^^^^ ''Why doesn't QL know that my albums are different ones by seeing that they don't have the same artist?'' There are many songs that have multiple artist, so this can't be decided on the basis of artist tags. Replay Gain Tags ---------------- The following (fairly standard) tags are used for volume adjustment: * ``replaygain_track_gain`` * ``replaygain_track_peak`` * ``replaygain_album_gain`` * ``replaygain_album_peak`` See the :ref:`Replay Gain <replaygain>` section for further details. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/guide/tags/tied_tags.rst�������������������������������������������������������0000664�0001750�0001750�00000002362�14035600052�017663� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _TiedTags: Tied Tags ========= Tied tags are expressions to produce a readable formatted output of more than one tag. Tag values are outputted left to right, with the default output separator as ``-``. To combine multiple tags start the expression with ``~`` and separate each tag by ``~`` again. Examples: ============================== ================================ ========================================================= Included Tags Tied Tag Result ============================== ================================ ========================================================= artist, title ``~artist~title`` *Bob Marley - Jammin'* ~#track, ~dirname ``~~#track~~dirname`` *5 - /home/user/music/Reggae* date, artist, album, ~filesize ``~date~artist~album~~filesize`` *2000 - Bob Marley - Songs of Freedom (Various) - 6.9 MB* ============================== ================================ ========================================================= Usage in Quod Libet ------------------- Tied tags can be used in tag patterns and searches as if they were normal tags: :: ~artist~title=/AC.?DC/ :: <tracknumber|<tracknumber>. ><title~version> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/icons.rst����������������������������������������������������������������������0000664�0001750�0001750�00000001346�14035600052�015001� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. |ubuntu-logo| raw:: html <i class="icon-ubuntu"></i> .. |debian-logo| raw:: html <i class="icon-debian"></i> .. |fedora-logo| raw:: html <i class="icon-fedora"></i> .. |opensuse-logo| raw:: html <i class="icon-suse"></i> .. |windows-logo| raw:: html <i class="fa fa-windows"></i> .. |source-logo| raw:: html <i class="fa fa-file"></i> .. |arch-logo| raw:: html <i class="icon-archlinux"></i> .. |macosx-logo| raw:: html <i class="fa fa-apple"></i> .. |github-logo| raw:: html <i class="fa fa-github"></i> .. |bug-logo| raw:: html <i class="fa fa-bug"></i> .. |linux-logo| raw:: html <i class="fa fa-linux"></i> .. |flatpak-logo| raw:: html <i class="fa fa-cubes"></i> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9609354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014377� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/album-list-2017-08.png��������������������������������������������������0000664�0001750�0001750�00001032205�14035600052�017773� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��=�����q���sBIT|d���tEXtSoftware�gnome-screenshot>�� �IDATxw|\ՙϹNQlٲ,7\ccMstBH$l^6n6}7즑훞 i@ 16`0*KV>cFHlZB_zI3s{5<uꩋ @Q[SKI(?1!B!B!ğ,c 劀lˢD<cرȫ]_!B!B!8&c 0Xn<?10iRd˶�P !B!B!ğ(elV M ĩIEA)JEծB!B!B@~@(EI%qpKޫ]E!B!B!%P.O9EB!B!B?c~ql_C6_X(>Zk,"8b(JYe !B!B!<@ CP$qIj̺C䳽/˽ng5Ibc/O1s3SWWO$Trc]ڱW"e)0R hzY畻b/a#6'B!B!Ϙru:vd&'Ϟ=AQN]y<,d2>fY+!W231(ʫ-9\{� R3Fh±m| Dh#[8m|A+g M֏\&Cϓ$9^S}|RFcvŷKq kY@.A:Ծt?:JB!B!k{ 3EX"rtSa<{/\L@ X=PDZ*K`)pAT5Ayc3s oߍZ맷?K:S -+(]5A`"5:'WF%f dKjs/כIP3XMhr%R)}lwm8/SQtћSaqW}5Ao4F/cZ[9<KV>6Wڌz-cɤsd . !h] 85~9:B&^s }^`[hmP&D&_"]\B#9vm?^yעZtH8 s]\sIS)<{2c^h^!B!3 o}NOc LkΘAЏq>."ag0(a!ɱf*<%}۶Y|)5iâ-ϫ!b&ӹg7?<EVWδ<<?(L*\3j]Mt~tsW¦AGPFa$C_6۶-@X{1|%IO}u wm7oH#X3pW, _y'%<,3(Qhp)K8}^+R!L1Cl^Hfkٌr)6!Etolxa:]Cvuq[)`tgA�ܳ^�A5D8 XK<<; L\Oi+9ԹLkN6.]<꒸X}g!(WckXumkO&1f3c7^/B!B!AO`Bs&%j E� aogNj(鹌G[!fӢ1ΞLx<:XVkk+HuU FcNLoo1Z1Yz՘e"DM /Qp2yV#Sgg~ݻj0WEYC"�a3r04 XM"Hˀ?>LkJP &!Q `O;V%by˶HEm86LeX`Lu9PL1Ob,-3sԍcBʱd<DhApB< eqBk3ȸ 7} ۶1ET9VUJa[T9w2;Y5Aa0ZbL=Gq`j}6oRT`s(B>p5kZUWȡF]#Z/@?B@rh c*J:?(lۢLZvlQhĦ9BC_6[,` Jacp m(ٴ1J۟ڀD4F,5C(qֻ>3Xj}'̄'fNs3{DRtZџ7}ENU&+AYEm,F`3d(.Zڣg ] mTfjBՖC(Hئ1%̜HJAQM*jL1qB!B!86,<j29<=9?oSSXT5g̼ZNHT!Ya:& 2R_8iI--8nY\rQzm �}n+;Ѽlw z.9lY/߿?}]!Ny8}&%-t'6oI" =p<5<k�{#ZP hsϻ'O)k@ۤseqYhQoG8HԹS9%E׵u?C'&Q1sLb-z̙ҳqϞ&Z Tl>s.a6L!f<ͯK6ϱr_#4y1W\x*s&E2=Wp!U*MՒpl A.t?y7(BLZ)#gO7RL1nŤ))P,{ǝLlk7+T~h |{Z ]O7NaVő0ٹ7Gsy7q;ضnpNtaΪ8s4Zm=$7]S^9+'ܘ"dn539>7ݼPܢ3gv\t"u_<zlrхfμd5˓W{j8YV]<.&N@&!5}3e_q>ܲ~i/3Zi8u\k7?٘'t$w_>w4?D~01>ȳ{E(I9I^͹{PiШ<0&)XqJDv=/v lae_,>ony/L^z^u??oK(:(OJ!B!Kwbf|̹|gj>:c#BRb~< TJHDUVooY&fQ'RZRGNR3lL^N>f2!<B,^V7^~k}L !58qUr-YaM#ˢm*�4 z?W/J}BPTKX e.Z}+_9 s$Ci:]&[귯b~( }å( !(;QOcʢgw?z*Np_%̚E5[8A1OfNW _r ZUXÉQp{s P[oS3LjBe2�-PbE8(,((߄h6tLKr/MCO?M1P=i|_5`!c aMLE5XܸTC!sϸ$;͔oL"0f|NR V,bn\d X@&_˒T KQR-9A\$꘱bYn݃:>yBzf,沿57pJv~@mL/#6Ls"*?ä&\@um9{i#6OCM2F<sϸ\5/ӗZ?r6 UR =5oM%b<r"v67]W~49̽})L9 `(sjxP5\L|o#iۦeɄ<=bmzQ]&V*t=rLO!B!BVcp{1RaIȜNp oRYhmi<G֏YO?mH$|ܲΑYx.@ bY(%Z.Z5/u$^ʇ߹E9mYYo޵3oU1>ᗸ�8&NIkP6:>3'f\§w: 1?<g4ckr^,eiK6v'h sw]]'f^Cl&!w2t nNd<zl3?Yl�ZY4%ƀ~yzL�|[l֔q#%|L!Fq@]V½DfN#\AE7;Ξ̴3'8ܓlx1M#?*TB_/1L}"V9.}yI44۟?B}Lcz!"5ԄAНygO!fwp7ŭ{=s^߿T& n+g0:ǣ"?`8z:K-6\E~s2}w|ч-Ԟ0Zx]*mp$J$>K?xմ3{]ct L<~oܰ3Ƃ7}w.m,G6R "a|<\?[-Pآ!@W-x>q2S6ʲ}&i�ex橽s409G2 7` dk³X{V ɱƯ{ͻSxj{s),?&?ڜƚy)4 tMmЪr+sn*{ 92O}(gmHι4&\ƒ ]f6B]OgS-a[10 ~_ !B!>NRSk`'S}@-jgOmrIa;XPR|RCϭ^zʥ- 2:G<0qL89凖mt<6NaeN?njiطq=s65j#" q`/jy#:RZ ` ωQ,4XaZ'1/ OfiJ,A9:ZژꀢUR'꩏l8Im\O<J- 8T@RQLBNo7=Kzl{"M;o*q ӄWQkϳ9LE Nں=ijY쒋:8zs%\ wjR&ԇ1F hjidqͦ,;m1KNI˼\TN|RO庴&e W<7Vհh( |)`[[t?mmLu ifՇU ,I5Rc�ńSȖs}W=h"F89 n!H7+]d7ƕshr0AHܹ1(-TuS޽=e ulP+g/Y̏%&‰8Z𐃅d>lalRT>/±Aiqp,DZG"6m+oض{H[[ g"-”viKT9=:AOv3Q_4'"mmLH6m9 ZXam(?^B!B!ıwxe+vd}N J/(çNc0i\a7dٱl)y mيt:M2|縕TJd-ec>he4O~> ?R;@Kqh/1}˔H4Ơo% SPiƪV*)eXNz46XosuBɕ O|w0N cʫŻ"-g-VO+tU'57e042lVʟTxJ ?GU QߦgYdSU=rFkӁ`@ ػn}u$;xיi=LS6}Wa)5RJA!̆4e{:9hf5p#CWlRXrS aFvt 'ی08Wr�^)1{xS Ԭszl!!Iװu0aGq 4e8 ZFC}wvo>`"Ed4ԑbBCD/8 %cd;* 2ÆGi9*yTsAϡ׏z(x`;ߪt7=X9}/B!Bc=%qx/`DT,\>l:alyGG`?8!gp(DNfħm>96m<jYxT3ܲ,E8fBRD"h?ftq=mIb%,@ww*FbUFCP dPv)IyX! _ Xu4 ぃ9Of)<}hN 6I:xp] kY` ںKO6b2Š2Bzb1.]Omd0a�  ?ǖxIr wp_}+r=(ӆD,,?0=d:]Fmtzl'kr.ӗ.eG:"π`whJ𜉬T&?b'P-lgf/3yՕ\kش׫+OUP9w(9,v-Fa'01ڇGg΁A|K0`PE(~umLeO<.?*^+r7Om|"wvџ o,jqJʧؿS#?kw=}G͚e1wlcec9sSogװ*^z0:bsWBnˣ3/fvh&W4 #ž樐LA ;TۮާqCWeKWh;`1u޽ HM4FPAq>B!B!FgqVoU\RP\oAeѢ KKE@Y[!gLezC}d'4DƕiY^T2~̲X>f9}}c58Qؑц T\)OH)s3{$c|ᒀP,ҚֱRV%<'qBؖBL'(tayW-Y[ /hd0�Lrqφ3.0_d%d6p׆yϲ\~>HQ;"7_G|W%]P#(݇4F||žE6` zNz|"3Nc<zF(bt[Y0+ϞW9knsI|CId2Jdc 9 h'N N�cl(G1o]$)VVgٙW(܎<Kƙٵ%l{?/y!.MgYS 4*%dN% -,,P@xҶs2޵|-͓${o/H(a <߲ecY@u9Pj)gZi~m49#Ԟop, R觲"d n%kHC r�ߦ(b'M,y)4L]Ç?O"c72oɉLK*ti޹Hsz/9+M`W2/v|Y3W_R{YXcgL?ϭRTqjn3=׮_Tnҽ#/Pw%ostD`rhℋ;[u1JygcGÅB!B1oG"aOH|w6A.]C)��� �IDAT2;D˨DرYgb)UJfǎ]D#}.Xe`^G& wff5G8~Ap $@NHmX axC]ͤj.V\æ4Dݷ]ǵ}8\kIGӱoi j=ٵO?iIb@0:cjS-uB!<{np8C1p89 'y:3$g<Nr&odˁ#tOiB<a">N"lVQf]"az >T(UעR>`4s2u1J{:ٷm3w:bFMu>+f7S ݧh~ڶ)D&s~~kٶL-hgJCYtlKQSb׭q՜w LkLtJd:p(ocqtF>ت2< m +APAΞǴI̱| ~Ͼ!mc`9WB*}ԱM6_zmWo7j!r;/y.+ nsKϸA]ꓧT/8cCׄy\b.S"l[qf׭[9oS$K aXsH%\}2ֈǀeeNLk6AųwEH([7{:@g3VF2B!B!:wYƲcn<jm0ڠrwPH8<fY6N! VdrYl^'+x"x9-5*Q.ڠ"V#a\lL7Vk3(ۢ)W Q*f~P^|V4%lJjxF6 cEC{.:(,KXPPR+m QXYƔ%h)HȐ-{XEC6.JMbT`e*k𝡌57S*f0A ˆE? Lq.J)"!Ch*{0Q >@f"^!rv˲ِvM==-Y$1U6(Ayq<-סڷ\PX̨"6QT=Ӹv|) \"!E<#s}e11d}Jr XVNu1k5tkEc\S(O$ȔlBe[4Cij�E|a Yuy\n"hmM-}<t_08A�Q<Bgp= "D$oC7J'i<:�1s6:l6h0&zRu=q !B!blZkԚUg7 ]eY8Had7Q{qB0!~@H$SIb(eu@P$ɒ ChYbl(H0~1!Hxu8!r7WͣC)}<}Ml8JRhcll"_q !B!Mk}l<cãD%s<Xٲ,l"QJ<۶”eŢW,16cV(L"(7+םd4ƴ/ dآONVq"sښikxO,ޫ04́B!B!cP9c\BhS^{R [ OQu JDŽB!B B14OīTnLn!B!BWo B!B!B?w#B!B!B׎r=B!B!q^z!B!B!K²,BjCuڅB!B!ğ:Dz$%PUB!B!ğGr!B!/ŋ̘N$y#P*عs7q'6=15S!B!B/0IDcq,XW X3X 504Dx|5{;5ry:L6N>;vB!B!r6ZʳoS CQyqdՈx "_lxh, NYt263>k!(2]!B!u]IX@Ȉ܈h܋|V:p} c3M6'9F#"5bWK7N ײy ),1nW+p J&&B!B!L^:䙡X8V6TPUUcm\=b,a)hv:zv 3+ @ʱYLZ\9=?N/i!B!\$*Oى0}8VZ@<0K,fvk3!ǮB?Vajd`tX`uΣVQ,ë6YcH,`U>F`*kYh4:)^$M)iW²l'D8"dASQ(xQ0sNiK&3`ԾTY/{ !B!5<``1{*0h[vgߑ>Z'ԳH/Gii#T9\fߣW<6,%+6U+vyeqVol}F}0xYڈ7#J}Ȝb\ƚ94o^<DGtrx8[m1g NS5y_椩Ǿs-:K<S$zK{%+B!B!īȡb5[w`KShIJfs3܈[@0尼 Ρy:Sxa0`tgt9V2(PP* ,Jf \ʫ kGSt0ةPVX+Ѧ)k[iJڀ4aY?'.+dӍ_Kٍ:f>j/[^e4-/`Q\`~U~X!B!x9Y8t6ϭ<Ur,JhVy#bJ4ٗfwgS&4fXcAwX$ m]=vPm0Jt(hk*Q>"^W])jP((ʮ^ X`֘r=0Ǩ *[ B: t6O:h˲F2]D w'6\�,"5zɬBjod??xL; 伩ǥkxPV3eY2"JtB!B׆!Þ`̞VG/+>uSjyr>vwvS3&t%6֣(Ew&=R|r"D Xy~y\mP$P ~5(8e6iu=DG*jUT Ռk%@C6_ |!7>z9ڀRR9&M{, z`𱦔>d['s/E^Ǔ~R,x&0, '"G{CѸMe>QU o'z!Q$:+(~Fa6N(ܹy [P|,eDc=>bhAa) ۱ GcD_$pFBw=O[/F 8;VYuq=?SF)l&HQKz^//% hp/y Y&Q'VhSHH3J0ﭟk]2B!hmmtE Ćz(<$zr8s6>U'e=̜̾vv/[&s1eq?`rCϟ=Sɀ<SkVͱ9r*ΪajdRhcQhG["~+?<|x,L2%Wp9K4bl1@Ȳ ."dWgޘ-qk|XVsH$`Ó0OIky+X|dClQxSv83Y:i-Ll% `ǖGYm`qe2'ji|׼KŶM$>û#쯯aży%yX4&sm?į Cwz 5S";y䶛Ouies{YI%\F6ݟc(O9e'gVLj  c2tuᾟ|w*)]&~h9j:)<2پe#|:]fs|4s,8M\|)̛@2v'xX+"bLiH6ɴF ^Ȋ| "&꼒i/#\!B!%Xx, j̚<pvh`ohij$#aSqx,J{K3u5Ig`6)MBD!fN²l~?r! Yb%;SU`Bv G<GhMyPxKA4!96b@gZĸ#{<aO^*A*QSOUSeͅ&vNYG|nPU�jg[.cExQ$8ie'._oE vCb.G:)/qeךƛ>\5/Qmy:vfB`v,Nh&KX>%1 ~2>FCP*P6ɉX8Ǭ[sWz)=Foe"Ŝgz- О?Ϊ67/|bLk m~, ǻxQF1퍟3WL3[IMlㄳWqd}lPLJs(^>{1(uML=B`㮧c⩯ kP] -=fၝw]_eA:ޥy!qOᅄ_k!B$tiYN?<IpS ZBB,l  & IIM N<"dv2oBݱ?51яk--۳zuMKc-|h8U85*諪! ogmLiF&GdX̸|ll3/ma_@r<ξJ.;e$g>xyl5|}7RaҜ-sRcR6>-_[R99qNǸj^#lFnzp+>;,.`93j6q>pz3va7n}+xdE|xoC8,xYhK~_jA}qN=4!aK ϓ54O9suٞUm;Sp Sp}mbױvN~E=#'rEyOx";j'h }L`RǏ?Si>n TtX3"G6À) <oʼnkHZPv$Nm"v 䋕a2& c.5`D$߄.l7hcPM(% 30{DY"Q"f 6(,!`oX>o%{xlijۃp"| vE':qIp})&U_Grif-o!:ء+Om*{YB!5h Y#ÆP64/fu!,zC|% {7BBH4G,i>--!ŏݨ1;2t,٠ K)>jp$ {ux۸1[xWL<_~u-nJ%7pӈD,R}N^KKjձTryƛdn7Pr/of㛏Y怗J\`Zx%UDT}p6o`2o]wf~yۂFιz-wmxf+#o^=|,OfﮗF7yi(SWɆϧoYu$y_ӕv�V-SVjlUK Ñ8HSPeϖTiE4B,G\ZkOn8fhʙ2t̼zbd#Eܳl߃\/o<toÍ;rpB?k7=Mni >m+pl&F=zma?WO牄QԜz,=uQ,7~~ؒ+rڧ4ӔPw5<.[-]<ӫ &} 6QRWধȆ6sk?;N甩w{)H!@:*^zޟʽ+ A  M&MN?13gfgv7!5s9sf2Ɲs^lMp(~$F4OܻW՞ݳ�&.~y;Ԝ͏n#|J94<rytx[T )gsGIURZ"w4-3-<_]V<�K<~�dꁟL UwQgO[yGP( B Ǒ1#R� O~{3�jWB^"iQ3N|(&(L / wǡ+A+Gy( ύϷ;w26t̚5vpq|슏RRRrNq҉8vc<‹i9/ǵlܴ;ﺗ}Ң;AC)ńs8㼳?ƏIv,yU1Y8>%=gN/?&L?7)nM߼E*g0bg0!>hF W"`x=9~�tΊs?)CI$a;cH~~\d܉'1-o|s wxNaA v)y$ ?$0HRNl?7:7=JNA%ifDr's7w[ _Bn^yMNζ=MEY gQ6s}ؾ#gUͥ Q;wDrj1옳8{^}[ؾ2-]Xh:3zk/&%5Td6VIs^tqݽu8(ۯ"bz?1@}ϳ4Spfݫװ% jj_?OAq,>N歯s@+wi`L\Z-T>󻯲p-|/ӸөYy�vL_|)sm߼.@ev^:ydfxŝrL{^_2x$fR]7kԵFU!^BP( I&= vg)pY=Ii t`(p-p%ׂ !!|E"cA!OB;bx|&ss6ivq\uՕL81+潶1 ]Ήr]n{ϱ|˦1^\2<dB ~Nb5C N[ {FNC;vԱ:j_5DŽo>}Z]i-sc2r̰{ٝ,Ի F/lFԠlHZ@IO=ɦ1}"zt{e,}W Bj|p4\\6k7v88}H^|b? {Vxp+}~% ``ڗ۽^_ϛ򏮬f|m1|7s/KxyC;""#~ff6ֳKXӯpƍ1!{D�� �IDAT%v*g3Or<sߖxs-py^3; #i%# ;x{z0%~x4v~R{2qqL{`;sk[]ZP`ʞo~KϔwI﫝i//sWMw/cp׉̥eZj=ޔLDؿ+.qZ>uڞoIfݸ}]v-{ 8vM4WLӧ1x6h0a:S]smnY6;.;&=@ݶ|)[b'RK 9o6?ʞ!  `jn$(]A|rgMMj2$|BP( Cdn@`ej3Ra>tnz H2Kdؔ�Os(ce̞} mI8̅iki}bرc7믿?HWWb]9S;,[okŔH뤈G:iiέX 6O/e$J_z2!Z+B|P!ž ,Q Pl>Lyw|a dn@% Eb=9s9 L;"x!k^ϒý5c%XX)KKަ5/EGuL|!{+vA;W}<lS54.oFض~3sDՓkOw7mEV4~m'q7x{x|[?/O^?ZP@ cN"G1BoaۖFbcf{=wd&^eE5/N%7˙ΐ==l'cD`c[&I"Wƌnc..=XXÊ6z,#ٚs ꌟ<W.0F.]鼧!ڳť GXvI($Ii ;k 3cP\^d圙hDP6>C?/_7ZlKyݾw H}'FkHN;"5Ng3KO׻WZJP( BxOVD̊xE;u']BX>BiV(8Y R̴'bNwؼ>ޥ)8G5c'|bСJQ! g֬۶_i{,wu?"g~uoI%l$&"/7Zt}D2Ν�^m.!r8+?}ɂi8fI~qL:|>| ǜt4acqE?Ő4Qvlq4Xw</$]kK:b/bԊgؿe-SbRҍ0N q`6q5^6ًN#pS;f--ItWbǿ7b{`#5K/*"$lv-Cb1\'~X#嬣R~*좳K„}> DCۈX? ¶~B ۧbhӮ3 ۗz<#Fk4W7|H+XѥNs Z)_}%OK28 jKth -+}=>o"+ynE3"ho$VtN?q8Q( BP(>tz)ēq>= |bg13?d\L?=E5J]^6@=q<<Ia RÅyŀp8ħ? m:j_5Uиcj-DCަ¡wZ;V.L `G<&/3XGiEW82A]ԝ/q͂Ly]z+~8v v QƼ䯛bƇ:>[771c㇦\sEKˈOb.ooNO:E3΄"n M>[[wOAF3uӕ>d;aӻ{ qV,}a&r)'ʙ]\y>~H%^1Wx$"$f^ _޿z;jl_y9_Ou-$$~?GFپܰ>KY0봱pӛtߛ>;@ع{p\9አl)0ז,{} BP( }DAsKOJ- }̷A y629f&] _OIBg oiv' yHgƂ s0Z`ˁիyjCGsiCx&̠-2N`!8xTDu6H7ՂNtq,+?K.wl t޵pi\0:4 O7b|vmG3 la32\ιgQ͐Jh,v wS LmobmEef/,_ }kU(4�!c{}5ksl+>e&xzg〮+ykyL64Z: I~^NJp4~ooŦ;grx'�Hv-\ž"6V5Fk4=u;zxWF�p.gOs^�4 E=sL\Mv1λ~P6dopߝ5X0lp�V*j;H^ Y0[H[�ֻgjMn'fJ[(Q( BP(> r{ŸvI0#DzeBea4GL~|cг psd}{Rd@xB 2=ie0XnCwC48lx?ژG4;ukm?~hsرC[#w<~l|~:y,j1܊i_GmG^`Sl]Z7Ͼnvǜ/gNAմԖo\ڈ_/:юv"DeR]ydE.>j/&4wwE 1l|7b̯@F;hnmY'0 dvK9'YlX6.tN[s0k~kNsImcYþ=mZN]8s_V8npKGG7]tk9b[ى4F1:AW4N$=b!q1㬓j BvCkϲEԡı{ޯ8XĥJtFƉDtvvwgM>h.]1x:MEGhk T?Vq$s[lX[Gһ߬WMD:4 ~j# v\?VMʶI%tl\+2jkOS9B&ٷv5;#.X0hwO-U񍴍ZȥOsJa}@?>-Vtn<bat]x ?4+J2;FFw>m<'}y|!3+xlf96~_1{L>+RS]K/+ S)d8( !mak W8;J' c_K8}wVmfor }2_ds2w|_Ϲl~w"W?q'^wNpS-3Ov]lf%G,,[ټNunK3k#wǸtUH`%Sf;Rs*,a|_2 7y# p,5,`nk%p^�!a<.FD`Ip8+}eW^ig'X:Ry#;<-lk=.Wa GY2v8� 7z)|M;SJ~`άL2S~߮U6rN\q|-{iO1\udƑfoK6a,O6=6md;eKB|~8ؽs7;QI1Of" <P30ٴ?gK9(-fŻIU9{&0t]rWP]z-8jkO@Ĝ>?qpfr5|:ͻgxƍD\ S5N(R8L} BP(8z=_̬'DOOhZ$Oѳ+ߘB^N$7d+vz'/.r(X7C=^6s8wYY]$垿ϲזɏǿ~]wǶs_zzd2oC̃&^&VY'eaTɮoZ+K^͆X_R4 Q:>=}\77{_-[MRv̆A9,{xN_t43&,_sH#t`l_t2go9qé.#Vd[T&رeV$1qd5�Aihb_V</m#0Lm^ۘv,h,9u<Ě=y2Ɂs}L}&<+_gKxmkQݖU<X ‘ RرvC/<sk{^kA>v,N:onoMiag]+-lo,f$Q<gƢ'35DwbæfN&7u#9yΜd7{x2f4L 1 |<&LLIގl&g7OhÂOuThW7=Zmk)wm֭aǥgpزL(GK5֕wC{xg�˹闗{ZWgs3ĉѰ~3H!<s.cx~w1{3iXw~^lʼ֭x7ᬅLhz4ٲYO^> BP( 엖>dwbf0p3W`V " !9kiH? )"@bI'.w~kBC Y<<DN;MX082JJ;'ȵ s'kc8<8Ͽ7e9ލp=1;'q<T(޿HAv7~Wnz/R:+(a˧W*`Ķqgq}G) BP(w~+xbd=Us4| 1zz/`!=r8}爼G~'@: uݔa׎M=Z!2*ԧ_k9f6\t#G(uy[K/4{ ^٘JX twG ڒ޷~^]]>@BBQ{\\xi Ǘp.SrRMn ƞI ͟UBP( B_v7gwBYT~p $*W<m ?"G2߃+K%N>ip7S/65Ҷc�x`0ryݶ7v^>F_̜RX{r+ BP(I|ۭ7 .aY7xx9c wJͱǶ>_"ޛ=9N+.oӟxz*Q׊_w٩?^}}zY[{p^BP( BK1P3{YB4!s bd!P1&Z۾WU( BP( BP(E|<9YpBbeB=<{P^D1)%kӿjzg\i)ÉV BP( BP|БR",}.<Άx~|Phg?10oh:iOU)=}tR7g_QC)YA*qIF"D-$@ȯ~P( BP( b�DɦWzKJ9 ,l�cݯКG^by<3bJlB7 h8&ɼC+w6رN4w /tl)],rRqyY3;q:BP( BP(L ꅅ yfEB`͑)֓ ώӤH}Nz+sv #%w.et({h eHģt%e〔ض]`>{ )IqWO7Esgoyík:rnwxoGvKd`(F:@lPy|]bt UVQv8EDbYLe�z!U`.FwL]|5Wz_ZĺD6.4* BP( BP")  kP{DZȣ%x 9Mܴ)]-}.@=H%!0 l;mc`QH,>-<BqpKO~v6 ӷaSG{R#933.ÁI||jmeOom!=1,~+<~oju),5J3SGa' {BP( B@qqYQObcw3v>-7ǻX|h#v"%Bn="O],h9JI" {״8B;̳pO1( q{g@Wqf3ـFG{ 1a*JLvsӡ/FdHUM-@eu)~7ʺ./vq+A**N~ߌ4BT1fnaoHUs?ʧo_d[;hmKa9. _각-q$h:@FsIŢtSXDh:rC68:;rTUsI6wp*t!_[Zӎc״#2}\=| a,|:߽Y) +)BP( BaAx7_fo5T\z]N+B!cmiq4t&p.Azznx)%n qmd"iXL52oB GT!#)r: 瘳qȊ |;hPN;_<_CY<_BKf9⳿qKgKirާ/iZF\onu|kCTQ|˗pҴ)v<Zoys}8MiӾv�4M .me N?<a*㆖wogP}ʗ^GF7u@b\x5םSx[{w]0'\SQx" -'/L_ȶxO*gan}՝mq1Sc=a7Om묧 BP( BP+ù{f#F8OAW)= dDX xߏi躎miXEʲѴuэt?JbH`iYHC%�RI8а-@0< SnNUޮ8lH1#&y~'s ynIb\y\fEa'jYˎ &O Ӻq'mĄp~}Q@DYmDI�� �IDAT#_rFu;%0<?,;vڞ9E̦ifœ9x;Bav6#D{^=/7v?GR 9k|J<0U IU(R#:?\3eWp>oRiNglM[OQRB$m]XS{vRZ1UhZŞ BP( Bx7BUb-TzrzP"9<}LLbE2DiE0ǓضǕioTi�D@ R)l'E0N zڣ4W-4BP?DOc:X�. 7hn^Zp,NISؾY-4#l{|0v2ƷXf{wI{Qˤђ{k]!?  &O~V7#֑Nĉm??zK-T۱%Ip'KSa1?g=;\OɄ+4s/ae{2kgX#J|3sM쌞ɂ-/#fP9~ BP( B7sP}=y?G+xy'IOޓR"Q4 :;;RR^Vd2ahmD""�!px$.tdb1JBa|>]]㤵4"_qӞ"}.ȬamS|bT&mn=v!iEv0!r@oΌB-_o#d9Vݾ&{JjTеcͮ@$wzm?=q?w=@) KwOK[x[<E|9 V8'1)ŦMpfzEQ&5 KټӘ+r9v5:{XIl۟3W}_s "C.[ BP( B2`#O;$ceEGHaMuIy朋cR"L[9t\WfDfF 5B$ 5$~缮cEA@iia&x$ضI V*E2 =*Ym)"*bp XǤicpw.gAزIk:¢Q1?vE{P2߾Ǵ.ۗ5`{meXKX~;4.Z~` ?I'2-}lw_r+?~CϘ@HbE:xa;s;h̸߹0�r"TIx r5WūJ?Xϵ dtuwl${S|s* ٝe ;{s* BP( B(@V {\nߴ7wfAe =�E -ŕL8똦Ǖ8N ql x`0HGGP]M]7, #t\X,DI&amma ]0}XI )$DiC44a` b&U`ٛC|3̫PdӦV)N#ŽZoUVRIR)bUؽ.Q>Z&k 'F$xA~r34QQOJ&ƭmg[vmG?;v m7vֱ7<]4/UƴD$Rdx&wO,xu2JϳYznjظdy[αI%4Գy(\~,WymP( BP( E2oYD? 4i' v3F6 B4Mu|>MI$ttFq)AMF#M#Ѕ D ıt�A J%urJ+*CFQR^B D w~=UruP0r2G;ؖ .{-9j,^q8gmLtwѮMbщ2tO>vN"j&RھܐZJZwR!?SˤeTg)I6* d챌?NsLⴏalU9eUTi u<r##/ _h.G`LlL,}Z}>֡ՏOA& Lݹ'N,L|lLeTq?ō?37]hl9BP( BP(>Yl}"Eqzܥc奔A8"b6m!F(j~ea:qǶm ȎDP(D*ea3add<AyE%U5BA5%hV gye ?6"Z1b Id{.qt9W^ y7w�dRxa<Nvyg^z(g挑X ʙqϰsDpLְoE%r<~~,HٶaA |�a빇4@pL;E|OW}7Fw"Y HpK.8*yqoesb˾DΘe)\ou?O"^1b|V]2q+fskl%̸;\{Kz6t;IyN BP( BP|`>-ϑ|F}31MYXRL%q$8RB0t]b>? J00}H ~_�MDH$~];(+ a]}La""ؖM(" *hw1/U2O=Qx)IJmLxP KI_g7F뽶GP( BP(_3vt4CKG oeֻ0/!\y"YS�B{O|Nض8HA,4 "i.dϤ !-8KUU"50qR-ߦ2c)BJk9BA%%>:;4= QV^Fu-&tˮ][ܿ} PeBFN5sslQBP( BP(,!wz~ Z^v;3yPRn7hq;T`v$)z&tܶl ~Mфiooilj֌ٸq#*: dnȨQc((Ph"n4ceee >3|: wyEUNO6a'bͪ('OBP( BP(}B Sdv44+Rzf I&3Ma*+)+-Et\I ~xJ �OgG{HUU5Q4"lݺP(LYy9w41֭]KEy%nj& t:v&hby'KՖ ۳P^TNOŠPݏs×P( BP( ;"['<=_ݧ Q`}:d^O #*r6EBH$!2ޛ.Ja )ˢ;!Ԉasg=H!p@0H%9а D `]mcʔi,_&N;҉  F(4}:=SݛN k{M'iJҨP( BP( BPdY3+!< ŋNqdEB9!yYNW)rl`;.XC2Ķ,\AkhFWWX{b|XͶ-TUאJ&ƢIؽ�Sƶ8jlѣFcioj "Ru=bp"BP( BP(5dkP>׳A1-*<xs RX9cBJԑh$R)@R]U ,JYDc1ZZػwe1nxb(v3tUU5oOkCw׳njٳw|&{v`0:mD0MM3=I EʆgUyz* BP( BP(DN_#xzw"y==eV -j`)= gf)d*k%IƢ)@!atFӣȠC좾~] :dZ⩽ \&;-EMtХĥ${jjSeh Ni.ñ@h:?.L30Q9=BT( BP( Ba@f=- lv7a|$ F@cf;H{! U/D}EnmXF@E'h'lx4n" QVgٵjfG]S'Mbfwj CVG3B6S'@k*i8ch21lIEpJ@Kd :h~z =Ph*BP( BP( B1�3$ibhj\+ N.\HE1hR8c$''h^{PIZ-FvFsQhB#�:hzH32!h“Y:eos8Cj^bAn" V1-1̻qԉOBu$5l߻UQem;8A Td<-FO P{A\= BP( BP|ȭWqse$InFV\dM|>??pv/}Am,-;~nNL) WǵVJ))Wp C$crpѧȪmLv,[c~$² u8z)m%Hl쮦$3Iaڃ.Cpٖ( T 1j --:ȴIT̥v!T( BP( BP(z(&J4)%V*c;)quhvHR}>Y?dJBOx}nKGYIC5!(++7iܻ[@/iM?2�PhmmE:._D M!t::YJw]l1r 2v2 +Ai cLhZ^x{#HK,PC(=ŠkEP( BP( \;mٸn{Hum!$J?ݱg;kxolz}P ^)\pS2nh;h[a/ɨŎ(,De+2j c Mc/8=نՙ`n5`G JH,¦F2։f8iӵ1ulN%T2W<= BP( BP( 2#Dvݑ.lƶLqө4&$B$┗@+H6RxM T7L BOz�k: }hNpvSS=&HҩM[It'Y=RVZGu`"CJLQtXqcGT^E@5a`4f:"qƢud'R;&+ұ&J(2:$KQBP( BP( B!n٤)|>pDH7Xu &&+@ eĢ1~?~o΢dN9{A;XZKHr\tO'O؊pD"Qt] X;.\RVN` `_`ܰRXe>`%>s"( R*m ==1*쨃 T*I,%0t[$cV Mc&B])dtona{~v-;pUHP( BP( ŇT2&\1$.lƱ]\G.z&dܶ,i2%"S׈D#膁ih>'D=ۧ3<=oRox$eC5MG7 lۦDzI&$ bI8TFM0֮]Cs.hmmH4NcfRRYq~f L@{[fc:@  1dpt#oBbYx D2J2$q}g :Ƃ::T;38p]%AӾ&짱I*纑؉gO# {!UqZh?Ha`[bl\8XI ׿:U( BP( Ňic$q]FH%8JYbY8WJH˲>7])E,_h2^/^Uc&iwdEo 'F6(H0aQ3>3=QA( �YQATX\rZ6ݝ:MU ,Iyr?9=}oսzzoF6#ώNfϛG{W8 tv#E4βK t! R*a~siiih׭c|lZxuL6 ̔!8J˲@:5]k?{mmm|䜳hi) xErW�/=E,]F{ Z}zE5E׋O9ِUGM&EXёsƐzÉ1 /_7KYC@GԫU|%><p {Wq<%|܉ڧdӻގ 5HMi'/)pS}bi~w&Վ]OQ9䲏cA,bX,)!&2"ABuA9!%$FXc, hCZ ӲbHl_|:A3S[no>7yE(j mBJ8̝7UWat-,\?kgӧc{CKضccc(dJw'}L6 c�>( C<ATQBB!~�Gv:;ꔓֳp|{s˞TO;yY{\ߟᐓNᓟsϿqɇ8z%|PE'2塥oè%S(e+[^}$3R0p7_^,̀x{++ Pa>y|#Y˸¦ȹ_}+}n?{w}G< #?xiHgi-p4Cҙ}2VZ'5Aj)tex0tw%慄ޑ~a62OYS~*`)Z dll)tLo## 7oneڙޖu!s"s H8}1j;H>57ȱ3Eyh(03ͮ#qö}X,bX,ۅh8J'BTT='H٬iySݜ%,P A@ZƲm,ƒ K�)bXX}77%m l)QB"E#R)x 1144]Sh1dX~`Ù>`˚Ukp~0HV& 88I MQZ "j*z0hBKkM&Wo7ė|;A4_~CkֲxB?Xn.ϒ%u3<)fS~)?i >f4ɌOI•5>kyk_Ek'.b�#A m~|y{mo}nj؋Oo8f䱼16?x#?}cGlg,CW7fXd;:A?V--za>D 7sgbnJ>s| ~?NDD~y\|g_[>s<qٹ\!6OV˾-Q˩' c)e|ԗ/smʛŚ(AMv1e ?%o]<1 ۾g~]& ilMCg֬期};5'_9<uױyѹWLoF�� �IDATe; =~q5cX,bX, m a"E:�4DAc!B" Z4g kf@ ̨-4QE H!B -%f Բ&jNf$Mdb&J|;d7S,XGfhQ ,E5F}sS0F344HD^bRqj:vM[a`lB.EZ B<GI?2::L*"͒HkU2,nmWG0Q3="aa($ wE4g,w�Ot5,Yw&&c?zx̑ #}?͎'͠)i�?~n51|M,s Ir4\ at'sgB12atR:kݥN>o$< ֎B"^p{+ܥ+dVLP6@JZRQGO(Hw1I2XzN|k|BBTcTƊ!ZXZ:Zxzn<*:!8gbi#EQҏ})j#5FH-I;#mZ;kb7~\'V)ncK略|4fE!-/gudc p\?]nCc0J*):84n+`F:Nom`|C%B&ɷɹ>Ӄp%m`tH19{uÉ(E_mЏbX,bf ( R P(%0Va"(hvm@%JD RZP;feض=1^73GXRb�eږJ5[1Ggʉ' $$(eqXlݲD2 BbY614W\.Q*R0u (PZy:*2/yƀ6dj"F5~>ZPaF4ZGSRsg-[�((�g|]Eo*ю*ŒВ=lK;Я'DIfO?.L7\ kwp9%l\llbh0"u(Xs9k?--wrEWwq2٫dq~ٖ8<sf;g?xߧOWqMDο`.ϫX@w=//|-co~D|^36'L@#\q~=Ws6mOf,w;i5G?|+]6{ ~|PObnu*K?Klk xǿj!yq{)\|[/^wZܷXQΌTksM!`Grq%n}MsEd:IutN*Eyt+N^rK6@|(Vp C:h^'dl]ⲫ vs=YVRX;ޮuqdOEtqM8bCvX,bX,핊B,F+E!@0xTFfHc !F0h0)@NWJ,Ėͻ8K h * 1D9\�(A6*RXpkc67gG|j"`+m\7A" 9FѨ)I4ziӱd0JjN/V^-@φq\R2 ץ n¬Y3h9(°AH4(#ERF)v@`;.RezHmP!&g~ꑰQpPb^FX֎Aʨo>__¯V+S)=j9u eC+Y6d3o̷.ngq],+.uӸIp7gVL;t@X<gfO+?piod~M^:5}J32bRe4y@]??2⬷ k"~5kO9sN}/\7G3P`n@Hr])TY8We>휼q%|6j Kn7ܶ)mbxk=,yA ֊/8~]ZRNe=˗F2y QUr{_%;m-;Tѷ0_Wne+S0xfv<lcVi{ryw/羖8G3?obX,bXq1:D 8Kf̈́3C,aaf"{s"` 4g&"4FʉĘfPDb"SL,d6(kK""eXB餚Wci6ѮbwEd4CaD2apF#l"cS+r"CVsS(v4ϻdkxaU7wR>mZ!(d,[ GIT&GG"B40[ZTԱuDnP! 0{LP)H֨($v<酌~f"BR3=jQHiDdJ_m@6`YAl:wsY<Χ<sQ-o+f OG\_bQ5P(Ūa?egauw1x%#}N[)Ϡs9 y?ᔝ"H])O1߮%ױwo}ШnD{7o+[pZCX^矷Jľu~ػ8Yj&_[.q?u%:Sc%_5kH}hFHO|L@%k+(OWMɽn⚟19_-nnR1"^|m؆﹖е$>Ws۷ﶙGd i#,%l&Mvfы~ÆMGiDZ~KpngfZqc]/*wnΈpD6G+XWs̼?a,bX,a,hLӡѺH9  @F$@t@ec,ќua&1Ѐ0e! Ah0VsҞ؇hv!QWvkb`T|lJL$^F)L6;X8qN" }$J@QOT(XE2cYjXFaNeNRr ǶPZ`;DͶ͇4c4 0F#D{^h&w_n/ �k׮c�ض_Ƿ3pnj8 /{L |c?ޟӿr6G>u(ᔗg@/ o)(mv)vG7O<ɵ9G=ABk{9iԨ9$NMРl#U$eHF=Vpw5#thÒ7|E@ZF{GXܖEsW}.G^2域B-%i= KNǻ~< 8O l}Lz'J*s>G΢ ;Bh�9Xݘ\J6vWa0Ò;>2MO?CFvV3m�e/ <(nʏ<wÎglI<Ofɂ̣_C If x\qc/A _!s}Ţ»n'Un^z{z}bX,bXl% %�pFI34:D8PXY0! ``'iI}bsV-1X6 t�b2)0J5F!AG>&j*YΎײ e5bXC1$2Dk#tͶзi\.ϖ1ٶu+^IHۦNjr4߬i ʂiIFG 7@PmjT:͒ZCA#X>- FFI$HFHIiwvy9|l:۷w?~6eXj3= j3n^Nwܒ縷:3q GxH#N;װ;V*>]aW^u5wqS#6?jMZHC"cA;=fG]F3 c9v{}rI "}$[`Q7HhHXl+$:Quz뤦vRpyaF' fͽE^Fk+n#J(/K]S]ހH_nzN|s3rBaj{qJw_ß0o{Fn8{ AJh'IXPBkA1o=s7~@O# O# XSQa4m:GqD>@; M籨Vn/5:`!52s ф4<XiC/-HG?2ߺ'71NRhY:4( MP<LX~ŷӜѿcccc;:97Z޾pCӴq'j8IR,F6sfabX,bXlȨ9y5 )E3Є$j6, X5fOL1ƀ1F͠oNA&KL֌ nsf#|ҮumNaYr*iHBH KK&~&VhDZ*zHZ^ 7\fxx~4LѴ H$\Dl RP.(Zɹ j~HyXb>DJ(tBHs)4TmI ĘfY{']s|lo_];μysT<'?fhO{C|)1~|l �z'rۭ I2{:r>۩I;91蟆;RKn㱊]> Zn�;㜙s97.-;+mxޑ73?{Wa3|s]mcgڍ2#e4ALII]aQq|c_ґ}3m;y)qz7*~4rSnc}o6cHl^ (mth1n)N<UK?va3ؗs'+Y<:zo?+ 4:J_Ac"PO})o9|3Wl)Enoyc#v1ngCf|$7FYVvγ k GlY?D)zj Ewqŏ;}:7+ R4KNy+ȭgv;?yu~Pzh C2e{7e28d\ ֯pÔlbX,bXY4g:ږ@i !mCĨ.Q)G@Z6-L!p H²&o7Ē*;E\(%|ZؼyQaFdJ00ݟl*3a'"-fFmXRbYV3KR :!KGT|e QN8BTc2@aZ6ÃF)=w.z0D*$Z$G!-)=t<< W=  I(u>\+@kalD>JgW7APGH )$Z)|&>]y_oD3/?kه?ez+?IvooVZ͇>򱧱I/BdN}ՇiWomBB8$'g[ \twV[ǝw7z>/;=AԌWt6,p5~y3x6k{9Z^WUIi'I&$n҂`#:^Ϋ2+K-Oox)h oA_.׿|u-88C.-޿N[.{9+I{y`Pr6FAgt>}IddH<ݷI?Xf�z\u<lwkz-ok9o񪂠ַ_'MeOg]k~p8|F7,e_Nc~#W= x嗿vHqeELd'ѣ? 빯ݎ)ysV6ldrS^-)<0]?Y0G]X,bX,V!hAGDa4-R /Ѿ-$tc$TH.aˆ-I&R" C8N۲Q6A`L4%L0慨(@1`q6CE7@Fuj {78԰}A>aa;.B&A,AgAZj삊I:Nd*C ШpPR:>HRH5j^ ahxDJQ,jE)`$ 50<[ a`N%/)z^tR!$ڀnX Rή)_?LI։m'2w'O]?߰ wZ ! gu|᥃|[}gz Du<˹_X,bX,{6!u0X:lQ  vdB4KJva7Y@X6F8N4 A!-TNټa5[GȻHHdޑ$p5<e$6YWw#-  o^Ngit:nGJDZ";PA(^R?~ R)J<qRnNR FǐRL&Jy# )[NB> `=BU,;yKG}BF_淬 Üٳ8imk%#$B2]8>SX&ŞNaƞgz%d)[9bX,b b.F5A-PJQjHɻ(!H#P&5 eHI,ZkЧ\)7י6[ 5lXK%$Bɹ$kThp WPSez /p3#jՀTƜ̜N%MF6E#lZ* R3wvQVTAHN"BK+CC2ANUE4W!( E&40PҢlma>oTYw c>V'03, EəCN|+4u;|Y'-`]Wx Ş]vx_o53︞{%h^bX,bسN5jf DѨ!- ۶)q+fRRI,)w>n"`eI0dCͪ2<44J)ΛǒB#aF"'%<ڋo  K؈ԡIǨtbi)Ʋ$T́Nnɴ8) aK0:F F!,l!G\"L\8Ӧ)>TeJg;ZBZ-+t 9w1/~ً9pwp?nv!-(ilʷ?HB6[O\ гi H9Xv3)[(bX,bX,wlmje,*T*5Z[[Fpm4<u?4ۏֶV<6Peڇ0B͂) �,<ϧJѻyaP6�� �IDATAEcP*4$J [`CK82Y"5ZԃQH b)/hFG%ۊ_paw@m= rIt'3 np'|4>t2DˮS@EkY:/sk_KR1! Դ9pQ5 Tă˗ss`JtovgXbX,bX,oNJIOO[6o^N(1FLfՅk;#�eR R'Qט=g.cER### $t|IJHdrygiUF˘THIQI[D! RnZ3l2ņ4b�F$ض^ |T%N5tet!|z"WZu/S[SXnIRK>fewObӣor?O2\)y>]]X�1BdN SZ7 Y13܋Ht5 h.:RcDaH5Fkh"/굸 ǯLX,bX,bXlt*MZekObEK(<fQ&Icppa"0F!Ҷzzgvq tДXRöJC(J^@>PH;TxCv IGjA:Z7-B5<КL6Hf86%a ]i6ŲJ߫q {Vo \\7`K M122J&e欙l\=LÌ+TZA8P&|Vx3gQ$2\6<j)ӱy? 2hXr%/Clb(+X,bX,ue9zV{73m�x?FS0M*i1T5)*:=jʂvrȒlyҬ\[b|)kIK: !]3%ku aŬ$ktwڄaD2)6>ZzC*uPF[0V$H-զT؂im)#@&!EkƬnu7ӍhOlGhDufzx%3Efv&8Edr4oJ' JGGزboysJa'i8]gq�0`dP%\,3=cX,bX,b ]¶"?`NT2AZ#hP+0y`jlRjs]ԇMj.] *i" `krI+ˆE>!hx\M ՚fdD1EШEH !Tے4< &A BC%RR|BfJk\ (jZTS]c"Q_׬"q#(-YW(>Hi!.0}TzQe&R/3;N[@q{o⹇=E Cv.j[$><̺aCke1zbX,bX,b""6=^1<Z "@?R(P6 W F MPW}%AvmɊ?H!"m([mNOVPn(;DAc4hgͼb]3ZtwHl  m #eR'i/8tm YB+tYIR @Z6vOQ%LR(T4P\W\I-NI#F}J!CcבMx`1u i]('IBk%aO#6[Ay Lc_1#yU2ڷRo/d7x!X,bX,bƜ-CjOGX[ضf<m1":Plլk"14v d3Tu6{ i%P )BF3:kh脰h_WhT#$^"fmR˔nf2wqe4T;Ar c$DM.#rix jQ"zFjh5Gg),#f=:ے) o#(c,B 0NP˄ae:wJm|üdήɴٮ,tOC*~mBFq+/g,bX,bgi!l۶=w3ÑG?m[K/kxl҃i8%1AKH,)E2Ep 1Oh0m]Gӕո‰IgtS<*p@G{ fVj7td5Rh8VndL&C:u]lfz6-t"e' I MJЙigQEXMsF)VIIDLѱ1jHշX)q$LfϤo[/ӲefwZ<g2*#tϜAZ"BH[6C2^\־15B[hf$ amҷi{ʎCY}=cX,b<|0T̜9u6[g}|=^ƛݠѱu7bRbbsFRi͛_B8NP`2B)@B )l KqR) \6 ,XEZetl kPUj)4\֖l#, s3f"mKE#`u2z0X8 y T:]lrl,(Z6JSaSoGgCo &DZ2H1FS *)͛dPӭet#kGY|/ƲVX7oĖzs>c&DbZQf qMX,3ضmn_K4|,\jCO{{{:?>~n㮧� o4r m8�/}ɉ\?/o TgG'>auwv?}w/D9CO{;T( W[Ş>]]|%?QGuO8y,u臹wo{-ӧM,X�<׳/=,Yd]] rIxmwwudbn'~'OSK+ 8CT2B52H dL:C&%JKk+| LT2q-0lfyO(,&ΐJ&D+Ea"vaz,DQf-^='l7]aPJa‘6FM8$Ғ-H;0\ -8&`ܠw[%-C$:$#@ql(+$h d-. 3_B䕐Jchl5v.4H!Sr1G5ضJ*}[6Fq|3g2e4,.Zp'?~Ha;ֿϳ?f'bo�z޹4:֚ ,gֽJ7o |=0tÍOX^wک̜9W%uϽ{}W;B>E7o:t:@͝xqqs|۱y9y`}_;+.<d̙c_ŋظi=0<H!ظi}s=;{󎳢:w-{R],}ei"("`hP Ph,7$Ē|kb UT,(",ܽuf~̽ýw {gΜsfNyرcگU 7v,KKOW ++C0++ ׃\<w6;w•7/iSpyk͚Þ{;fY;=j=SU]C0rk>zԈu0Idzs׮66 %%1̙ӹGUW>e|UV֡{l>2*WR"nPP8zp%k^t\sΙyg}GdSU]mcE]]4<^Y/qe!-Q1|x6Ѓ+Iv%Ԃ|~?Kr!Xۋ\[}I[G~}3j $7gVVGW*xB>غaÊ9rum)\6R6m~j3!==n 6on7;~zk~tٳ8<L:!s.guXv)ӦNC$&&p ׳afMm߿oL87Z/|ܿb;w{n=(ۇǶ9F,ٳxc,Zt>d>dv;Ǝ!##>ϛa(i4ݸݍ�)i)d̡OQ_ !+'ܼ\cA <~ӧ^duJzz:NY0t$YDesDEnw"99t\.TzHjArVc+{ 'j CCQTyI>9PvՆ!E rNTՆ$@VEZRq6�5 eUxxO[8LEe-_UosN@&ck$-5I)t Mcs&=0-FS'ttO=t'.W*;JN!SWW/>YV cS(B}}կ}z'η9ILH 1!Xq=H={(ݳjcɢܼ?r?N.I�xg󻭦7%aQ_ϻĺn .WNj̟w ſ2Cq�T[+m.,,l3 #䒋$-tLprқ$iN`H@,\ɸc3z$I4a lcS p8qVxN2)Eto^iS[gSd!Ik^۪@aA>6HzZ6ƐA9؎69g$Ze(,,gLm|EQoTpQ�ܙYYGGzsp䉌9'i.3~Ӿe0glr7�7cZPΝ;˯2th1}1K-JuOfffT+ %uG<Ÿcp2l}}ٳ. ?ݺlElY`q[z.!iZ;8[T[ukb]z1/8~Nf^zedfRg/.#VqNv6Ӛ‚|>Mr%Ȋ{O>eT@2JDk=M=w II|6�``b[IsLybzi ی?q7̒xk;f �;v|Aq\ d%yOQXOAA׼͂ks/JƍmwA>\swݽEݳ+HOK#--^~3f/�\s?!q z<ed$I;dl9Ngsf%3I%==˭KoOZ3b>è{ӒHĒ VVQ#Gw9c:SLFLp?e$ҷO_oSᥗ_p8$'caA>:eXۢ 4I>l(`ν,\$dvUKƍr}- ]jP:URRy㩧~/\vS^^Nq ϟ\T\s'mj|\I8N?Naa!\oCڢ{#�&E+)4[DIv74s�fjahhJ( 66YQA` ( uȾT$tu~É7@Py+kIŤ8Pl* "2(#"�,! " n D@DeS-ǪhrVWqQku Av ȑj/v N8~ 'ۓD,KΑ/`׫{|TAԈ is1\I)!GA-6*OTQq]^)H<ޅyB=#Ԑ喓8qӛG(č7\d,vSbZM /[}d-,gQSNy+- X_>$SRb~v\ݏ1lPRSRsӒ 87Z ]r{>p⫰ [nUU,,(KffQ~4L̉`aa!C?~Ŧcg`mHe̞=u6oX<ÿXEbb"@3b0fΜΘѣtgajR&'Msbz?fϞ墰J,.d5g#IBD=ws&OOEzi ”_yL0]SXXPK.!;~IX233INva٢ӦMeb֮[Oݘ;".=f\x,DQDdQٱc' /7m650̺|]wX"�]׭喥7l.tDEn7BQoC GaA> o\w6r% ԆUUeQtԉ|'YWG v/\`=,t钉ʨ}{` dI/999HĜfG.]2> cZ*<Sۋٳg!K2?5\IXyޭoInӢ1p]pM3?Ν:aۣ„M/޽O h 9ry|ix[cŲ{ٰq)2iTTV2g,{#+˪gw6dIf9#G0nX~+b ڵ+>9,q))QiXﯰ #xpJK;PEwf%fٜ;rrr5rƎwBR Է 8że ϜA.]�\8|S)+!"iihY߬YpםwD9]_;XۜIzzUW^qu>\]$ܦ#K2$qW1~8RSR2x0̾pyy3΄%z .,R플ˈQU5Փq!쨑#E‚zdeE'K2#ghq1vݪ#G2h@Xt V]OHpv9aÆ"IufY+.ͷVG&ϛFNN餥u(䨹]waΉiK((̺#+ ]=zÆv /\6t( NdI<\am^z2a| z$/{?B�̀-`ocF];f4$%\;Z yuOeTVU@Uu57-YlCTknr%SΙ̾)*ˀ ÇGchq1ǎ>X^yݛÇ#+ UU1|8>>E>s{0In3s3IKK?qcǐx˒lnkߗMC$H^ꨭ"2MfLHp`;p8lvl6bTT�r {xJspp8zAd@9x]HJ.bG7` E3Wj:vg݁ÑfC(*ID C0 j>AMH& LJCBT23p8~ IC RShjj"1!QPI  64 ɁHEIFo%*�� �IDAT4XWIJZ.!TUägtf]T3%,aS6:N�^?v~8qNU+;$^;7>a}in}GMD/*@y(KoGⅿΝXu[}D۷–�M(+;}ӧ1h@Z?y(S|du▥?W_gg޻[wkhFP Ep}k̟)�{K`PZ&<)\f-{a |~?.xeMϞ=9<SO7{G$'RSSsϱ7:ݑ|huh-p>eWqn%%% '//7fivuV{׷jy[Fbj:nێn&L(A$}t$HJK3j5kyBQyq4sum}n^z,^t)E5n^z%r܋b^Obq~N J楷p8{x7pқnȼ~7-YdEM=wJTy+;ߵ[n+Æv슊&?UV\]w/P|=#ܼ6\$KS7,_?fCseX�?"*&ym<#Q�Ӛc[sSe+'{;99$Zozp4p`1k}yjr)-C^^ՇMNu�{x$--Ceiok>#Yf)YoϩcΝw&r<7c{>zCbB"* .W_yy8¬^޽ [}leݺ #Y8"=Z9czT?({ |>DQF%DY%#I"6UE$SR%.2BH*h> o-6!TwUej3hBUmjJ :BT*"Z2qfdaOJ{gdpbs~Cm(ڪa4: "T"tCClDwW⮫djjy=~G x=(@ѕ,K $ΩƢΤʿE� 4M8¡J Azz'j<Pwl.|m+EU\<^y 6>=G? Ώ҂%ݺ_pKc"п_Qj?7-Y`6 ֬lNXgQt5ꚪ -"HtC+/C$2a|i-ZEE}ӻwaeI~HdM-MSC rZ<ffZ:a `VΝMNv6#0fh,0a- UU|ƄD'_wABQ;3 Y魦ht'MZmӧMOJJ2=#eIn1r|me CUY,ղkMn.8Fa#ի~lH8]vᒋ/򝗗K]]-\u(ˆm 0$q%sCu)5U+n\$DIp:rΤ:X~ nh3EE}3zdV3f>:WXυfZ=Y~=^R-")>嗝Ԧ0Ac.+.$I>&Ol oE B-J1%dWFP Y.f<~ ގ~eNaIXjkk-%%clޥVnZIINn1[�mt\Ef橏aۭӭkWˢ&YIX:ԩSҿ_nKرs'�g޽,^ ),W_Yur3B`Wo^ݦ3T1DyG0}ۜtS�cd^;Ҧ:w|>Fdƍ$Iֳ&$8 Y h3yyJ,}l,zIQQ_RSS;%zW^~;ɹNf}1%nP?[iS1Pu`0# �jCCUYQYdYQ$E*(xhP#?7` "'Qd&]bo%M9T;`>(;ܼ2u#%=3#{bv,!'La[K# }:^M '<6t /"""΄dYk.A~$YJr ]ȸTxP.ldI{h(肝&$6l4D{2MΉc0 /@V1lHI}z-ԩ?A Ez>WԗʊV.gx뢪*E}cOv -~B!MpۛGMh˜gڜȦ2}Z ӞLMɸ1-LwOSo꤉<iuNíZYjqo(T{\g ;EH{=sv}$kl=$//׊/=='_~*ϋ&_Q_O|cǍn1vRL?^gy1?ݼ`JQ S'L(ZnZ.1M"c/#,0w6ons\=oTZ<\/c„~{W]q>jz'7-N%J&MǪӷOoN1G?cE}e-gOcB.]ؾ}{>jpVy'73a| }16 n^ ymj M::6SX` v Hd9jk9|p\욫ufN?ϊ{ݺH#Gq&/YǪIIvRDQd̘QmvK0V.GD;?͊?-^^Т9w%TtAuo&g8g?H&r1jpzɘ1HJHgN6+;e+'UWo- h/ mGg}m}9Λ6Qr � J,]QDAD j蚁$+( E!+&,Ȳ,KH@]qH5{hA;HYHYc"ɡ^ܩ}Cvv]<WvgvfC;Ql $%a{ y]D!dot/Fp$UGph$5$ *M^\R#vp $ 4XOۈ5QC�mGi,SZ2y"jQRpȂH T$D /u:zi WA}F4R2\i OM u|H S ٰN$@eun.H؜gHhՖpsh.䤫48e ߰]2n,[>y^L}]k֮kwm|'ep85r8κFw#>| ^;ck||fq?DSMN׬2ޥߑ7~guo)،dܸM.Jƍ+.GErE!s&q8̝seb>z)Is楗_実q3~GM"ϷCN9w߳U0BDn(6tha 1]&&$xpmhCd 2x,bm;~{^>٧~ט?Ҩ ""%%4W^qu h9 4WR6sη޻s&33?q&mYtsb%O#ߍ'Ohaްˮ\ɸ?~LdYo>?~#9ihhlew?2330?|d2rWXP@V676p@5Ԯ䤫% :=x(aw&q'$!`2c$K(,(4MAa EI4}f "�` 2ހ�@t6GNEJJJtꦒݓTHHLġi2/J2"l$ Ȃd}ch(4YEPTl_n x4 $ h26T̓,k|nx@[(?|e @DæJr AC�] R7D1Rt`5iA-ąq>R'?Ǫi-͆&sgkyT f%4QouOͣhqZ#_ g]=o8Bp&ewqw1ޥ GlY.+ĄD`{?[xƉ{a}G1;apn+_γ>ž9W6YsOogˑ%[z;˗~b ‚ʇW;g6#F ;j5\X _ğvu=\Nϻ^2j䈨3O.**BQOqc3)>L^nn�BiVˤ6l^֭lƢ#3,,,(8B8qN~7On2�zn;wc%bSm:+GZ+r'?f _߮Q!}>6'=c˨Ў<AL"w,0®Ⱦ*m{?n3%IY1l `  膎,,_�$ڣ 4tvx&BBf*ݻtKndfv&1)4lv)TUTDIB)85DIQe EVy@<y4Bϓ iEQ'x$ /'gx%ECt|~^݃ c$xBt:*UHbA{b2zO=>DjMkJ %rҔT$@ 1 f'(q.<wP G?:`anBi&}/`U9]1oȶwy\Ѓ,qM_Vcz3wdmui97zUh=Jn"JlὯO$"% _SEa  Z[Ww5gUK}TU;?M ?j0#M>^Ķm0w֍!ӳLJƍ2%}yոRVVFzzGbܸ1֮ʀ_YYGWجeP_׬4N8n3-]׹ګQUÇ}m R܎;`̛wILSDQxv5FyZqNldI&7 9ct0d u놪0ͷV3).,_xw葕śo[Fod„ [u t9wpX{N}|V{|-Q#GaGs8($$8n5ug?yӦc92lx{8?n<"^]H.]?RΙ< M8x齐VSs;[l-[xMl<̐:l.'Odl!;HOԌlUsFΛ6YM2M%4S$dIFkw0EQ@ED{)IQH@סϾ=9)/}+̮IMK'!93՞ls )6m A#+.$Z;:wS2ȚY.p~DQ@4 =mlDV4iv/ $'t*DÑz*juΡDIBk9]JPp{5O0L[D*123B^QT4-N81ђZ}e})>F[p^k(=g`=eJs9`wP c8˖c+)YAQ T`|Ak~T$zw`gHpm27 `n*n(J.C^.,>x2WeL6Gd%A0va}-]-PC�; 3Բظi3^D?BC}=ݺwcȓE,n~qFn}$E i.IRWXbƌiƉ'66hnܜ' ё9 @Z<yĨ3fLgwo�m6L ̻b8;G18khhGe*;H0ha'Ι=+_͝3nmlZXPW�ɧۣ7@mkԹs.bV B\̝sI.{2?#MTk1y3su!5aػU c)(.W[)!I "c#l.c` "b( +ut@5t]G7 DN\a'99+Á@QmH#d/"%40S}l&eⲀ.bC"*`CEMߋ39P-~t-^F�j2lPTdA hf낮 EFA#ix +6SQUt| �~/xqgvۡɽ`eC{U9a]g~EX^�tMݐDQ7w{w !I瞼 m:\a .{;!hV#ƏI6OafwИ}oo_#v�K >`Jks;oaFG#>8 HJLk.Vɓ&$I춥-|E^0m-ĉ'&�crPio\Hpݏ:8q)&O4meEbBÆ3mTk!IԂx8޽8|0`ǎ3 8q}$/p$aC[nؑ:~$,N9s&Mb'iP__O  m|&ʟMAc�}L` >-B?59A[Ȳ) !aABBCM*  !Fw lvTjs 2"IhKT 6Cf'vv@Ub C- +FCDMpD2m>@GlvzIAFW6A A;) *PUDD<^un;z.4=$J^${ulv7@gk D:e84d0_* cNJ;N#$%B#e*:$BIb`h}׎8Jcg)<w['Gkכf<S|Y0aAk0!'N8q?d}b&R7J M6a2a˲|8NH9fZO  <_RA3ub2Ft\ [04|<<@ zʒ( ALAho`daCf;($+bnJ$ !%~Ҏ2|KBF'z$+6A=@ !IA|."4s@^t`0iȲJECcEiį*>tMLJ**˅aQ@L!j0c:6M10dAj4Gn]8qN A044tQBN6@C5޼+xۨhG#Ov4Q'BmyjOՠTK;#h8qĉq( 8qyW! mPU]R& �� �IDATr Λvn>OeRvU�U5�g@3}$_Gkh@mI,`y]g>ů, (nH0�0$B~2EK( *#J2"2h EE4o]�AgkӢZ-ScUd%Yް +QS$#CӃȆDكfEEVqm>o`' ^/-G3F7) j~;l *(zQdƆ:FCb_.E7Ϙo:H=Il`04 I G=Lvo#>?d>;q%ZOpCx{PQ.dNNn$uV`LlS=\&pfgZiwd(U'~d^VWd3O:A{r ޯתܑw�\tDm;%%%Z&OBEe]veL ~#=*j:rT #_ĉ'Nd~QmM72)Sgaт_+8q.{]犕b<wc1(BUM5 (LyS#+zFiM dfvnsmym>lXy>;rVYQ!Ml)++k;ʐ4,F /Z>Ю<!,lsp=m7`J8% `A4F0$C0tsw QBff QABTT$IFA!SȮh !i<WgoR5BH!Af@�ABP x"M>=  >]A"i% vPuO#0F00t>/cHK ڵ$ FEP 4y<޵DϷ,ĥq:#QP؉O˱Mbusp )y.d߳╽hhRE8ק(Qхs�<zH A2pkp ó荅=t2}5 a!1*9!JP37#SN TDb=嫯Χ?k{?jmnj/K~~>a<:"[;?ߓٹ3춘W䯟%Z̟ܴdQ̸0ʼnq!{DכoQR2UM8oLz. cG/�<ܺ6)Ιaw6Eq8 4Ml7hhld3cƳ_pםw=O[Zuq|]ǟ/V6s-^�jnops[�?:Gy=<#OpB_yGdzK4q1"lڼ|spfH�7L|=y᧮ڋ`SQ$>> AC L:eQ�YF@Bhw!iqN`$QoOm)lpF > Q@ $AF+tA8('EPE?MG4* :MA@DDz J no$$ 5<M~: `�>l AP閕CckrӹS'qNj5ĉ5ݯH|-׏!`/Mټ ?5e⋦}j]TCGG\UtwLk3vRo'nSAkOhinPVVƳϽ}+Xs p \D+xx'(++ MӸwي{>ݾ |=`8q(jq~k䯟f;n#ο+|9x淿k5̗_Ç[Zぇb/Y0\v:˖'hdƍk[�3a[�bf:q;[76CGY#Aq+# -##Ç^uZsXqlzg3w< y{-|1x{)yRWͮ4'Oz0vxdw&%Yas\/=95B̾I@Qņ$ښ( *$#J 9, 47,"$B(-M"G6?ך�0]6E A# Q$ QEHR 6 E $rīh8dmë+a4AM74JK9.jRn9ZmpH=u >Dxʪ^>F#+6<n=:z4ݲޣ;QTGk_qqt*3P/dܛϡQ+/Me 5z1Ў=qj^D<A>{~4RQ(5+Ee߈_~U|K5QȰ.0H}ݣwݳ#F0낙4H2hU+%N8gX G>jWNXg}}\}podv }{,*8)�fityyk6.C‚EuFg,Oˬ; aF<&Ku۶x"MZunˣ%ϧ۷S_Ю],k_9p&_|i'ΙA"?Nʫ>BVnȲBޅ?~4L`uQDž.<CVn-yaϳHlfv 3% ;RR"Aw[)qƐ$S1,E0LmscR}417F` 17*Ű2$0wC  TM[nxd% n(ޓS2(Dm bn "$7Q"6w:n qEdEF,Fx~ /Qv^ Q=٫!J2UQHr%ڴz ]CR28v l]>=tS ]Osݼv^l+0F9o<r'oWSbæQq{Qg|'�( zذi#go FD 6Rv�7-n>N3wE`/Cm?^5*]5!7C6m6oC\.>s|i\9M-5 ǫxm3Â3ѣcYej=~p[Ucjt6-�O>txifƏg "it9|\`h3p` E_`w # =w?K-$##{_gnI_<\7^:V>�Ҭkeݯ_>ojf ;iٮbYE�wݻUE}W_Ш;}͛)ӧպ%/*o0ǟ|Bmm]nN}CCuW]m -ؿYCف2+pXv9vѺ<a:mgl DdmtliD$Dae[;6& Qi7σwWHP*a` 5� N!%z (>l.Q5 ,b` $肀ap:$&&r:ePKRSSo�(2$"~dI•2YH6Ű,+~ďyc}m^?ОSVL=<,;(?}7=ޛ"EDElW]g! PQP+H MP@BB ^wg?dw-3gNs;Z}u,LHl\˙ >dڌ^Ӝr !18q% ٳ%K|y,Ι;;gXY<|_*Ϝ5cٹ >xK:ZcrJ}}dŊbJÖ-[lם^ޖlKJXtoMcBd7oMs/,+xر$ռ,שEf߶tʾ}3q֮e_͘]rp~'�,\gg3if$:1i6+n$̝Y�Ĭ?wv;m?[<&QTTLu)VAm|g2g\ޚggϞ}ٲe~60H޾?j+Lee68 0UqI^5!-.`k߹]rUZb%c|Cj] lKJ%X׃3>֯[bw35\ts?O<_ v@$880@"/joɝՋř O'7eR*A퇤4P!BHp0!A zt:-:NZDV֨Q)TTP*<$o…hތʊJ (,'?7  s z[�k{z\q˗SQY9w6owޫٶNww9xCɻO1=>6oŒKb5z3VTVn϶_6Ȭ�m-25$%%n%V30͜5F͜5o1�fuľ5!f_<V0or%KH_Hf[o޲š͜5ΙĤ$6o{hCsA>={< HLJ哫zX[WW kl3o/Q?e}j|0bVFF&FcUYnuwcƍӪw?1)}aU9|9wnRXT~k¢"ny7i5!egdd:.LJrobRYNHLd-;v,rUPϡC:m?^oXۄ[ք8]tok8u˹su>=}�wk44sZjZ{m[ _d[Н+.)amCͼ֝Uok_ Z'u~đit7 l[ ]%Av2(Ъuz$ (pEEѴYQQ͉""MFдY$aM kҔаJ``bC$h:tz=Z /[^D4Bӣ yLp* %8)MEмEs(;ul7j&j|5k-l߾O3%-[ٿ�#Þ4{Sddd2-gf>dddf{g߾�ؾ}'Nh4o~ny>!!qwQ#gϞc}|$%o={qyzS_@bbnR#CQQ陙8pHzf&]tvHս`6kvk>~ljuγqoM3Ġ,bgPZR+ٳw_4[ٕU9z"[`YojVZMA~th߾gҥl7>}͛y.`%!q+V… pMFEwFEE=]~[kǯ$qBСTA`0u, VG@4$''~&&sA8z(-[p͛3ٳw99tmg|<sgҩSGޚ0r%!n%enO=}5d?Am]۶8hN>CbbCߊB 1XU˖]m |[4:ʞسw11qp3gͦ u5!qѭZ?.k [=Dӱqfڵmc˞L%!qSSٱs'CP(t瀀(n2n| P_@B6˲5bM+JQ_ {[#{a|zR 'OzkDҪe߰`)H$aޔ]=kFm5a"jږVHٽvmۢhdˮs-\ ltͳ ^*Η` -=h+en~p,O]9Rv]avJ!U+vl7mF f-7',,wa_Kr<zSx7 kٳwےb55ttނr9<quY߱k̹Y0=3eݹWmRƻ'Mzf&!5tkˣa&Fs.u;Jٳ,^!˗ǓR'RPP7g32Ypg}[ٷo >QYy9 }Vqdeeq9RLB6N>9$%og]nքrvfu LF:A}M_\ZzW7u]##84n/QwtӬLWjWh /js\-[� ZVEӡ?`ڿ)AAa0~jTJ*zJ(L"ETThݮ=?^FE֠hP "H D/;bSF3FOKCEey7ǍurFo�ny�f|1p 0@-lFs}+'MZzmv9ˀœ�C<[` 6 )Smb+ eMlL L|JCں_q`IHFkt yy9i锖,~999Fmnwip lqwo6n]R>~$Rvvk42Y8KJNm!~?x,RNFf&Iۉ<5a")ws)KٽLCNNm@z8wpۭ�={f=wVKJ>NXXVC,Y'O1b0DZY%%%FI9srT:JxxS;\%q)\$%FỸDDf<3pg_nb3PYUg,ZZO-^BŋįXɹse:[-/`Wn[;͛p,+fc_ے(w#kZCRQ($nfsc3�Rc37e*,]NXxxlr1b0ݻIKOw֏@}~Δ֭ռwݻiѼ93?TW꒳޳33ٖLQQ͍H޾ݦW^ï78YZz:\'KųͶ|7$&%S#`$]+e7nhD:spxW i}{\5 :^/[*W,l`9l߾6NlL ~?L*++7 }Hp?SF#%%V_r#ctҹFZTTd3>I~}mF9svoع ~X˻sv .ggJ }ou& 6&ݻ>b0QQ^AnnaaaucDzlgfT*X<ަ0GL~Y+سw(.*dŌ>̭!|TVV2wרj~yCޛ7;tY<]g8]Y$77NPKKJex9�� �IDATb+K6<re]E[˻HvӪ \}89k ؘ ;69hqhwEZz: ص+- 25>Ϝ5yy5F`ڰ78:/vg}WSFN{'c7V#~ (*yyFEg??JZ?M�:<C?�1 ѾCZ-BAxp¸Gtt4* ZJFӡRPh4Z1V!??^OIq1EtbJiYJGC:dR(.)!ndz=# m=}̜=5*h�ZFE1<^r)~딖Q#GOr<nOfxuMJ̝Ho~أԱ)_ mFq(5fjǤ ؙg*s7Va֭6wȓƌ}vxf牎W*k>Q9FcF$~Jۣ}`n:c+} ׆޽zp8-<G^\m_ˬ{n]Crn7v۠Auӧ~s8_ +UqԤ >ӧe(.)… 6eꇄ7 xqz=7kvmxǼ.vcy 0b!3g7={g>.@YY'1)ȤЕǾv9=ڶgus<_yu־3*<77ݺ۳ /[qm2R1uc0]Τ.\W=رkr۠Ar%ӧ~P뾗p۠A$&%VxgDފȈaع+ū�xjW_"##|+%o- g~8-oJ^xr*{3ƌP!5]))ZCdicʨlج&6cjOMw:ih9]v-;Ǜ ލ1g"gj]rJKKXYQ4!LEUQ^^Fo$(,V $"N;N֭ 0�J'I2QZXHAE)-)5ƦdFO+In;z 5^cǎ֩U\1cؙžZ/JC [F*;c/ɿg[-:UW$?2ռvcPe1̩Jθz rM7 &ଡ଼'yZ&drZƲÇiS?^Շ W4AR6n֎7^{)S=hԮmZַNYM} %//VBpڶm={v'p.4lFOV 0]=zb6|:쳒 POȻi9j3Z"&**0LL&D hB2E#ULFJ%͢"tJ- dހJs1AQDEJ (+)A+tl )########s9�W#O?7*2y̕lbwyNHvn&hbzf}[.a1z:[:]+Iv3=-=m50cT8koE³4m?jTQO ΢фh S@+222222222r�g[bZ&#SW6oMjׅEWE<d?*++M" 1ys*'`:.$'#7DFuNlUY}\;̀j)P$rCp~hdvP$ ; edddddddddddddddddN<Myu};h1bݹw^lDEhw'wvտ-arm)& 7ۿ}p{ClyY*g+jeddddddddddddddd[ر#:Rl<ع<c?+ RKŽF3'%@38g`)yfai}Wp5#>)vWÎ߳ݯ9q68eF@MR L_@BB-(\w>'&Q(6 璓Qp2j{:Qt6&sI@K$IB_HÌOt!I`Yn�^t[~[c+TEuNk|MէKC^Xh3*7(Iq⟜8yiiA=x]JKFr ݕ%SN e Z@vZĉSlMHp0x|؝%###############ӈ9|8ÇӼ;p[{zldUn^5ByyŕW‚|yOOFGfa<=YFFFFFFFFFFFFFzD>]FFQwsϿGpH%1X򪱤CC[22ȸGR%)+ kI'Jcɫƒn\Ȳ.#Y>7K6t6tFOHBcɫƒn\Ȳ.#Y>7K6t6tFO:HBcɫƒn\Ȳ.#Y>7K6t6t{z4Z.մ|A$L4j,鐹떌,22qsocIgcKlLb0^=)8>sՠ\eUcIՇ\dddYq,|K:Q:|2zq(5B)//QFFz]vd2! B FHpZg#$ITTTp1\$ QEIP*/MWh(!!JץZu9i,yX!s!-Yed#Gz)ƒƔFOAHIMVv6jՊ`BPT*medd|'3 Vo d2٦th:֫Jѣ(.)&22;bmT*/{M?mڴbGj4;\zK^5t\}uKF@uѸ^ʷ1ãѳ#GGRR_fl 22'(((,30A H!((VZyf6 #00ЭJ|rrs<xlNQ|񔮰&a]8ځCcɫk)Ev-xh.l:sV֋3jL㦡dY26j9ˑc;~-djϵ^R1-c6ʽL^rC@bvѓpA ++m?:f/]mKE%IT*ڷkGNnW}KQ*晕.E,]9r.dbwVb7f*k\јG\3Hپ}K> ]u;`sX"zu<j1(s`툳,K\z6k�=qʶ/kkk%Sku+Zi=dC(0?o$ OLVj|z(AZAr .=ەJgΜsh4Ӝ%U%E3gPT&ee\>cSO#IRrFk镱cKL= (tMZX2_zBy�TD˱<B1r%|TT2quaԭ#ڟ;-\%sX?Y592~/oN0 EwatY+T¶i2}"=L~n6ѱ kL'\Ԫ=,/zSf>ECmp'�Rڜ6o`]wskKߑ(W|+BӶ=iPڇg<G%ܼ3)COHTkC2Y[¦wggwvsw#)Μ%}9EAtnͣO7}P@M &LKCbh۹ޣ+QnPq9]5@)knh⇅4f.qQP`4Q*n͍u̫B`RCS()(*z$o<{3b2HZ_KicMZsXЄ !9ݿ -\O?QUUœO>KHg+Ϳ!a}R T$[Jԩ̥ <ʎUK}d2 gl̔<u+ϼMLH\< a-t ntG TtM1>$mgާGNNV(N^C:QvDel) "0=˓Fڠgβ,Y>_52NOc(Sx> 0z,AȶT/&dG-<8b^8Fj LJw)QɒYp4G2ftrN!>eŷWVIr[:]8BdT+<ʫqf 4-:^zK@0IB%RyQPc$k=v I>_DK= %& F#T$#s bT?{L&TJer?a 0yҤj0˽RS GЮc.=E><CmƟ>vq&>̳OJK,)Y?PYL)x}ٜ)\TؼCGo B)n>Wo'l16X7rf!֥O,\ۛS�Ɔ#t8b7uց_-Zs(+$_cwmGI2$$BCi݂6m;!)6MX2;7'w8w=x/;9/ز'ßxzJ*$m_*[tgCO�Hc~JlN! "p6[2W uKMXlg�9yX&sWZg~gXN�\׶^HŤ$S u)3�?;HޚH0B-͏[8q e ϻԦo8e/#(3,{)>ȑOzSF=4aCD2mzN |re)Eݴ}h� 90d1L|Oe!NrQ&j k۟oomٕ~Bia^|n1x]N液k/ [EOCOxάd�TDz;P`o0[G<~C xu(|H/m{έ;qQEO)#{_[E籝AmxɸA-Wq<N&%JvqH?SH];(0N9sl;1-: ?^l9 w2gὀا/5+9ΠQxK,r-#i$}z0hH*Ϳ#8 ??1-"xM䭟ՈMYS.Ia{SB-*Xv+W/Ixeh!F7F߉vlJѪH2EF#<edX}}߫.8/,ZMUU/-$QUUB4/own޽̟?7x&M(I0ex z qš+5+J+*l3G^AXi;޿/ʲ鲂wkwF@@Nr΅?tkpT�FÄrrӼ=u\HYr6x.]fW&P0e-`dCBx`ST1"9p  eŅde$4$1�UU+\ZN U@% 'Z-ßz1-Doo%J$k-*#3?XsA+CRN4tKY<e_*Kok$FԾ^HH+uM;W4m7 jƆ_RԟAf$f� d!̈bɉsJ tv"Q/HTg6u9'97ed_elZ6po=.3Vps&g ̝HbF4󭍷Gx.*N凯`nz^| ҩM|̌ZAz-:=8c<&tN.DzHҷ[X@.aP';]ޜHu1~Odh{{~ЇsZë|TaI4}_x\AK"uPu\}]Uxi."}wo5 *AW򵉨 nQHN`]1!DLp>F ؕHdh(=w4T> lہ'zΟf$7Iu!6"$E `ИGNF%\)]G^x%<z9_/m7" >_Ɵ?GӣK[ ri(`dL9 f~!I **=iEV7>¢59 >pgL zngiyd2J6& Bh=(رcqq9{\7$t]5, W2Qp(;Ã}�tѽmqԮE)[,Da% e+S]&{tCtmS1_kD I]3&GkZ{^9<fPEH=:w ňHG8"**C_X"B07uACM&RfGvU6e(Kwbi:<9jy>odL! 3"+>r*<Hw6Ef.\]4QgwT@P2_.s;*Bor)B`g73*B%lޞ-B9cx_B6a4]ۢ+7ul먚Q Ѷ[O:6 K;wI/yқr R$}ACS<?#o&m5G0 t癱f#ٷ?JqP7kOQљIGnpP+هS`+FMozXڷR)ěrЃ(E#!nv+f1uJK~עZij|H'9U(Т}<%[^Yf[6Qå}(WCdR@}1}e6k{Oq'&I 'D^LP.1Z!"yG]BBD$:7Լ-Z£[s 9If%^o$!I DSpu*N][j n -:{I7 `9?r$ORTY#J6na !N(hi=!Q.mWԞ!AVL2>h{><xa0E/FOBa;]zADDΝ#7A=.kѸK>K/C~<4UF.Z>C ~FTIXT$p3- kv?_"|+wO+5|h((1�YgIO݃XUN`@nUT J(e~`cc!(1DteĿnZLG]Və9<&H<Ngr,ch!=b!%cefG(={dU@K%3d]AǛZ ";27n-3ڔGa:-'z*"[(;3ɾva.r7LC㋬g`(<Fh;ndIO{/ѱK4lNT@'VS& Ad_�V�� �IDAT$B=:ŔH4z'| t&GK=ˬ%<Ç}HJ7-"|˼�koq!OxR վqt=å}y\d< lӱ;|q )ϴʸiݾʬ#ڥBk(s .( N32$L&H'\i V,υS٨1Qf!$S&]"jDDl~ :GEPP<"J o3=%B{ݺaW:2 *$|2~7,Cx?6g_1;wJG[o`,gΝ;Ǘ_~IiY]ve0RVRRƍ;hj*J6mD߾} qõLxsltE 'W2m2n/#Mj"?{PQ$RM&LU=z4Ga1n2nѓoBR5Md ̈́7I}$!O!o[L?ºCo:k_tG-녔T5n:pø~&67BK0Ϩ*WՒ;ͦjƭ`γ}y(u#')#s1qtT"g#Aņg@s7:D40P*~j*L؟T)$E;ʎqBл jv% Q|]IL~Mu,ڍ1po|]}#ّur"&HU%R!C^jg|r9\9\}oҺeKDAN>q%=5kNVGgpn{a4 6n�z=NS[O⯆D�%(% ?AzR<<-50 &}y̴,8|DeaKhiD:ǁC1m-Ye"ACv4h O\I.咆[CimQO9Ta뾔{#җաK`T\8 SvLY) m c`̍B ƳP0(7<{m<Kn4:5@܈UHHDtL |AINNfM  .òF3$%%?{カFB,X Panݺo`{VRZJ\\ٔr}yLו]-cbbx굧8<>ׅiLxaj"�U UbJKJ_EDKZI;|S)O<Z=cQcB=zjJ %2}۴6EEd,1RNtX&m/{r@DMgVbR"]/o\Q^F<뎺 ?o#MۛWzyp'DZa6B )C[)} @Kxa<mC #72,ѕ2r$#s*ٰ<n 3cfM,:<ɂ =u2M >᫞pj1-$8aCϳzXb>pmP}9\{HًH:s~K.6*. Є_=yZRv3C9\*irm<TTP=RH� $2= 5K}?9tބ:8jĀU*13NPh$㷔Ћ/>r hh06CUdFGjU�wve6 wأlp]!kR�F(J2ܚs+ sx5%ʭ,KFjA!@̽~a7.A&w_'8sOdі Ttcq^7 ԷE)Tpē߁>-iPd44aZ%3wCF=I$x%Eù-*3Ec:Ӓw~SHC$%%ɍsРA '|3v8$I6 O{nV,X kv5/kגo3|<cbb1bĥLVCK}%ȋ-bh!,eÒM4Kb=e$mbt,۶.FګSՑj]!wf0QS׏U(:**0X6P+̍$5H:>W~_{$zSiyG" }dk\2gD;-Z;pbX:u{Wp] #5Yf7?D+eĝ^z!')!ӛPwλ:vl2A44^e]D|ҏ#v,G22/^g1{{/ZpTQCö-lJ}v]dDޯtKXWYN}熾Y>[;,$Gw'3<HXAх,'ƃt=ǻ6fy&oO_ѵ<]Ktt%)Mv5@yR7,f]]"P*[~؇Zk[qp ?NxwI+*9'&Iumg|ߍ.>u޷abmvt4tJ${MI9wz.P(kSTJatH: U1m tDbutx*E%eXP!0sj-ZZ$(.勗{j? 9yvM F;@#槣ݣؾf%w'N%PH&Xqh7!^"Uӫ7ta/Oknh6Hv8wwwԭf8@wڠAXe痏8Cuq_2UMPtz1_CЫ"hTqk ~ ?i$#2 c)2o8~ָq�5  bرr-5[u9+\ܞ`&1q$/̇~HDG3iD^1=fٓ%zoحcx<| 8y!yK_0)u;0%/r'߱ÉThhw5!xHaո,|hҮy1 j,iD|+GS9||#䡈VJ0չIL~K0ixH3AEC㙠bFwL汁�(5夯KQ7mO1xpKB옽97z Ι-�.#NRwtRz!FQ?+ZE_2{K/{]M\3x1l a=+^f}w97ed.;)}5t@$m]8mi٥2c"*Ӄ$liZ|W`, >&ݹ%Bcυ TGw`8'RV*Q|+/L[z@8g2uI _8F€!]�˒X//(GҬuwz1FO}op@__)Shl)"aԷ-uTvƹmݰyҘmZ͇q+>=աxW٭o鄐&<J ߏ![!:ϵm|雌# Z5﹉]:֫1O}f~5�?6I6c;|nҏ# fMPk(ZM0J/<e+YXJ& �< 1~u+g%o!cDxP?h"8)J eJ4Z˖-㮻`pTgʝVGye*9h߭=RNY3hPl2he4e嚾[ʗ b|أ3 )n�7{\*]Ky,8)%xϘ;I-VNaOPH\_<=Y=~^Fn#6g 2hԞb��K.}){ɼlw}qngyZgi+J6lȀq7鴪?vC1LS̟?kߣ>(�+V?¾y'<ŋL43gE[ S>T5HJ`;=_WJ%'gբgݷela3jwοݳ @i"c&U~/v>U"p\PК,cB! Ije5PI@B ,R_tXx;oVϼzT1-x WSkq�+gu"'[זq@OYwY<Rwҕvuޫsradݍ|W?NpVWG/jʀ%{\ƳzA:ͮrWp>;wS;^׶})<3}[&;7hPd|Ϸt*9)@s@ #PR9 .GD% @H-9N.'%"H00 FLk)]5c'""p([0�:DTT9R N ВӈRPPF*viK:d„ ͉�L1}0*MKT) e_[ba7WD<",]@௔??f /ԗ0E1Ew$qM.]gg2{gZ:>[7Ivm�::_~7*ycr^mdNCo0qF-ZdGt֭,ZCRVZJDD׸3a&Mٳgfb\zW3<ݤӇ/7{\{y;rX"2,�uyNeO^Q}je/,hɄZD=3&yM~i}͝Oxn?Km M'պ^N-}s-60=s%]癌LzժκMpaǝh<~}=q%2 ꦮ}Z/HCU,^`vT`w<W%v~ .Y]Gq`5I\=jƩI8)-~7LC D&$0md $K}:괼]Б?I?) `݈V_@x57Ϸךnۍw-o=A Ved{Cy~N{uxz&Әx84J=wݻkG_|ZYU}� i oB :C"?{Ep{J H B MAAH"JSDy)ґtT@DZ N( Fz.!\ !!y,wݛ̮ٝJDDk׭cu^lY,lll8p̜]ܻp\!<&LlpE]iPpԼp*%%BS˖A,MPJ {]UIB19zX�|<US2 8Ջcihg>MK&-i]ƞty$M*bvU+3$<meqx;.l~YW�Vdn'+F%}z�FqHof&%K* |>iLׯu->)e z>t"$(WOϏp"""8BՀ'͍oFF2"ߕ̩}_wqB{UM>d'ޞؔh*v]AxF%vBxVl>bPcS>XkP(Ͼ$2e| ˚)XfƠ:+ܣRM.=6m䈫AgaHahr)J:ᄑrN%vN=CT<mN;ė*g; Vx:%&lFyLo/J(([E$)}Ex*6>|vvv?�OG"22Yf#K7_EE6ՅȋSQR vA(%"vBxF�lPq*Au1z>?j_ՠx5(sf?.=Q*g/6Wrzwﳔ2m;j< :012Hk)ܼ2knW' %Ujc=YvBTEA=.I,WHO&M *<;;G{9E WRUIɇP%/Q!g~l/-),I5ibb^4?zn]_Y RvrWn g}!3%9"/Rx9Taܛ <ݘ*tFnFeҐ%)ǠgV;ϷQ̜ܗ+t=|JJ>G-Ax9.9d{YoIgIGUU111!---) ܿBONl< KioS9=oP&VxnC"*iii<ʺV%55SE#KJ?PIW%%B#ʖ D]Q,Ƿ#Lj111yT+_,!߉QC2N`Qx<niiܣ4T^efPTUբ @Jʾ*)Q Lԏe9%%%)ؘ҃l#all,& BA 9/<< |飲%dYBp 1H,kP Etã._xyV6_ڏ{!_AAAA\+-!xyyall Pd/ H fiz(dI&MٳTZ5,`oρpqqFBƳ=g +_rWEJ%    /LoW(cg{{{h4Ȳ_å}zv�GUE*11DDDp-k$ p,W{{lmFF#HFPݐ|99:b[:|   rqz;BZ#Sw>QQQš*<2V^$7nxxxxC'GGQTgzTU^O||</\ ..dHIIyu<|ɉr景IV-͂    >TUUtTZ\puqy2 Y SK/m>>7&+++jT(Y\nh<mAAAAx:&EQrx ȨLAAAE'    X8No_Ģ_7t%'2+d,B" F%L(75PS ?s.=x<$eyVtvQA$?mr>^<j !?mHr>Qc9`/G3sυfQy2hz h~7{{L|#l".%9Wr\VIe7ǩDhsŻV{>w.iXBuO<EmڼùQ$bU_Du)WvlN)_ #ȁ]>) HZ,\ވv];P%O �Jwfn.h?oC r-?mglX4ɲej݋-^?kYHcmڲM!UkO-Jz.,T)]`&L-LV cqď֡ g *~c3rw Cߙ'X ='Jr*z5�� �IDAT1Fk%sjaX%5'#@G?Yr%Ŵ -3;o>eWٸ55ߤϠuzP=Fm~/Q E>KW6etHq#&@L+u& D?kt0hh}^'8q :{*_+Yn/WT XG}YMMcgiJ!,F|wdp/gu1 ;OH\2-(<nEE!>&4|1Do反kF.D.n@TW�_g2mO9LꆿX^DZwdpO,K3f3u54ߍ˶ ^0M'tz`fOJ=Y7ցy3:iR"m3?Ub bᄬ;Ԍ`1jY85X/_s?XODG]]F%)|7->nrm?aQx}1fJce*eDf*Elӕ 51Dمh㚑0ق]CDSP''Rǵ=x{<޷;JLCo_1 ZœˀWk럎ۣif=r�#b;ιu]5g~W|h݁V,ّ[?BM0AhXݡ\ClO|յ ~p^, 4]K7n+O [dİVT4Mȝ'1j!nF%#[:׸6̈́G# 6zOOSFq o$)FظҲzw|,]^֢~ct[?i Y%oXy?gbVfҫQy\y>sKhx"Z+G|;~.V #=i!k*nG̠z68u178&V88{Z1 L>.ŏ^plGjT{xJQb u*A36dnj/}>g':[3fP}-wpNe>G~JҐʙS]fϥGix_4MZgly)֣:\دY86Ō NC G!n?MwoU $5O1S ̀ꎱ 8Bk'[2fж\?KᴭQ xa#ێįNzP;3 497`Z1]Pb7/&7 ( ϟW�5K;mR2^>B 4<� mU:mOMR^UG-Lc[3,^1?sV (qܸ 'z#St6Xʖ~*p3ˮ | o㊌];v| 㺟ӣU.TήL ~"Wm> Nb\:8=C\̨(Ƒb猬Fq#z2vD�f)7m<β~|.͟?wsGF+M95/әZև]̏rƘ#9u1+OytpyQIѓ,T"S�|c}M8.avp}3SfŬn-=,y!S~cؑqiH-O@PFX3e5'ţֳE* BW@uJ|@c) <>Ifk1.P[aEA9t' Jϻ�HTڕzƳk ?]}?~4I^ "n&$s71ީ~HCY薱qлF׬Yw:`ϩKW(H&:*xUM'Sҩ \R<&ۦJq,||E<ҕMAd{M3ïߴjHA]?uIlу3Ondz`Ņ i)ؕ=un.YԥeZ=zjuj<3Hrzˎs ѳ:j6nAԫhH3.{x4LεX7JX䖠 ji y9{3~?pv3-_z5ՠ_;R#0�#N9ʞ lޔdV0)bc+G<2΃w3=<ɸӴL+T3#w2:ڻ$# K$yqكu]~uX@_Lve\kؓ1ĨT Aeo $}ѼP.#N6=9l1n9eB*I)ivAxa$U0u*CNGsk/2|&Q+yN7C8z%aV90n<Pl;74q(O~=ߠ?;�) $^h1)eZˮFBPl%:( LceJK܏"Ӥ.`h93 |,׳oOR:!4[dEtKLrZ2fLH]Eؑ:36ǐh6MA((&$`+3ɏ.i3t VF\/f0w[vÝV[=KESá|S];w%e[dІ8>& 93xUM\NL!ln'o}{(6'8`%bU(Hښī`+sx Ωw,1PS2�Wk8zJwlo7I۫t<^Zr>њj= bH9| ]1oTw.7|4b1Wz2p1M3\HjO/x ‹F`ꔡP$i,]p)>Ghpi=B3q濕u#~IQ5C;zTVY3*<y;z"Sc m|G:L6f`da(okoV; 3ٔorܠtǸ`Vn J2c9L8gixjES@IXx5UE~#rYj5CY2R(Q}/q3c;*5H{"}1UЀ|e[gK9x*ɸ<6@M#::dPUTɒ׆E*֪,Z#:#mo�M7>Aq૏6_9Ӡрq#FӍi#^VVU}ˠʶee 㿱mf}uogXY !=HhdHKgP:E^Ҡͭiֳ)C^1PxD /^! Jf9d[W\-;w$LC%_c٠<2X'>I6t$-f7N4z,yAo|Bd RUPQ0v]X,;I2ñ)R,Q:ɔh"cTm3IoS64ftS|># Hd.ݿOlɉtCѷQ?zk4'F|o wd3?7y+ɦ4e;81A(: G4U2íΫT!<MbNwͫ`qe7k-cPtI LW]NHTSHO0m\7:-/$縘≇IS GǹtSwxg+jx{~$3{+zY J&1*h\4+> %p$S[3`R-Q =szؖ{oC*P^M0r\{_JAթ|ɡig𬌫$O|}*j0 e3Wb,H tj$̀QцOeM_õLg< aC*UR U=?J C$VX["%lL`ݪ ѝfwqt\?{GN1G[9PgěxYDL$#,)9WkKˊZUX+fGu,<dx#te}@ A(` GqDHџ3ڈC,<ޡ#N4zzv&h#aK&Bq≗$.ldV$UWҶFwEs]4|"0LW0D ͒Qey{',:+9S(X� Y֣S7l=yZ4aL٦.NO#7ʳW­F)Eu{0rп>o3n=ɠ5dُ`SaAc Cʝl;gY̕(B/Fbm,!ʣ Q&=H^,]ish d*o7k'0ݲ/ͽ͉ <gI$(:e 4NٞϚ('FȌXV }kR7p*vqxZbc%ub/[Vʵ ~G'W~F0K 'tݧ/㆛l@̩>&oV9O_/fD꣗8j<jа#?Hp|zvTNbu,P @B!rD<OG䳧' *e٣aF#tŽ6`\+|X I $]pCX8z Jb߉~'g͚1fdp5-2-ck"t#>A><ҥ;ČGj8JS%mD˚MiUAOA{. _<g\eذ NY/:wzw2S6*rtG*8>A'[a[~$0;n%0~i;e!k 'ĞJ[% WR: [�5ٺ{)Ē*aUƉkn. E,߾Л وH^mqiMq2h%~͆;Z~H@4[7[3b j1f}Gy}63V 9}@ꗂg/COȸucaiZ4vθ,tg쎒䎑da_cwA)sm/,=5QΠ <-ɶ.oYδH9{QI fʑ\׻weYDѵ|XpPLKiwnj ѤY]w;fS5SRR%lm1ra=8]JC&mi;|ǴQ$kq҆1P|j6+ 7H5.K@Ii ׷1%y_q8qb .s\21{Y `hZ4N};1{%ʹRFʴ⒏,,Gj"1׎inF*g`'J|f%UUGyAx wDPWCiҼUHA(P{TtC0UAFƿ^#$#=AAbBƁ8披Fɷ9ikIMq( Lpզ!ks $AA53anG%[i֩i PBWUkdq%  B YP<V/ % 8QAAAAA(QDSAAAAE=AAAAA(QDSAAAAE=AAAAA(QDSAAAAE=AAAAA(QDSAAAAE=AA (^>i?^A_iA(8No_Ģ_fm_v[쎥,JQE z 3WoS ?s.=@-,݊W3xYm O(vvA(B~ϡ9(YnFs|Zvz Pbn>ϧ:l_GD\K=3ldm<{2xϐԶ䲞J¥],[?N]'*E+޵ᰖsMp{Zۖz6bpfaE:ѯg]/S|yʗH*ĔSh;0>[7x|ת3^#vv&a^p?r[8<=rh1vO-ZtIM߽ϣN^P6]~:RO]O7gâI-(GP^ hi/kYHcmڲM!UkO-Jz.g[OU90+w'E 2xԦIik+evetHq#&@C#]r*z1FY{*Ѩ o%>S_/kd>vfۊ ]kIom ?9u=43k ) \G6+1Ws5Ǫ-?/9e]8}A($j_y]Az7(%g@)}Q5;QW~ɷo-|9dT}YMMcgiJ/tU#>fyK;23'$.XNG>J4&!T|EvMLѱ(=7qiϔ!aO$&"eGIY .yiA(H- ̦b:i{gR7d}Bm"'պ#{`I/|\a7[n_^pg*ir8{d8s3{SPg 1U`O"&vocd&wǢHBqq88j u5u %Qwmi>Bg*~̔<j'y_}:"o]x@`|8Xb5]OP8F- F ?Zb/xe" B%?9n>u {1XPܩPR�|lZ7>N1Bbyt zUO (�z.-I�FZws P8j*+Δ̯ *Vϼɱ XA.DTICdF,;1tW]px| Œ`Jڵtr bŻAOF kEEyfT2~{0l`SL�%{{zU5~#I15лxD%:2l]qɊ)ܨD]ɖ:%6*ՔXBEsn*ni} cCͭ8u178&V88{Z1 g^Jc6$Kg*a+5ę~k B'73r/ґOC[IO(F~f7Πmz-˳NQf{$cgMwOt8oeQJ.#@)3dը)nΥwp^t8bmf[H9!sM2W~ߎ3Kd= ³-C_3(>QU�;8^s'V2k4rfTDs_Q^{9 fwSrV'O >`/Ѡ[4^<OdJ# 'rfxAO'5.xp1ޕppĽci{3cNޟ@CXOyP(*GzW<uYKYF0>Q W`YrOW1S ̀ꎱ 8=xe"J AM>xi3z&:@Bc[}`TyD:QF ĥ8 WL~ϜJ7B. (^ׁH&:*\Nr8=5I@�� �IDAT{^nf5o;m\0+{VΟa\szT">g*gW`?+\6c'`l.p!ufZVHsFVrN=;"�d gQGO>z}b##S{k vL-ήOGMF n9vc�ܺ'Qz<:QArn2~:f[VƢ:bP� :.+P0&qp-' %\] >6ٕ<ʜKkF2l}τj0?ƚ)9q--!imi$ݿm^6>äʵaQTqC΢HUjYuZMډrʧkX`n[g my<겨O/g/9zl1f܋Y[5|LUFȤXzT̥OFAt\r + ԝ`/7(U<f x YPkWmϮ'W+_O($YP[/Gx/~ڧy(8q,1Lv,[&FՠGl=֦r۬et˼&ۦJq,||{OsP8;W;{PD%L(״޴J̔dŎ#)ThZ(k*e|qN q5yDS Hlу3Ondz`Ņ i)ؕ=un.YԥeFa5?/{x>N!Y:Vv fL5Qq Z^EǞd\wD_Zoܧ(d0ePK{dSß;똾ijԫߨ%"ɗwQLO`-'C<8O[ L=h䑱 _wIƕe\ռ9q6%8=bҖ]y) ۔%:GT;5(ԘhUN.P'br+SWoZÞ<<'m\U֭?]۹LS%Kj?Fi̦Υ UEQU$ٖZ|FLR 4y Y8 &.US:F@ugZw*dM|^u겨O/!CK>6ǘHbT *֠^fF~g*qS:4>W"!fHDqう>dߑ̽aD)(mX}2Ƨ=a7k>VՁ^m2F֨.|e'W JEؑ:36ǐha%+[2eRU,ۖ ^(pÇpӹ yF59U>NGoɴ8Eº@fuqЧ${xͩŤ)j>Ij]ٲ v%bGBK=A lo , FgK{j1]ռ8׋ټ!d@G%VpUVB痌/CdHm<:Z固8wx+)j$6|88 9Nc2ݾJע4ˉ)Dyr^$ I2pX9fp*J:^5s]%Kt:t @rNFǠ"4yRxǨֵƉ6nLV;yE)%Ng9hM5>DžDc{ӅBU|re7$O B%5.Kmf|.`v hȽ[զq)$} !-5<\lQ9rjy¢s\L Y2~eQ^՗|=%wZ߷ysᛴq|\FNtȗ,tWTQ'MG4Ǻsq2V+GQ/~5j7߬ q5%gz$#<ՙzo[QΫ'tƷdP5W}2| _~=!:y?F¨Cϡ]>Gj=K=A Wc^X72}-V9:q=q .%ר\im fٌnb3Ԡ#tT dBKmq.५$ب55@UQ%K^}d>ZhkoJFZPg,h(71~ZROcoǁ>|LFj5x0w6Tlә[;\CU0Eż9Ǒyf[r춑W ?^Ҡ5g4G3=H*hcڮ?޾'(%4 5C-ϩN7~qYOvYs~,K%"!-McT6t7m̼׳V7=RD}$Opp\+zHO!lP[P Y.p檞RAӟih(*HRŞlOS ο~SB̝$Xڄp(6Go5c5UZo.?BAIo+ 6{벨[MmS,w*xW&1C6v ,i2[lsY"vJDFxTQ.M5m@Ahd[Wd-Cy8p'PzWn,[ƪ*;/(/n|˘6:0W]NHTSHO0m\7:-/$縘≇IS GǹtANNݕs\W͞ほ/eJLxRO�c3$@*ݐwZZsd~t H&ēOXNvrxLPn*sSk =FNYF5D=h1°2j^3fٵTYUlG+.gu*Kߞc]^,4$D\215&-e�/n5vA qUd6ϹO9}(\Iؿgl е9B7GER' >q\ΟqhҲFLmHg"/nҝfwqtHX7ɷ+Xb+V̦F#X4>rWbp-_Q0O[r~;">أ|gG 4 *.>TR*UPvVNg#)2:|+{bkzHA(` GqDHџ3ڈC,<ޡcϐ{!9q/ݬon6vlɽh"'z^gMywfg.^9<\3FmneJAmNXq,m:!ktxW4g5H(4} M߀,֏mތ꽇|s vmiLĩJƍ!'q`M-jS#7ʳW­F)Eu+DJ I`jj4·@%ڡR)$ē�`Qw;x2h&Y#ǔCkXtИcАԟG4Nٖf5(sVvov-ۜ# Ic6Ը9yK%QmXe2jK^ᇵXdNIOLϳNg|fOgTޒ@J"^\u5<s ƠH^,]isՓiʝl;gY̕(B/Fbm,.#hBdF^hu|,+ǵvmx K)g8Z8<vnYmL#vVoM#r%w GqJ6NTYշ?秉g5.DZVy~{d|{Oo5SӐ!)>feZ$gvb忥h452gw% cJ/0,u-fh {&2`y=PٿWb*l%%"_l"Lޯي ՂAd g~ĎbWGk Mv ~\~Z'sϕljA+ߺI^HYKz+e[!qHwiӡ ;f bs8a}+4VLAOA{. _<gt>eذ NY/:wzw2S6*rtG*8> &2%e1 VX'օs;: Llpľt 0LcNYȚqI1R14Vm•T,wj^5JfXqrK)g1z˷/b8&;n%{g#"ző5ˠ}IHӌ�C}|\?2ffHxT02»tf--Dk53Mȶ6Q.2c<';J¾;FZ4jvpf|d-V8{θw9}hĥe'^]?HjO<tFXk-QY 3t+]?c3sQwt<‹Ɛ"}01jis<9aO}%m[1JWN_ rkJ0l2||֮a۞L[KdU i=N~\{$JVqwM55xɼkz`H̡>U3%%U& L)kkmC7#iͰwJS>ZЎ33 R)G&~5�T5~MO6H̵#lڴQh؉RB<i7v: S^/8#?zO<%+ 2E/F6Hʕ\&pq)qzѕ}ߥFNo'-yA#׷1%y_q8q]-jO %{q=_MSMo<™kwu\D[(^v>߇Ӥy"H �@>o?-LinU#?П [G)a؃Q"& P{ȟldd �bBgfg%oVSiw[  PqN`Qm~Cښ|R(/R|$)?cC\SƾU^LAԋgjӐES z0U1:s  |D"Ɇ]jjo}>ޏvE)7`zNACWUkdq}.J=_ֲ^CIOnf˩|kEo R,uBxs,mɮw-m Bx BA@w Ir$(Ȕ_MҭJSl j0³?_[<mێv$F_D]yw*HZ?nCNOmq+"5hԇӷI0*+;�=YWK~ˑ[aTw?OwqBAAAA'"GEN%G[%EecC?ͧy]!~tfȉu##'Q Q΅'YkYfb~:v j|8~EGIԨߘ5v9{G";TŒԻ)h ,,    D"YԔ>U#|AEFn3lv]q ي7&n㧭45βJBVv]/-Mofd:c U=(QޙEKW),-    BDг)aD2Ti#Gd4a!)޽I7$MF,-r+R.Q&8ϓ-K""["!hj))=ZVFլY{,htQ!.1YϽ? ~Z=9s9{= pv<`/ hqĪC}os,|-=?cB!B!sBOU*ǷlT7S^o /ȫv;?y c -T�N. i)$'&SSS44z L@SQ5}6#7]<gB2+ZB!B!"G|ue bNxzzflcͿsSУ"F#d.m8ć`‣HW0zӬ([uAuBCZP!B!B!y{St~SE1̛_͢F/q\( ~agDKڗV2fdRƽw-d?otw8i& DJ \/Ɇ"8MZov<Z3\M~[™*QJBB!B!E|ZUJMhP*PӔV Z1~~UBaD]q{t}WL@*u47cUl<[5i/R |ئu$DFq[٧yS!;mv2FbK#\!B!B#E4Qھgj}ܻ| 9Bgɾˡ CZB! ZG^MY3zm\͓6P"M !c},OyiD_cRYfKOC\Т,;ey)BU9wK}ײ%,2QMY=DHy$ē$sz !bxk6!>Fc*i,]iф?ȅ(R-KW5oמ@ܶS#V/XoG.myP 9ŷFpBo@XuQ$`{Y؁>!u)UvΊx!3YQ{1nOruj?oY?G(BP'fR Z~RӔ'KHY@V=*YDw+v[ZMqPmҮ;YCէvˈ`MOMLVwzk?~\|mXY<7 `xXSxm gb!.q(Sѵz t$&cЛaaR:-Ȟ$Y'tSQbX?k6v$Rûƫ׃.O6[>1t>д2\;É0e}+<s>pKupRŗ5ә~p҂EW&AO!xL[?ǹ<}P>H\vۻ<*rG[Ok/r\>Q]Xilrbw3 7kq#ACp'C ӿV)\tq΋Qs~(B,[ɤ\Ƽ"veH= "B9`4V_0qG)zFE@1écsxdl՞!Ǖ8jG,ZQʒ3 H l珬{C&3%C"?|Ϩ%9im1װv'lLf}< %3i|҂ʼnG櫟юcr,;|k8s1?>HE l7O2sA_PȇC >:D#yYM�\:$sq _pfh;3%!*{>U.8##*%sŒoS1ӝ z !cJJ%e.w!;Mhlk\T)]dŨyU~ N"BmMל8cG?[]4 `.0bK8Xzm [[6j$a{8a_{-'Z Mf0]&IgGյ~׻ߍTs5^\WH45a蠖Hې[1|^.G%q%I /s2FķTT"4oQMEYE:Fȳl1}?w~=jz6$~R̍*㔵�f ЧaV�D�� �IDAThE=ˤQOWGo=S_sH/9#!S#tTJջ^!l}.ܘS{Œ$rvlf,IXD&.)]ʧgB<>Qx M~A6D ^ ntzjM>G~J̱e+]͠ObyxW??O`y%`g1Fˋ7st3PN_QnՇNx@>D{KJzl?,xo LLTSʟ/ te?Tx^ (K#PD=Ky?ؽL(gѻ5 *׷boִ A 9$-E1>yV[>SX6ǝka Ts!7Ӆ&r!dYM56Wҡ"/Z<7/a+$?6sf?hg~`(Юw[4[VK>%L�$78Xb]Μ7m!PxjwiK`"pPM(ݬDhtΞr\2^u!xPtt|r[cVSzTͥSLҡ|}Og3gϠk,'c'Iq-$G7tZk#btm g2w#{0KI [?{*X:kFV8}rfObsfwxp{x.>.18+C$nX(t&܋@9y.[)Z5bc_[pmjHs(g*jp>EA=Ov;)_#=l=Bˡ= ?e'0&q2sLG'27UmrmL]jѥSJaK ϑrͿ\Xt@R׮8+&fFR Æ0/Wv_K@'':g\tl{/:P\#XMhS6u12%HVT<:W\%& l7k3Px>sb5ئ6a\7u8ĺ6:q,xb ]K&.YgVH-f!lnFO®RFe,ӿ{T#Rv9IՌ!uDKkiӜh8q5"AO!÷y'Lf߹i 5B9P"+ ,i^LʎK:F4S�</; Jx#*U{]r1s 3u"!F nN2vf3+qoUo]|/Xֻ5][ k |'/*oO[³*HifT Ĕ@aǘҌtP v0z㠀O-ߛ?3)xlZnU#S_"GOc߁hں?'# Ae+֬=Ivs[LXd;z;t6~ 9MJ{˦ 8|. ct$њ5僪SgYG~3!UF|<Ci8MpP.q1Vgrw+?{}"QjMJc[B ޝ=~3 �CR<wR^`^̢ˮs%x�|<~!hT݊c#p$yQ396@LvW}[QX QFjJ{)>nƪ Oʣ6e8IıBCڶM2gagHw+esՕK>[DiTp.X\!f A&IduV!ſn`bbFã蝨Ft A줩R;<NmgK4iW':ч67-۶?3$-f/hŵsib u'ө 2n7{-?d<L&T ]6-߾۬xz+7Oq&!K3:te JވD?iV$&*FRb%J Wbqun+6XVL"b끇{+ z-Ub8'Z^�CI̾L�lMdR 7$:!ʦ=0z59UZӤS>F QT PiPlq/>Gqo5q Z>ӧ 9:mvӪ \37JY#%"ݨx -6Ω:1n_2t Ҏ:Y&Φwi�Z[$(Ttr}rePˮOM[27jqP >۷OM=53c*Aϧ,Id jV!ē`] /3}sf*9 yx tP4SJE& X_ JU"6]#o08(&̑ St>?Ĝ*Ai@{:7܊s7@K֭xU@^<ޕ3[gLno*&b4$7�·cX8:k_k_#P>ȶ|弇+gʔ+(uj=~eS/s#1LKU:߭gkT76Z@ZHeϩbF,>.!4'.iPŁ~H1q+м`I|<}TOlihʳ]`0뼌\њo^ә}]ws!MX8Rn$3hQLfq A!L^Ӆ7d}~Op_;cU sz+cMs:?FT\<iAON*qPbJ!#"2ZfQ ?cNΪp'UH1y >ܐu_cx_=qYN*WiҰ/r!)&^R㦼=&NaV\zSj.F7k̠ QG:g0;yF4h m7?f!JcҖ̙Ļ+I/Щ%M5׺0hq ;'ēģ)xyv:H=oWs>4nUYx1+6RɅ;#兞Jjj~qV ocatU᥆%{5O&渘x\M)//2ĭxNr8 y5%5+w"~&_t~Z?gIN+g^Ruq(7.\$!›C~eSLoL=7bKP+[Ăe;BY=saey9|4/{{k%dYA<aWNWFE?B_M f,󙮔̃{*ULʕ\,"-vnHq1xxz8WĿD\!(L3αǾf%b c,[C6(yC1#nXlʘuiʸ#G[./p rNu pJ!lg�_}ON *Id nV"tIwHG7SnEӇpCI.FNfDBnw_-Cˏ>+>\˒/&~"ڵ5\:+ɲkܸsk+.zL bZ 6:" \snA9L=V nZA͙6U\S+cŪXi$L+ѬY߁pY޼iI7|S|soAE7lu\;r gzthŀucԬܱJť̩Ѻ.{L|d5[VlūyYLtˀLYΗ~0Φ,ػ{̨?"|m$7/zP~Y-^ĕ*\7pQWkyg|!ēb]ψznD]5zu(댕Eة(4K̔\{)韋Ȓ=H|oWl;D^<Ƒ䚼ߥC7K畵 T !ݎ c94X ;wߠLIH{3({S~ب@U }/90*I!|hܩNJ.Ş`˲߈wyzA4;(G.dpk4v~NI c,}^wO5jKq,LZoߗ5պDwUk>:Rrɯ|pԩkkHv Wq>6p˗aҌGbNK_}^~2\oӣ~ï y]^&x} ӊnWMs1ѫ^hg݂y/Ӗ$4y+<܋(lkgI^ ]͜ye4yi Qx%r;|HcFT]N[B8<UrLijҺCY*.yh <?kq\ޕ/zwzN'G Eg]ol=Wns{\67]s56j`̝(v 4r{J)^Asj%/U1$+ؖpRx[)ߚd,i>`GŶl`IӑOF2co#km\ܞ)~'1rЅ)X{T)A] w뙾u?W;E'2|Q*z+{JTI$ٖFK=)DfjD=QWc<ͮ_4ɊNe};/Br9-(š.&`*6X1$)V8JyGhj?f=u%ޜ߮`L^{dS;/Gz`L̡>U )Y>AK* ͞lW2R0)HL\Eʭѿ[\˾ϧeӫ'47'B7{KGl"2I?/ ;Q{97.zI^7gZ Fm&z|=;JySH(caxpo=I-2`]_ bs>n}b|tf Cp lŧP9Kähˣ� Y]~a6˳yQv,:E0 <WXۯ+ G&Nٽ:1äWul:oޯz`$ =q57fu Y3}q.F:~J6I C{i<wo)9 i8Ϗ#?`e"u[VϽiJ˧#!B!ȇ;膭ct7BR}Ctw'ouֻ/ٖa0w'gjis)𰓧Ҍԓ;~gzO- !B!(bO}C^-O! =aQd;]j$ukAOYN !B!EYYzrZI2,":}t0&5cWb4Պ:(3u"u!B!dLM4'oEJ + ~de$)V8NҭCz@&O,ԅB!B!ȝHL !B!"+?-B!B!(R$)B!B!(R$)B!B!(R$)B!B!(R$)B!B!(R$)B!B!(R$)B!@Kt ΋B-?g/oH-ϦYQHS!ca\V41-ct,Β7[~>8y\㡫yYLy-ҰKw\sO~K{&=Z4^˖Ȝۭz 'Bwγ'!$!([Y>o&{L<_?}CXܽ=3s`Zn%~P\? ۑ D%vf[oNhj+~~㗣HGTy}BR0~%<=,e3STfטt=NkSa:޹2pjX.NUʄ$ũpW! wb]W3a@c\Ϲ*O'n;ZzҷU鳖4&]V<$V&Mv]=w,򳮇Oi/#7?53UZ*qq\żTk<w 8bxX޾fXwT~Vc MδY#nCCS@ZsqfTi[zGٶp6+r2 ]H՘W>Js든B<&ڭ?u>>F5":MA*6 EQ_3|vnYbw3 7kq#CΊCXt†Z h_:D [`QE9?|OȡX} K"K@(s[4"~5M� 21(n,'٪=Cܱ!+'q".ոXֵ,:%g܉=KaAYqLfJHE=Y5$3'w޳LЄk91+U]!wjLk $ =W::k\L�T.8##*%sŒoS1_GCwYz ImxdǣX2O?+or>3v}BB#9Jʮ]C* wjA]۹zSE=c͔|w M6`ep?nw4c�N/ �S*[nS_1Jv, ^ޒe8k=԰/]V}нz-&x{FBZ}s?gF 9NF /.+^$0tPKXm-p/ٸФi9# MJE7{Ѣ�ެ"11\%Y,ټ1zV 9l ac݄_Oƫ/w<IJ$1I%!4@cFL 2ũl N�?bNOT[aRR0�4_ȢeFb9tdms72w ?eJ#۞ D%h7+5lz =z1*6Yۻ|!c&IWLA2KP~/Kx'̸: <l}2Fˋ7s.@y(LeOGq8UQ *chq1 e)hul6;CxoX Ml~5⏿(ݪ \ׁS9|<Χsgӹw|lYu 3c'BQxNo^=WHJl&~5'(P;T])iH7|J�qIn4qĺ9oB qҖ2'lQ~əmNs4B̮dzF@sڔlrңm.d—,~w,{89#`x\c9o/;1|`Mkq$9ӢxW\C94ˤl[8S#!]J]SnQ\3BN퓛7{+0ǃۣs!sƈX"wG3i ??8&F;7w7.鹿Ne1/-g5 $B[ƎeA0@x8ֹ<h9Dݷza=IJ5t$?[fnٞ DFңj%SZtTRfm҂sb/)V43<PԵ+6fC +~l° ƕ%kMm¸n+mbeZJEp1NY;*#]7b =Tr);Ф9:g\tl{/:P\#XMhS<|6=VgƮOB{>a2cL5B9P"+ ,i^LʎK:d4�75;l<QKjqUQt.|8"cN$7hҜͩW̊cԜM3,�� �IDAT _zKT|k5Z8| ^iYxV^{Դ\3WbJ ~IcM^iFR:Z};|]qP§|MۙvD<i6-sJԪsUDƾѴuNF<f܎ݦ(e1tN/U{+?X$nT?׻2aOom](#;xsȩ=IfMTF,Y֑LG'*_.G-|д~(*e8nj9ԨK\Y\ʏ^zv_HZRX'>wwgaLBϝ&(k~cՆzV.l5Yu|=sS,q2=MsK[DiTpԻX\!f<Ε8 Qu+vahC=G>uUsM_P+cZ.Ay_veUBn },ED^_^t2yfTx/g}Dd'ЏޫPmK:=ϴ[A៯xLpm8y3wx\o\5<dfT ]6;}A7F馊)$$q`F6nLƍi~1pF.o0͆YMTLzDbpu׌~;m[+={(59#_zaѷM"$1P/\==2\ D|M;V 9P0[&H뜉kt¦b{伓 3ظ^}j8ԏb帅߭Lyys7oNal? TlJ]x5�Y,6 LݤmL2=qZ Q24n^""ٍz^Ϳs*ޘ|摾@d_rݿY҈3cl_ !D`] /3}sf*8d](i|kq(4SQ4SJ9yhD}*~kHph(-NɂyefoО ޠ$T bL9VHQZrnœY (:cuS15C$7�·cX8:k_k_Gp$1Pcl˴U!\뜂^{-Ҵbncwym43եxI9u;S9xac`S<$6 <quQ?Eߏ8ϕFmh^y0$jtָe}bK@SFW/s[8VuP&%}&w,q)%B3 }P%Ȩ2h-"5\`-iF>5ien<GJ<X6^,HO!(hO<bW(oz5x:a[UvV-^̊aTrሇ~Ay`C^.eҥ,]:Lk41~:(=Nժ᭻#s,!vn*԰$wfӹcϙ )W/xR紡<f}.GiqL~Zp\\ΒrK-w?|߼B<s8.P \Zw"-MôgB<**4M}{˜*4U3�xك+Xs,j-+ Mp٫iyS' >)65x6g pk T\ʕ+SYIJ$>"_qƌU/rv܃αPsHS ap' 5s+yb~7Ns6<+ȧG1eޒdsϲ[B2Sɵ,b"w!]{\9I4Npi~lo6_l27ꊑ/+t%jަ$.v9KzrGW^%Aݴ3mӧWƊU;W&0HVYL3?byӒjo&Ч,hCnv*iUlѡ֍SWs*3F뺸1lYe3M-2]g*# Q u]:/?c]OިA˜ֲ{u=:ߪ1Cp "b3G2%SylD+Ș: ueEL\ 1I8uxJ>67P+5SQhؙ)wͶ={z)A##KD˃#Y:mοњ]QyGk~^m$7/zem\CƲosiTw"A~YgD̩>%w/V}cčKVo2\Kk}R_15wӰ f'ز7]^^ ;(G.dpk4v~NIQP1SNP/㻧+1A9m)]A>iyT#ؽW]foBҵ0~Y-J4&`Z*i4&z#+[0KD5ץp&KpΚj]abjk><?>xe"AO!(P3q-UӖP}&NF:eD(iB;fJSMTqy !Eg]ol=Wns{\67]s56j`̝(v 4r{J)^Asj%/U1$+ؖpRx[)ߚd,i>`GŶ6xt>dh$3Va8RM,/I%0Q'S5x}otuw ☘Qf/dw .}1*O % d}S,0I ]GU^1Mr|hY{^錩s:,Z?R[SҧM4Df/d 2>ζ=kTQ!Psfzw,a+Riu<#G4ޕݓ3}M-~T;:J9m!]˙ɦvU_L:C}jAR}>4T D=ٚ<d`Rܑ˙&D[3/*ݷ}B˦B%%-春卑xg-U\JFooPFJmkPx}7cgK`+>ՇODhG#6͟LFiw"?G4pG!x۷L/<{wO!GB!BwI/ [OE9<G!B!H>us y<(HxB!B!SbV}VVɰ4! T)!B!BH'O! *!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B!D"AO!B!B<[84`l5}K2dzii~B)BF#X9sLK$>:8͖"ϐ^a;VK0@(h-a=}p"t'/N/Y??<? x Lvngln5#14 qcq.b~Vc MY#nCCӜiğX;zW-j7v4_H5_[OXuQ$`{Y؁>!u)UvΊxTyڙ)*nukLk)ېC{c/#7?53Dwzk?~\1y^c}N8Jv7 |Lk9H]OSFO/"Qgw�Zo g-K߭miyH6ǭBMJzXg]U k˵Ao._;Nl==;7ja5uO]UzA]Т q)Ñ QZįvkz=?- \>/ɷTߨ^c*Ixy=1nt1jh}N} wzT@KH ANQH25Zn~0P&t:#No5:yAbVp{t*%Np8.)y<jO;"ot|Ϩ%93!?: F*&(Eqݨh(f8yrςL}?r'R =bY|Pq^p',Eba;d}2)!)Vg(\)i1!fmn0t^�{?1fE4>"*Gc~D}>:o:Oe悾rG[Ok/r\>Q]Xil?MH85GoEΕ&(ogU eڵ?~ؼ‚ *СCի#x4CI>=p9mߵ7PS6xU(KY6p�chGtud}]@0pzI �R fwt˥cB ,=VSf^-어ͼɁ5sXNFjؗA^ eY=sWIQdfu-w#r x}G/~ B:%e,6q _Ql\ h҃A4˜~&ݩբwTS=hg�ow"cd[ګ)ceSr3+o]N}V51n¯'cUCFSPGr+xLq*�*X9S*U6)j asCGy�/dQ2iu#e_EtL}%%k3HXLl]o)SOsmτxT}l6OS@ܞ X~J̱e+]͠ObyxW??O`y%`f\ >Ppʵ/V4M𳿷ؽL(gѻ5O*^^l0m3!)F΃z7AP f'v2<j]+z7Q)lʜ4b綝6:9^{tڍ'Opbbb0M( z) :t:i5 )i5EM@Q4-^GQtSEAѥMCU M[N?Eѡ4 UMEUU44Pc0ecTUKM~K7]JzߥrQGYbENVQi޼{~9D 3?0n JUh׻-w w-+% &F\M,.gnq\<%{"Zc}D','nu*ev=m0:,sЦfUms@%t(`AcyS93h}{9؉kR\# ÇȡX&]d™̝H! RVϞx�tF2Nvznļٓ\ٝ<-K7F ɿl8/I;gWJ)لaC+;/ݳPpj0/fA|o=Y0f BF6v%yo)C`lʃC{@}3~N,; aZC7Lbe6+*Od^o$=T2uENu(eK؆y,->G!6rbG9S�ŚJ]Rohn:D₮O/(br+mb}9f&X'Ћp,5ku<%5[ٴ?gf 39`_rffc汿̲ zr '559-ߋǪ C444p/hur_pR):TM#%%01I4UUINN&>>666tz4EBui^CLS;wĔTՀ$tn@6**XwQTmgo6 !C/ 6Pņ(X@ AQzB elߝMB$tuҰ3sf̜3swڵk۷oc ]WGFQndhf:|Ōbt8b!.!glFoD3J$M){׭f%2}LO@x|~d/$~_I⿵ {E,aY̿},oLw'a)zˈqxxJOOʄ1c0FF!GXINIiu\rimװl:ܺ;G!S%v{_Vqff]׽{9𑫏O{zgttg˞.&kK*-cڟ۰K&\�cJ/.HGZ2=IhZꑎͶg)1䘶WOȅWx=1i~ ;M.0p TWzڗ}e*ЇC}lڂ@+ҎGSg**'K͘m]Ǎ)}?`إ-c1\MVf9̭i\ê,J6aߧ?q?Rʧ /SY'/do$u$|fQ Y[<MJY L>-'qUM!HOW^p^x ]zϳu-Pn1^`)"'ͰaЈ"ţ_#'b XF*QedE<Q5sh5Z5oDٿ?20p ݺuuS- b@7eIQ|le|bv܉V Ӂjt:DĪ!`۫,H?%%''E<LJqs/1>I!O"iIܩV"W_`.8!zU3xR4 B&]r{Y9"i#ק_h%m/?5_5/AEeʸt52.CҾ,^1}(6YɌ=2S=O Y3^cnL_p}\Kv^%?~ԛ? f<wĝHEd%P!]+gnx..~W2H~d}H}d4Ei`&<++.[>m؅`L>rFkI!̆*z<'OJCܿVyn6g^zZ)k{!tzXdYNHgX#4ԾUSAv)Z듯c0r(wj嚊)FVޤM4$1ǹ?n9}タ3M7n{%_^ˣX'&ԙ<U�t SCxhM}2sH 2~0߫W'M]Ń+μ??gГϓf wY+VC={(ul3EQ #.6FS,=w;88, f%R@$~?nQ1 aWbL&3q1|>6nȜ9sR鰳w^Gǎ Z\A jV."#K $q }BvN6L***툢HhhNJ$IBQ!I@ P/bZQQݻqYpuS&̿7D.ʺ%8ZµigaXc=J_"׼5GݐŇxwCeJLjWs#/o ]?WT:uDZ+Oey3v5v ed;3?Ob1,s^;UkC!]2Iڼ֛@@甈!xh$Po}Я_8ʥg_.<=&$# o%ee2((B0&͝j5->ӢCF5UA$V�� �IDAT贁c�r<Cwv JW7&Q䄿Кpp0o{osA]꬇r oC~=\ן-O1㾾is_Qɬw�5sI$Kܽq{2%6 |ʍ쓧?q?:2b\Œؾ{@f]^Kz #N'Z*6OcZsS$-ZGҢuG쌛 _nIF?9]Ve9*Z0̲\/᫪ɏA﹑Yo'.}<\:p\gmt(d2gݺDFF$%RZZFlsNV+&0ñZx<^t:=+WvZi޼9 ExNJK(-+&/?[`yhVǸ+(BƁL-\H^A>^<p8zf36 ]%x*FZ-FJ䭹'IN nĄL.,"�(r0n3W* #*X읫ڹo0떴spX&,- y|m$ww>7RKb |rX+3Yx9# 4M2\qy[s6]0ΎwVmr&iTa<\Y9]f Nt=~DpG?KϦ3PƢ![7_9S"0aw4~Э…GO X׵ϴ;SmR;>a=EǡH Tc4ɉD͓fFB"\ؚTlt�_6K5-j oCBaPSiI FGr[ _0|0z)**50h~qɄ6C9�:3$~b wv禴Zъ ڙt|㊍蓧}. uj̹ݾ `#I g3XGm#3[E`WKb;:&^"x]ڟ/Ǘ0~~I׻8L$D}"|~?;w"22ٌFra21Tl޼NPP %?~Avv6Kp0,s.>SZ-ڑ5),,$((ҲRJKK''2ef[0tP:t@Hhhy(?`ѢEx^JJ(((frX,x<h4U"(zzWjDno`z͵<҉e3,~b f1F?W(-|2~>9bGcT+zۯFdm˖b[bGӦ7r'c;2oYp,�ĸothHfk(L\t&4U3\ *RC d.ʀ'7t~Eom ^N\S\Vm%ѫM2_i('r+WGU.,>g:1W0ct9p+aŕ5ˊFL~Yϱ.m gJ;o _zܓ6Wܒ<=-X秲xnjӊ.yi qڂ|ME2 xEgŸŷ%!T`;?})ّCS6e0u<2ln*1\%QuK3-J(udhL~'8*n7Nbǘsd\q9;$`l+@܏+/kO1ꖈ_F!=.K)<)4c?Z]&u;(Yl{6"`mC&ζwQ驧<xF&.̠&ꕥ׌IΏ[HڏxgSFSO=7оШ>GxwλL#GuPFr:]Ej fJQLi)c*&p#|/ \dd'w_} &*Py93Z@f`C,&W>ۗ竊hyK\߾jzNlDd71/1}fP(.^Ag3rK,eA@d3,;hh|/Ziѵ)U֍p>RlI ΂dc=L1Qo2.p+6- q_Q3At ?MhYj-̈́4$Ņ\˴: a%z2S13c GӹKWdYF?χ/Ӭy CM2ڶm"bc:NBB).)"Z$@Evd82v;c "eK LN08N/_Ί#// $IBc۩DQt: xãh2 kΥO;cXǟHO6RDBzYs}x!Ƈ<Lg&ئ 8e#oM .nkLz04&㳗PXFAGI= l-]کߒT|zK1[Br8M 3ؼ ~IM ձ5vİz?7;z76G7Ǟ{PZ mHe/"Y:2IMVw41*ѕlܞ3U>;D&zAͪα}չt_{Kd⣎nWx<vU+[iw); ʼn|GzXcHMnG'VB+-s!fl� .->zrCmGO spߛo|Z.TW0ac$H[3-~O}\d'hZ:r>XŒo2JZ#hZ D{lSb*NKmTS'k&c2{Mog/l\85n RO=ǞrҘ>$|<^.wh̡DtcpBdO/V.ZC6ݸ뫪ÏDˤ7g~G|l.SD$ːNijEduX5m1-EGz#7:㓥2mQ^] sճsyIAcd=WZHsfJc;k]ߧr/qEklEB$,MNy$|J }H<g wyAC;شϪp8~eu͙3gr嘱h4**Te5W~_1GɎdY)(u>voa0,8(l6!I~n7EEEp8|1doAXX8{ .`ӦMlڴ Iy2h4NgUvHDDVk&N:ӪU+bbb�x衇8tБSZ-ݺucժUǿ ķ.H<gj*<1\1cmᕫ˒=G.џ¸7vs_Rq.:Y|l+0XRe|mey?fhMd15Qqe4x~3ps@lϭs_g| =HFSL\\˿x<cWZ7 W;;\2:v}Lwo,cX2$K^\>r}-:Vv3;|Xӱ?~p/S'Wed; /&EW˻c z7<g27njѵ\">JfG?Sp&X{17]ŐG42 CԠsrREoJ❢(JYJS4 (gVIRIEQiuzl2VZ->Vy%#cWKvvVkVk(999:tŮ;MaaEEE\  z=&s hfɤЮ];$%%vBQתȰ�!CYkWDF ϐn&[v۫w̫]ؖGC!hGuȇu}51ǵuSNNFe2뱙xs"=M .5d7^Cϵ0Cxn0tgq@[Ntcz7c�t}M Xzh7{֗=__CقR8&x]n$8ンd=USETr\j7cz("+UIȠhj2Wﳶ+_kNmFXxVc 0lDEE A3`2jbpʊBjVh4: z=Zl2p9)e*2^ uz :zXR[&- D ~(((8:)EE]Fު|XC,=p(],ǞOrm%JH+r{g筧ԆKa,{]VU4.uwSq] D?d}o:hĀzk9?}76f|߯bEL[mO#Fg?ϧ~ ګK~5אƿxSG!b5+D p^  etk\ƷfJS<=Uv@n-.**ZzV rd<N�Y>:EVhZ-E!???Kxx8[oc۶mtԩ: fp*++ V~70 DTeOIiA#9D ߇NC(ZB 2Ӧm:oOfX,Fm׆ѳ N@p\/}{~m FtDmh?6}{MB4 (b;FP)?]1|3f {\VUmlWJrHYm姲 P\ِBԆ"Bq 9=is~rJd$M)7ʺBVމ@#-=[qI @D8\ +lW":ױQuD (Eoys7u=6.FlGA MPF7SRD^!tVث$xrOKKmkɋjqؕ>H`8XOQv;w$//V 33NbBz> "^_,M&zҲRAᰣQٳNC^!*I~ ,r�E ZDLl ڵG`0(..ANNN9[5z,nM}X).j-Ҷ O0bX }#bP]ۿYwp:~1W&U3V}y#-B}HGԣ{W ?d+3>w'I.[FQZAVt qIw#hHnE(nj熧14_}Y7r!h9Hs~sTDi)rZbci]̯27 dFP\jbyQX6Υp&B.n_SazGP&PFel;^f:x -MkZzsԫhO@\e*RQ%*HDff&~YnVΚkEhKrŹ:t:qTTVp: c b aIs($EFxp:hZL&3aaDEEѡCG^t D퉎&((ϋj{tԹʒUsARܩurz#ʡ*!F=9rHHR[R];Cf4ff[}J 1tIhp$O%\V@iDו*@X\4V,GODN ;fK`8F='aj EH_{,LYR]&&#%$4r0ɡ(e9dJU)G6vΆ`t30Z>CnP;yir]ukYKG$`ᴬS=; AVW<i~cFÙL'SWv[z3KTX3qW[qV {X-ӹdp, zNttwoEAԈȲ̪U@ӱmvv;!!!@@(h4a65ZzjEf3><z=>ٌd$6&)++ @|*++1)nt:HHH(11Ҷm;[$iʞ{Zܹ6mZ(2{aS\R|TNQdڵsUڈ@~d\3euƲ'3~3|)1g7oȺcz#5{ǽ]Dd@If(">e6֬Y("9Ѐ{(�[Vft"$b #` v(2z?.Iah:ZlIAaETTؐe?GE )((a6H(Ubg {\\<ݺhlv(T p8YfUJzbzqxoy9.L_ 2YxkEqhLr#c۞uSEEEEEEEEEEEEEEE.=@N8Srfdff_Ϛ5k$8',$$غu+yyt:bbbWX_z:EUbPuL/Ih$##r͚5#11CrFQ(//GZ-v&hd2Ddd$}M6Ann.Fχ'##LYY)$'`Ν,ZҲ×&uϪK9Ȗf|"ӬAS<ﱳ*l- MLWyp4CUq_EEEEEEEEEEEEEEd.v�QX,$''ӱS'*SZZʟd!jeǎ  ~F#5ً1( 8~ EF`( vA8x EEEXVl2v;%%%.DQvF jbXEHjjKv;?p{h'(BDDXp!vh4ey8caJT1˦~eM.%רi1\J+z* hjx\@ nsL˖-iժ]tC9,Y~ڣzBBBCz :> LJNA$GMuӉds!v;U8N<Fd!2*HF#:׏ $$&i;[عk'A bcc/f] &c !3+ }8LV>USEEEEEEEEEEEEEEEEEQ)$ _\- . ۍFA|>]ve֭t횎b I_I\T#$Ċu#+0Z-~Mii)GHyyl%8K�MPPǃcؾk7� `<nߎb!11DRbȊ\:= %X2 )5DQVE$***q\L&�***p\?pHZ$ ** ͆aj\�BD$ɏ (\N|>/T#|QeX-AM&-[$YsB(J-_ dVu)�� �IDATxۻDFDʗ_};f=DӦMӻfmZr@<ySs;9r[sT+8T^FOEEEEEߌRɎo᝟2v]TTTTT}{H.ag@?""P@AOA ܱcy:tVj%66#:Lnn.^Epf Zχ":ׇFd6jMۍ 55Z&3N#..֭[,IM&bb1[,|`0YAVv;v@g2mTnB|B"ݺW$$$͚koW.Oluge'Rƚg`sllukxXI(,z+O{zɅ3<oDqsmG0v*'r -.%CrnҔoy8P9{V/l{U{>鮳ڟTT$qo +Fdn7;?6 ˉEV+~\|TVVRYn0̀BѠEf3ۃ,Ʉc6 pb̋l"&& ؄xA~ ߇_h\.Bq:]ddd矛^* aaa$$$뉋r~z*++ԩ�7nq]-?Ol=nMʃ\`VsO*; ɍ* /af ,~{'_I{ˑҷE.;kyglOvޟl<W(3h`>~#~zYAP5QPtL&4e6~1gHLnlo;`?+_,U!݇?L];9>aŶLJ=,I9N2)1l6RhRo.㓟7;'&"[e2/D6kFX+:5)u4\͌-׋~mQ Gm**uӘ>L|:|St3fL]eE 15nnnmD>=l>. %]Oǘ~Ov~|)ghN+gs|}wڔ*5ov/|^bg2>IǨ?fͮB<HR҇si3 KfdTjoٛQŸG- Q|+|z#ڇ2^yx*ϛ;v<2V{k-_3?>u53ƖudT2[ﻙ:Pll=>f 2Ki2nk,C EJSj*I)(zZ-^ݻwn(jfѼysN', ~YFZ, >rJKK)++#3 -[oLtt4(j B֘@hh(�~׃p8 #2*rA 44ۅ^#$Jp<x8&{mïl\RhX8˔ik8a+%'ӢQ2Kao׫x,Ni??;=`f־6gҏxǢzTz>�.2c;߱m/eDvlE&S9Ugp<Yi>t$'^Cbd ͎Tb/:t00G>Xp]{LQc>{RF=zMFzhm pN|vPe.A zRDV6}IcX MD=G SI7n2$ۺ>u5ѝ_2nai<Ag`|9O>Ӯ&p8{f^>~b@,vo}Ki1?.mz~'^×/%35>S쬟�/֊zQ/~7Is_gl8w䧖Rf<qL~s>^NC!LU)&2',:dr|s~#ڢUsGf_:u\j]nfţr HpS?{\[ Bv{0i#`%je۶mt]Ȓ%K~]v\NJt:a0|5nBPpKLƮ];iժ1Ȳbl6c4*+DEEՔtH# %JXXN~~>DFFR\\( x~ٵk>ƚ:HJ�mOqs&O\w ({�h»0tue~O% DjJOMXإJ2VA.alڏ/ݙ0'IAp!|ܙN/}rA_yD1AD� %^z<:,kOO8݊gpԩ˹=!q&1xw˹|ƻ\Ҹt0a|,xTo H5wy̼*8]^佝~ J=3ѵ7Kcb {KB[`mW?ƜȳChw4ɺU8TTS6f W oNΊY# 8AKcD~xɳגSF 47PcaI3J)k%MJg-qf[Uim5cl޽e`f޷.y۝~i8B}m`|k4k;5ժs%m&D1.]Z]%95qbe'> v~5YWP%JtB*n J�cl_6,^ŮB/ͻqus0= 5v́f2lwƑ61^ms3jL+1ǝ =Pe/x}utÀ /;0\noo\N?iS&g/&&a{Dtr*10sלyhu#DnίO֟Ki10\IJV/Ζ&\W_D4-y+,(鳞cRYkE.o_~kzaŕ릏YZ5ѵz,g} 5gDZ] 58~?ш墢͛\%B~ߴ Nh,#BU\OzFS IAAAXV|>6&bt:h4 $ո;L&S "Si2X,TVV{nڴiCV2d˖-cŊDGG"IRE)pD<OAkF Ai<ίxjKٻn5{-xds[#-}' C=72W^\ `_f )wov&$V=4͈wDfL:;m_|If"KHLj {9$tNQ'1:J~E6O\ü"Ƅ p7_XiF?~^FfhnkOeI"b?mw=幗]=_u3Lf3y̙ [KFL'aJ%D-ɍvbykzFd;3Bb{fOFD$P&<8 ̗x13N:|Y[6s(n<S&u,Y|s:c Ҹ�J=msG׋kC_{ǻ׍j>a[Lk鮱 |Ў* |!&}PA4#k0{Wf > JL\ //tz~ڊCj>SQ9YD~s}>jR6OYkj �:G6sS1XЃyy՛<?*QLv>4ܔ:㓈4nA!!N֒qu - ;sPۚ[U/R_:> cX; 沗rAͬYgry6Ed/EV/lc{=:QPԍX/]}MѮw-Q>" "A!"11(T'%zH^~>' <J2 I2~Vhp]|dYd2# VɄ,bz #NV"6 FCxx8f Ȳ ؿ"nmڶi/OcHDxx8 ^/,^(2"!xV_F#ZI4;O,wMAEeʸt52.CҾ,^1}b)6YɌ=2G.BZh B1 & q.Tef.y; )E`R&HP'1Nו=wiv3zl{9ÛCgᎎuqxxJOOʄ1c0FF!G<Fa$4"er\yZ[,װl:ܺ;G!S%v{_Vqff]׽aV|iIJIx(}cEڒu˘6l ҋ RLņ}n/!#zvm쫬DUjƶpL/?~9-cJXtid˘ >^gM>_ĺmqgᢽĎy'Ʒ 4 xq7<) j~J)ڦwck H;jMy,5cmt?PPMVf9̭i\ê,J6a'ڟ'ĝ{co:Z7qqUh1yqOp|@t͛kß֟FxFMȶfvȠC/1y VW^p^x ݇ x]mLX²XrO/RUmJ+"jD ؊K3}k)?R) ts(Ujg&b dF*QQtRTTEՒV%99)Hc;U< A~DQr-BFf3$Xb VFAA>dgeoqzp($`+?ZIĚlW* Hj0A1ҥ/ڛ$V+N)սO!@DfۅjgDž#:Mo)f4V�E͠rrTO9͌GLM=oz9D(ߦL pa./ZG~MJ/YVt{1++zgPz;R[ufwsI!.A=)&�-ۋփTSo[^YAt:F"3)|W,#c3dȠA 4Ard0}d4(-z fMPY]}:FG[}^F>4kI!`+FqVԅHbC^.ک!gTHY sBBnS{<mڥ\wg" SQ9}ȁo8P<E95hH92ioYU\2lÆ cبd'>(e}7R!G֟n{w�4J>}t)oϠǓvQu1}{/I,a6=+Mf2m:a ;<B JQ v^׮`^QT7,JS- e3M!BL=93g~5.n=B],Ȳ͖n2"%%IYYfN:**vD(DQ@UUEATUv#aI2~iakRYZcp=O#EA㉍jxٵkWBSm۶{hUraWz4E1PXhBmT5+ eb֗E;zv6ԴwnzHK,2 9v/A lk;JVB2yeN\8bac5c~ōp82/:,# Ůr4S)$Rg"1'Ges#SxG/:&ϒń 2bmGjVZEII9>44 ^nU/h̞FS0PQTT2s�yYNۯBŢM$go H"B6w5QAB>4>GW~/!QͤGsyټ<w�,Ρ#<'RYq3^Z=o!&diW埍xIۿ <oSE;NOɯ3ZE*L SxqX0>[pL~JwkN$-B ǹ5tT:e0W ? x~?8(Ɯ9w_,S?>'eIN[.BY~_V\hf;ul' X%ńD'EAZBQFl|U$.v]›sԫxuV"eY RT۔%)/r-[w 4t <$ Q PH̅]86%!..N-BAFb0PUf+.W9;v줠"6o_xB *YFi "ٳ7A l& ^PXsSELO AЀ{S)P[s]xyLa'U}g"5\v97 5M떻ټ-|C';wwO]?̽/p_vM& oق/+sPC+B(Ta3|_&5 mvT`ʡuK_ҊIc`Bj˦$ޑHݛVEh 卟t{p g1wĖm5il,27gp?)81Vm:*IY^j-1xػ-Og9PVN3H9::$Rv8YJ$Av�q/LZL|tOlKWTy,}9сR0tg陔/5̫rVzEvfp<ƌfO/W1㷯*O `kّݺѭ[7u%r߽":a5yxx=ַmyoTfC<6;-df%E<E:{ gӧ3}tOʅebkoUnI]dj MtںvG U_\gUkȚ�%%%Hɮ](,,$+'֭[}੩pvA j1ZZZJ(ED~?%$$$`61͈XzZ+]!IUCcGn`_3l*Enrۍ$8vPB Hf=MU#Wj4:{{dwpRV+C�&N}>|ņ"䚽(g>*cԸW/RIo*GB?LRk{-;}> ʞřUkIuI@2[4<D+߶uƦi  3r cbv=ZQlٙ9S / -PM{G=RkN?>&O}let3%aҮwGb|'+Z FHGkme悙BCWNkg|e;OyB&1r}y5l9w4'v!(\U �>qig[b }ތc%Y|3ckDB[eڛӘ蜈= &QhYp 3Y1~gR .CN6cṗx~%#;ٽd&-62<'�� �IDAT螑J�i|/k)ӦV,5 <;OHbϥp3z(wJ.x)_˪@?nr�ǵ(^E[ZqBv[9k/w&]͖sahT,ݬ^/K닦pqGCcÌ+.gF}|I b~;7Rˢ1eFu3dCa,[7Dy9 f(^(`64<)߆JzF!ߋٟ^q2jalow׵uȁDliտ`͇ދ,S?g[l=F[Y*;VL=̴#"Ԇ˱4q2|;C'µd4~d¨ꕩLξ٥<m&3Fr Bp_Cִxv>pNRPS#LӴh ={¦<ڵ+(!"Qt1[,hh4FR.쪪 �!IR3Dqq1`UUd9)go]M̲7l*#[ZE,A`)wW={ QB~JaYJ0mfz|R"_dj{s~)˩Vgr3..\`:>c[8yZe?/zq=Ǵ QAp8&i9A&_i nbLVu b=?+ 8?_&Ġ_a0 ,-/Lxl`NA}ie�3]z'c_/^](2"{eEH6cKIIE~[}Y̝͝BH8Rr{srFCR;`Sf?ZaA h OY^ՏpAl=9g(#Ľ:JQ|0v$E_à�[ϳ}R:!a�^~γf<ˉ_і{ .Gb']t! ˳3j}|5qPu岩o]!v}88pfqИ1Yxip$5BKnaIkR).gb6{n6jijk[vih~߆s¹677ȉ|#'4t74t "#o5C^=CP>p&$G ǃW^q6H9Y^|!2}=p%̠9ٗ#>FKN>S srTU%ܳu(ߜ6#BɉJpQRZ`]v nw}gMHR8[jZEF#.6mCD|>lvm6)ܶbdzkN֯P(D~XHY'"F=HII! yyyl1X,IiI)Y9 TKb "c…ERβyL~ \ɜ֓yLpü/?`~[S8HGGGGq1O#?qNuttttt|4sx#h!/Abevn'..TAE|p2!E`0DY�IB =fEUUd2a20MX,%D0@UU(..f 宯~j|�.W(`6III!11rL }E\)Ru΁CO+ �B/{੣stV2Lq`Ϗ`ܗ/:::::>ײ%n7?ttzu +ʸP! o,([N "I$%%a1M$IرP(D @$~?bP24Ml FD [eL&dY#Iawpw-n( j(DE1\+MSA �8Ȳu/++Rp#"s{WZi[6m owgݖC~ơy(\3b/9N~ʕ0TD1Ӭ3l;+x=m* @�IYbۇt( & K(h4a21BK,+h4""VÁ#n~8qR0 )hZE&u!S@֠B*TUM|^^@8RYY�xv; FΪm4F߫gUG ::::::QW<ut-=+<UU&l6, ^7 [eA|>.r˫Yx B})n+n~b61LQKJE ( .KZ>pU<_SjDHn.u� шd`0b6b˫e(obΑNubaQAE ` KrWTU, .UհZ! li0lLp&vI"RQQ$,+~�Up=B*! J"Uhʘua17,c='`0pQ%)t ÆyoWQtY-E,}a&YoSuUE *PMB` 7ABLfeHLll IXV]$Ix<>�~ b."DQB \n4Mb [ kXHLLfE],U⬌*P9p(Jl6Zb0,xʽ¥j4:޺,ΛW]MXL>M+)QvwN::::::::::::::::ato*pYFVaH!Z-Loߞ |>p7^bf 111l۶`0n$ a[V v BȲhh@RR2۷v1vx<T!(u . (D݈@SUdYv(Vsq8vfޝg@1= LgF`'Ν~c|:ĥL<=Ca*ZI"+ՁȆuz>:BpXeW3˃ Ʀձ&\.qu8u9-za91i>R'IIIA nw9D4 Jbb"999jlrv1STYrGbw$X,VL&#[f(** 'XAKJJ "i`D}(F{u"; ! ^Fa)$ !BԲ{;xPR|vX:f_oyxIKعa9]C'ٌ|eFK (m9o:tF4n nFX::::::::::::::::uP~&a3BEͪ1=ñ9Cԃl6b4 Bdeeѵkhvۅ( 2(sg2\.7F)"# d`$I={0HXVYػw/(k^d]WQF 4EQHHH�TF�1v-%zpFC!&]bcqtKKg=\y;XBAўN/kN#TxAx\^Y!*z@xAvxjB֩ۙui7o` b/)ض#{UhQW5bS!n$#?y7X͖]X:^0 6kG2k,z^{xUq~M\6(rieu^ kvPLR2pepZ{`ϠC$@e핳XϸlKyl(҈ˈ7qQdZ$/L1k^(gժUG:::::::::::::::G ;H Tj gQWdI&.6DCdddн{wDQM0$(,Ͳe˰G2[}b,`4B~$YF .ɏQwI0@8#{8ђ ^YE\@.]`OflذORR>/rPlUS�n{3ݎ?@c '/3Ʒ?KnAr{Whё.Ȭ\l4~.iC=S /Sd `"ֳn,6\Kv\w+LzbO=PrϣG\_+c%lI;oGŸؚN m㔓b9;=cUXO-e̛y塞1XՍVYy}XBvZ1cr`۸3#}T6|/7clzmu@iL~r[:E9cUui$$c4@h2*Nzz2g]\I^^Vb|B Dʴm(AL&-0 u;*97T EpO),z|^ Y1 x"!D㒊H]IK +3X"K vg3?TdQ5AjZx pz1C\`ͳkρ6>v3!;QĒb�D͹ٷS+~)#k%Оzg,-TѡW!ЖNMzDs/ᣯv3M#& zE>>;Qʊ."�ޜՓ}Gj mٔL]߷g;ΛҿJ20U~6ziFy4 U]/*DGbf.WɈ@6 ˏvqyױSsةS ҽ; !Pɀ4, -3ZeB T1$I۷qϋ #e|~?111x4McETB  e3L X,\pmv;[w>0 ]}BjZ*P0֟awv"Vg?aOBxQ!5!LqCylR9͋X3!C;F.j]KgYmn%D'Q_ ;_gt6w^Ħ!g2bHNYWu{[q얉TGIq̣,pXZY] ߦ}Bmۘcd +KJH@ݾ z<bm4B~[L=/ 6gs8B"TpI=utttyɛ?\rZfy4 ?>d$.:9q"e3dQXn<3߇:::Z/VOڣ `4 ̐ef>_5.tzA>}ر#&ł b6EPH /u]( ٳg.h*IroAp8 2 IR5}BqqWfSRRa')%$k.\.Wԥh +*&q].Zv;xk Z@_L*T7q f~) )<SڅoyYlS^gvZK&&d}furLfN_x\JWi4j8Zs郰v*8Z[_L9h!!IEeTE ӒDV\rs[ӡ�κdռئn+ 1}3x{Fts:v4Ҳ߹c4{/ͮ mqsWW_SkVm˸9XrǕъdշf;aB!/>tt'ugoGX-b8f{  66@ �f 믿شy3&}HOnc </ 8N$*rFTT D$( @�łd5l1H+U^իV#UViJHAS5+U \5Afn*bI yQ8GA.yJ,cJH{pʐ7"6x^# ϺEψxu#lG,}=>]괊)72o_nZI}MN}m{ 9dI%^WAԼ{�erMl&uD7kD5a.Z)?}<ɄF>~32>�ϹWXF"gy5<۟hvJ"1 -i{$W]{l'f)#޴qͲ>~G ^$d\2?)GSZeY7o&,zWALim ǎfP핃觇߼8^1/_N|<룣Sm~9FL'䚮(}dS9DD, ;J1$gw4kͲ#Rz3qꟾ;X}xrxw%o?~IUƬy%7[+f= sQшOxu>{EϧoR*ySXr8`{7QY^ z3쒫315GMjQ﨨"Cykn,YB퉉Ece~՗lڴTvFjj*qqqȲdj*;wCbb|XZQU-[t!2_ l6`R<Oy$ ۍAQםpјju($$$jfq8 4-ZnQ vp¥ 1UӔ*1=+@sfVqtmEqְL>,[ }!;,f͌ydkK\z g}?obpt삗 ځOݵPiZhNzm�זwrnLbBjĈɬLZh@n+.gF}|IMr%F=m{ s1!دvVJWePߣZsvJwqk~VXyˉd 2nT67y3wK0w�<8@,ҊRFG8e !Q&NYǀ^6T?ħ30𒟟<@ݹzDZ5c#tWlhI>4}pwn;jv!X@?v<: (-&vҧgc_s-{4DM@np3m%@9y7Ng XNj&, irP(w} &NQwK?'઩1*.;h]081wѹ34NAgՏѪ<-V <K s8:ɀ`$)sޭs,}(&]yX4nNt}]cƖx~.NhWE_1m<2#VuT>W.{Ya7(?/ߙ,k 'E�+d0;83# H=ZVβ?[sO7ú^ՇdFhHԣ[x=YåªQUU6mfF @c6q:jՊӢEZ$gÁlpr| LwRP8CW)^^O'fxz,~L&IPJd2aݻYɔ, fب5 j>$QMCE'{".8nS}DN6H5OeېќPY1|{;?wRh{RR_sLz%:Ϛ}�� �IDATb,'~JbF[z҇@NS價`%uo.ŀu["iS<o|)%(ځS 1xtzF$7-? H;Hl~ _bX C+ 2ZKĦX>{n ّLFx Ɉ.W=Ó.S]n䀺;Itх,|r.π;Z6N VTږfVXu_СCˉ?x?"d аۧle)ާg l>r,m*5oLf)>E]cY+X]Ip~g ߻3x<snZ=M s2c}"g?<۫l{:gWT-fGxTŰK>HZ<3~ZǶB'~Aq1e\"|ne2<yZ&; pGAie(I,#Rxxb(YF@6=~rj e7Ns\f/ǖNN#=F%/͂5VbKY7=;'9 [4Z4vיrDr_BJm2{! =HT:Gƶ{lh#_~c|<l?q\}>>$)9Hjݕ$�TZxrv[4fk?gwxaBp_.qOPX9U Ѧ>ttȜhC"z+W1tj_ueϹ&!23/;Ze0~;w͞_ƍI.1LC{LRv.9ɑkjΕ/G׃qkN4wnl߆-P )Xg)g\̘ac+a/j רGM}jQWJ5j !GߏrR,XÑ$d233瓐(`2(/w!33Sd+#)) ӉlA%bc ޽ YHA2Mdd4INNZ`Z BL&�$IB (AZH DEHTAЪf3_g<132ߏeaܰ[}VўaW?İk_PgOǭgb&_U :gF_v֊V-trp3ӥ{Z^bjk-ZڶfkܕX}?S60Sn}cLpPplRVDz]p7.me]up߿4uLJCZ&x{ru<L_7nG^4(۲ږ/y<#w\)+.:.øl旤 @:C,Ĵ5ŷ߳^47y`T�>mӶ^w%)%+~'e5j2-Ϻ@D\$2o6w׳m3/M nT4=6 O0*E￱-a 7_Ӌ8@B:V+ٕ:o%Pw^͗906mL%Isg#"$&8$;[ޚ,S[s32yhq>^Zگf䧈i2ɊY` FM==Z̞>)wR=ϝ'$ 4Z4Oz~F`] MxvN}rϼ974$.Y봤?aW|:5k$ VGgkѶܤy1s:JI &>ttȜwLN1}iath9Gp5/z]"x qd~v5ЫDsISTUC5񯢖Ԟ}l%WK᧤15ޭe%85 Ž$#0RHo!_mLȗ[3u7k|=\ףNSq5ZIV%%EtGӴHL@$!ZHٌ$E .+jm1 qU[^z^G4fg(PHA$B, )j@ ɮ.H+\Gm^QzE+,HF#^O9n Y)**BUUv ij* 7KSi^!/ivVtBظ-qC&]?*>ae(N }VqS^^[oSO>ٸ+gy*eKdǤFDùXB?֯J'1V1>G+]̜akg -qӭL~9#zx g ;U>i\6Pt;NmtdW�tUذQ~Gmjٍ{v|ث%2Wt9?O))'?Enp ϯZs\6s08'rٸgnn[cZ' tog%/ 'g *R<\93=̰e|&RF=a�ޫxyl4p\ϿEmldn.;5'lWLCn=&uW[+/# r 13 @P mkut=C]σJ҆HӞg::KŜe s2g\/.~YZID2۵5$ӆv"K SP?6B+_ҳ_pWY2AoӘ8S9+E$b `ҥ2d_})>>$ j<*^=_.7>ĨcupC x԰9 cLJzk]Sti&Q;ve7yl6c41E 0LX@X]QUۍjl6 eY1Ȳ0 a+L_f3@`0?K~كd&cr~Bfx}>\.ͮůbzԂ7_ۛER:O@*fR9.p|0o;h2; )WrZVqԶDa<kv߂H /} EƦG�\5_dq٧>4|2ڈILڠkx86,er͠ja_*ϔf&LS7`ǫ1+!}(5dbBS +f.5B>(b0Ch5=#3Ȉ5N4tѳVE#^ !HĤucWsiwytK][\XMhUځ\ ufc޹e/gppY«\͖qưa9VuYI#d njgea '6~c>Ft:Շ`K'_:ێkW5юy<ʿ觩{=_g5rMJLcD|۰³r35Jk4E;H縑*[N/":D]C__{9r7} F& vzԝ="U$.BۺuĄ-%v{8`Z84%"OӉd2EKҒHB"76϶lIĠ( EEEdYl`2$ HLL {EQd w Ypwχ%555j9j20ÏhVxAllN`n')9I6 "eLT3!@j%Ӿz69*EgF߫gUG Q@LLLԽĴ>9_eq zV@xKUK0xzvi}Q~i~c11vGni 7?ӺvM/NZʯ#,J8`cuSs5ٞƟS6 T 2Ox^MWt$b1I5%#XBn7]7$-QQ!2p-"pW=e}R6r{O|gv~'_ B}Tl.|۲nrV#ϯsE!@}cd*D[^o4ߜCoIK⍛<ٸ]>eYҌc6-hӡCe}8:ExM Uؽz:\8^`&IjW^nEk)}woMWTD쳾^/ƼzH OI.Đ)C޷z9g3x(l6E)2z4-F 0̈́B!F Q(*K\\iX4 ˅ (lɎ*ȗr1L{$aicXp<OM|ԱcGӑ$ Y1 dFQI  PM^! {'̛ӦqرYY܃&X{<"(Xtwݓõg{]sf`wvnouas e[tߍ�.ԣ'9;#&xܞƷ C%Q\>չK+I$3kIZ\ndҖǟA9dv 'ߤvXRhն-[eZEېk)c͊-*je^ېXFS) 2V4O fRs/YU|`79>ȋ/Kr /UƜ_G(Qc\#>Vcѕ#<9X]2(ƺD�Qcb©'eYs{<;tN:kXxl̘<;b߇1+#g Ƚ摺nGݷ-N -bґ){vn{MCޞΝ;rH^ZzBujrp{  ưh6ٌ`  TM((�$E|>l6[4񐪪ƒB0GЊ vQU5*GXAEvŞ={"q<EAA%&&EQQ111Ʀ$A EgJ詣sѽ{w8V>ʍgZq۸ {c_=z4i">+ضk ߘ2!żovPK%9_&Z1]$P'<6ۓhnV+FtICiea9|:#w[x'$y�jgDž3l#̸V<Ӱ~كJ �?grO쑎%Tʎ]FzٟflCf\{2OmCPPTӟr)<iam5ri%YfV OOR9ǘѭ'xHĄv٩E7'[+dJnS)[0VxE%8>)xw_3v]VҶM#ίsИ1N ߚwf`Xd*4-]]m}BGٱsµ1޻k#d@TlYUc~X!Pj!K00*S#/Ϭ{n!  ?%E ;V|kĘk<u0x?6>ziK;4J>C;64J>Mϭqm4/l`'[ozddž˫{mӦȆ"9˒?LkKz:;OyWM NrvB^ e*ܢ8@QT>e,DōQFD٫sڳ|C mi}] 9y]y'(:r<~,_H]OꆺHۺOӂi6vyVO(M.5G}?ZfSXx<nTU!=,S&!x<Bg)Zht:tȲ/QaDCp8It+gaWx^;''@B,{ TeExzX,| `b0M=ADUQEUivѝo@E߉5Pp$ʭ&))ѣGӶMJ:Y <8IO*mk4KdG{oe2Y[IV2W# O1u�1P>}csPj6cȤ jl�  g-&4FSGTuBoŘW^ڵ|rfMDѠ]s�&δ|)/l j~ՆJTHosxc܆3M55_ZC0ʹar\ U5ͫy2P{4^ [1<<:9,{LF9̶׳TnBt yTlG RѾظm¾bW1q էWQ9."m X]E4S)]+˜OhhT>BD|e.WߵDפIf8/DA0Cy9ۭ}40셹^]pB՜OMvUXgN2p!4"U潣%=|/-ܖ~'μL|`E t|b-OucMj4ϓW,,֥ǰ)fs_K{0_[Veȥ~T!%ԩ#PYY4kY9r�)))<x~!2ёQ V+dddP`/ <"͏?Nl6\Ϝ>}HjժEXX/n(;v4DAVZTwOll,QQQdee` ,,~E1|nv=~T:(tjTA6m0}qCc8y$HDvv6*ȊUQ_t:5k͛/~<Tۅl0R%TLWͦUPN1vΫ vZѶYyi<U&>MNqfuRШT !]ʓ%54f.(-1(\.!_uI$ ǃ++xeA9Ett fA$44 BBB^%lU(wPBCC}:Id $?2 t:q(, tNBBB. *ADDD 24lЈf͚ (Sb阾}?󬇚+o<ӵzJ qdso>N];uSNtԙ>3~(g}ˋ^Ѱ\%J{9۶Vr[hhhhhhhhhhhhhHXGzIJϢsyYڽ^/nfyWq8 Q@+1}Et BCY &((%ق`d2ⅺn V �Y d2aZ,+^ *x>P."eV J\5\YAߪW exݴ wM݃~Qr֜{_YΊ#Ic>?<q~.ŋ<%8nϗ7q׼hKT\ޣoᥘn_ƶ-8&wp,o"B rQҳ0e8 "6[>^\E(L裪*~J׋,�x<@NYl8> M˅,t>KNߵl$I`t"PzEUUl\@O_fw*(b1 p$lb N+'{JvVblwMڠ7q"Ӹ7tNtԕ Pёܳ+v˓e(lxvJ^Z4yAڍ^Sk} σvgtt5?M2Nf'$"G/>0qmמ *KLbf{;2+�� �IDAT{=Ʊ>K=Lw<:PNeL|.dĀWкܶEžo=/g?_^ڦ-J^΃0㾁v=]6Qsm*]kxfM\ߵ'\n,444444444444)[hhhT)+S}=U!2". N@ӡ*/ÎjVZWuUY:N^/| vQDQe^.ӈs7[ f˧mʩ'ILF@Ɣ$Qz}[קj l6^t!+^B9G\UR>@*ZWaQ4tϞ^@EdN7Z- (DQYp})氺S+ρYt] y6UD(4<U8szyk875 +fDW 57xKKвZ YʨϛK|<q=#3'.rn`n#rٱl /V&-sVpX25>_0n~ڦ-T?X27T#W2yoM#]'<^Y|aƌåVH>|ϮoTg8g�* 111Dǐ!222SQz=^E9@"䴻>OO)zq8FUd2MVV ӎ㈢$I8N.^7`!~|rJx>Sɓ'hN8*4,HQ2v֋|t/u+%�h# KD%Uэt?tq~Fw7#)z 69|v,|]y0ɎD0i%XLnùq:o]ԂU$:Mڟܛ+k<>lS_HhTZU?T!%10zrmel:jCM9hc5,t7r(=i[ί{- iJ Ϊ~eZ6PV}/R T|mvמ߾wWՎd=$>_募 تڹmuLޚd=ޜj/.UIƍ/444444444444444iY>_zt:۷j(X, ZgI/sza<N_lP^SY,�]n<./PF |J'tL&#^A0[,zNrPY]^ޗvSq{<c ^z8NA $$i 5^ˬTes3zrI t,Vm=@LjaOgvQM"PF9dW'ү40`V'G{_DtDHܹN"y4nJckWv Wd aEvYJ #sW}_;sG{||S@۔@Y-G[tve*]YD/V!_m<sGTSK;n ̘g-xe69gt:tz /FrQQˁA}JQ@ppp ;dB! `118rre/ۅ $URQ7+A*><QuȲLnn.:x>%l\INNx<nTU'1RPUeC/ύ8}8 J(!]fq/_c<cd1w6)$OYRP#_Gi<a_u1fCbњ%< /Xω@F*III!F21HGBJ |Fj`JBB`B&3FJ2%)"ā髙 .6RV}_/;tJkcdAY.ܯi-m)* K)ҽTlQܹTVk:_C֭ AUUUF- EzF:111~J夠�ۍ^GQb JQɓ @uSDoc61Mt:ÁFQ.'zO |BKϠ \.Eb\.?Ι3gdΝ>|KXX?~_hKetK;ifvx*"3O9K<TҪDžˣBߤ+@FGpv*47b 9}šSKa~iڿchԄdlz4çks$3Y6Զ]+s(3S<ߗq~£hʪo9ۢɍJ7oXt;i'رf!ӽUPmo҃nƯy}Fg䐝MZl'Tv³l6�|ɋT7n|rrrx<8,j"aaanv{kfxw:~Ʉ"+xeb)Q^/(p8lxC:ΟP~H<O1enaBz^Gxx& Él)VePQToJ@\.J:އo=>1q( VOâijQxfޝ FWx۹gv'~ɳ%O1H Ҋ^uY!:}Ζ57c54ps7r!P_j^ ظ? 1G0X*RFGoܱ&,$60П߶/o͘F1Wy&ncRGȌA>3f6opJDo[\m|R F*G7jǜ_w0ȭ)L�kmgj]?ZءK!Tq&ٴ$uSNر3`YT1Xsܸj^h $ z(~+Mٟ4g#'',HKKCQp8<yUU9~8񄄄s$I";+ Id@9sUeN78p�?^,&$ڵkOff&�h׮=;wFe\.'zlTU%##׿OAA?qRDQ+:ƍy+чW!/2lUMxi1Y5z'i?nu={ihhhhhhhhhhhhhhTҳ Fc\QJ@Qj20 HDHH8N~Μ9s6[ XVdYFQ|D͆h`0Pp yyydeehdՊnGDfs@+FUUzL&$I"88łnd27D#,>}Tէ$CEN'E^@UE; FW${U72;lCШt. \h%Yh gc_bu*$ ]UUfF%^d`#>Ѱ0((SΥ(j ȈHPp0&pz`ÇQP`d&""^#::ш,ˤ >.p\.iiiE!8(8P`TBTdv60F)>Y54JE Nwzbhhhhhh\v}5}cmZ +jOf;wQ5@懷}m</-T;JB Ϣz=$( Izt:="rp8 ;p\~sFx֭Gfhۦ- 訖DllFф(Jx^TU`2YDP\n3<}399rGphNt-гG/RSSYz8 zFgj8x�'Oa1 XomYy|l3?Ͼ~X9oNWn%e(ܿwqn2èNX۟¼ysto؊?]QrQڸ\AU|[ 7^+؍lkhAE+Շ]ٔxzXcMr,?ݾ2kICJRgѤEb >l֝ DA $IB2�hԨ!Ubc `#I"6 tVv4lFUT믿p]t:?Npp-[]v$Vn豣<y\_#ϐUd2a27!eeeq)_¤"|*+ >>ƀ˗鲠oe/hj6gW_`諬R,.ORXWOfFbyI]LZ4_M"f[�ZFuXp-yDpT5@ "Z $׭`?xvD%֦5kdWh BtRIq[d%φ71�kf'2J)q_FcЁNo(uݯ~d3uTߚ c`DLK P2XP)w1sW3eY{%X|oLl3{n\cb+s {.x%/_}E&r U,aPئ2O;>X1g;&;vzӍ,0?yNl 3i(cܐW[D Yzg+ro,ug}dahu#wAxZoϣ9xUӶw?0%Ow}ka*]f喳={D� +*L&3A tCaUɖ˖rz}q;UE'>@Ut$$$PZ* ɌN\+s7EՊA#77cioCE"""0Hb ȲLAA#& 6&&&"Mnn.*!!!X,f|+PLY|]5Ivt[c|/ޮ4Y26+Ӻ|+a/qm1q`+X\w"9Q0hlOX>.UOpd\{ٕs%xy4(vUݾl%m14 *NeWshhT&|?2g@߱5 Ԩq\l(/\;Kۘv˼'\%\SպYȖn {h"D 3;PJ79�ݬxQ MA<4*O.ÿ%&(mL] b8Qa{j=ƛ#w(FarkzV>yF#_j?b$Φf236qi15/+vָ(~3F&v-K5y}\/ _͑3qAa[I%Ixv0w|ŀX?ʶd&T-r&1ސJޏ3uE.mZ&\ ʡ)Fz;<7FlxUe{hhq@0 )-|xJ;rDZjc;YUL|IZI<rѿE(U) :@AE>O't&TlC>BWpEQEQz}JNEV$IB x<>^dT0 X,Fc p JѣXyHTd$IIIԨQ*:22UAjj &6kF:u ȑnGדC^^_.0V0Oٕ[@ngQr֜{_Og>3U僬~n>GZ=ÛZ$.òS}R ʶcm%^I4_.r*9s&V1߲TE#JV6Ն S,zGvy}CʨSYǕJ߱…0\s msMRꗥU?P] ໷̖g%;'=#�xs$]h Zƃ+^d xyrvÈ*~}*[瞱 o˲X.%QKom>ĉ<슑d%?F.<MM">E8D Ia<|_w, ֙ɻD氥5jpXFwp0qrp>)FET7mfi7!-1>F]'noxTME{,c1HKJ?*bYcb[x_8'U>Q c^'0,n^"oKsQP\ߓo</�͝ۯzbj7%�#HR5yᒢk%mfw|Bi0i^Wt=иThcRCή_]c�ضʨ-YS9 P5Rr']J _jVڡ2qzgb/R5b-Pjs ħH]8EׅSNx`Snŏ"v<l|rGOA@]R{o#i.>L6Űww']Le|QmyErԎheoto_QBKF.F$nr7 ]z}5\ww:Ȳ^ogl#I@$}|(/ O|\<`00LaX BAQ<>KΘ`0t:x<8vϝ>(UU9rhEYR9V*nZ=>kÆ"7p7ZŒTE= ߤdT [n&cRiS2S%Bnc_Sٷ81˧@BHD8!0G7)%( enފ4:T~(P=X"NBo*Nrǵ<Rv)D],4v}o#|8Њ?Dǯ,z|6?n0s?g͇<=WQ 8ٛz >q/U$�)@pǕ+ ȮJJP-Lp]#9ub#0"D\[jg?ojUl∮k]Mo_nh$KK$ʔ~0GŖ}giF4-1}ƃI >ςS ^2 VQC85 WTUD5?vp2a$kٕW8b$Vޘ?D&S^?c3hNΤMp!˦L'b\b9Q*'Szˬ070mNG]*~4sJ\l8cLH [/oYWA@viu­E^Vi<l>†OwpGRN뮡QYTҜ,uL;L9^ބyRE׬ g2v̈!e*mmh; Vv}:K+뙣kHO|qIҍkGgz<7Q\-|1]<>s++2]6)Tg-@~3Y_DpaY'wJ!nϗCcDXYue( vIgǚ$s>EH_w3r~&yL土%y-R9R.Tr H:ѧ4$UU0 (ϕ]UUIxP2,rx<^GvEQ|rV9W {eը$ d.1^":* s0qH& F= A$22}qiDQg]7bAvgұ:Rqպ2sǝ�籣G ѯHl6E5銕\[&m|މ[>;'#ޜl9JˇؼF<=,q/+ $/a:8Iy%>)u�� �IDATl9j=¼0L$ZEryL2j˦U<AޑV`/=1eOl[q/Y@]1,؀W=Bz`%]E^•}a<1f y+ܞ% 3!xvFփ{^B1s37mio L.^b|_&LJcVzѻo/: +ffHFJ*gr$O$A=ʌw;Ff ' k)r[3%5C˦g~kHh@ԦiJׯlEjyM?l$wX "09ܵ'(-jcڴJE4A\$X\N'Sfq}c&xq22y[Me"/j6o[S,379cY%-q :K؜FҚ8掆ƕdiA`37\5z-i\'48Y44.U]M)ϊYm; U)O#yf^?u2NO�Ȯw /.w$~ jErC/`3㝳r̷0^?2$9&4 y}P;CSPz<ol@X5a*oKc[$8" <f`{RW]rV˰%=Uf=DhhVÁ'Qt"^Tqba\. CS,DEr,)F#AAAxEUA3Pd_i1FL&# d `eE""FI'( JƍV-NfV&p8ȊLacŧ$I+ɷ^ۤ{ys*NdH018nz. f9>;Hߛ/oLd_-c||5(ofw5-ŴX60,*Ϭۊ/NeWv͎O+f>ّHb5&)Z i]lNV`&" 1ѱt{,˟0i%XzojWCi0p*~SM3R F=ŤaDJLY'.Q!ՠޗ^DŞutwU:| yWMϾc4(I[GBqv6|ʌ;{u!bDQTT.ynW73k?.us#{edfQKrT f8h%_HéVp7y4Bf O9=!`\T4s>)SkyZg"oex]4 JOiޤZ_1q!]9kpsˍۗnMb*`Q(**TؠHI$9]kDb<Lo`y:>Eb7g;rK؀TG6Y6mokj4P _w5N 'B{qby[vHϘϝgF 4 K q>^kR)_{Kcbٻ,7~92Q'&ҡ`Y[liZ}J<R$TUtBXS]QT'^EQaaa]n$wyzkpx/{bSEDQDeP|^ш^)Yvt8lx<>Pǃ@eF#Ւb FNJl4K|B,'Nbwo?W\^6<~?'{܌L3Ӂ!ˁsf,3Mo|!Q:2ȷUJWVKw#KY|M[rh�&}= LjZ@�(yLTD6c~?c;?Ob+ƛg̟8I=~~5) I+[uJQ^2Rmǖ"cW@oiٸ\eط `u& ҏ7ēw~1DQ u_OfY*S;Sd1*Ud8bVƙ38@UQ?;]h,:N^H%I]P˔oӈ- LByTFITO= )q> R}I/8}W+$LFA<A`?ޣ2!dʘA_~ϯ_{;i snh[?ߥRy_C.q,/B$׌ <XE/$^~?1zl*U=c+@ŧC!.ZSY8LQGT rM_6^ά?-@xH^z6lYY!wQ@ h׉zƤ3lZy S+Cy1&ߝ1=GС*g oQiJ^zٽ3g�՟G$"{oCE nÁ`0bX|.玢xz8N^O ӻl6(J V'A@E%YQUqX�HXX^`jbCzz^1"=BCٳ7ܧ$Uժ#2;]"* U�W^EGF9Q8s#&^P:qYG9=IK2Qob�;FL&)F0wu4Ădn+=0E)Ad4CcٝP?|[f:9' K:u\yn=Fp=L3 syyP' ,2D#B }E79x~z6h%Q -@$m-8pW4YQ6cK:JB)_+/UyCyfj% AmD8xd2Pziтw8*1 ݆f\ߥ _|6bxZ 8x4>MwGDōodoZW'%V54*FcJJC-jvzO㪕?~=�7S DF@4j3|6K\;~ڋe%#7wKhPDl'ƦEƿJA0ڇ{R{rc=jGЋX44.C3R/6ͻ{[3n8J*NV!Nώ @ i\+لz?S3~/rd"}'!I<:_,xdRok&Exrb↚X^"^"cgy-RDپGlȲPK, _4OarVHmTPQQo 7AԳ_h + ]M9 -C -OU՗U:S%\*/; pB0ůTTٷ(\}"*JLC )gU](&<A3ABj^˵qfOka34=)^uq`d�*ttbѧb4Zz"#/G&?0C1^ө K-UԉAwVN\T/NʩyuZNeWv)D_gYd>�ANF9Q~&UIeH|[p_9}{LRr4;΋x_&xzƛ`[I8X{9|�;seħ'q %^L 1! KYh u}hwp0--5wZf˥N$GAIv~X7K@<ԩiaզUK}6t{YwMOh5d4bxx%-ܨ*?3P@~Ɍ]; #" Niկ= >xWl Wm.т]~T[;0ե~|c:cVMez]o"}*j㤾H�XK3c%iξ2gRBG_`,g<GqKjys W=<4>|e7sm8̎tvmz7gRsLF4<14eT֜,'ʩb(9ڟjn@A(c^k :5.'fZz޿Of{9rK?:5H Dp7[mU.! Ė5&EuT;+Ui]˥P4cw5<* {qKx ֽ|[ oC@Ii:1]0*9㞙iBƵ F@!{4yy/! ]K#!w$z6WHF?O-:'Ueɡb8S>{3v{0iB_;g7,߉nMbCDɈ.c$s%|InB=peUr,:oCmG y-r:t@ݺuAU9y*͆LUUq:(S(?:m]UX>rT+N s HVXNQ\ <|UT A&{=K !>.J-FQTU.PQS`-AAҨQ#ڵkw#(;{ EOʂPW[ӧ3]/m]ϻaNN_>fYz:rXx*hڙϏ9Ƿl!Zwo33 %e_PƮ?&DQw|rs<o;ZKWSf@tkCtV5NƝd!ŷ[}f1$6C}}qLd tM򏲸3MZ} 1+X1H\_|lJ)so"_IڀNcgpߵ?yP30_'ۧmMw?JUώeހItRÕю,|b_[0@㎭a�Kaoo0e IFӷ} ELSe3g&~dë3^]~%Ը,xE3T:_OΡ|cJO3yټߛc<Wk^b/"ɃaU^$K8URZЭjTpږJWlE-b\<RqhUJ!1g/޻+Xr^Zs>uZ2ҩ?jQ25'ˇ}׬c\܂->>:A:N;!=̧۫hx;`!jm]xt>/wl+r ds.@hdx2i<aoφ PՃ."˙NN)jM1;h\pg>ڒ]qDMak ޟʘ2a51 HZ2y&T ipjS$+FYrxL$W-L~Op : /&&cKNa<筴Qw]7Rh,R3a Pߏ.,,ZFm۶fvލQRBf3gȐ!ME9ccڭ0s& f/ mw:o6s]D #O xLZHjh(#Bi߾E*E9-ǚпvsШs8 ީ54*2-=5444hW; 544*mFihhhhhhhhhh?{&E5pWU' q�Y D9aD]QkvìEŀ"&( $g<+zC>τ[uԽ!؃$)DÓWB!B!b"AO!B!B!~Ut{BcO@!B!{i)B!B!دHS!B!B_B!B!bi63YZuvWM^:ŀlcOWG!B!BY=_ջ07e7o9U^XZz/j&j %AP(?SO?ƍ9A,B!B!ۿϷ:|!Cf$hb~Tš߇Jגժy):PzIf.ڇ} xfzx{cB~4O]*oVEӞ+TBvc wpe>BW=[grٸqnk TyPwJmSIMqNQ~-vl0h'e4u<]{ޏ]ڡ{p<rq{tޓ/ا"b(ckv+?LE\~XVk/\x,;zG>zOx0m_=o;r +?6x~uߺ`ϧzHv轿ų5esǻzbwJڽ}YСo߾UrUJ%!\O4ܪ9ixܮVZ M&0NETӒJ(Xfҕ{{2}Iھn> ]=/R8O`+[g&fCzG uDȚ*u:ƺ)pw: ȣq栙y XEe2p 11f_?CJg Q'9/Od˥ۮy2?|%;mS Dޚ<Aۃ+gp󚆾VMgbUG RӀSGӖ}2YuH^bn+5\O?r;{\2v0ïhܺ5{K a+r\Ψ攇q|4Z[U.ঙrlζQ}m΢0iB? P�MLLL>_o)GNmٝj'<>Fw.^uj{>ŞS7߫ ;>9ĞTqM=Siڶ;qGᓦ깾#z{U,^+]p)p!곮z=2ypzJd&h5~. ^<^]y(IM o_7f$mx^X'[g'X[b`ƌ;o{3TUȂ's*߄N?^zweC3;KogxӬg&~x^965]ߣhySUS4bC PC<Xd}~!.C#ňY,]EF]}Jm vWl/1bS)SP*Q-^VFi.ZY5 RhNjeUVTjx ۵2@hZY6%SM'~ ?myي! sn`<=s \q6S (}aM>{Ȧt܇_D|(͝wK =׏`j!*߬v!W)`*mwlۮ鍃Ϋ^7Z<8W^kQst n\yM‹xkynqǜƕ$`yb~+z o�:-:'%+mF≮z&g]vX+B5hw}4^xfǫcU}7_m(7pO�=a}(6x{hEwKyigM]Y8ycqx־5"r^߅EykǝƕcsIK汸Ī <Uh!/_w/!c ldW?/۱7_r-Mx3P".Ens | O9μ/v˫R{Z#]Y01^xrw7Z C1֩է_Ns^0sB!Bz.cnZmGO%iھЩ\sN.M1HA�� �IDAT=ټ4M؍nV RݘZ-_՛J 4"1vHz( GRXe8 ]F pv8.#T uQ q*T01MKjT,+%+,ʢJhϪ4pq"lljo[id$#MQN]n1_>8R4UR;TBt>A1S/_&Fe-0C&혮?On&*o6Ip>m嗄(g;(\ͲѬD߼XQY}\W| ]J|RO  Gʾ|~R˻ݏԁ1i8+!=Q?� Sv}6;7R:%0絣{w_ Ix4Y|j-'QOg|ơSδƽW_(s+ᰊ,{a,_�pWxF&^/h)<'JJO{sX< 7`"~z~|+63z<~Nc>y'/Zκ-E/9qmX;ssl: uWK{_|G6|r7>-k#i->|xhaVwU>vdї!ke\;NKj|:s˘bt8lZ"w:Ȗy foeCCvǾsqOΘ΅Czw3/8E,x)2EcǑ]#Zǯ!<~x~,]>ێ+ 羛Zr:G׳i׻}_zΚ!Us|%OG;5ɷ\s1;-Oyío}ĪQn; i҅g\ߎJZ*}Hu9X0e'ρ>f?ȣ/ł!\vڿy.e-<[5ѢƜzqEߴm G{㏗ˋKZpÏrI: =(<}%^//x˻{v]?:}[-ON8As|~LΨj Oh4PxT~.C F]q:?rZݢz笫S|^xō FsJ(mvcڿϿ]~֟~g]נg5<´mggqX`qfgUL Hp,Ek6B4lq4VMT(_<սRulڷEi$F"䗔+wi~R|>@Cj8RGB#hY]p=5nZ8W�0P*SG;\^;CB0[( (*Lr<;- T~EOMuƬpeKn[yX>s.J:,Q~Tes-;{ub�FvoNze2§y-i(J-'w}"z|)7P)!|do nt'6 jCoښb~<6dONhQӚ/hxcѤ=cvh䃉<q>((foYLnj�Yh*տc}r]/|c<P#?knZ5'>=yܶdu>GNAi<5>۴+l Ǻr^<~ /vYu'|gwKSXBfP};?Ɉ|5F#?WBtIFu7gSbRc_糶֠9sT?0_϶Ա-1YLx_|l:~ճ2. ԼU\u2 @`�ɠci5#?*idE}t;*hfo#ײE4ocX!hs@Uy@~ŜUS灯~-ox犜Gb7+&r I1PWza!qVB�-!i�j{=iMFquݹ嚻=&Wn&^}neMyFW}yέzSZ6oYqf;{%,`'v܍nS'–EәSDkp~8E*t E2|՟u~-  ?ޢͫt5% U-4+yexnZdz{xm5fkQ)irRPDp)~|^7~/"P zJ=[DoZ{i98 |.HmX<kRwH;4޿к\Iy{oc}+g^bw;]i-=8Kt=1ЍxJFb0Am\M* %z!dQ*I)Dl)= AO h)t}>玧fm4dlh.=ƞT u3u0Gʥ# <=m2Lc:GU(Aaf7cн= 5cnjgdҶ]:beNn]&W:ﬡǥs9@6/goZ;/߷nz)3_ܾGf:iO/Ӗl |2]:Ϲob"eO7ЧS=_ 9%qg�o+tն0gsz8+X$Fw !,;ԇ*<y)?5?5̉cKhvܮo7`~ciWzwRmLU'>]?ʇo`DjV|k34[Õy GPr e$l|c:":F}H%uTA< U*]gT4:ҭ:<S5Qεvߑ:! ZwzG tKYW Y=ֽ@m1v �;$l_qN}IGs]Ie-`̄\1F>Nmձ朻98.sǿHvNjj^44}$珿o]ZgsS8XChbZ dNv:zufPӕNӿk[˥K,MzCdŴDhb-䠦.57H# hZ$5KL3UUW󡡓ӈn[бESjAV-h@MТ+[7b0 s1rSw|֦(].*~ռ&iO}?2P㉶ +_Ůy jb0ygt=To)oecE#vEy[AK}s _6ɰGr5Yï)Sxch .yp&v4XEOFy7|3Ӷ:kW(/a#G2rHF/>-ٺ~=I!E7dgR`a8帣8j<9ĉE1kF([ez+Ze@aAd*/]쌾a 88dƟm15|ٲ|8cw\r+>zτX<N{"2կö�A~`՟, Ae9W|S¨qm鬝G6Mu`3٫-e=P9pu;L<y>} 2 أ!mGk]gaw# ջϏ1G3zhF\"{^K:d}yEh6Zr1Ci0F~kwm{)7צdk?cW1mƧG?kaNIͦ;~U2^S+\W 7hʉ' BJZi>@oC_66=r¤Sjn st $1 +\;Y O"^=ct;C1^;e;ZKB#+ .V Z{_CI]߻Я*Gʺh)/@|�ʂ|FjQi\0Yoʀzv^^7R7w&jk42gSu+zys+-wO# ;.N;}}lг[2fβDȭԪ@J((q':q.>0Ip7:oSsp[ޗ1ܮ6�gv;_уw g Fv~[XB531B`#Z'Yftk||}H3wdNQI׳vA]yLp}Χ>΀GgXN!??#Xx^K6c-Ǟ| �ljݤ%\p.kwpݯ1)<ɼqm<z`Na%%CnE4o\J!ūl҆&[e38zMT FTZ驴cK/{EO`=cZ>ն]ы/䙧N#kV¾F4־C|{xzOm rGx<}gȏw<UzhЩ1tI楜3-ޟ2T;sLǽ߯CP3 /۵sI݅K֓r�-{C hViWHon&]gRI'-`_6,6{:;SgR csjmZt4}{(b‹` Tea4([>I\hM*]k&pҁSY9 PVcmQ/\YQ+v~>=ښ �?1 JfСtZoẂI]9=<|�gs¿m{%MZNsҤY}Nze5׏zukP.xzs&z)K".v7_Ji֦ m*~Z2a12 nj=]ѶC76/{5e?o3 =f:Gufyk|4Ar>;rVav^N3~^,`˪Tb|o X]dXO3^gqT:K?b+I9�'Xm:׀ǰOgבyws<3#kB%3<9_ɇ&#v#[ Ư,xUfr9^<wvp"Oὕ Z렑ەȁȁ=ѨJ(qy_1^|e^4I&1iÜEƈx1 yogqbayX^UA4WtkobWMlفzhslےY_p<DF gVKȂlUhlK6 elJ&nFK=EzbW,IdmgH?2OmAp3AM1HbeZJeǣoƉh9P6Nf tOus {!{Ƭ%/ hpv"lch__YDlB<Yb3pqF';cdWC ?99sQpm)a㩧"^]fbV_Ƈata6ײ%\&$(Bj&V-~"|ØZN)Si>~UM9w täS�}{Ytsݓ#:/K^7Cd orV|"z$]i&Úhip ms>c XA' f'oUnӎּ'Ld)Av1 noG)øehV%NQC%hP<ZG>FNy!ujxvJ1]}l5achg�4gА<s*׽ПlG"Kĕw{37Bf7',h SqZs3?cc;>-v>&_Sqq, u {>;/oy_GΆ|pY4FGk!O _oaU8[ Ҵ0y`~l�87ty_1{E[mzyy7pyie8$Fh?_û8{ g}'ޗxx莑ԡG6^r?0~ *FEK*1YmLgxxK3 6?C*n+򿺋q-[e T4_ɸ1gj`*y_sHŴ=COmB��^ # g9@uy/ZLg8eDXKL]Js:ﶄRzZa.⣗ݹ=MtB2թljz4#{{h?̚<]h"i6ktJ^wLmIoә\!ʥKˏ<!9B)i6J2R -YWJϪ+nU7U~T~Ա{6ӛ^12eXN&l7"Xo%%x{vCOgZVH8 1rZ`d807+@9nx:FKP# VyTgNև$z[\Zy\y^²1O!{ۻ 7R&ΊޘpvrmF+5*DCtK..W f/i,sh]Ƚw epi,shb+fm۹J}SO'#4O0x3iީ/q1g^\z-'$:7.N:\iY'ګL9~'q z9 ҇?i^in{ۛMi;]ǣ>`|f6Ƹ\CiD7-{=_7c衹$5y;:}sxOs=kڪSV_6[)rsF &1Wqx/\xǃ<>;VJ1g۟͡F|38cf~tM޴}%Z9q;<FCjϪCbؽ#;o߼9 ir[.gH 4efk| zQ-@}X;HoaSxd@tpǃ*Ԟ\tye;sƝwsơ^;G4Y c9^:$P&Fx{'12hu |EJ~ͧ|Z$1:p-qr]ww{oEnF^ e7/pX zP˾dϱƓтNϢ�` Q'~50қҡv9^wF>U>Pð[qmJ#;bo]r?P6cY1Yгb$⪉K0Te[;ҩ㙉ҝhaCr g=/L#YOߕ^p %.Õ `C8c@B!J_<~[6rϵbSIClTeYߵ(]u 5KNo;6TSpZgc8<Df/}q!B!b7-9` x ѐrO5~*$�|ZCݙV3.v=BlU8S1!B!ػxW^wQ, k*a>umـ:F1�� �IDATLGյ>+5�I4#8C!B!HN gCw(cpjޮ %%[~I8UZ=B!B!Sjn Th%8]܁nKdI2E5%4ҒCɏB!B! fu/j54,ϔ^]�Pa(U%iR%N,ȩ_Sv*_ Uz屿)JG�r z!B!Bת6˶t$듥]e~U {;5{2qwzD wc׀Sq2�1FMֳ\=iYO~AMwvB!B!nSmvD۔42g-'9RETz֪b_ӴzTYvm0 wow*rк&q^V@Uu+شjוHRO] x2)bG Lg;4ܝ;Ϳi /8a&t3{={B!B!ީf]/$2['Y P8jOI˻NLP8eY؎e[DBAp\(am8eВujh`]SX]&j\W:vWߑ2�:z?W{sJ^Ϝ\rF'OƧ/Hm'S|zo,ek+KZ]+(B!B!bնT($ 3UCՍY дx(RZb3?�iq0XԴ4 Å񖟎n+E쪶TWZI `;off}8vK>Vз˜;m=N{=0j] o#P67UX_Oݱ2㒍s.ŏta~%8Q~G`Le%K=<97:(*Hn%:qf٩ύ@}n B!B!v껷o7%1$P*3YUmێwQwFǧ~Q;P(0\bQha凩[~GUqGU׈z8j;ypzwg~[_] W YD$0lƭЋWexGakX ' ܝM%Lw%&rAǠ/YP^ٰջ>[!B!B]<Ч'M:;t>zB4p:eEl DZ+F#RN|Nhb&h:.H$mY.n0ُjח*sOh]ފ͔2Vg{3CW쪆];_*O,{|`= 6"os390L_+Ѓ,.B!B!{{T6ndObdĊUה%]m0q|J3:%%%D1L2-t]Gu,4# & 5emś^1&5YsG;F+*7c[',G'4<jق,@+[xC#f*\ ;mICq~J%HS!B!bPϖ9l➘`qDJ˂iZDc1lQ ˲lGA4òuJ)(f,.`۲z#aJKXBdZ֑/)89wݭ^P'Zt>WX 6pr"+ ?jjV螲ZG`W9%y(O@f*1:vY Nk -\Ts-!B!BO94�Q{{-+ER,UIցhiYCa"(2 |QضiheL˪hg,a:e?gm,4Mvq{'S%:: ƥ 6*J_o%.{L#,'D =-S^)F(o0 =+ޑaW=9N {M 5d4Jʞ%\5Uk޴ CB!B!>퉁;߄@_LUIƼS$lʪmQ ˅qlc`ar: AF\ZRB % Č"B %F t]G*uLĭwӇī23-s#ȋ2Y`:LlX,@mZѹ{[bw w1,{ .~ D~U{KO-i@)2Sk%Kv!B!BVxyϿFs勲-{y9Ih٘WVi:N]U5U|]J9XE(2-R ]p:p@�4|22|a M c á_Vd&+b@}u$Ru'؝8s'1C8 |vӿvuB!B!Z'K<ZpVh|LΪk^]6.Vq{=><.>ۍ t ϏeY"J,)%.ql )/2-^/>?Iu&/z^-avvL܇MB!B!~U݌x{˪]a֞EkTBfn-aB+lSӶSmkeiaǃmx}x"0\(,*t+B˛ʕI Dб#,vv"1N,{AӮ݌*Vv;B!B!b>Y]7G=ҽk{,լ|55�ۉglG),!fضqB[󶒖J0!v Kټv-ֵ]uh$L9ҤIB5-(]ZEĎ()B!B!؏TjLVWL1@UnYPTZwV}PF)]ӱmFq:lČKظ/:@*7oΊe7(ܼpy 4ĢQ,3Fb"d)#)B!B!Sjz&bӉ'.I~t8VXU'}puz<K|Y$ #&tDeGS14 UBsO<-K -R3hIg#X1Z<:k͐Md2(�@#|IJ !B!B!PAOmFCĢQpQR�S]F5=+uWU6\3m݋hf+ͥp(Ʊ=D`rh;+IircVJ6oLvN#|MsQtxn[#y%6*͏+!E<iA٠3؞B!B!BݮgyJ墨4s9%x<n2 hbٸEV:1f8 u p!R¡0Ei;֯va$/¤5`6۴JmIq(q&Ц~?=躎mZclM]ܽ]n-Pk']quRw57B!B!LAϊTJaY(R DZ]H$A jlY>'cyjW]b95 ˅:$x-Ey0aJJJ[ش..]{lAoD dCVN3<0.c[hN MGv,Lx V,K34=$ܭ[{TS OC{<gނPZߠ9CNۻ?F,4"8[a/|ȗMÑ0Ζ58%J!B!BYAOQ`!;x/ Ya;u;7Mp8U^YuM4-!ς^dU ]Hprll$�,2\MX:ʦMkfႀaSe=[ui>i:v8.ehV X&.]膻JWbL;(0p&ѫإZV{\iATaNx/_#z02r:{boL !B!B!)=KB!tg-""a,D9NER8V:D%E. È5ʃUC}9Jae;Ғ [7q2Dަ4jϺYh۬ A;d㦱ǃWز%L,hF|>H%YӲVE" D}hL^f0R1~uͥZ Þ"0� {ŔPJ#*kBtzK<#M3O]t\# =+)_=:ڢg1u(\mr)ӱM� C7bO1=O]o*0Q[~#6 "lڹc.B!B!շTi(۶),*2-G8J)tMPhXM4T.:%'\<AaH(88Ci0Q4LӢ$bոιM4_4J˖0yyylްԴ4l+&MHI!@*uPXIaAeD#sM Xi C_N,ppIuBlyxFy5u`QbIx1R|g߀zb]F/~ԟQZ*-m/W �\ _J뭐sc?o_{D'd81W(\B7kF.@Y/wu8^O,oo/B!B!jf,)lD xMP蚆kJ)N0X~ @OM+^j@41Iev˕bhH8B8! mۄ#!t U+nL;wag钥4nڌ5kbY1bQC- 4MGJ" )*( ab؎NY1s 5i7 b8a! ޴nLi^Rs7vxž~!`o00Oצķ0VNώO/|lOܧgcVˉu]wM?a7\htDcm5o 1Zug+۱B!B!jeӌ`YNYJ]7p tG}[ Mqlp$躎az<p2 t@ʂexxr*) =@/Kf,J8$'IJDz,JKJ;&CvFZj *$alfׅ\nRR(..qS\\DFfib&ۅR`)p"`˿{Y8td.p=?#b֮' i=%�' A"U, yh  lP}YrTU'fi !! !@$ l~ɀ̽k#'c%HJUNٝ{5stWU} LW2@}.DބM~ WS$|Q.z+B!B'%62rxىf<sd{ ʛHNQޓ{i;Y <BuCOUw! B,(=ass)Eg3#LQ055' CL01>֭[֓em92㣣LGe6|LOM21>$I6Z4mSҔ4KQt6zDZ}{%=|J9i05 ҄+֢ضw2R |ژ)䡹 { {od;s(pӅ4x'./7$ ]kt7wzG'^JX!B!O.Y| l!Ź =JirFkwo9ukm0  Рé0aj6 �J]uPŁB y9f!]$=.j41'"";`r"f&>pHOQj8cǖ|;\-[rmVi'ټqJk( 瞍߆ TRK䷒ݶ%Zu#;:1Eu{D?"@%\92S!B!x[46IbΥTޠ] ""cxfg;hXGmhxX0!{ >P:udf#".4Uk38φ(TB 2yF&)iF=T.;$IB>gf F<4< :n�5}:i=M7 ^N7 ۛO;xwyN A @풫$_H0;s؎1!-kڿD9SʿAz6EɯM_̮8Zwz eͣ{!B!BdhS3a;P:YƘ0L'-Z(;#fOkA^("QhPXQ2:Pt~Bw6RB2{ XOtFdVL4 SivE ֝c+84$MZ& 4yhZ#ū4iBTбyDEi|◾]J m׿L{Ch}'7*^dK.Y ;y gTQN~Ǎ6@ AvSNeT6t)7.$7r NTQbonx(K!B!B<i':?ǻ,Oi6;#s4MZi@LME5;MЙƮ5AbLu*YS+(蜘&wsIJBi&T:Sj3=( m qhMOT{Ĥ:Y}.횦UEmuwPod0d˦iV8Z(51C=+fA^>�ׯ7p)Z52BѤR)D y 2ӟϖyB<֮;}z�<\{%gȪ !B!�Yt'1LP>Gem4saXGC AP,Jk\ BL.Z$)2mifVrͬuR yhQëHLMNkd cذm۷h4i!;wbhlʎ<%lP*c|AZWdsʡֲl|`j}z&Eo&xi{4C#MۏBd=O!B!BD虤V k&bbGXMpyF\ kJCwv\7qRfJ5 OC`<&(rifxjH5$K8Y0X a9M唪}$6kSf&v15v%N 4%C$#$ rSxu',_iwQըme`jJCK9#;v`^zz{1MoB<<sB!B!`s">Dy\wW[ZJ2qb* 0& H JADkO:0H߸ #mVw:AJ2!ARdjfnsZ1َ0AQ*,/L񔣏bqϧZZf5Mmfv3}R�:}=u$&s,˰i8츓84Z&v1VФ t38a2oddv6e#zbR2S!B!K,T9fFX s6$q-P>VBL9شqJkz8]wӓh1Aܙ>G�� �IDATs&n 9T^zPPJ2ns3 ["wAj=cSX6&1รDmIX^qjD:NY6Q,IQeEz 1\cYrh:S׬^e?4xΝ;}:9 !fy$B!B!⡧³m&v<1iAGhSS#GnYGmoDj qLTP* $E; T dEk ޓf9c:VB'1q!:d(۠\RfȅLS5k [:(i,_Zc BP%);Z#h9+>RuXیV "@]ٔiw~ ]w!B!B,z.9cL0B_G(Dk;ff˱O3FOI1U3XPkMdhkz*}XgX8g) d26ɜqxt)K%J6-B_Q-a[㸼Mb*FŖ;(ڌjyMbbqq~Jňj0<f|r1ls'FGr3_Pq#jNRx^ 6߅te^Tko\-s  !B!OzEզLi򉜴c&iLSo9$zɩrDB&G2 ӖBKSyVDx&wz)EoP/G 8瘘U5aHJ!RĆeIKn\ +{v JjRknd nix(16RrsZ4wN vuPd(kp͵7qߍħ?^L!8oۯMy` [|, o9"{Cٔ</O{=<}D=_i~gB!Bh9D]QMJq}4 Yy̳k(EyvlRɘvj:� Z9MG_0F;{6$q7!YC'J0@-18`orYmW&dj2cD9yoDдZ6{jJ1J13Dؖޞ&U0piͼD!'DKqYO:O~QG7~<}{(uy1\m z_AϞJ7C?=.ORyӺ=%7_{Ȯ#Ӿ]/Մ/z7Oń5ߠy]!B!B'EC,bbgRZ>eڴ <7x(0Z0q+)Ŕ+epi4uBQILX[X><@lNOGCTFBHX$ I"|@[.[)2EvQS,em6<^ ieUOj$&kM#HvKj+ C8h DS� /[IRꣿ2H#GzهmԶV^ /ۻ6;3WA8ڏumJ!#m}Q:ֿ ΜHwS8FjWl*#B!Bhå9cl�v;SS0XtQ$1RjJo_?T{zV+ ,^l5I)brDD(<y¥ *Qj o%GI[)\> QB5сhMhDF1 LYM,qqԲ6 #cwm娾,<A1Q'2ªl2lkV6f;C!p"8 l-8cY{aT*=hh8ؕ'M^s :Rs[~Z7 AAҸ?{ G(ut6}Y"WpM?L?AښsX?0f݇_^sqkQO*T{[FO'y{ /CG9nOI p"&c_K΢t~wz~9W?hC)ٱ\V_֧|Z2pU/~Oi}dc9=Y/%o~Bz)Bkȳ/!yWw\C_B{Sm^;s(1~dth{(YS!B!,z,;K(chxC@)O!T*K IQA \nMZTs|lmMԧ |FkE=z š0@�;[Mrf O٢>Sg ۸: 0(EHnpzz8^*!̌mfqZxƻȣ�Qop]wѬיC`xh#z(~t+~+L{{C(W #&_܃wPXI6%譴CT>ސ_j+)叉oֶG;Ket _AL?B2|#;Qz!JJ=$y%h㡵7¬^J~x%4.| o}mY3_KZȿ=t}@7Oa^(}&W~ǽ!}(CdþWX~OYYO%~;0~7Ox/713"cN"yùWGPx'sB!B!`㉣aZ[$33x($E8 caF1xM輎kol>nټDF iӻPU?6\ʣF+Ed|ghhLLMs|];عcgc5&ghgeq/uT+%`hJ a(k9ykSF)jS.A+X;n1Z-䲩GT6+#yHnڡ ,Bg+ ~w?wm~d~` /h^v 6&G\C ^Lh5Qi ѽ1S |P<6?E7Ѽgbwㅴ~9KyCkouFHNO]رQOɶp# |fj ?=J+~$]{+nN|ɾ,=Hw^D}/\~Eagyowҧ"ٽK_ 8 qB!B!GC)V ZVFSHb0P(F( ΢l=l|:yV"-BZV2u|FrK(Pfa#V$ VaLr8#t9qp,M[\kV#e)WRoeHQgl &''H2:P4sVj:=GT4?J�}?Q>n nDB{(ʤ` F fn]j%1MP w~KĻ~Jҋvn"]?&_Nۤg|gҾ;^o7 ,� \/3Bu.J?$J}7B }3R}*>F9/t~X~[Y�jzq 7e%N{aN}nţ{'B!B!X9: B(O)Zh0" o =fl@3Y WmѶWiCO{0C,^* QJIѪβ}yȼ uP{&#)Nl ^wMjBb) qB6E;}Zg 7 G=x\9PHԿr^%c䦄lem@᳔o]۷<zO(9q7~z9 ,øB=IVE" OBeY =_� _}5+_1 眍nS55Ǎl{;ӑgKw͙;]sTPEһצߥ/*KRBt#y7E.b-8lq5F;?= w<)B!B!X" A\6qPRxW%ۡum:Dzi}#ǰQdL2e7~-[NR&N a\$c("2=/{+ X(4g4}Դ2ej3- A<EN-u+2cysIO("z8*7(.հ.ū|=zP7i34]RĽ'Ki\qb0§ŮW(aP7;D(IƇHκw>m3{'4[?@/hƘ:n.Z.&<"n.(Aܓg{m{DɯUlcۍ$ Or-{z'v}G7PK<ڣs"<k/4y; }R̅[Yo, -FT 1:I󏒼Z m'wn"B!B!x[4T Z+°zasƠi;jVȂ>e|Ql˖S $qD}'3aÈ@qILR bBEPEf$SZ& WgF|I/1 F1XyD\'O%y b ۴ }4V g-a3ǒLj&.-</OxP1?/|F/A?f}#;+Eињ4}2WC~J /?[Gbw}`3Ib�a^yG[ODTSv÷7H^>Jg]?(6ּM\ڼNZ/TWcmߢsGoלX~֛n/^OŽkhsd %.W>z(p#]nwi!B!BAM>W5^J` Ju:DwYk9垻$ XeJqҙo4FtT@ksGέ}; ZgT-]d V69͔FN6c[דiuCEN=BbmD啼cp*ӣqGf-4^ynDyϮLOn0>Tj$QQ~z_qduNakY5!B!B OoCQ gix4cX|%՞>J2R(IёlT8u#5>ep:™T9RZL*e&h9ih4ɲ&wo+RlL[mF'lANYu{ʕ*Vf-l_hMD䡠v3ˮS!B!qh˱ցGzhٙ(l}} D aa!Н=ainَhKt!U6kM!Q3"ߤnH=) & }d39LNr رC$C;V+%F+:՞N99pjx?#=xQB!B!d & A`0&@R t7,RіJk1hmPZ QL€@Y>[+y?솜sݥD"Eh ȭEh֚(i;<QOjS4hyg*{lQsf4m⼣V155M-%?9 F|q{h У J}~sB!B!xL,((O ĘDaL'0!CQ CtvjtνBL|j(:8Q5Q�WhMdYF` Ȱ2XhRcYN :vZcD"XyNZZRSj33u> =SNL@6-y0W|OXDdZ!B!,{{71 t`{t#JqVW{FjEA~dn{o>|^)1h;煣!68_B6OD(bMhldXԱiT"k8<N6Fؼm'Ai&VY۷m! ZpRs|4ѫM|h=;4/{h˯񱏓޶x3_Gxԑ[6!kA1<3_|pR}wFS֟Jg!,HSoO~9һPC_O&[FF+[Mj>[B!B!xY4 SQ眽z^aJ'Fv^k<@l}sfi" 6,TJic5rk €r L}V^Mo�R0 .GcFP.xmS~~N_ cYGr%y=Bo_njj"R@v._M0/EF]"w~~aắ8 ֦l$瞅1sgy'(,E?-٦%blsB!B! gSή9XzuyE:xȚ{~k0&aDMrPDhi|@hp6YKu0 Bng;neˆJn0JfppV�Z  ?gT,IDsεv6J_/}3_}Ak͞9ҾWMl�8Z5|m {若oyذ3c#A˫zһ3\M,gK[L|,~ԯDoI3$ocU+A*߻tkÈ^sqkQOz ZB!B!ksǝAb!B}#/΃߻`DPRRP0=5T5>B35<{-3334 H8QJl N<T1$ ӓӴm0>;<tH? [?Eڼ~}Mtp2E^5|UTa{y%aդE^�4IP4֩4#zq <2n:? ~so$xui~~k�a|p?Sb=ڸ|ƽ觼aV7HvZ??iH2|#;Qz|{ !B!BG9g,t !z5ҾܻZCQ/}=YFdf!񌙩)ڭ6XkfzFo_/ E=m۶R(  QF!v xC3^~ɹxjܸ|T5IxӞ e0g;^Qq7vo yaNtz݅_Qb*w|GB&.qӖ4ҍ6=gד^~-K ]OG.P/^C ^Lh5{;u#w݁Dv/ &~rnz'ǟHW{c-[ַ\!B!B<t>S-fϹeԼ2^'tވнE3[x|w~wJ!aR(TwA^'KS,#s6Z((K* K\&N iF0H"SV\/Wk/G٧؈sv#K0KZ #x ˰=^W vg}7f2L+E%ӏ~|#U\IPxq-X�� �IDATTtgj_.S4 g!w(Zw"mzоxj%1MŖfi)n`*_1$oҺ" B!B!Q`h4gG-hh}=7y7ܼs{\;s.Ɣz# ^wvw:ܕRn Xy @f+VRTR0uR :Bxnf 9!@ekƥn쩇H?O/ӛY I[Bc?c3c9џ)+) kO'h^Kk n'/=umzоx88{>P}˨at,0E^ _oԮYAQ8ltB!B!1nEpDp 5XB3b9|ރݟgúu{yܞt,k 0TTPۃzf0@ P(E^#ʏ >أ=5g~<Wp[6kvIt3I?s^ky%*hC]dW|ݷIvQe{FzbPE+O"zKbk9xad5n&\ߩD >̉4~6-ϧ?"=X7o >@:St�g- MzO[r#F<-DoBߑvATw.!B!B[pW| 8T,|E^{ߙ{>7 ,g}wbZ?:sN?7]6^8us|Ѯ335.BޱlfT:E0 Dg9oV{qpMosUo׾#'V<=i*%z/;I-J_>S1B|;CGιp#Ѿ{vy_MKEq5fѸDN'Sz9d~v[_&6)nUod E)j�&n&d5PO{9WN#ZB!B!ģFMւՑ\~׻8餓( c6 tPwvΎдJO+' ;TC ?wstC9l޴R}Uոƛ_็ wxҫ+Nc?Ϣtd[?;}z+xK>�5B!B!āFFopDrYZm":G5Xr?y|=p6tMB!B!XzS cP%F'Ot-B!B!#B!B!$B!B!B<H)B!B!xB zBt B!B[FFz !B!B!P$B!B!B<H)B!B!xB W^_]wEz<;'I9=\g!B!Bdw~4)x"|m &(BE)Z�4xW �[P QZ �B9;osu2( vM�eA\)ߩwzxU=(΃R(:u&i,L9/'ݧ$B!B!oW^y%wq#N� xmR@;O'EuCM(KnW~NJ7 u2 X* d톞[w=y 7VQs?4^)T)�LF7qWsi=Z1۹;X5W=CtI|k?�f/+Kܓ{f6 B!B!hssj5im`SF =9xCʼ{=Y^Ż,yx98p.ǻ -[wx cνw=]n練2G>-w2\Zl|'UjFWq?n_|.cC~kKؾ>>e{0J.B!B!+ =n" 5!o1,wBz!b'L5ѡt:#Zѣ6/ӆPtB[4Gy({ ;;,wOnwθOTgV{]mwӾ+*wu7|N?ys'sy9y;!>GӁc|׽#\�5Osŗ=G?~^Po:7]p'vƷ=%/;>|Woy z~3x?^]}EٴB!B!oE'37MlT ÷st�you@l`؝z;+pv{M'=xvwCDpl;Ehe;k0*α Zq l<5Zac(f0]Sy)[o <;QA'vwU4Gd̺v\w}&�W\͟Y\0,?)?_e?]. | 珣;L]y>IN}JtR5>};95y|C!B!wɒ+8~UR])nMQ)R HacdCfަMβ_6tVY3Tؠ%D-s}:[0;fwuvڡkvN N{fqn' G& }B.>":S_N4�)| ,?^^ $!t"=TE8x^bYa,R׽ffkNh)D=红=fIs$l`9m佚jK*0n|+_3=sܖLo_;f k~Nθt!.)LХ7.g*P6û81fs:?o]n95Wa'9&λq>{-K{tR72jžrΛrz6q+jG~Ko' k#V>kn0iX}o,fOsjf#}wpoe쩗p0~k?"}ic1c1yzJ_?#  qoZ<T]"$}R]VMfϔijBݥTˇu3�th&.*B5 T$̥gףQ8ឬsUk]wݣxժ.mYT@vvj(VM{Js[M7K~^尉qZ\(,+_g$#@G)Ϩt?G߾A.i#7 kSz9*} )ZJt^ 7O\r4Osܘ !YzW6a?1}*n h0%:˄\ ģOŬBw'|Cǹ⊧C Qq�f2#?%$[~4e ;SgQ=µƜ1ܳp%3<6c1c1lҳd:&b fՔYՆpgVoVe� H@›ձF=O2e#Plj)€OHt IV 0FFCDXc⬭f xNUf�qjJ+#J*W{n JZ=Yeey yAy?bt|w8wv{%7#gd\Ȝ?O@w}q/ɘ'։wmQm$7_k.ȫ>s>ۿp&[p'N7wms9\K>r@R!Yy5™z79c<$ >xFX^vX6Ic-'s~̭?8]"V%"V^<wqۙ_2n,tc1c1cr^ |Bjϴ16[͑Mk"J²q7eSH(AR }i9U]PsD<Q1 Be&lv(O}\a8lQʒ,ƓOA@VFn/A<#PK7Wŋ~ W{ Wo֞uTmޫ.k?~S& Y"5{rmsm_g;aneS9= 'r|=?ʕg*yxwR Rw},.⥜3�!af\ݴ->A7`>q섧o5 Hܶ^1c1c1[te\ejPM%[$Vwp %I!.!BIĥ:-ȄhZ|s+U+!*C@X(FOO@ TS~(zC ps}_>n C]M~„S.vϾEw\r[|64¡'Λ'^$v) Cw~_}53yݻNdnFn,ذY+bv؆k \iD"nt8@0U9<n2s趟#.=y-P,BTf#]y߳Dƍ  ~3>wkFzVכQ{8eJe5c1c1f <'W'iwuYo( kųX@,f5f*7R *cƠ==)ħUZFPFw Y*I">._.X"UlΦhB(B? FWU5T5kctc;R<?@`A|4 c}2EϺ5k&i'),eՏb3bF_z1>ŭ [`c'YC9z Q˖Fy>7̫=k;smvgZ7&`G ۓcK_@{x`_pג<io]7n=s+@1c1cl1tB�:JBJu;H a8ѐ$PhRCE�%e< �C@k Qdp0].DO?_X֯E$0@!׃sHuь]T< #> hhwУ ']( <MuqR= 6GBӮ*B =*_W8&secfw52Q(0Os;5G]l1-#7?nxsqc/y슳9&.bsg8[o~XKTړ܆|`u77z,=]+P 7a3*':g\(OVmU:b]+{?zƻmy=UZO1g=+o\ĢmUzc1c1l jqIb5[TmO},UjN\ִj6n,P~CЍR <r )SMȸIJT @Y@:J=0DNYYΪFjjvնy4{KAwgΣ(D}9&brcl>}8ROU˴=gR~リZt 4^Ʉ:I+|+b@;mog5V~g8t]mz' Lڹ^ͲD38ԏS=c1kn`i/:|wK\s[';qXxWRQYy@{c1c1#Ͻyg޼y,zjW|MJZ>[h$Hьr:g@sPF|?i6hGW-b u ~JCax8ro0HH= $èc7@K : >]4<# 4 C5ct0VB&T4ILť3EE@{UY^=g.b/g^2->/r<cwt?yy!yطٶh37F8x޳~ 8wc1c1fGj#R_-5?VJ֐οT`@O);ǀ8J(^XN | D{!̡qvи5gsO|1u^; 2aW`Hp^ѕˑDDfr(+ij@(lDX ܆k>[iJR*5{@ߟ4sΏo~wE,zz, <1c1cbˋ$Hq"*cT8EnwEbœ/5u0ԏ !+W"Ce/B 0 fUt!G[kcVF^}b&7M?pP?דVr  4 iرh@٠0Z1(_m϶DI�/Y﷐ ["$>4D۩YB0vN?l1c1cfˡ3+UAPZT8;5fA iP!_DV.G:7@G;R߈K"D=$JS*H0ez̻^L(5ur ?M$Jrxmi1R_IWyK#hTA;7B#Al,h xzX Y1j:ɖ:U8'j(k͋)N;vePdW+\1c1c̿-{,ԑifG+B.ABJY7~aQ GQ iKg2]KG'KF:v E$Uy&rr )p556!sD>5t52^y 9JtfqFl @)c1c1cly,K73+Sa <yqP�ZIuA$ak+Ѹ PTDe!'!?㮥$՟'D]Z_MH0}zqWa\I:t*tb$$Je1 $1SGi+Y�ಖwjc1c1l1T1h xbWaJ/B\S MM0,[Dec َ2 %Uv9dkrq av, =FHo">R٣`2A#HOq^8 ,5+SP8eŧQj ق&BVoz|i&[Vm1c1c+H&}BOp>FK b 6 \"WLZᙀhmY{"㧂rEI-c\m?ʒO!ٚp6y^w:jelG\ڎ+Vz%z" 4kjК:"Iz:p#�>'MJRHKI?oG 2so/1�D<+Gn/7ic1c1!R陶+p*{pI%]D 'mkqDghmFBArE NRzR�^YJ☹ '{I�v1yIrwoD g47#"WOB*e6K+B}G㽎?Yw<έ.e;w?xIoy){S�*v=3>cxx9p??8[ *�� �IDAT_WΛǼy7p=D+|믽1c1c̿-ycjաHHcr%Z(@mɪ47 8E둺iHھ=yJɱ3,H̆8T� sƉfˌ*Y@Lo WчQ�eԃzU{FkY;OMC<XYvl[wL=40BVd�x[xx,1E/_W>@鹎\G>|Ws ^0K-p-7sÇgxG?_k1c1cvpK/&ٲA@Ui ^z*aNVJt1 ۋry$Jgj* N~iz:ss`�JCs$#3D% LӠQaB8b/ySI%h�R]@ _AEJUqp\9#*-}F:_5mKK~Ʌy1AzAޜt٫y;WΉLJy"GP? BrxLs</=wbqQ$K_r֛grxS7;ϳ~{ t1_yÄg|` -rA掇)u(m1c1c̿-hVo鉲!LX)J&8 v$Ю UHI샲 E$,+#jj<F!@XiDFiV|3gv/$,OI[Yy4-L炊*x4%\8 #D ER_`<:]-I=MRnjלC_s }OyOJ}GzCǼt[ڃ&Q3U6[?1!YS+2cZ-�U+h3424 CbE>C滇X콼 MvG᩟7=9벅Z3$kClWh1c1cl,Q6p17 *0U=I!wVs cnJ'm!ɷC|pA=!FP*ep(GyٷB!Igtf,`Ҥ q߽$G|(Tͮ?BIH.qE:|y%A8rc@9 pEIN#՘�4 tѓlLOn']}.{A|oep38f"~;i5_qAo>1TꢫĨ4. jB J =c_U9ӗG"�W2oo==ZFEm32c1c噞"HVC/A af+A\rz|eI |?q"0Nk"A|!!(ǛALߓ.%buv2ql?Z\ڔonS(w] ֺ D$,Bj D~4ca֢ kV:ry'M.G1o3@7ޛ<|q ]f.PB=^c6QMcbm Rf80-SHm3)V&MmobfGxds,ǝx̷[際XMc1c1ؖ =\*JNN6tif?܋&UJp~Bu$5ontrKN mMtllu8uki@|@'_C!LCn86 []q D>*=Hmyt0Zɡhw,GrE"kv4}&4V0=_`}, *5L=hO='l<=_z3~{\D{g4є맷/ wb*;+Y[;׍Mk8*eʚ#B&LB쭾fc$1c1c״G%=M鯄D\(h*X(} Uj_H Z'6*ڈ #ȼ7R,&j`ƌ瞹Q/ZTÂGF]#A9K,P)Px - jH_)2mG{ד_V*#u8`d|ooVәp˾޴wo}t̃OlMvtp[9u!lX�/1#LGrkaڅc+~|bFp0vZ/N<!b2QVvl`S"L �<]˖Q26c1c1n%4sAzEUq WM|i 5q21H4EP_x!QeG[Ǹͣ++yw0t#a-)di8[m'TZ|~6DfsBQzѮQH^ fǚU~nOm0mw0oUx3x:S7;fN8e:x3E9f3ns_1_0LO /Ō=|mPޕ,|1w䏽5}7˸婍 y\pށh{'c1c1[M׳?˼yxl$FQ'p6t lKq JK>C$Dz$h#$Uo$7tTB=Q9 )RJOw,VH( kP^,HqusI\q gDٜZb <B02TH7WM*96v[ǂ ^/?_S9{㘖4(uϵ:'9Ȧ\wo䀃=w߱_=\1c1cv->[{6_YzDTj߃{ 1b$HX6$*9Hi*^8-q>ƹjhv-lj#ըVCH^ˠKt) #Y\$d&Nw%Or^Ǚ,G-RHU7O8yxc1c1GJ{{λ8e{u* "A62ԡZqQI܋M3q ׃<g #sȜG(W4T? ^V7Wg634d=1$n#aq*y4»J֌ jh�ȃ4]%ki)Y *]tS{'1^H3fO c1c1s4qV3>EҶ]OB2%@X ]K4. iBC]!G*igKKc;z&6 Ql$%GXP\>$C yO*z O3kxPҿB\fЄMNѣ A<Y)VvJnVe iOezK~K~c1c1rq2[[^iNy&tQ ilA xY%lkXpcv ]uZ﷞BDat S\T(9WGXg ԕ5""='ήJ|YQAA\M NlD � '6dpPmcij�"SϦ)Vi1c1c̎ŔND@6-AtS{V~}8`TqDJ~ŵ#``!$65ϻn4ȷV{(m;r\MxE=D$}OaBD svs+ ?n|R&M8yObx6R\m -he_@Fzf՝٢꯵$y31c1c1Ƽܶ\nI>5Aicu֧Oi MxBpBX<.sұK9lz{ΞimWBNDP  8A1vb Ckhk[0R=0!5 4&*/'VZIv66x<x :YVygQ{w?/vk;.(1}-c1c1fzC%@% >C 2BA$=ujÜx"Nm1*hh١e0/H rzG I$%GR|Y#ǂM)ׄA{0-$&&6"B6S<Hk�W H\�!γ@XGA7 Gi7:~F{OΞ_KucC_~ c1c1.R)8%]Ibp<΁OW,@!FeBIsq-8ُp>˩-FH>vĥf9 v$%G4h$C9*}ɰ# ˎ$iJ5]^{T 7܉"cuP_ p}"T*HPA)!- O*_Ѭ]W_Xl?~(^_eq+sыpp2)mw/rc1c1-/24"*8@RG\iF Hq4_oXQՆ53SeTwB2G$v=nDHJBRru\OW8I*NC. Aks1'q k#c'kC4A~ԡ0Q2C %n<*q?;`Jy\t72^c1c1Ƙ"@F"Ђc\X$G 9hTr# B]ih%LB2X RpPqbD .hD}2OgR1̓/}mCH6kᇈˉJ15>Y$̺C\ЄRBȥ!,sLwr/_ΓJNืF/l]e|KTCWs[>ǣɏaM�~׽L~ڹ^ +`uW 09G*�o,Xʚ ͓o{/g:~_b_^ LG|/ o|WhǾS(l#q ~ŋ1c1c̿->DQXQBQW$!|ZHo%hhBg&+&>Pe' -#d!9A#N)U@fO2GtQuEɸnzn"ڀ8ހjf-賺= q2U$V{$i?(M 25y>X¢χY}wO<KSP9iBOyFG޷?-OyD]�">Nc?w?샭ksLKئ{p|gmMO\%.;KOAV> kƟ?I' ~ i7F,|{y\wtVO]:}|ꕣp[<~f_(x\ <1c1cm]@}uh\!^edc&te܈^[ Ft<]yc�u[ >) >$r_ Q"E*>@_*TœӔYs<Qj<4Ea$@EZ&-`M??z*erEks!wxWD\)G_\=p;?*v?:60gF¢;?_n[lj'o+NهCVk4l$sԮY򺷲3󼭝ԉ J8rZn;w|iLm=8ٵ#';ፓZ'O0os[gmO;OdI3fok~#bZi Wgn2.g*9r̖Gc1c1Ƙc' Սx:t u%Gh$Aj[b EH4{ $QE/eIC3Xd_[abp!F@o@m'۱WH=O4.k&:|-0outR/ٜ�'a)D^K$~NZӷ`34|ѾYNUo‹~%CeV]| Gs8ăN<-~Bi`vFn_̲R~grkڿȊ H5Q߽L<S'3 Aiů\CM@R}m^g|'`?/_Kp{1c1cѶz* ^!6׀@�|ry BTr :Z#4Ap@Vw('{'@;4$ BRט0[:6aH@CwD4]|4iT̔^:}P'%D"yD+RZARYR,*@nӖvy_R;]wCfIbRΩ4p.=7)c Y]^AoczaW~:*Ǽis%[Ҁ צY\Mkg7/ao?oJOc1c1ƘE[ =EFuQĕ5( 8SDC( s5{$!#r/(wL&$.#$C"OVlH%ńxP�J(x͉t Pp+BXtL[Ã>t8GONQȇS}J4Iuz H;3]\/7i ,Y1ܴ?Qwr=ai(s@Ygg1|5H_J̧UkveF<^>bflpQ|QOͨax1c1c١ޮGA"jpGU kP]c!_MP3 W?\GV AΑ .,hdBԟF^B!I(xIe(bJ +SD$kaFeC-~sMC|Bp,LcGC8儩3y~Y+N8 [9?GCc7_Ng[= ,|MWم\U ۳^7~)>XHW޼rC8 m~v;3-{lvփxߜ>ic1c1fۆEF!|\$QzAq2 ԣ0>&)J'ce;"xZJ ΃/ 4$� @=gahA4pgM% H]@d)}x(+vR] R' I:t('%Txjagt* */o'ܯ˹귗I L-RԽf­s!em\N9 p_๶M;O\G~Oo.M-ڦpWrwޯ/S usg8r//WFOއc> 9-C{ڙIٟ*4O޼Coc1c1DU3R7o=BB %Ck1Cr14rD}KP@dԧNp1nB_8_&!@VbⅤ.JPHw�_$iҹ yshXp9ixEd:Q(L'0a M<L^{לvqwes>fgX1/x#<Y;1c1miFO!�� �IDATWU*ILXhA+I'er 4q]i*JL9 q hCV|)�h4qBRI X䕤Hő$ ǂ 8ȣY8ƽ xxan<A>Ф!7'q"*ٶ�En1c1c~[ =scfE= 1Ԍ$?~ |Hq'<LehRB\~4(*t|]'4dLTEGva/S!UC�UY"T6K%д1'$ 䤆$kɀKLPlӹd7|Qc1c1ƘmJO HtE]?r(.P7 "\u0;u6!�ByVTP&]S4ᩊ 5}=P4j48M?{Euyu;Ki 0J5$&Ēc0b%(!Remfqߠ²WhޏK瞙3gx]sXƀ Wb BOg4Z1)LЊfF|#R Fm�?nl)B!B!&:L;q`6LAeE^ {CLfaz5ڍTlRX;/)(4EXFk[dJC'-ɵs&C"@'�עHw~O:W8e!kS+Wnʴڐo"kP* 6 cm|#14%M)B!B!qgLUx=vd09l Lz-NNDj5ּ"Pdkq= c7UH*`e ˺&KIqHv滱@`QlԲbV QF !:8a*Nfaa*p AYfoo {z*B6{*k0a++qt9*ê6 E.B".hC׼.,m7_B!B!B|C*W�CP7c-8k`kP9uSxv¶ɀJTO~&û<>@E<Vv@-)gp N>6('$ ͏b˂Y!aYZcb09#ȏ])PZE161h "hXm1A+4<<?]TL3g#ݢ`ķ!H.YAqWB!B!u0zEf$$Bjo+fZ0Ä*B 72`Mÿ^kp( ]ѝBYkɥ4E!^G J ͎lQv>8NuZh7r"X@4:E'Jp6U(,ac׃vxϯ74,6m};.wZY38j\W1YW_ztB!B!7S)]lZuGQ}෢�7Qb[VbR+ NvkՏ7KV,\C_!A%-V1aSqV<fC,eb46WXd^n|E+CkqzVpJxwv֢r8>^Fjq1A "ӌP*�j72 !׿ef=y]߲dnkd[fqߙp&l cV|.gь}/cJB!B!wg,D͇FJiize([ V4,G-aVע%`ؠ0i$_>|y^S%]օ,r4v |q"PY@XtZ)œh[~"V .fus%NŤ4-E%Z=~"JмH'L%hȥc,X5i!滻o#mnYj=E`oYa]ϔf+q]1~ɛ2__ܶ7Yz 97ͰW;!B!B5ZiYEQ*Fк0\¢cCPNC*v hBC#ErnbËN$$9 "(LTNe5nE<ZF=lZ4)dOφ5-,hL1[:DbP6AYOn&4cqBl.ɦQGFP:>l\ܾV޽,;kʽ¯ǎf\| 6!^xG>¯cˏec{νM 6yn:ƍݗ&\Ƴk>,x8g?\f!<C߇ͯ[*2L ksV}~о3vw祜r{Xg6?Euvs̒,�fc97Z ͉G{;7[,c9x9򌛙*(Lͅ%YTDQQ)<r'>ڽ_c:Yn8h?v%jw0w`i5ߞr(g?ܰ !B!B|}: d}T)6]t'VO+֥PXeJu#GH4Wi<>(K & }c1!hkFA&Pb|  A3RlHl%hѸ( 3( Vڂ ZG R0UXc2>&Mv-Bnm0ŪXaVe52y?ߛK7:bdo.)вY3#|$:uȨS:'[xt(~6^v; 6krUnПܔKk(t';:LZ̿gJqg3i^||[=smҕ<sEu\w"7^|;"o/owQ?fs2qoBW+˘}/~N g=5ǁ]Rk{˼u}|=IKB/e/>w]2pQon7ܰtcB!B!؆:SGN+AE"(6l؀1aM0 υ lZl kM~ګ:~1ŖR5.&GiZ~)2x%!:jюʼnXg+B+TVP9Q24ErpBXb}"Sh!H[FEURYd3Zd&)AQE'R>:-`-߆!ƴu՝֠ЛAR4z4>sYqG3P :uk;Jr0cod ۗEUؾ/UN?5UE'kaQm=*>r31ʍlz7JIrʻ ᠱ;`QEDZͬX޲eQVUIes^2a{Oͭ?E^ cѥSop�ggf>\ؖi<5%G$^XN;ywzW`Ąi{z[s|ij?Nɮ҃AO !B!B|:L#>eP¶ZlІ-@R1r 7,C=M2p1fæ<cl @Zr ٜaUejpxn)@*Ⱥ4kc}sE!(7~CXm-ZrlsYJ (/ Bv{J`iխX\z6*Zs; CMq>r=Sكvd#nGXD% gl0v1+>-QQXq ;. N 1v;;ŀr(_mLhd,"ux*.%$>oqnfC=\g$-si=/n籜]!z{۽eh纚3ꚷ?9wҝQ !B!BB&l m�4n(k1^fhA#qt4a8,nm.axV4f4KL5S5GIoCB.TJfez_SZZL,5<m !nˀ$diȆ\O! *V YuDVC!Ěnf]&6*кY>c531w~EGq~1{^jOe s3\poѲrjYۆ:9ʫm[1}tÏ{Xū\̵7LfEQ/L_O$C3L6E*'jijPYv6V^FQ3ſ>\̚o~w[yъN$RsS˚ZNJآ%'.֩kX@ͫU;=B!B!uzX?>h P=YbEҠ\[$fq\M(?%>K+IYtTEC`CzM4ydfY̑+U$!ZҖVdBwԦ`#(le1 48]xe|B}MZXvAY`} j܊  X {_gKt% R_6tpzj᯦q6+N.Lgo!o#vor+Zod,Yne4Wp=#ȝ(ԓGy^􊕜y5<4N,[ ջg^6~*.wco1ֵ+dmƲgZ}xg>x{ʂF6QY;oI7>˅>mJ?\5̙l)l~ᐭokǻ{ۃKIwL?_OȾKӝùT7j>{"B!Bmt^Ѻ )6(塌V8%=QN5 uKɐL҆5н® -aPRռ0;i5(sebA>Mj}~"ZWӆ!.=]\dюr"& Ny'mER/W^ Byb ?خw@~{iT0nͿi<F.c4=8A%FqƵ?֛op5wrrύ9_<!G[P=s9\g…'k8uR+$*1Gjrn?|WμdnMzrjv>zn8:I'&2ʲ/8IJVg߯b++ʻ>e0~z1oMŏ9K4w00&^{=n )>53oB!B!uh8zhfՔĺC.?Ma:5(]+dž l34ckqBx%rk]PӶ,Vd,kBlj{ѝ+-jCB͘5 ݮn2`AcС,a:_ӈ{Z/c-P=]}c$�"`yY+֩!P1J?)JbXNq1X"`ފB##k:u"[s#햣iF^׳->{T7B!B!is{l0u\EQ.hXԭT~J$mmZ].iz�lW bOkř S,-Q]Bd,;ʵT&C8EŊBEڡ|Kv%Ge :p\ IB(q <KIC vvIwqU6ÉűƠJ9FH>J;FF8].\ a+c *vvB!B!_ì_Fش0~E6,HRAd5C45l *M2a1r�(6(vUUdSw)J@ hHجxs|Q }Q,;%D;+ҐhKتXUtFQԏ[dy; h�6DSrt2̈́~ 4ņ&_Ez46&F#hWcl=ڔ|oM| (?a!B!B0վVuֶ?1-(@)K1l VPP(( HK`Cv[U(dv I i!*Xc e-6 Cr H-UsXS>K*r ;2"'8u!3DZCzv]V'$KqT N<4~]]CP YLX:faTJ-f\7hGE?ulc#~qE_OB!B!}[rcX M`6`2->e|F5js J5-|+^&lѢhI;L]EiA8Z2Eu/{81%ǙD9k@#" rHt3DC"U>Aa$YeB5ǜ yCp!> p2~&n!6&́1Xku=6s0__0RKx niz• [!B!B|ty8N'pP|aPZXn}HP⒊*:b%Jhԅn"ޯ3qEkr|1tLiEsj4M[V9豻.ctɮѬe.E"TQuн-BTk[oEKVd(u-(6BcQ9|~~-* 0kt̃Z쪥Zp#8` UI_v/ ~r=&^=O%Xt!9!ADFN?@(\sZ |޼v</}gfqS s cѧrɝ/"؃L{wKq?dr`ܟ Oѣ=z4G7;&v!B!B! : =s-2k(PXk-J+vߥXw˻QCoq[5j9U.u zZsjr/YQRh =ʀEIQx E4;2:dBu KY~rit@ZD1CKsnj%G5MU`m-ۊt#&c-h X|6V~q3[F7=C?n q9gfx.!NY8ݶ=ohΕ7mmH<aƵ il@2<7n8\.4ͅ2-:$9?g089jM9{/L”)/#kGe#_Gɴs !B!Baim9lk(\ȣ(ſ QJi$zzDG -Xu[i0hGAN(JК%uV4ҤV+*8%#أm- [.1?!AY8Cʚ²yܻA{:̢nL)$]KW\A)u(SLd0mk ׂ֡zɢbPhp5~0c}�~~c@WxJn:B�+3mG'͎Izטz*&{{aߜ`Hcs1;cظ_0'e!,3}w=fR/ Y< R}!O15Ԥ݈Ǫy!ׯexܟ(. xxN~^/ڑ{>#Oڋ|AŪMsj/}c o]9x7g^߻B&_y c:_?vaB!B!v: r�� �IDAT=ReQVp<^Jn>ٝ5Q]fYYՔZ>,OLMqc!s0JTEF+EkxI4:ik5`# Q$JC  {ƀa@T;+6C4T49.*Ʌ9尡MsqFgH|ɮG'׶ ? TYG֟mPf.oτFlۼvO۟COCXT|7tC'mƖR?? k O!upzOd@o0jND7;F0<zh\gi߱w:~& ͍8y״m,gm^EroJi2ƫx\1aȥ\3FkY8?!7=3/_-֩sײQ\9yB!B!:U'_ P*_B) Z)|)p5]w2T&P 1lhjqb1J{hE.  } 4R0 &JC$4A% T\ns~JYCRmȼr4(uiGK =CжbJ(ņ>֘s9Xw|~af=|=?nSUKso/a|/_\ ?c禋L.4k]lͨm%g{s.C;[\ ~<G֖A\~`vûpTha-9=x?pދԹq/?`}&4ǝOԲ'/sedRil,NpƉ!n!l+}_E. ;*ϟ+; Pq;WSUٙz. 5հ6ː=_B!B!2: =dʆ՚f =5Xtp#u))֊|hnQGG֥oF<E5ٶDwȬp8TCGN!�,-@O]KVBfvb4eMcQxpk}mNKť, ;Ѭ^Z\,Q#;(e!qEYCPS-J[K mfl3[W7k!e,Y]A<x8?4w/e �eӋfhI$ ;t/itˇ(T>s+M[?SuD}jNߠa) o'MVpmM}e\x p:τC13{P2i҅OM!F"μL9Zexe\2gpe͝q5^p:޼V!B!Blk[ =8'8E @F$Y]obg]7*VaMHDz=c9 uq]hhХs& q]09s.0D2ɀ`d(lHHc=Zru!6 uڲs6EYah)(Vjצ{-PRCEOqx~Ty 5J+<kiX5P+Az;q'_<=M%5NTdB',Ylm}'^~E2mQb1Sq㻝ȭVr#I"RXiTT|m4 ą ^2`kY'tݎ?AOzÀO\qwp\E_ 4Ys;-&  XՉEt|xUۭ>[#1XΡ- NM4ehdqqx }eB!B!WjY0^1BREQC&`doΒq0b pp]uEYr3' >V)L 1GYA9`| ҚN!f(. imq�chZ,--! > T!@CﰾTS^# ?t(km7[Jl诘QA0VQi]E2b68p{+}}/@)s`v#oSgY8`.jd·|y!q47݇͋"m:E{̡Lz@@4ғlkM!_eI^l_Lejsӽ7L ;EX+,(ű53k^wc`trHѹ5^|y-"C~Eo~Os; 8$_1eX .b%g^t  6M:m s'ӭ{r³|lF?̆]8}yп^+q楤cB!B!` r-1ÞtJ(j ZGG%$g\vxb%`bʨb -?㐀 =1oC!eQ,C0ubP˂PR6lhJҠxo¿5Î,)a\]FˮC|{tfmQޘrȀU>o]X3`XsRQ>[z#=$cK1k0t3n1:UP8λzj =?>,n HnQͤDDdӹqG4e<qaXI5}kOffKW:F.I/O_n<IuҾ3קs31۴Y͡K <x'S֑V^'r#GkᔿtzYiCNy7?7 _f&7S==K4dX4*N._o94$7<(19>R)B!BS-%'΂9ee:5MSY*G찧e;_ZfUQ K5_u}S6#JCC=,1[1{**K}25̉7Bv=+GYk{3B.<3Gcj&y4td%님x}ǶRBK*NK}&d;7 /EyEoE2tbyoFG5M3Ҥ{F6oEtRyaxuHcfc¹k|Jz=\o;Kl\|sXғx_ϲiSoo`DB!B!uzL6I&1w\]x<ΠA8c}?o8WV'7OBO!B!Bl3CO!o&B!B!6'; !B!B!S$B!B!B|H)B!B!NS!B!B"B!B!;EBO!B!B!wB!B!B:&Mb޼yd2kLJXA1asoz8B!B!Bjyē5wŹF %bMBXJZR�XeЀURX,ڂe-Z,`X�AЂP 0 P(b)bQ�hkW:A`1ТG!S2&J!t4Wp0tz_%B!B! .oי5w5xa ,VCI,F)JY(Q Qh@[PE6 (ȇVBB6(*MZT>b0ւ|[ʇ( cQ*Fzڀ2pn>_ƀ)<-T>VJ1D4e|4g.ӦMƯk`[YxsOaSxXl[5/cֳGEdYmzӦ-B!B! ='MDmC*B!k1a & ƚB[(m7P*mXh <>qELj9Ux)B VYUT!a|IU [La�Twm:*QSm-EA3&MW'.Wg^[,80~b[K.?ҭ'様n+ΟiM{ !B!B|}V|5e4ɰY:_}�eQ n.,6_ZDA9bҖf8 mkE@U3؍e)t>DU6~]_oDi>ՖEm*¹0ZC~(_~a޼yxy9gq.rNuLLޜi37o1f v Wp70k-<A8NcSgz\,{ࡗ>`eCEqlYo+B!B!kWi)U@EljWWZku~{M4Vyh!.9F'âWĔafJBgp rXS J4jjU*,XS8f�icPBAV(G)w {*0Z9QBg^MZL>q(ոVJ>{ss ,Y"Ēkeo%)o ~1'^ȹwۦY"OM1D…Mr^J~:jURstGW]77</3m[.\V՜g r_i G>U>ɻK!B![ck 1M ePChP M4ꏗ;X4ݬehoPtϑEıRtv9Zc)|٥51=G)1KY"9S 2$&PmMG,c:joԤT></VW3hJLg^qi5^TfnūOߓn.nX]HkUuiunTo,4|Ľ<^D$)ܝ³~*fͺ{gð2 l&aRLNsɨZ^/L~#zvxxd,VtcVWٱݘKbg_[^-b%'Ϩ³+F|v5d~$uQ yzD۳/{^f>qzfmzB!B!⛵B=E`aᆜ9>3>ne6(wSs!kB1T: GZÐ CK[Li-ccGCq11cta?M WXӎ z[v1w0jR^7K,bb�E '*tW`ʇV7l2XRh`-JqϷNԀme)D*zm2̺|~0cE3:!nSzu̚.jH;Tzdj_.'WV޻οޭQg+ ٰ|.3/aYS\ɴ(\_bµ4 hmq))nb+ "ņ;{# d62( *8[UPk8:ZD-#sy;y>? pC!zg>mYLXjC {;'N%Z)Q@gǣGC8(Wf]8M/S'q�C1Ǣ5fBM6sৌAAAAc̢1YψmEDžힹ: d?B bbX0C= YaF zb5 ' >7ea)6E0Vd"9WВWs�7޲>6aĘk\rԋ z <y{"zEeڤ ]6`Si- 9LX0bL|?\IU?$o}͹˷w7\eW.k~O.ySű)Igӕ+0Zegﻞ~DX|/'S g3(b}Lg^|W_+~}_x~>cjk4q~;FY1cn3cQ�7_y kFv0& )9x? /~~z8fFM/za׎]8M>    _cno7bS={RaYrGMAe8R` GFYXԀ)tZ}ʜ8ZqPYpaU5Az5.! jDq*8 jR׽aE> OR!i(i0{ZDH f蠿/a|!R*UC{3+*\8Nͺ=.eRP*&F *6S)i+QSZە2Rh3h?Ӿu.?&寸w|[ +̗O#y%'^;QtƂCga Gk*%s08Nqװmp+7aS-7ecH0Ny,x: ez<Ƿpg;�q[R´qJv6rk_X;ڛXsU@Шpd[AAAA ۘEO䢜rtnU0@=oPX+9BgfgU49{b pHʃ2TQy!Qi9HVd[΍f]uoEuZݲjE`JZrţj vL(*$)Tj)I {Rq$HڅG4aFp ʅO[!>~ɏqc>h-q}E7V@&4l1O3ZI�='M<4jv^ȷ~Jȡ :^߸p= s9ﵿo|g'hZ~AAAAژňh 5Uӣt҆"cUƋrC5# $U7F akx 5lBjӉGfDOiT*o*…wzClY1eh@jٰ5eGe:PG}f}L T,sl}{ oTF 6)v+v{J[ەF#u I} ~A}-Q"Q ngbO+PWTW1?'hnz+ =w,]to߯"y<]R̮X`uWqG9?)+^o|WT 8&MQ޵zf$}dzC\eůsS}kY?\dEze$ع}W6Sرz'O|V    ؝hxvxO<F$2<b%a*wz(%oX_7)9X/54Gsb v& "jl(bwO;(Fo@to`6RlKcG�u`곬[l:8P#Pix} Găٿ@:'X8Q9 4+Gqַ ejE3ײ? ;fҝ7s=QUS!%bojg~?xq7m~d9-: 7*]ٴckv-+/:f?O9|(:56tWmh !|JVnc3   OĘEi(�� �IDATOy({X I9̋uv'llN#G˼ۅIaÌ0[MmӅB z 6k69cqfAAYz0ٖmL@/ 7)qΒ:O5lwdY0ILyonvYg3F ^=qlڣ 67`<}/KO?slA3Yxx[_MSw}/vo6Vq/wd&艌cW/_AYύwl8fU^wk=Wb:g^;^ ]Ogwq{&}ˮ+0(E&OcØ a /eqܱH>auާ'0(w<^>IW/%uKԅ,ygS<nUmGkAAAAp`>IΒ%KvWG3)Sų.CdUG&)- ][8J{pgK!YEcCvpMUO#MQUȂ3Ŏ<\>uDQBg"A x#3#}D9ad0Ak0kb:p %.F,_Gn zV)jEIaȒ\.ƥRAJZ ħv+{wH "I,[�ұ(;HM+ 7_||nK>O/>S-q?^K/�_{_ҿXB^nXz Ǟ _~2N{Y    8ѱٱ,5,5*@y(U"\>ERbz50x|.kSJ)S7(FM$MY6rYARK0*)`<kHb,Ȩ%erg;6Fgv&NwTҤʸjavҨG<DTf 9\wR(U=VP/B=U"Vp ,k)f` o3wnTivsm ]?w_>8G3a_|AAAA'd3=戱\]UD-WD@ O.NikiP,ٹUS*'o,/7h)iK b5K5$6M^i &v0o4LθtMLkW'OH {vmg|Wå6rXb1 qdj5%O.)�k' F04=h֟_Z&] aژDN{;踶fχWbY~ۻ7|<NzZ    m좧wP y[i?@$sB P%T+⢐x(D1{Rpi6?; 's$ɮGqISݑԣ3cTZYҧ >ȡ !jx-2|*NAH]Jd IiV5݃f8 ľf 9@S`ց :pAAAA5fFdH@ 4q7fڹ༡VH=Z"L,4jkkR-94M%v9RS\㽃AR,U]}T,DXi6#ϥclB+֠cbbA'ε2m#LIi`knZ,OdI1@?P5 WE7<    gݘEOUG)JVGEX%Fsc FBo^!=6<k R@R+7І""XYs4C5E9zOG1fqLZXx2mD$p8.`MF;ʤicO:VOEl@%o#*.F=scU=" NAQ rgAAAAEO1XjT;ŀWA5KXҜe"#S)b=jhUH+JFbH#CyOB6 b06"rUO4-( 7̥T~z'oI}W%Go)bQQX$F9m<56SSZ)izY :Ec5ˆ9(Qs|,bUQx4P9iJjtt{@AAAAϊ1<Gr͎O͂daGX3R&O�cbB©bTBapb'c"h6#ypޑo5Dya\W9s;7o"{L.8%gMxbR =7,[сZw^l_+vMA<br{r_|S_JCkӒ٬*,8DUGIՓfM >"}6_#oz�{=ԟʧEӽ    iEO%r.Dds+m'#ԀWL:s0N/ڔžA:R b )APrNje6lM\1ԣNF*l]7^-W_` e{RV]w7oaŏφetF6]$k \(ZZ9`!uo2m>{�V ycq]]{ '5�z.׾@c\s9c?#Ҿ,0aR]x*/;O    1B3E=xmne7Ygm6Lo( $ocG-) ĂrXI-5Ցjʎm{8f4&-ۙ<P괲}&nUkĹsf7r˵q(Ce܈RGڿ)m zc,Q|lP(BlWLe)FQl&EZ~S6|3ׄgc03y�ů:~/_eK/ għu'[c)/bYݿoE0AGO_wjΚkn!Lc    7LOXLNϢP/,\H6RY81c&lߕcz%gԒK Zr Pl_`b*F\@uO=S3yk6{VKvt3e6mȆ5[0zGd k(ƞBAjP(is;(ϸiC D 4!%g-`{"l;l|*Zf[SoVۆIMA?6{yU}\}~509#@O"m/ceQ6oG$uw?EgE/żc vis_ɱ>a~P>|SXw}l<}cߛ^?~2?mS_Ba?^]AAAA5f3"R}zޔrf]zDذ)bnPF(9RVIV^$z%B&Y;@85s4q<a_&ϛC+ױc64T#_w$6nZ5;WZ"!B.V --ii:1NM[{+%4RRgE#G I=GAg *&D?B>6 Wƥj;W?5A/q^ < 5z9hN �-3ij6)_isGϡ˹ay+6D~ {rǭ9f{ s    i.+a ɂ &~'FkPʣ WZ +PMJ)F VU ^4$QTv_F 2uJs/[ler5ӻذa FQ17ݧxZyQ#{Fnh#IiwTD6Gԓk @9 pJ)S+ج#v@ 8uFDN|3!: k~>_ɕ};;ٞ ?6b3]xAkteƵJ-)6oZEԨ<n߶-"Ϝ]=J�_~6|=`14ȞfAAAA'o좧4;}ٶv?=* iTj)ހFO\<5u4x`<U V0h '5M2UdtB(ٶmkQΕ R" *ROc+5Eu4l%f2"q)Up%DXU"mٔOgi^QLnNG6mʒ9+^9y\sqL7Cw)DŽY\(l|@V -EV<֫(R|ܺFfn N,꿟w{_g>EfrAAAAn̢K9oT Ͷ 4}&HpI NJ�gCŃ4#ϛAI+Fqy1gJ;/Zt0>V2ZV. ݓHmMBl V<ňT<QEU%INZoqM+q4ū :DMRH,6ldȶg fO[NUF0@޲cm}n97pw}E޷]$N:QGdn,&obK3ݺ-3􌧻]u45&slNo8i KNz_p_y|�?2h{ī    ^X.4NUDm,y{ `PĀŪAbD`puz:[I(zJ%" b+"!*Z|K+6vnx4KQ"%r]GDpFHkJ UwWXO}x{ 4UO衷 k Fٙ8Ed]lܢf7l6)y3wo~}xD;ko1[К{Wa\y.}y~{Vîgq#LNM?){l}8tρqcY+U+a'rtOo.[ƲeXvE=sWc3asyAAAA{>_i? I{Of A jc-cX>o$TbG1-Oua -hPTNɮ͛Iub B$SPEEVQh8a vyFV0@;aMN14뼊Gquky"Hv-! xz݂5M::sEx Kk<<dUq8 /\s T^\`1$^|x_:>fy1oC\=b ob(`fq?} y=b2އqM,8v1-O    OIƗ,YBoM,]]P`b�-P+C<&y|dPc"!U$+`XQb?jyϻ-W_]w?ӑyj*I"SP"uSO[ IC):; hh}ѡ,8Dw^VoW7o4EEIRF�=cfm{o,Q.Gd $-[|3+xV3{:Pĵ6)g K<o[i8�QAAA=pY cLNnFDȀ8kPkQ E%!61DQL.c\L.acKꔞ ;p.yK+Ni`4%g㉼P 5 [JTHxP7nbd}o`2<8$/[0'7Đ=,DP6{̴W>u{>Wtgs/bI(xAAAAut뺀�$Ͳ_t<q7vZ!M\&�ҜiBR9< b<,Y=hDTU2Qj4MI#QOF錳)Ţj$Z 䔃sЊgKճAk65x8ޓ""AR(6b(J^M�Zy>'G'./#]KX0e    ?)cyd=ټM(xcLVo(l˃Ƀ* JzHH=ւjΘ-CA02@Q4!RZ3FݰL{,RIUdq0a@ 3:SV2}<@D`4n%BYD րyĀ m3__&    xތY:b V4fS"#9-=R H!i4FV@rJRepJ+ϊц/7ع~S0>n=$)tGJg9HJ=U*=9'Xh6@aJw+E(@̙U'S TDTHFHGY8 6ʞGAAAA;zEp͎E�E<#Ă Y(F jc4ؒET 8/\ŪA;58QFcbS5nZ1~GQ0&";rb,,y!{WZ XbkJ!68"KT9`sy2iZQ/ =ͭū#Q1-    ߘAF5$ۺ-^{+ *l:Nhա%JWMqm8|"g`"kE1D[-ŘYf2~$zwQPqC:Q"+X(Z!o gs@$%Qp]['ӨiUGRe~6lQ)Wc<ICd 9jsi*H+<;|kp^    Ǥ[5"XUāQlse!0FJD<J2D2J4B4H4HR/SRR) R:OG-ssy/mDq,th K[>` EB-:A0cԃS\*1%M[(@ix!)غ2RZLVŶ@dQkHb3O)]ɥo; >{+c5(+s:8@k|v~v?    cժD6;>QE(>K2« AZ!%UldQo0PŘHKĄn:;ǣXv 242B4J=IQ#c!3z8)L4 T)泫o0QR L.¥,e=ż=A!NIDH|Jw3r،-`VvEZ'C%ūb Y7ٳAg\+ï[zƧ/!~x2sůrjً8幨ϘIyX)]wyuK[tsW253Qu`=AAAAԘEOG)ۢ`$/ (c¨zQ JxViczcZۡh-ƌTx" ,>t6G6ҞD|BG T㒔Ol!bEu xR`6.@IڋPm!Չ[:x4u>Qgp00Z8MkdqF{9u|/S v}WXՕ|ǷWsLQ?|/Ggfr'9KGn: Vg(\Ê6: F<cAAAA;]f8ٶ_ɶp+`Q,w#9LΧ(yiy5%$Q|l- ҒcnZ- yp)iSeHJ:ڬ`#Jl=I"ԁ1B.'�� �IDATB:AROA\*[c [|<qx0Nc#So$#ܱ7q Ěl>:gB(SØ!5nW{͖pGqޥM`uo} N}3g03%gWG?Z=8_}/7<B1|/q>v_~oy'⬃5-\zl>c}wexG8 )߭;y?|+NX{[8RC|Ϗ{:-_kz S1]ӏ|?o{GR]My<m`ԃx>_&AAAA<G4me%+vj F! b XD@"FZ" B{ry hk̞MרaCURP,Dl8N( O+EuRFc#]sC.b(u1qjc">{sIJ r*:|6:=ٌ1w@c BÎ?wqVςHYs}cgUq[>x6:-79>ӻ?ǵm$'x1|lK;tTm.b�cOTo|OB8][{{Bwq#=a}+qs.x}#{93OYˌ|:w:Ӌa~Dl^M~pZ�+&Ōs^!~{IĥpAAAAϙ}vz ţFP Lj8x,|+%2yH(F yFTkkFL_?C}%k  ߈yia;(g n'Jj3 r[O+ B5ULlƂɊ(  DhB:5/ $D#KùBG[%fz,$wo"^_'rTn_7ΜqmnzO89rʜڅY~{`55=8l9ZQrC i|1/׆p0 u8xZr>9\#fgRL/w)eG2eh.0Çqgr9grGwqӘ=gΣu槾c>X<|iHe9?*z^e>(�$ ?`طAAAA< .z6TYSJTFJ$Xb`+D(x^u 5"Ēzb7XqSO:\8rV\K'Q.Osܙ;r1uOPd[:|ֱ5mͷгx [/Jy*-vȒDY3h1Qsu)t.^7rNEʤqSngyƄp)|ʂKMq|M)I;$Z'Q#vl>_Wco?&֝*>N=l9 DZ[ֲæA!8N=7ʮΧw}ܷ=h5'ʔopnϾ2zL}L{P[rG +xAAAAϛ}Q͊$O˶qplP<`0G%6wzP ˸ֈbD -흴w\!ĞNZ;'U0y'LǴ9[hkLRԳg! QrGLADlYhAlUAC䋖iM;5٣pi={͞{տmXm@j &gaN0^2?ӵL-w >nޕ:e6/+M?>C68~=j=-kS^|,\rxfoz{)=K 0i縗o;テێiaIK.=?~;ҜWx"muU�pbԩ    `_,zivXUDcR 80^bb<QŖ::1bb Q@Tȡx\cRT0))vR=&ª;)8/T PqPrB]= B3X#$^q '7ۻ*;`Ml\ 7zz|x6og`O=%l-_Q:Eܷc^˺Wr_w`v1Yn>zY`ZcAഓ'RZC~ٯIGͻ.6|lOeHci88̽_͓Isx,]z7߲O'4=˄bm�*y y(ϸlmb+Ṃ    g}h*IU0W^mkWŽlhi+PoFr)#Rsc*K1_Mk: -Z:P<2ZvwU9s C$DB/4"RCQ4)"" -@H-~ۜ1w7$ٍ>O!ɝ3gly?>|<3ɶ}K=>48q1C4ZzCe%*zbXkq#9 LEi_aֶ:;K ylq|U9Qs'ƃ5`n5Ҷz_V֛Peי4q{ v񡛲O1t0*Yr9Io#|�cF ̤i\4ws;p7=<cS웘9 )AE¬:JwÆ~/1J%|,]8}{Q2r?;?]ciy\P3[|cK)eݼ)9pA spF[3~ݙ14κB./; [<ϼ*RJ)RJ Gҽ5P*2I$m@*UBZc+,E1jI3!^$~}ҷ_%.e@JZIIe d:y'hmϰLɇ1A  EN(Ix-6LQ#"jl֔ hٻ1Il: #1ҝi !Eh`-&=gmb,`(_撟H8;5?LO=S�N:Q]d!p=kp#g?FKQZُacD!ZL.{xsٽ-dM15^ۓxs= Kəbn ՉZn~mk߻k+o?4J0[XiۓsyaLܶoJlP^]wޖSO,[d%؎.:JIvxoMe!v53p圓{ᅣg }oB<Z)RJ)RJ}6w̘1 2#&4D`,`m j)-)>TiV, l#a dE'R\C<PVV_D d:تO-*b$bJ9p=)(-Xb%12.zKv9$JoZs\g6'P6pa=}ꯤӭެE8!fӧO_W_?/~3(ms{\0oYhB ]cS.ck¤/`DJ)RJ)ZH$q,b@0l4|`H1J4T"I(yZ1qGs*ŽVZ2JKKL9zQVZBQq E)K񒦽"2-g |H8%Gy'{1{Ҹzpޓ `(t(aLϓyJr. G"&lu,= $Q3'cS"K܅M9OeZj+@ssf1rwN<=^zw! WN<7t 3b9s=6RJ)RJ/^C|.C@] Kݑh?O#џEoyPYYE(ybaLC%M hiæ[S$e=UiH<3AQ*Ũ(!̗̙,bl,NXZ^}J e) "o3<d|VQ+ā@e,-JRTڟ\:A*UKDs4C>̓GX+Q`XDrxғc߈q<'Pz $ziO}Ȳ4fȈ]9ػRJ)RJ)ԗ[{zzADcX!QhFؘe#U%diJJA`ђy,[e)x\J<dcW zbE$A┕Sto-yb8Bq!llje jK y!˳ӆ!j(ilhy G3v( %Udxo \ra JP U %o}')er(RJ)RJ}{{Tih?Oxq"7 xbVutub9K,ӿ %3X\G{{+ZKy0ޓϧ*6 6& WBg>ɶB{P8jRY-ᜥeҎ9'd;Wܸ}Mi2i]-p>lʠAC'˰Βm ݙ g!8'Q0 wSJ)RJ)RꫨSD0`|aO2E, Uh~k??EEbqJicpZ[ZhɼCKK  ^X2] 6t!x:}`<yCs@h2b hP BMӰMޘ>sҜ<$ ȷ ˚(*.Keecwc-6#͢#F =}`驔RJ)RJ)гQ�0PQ(C[s;5Σ$adÐV*)N$).޹U󖪪>-Xʺ j$|_b̹tf=ރQ ` "cp2bhv@ &/D0d;y֜DϒB 6Zޟәc+W63b.\ߦ2RͭQu(6xCOwr_`O\I5eWJ)RJ)<'4Xc@nf$F.鈉:'HɐZ Y`V(sV,'iiSZQKV1㽧4.*lŅz@@K:Ƀ0s17X1'4Q,mX01y^0XblY1px\`0�ˆxr+il2lcVEϏX }_,.$)/sYe{^??~Æ|=>y_:{;(RJ)Rk:UPFKx-k.FnA< (e;eӤd:ZIwfhlo^5|0$ myޝ=EȪWў ɋ 8c r>5Y*,,bLt@@CrКs4tda L�ȹ½!LV7ZLiji?"ODs�68OkF- p�Q{w}ݟ8퀋y9Aɼ{N/S^.xqı~f𼟔I{Uէl?ӹ.1vAG RJ)RJ)%k:1  )5:K ;o{љbʋKqYG>&Hg bK6UI}CmmѺr!+h$sH1^0ށ 1.1KX 6* EG|1k0^C=^]¨PS@҂O{Qv \{ "0X1CHY'Ãs;<ron`wNaR>.M|H?D^Z_Kge|u iR9DƟ0bm:> gұUPέo;m+ϠoG~UJ)RJ) ZO'` b�Lb {#47k +W6PGCC3Z3CGYy9jY1 ݁tK󝴬O X a~qk Oc0A7!85:EBjWh69H'AXKr^DxP F)(,uyb`?.W}T~ݚ xn~ < x;ers13lC2os cc_񾞧?I2vdN4'Ø0vO&N>ǗILn>@~rG2sxcx(= ꤝ7n- >k?6-w}I-V2h@ D׹#9p1vn=ho NE<H드9< k}go<</ _�?+^(Tsn{\?;מ[>sIWҰ0|nlYaa<b".nil53zsى2aqx<0 YgNלfNϸ8'})RJ)RJ}~z]6Q%]LrhOO&M()JY\<I<=&H$46bUPIc}# 9rmu604ҾtikjOm55bxϻ(l\XH-,U|ٌ BoyoOh-A!$D zqܧPvGvCk-^ȊMMEj7bP_Yqs_gX m˘N}5X}n? κƌ'[ǭG͍}DK~ O "^\7ysrϞM F3eڍ|6[o?؝Oڌ^^렛w/c]֙eчexTXŸ/>{?K)[g]}©R~&U5֝pŵa_ x5rӯ~}. +y_pԧfʷINM}^}>nut̛&v36;~7]0g_];aWzpw4Wz :fe}lyRJ)RJ)6ޗGm C]{]B >̓`US|2Sbt,gag˖` ;:ȵ6�#F@&Xӗ$ č#P DYKąXX,jZD  f, 5Ĭ%AG<XDlX#-w jdLចe&^L#" I$Cg A򦘚}D2 ĩhcVw>ݢe2ygs{rin)}Kys]\tڮT[,棕Y╵V<Kmmkmm3C1Χx_2z5yV>FAyMUF2qא~lZۗ#&,Z:}g08[>?Q56x!܃ŀ1yoUSxa* y{̿4r1;3_-N!௯uw~< C2bm W)RJ)Rj5ږR$ 'E<!6jjG`m**'TUU1V0a�u5֑IwOфB24``E)}hm=!tMbM49l & /ma`zK= ўZlυ` Kt % >m ZM1�� �IDAT͝ agÐ*.dҤO6MEy<1*y#IaVLc5S~ GS]X}_I\Fn8{2m4D,|!Ŏz0e˽g'r%@S RTIyC΢#6e^#{KqI1d*l1ņ\=�V3e䗐gt{Lc^`{2/7eezOy=c> tкN@ɬZEf}zW)RJ)Rj}y5o{@^|aJH<Lƕ 8ҙQ^هZڨ蛢iIh0OQ"O1He4ylWx`b,e3Xk ̣ͮEͅy/{!�7,Ax"A6É{k Kz0&H X3*L ٘ Ya.YIJ Y+<<R\.jlџ߁deE+wPv /׃ralsĹrR^,.~2-ƔfܱY<ۍ?>+k ޘBNIߢ_|˘g*") Y+anSU%wVZܬͳ)\HξhF07du % +X_55nIP\!Ԯ]ޟRJ)RJ^1HOTiiLWsUIF 0R)*:t0 P__NJ% R;Vt`cqlg; % )aU]׷'6T3K!\vDp0+TvWF-ZcviEBGGΑ98,AM&K,5Qe1'WShhU'`e3]nVd+?>8|<IaYy+},c7"5Q# 'rhbŭͻIK) C\|Oİә>}:_aˣ׿ų/bz7&vڡ{)gŔgyWXPʆ6rin[囹r^a^}M1gI;=MqNGܻd?79x)ʓ:qmOt#{Co3[oEKykm]}<{&w7>˜&W4.,(RJ)RJmWz[N=}W]aoLSCƒPaE2Ja9a"^3űvVaIrcLԍݙK(ጉG[Em$n 2Pc č!L#Hiog̋)dQș PDu6`3sI,b}0NGr ےZqp~}V3+tϵO2y<Ǽv9Z|Z 0ţ929\0FhwF~3xӮC0u,nm8ֳx{|*\ t.ޖn(L>(>bn*,_wn?1\{͕tW=d?;v ZB?qUkM92A}*ל$b7,Ꮕlxǫ7kU2R^#GߜȵW\ Pɮ|碟2@z'5.9^u Π~4شS)RJ)R##cƌov)D!=XN�u+O ŃygaH4h^~5Z;ϑk[3qJ+Aa10tH (aK.F& 1ԥCC`eBգD5 Q[IQ媱Qc!p";b|H1D4k,ZFL�`q2ӧ./Qɼ2#ٌ==;'S.ck¤/`DJ)RJ)rr B)!l\+ee ߏdI wT:D8q23N ( @8Z a-Q/,q,6Д9Q5΋mUxFgVB 6 \TM+䜧= !PU|&fq |-7`̩R�BX#4TJ)RJ)z =-Ib<h{Mo|#D2IUi% +ȤsH5(AQ 4 J*9Cs1cȊc≚'(Kk-9Bt>uRXb':xu!b,BtϬ{Dd>f@ȅh>|azg(bo&~PJ)RJ)#xăg `-+1*J0/+s̙srY8-}!іRPV-#wⱁ|Q=Zx Y$ Zn[=6  HUds!\L@ l]ݣ3Kđ¸6O_]nt;m|+ ߚŲ:67A)RJ)RJWg QUGv}VXP] |@UUJ+hid:-]e+gq,l|. CB'jɒLĈ IC`B>j;#<]+h]!pNCI# p!t3zl`�1'C.td9z#`*doBX+/sY75Zi+MgVJ)RJ)R_MQhIcUU)X k1la;m#F{{X"C5X 60rw^6FCG\,Ġ(驭ńx6G40[ήa>jRdXHYO5PxX`"`A{O\B, {#W174.1vAGY2u IL:i2\{orQ0nn{CcQn=c0}FƌXz)Lm c|מl ˂.ă3v{j_s`a?y9I| {un_$:~5wL)RJ)RJ}zFQ! ws7I!߳ CRQ݇' C<ys֚B{'4C }HjKYkiK)4PF]>ޭ(ZHyFi@& Ȼ(yOh_X<&QTTB,ޑsh KŘ.o;m+ϠoGIZ_Kge|݄u}Ǣ:hhux胏~%O8KV[dժJQx?co/ڪ}4U|۟ƴ'''抃3*~C\z\=>|d* 6]y$Nz77pu7us77`_;0){&uL)RJ)RJ}YN5G7Q1eY ՍL I$ba#^'XQuC. P%(ͅy:XX)ӧTHeDX#at/t7"hyw*XՋ8DO6H<P]z1^,f]bRXWbߛv6#&bѽh^y߲`S8vWc4ZƈAjum{!HQV՟Mw8#91wt-F&:$))-Urs}9ı9]ƷGU,ʸwE>B@Zxqe\x\EI|rss;0dH>j/̋F:gr >/_=bQ#9pXv;C<G>h~2sxcx(=װX)RJ)RJm8)I,,BhMT Q@pzGS]== в5a/>BddC[g,WyTH$L`& b ̮boK^|3UZb <⣱tFpDyy<9E3cm [[M &>[oYwucvsꡛvc|+mlsd'^v^_Iw<uҲa[<ZnyvrlMÏ[G0~`<%- :B<H۫<j'>o59f+/dEFԦ1s! z<?+xxqsgM~p=wp$c\͂W2>g*?j!b*/ pړ徫}`RJ)RJ)I3 F X|Wej(ei|<ۙaŊFfU& 3H8w91A :3B}Ka~34wzAHZb_b|Jv"5{s\!T/&/wF/UD%8>j�!z^j /l#~[E~9O6-;ak';qN[gwo_ox^ߜAy# bA?i<:w͟˭֨TnAST,Ց}x1=`x(L$ YߊC~}!칊.YklU*d:H6"dLXs򻖃]zP;wޚ2ا5p"aSٿ%~-MPTDe1zEJ)RJ)R3"Ha9u/ Ģ_1c d@iE1n1 f6O"I !nCqG2i'XLB,H$ .і#8IC,ALX�A XBDžx @"'xVHX�!x bq' IądLHƅxLH%Ȓ <Y &b: f峟 g1ux.:gHr>ىL޾d(..b~};51J;3ľ:6_?gK/joMs,{lY2:R3<G} m�$%kZM*Q'UûUTq&&]ț%&Ca~ XDЍpe`_Ou72R;Jrb:{2Of{RJ)RJ)z,=+**=! GDlu{W-zoM9F:iǻQ1Č`!& E{ 2xUDE;w5]c)|^(礰uryDQfTjX b &G ㊾#(..^gS}ь(Uu,|u3v<iNoѫ<젓$!ȤAc}}8tcHtvBORTWP݇G#Ǽ͞-~,x;z[z#yf.գdpoۍ2&Z ՙרk1˒8*YC6f@BaX)Kx(Ckz#/^įM6Yci]@uuUѱ,UeX[6G--ka'J)RJ)Rj1>|8 ^_JAdt sK<t"; 7$$:NBi{5MxSXVk!@wŧ>ZbqzoRk(4Qk)SV�xt/uOb8&H,IJM}!cX<`qwqb=',:(c{NҤH%�ۏόCwxI&+=qd[hir7{g^]٢r/qv {bfk~|g3+#7C7 c6ygΰq?57fOObf{ǀS0lbf kF% XϱO 3/1�IT@#Sy}Y }=]ͪw+n'nW[1Yl޷!ݩRJ)RJ)>='OFvw؏})5X ߵF|FB &zwwlZc<XDf QEDx{x_G]-P5 2Dݣ&DO)&jQ/]} թx ㍉Wh$^i1xʔsW|p>kZkƻOb -ddIP\sѨ3ݜF(?�$Fڍ/9k䨞%/Dݶ!z=no6ǰV1TN#kk8휃b,b滳ٌ{.c ӑw¶�둡h9W8-lV9m2w l-Yn G\W6 w{VeW=6(݆OُMS)RJ)R3gDz3gQ6 ՘(�P5i7PTYX^31`-εSB{ XݫڱA`[ RPw5~#Ql`Qj 5B0F b CƦhWQ#[>_/˅{KLZC.\}JO㙧g]Ƭ3ׄI_RJ)RJ)Enƌ36m>tOB h-ܒ?wy'/sүT੔RJ)RJ);Z驔R S)RJ)RkRJ)RJ)R_*z*RJ)RJ)T4TJ)RJ)RJ}h詔RJ)RJ)RS)RJ)RJ)RJ)RJ)RKECORJ)RJ)ԗJl}_z%Mٳd2ט'R)rK&O7/z8J)RJ)RJ}ezwhYL&{xY},B> D'Ǿཏ`5u1ߍ1&Ht]׷s(|n� ^]5Eǯ_=ޏ k`E װ6`ܹ+l9|8wu'~RJ)RJ)Ԇ^zޣLgz:G0$$g@ʐCϐsaZKuu5}ADpEa (++x<Nޅѯ09G2ZK$$ #+**߿?D cAt_7*+*Ԯ_CEy9Ub UTWVS]U{QiHjl?dƌ Y<v_ʲ;_RJ)RJ)>=ӦM# =N|!lw8s^ 9g{oZ C;W]y%wq_5 /<w؁orN=TfH,g?;#/Gu$B=窫/b n{7.g!l lI'+nwX]9`@n&.B:5IGԩp%S\\FAW_ɍ7^ϐh7kaXhޙyL8U*!n4{ɷ=QpW=;u?9%nr3Z4TJ)RJ)"z~0yOFf> ]H.9ɺ<//m# RT2Ï>£>JQťDux;͇Z�sTڊvvqGWG/TUfjjj4"Q1$I=q+ʩċ2---efm])"  A,Νwc=s#GL&?~<|uvbٟx&0v=!KƨbGo�� �IDATg_;W<saws`̘8ƙknxHGLfӈ'{^Ɛ*iCIM2{kGs^}/})G͑7[+3y9tžǝ{3G+)c0fڿv[?Y߮;ر8<I8dM<-}<(RJ)RJ^{zi }pFNR QOw<Jٗvٔ:' ,-R$÷ܒ!NGGGѥ>}�!Cw"[oܓ8|>߽}@lf̝;{ͮR>h.d%Kt�#GnA8hhh[o[l&oC|gY^|Ec6ٙ׳ŭ?9C0V2獗hߓ_P<S3+3nA=^|q1yRt\6uTo_Ȍg~0x/, ;<k8쐩7mEGw+;.v^t.}mǝ9v0\I~*n7{;>)RJ)RJOל)]W'!a:5�<!qycA ,_I|IcUU k9_Rr%lph9g*fNm² vKaC%*[b175&1Kch0bEĂX`ar9g~]X7?xXsf,O2jjHI P"Yg͵^GQq1N)R )%ӦLAA>C xggؚߓyy=HKOcҥ;OOyy9wq']{6UVucqaFb(BJS >'q3y�'y*(˱?w<C^È7<L4fR}gpG0c8?2%gN#bsRuݻ?/g9/qyn^\jPQ>yMĤ#r8& VƝk~ͩE{o2s`ҏ໣w.T +g?{6+5px ]ˇkꅜ1q eFsҥ3YU1@?05}K_4M4M4M4MFE;A*zWb^I(Np}7(emU+l</İ|xN2Q##=H-[+blR|*R z.eDZ";@˲8q~ jj[dl ̯~+}gW:W^deer饗0w\o߾3 3ydN= <h"<}TJ3i|X[~`e(LHE;v{=).. �|lNBK$55β~3U ~d5 �p>}:~A((B2v Q}3`g,ɛv <x-?Xjk ?i~bO wQ)Ϊޑ\g< %[>Xr,hcP3eN9r#XoQM4M4M4MӴonop]۵= PaP,;v8ap+uc<ޟ!*_KƍB)fmmǂOH$�jʟSVVeضmɧBss3F֮]͛Ƣ~kW5kq]h_xMM7͕^U\OubHq5).{M\ͪ弗=N8u'+`]ѲS(4v]Ld*׌pqT\uČ2ξhW3YzNF4?s}"RGf{/K{qyB]6keP){v&'9pݪwx :Fƥt<Q+.gnsp +ީ`շ0d=`G<|riiiiZ7 =騖^G3<y qڢ ,/ƹxh zr)'̡=Š&<ǡf,]" *|17wNT2[v-֬2wr* +ySe%*+w$PDcQ.^RBtT mFYf5VC)`B˘C pp)Hcԏګ;<w~:9fnp{NmXUq؏汮74VU1�oW9~w|cD 9?#4K~w.7|?W�D`pfzx~}L.ml0P)v>}]֎?�#x{샦iiii6Ȏۻ*C�)=f,)=m'r3+x*Θ\D8୥[S ع]*Ү[;u]HB q v}~t^|]!yݲ,�<3J D 𝾩ؖOJF s=H*/KSPt.T@ ynrլQ̡3&ӻkf/}ٟ@~?ģd<[:Hm--2oѭ .OzJ␮H>7}#Hq)/ nOsz!Uh T^iiii5>XK)<L)P%Mnyv {isQe.8H{0ĉP“ld|%ZXÑ]rxv{G:=ݷ+)! )RJ\p<)LƖ1O�aqd5 ^C|8}z`YarBHq[i)HO!bC#ޠlfaѻ?e,:3TQ�!}ﻑȵiݱsިj;2/52o|fYw;jYdž�}w4S۶^HUCU5 U5M4M4M4MӴ/Bҹl46pϯZʣn)0o32[>V0~pe4FVǴEI%n{ns{:u 6;v =B@0g8DGR;K)U=H 3$K&w] swLaֻ!  A`DFeI="ߋџ滏IDrտnfOMcً,=F#qcuzc݁FtK�~typwkaoPxl9k'rȞUcێ lxX8IwyxtR҇잴ʞ#a^N'Re㻏RE x+YY€bS4M4M4M4k"C3Hbg((5ʜB~iz[Y%iNmGQa*\V%'g֧մ\xta<!>s:쾊= ?nuyvB�a 0drRHz4& Fe>|ߗ='lR3S"Q?ڇL;Fc]+veEɟg*{gK4&I+@Q9F<o?ɧ?_w#ɝ}Ļ\s _G~C_伮<o$IALA󵜒ǜϹm ̕#~]Va(4M4M4M4MӾDB%Y4i1-܈r 177G'55LCc 3ncd~{ҥ6-MLуKkQ<0k5?#SyJx|6H6w;Y]6IB8  cJyDpQ6-Zۣ(g岩Xx3gAMvT#onm!de}xGuY37ag:v7#M4M4M4MӾiC7⇛9nto<S9vt @9dd2w|!~)\}^X|ppТu[?˒[VG"?3Wz s"C3+;;=w-\Ʈ|> @]wQLd` @=灀mw^K 8fxF|nVGsyg{#N^SKm`�xjiii} =^ZHiiƙjf +7R3D<0vPO섟x}+\@IF frս:.ޗ^XMO.5XƙGedY60j|=:ǙbSmNI^k!@ ӶYCmb&a`&RضS(u!8t`e#!BEu}/u3{OKYk2-#og^u)JiiiiڗBFXs8/]ψl_œ%<F~{h~ U14_Z09o#Q'#-Ȕᅬάۈ$0)SoCJL>ZQC^gw;J% (Ա] L )du 0IJL/@R(rR7*3(xL1ANX:G^S/C4M4M4M4۫ە;pV̛+;sydJWԳ2BŶVz[X_90jV _]IqC6WNMAn^~EaYϔt0\)V}A�@�u<a$ (ǔ > Ij$賱M#L5 )a"Pb̈4+7ҿW:oPIM4M4M4M4M6KgjJ`K};x"A^^ՍdgYVQ0Mhf}e=1'ƺfzq9J ~;k-2c1 ߛJn=z}3:;8"0̎J)9~sx_VBg >~4l)0= tLiQ۠UBX/aj4M4M4M4M4M" =;WTJ)<U6^W55LTɅ텕7ӏVWpŬjS |!1KJUHA 毩)em9yR]h,)Kg|&ڿ0˲mTR7R3ydvt[Q~R)6B) $>C`4 <:PD"g(W,c[&[3:ݦ"l#M4M4M4M4Kmy{  㕵RK; )Y6GRƖ8BAq1Xn!slpwGܮK;8dD!Me5lo!%:Wtu]ui(a&B(.dnf cpi:F|(~ tJaJI61'bЁy(GnUӱ-aJOGbϑ}m>~|+n@ՏW{:獛gV}U5M4M4M4MӴ/>BT2�M>\<9{u |ޘ_㯭%T `Lfϯ9m'KiKM3^)ǔ[x544&ӽK?w>3M$D1"�e#z3o.VWCVn4zge$WlIJ<&N7P1(1?JHA,T xm}mm|,j࡙)rp|@|kx4>j*)tԩY3OY[ϣ+cN䦏 29#~ jiiiigs{Rz(oO63-| F )7u6o3_3t ?>t Nmc;�Yz J&߃=Wxvu+R !PN4v,i#`z =zp3~99􀏐-&\22&#``[fb6T$_4T4~.bǁ-4-l$u$J+]Kp?ѿGnbjDֲj]WN;㾋`vQG3vnNfjf~W^4M4M4M4ME@<&+X=7S&X[ar(pY N;z�) [+X1xf�ep]۵fk0?H ) !B6Y>2sH* + 3$Lioeȑ,p!N4]),� 훁6xkW{!XG'@YM#s8xۿ6~ (N~ 823@JϿoVasrlݫ+t(R�w[}4=zQ7X|H]?&޾AZΟND_qe|wml˔<bG.Ciiii߭SJu]\%yɢFyZ!ÊX» *Y!<'wR.U <2s)5;oCqbjZXνx<ك.+7+R\6Q? !$1O)J&5^<^x~V,ۀ܀&um.~# GmmT?)6 XbE>mr%%Y3}gsO6ǞIYJ u43St{f/ ݔG`r+7=7iQXL϶T1.3T#fƶ9F|E9+^�b+Փ2>>װ=Ciiii}n.[=O$vB.(2gq:؆ HJuD.4Eb<1{ p~LSJnvS^G?ޕqC[[v-H&rYS֯b ݲb m m8J304 TX*BaIeE瘁Tʧツ#t0r{y06F <z:Gg٧}gh\"O~ TFl=E멏.�Em38TZ8wkrӑ <zãH�^>/N_{"]H4M4M4M4><u<ܝń E%:CI<u)aVzC Eqy :"1^yoѸ vU @ e x8, ӏigi!l 2eb-KEIm1MJz:y5+}&H{$JecN^W~mBlrޥjs=KlRߧd2+h;Sv hdp ]jgy!vD iiiinCϮabF]{[ۓ7u.wY벦y+iiwTXW¾=y-܂,2Sl|eVhQ Gs<Af`؈~%$[Z- 1\n}iϜO[Q"@I HzYLup()făkH ɧ}/MH#͊ԜS=j7QٱٲmJvYdFw1ea.ϧrݜy$&v&,իOO�xMDu/B4M4M4M4MomcFh3% H~/ErGj[�� �IDATRz*Vk8)�:w WޓF"]5MGjt $yYA6H83?jH[mKZhJaiH4-NCeHgZ_/:={eL߹?r7r0ޛe7fj*+8 6ye 5KlQBYv6lJj=>?r2t6v4lf_9&Z O|Ď:>3}'2&ˢΜ9̙39>Ń8gjxWT-.@iiii_ogzZM)v_&&g/A;Wet՞<]Ϯ;;T2! 2R}DR`H rR,IoЪ171eS VF` % ~Qr}J zLࢿ>M[J5Q|3f,N?с:Vim==&-!`q/d /x=~sj̲+�3~u9W'}?,~y EȧmbsiiiiP{I"'MʕI$+: I,_z,\$0$p`&[q]wWwE%J)?}i4xɂK{.�)M!Ģ1eSSO(G_r,GbS82 R 2i#Җ oL!kݭIzD DKV3g +o3\vN~z8U_]ҟaÿ]ڗo03?`G;葦iiiiߴ}]Vj&W[zɂFD$WL"dIp'`oGggWu@Le&W%>]aHS>)AHeH $=/ґ�Ï ` hy&ئD�e~LB!QO $\S`<jϯj퇞Ǜvtiiiit '8C׼r6vea 㳏4 qݞξ*nQO<Oi9&b|rթ$Y '[5 <i`JJǟSA>°I,` 'f2zj!Nkԡ_n4~O )}xB"EJߡ}M\UF3س iiiinsdxhy]Mq,Ym랗 !;V{vxJ)Ps7<Pңx,rg+R6J<ɊeL <#Y[gH)0-4g&m0naɢ}4M }~BJ%gJ.(! $iy@:QF"-+iiii6LǙ<SJQ@uL]%aKe3Rxޮ<LLwx]uOߴPJp S(rmv%NiH  Ս4JaR} H E@!4߃2M#NV l? $)lQ*&yi`͗1?iiii}N݆J)\vNOupwOPUB<DGjDbgQ$<M3 84WvU 4I bnoR 4xR0- W BeDx6O(h=;*a.QH6F **|~?0xPx)!lz{iiii}S-d$LD8Nǖdgf NM4 3YcP˲1,+UJi !˰cH>2/Ic(N6-B% ;7}2I6MQ[ۨon!Sq<fp"2ReAV'zsti.sdYFLJ88Q&s*%S_{_36z{^]y욦iiii0,L0 n`>;m&ήBBHIR,> ÐE[,Ωӎc<xfHc=?$J 3m9<Z 33v Y\)gs^(Pdffapy $asxjm3F|z͠d`:'ѓ񃳉$ 6'_a'𚚡 ]TמkJ덃jḑ:kJU%3;}6]4M4M4M4�u=##bN"( ÏϲɼfP s<cFE Ҋ{h,^q:R@u ASa5<Oa( ﮺M6Kx44Eq񈴶 ۴0:{nreJ3ջ8N3MMFlZOp=I<l427in!V' B>Dm+-D8 C>)Kx;x3}qb?=8н6>|1Gl *S=q'ESķCt6ͪ%0}7pN={: tX4M4M4MӴoC"!LBT2>h6r 6Ȏ(CJcNMd{SsZlS-Ðl^zRN ˠAøGo~1Yi)M)rC̗.҆p�<<o32r]ǖ5 q8\?ی}- vku[X )(_D8"l i#%8aPlϟ\p9 6aSjAbWUW0cOe&¶5XqtօGKcNthضwyd"ocM4M4M4MӾ% =-iaJI8da[6 Y>&N`IX>?mu gV#uINQ.G)Fz> (bm- 3QJdc=Cs 7X/I8f!dBy1Nia6i'^^# -;+-%<ʺ  O&> `:df  ~|ZΓ6=Se ftP&mdWxbJ,rXqi�)3)>V-^%�qT5yFrs&իcSws sYSH5/ V>vfґav_K~UMVFb2߿;ψqy༲sq xLQ6.nmmoLͧ|oY0 \sl"=tS(uvq'6MY}UA^!kb6uۯBLС6U+n{c_Rǜ liݳHsQ8_-;1 �EӬ_rڟ.{VNɃsPX|\= w>~I26FƓ? k^eOQȚiiii_nCO)\(J'Y<24t,@ }F9qd|wH9g_|NgIJ!\:Jtv S0$8(8s󨪮#%`@kCTKP^ECsV;ͭxJ S*Y4I$-~ttr2mhfGY>H,dz(%8ZP %rx0u`3nfKn ;^(8+_K'k^{Rż&uY3*%CEe ٰ~z?M+T:d¹WHNA˚W]pS@:I;~}YpyD־ӏ.oX{_"uǥZټx[FЭcKnsro|ʧ[<H +qKg0<L{,壆{m˫=e,P_E7|h\a?Piii} =B-ԶN?D`M訔. )CQ;7yE=""lmVUGWn MMmRNèDhj)<c ynfqIx1V/tCsͼ-lonE)p]h,RKv;� ~+!m|DjMlK"qXg"l'L8p6Q׳_: aނFN+D*'$0y8{;=a$%g&?:U FfH})m844[&Jxխ:A~}firo3wguDUyY(K9{Br? v\ aܘX~Q9�y(#v,t7xY#xc6!,XaF4ڗ,`/oBD+/ciiiiv =1bFϔad 7Rik5uzlF5Wy64 8AK+'>z`p^\tѴEj\5kl¦/�6|YidqUHt^SHL"Pd8c|'EZC~չ\2RL2Rm#-/2q% ^0<PH X2"\Ha,ihDe-bT~:Gݱ>qɭcW艧P̱tfɜ5=|'tG Aռ'X&H P\GE<Crw__XN9/IB%8珗sv_sZDQ9T0vzGs{sqt*1xc e|i?V_Jڔxic,EM>7T4M4M4MӴAg߂n[@tG qj0m3-xJ5ZM m%;݇qh`t,& ,#s98# )N' f3#O\iS_^P_b JsCLM,N�f)Z>-fu7!C qh Ҥ 0>*UXWG{e[mn4tg87C~x.�% M$;#B)+C_35o<@;>{EX=?y|liu}՗&NJW򏝏ɱx~Zq�Sh<:Lw+dxy6mϸj9<0s()yw±?aM)}~"9dbzbK[2SuLh{?[JKxqY_�M4M4M4MӴϣГ /3Hlxm4$GgEAL M}),Υjf|b>  ⸮ʹ(M*(D ⭐g |(GNx^+/gߐL镍n /, H[v< C{J b DJ�#+B E~vi=|L+'`引<Il5e*1) ٕ8NCbGU7!kB8xm[);Y؇R_+7ġu=&'걜9^AflLGPy"<㟼<7)VNelnLʭ4''>^Mt`ֳuu"C>>\|mL$q;@pI{f- mBc؞Aqbct8?XͥCRsK.|tiiiiף3#q'O \ d8 xCvŸ`Qp!naJ}r Fz/D!E$Ux^{PtۉmZІFfĩo$R}ZkRze+?5\8},ڂͤ)VK]#RDLV_nUD�@]'!Uƚ6CK)7 afaM`wDx"O+g78iT!Aʭ>Ly`y?cOS1'aN,'gE2AYmvٹMܫ]z#ճlm=*PN-JJ)I,JKe 1/?ywJǩc9[XרvVoX/ < x7̼nNf4~q'\x_aj:0v�rN<?/<y3pð~yqԐ{WHr##8${dKV@Q \tr\1>?p-+p}t\ 7?fkiiiimiT (U>QkXn-0c *,0}mQ<Igxn2Q J kDx1?0h5l[9-U,!kPlZ`ZJIЖ{02kbl߃]p<֘Bvekc 1z%\#־k{YV:mJ%@q]<c*欫c\^ zD9$_퓟? Cu2)|N39+AO>o>O6A 2ѴwZRR2w6xfy[:# [~_{_U}quι+7;7;!=DY.!-.ꪣv;u+:[Q[V,KB 7}GHHHr C>pxm^~pT2}[}O?^HellA}Kr^bF23$wt=kkDuaFD5Ҳ2 yӯ]=>űivhמb339vd>?#@f3g*3%tM1GfNmW]R;!B!B4T<a̻X32fu9 հlC# Ĉ[ ]7pd3s@ +!FcˁÓ\Qh X&Tmt|^ңAFU5$is(Xʥ F99o N7|xluRTL,`ad]|lJ3v?cFQ\-K|p� KYh)tMt5v' )wWNJЕL9-ϟ ؟FynahNjyqG šB!B]v[Rfz_.Wױhs#XkG"ؒ EoӍ5\|T 3#@s'e4M3l=APM#5}a<df& xeV*UkpspQ$LMCQ_H\qDi˿' &8n hDmR勓UL$f)n?ȺH{:4efj AZ˨3],E8u5_̍dg?ENW)c"W}<#lXNHy?O.x !B!Bt3R_ ḅ,,D P ]Ӱ`h&ިMd,ĸ#!ɞh {$ UFl{U[ӘpHo|e5247`KqʊSg>XKX9aD7Fin&(X& VHӘ|h!&En׿f8I9L@t1=cabM6Ë0E¼i+ C�� �IDAT>+-:pOP|+#_X۷]e:CrW06 !B!B(݆L2i F1,e,dt~*Ӝ8- _ ʲUVFaƗ00 ;)daR&a:@~F3J8AL=O[JMa~L y !/HgJj9R^vq)?X&'\ŷA)/&liቦ%iL-et2KH5BN#HvMkXuMX |(Kmeqpm.~(u ໮C!B!{شo0޲fȗ3 !&Ȧ0mc(M#٥dsb7 6Lt'Y):2c-ĺz?#USxD_.3/_{o|:o3e@oReҠ>- m}7>^j2o0/Y̫Dlڀ鬬 m61E8CبHДNʹ\f )qre1Řb# @m5>UM؋B!B!Bskg6`O* SHIEg$r}`Wl^2o͑(Ѩ Niz:vPL8D>^}h] <y,hsfي-ܼ|+}49=zwaKK&jR QߗF d$sz ƀ~dy TLjqڱ^tƦ'1$?{j 2]3 pwnktbB4 2QB!B!mUe31 (43( JƖE ] R?f(e[ZՈ?bB&x3M\~9nO&|#쩤EpDbWa4<lֹc_ik_3r p84λ`Y|j[+8BNߞWm%jFCa)8PBAX0ДBCw 0R8b^Z^�fP#''m|/ߊ}P u1"%Ej "B!Bv¼ eh6ţ0N'T7 fm%7F)ppH ,L=7\y 6p^_r:qP!6[ ¼B_燜bzMi@Mt2%d7Xf C\d5\ɤp깧ߞä#s9B84-K?;G"33 ðTK^|U9xX~s=͛O*蓓%%10a+V<=@+! x9|WU*>JطѵF? MgkeDB!B!I&5ŅMu;h':Jr>MlXYeYQQ)XkZ#F "4{}gk#%48M'+~Xj>꡾'\¤Dd1rL 47ٞN :ZA Zw_wQ>9HBuuXF9O~̐~V,i(R4tG,~.69|zLFҳ+>%R1tN؛ѳ&c?KO燣+yw)s9jk¯ڍL.MTSz`&'sw-?U{Up5/y? Vb.B!BO ={2nX.YaC'_ aWe++I3aePS>P{U#8d`s棌TН9�)G0:X3N4ߊ34h$͉7:y.N! 7mu ?t K3^ycf%F֯Ĵ 1s3fQ?f,L܌-oaW4mM~t dK'Ѓ嶱ˍrf%SBjP*mťk>' Tٴ%DG̀)fʼn/%m멤p}ƷڏݷWs1KsI1nr˭z^B!B!"47/;8OW<$'v(͆"eH2CNF*ޟCK2ټ EhfAO[B 1t͙as4-Ң&Ap9@w2t;vEQ->gp%b :h0hn&řĽ4QSn�"QXKrX>SSfBjq4n¬-HOǖGz&Zv?`Lz ۂDEWcQWGs\1j7C?~2׾G橫/4$V-U;'LcgqßQ# oz/?p?fUOW23b-9c0i _qѩӘ2T.l@:9Ә[y,U<͸Ova7fi]EWqv=|-qIL> 43= ;Ҝ4\vMϠ0?N<_7)Sy<4A߁¿9|L<3x5fڄB!B![ݎⰮ:!x[.q#I2Bϩ\VX2 08zp`آ1VVyDӓT=B\_&`6�5r#4 oV"Mlv"�z4Gh4D<& G� f~^N¤$ DBqJFe`e5f$Έ"k JApdwejjƻr3E_͡孿0Ѯ:+Y<i1vn2<P7\{sǏኁxhա%7i8K=kղTf>p?'o[5?~I}f_ s'U}w='{2| u[w&+y~KyPsM<~c{s<y ?0:#3w^s-sy#R;^m}]?<S>: '(<p<vk!+;6u_Z!B![}>aObȨ88q+B$f[l]b}y3^e۫}6f{M^/~BhJ64h tNPiX!V<eXPc7ŠhJ BAjkVO)nUOjQə)44U-n#͵4jFC!0eEOe@z*ƪ8*XD&4bVv%k۽ԭ\ƶwٴXMɞ4R'OD<4tԁyz�haiƓMFV!:`SRJNz*9Îg@/ab~zQˡx`_rPGt7(:)!>T>ht2�Ҝy2Ʊr[CLcKQqMv�&2ܲ5l2x;cl|y?N7fM#oDHJTba sc0?{^{)+[ƮvuDu\c+d.pz3r91u!.jNwP;x,zHz&B!B]6Edn|H\Ӱn7hhܢMlsM58]N)iXəl+gtQ."耥Y(%Qt*=gBE5 `7kch1I)W�*\4V$Js]EѓSSt a+H0H417CxK)@EXPATdE(< /eC_UkQSB&?0=*tFOEPlWp/@]̉#p}͞]cmeBϴR:5Ÿ+YA; a[#v=RIm%; jo<8XtĥX0nsKf\´νj�S8l9/}څ]Ey:}RgqӔ}nl$Nv~ !B!B۴*JqHYQ7r`u9f֚֕Mu;:injcjܶ4X0 f�DPz MHFVE]t$H0B0f^X D#~J C#f >o:f,oG8qDu4,B|RgghSQll,VVzYn/-ii `(ħM>|m ?TBy97BQ}[7ЉA9y`Pn罌o3IR} &:Moυsי}B#%4hXjh-_$m(J©|4d|GWf)gp듗rP%Y8<z6>ZnUzpE:[@u*}}n3Cr]55[5Tx<i|;ǃ8A헾B!B!FNwj 3==9  1i`wRhIK'jXɆk<l5xM%w?[W&u5qFT B,ݰ:?Xq.r9~>;!r ;QtWWhnkbs9&h46'v`h,@$ iҮehhhD01bqY'JGi-[7$;lmPM43&V }Kӽw}xy٧eV*qJl)b"1E뢑C&3l@mwFnc?q Z?Z`_˼?gsm=5u~;U?̑wy)m[(^ˊ /!BIlpM m|گ𿫩eyd26uUW3u__w~t&?~Ζm|1 2)~{Tu !B!B8 %kN{},ԅD+6򒒨İ&~/7?ɔ5XI7j |H*AKAG sUjX >.H!e Ah{Ir�60�XK-a$'9H%7?)Sfĩ۲U>ʶ[,mFx8w>}Dc1EM25EԴEhF> 7gu`Ŝb%ws۔NOϔplr4YRip?{0Sp-sas]oO_<>?%̺<6q ?y.�,GM;3rr_ҧj:suqF2/s=R̼$J62Gմ{[1݅<jn<.vU듚M})<׋ g7_}wOm"Q}//A_{媳9xuQB!B!wLS*Ǐgm.|?bm|\^A樅eYXB5Pe ]37NJ\2Ht4w>XB'p8Btǜ ><O+M IԌ0W gv86n0˼gW|(iTĆQFzJ*sIvEE|2sm6hvpvBE ɸIGc5-'u=,+.Ї[9x3(7wNp>8;H!B!ߵSI.?a7,n@(P\CNQ>|8s|Ŧ& YdE=NGjjDm qH3}JjQ:S`[@u}Sl& eX[/3)m$;ζ 5U7Q 2ZA/Bfr3n,~g2 5&(Ӌs?41vt M#餱z;V[δ$ %QqK)B!BA詁&5'&QfAR8m}3(ܟz֮ ?&JRSH5Hs e؈40#Q6T%L9|PU47f8D}(HC  7c o PLc8,4eK˲PJR 8NFrdw"^ f*cQ:t2?B^ MvNIF]g5nbҏÓ#W2p~e!B!B�_-Bi%};}ufL*B!B!wM5y%B!B!BϐB!B!S$B!B!BOFF;m ϴĿj-u{󻓨vi]#B!B!MO3}Ժ =MM,ZoH4J4)i{)ۣLD4t]Gu4M#%%CfF:NWJD6#² 0hK˵{RlB!B!?4]etfjYYdfftuH4,XH٦M\.p:mm޲?uBkZ^E(m۶J}v*X@ @AAOac!B!B!~hRlXF9@AAa3fj))׷ӹFz׳aFJKKINNp`Fv{ˌh|kitJJJOmPj9iҤIqe~UV3z|G!B!B^/u{%<2;djBիאMZZ} 䔮Uzil6 @]}iii khh`;$)!B!BCS___2.3z2;! C444j^?GjƾMPYYaX6F}·xBN=B!B!BдLI2ڶm:az$i[00 ߐ?nl@Ǵ]ӈ7mqh _?=iB!B!N&U ^᭵M)_0O7c&<0J2oƗx[tM4weY8C,XI{u| x<umAgW!B!BVf<3w1x_pcKiޟmU _|KͬM>Xհ =u />:e=4%SvVJ!,|mXtq,-+Nj 3ttneFQb]nۉbSeZ:Uxs駟ؘL&Mȏ~#lݍ<@B!B!Dϩz}^F+^Osf2*w*`S)~dVK^ݿKb펳G`[EfA!)gk΃eՄ9$co«tc=Qg&̈9&-ߝJ>TYgM$t2gLm|C׺+v=O=Dʊ@:؊7ltm5ߝ+WrDQF]1M3ea&c`ʫ&Ucc#/ h}v!B!T-=t֎~�{%>}wYw|U-'wGB!Z>;fjnrl|2뙼>H؏oOi:x:+|Uk'=~L_>+OUJumg[;ӻK/ﭙZrZ{lO&݋{×FH׶ll[l-��IDAT8 TR^r%3`0g' e}'�z 80a=k׭?6LdG!B!=cU}ǫ5KjV^IS(7Ok9q)מاe{ܻX'p(Gr+X2\ ~"Ԃ}y>*g8`Çf{3#O^oƜs:(-bs8 s9@t;c"cUAҞ ]D j}%>);/Hyv﫹az'7<[Y5Fn>bŃξOIߑ+Y{ ƀs/Y^V Ͻi3sLegPν [UY>\Gy|2閭x_>x]Ɲ}5x-K^y?]6Nfi?xzC7X.C:4c*eFtu.wgX^ߖ:fJSwڥX ]Bh~\v w\#QHۺ)8`nCPcT{B!B3*$aQ؇ގX# 6:#q񇱹\).nCfϯ9[::uBT[,/|</?yzu޸[_jdȉgˡ؂kxY-JXG{16ߌ}}L߄3؀?Ic{hOML. \*4s3Tgtrq{'=S0 R+3_>p2+qŦ?D-`Ӿ,Q?OM Zn>J\|7֗}t\58|h%ih ;#^Y}4/T�ZV?{Y /?KFrmn^j/<E*^O[gu\- <v SRx̾N~.(T FmǪ.ӀqOBo=B!B!p Rb;0d"Lj 0(rw0(ck|k33e'0?kx:v&vbFY'Xt{̩+tΦўj.JRA6)+Nq'Cby˵Gʞӏ`DWC^?Q -<'sH' .IˣWP-yU1`]{t˚{l>>[Z1}{ؗ]Hԏ)K"7G_5^$ gpiOʼ6s_>tC^_Ixp3ЫoѴd>qnICj}UFxLOvweGzvuڵVug̘^z0/x;wG022cTnӺt{B!BCI#8Sc?– !iF's!y߱eL<eaʍl2䠒w0t�-%TGUM GwK&%!8rw<PSO)Q=3=&h.2]PLPm虨O%0Q9]ffz/ڴeck&u`#+uxxJ$|vSr#B 9W;PMc蠂nݿNE6mݓwon#v/s ߱W`Ӻ=}Hj*\xmǜq(]1cƴ]Urٔܳv[w!B!BFA3hnԓ}kd@]q̯g3|g|;<u[9rxH1(1,(tDb:_spB4IV#9JV\_Q=.k3a~efzvѱOtB7}Hf̅q FY_&o& 7JMu_a)۩Dۑ%8edhɎ-@a|hY"˒l{;H]?*9hԨ~+ioދwy.;݈ӧsOSOmk9s:L]#ۍlL�֭[FnF(--Ų,֭[@VVVB!B!B!NrV^}i cXŸ6IЉW7sӬT>K #]~֭-Q~֮$ر==uU Ǥy7A_?=4hVEv8p8 xj^ %[*dR) /mǺ=jߏ pk)9϶awc b\rF~)]~,D$сj<9=[/u׌N)J)9.?ntg#�*?0%]^VO5VRjỲYbӧMv4駟^~ers² >, k?~<:�}|>7|3�l޼>a„#B!BP+VSO冯y$vݐ۪Vxp)˛PlR$[Ln<_LĀ uRF3Wsx,4I¿cu&r::ӧoxmb�T-ۇTw:?-{‹/0u?#RFF.}J\śb6FqBnyv2SQU)#ɮOЗV^u{)\5rG—ߡ]f[yykcp"ǽ3=O-)qɣ9"n�i0yHΨ>xGr±ܫd!$ŷŷsݽʻn~< *Jw=-SEpk�j4lYؓ4 75{6J,׿dffv+v*LLǃe;p'c& RJ)N?TPOcw];++ 'pS=G!B!=c;K~ ~?2Wna[>bZY%qeg1: NSZ3<cn‘=gaKCνK[sXؤշsm::\ C<0b0+y7nax(:+8n ?c/ScbÕA{uO\^,Ne3k69^9tQ0`G/ѨFJzjQx7E^^jwW</s}y:֟g\5)s xI9\/''ӗCe %(K iZt{{KZ;6 4-S5|M޶-pBDR_ 3#擯r]φj kLbŌ9\VxEpa-r͋&n*+ݻ7rnٸ~kB!B!?+;~~3F8 )=p-k'-F{. 2voEu?q۬ ɗ8]3ѣFvaa8'n}3S~JN~MOKh6T-Fі͡vs4?PRRByyyj9B!B!EՒݰ 9ϳ8q'y1)^ sʼ=+/"m,GHbly>c$^t=Gfxs˅eYݹ+ks36m_O<oIo]Jk rx;WhHt4nשiځkB!B!~T xk~950ʙNAQ38*c7x:?q !Cλ,#faxpO3&gom3Dv߮7 hhuu845M##=:RRRZUj ً!B!JsssϤh^sN<{pFFfԜ[wxJ)|DQbXG뺾ן]|֏c:q3Κ5kde%|Iu]'775kZj0^O;=B!B!BNn>dtԲ2;ejFzZEjJ*MRRIIIm>ۯ7B-&-e-[[ٲeTVUQXP@VVf:4MrQTXȻOA~>9g:>5؛&%'!B!BCiN=zev:Zf'Q[[K}}b1Ll]i9ֆjaNfF瓜ܣRI `7D"!">=B!B!BtD"]Ln3N΋HW+e^sZ o?~Ox D=B!B!BkFL啲ǭ=iOo庉H(B!B!w@et !B!B!H)B!B!aZ{qW����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/album.png���������������������������������������������������������������0000664�0001750�0001750�00000312512�14035600052�016207� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����;���R ���sBIT|d���tEXtSoftware�gnome-screenshot>�IDATxuxG7`'v Ȗ133˖0#03ClǘĜ8:lx_jHF,g}{7*|'=:H$D"IdGEv/ɓ'|#G>򑏻Q2de0׿?H$D"ȭdC]іJvs2qD"H$Dĉ3/D"H$DD"H$UDdI%D"H$DYRR$D"HTyH$D"D"H$U P_D"H$-JH$D"Q�?OH$D"ݰ*a4HY%2?5u.W0WMՏkoFgx%HU:uVukS|q㪭5oHt�?RS4x,,→PY7/Z/u5u.g1sc费ش@u1b < Ӗ%㜪ˍ|όߊOYTPVwkKǗ^{s31H=¥W4Uq]s}*sM˺",J N3_'Na֊4,Lki LwY0~pa%ϴ`qcsu\ ~sUϾJV'1yႴl,ʰؙ8~ilݩ_eSV8[\]V.fu1ϿB<StS/J/6ύy?wM\]۪ٶv<<~aZm_OYkR-Lw~g,JkO3v8w"x~ﴸ̴Jw/A/w?æ~gm8i&FY-wQQm-qN{O,3yڒo_*ۅ!Sh(L_W_c~jO]dMez?b_:<7޹<FZ*UϘ/ZlG*]P{PiKtOOL ݵ2/% S`w>Po{ΡuQGu"U]=aÞt9דvw&mUl[^C=&,XAf>GNYZ=+rM\%ϻ{V{>?sؓk)yMT=<Rݧ# eU<J оq+XZxM|K^}?v)(zY|^NǟAG_׿ s/ཏ>F Voۭ_¯(wJᘩnw|=ei` gi:w?`p ݍN|3/ ڋ/q&_v9ݥ~ͷ?m./Nz_hEPI4\3,пQ?u+w u_{g)]{&mU^. U{Ӷ᧟q~ǂZx}?gEIeO?Ҭ\7l-{r-E7POJC${2@7D7̇?܇?!EcvYϜ(�vuq.,>|@c|.1ZQŗ51^~"GwA 7囱f6/v*wb E]蟪z}ܵ²vu9{!詳.ߩ㹺gx,#ϕ(vWszݵWimRֵ:;s.]<<m{NW 8YTo~gEIimY2nދ~u=TzMܼw }&\2 Pndg2ȿ0 S\|q3 _8&t>ZT'+n/xZs\*yZنtr_C'3~mv]8nCi!rŮ>^LiU=]owUZU]g#+^C=iAXgk6uՑ]uSϊ^Ҟ#z=&=[e]KQ\mA:V]84c^X@U(׿D71V<tTwG'*a@i*ɗ*_F+:g'qMBg WumǷ1`vCZֹUuxUmE! cصXT^;IǞ4r,;|湢kA0t]~Ew1Rj}Q{U=C\Oi,vU{<iwwmRVu?]Ͽ|Xy{<zC5V8VMˬgE7UT ~GVYRT3gՅ:V]\O({(.3 PnO>s a2Evɳ:{'` q+y3܋QY\J7XDg֣s)~%DwG$ g W6"=l`2U±`eYyI1,hݵAiׅ@߾F3%_Z=wr&%mUיK:\,zyzG,`�'aEA?zVxgz) eKYRT* u@͡]H++#HVRL7C!E؅t~J7Cs83]L/dօuww.eUKXደd(2L/wyC2KkҮ [}?\g\zOYMJ^۪3e |>˓{be]<w5)ٖ^wcyLxr-EY"Q5AO"a ItsMiSUGA$ PDU,cM̵thi'NyJ{D"QIR$F30n"Ƹr6UӟKC$�PI(D!RڡeI[D"QJR$D"HT5@?Q$D"H$*(E"H$DUD"H$DrKR$D"HT5@/D"H$D�H$D"jD"H$ʭ"E"H$DrKR$D"H$@)D"H$D"H$ PD"H$(EpHH$DU |ڳW'O\M,y*yҖN:~Czž9rvكY旺}:O]nէ<D"ubM^rzK/)ǟx_|%.]vC_.;jӸyNR$D7PeeCEiO:ĕe—sڹOcaD!G/޻eot8lشF_V˒LCH x,Z/lEn=Hhx^Y*cR_v ELs/gX#GW_uѓT^_xVXW>}o_|_ ;O+6"sq"%|D"n#>?:Bp=~BCƻWbI V]}.&6ot~-AZfV}ΜU&e{eE�zRNァ5zD\ifk P6|2ks8Uq>(SLⶒrwVc=zy]en'}}̶&S\[Z~D"HTSfPS'1a49Sز}KqGi!c({Pdբ>#mswwɺ;ʪc%W_{hmqֿ+**뺖<GOSU<96n*Zizq ĩӐc3:j:sV_O+mZD"uqro_~Y[¢:{~e*D5*,vaZ"eǴzrUb|tP-ٞ\�^+rʕ4lqxz9<iz}HSv3.dB5۵CO;O+ewm-D"QJWZ&LAuZ\H/`&tuy WuZ(/Xt \{U4i+jtw>5i͞c{\Zʺ^ݰ&O&MX}WbD"uqqǁy %BU\n.Y]8߮1~׋ݼutW^ ݹW7x"/o:tsrm0|Uڧ"ǩ{m1?d^.~e]۶#k:(}W`s %ǫD"Ht%-R6=Б# <LЃݐ&-=Kz68a1ܝ{UX>}ڲ;'5KJWmj6rVYכW.R\wB)/oO+g/o>#?nH$D"nIbRD"HR$ PD"HR$ PD"HRR$D"H$@)D"H$D"H$]@;D"H$DVP"H$D"Q%@)D"H$D"H$ PV.^ÇcϞ=uJӥKD"H$@Yaرc._\:uN$D"�e {=uJuN$DG? s<g0s9M=~Jv->:)B%(H$D׿+ >!V ibn7{`>9e&sb쾘5s LG`^Hc;˰~2FGA#ҧ? yӺbԨ #za{{ChA@<s 9ӧB̮1`4thUqb8臤=a_)s`j;glus'1=0xP,H 6P7PU4%@)D"эc.XQ))8ypnYٰ-w{bBfwCyh=<#Vh4t &cL߈9pҍhQq輢�w{&821<hf4_CףŸHHƨ Hu+1aU62Vcnn:B߼-OGh1v3BAĜ٫RtC:fIEHڐuRb{JD@c@i P֎L}]Sѭw_+*O$nnV|tOJAnYh7zdQ4\}PR7;[w-j^lOBYj뜅[.9hSmWe4앍h? XyOW*ׁ[Զ}Qao>^4nGS7[Ө׻fALUlUURuk+-1&}2zT6q$;–#63F3((kLZoPٷ?Sc]=zu8uѣ_tT?!(&tŐGG/k0cμZ96lZN^"Q-=€92]d=l6tb7oN؍))y"wòt;u,[3m&vmox3—A%[ujUoz#}=/؀ ÂSǍIb 蜲 oGĒ \oUemFU=3)xp<0m 7b bun;܄+21xDXo��e[4YصDV޵ َ\}{o/O<1'ݴ/?Qu9sF=K7,ZwGWjXѝAhŁAТ44Qj4~t=ZFעp!?` ؈CԶGVh>תmJ7kZO^;n@a U7 8P)@5yZNXU}עq<4RǽU<o5n ^zע ڎq`F~ YYv [uxXjآ\O^vӖhc غ,yN=``-wtvMLZ]UYNQc]Zi7O<.6k\'L9 W{X}?rTwGw{ p1vB6m}t_yy '‹1nDbj)ӊڽ>_|Qf^Oi?c Z@Gu b=1ob<nGG?Q,u:s,y O1&ቧNj =Nk3{R֒ؾkEV4c�GeuCgA cWr7W𦠭{>n首.jJKP۹ܭ0R<C=TZPk=Y[( :РjG9 06q- ;;pk|.wE#I3ށFyX;wVFIEՍ`X;bצ Ddx`bZs P P_m+Η*a8LKUY+<sa ٝ˴Q's:A*5t(0C(6SVTBY<hb^ ,MK8Yv =u2h 'ѣ9v|ۺ{籃tYˊTamB+;<@n5σ'g1~TyD^kzPT@FAd@v 5 46HS vCcr*л5.MT>(>ǀ8A#>uYF q[FMTb4U ٌe- -m94 cU<4Uy>1v4u(,0R_U[2lCH\}qU9gnM7P"#j<�ex"q+ g1,Y֥˗+%l̙Gg ^4Z<@ZȘo/a-i!1(JOuF;6wѝYHY܅t="Koi[v BX+kw R|1l:k0;h?=on&L>(vGw"/xk MAyՖf*BDA`+(l F(Sy:q-5S[;ڡ[Ejj?Wt|Ծ }U_C[IUQū}T>(:v*@sڧiLU^cU1CpljI#@N拆fY^F1>f_9rɲ$RYt.�Q2!ל,q&v-m_n,|& ( c.`%;wʌY>u&ǙˆC!53ظEOݽcvݫ_tI>-=huUEk˗.kMS yr/{坃2asqkt&En5]e8 Z[X *CK-mYUE<0z)W۔~QYW+SPOQvD2c 8-Lx}ձղRCoEld߾o7E{]Y@ɠs]U{|,-/KZYBP~'R_X 9p*Z+U()ۦ5aۼ*]zyV'vcr;DŽ%ʗeY!+eހt*}Mi)KI+,1<~ c8M9[ s{zV\G~RwJ(DJd+=k ;w{RX(EڴP_Ÿݺ 4YT,iV RbO8 X22^* *VH0U`S0Hp#xF, 2"2vLu_1li^Mm\`j4ꗆ3XAI5=yb\%_L[e+ѝV@ik:Mm)Kl<rJS敷(CW/f{^\<@H)q+ fsle\.oOϯ'O<Y%?6e{x;^/m]V;O6]1H0{˲<?*,C)2P KƖm.[V%ECUfZS`/JFzG< 0gUۢseW@2v|$sUZ ,*Զ(, }2B Uվ*k|\7)t�1 k(9piK_)PY,zg+\CE+jJNuY@9lhNp<\@1oV+ SCh)S=Sڟ˕qJKBzJwGC2-ہC뺹;6=ܥǾ?W`Nݰ:hqΜ3<E^޶.O9/YBYm˛y87uub=iutVbFiPUVuHT @y{otX61:ÒeIUP o6B]PxzNgԾL'Px*R)TyZ)h$ )#D1]i@`,.?8Fպ!32S;e*[stԱiTpڨ:4]}8Fsy�ӧ403/Р1Ue| @<? ,ŧ~V*PW ö%_ 1C :ܳ\@IZp< I=ͰAV#y<sP6QZ<7ήPܥs,kc� -/Xf_:P˕T:0JW~q:kyLv}Jv5{e3_tٻ(eYhyN;t^b!üouN�/I-<)2Uӓ^^"QmX('"w.Gk<xoJ&# 4i#S;8H2,EA]J)(T-#8 +#Ѫ#-S�ڵ I@U3:qugS5g^(Oul/:~ոS&-Yqٴb.^fҴeBgŗ)Kےm(MZ4PH [~G  ?C ֬Ō9sk<̔#"P1>I(oZ@(*4,Cwy[5fj tC Lc6Q>l lQO~nLN6)q7aʜ#m5ZG*p:$"Ȗҡ A*"r KiyjW-cX2^&j.H9)hYJgOLwESp@i֢�.]Q P=O[o]4FO~޼j"ws;ïC"KT�8>ew�%MKeaayB@xVPX^7 ?{BR-GfKw|e],t7vQN{]AyYVHJZ53 [Yrъja][38^a P*@MOE|4\X7S^^%rV@D:ę\ݼN(]2X2uR$;7tT@yORc1]|EѮҀGB1v�Jm-G[ڽ�{v_5pc YgeH ugϛ_5Lhd|U>fW0 :J/fnq?PFAYh?\E7G7"*o7gqB7 PD"HTI ]qIы6A̛N6JFZ" +N(0A*?=$idWy=?q6"SJoax##nOUe˻cع5,\~R$@dwEe>K?@R[&iT<d#8@-jز4*bPf< lKoJ֕AZN9ÏHD"wF;eR-ʖJFIHЪHa҈ oTf E|<XZ*c1r:$cH["Ejo@?7`ph`Qa@?GȕjlcfhT҂ي�2J: q6k zx9ed:M6!HBW5P^aut3L]�JOWyD"fٝa 蜎;–ga<It㻰K^ݺ;̰(PcI‹H\܃gV.1if$N P6"Q3N@x͑i(Rk:㍎ϭ㋨{h}T;vLEpHqI:1:V͘ɇ3ԏFΙxpB2墾eؼeA6 d<Ēo:\O@Y]!DrGm Iha@hN6 z$-M@D&|-F8_)ˏfhK?TN]p9L6Fy5KdYRq¼h]hqd!KqY|V D=~2z<*S9$SѠ6TMNgUH^̲;GULWѦ^,PnشYO W؅YV>Lcse9v:|(W$;zd36c6R\f1Rt]}-g<BeLBxN@g.<Æ#WdwQQZDz9D".<Ritx)sc9FgC4S2 ,݀#W;ځ,Xf0: >,%e,=NJdF;Ysuw*5Z-H,Ԟ~)'y4Lvsve: 4dG9h-Mih6ꁲ*'+U ʺ�%g` fˌmd Eyy\}==-9GG[oVTuPd3|1;y6cz9V.ݴ73,]Tn eUGY@鮞eH$Cn>Y;l"tZ&K>4�2@=AUy|z@r=#f-"shESeyQ:ݗsys&p PIXLZkgaWi 9twpF愤?4Yí ԋMFhjQPa�;fd"'7/^X- )@!\cgիYqVh|ΚA38u@k>Ŏ`(.uIs!h39 |E<Jw,E"HT;çl GEːS /K%Ο`z4$?{^ -iz̥]Q66 "S8J%ƬòذycQ>p8fYi<pFh[ sj\ƷCLC:�0*cR$l1siH.fJ)nXsS>zL[8ͷ-=}8Ѣopx;ϩh 7~WѷvPV<Jw,E"HTVؠj7w&m˻E 4 _  }MU2f2rAޫ|WYr 6+p{CCxLA?.]e;`A*PmE矰4#x:ތk{ "nxX̀h*گPFQ)�9> ryX(u.;[~o~ʼn=rx<Ҕe\ %-jxl}MZPVUA.'A=(D"׿^DegnND3rOBK-mۇ] C s]o}`71mQXaWTD3غ&&nŬxYُiK7bC8Y8v v+L3FgYt8nX;8{^Ǟ]o"'LswX/i2$YGBϭQh$,A, L-Ce籀g[5~.<\<9 =8Ills}yw4zɳ+ ]Hv/FҼ<ΊSҙc!مzu"H$*c }� "4U0Ԛ%-YRji72ms3l+9g"݁`ȓr%?͏`Q:$ZçNap�;=۱x\Ae1Ş#w`e9LYxFݝ /:4PC~Lސ^j{ehbB=P P6Pyy#)%2z@:uQd k8%=;]<6j.+/o=8ÎV<D1B.k(uvvy\ʜ-F.޹goճsD"Z;t92chfu,3[wD:"Ru85C6 <~ б:#Ho;={xҳx=:]'ϝ0!i;}GRyXwosT}蔧w- ҁ�K7wa"N Z(`2襮Q'tYTY P PPz]{"ˑ+?T"H$.Ct%~ 26^Ve).Bd#D)I_=x6!6o q] \)I`>ЁysRēϜGަxЦSGs/111R%c,}UƽS"( cqK|읈qhHRW_}gD"uL}r6 -LՀGcs= cmrzCl%-NOmm˅Olf3gq[.>ɉ; <ہ+W/bM~GϜBr^<{9t蛏({Q@u}H#|i@*/ 1Y/ZO6^B6$~B>G.@izܽG~D"Ht� _{fil@K[iuʁaRٍͩ3k$% :�,c2 E.GYΆù'&%<Y); 1<V{1f6?Fz!P=Owch[mJF.C_̷MK?<iKpE.z(4LzezvK^h@9u[$D (3><7Y均1y!LRLCE]9ȷWֻGp1J;zl>}rayt5 6R@<zO\OA> Xl߇Y;qش(8wv0IJ ScgQx'=_:|a"h?,ݰN2Zg|Lvy7bwlnM0&)ȑ#:8_|Q': PbM~Rsf#3=vmOڭ\` }z6Se\ ˛"Ӎc\e<-wF$#0<UP3yoLb8),ۋ=Na'0pZ\3g L\ })7S+.l˛c##rtmq:X'j6fX[_X;|hikF poIpqr4H(@(_{5<HVaucoFL8_y8]C :(q$Ӹy:Wr<VUY8X;%qĺu59ԙt\kPQ]-ZHcpy ,9|]�,Oڧ.eimYY< '9%Uqnݍk:&⾞90-bUmWM9'-Ws< <#yW hÔSش8= (_@q<u<W-ĩS ZE&2Í?RbԀcnn]9|xc{[#sq\u]&8>O6Zٵ\:nqlߡ9ݠv #ζzy+S<VU>clߵ VO?N%G<v^9vug!i1g.YtNv:Oڧuiy<W]zGtO Wbc !+ sÒ)b<yv@k_t>r;v~ k>5iSzdj?|vǡOaQ~[ P TXF8 eVQy(u0snc& K][Hi|'^hm7JQ{ptZdN3r3c%c*صm<ViK:<9m@6-'1iΚq,ieԲRr;:k3B4g bymjiow鴖 :LT02ƈE? Z\zdd[^aEi_~UE+\:'uy>( ?kΖ`EDj`ϋ$ cnںeلnd!#Fjwz(P.C}IoJ(;dm4W; R@RGAUhelt蓇aǁX8[`~.Mpw ҃Yr2r:T X9F<;iAfxz3 {<wB>n霃4OPr6? &tE2䶒S4 ,1%A&efyE%{:yFO˶n->γ2-iYJq*neo-!TT{;/\Lѣz[{nѲD{]cim ЙBs51g^Hxr_ ә-Tf)Փ ێlbsuFw^�e:sF p7�:u!(8/ ڍ[xβޑ K#u;t گ(JNkÕ IQy<AaiE9wǣr0BV;zOلO R madz?'NAk�ð~ZV [2nm)1a8SfQYh@FjC3(E&4_PO<<yJ/Re\-|)0w-/Ar,';fE%ϗieL|#Jq GCi|r͹lZ$]Շ5%aôAɶ{r4d{99>c( ,&;[9UgyHxr_ i]uS@I맻_`ٮJ+`K.yT)YCUf͛e/{}W Pwltf+̒ K1,48{F`ভ D9 2(L]Y@uO o!8yG°u-"(8`4(ҮQ[D "-<[taŮ⋺Cӕ<s LԏARw/@)]/鳍UBnktQ/7;m^U* J*ROwJvol�8/7A.RL3拷<ʣOTBܝ^]Zzɴއ/F[q O]-BJ֑A\Ё M WE'jO!-&5FS(9p7f⤢]bϤT%˦5.IsJOs#ୀ{d Y9w:ZX;_Ax#@2(.iz< 0`:҄!|)u3Y茭8p80ފAfnlBdE ]A"0n s872@խy,& K#s(E # Y3}Ec>J{TZqӯPzR2Ax.Y~e,%-|VhQBY])T>,/<?}e"Ҷ3�Y`̀4jEoya\'uyshaFn誶PgDg~;5sgA+[U/Gp6pM)PŨ�u6l]ᯀ}!45e坭æR8Pc,e@LlNj8Т8PI%AO}qX}Öa&mΎ ,:4 iX&9&Sd7 QvȜ˻p߈td . PtKs>4]RT@`}^~8 49w^am֊Գ'Iٴ0/YfmQ&sUd cGGT8U}a*r<3ER7 ̞JmJI*{}:'}]6Q:p;�J:q yRomJn+m %d~톍փ׆`vrZuV̅g1tJy L4<؛6S\-c򌹼Pnmk*I˟ r Ty -JNw8g>zwN>ОGT`^\.B4"`Z@-OwsE]=MdzG9 bqh%9@RT@茷h8ün^hJw1 yt&MO?S+r,o=^Yv8e /jO]Z_J*eCg򎡤gIO"S4KeWUOkw(/Tx.Kއܽ'RR]�eKO]w3< UsQֽIxr_W T'E>m_= μ>Qͱy;v�ZEL+ZrZ(Y(/4 dUt( ln~]aFW2SX8϶@yOvpe%l;ugiH @:NB$Lbxufjx|=0piLֽlv=dܒ$�# PdFx ^+J[TJ6Mƽ h6-9 $-7x:5Xq"lc-%R;XuH z?^mH;;c'/ 5!P( ʠWM\u<SFz19Vu.-z#:ħehy X P(E"JHTe]w N5l.Y O7bXvDPYsNXE RLj4`�@(>g%Řy;Npa\I¨/nB ekxJASC['RK$aY\IUhqyhz)�ޜIxy(E"JHTu@ytMmÙd`+K:k13 CZ% =Ìf7x^HC&b|y|vu`N~Seh%- v5v# ;IlcUZr^Ѽj -brշ|jKCL4 _u ʌ;86�H$Du(5P`&- DTuLB@FIm]Ԏ6g!i:Ms|99LJO=߷Q_1?cIZ nd7ZUT0 gсs5|9vKA$Yfj9ZP/."g9[D&<P2nӌżߺtba ^ s>e^:0%6ָx:UYuԕoJH$a ݃e.h5^:܎oX_22]`V6,9:`'C{V3쐏,i@J%T~i8>,_Ka~2W%^vm 3l5` 5L*y-vrNc٬S>Ql6wBi+ݻ㢚� ={#DΌyhMV5~9w׮}O?L <c˼l{Z\޻3圶 "H$YC࣠n9hc[;.H)JV7_mQYX0>DM{R!wE|Ǻ]/aJ㘟uY/fE]nGg<-< &/>s$2=OcY=n5 gOO ;_Af.9PsπUOJ¤P2L f=abe1.ChC4@, 3ƀInD" ^l3w-AZ+6W%[;27g76h*&ҟSH^}yg0{zy.b^)Ypv3VôE؆Ǫ]qGl6:܌eg{Q@2^{X<&,xKNa͎bR d}&Fpxrf"H{=G/m\u-h1� (:ǵϜ dCzyԩ9nK8$h~RR$D7+P63y[ 9[mChFʅ/R#RW4Cq죂6Q+")Ópgd Z[Sq%w+p{JHTqW mC>*?WQ3<wtzGMoۈ4UVGy+\Ic9 =Ӓ n4ցFqv4k|ϭ}/&we rH2+E+sa.;Z@YP)@)Dv #6txp,F1r4LApγxEQ,qad0̉#1.b"E>icWeklL∑>3"ce?Y//SyEL|,$$D,@@1{vj!Y|B1~hnDιg ʨNorXT4ۢd= &{R JS)3C(E"H$F陥`l a%bW! :ѹ:E:SZ`|e#HZw;-Q m,Y=*m1l%Z+Ȼ=d%n KFj=$Y*]ե*uXJKCmø*Woo,*mIkdpwH3t9Ju,t44M2߹(mڹm׵ۯ恮kc(B)D"Qec5wB bru6?:_äLK� (C*u< yQyhi9#NGZS1A:&)5փ@Rp:4'f)Pi:_+ MVIZ$Mg!1f(%[h#ˈ f·Q'uys^ҷyG/sټuz*67tipkZ1׮]H$ݔ@2> n/lC@hK_B/oeLj諭F<HƊRg 7) |d9گ@�RAIU@ԁ8;$! KRn: (YNWl4LCt4LJG>P;tSNrZ,.Y躹y\֒ys2TNn^q(#eMyyD"Hte+8c U I;6>q csW78U2PA(Z,cHǪԖJC {KYK2b̢\8cto=1S ʕß0a^ Iy\]AdҀ >h hb?[6|Va6lЛWr~rsVj*H$D7+P QJD=L<uJ WS`X"mXDOov3cBzeӮS)ӭvm R2Ҙ;HOhG+{t [Z'-SJT$#r-Si*O�-B$Qe(r%#̖= cOAˇgp`>@}]-[qi9A껻kbH$nVm7 hWAa4͕Oj9&,k qyKG'@oc*lF7Ԁ\=v+K;p2Ӂ@N VaIӞOE`ceZ~j=J e=3/VoƑɨ~þ) ^3j~EBei!b mݱSnLH$DוWpצ[6|'q hs-Z+'9'7=.p:xs<@j%-VT�/McFB%(mÂI1, 7o]ޡ)V T@1ɇßˎIdX/I,NKt4LECk ED37= ͢ X@Yُ??ܘ"H$+tۻ;9 b2ܒ/q^a Yl) 0#=^a)*O^ K/ܮ3<MCvS8ZKpPĠZt Li1e2Iã;RKJfU> %{i;<-b8l9.F=28/ ӴQ�H$D"*׺CoEFMG}hq|`g) y=4 -TOES|TU^?-nh?]<u K*d.Cf+y "+3L (߃cT~`�s,z`qh7A&"򆏅_<�.B9w�H$D"Qeug@X|cs6ʁ3aw*{{v#>yg_^xp:^CAka: ^0t#>xBAAk2\m ٠"lz Tcwk.!bPB8:PA^h#tUqO׎]ign&^6<}�H$D"QU(P>1+hƗ30$CƝc'v|8o1bT׷o1õJAЍ)*=Gmv4Ru~,q&N+  ;Kav hROhİL7BĽѩרRCR$D"ꫯ{(`E~΁JqkhEInhv{OCwA6qm=h5mҺi^h4momLm~G/x7HƷwG=A50Z#UoWefmzm]oK@cf:ip<M;گiP šIk~gO<<- {{"hPn{Іۇ#{?|YR$D"YR'Bs9JD"H$U(E"H$D"H$D"JH$D"�H$D"^$ڳgH$D�H$*QC>rGPD"Jy1GȽ @)( W#�H$|"#�H$|^�e)zqabݐK/ \sPy Pظe|n{.n^;[1KGDբw_8{[s<{~:(kim;wc_�C'jXU|P֥kyvٷjVwO?D"?Zӟ'}{j<oD eu@{zMg8wh0/Te-r(<P%Æ_"UxjK-sPYJh~W_|*tϞ8|>s\SeYUֆU1̊YWe+&b%+(DI"9  &2s&,Pݙjk&yݕo=آcl|"v:5Lt孴R?-۶!4<K*46o:"V?w, '7VF+:68ܹk|;vL'-%fsXm^̀Y_|)dV(3 aصkz 믿V7ͯʍJ9!Ӹ";8zß~ V<V(,y;%-]կb{֭ra(PZ6R aXLM3IYCr}3wk@)#v"~S3ʺ>.g}PzJ0ik3f|nVʱy*^ɸunoa] ݷG4 P S  ,4PrMm^7CԴ+G Ƙpn( PևfwO^]A4JgѓXRZBWΡRiZ)+&w;9.N8e>=P{Hۿ_RRiɲ._ V{¦:�Qb(Tfvoy=>P.L4$&d<oz%ou@ub3_|h T \\S%j@iZJ};x(_ѣq7Uc=c43 N^~v܉o<2~42S4od(RRP9ƘDgCYV^T58|W}wq'&i uL传P6PZ^쁃U-QJ+=OWW1~L(�7|L6 ƍ˱uVFlվSS5n%dK3J;JNMEm<NwNw.Szy;W;;7vol~t _Q <S쑾&6VfOo~/M#j@i~P;wFDd4:gQJO#4]S+<^CjB{^޵ \&ErؕM&uRث. (lgy\>S24r.PMsmGif&LP'4c֬Y<y2?:s_!!!2e &M`srr0sLMIIQӸM7._XX7~x,]~y60I3ۦ>i]PZ #G)p-O?Sƌ)y\rwa6"Ho[NJQӨ YrHHz+ g�J___TG<N>…ʫI&f͚*㤇E+V}r֭<X״4,[L`nߎ}=zVCpZm弅zt9g IӦ_q HM;\/ r "+" V}ɇ=WN@1111c0Wy橁0{n{JzH84.3g^G.w7JšL?p@U:<m̜m%j=l|~}82y\rwۣ>2:Qʗ$~8U "+" ;ƇscƌqO>Dy0tyy?&]]Mkj Hr=nrלpa>U1;.3z:`ghgw{f@iu;l>Ёrǎ4(zG OϿcrRԅ4zWwXVV-O#�s><&&-Pݻ?CZJWP-LP4J7杗`a&oc*0YSHHBe`` ٣<|'%%J}~^^ʦ갰0ӧc˖-j(c lJ13:%P2Mw ꠙ#N1J+XCaN9s/֭۔)pYce D>s꓿k`I]I]sܾ}HA9uT<Ʀ|2q*sرcUl%5JONNv={{};JlxkنPZ!/7|26pYc,_cX4K@I6;lv 5a5ŭ3Ϣ{w \>="H$jJ)Bd<l]PVBb^I ^wN<.S)@)D"Jb*m䩖quif@ig[e4zwz⭞wN<.S)@)DZJƒ+*>|N (mz&iu]FOD"�X6ֳCթe]_mS$d=/@)&&@)@\yq9Yu5P,nϱmY&6j|0sθqiᡇBlll_L]r%ڵ fY&yp駫ݻwWc Pkd43rz0wwGip@Y[9|I 8PA`3<Өף>H5cAB7|Efٳ'ڶm=PD-ֳ֩e]_mSJ>ЫW*C>E]9M;wq}mٲ%7TRRRpw(UW]KTƚ*;N+el u9ޱc^~eU9⋪3q;/75c>9W^y%!-Z7}݇M6Y/xZ]2#ZכrYg)8r'](3ϴts^YN+d6Dԙ&LPuy]N޽{q뭷::s=ضm[maO8<|ǎFR7?c <j__5:u8Y*""B=yDeCY0JOiVPǬVZ!--M 4}A=lWt?^y:wޭ]~, /`_pfF=ӺY_uͻ}Ů]\7۞5o94iRef&P"!!#ыD5chU= r PV(v)PO?}6fV-^{7;7M7kMw+0w\l5U3tfel,u;4nm:^G.B]ǎga(=U_u pCUI}g-Zh;˖{$bGL68zcSf`ٔ{wqm~rwN4߸>'|N:I㧮R9q׫'o0JOiVR1gcӫ91ny6bجfu$}lӦ]&/[=y.`233@)&&4Lf曕x(7o\eoQ5f\{ND9&颗չuuV꘧s%$? pCY[@nPچ~[WȸJ3&*e4BBBp饗-Oa4oĈU裏wSO9ygϞmݺUŷoܸ۷wCj| z'scJ7wj58ؘq!;**Jř2A o„ *˻-tUꈳ\mlv ٳRv2d=kRax )aJeS^f J111J"oǣ`惌nl䃊1^lRc<^ތ=dǎT`eͩ@`|8cN9b\… 8Tc5kL=yN `0|p<:^'(]-:,W0ۯݺ—6rY,¬n1N=T̡~IfYWE~5bbb"H$((E"H$@)&&&@)Dz�2|X1JH$ P`L3M _;vT4\J Qc#Fߺuk57cUw^`^%a8{f[7{71XmW}}z*z1bcoPS`'�>Ku'W"�:ˬ|˗/W˔^F?RD"Q%G/))bLu]wU1Ns68Hq;Æ Cqw+c9s~ԸGFGgu%K8u_wg_:/oG_8-s+;яO~|~9BjK R=qr, sriA\ЏK~ܕC/ 9_c!)n8u\K.кvZunp�~9@0!/LEơ)\1 3Wp^'@uW^uYYY/^Rz1SuqX}[|!Xt<wfj}v�H$>S fˡ/N` .)'q)6d5);d5̄.rʚPjNGV +&+w"$@)DA___  z橧.]gy&֯_<E?>^v=_x8B\rp`~M&o)HR$D ( ~L8Iw˭xy*8ST3"aoƩ>_ο B5;R*#(E"H�@ddd$Z^zN\s9j>.R5*Ygg7Gڙ5{;)@) PD"n-[T)Oɞlci֬Y[T v`ڱ@㏪ЛP17~"j'<BYYF뮻NpM�'\ ?? rqةܞ6m]ܝ�ݵo6mgzG.J3104{wGuM}||_uwM+۩r{u饗^SC PjZyf+~r3СCC>R{>N8PP? 39/& Sva@JD�Y%o@Y_Եo&9 > ��|Iub7GϞ=Ѷm[[ה/˨GyemCT:k.L8Q=9ܗ�!ypvdP|#FPc28 $PJ=fғ805ǜ JW'n֬YX& q0nq]c+—-[ǫa)S]rn;<n8> QMAرcq/V˻ڇsNxx*nד\mݾ]]#P 0Ɨx*?ު=dvs](kWl9aBxזqL69xاr>cэ%I $;PV=?kD264jҤI*K׎;/zzȡŘH9/ϟ2es5;6nan_~zYע_gdBW_#0EZ_.>csGN3X٬oll@v~2##7ts57bF 86o+Vlf=;7o/s' 3;<ٜC*VVZ.?;wExh<gڞ}F<!OBs ܹ^5k֨:a7|8/ά;۶mRG29ŎƁaA0!}q}fe�:uRk]l總agӽ]eM (=Y#P޽[\#R ^g۷Oݣ8ƭ8_c4~Vٱqccrz-Y__|_(.&muIC8Nuf,3Svv*)w;%PrH$]I6cuRp>mڵi̢÷L^h1=]+Oy=ml:TJ4Vo!hCQn߮-}r P8E;qm5m׮zĨlKk-[9kyq}Ӏ2(]Lʗںt9̀q1%|>xwNZL*ރnUٵ5;6nU1עSAAj֟E3s :P|O.,l <HFB"gӟ;7]zc`8+vuc)OPϪgr,ޠlPz*a\;wg]Pit7P2IT^Bw/VϜI6x=wvuqdqSY~z*uY LffW )H; .yo\iz3=)f,؜e([3tfel /=Il7& :;wȴ[͎굨fl(Xߛy(pc %p1q 1~[0cet4nJwZ&cxJc3$D`=uჍ0M"&L}q<jFZJ2A}yY]]c][_qd~l>ݝ5?Sz %1:Uzʗ=~[H`x(=2P};]z<ۉ(rFZ 213tVϟ4^;~4;6W7ע_vb(J(7lAS}n_W"h2P ^I(Y Pľuy1iOqISOUo3LNq;~7|fV*J|yf _؄n\qܻE$aUyZF8L [?+@icn4fjfZt➕l93k{(^8OPÀjXa'Ct'7nt,L9"�~=&M}BAƦ@#٣͉ {q˛a3}/@+88Xy!d5;OYfz/dƑtfel,ul8F )EؙYJ7ٻ[%ښkQ8_p8t8 [ٺHc_N(PқHaIRm�b|PD"H$UԻؔ %PtCn>Qa7fT0�H$PF�)N;Q@y":g6_R3{Ŋ^=$ۥwTO/|ΝU=m{�H$ P-k߿9=uZcJo=ٹAoc<GnݼK` r0{sq{*D"�T) fފ cRPiVֵ!ˬ7!ϟTkj(_}U3 p!JJ1OT]!@)D|pv#PD8{q\Jd3469{j ({4uG_ͮ{Q,՚s�JKP XI)-P>ê$˲{(E"H䀒C p0\c:m۶ q;Fp45k,4v[M%USkg?\vj2xWWJ5t[?4zFٗnD>nApR[uCU[R$DNPɎ<U|@~ǥRwqp�Wc ڌs4uG+6Y<+<د)=JwR[4�Goq6m(E"H$@ &y-_m2Aʹ.j8?6赳-PR5uٺve f]w4U em@%KʾRsJtw(E"H$1#?G͓9"Id3:!Dyu:l];ї'_\h3+\5NA{yÑ}zoR,m3̃=c7W[ͥn| PD")v]wXD]1m+ԛLc 'k (2uٺvc\6zdǎ~JfVqJzXj(RmpI^ #at:";#H$jT@ænA5b`嘫PбcG׉͊]vU=OPǃP�7=~;R٩w=1f9Dqn W9Q{ld+l1uX+@ FE#{{#$$D5{9pY"�qH|7* BEmCtbMi-wgvU7ި,\p˘>1\Q&Zpf;"�[JBl]#X/T9B`3�:'{^OqM2Es{Ί ЁvB{G/hE ׬冟>|[!,XKc7;FT[R$V|HO4Iu =1U/UM (�s6<OѣQԳgOL6uuw]:|`z3m%crw9fR7s>ߴ[nEQY@ټysY"�=wY<=tsb;PQreu84:)U祶yX<uս TS(wuߣ#/.st>P13P7ݫ΂02;1P"�bz +.Pv0$ph*JDvϋ]ȹ9q;պukբ`ڻɘ[tJT3=|p)F%o8ᲦIcH$*ہ5U$�j;P:y1nʵgșqh=|9Zq⡬S'tS5 ()PC4H$@iE;wV#N믪O>c(̫ϯr%N vϋqV=!w/1<'LPeYQof=QwMD"UՍ<cM<"�UVj|17k(21kfI�ܙ*T*{yUzN}z ߅�UH$@)DVDԴ%@) P PD"J�H$D"JH$@)D"JH$@)D"JH$@)D"�H$D"�H$D"QJڦMlcdrD"H$@ٯ__\y0~#3}ò2jQ̈>+uhiQ-)2R#}S)}̤K BR|dm DG./A D"H$Kgkڸ*PɌ*h4m2? 髑ʹF#A>Ypj@}qt˝Pr26EQdO9lz \RD Y2\kK l^3`0+cM(+-'3ٚt \&';33_m~FA:aC"g㋍O$gR :l__v~_%/ᷝȦ=R9E"�=ö\֭C vjαԵ6[_aW||<{1K.Aqub.]SGP}ش8fhPIt@;KXd)͌5dVx"+]œ(CI?2c-ߏNS6? ?G6_lz^ki7/aWQ 2םkyfw#;y-T7 DrBl.AͥvD+WΘUuz' ={D۶mݺu믿?\k___@ۻUl.j�2+}u%(F"/s4 `2Y]2,vӦbG+{ ?m^44oq [o¢wȖ5IA7[>o`D*s7{qlۍ؞~O|uVؿoyD"JqWb^^zU?>�]t2~4] z<?u*7nZlx7?8槤;Pމ K.u鉨rڇqRƦV̙3qoqե;v_V9/&tQu}]1矯>@oM;m4X\=%ˍw`s+=}j0{zm*: }0^|^} |8 qE̳5W[Rogı)dvyӟw^O˟ï\(|G6=5j}(ʘ}Q9Ruٿ�ZouD7K/To /1cP3M~ڴi^yr޽{q뭷?TlV>4rH<O1,?RW9СCg̘\�ܩS' 01M\ <8xjf@8T9~qaեVZ!-- ?#[=zd#<CnMgyϙ3J/pw@K{뮋I<T /6=@qoI//;딇Z<Zv#mݻ>^/vN:$N)ӵo~?`gd|1l(Xl(eHKGVb&Dj*hn?ߞ%y m4S7fQ[lx51?TzHxZ*.ț;)C1oj׮%]Ok[lq޴iZo~wo\nRTǀ>]W\qΝ.Pz:N26zJ+xnϱY]rw}ƣ2uM=.b<r:w;::tPP*oTm懑}v (ĞWCuߡ}&a^tk5;U{3:gߧ -� 碼8%E(.\e"3- !<h"< 2VX~N|PI߮2,dŸ;$g6Y|0446͛7Ou g\=ȓUS.DBBqKO?iq38'|2s?u*8_XzUϽ (=Y96ZY8�kQsQPzzL밵ꫯD0lb„ ⋽J'1D~ Gk#~q-@Mz {'z ;cc {ڴ_/|gDLf#y ?wr.�YV$$Pdj@R1>%=ZYf9nr<){ǯji>a<sݵkZo\6e7:h5koeX}2yrw (tF'9ǘ.8~盛κ{UQK{ꩧ(C7߬LWCy*۷xo1_; ;v>sy>]26vج.q>: )abC!!!KQXXhN ,PPN9Q(mcS(.}G5u)yGy*7ODadDNf$rbܵ(KPHK@fj׳#V!+v96fFcKn,6gǢ8~G+[$r} (meF) P&45yw1vrذa o|˗/W{aL 5 WM̳>~3;v=dKe`oaP̀Gc|p(wPP.rȍeso\ԅ^X%ؕcLtƐb3^-(C:0bĈ*qq}G_@h\ָٳմ[N7nD#y5>Tw",ؙ^|6tfel*@iv̀Ҭ.⣢Ts={Tʆ/>3ٹϸ<׺ͺxpp U1} (Uo�bHFZZ82#tfkF (5MT@Y_a̍a]_Ƀ>3 z4js< N5es &++�@$%z v=||^@mAo6X]&##Cp-pi 3Omq7ҹIoƊh,htsw"l=rc²wcS|g狼?6 P6-oz]~76Klb ^ތ=d!۷vz!ś>=|ɚ.x;lr!u}9zq/\ӬM(αPեkתk<~2x9+,,Lum=|c+'Ct' - #*3Ϩn5he9q(ȭAz␓!|D}+a0+H]^Brbh0YTHO'Ƕ\ mT6o Jܿv< 'ųg T4: ;p<8Nc~šcrt{7h̀:[i|H*h,|<P)\I<"H$j,2ʽ+!(u#L!#muRJ&uLU@X}"'- q+ᏅǸw; -h1#7E1AEYkP\b)Xb'ә[3I42I3-hʹ&R;HҁP7vS=9Ҋy[~Wb %ĝ)Ƥb(\NNJH$5)Tr*=FKOP9#ՀPe;&4 Sʢ^R/E#>@ԑ؞-IQ[Yk+Y1j@AdDP*ӾV/oz;++Kuphd\ 뵳 uu.qPYI|a(9tѣG;b(e{J/z4Eym6b/YCN<&61 PD"i�ezP /jd]TdQA2 *`ҊP>H#hP̌f 4 |Qlm{Q<vѾޕI£Jvad*N^l׿bf MvlfuXuc/izػ.P2VwdpޜG+7J\$^f1&fl;9Ci>ŎPx,<&,@)DP@Y $c*ztgUpddAWwaAEdIqfI@|z`0GgDM(\q iN WL;" CY ^eMʐ#V%a)kL&O)ӊX$SH$ P^1jGw@]a*('(uԦsYQEH uK4v򣗠$;Zʵ=nje:Lfr 7'6%{^Ӌǎ*/@)Di0RC4ta37/e<JKұqcq@gV݊vڢ@4^u8cVe8/<z#RC5 s�KB:(tPB*4ʌ7MMMu!&&&&&fLrΌ{2PA*~2wksk Rb1~{8S𷿝<Mw/d&Ǝ ؘiX>3&yA>D^zD7*mPh  (lC.uH$@)&&&&&@~ej&P雖N2oJ, rbPSᚖWkE-.T?3[oH?ώBZ,Oc7dR׮DzBLeEPn!53CUp{2Ȑ~e]sCoyik@S*[N{cȠ(ǐA9H\At@N/bȉ ʅ3q-*K.F̲X< V9H[Us퇬U(ʉEiA<zH4vNR^z0&ڄ$+~N4qH8Ѷm[9rD@TRLLLL6dgEk Y1GeeLT(P@"DȈ\3`[Jz*O;F~e`}j'bռX9m"}& fd&jP!LVʔj�SPZ+AɁo��<5{_~z+u)eGswJ828yZEw~v,2bW./Y#0c[=�_ҢvI[#/9 b)?%X< ~Sa>3@n(DQZds,̤@R~r<CoF/ ?9P1W3W_}54=Ze]݋˖-{ Bf@9vX5n_Pׯ=ܣx2'5ն<ەB q%ItuL<2E!?Vc[0]߹s'yuY*wA&}cJW`L̡F mβܔϏC~Xvjb׵?=M߽5z]Z}zNn_ '65ev/7i~CgW۲䝓S饌V\jcPx\3o>L]=<%� 6ӠǙ[n%/JX$FӀ2-z)6mQClS+س;Yx!v:43on&6{l3oёy*ˏ?Xky3 SR̰l.?$Tr;yu)P0`@Ԑ)!!A.;n߮Xz衇秮S)jժ}cJ]{ hX?9UoX*%^6xmpفcX]Đ(h8Mv养D۽ٖ܁8f>cUVBdjbjV&̥T 哵.AV7#`O9aއ=vtEcIhX16f|^x5846J2ss.$$#a`2K3DlbH 2l)Go>PJf Pr]:CϤ38ǎ;n]“1tPPd[7jԨ<®<>@mq=#mEQQQ-c4~zXgxIr*PR|p `|m@شz>m>֔o9MN_TYzy_~?-'wW̩6Z2T9̠qZ)cckh~C}{>^]c+4jRӃn*גWs_z#Y=tn|\e۟ &+@Idro*zWk^ש+tP {U= ~F>X4'뎌6qm!j4L>_<s-8YhPVʰ &Dvm3%*WxVf$RB:Tj(&M6n!xDBYLLc>=~<wUS\\쀺ڌCɼՄ^zQ16tiD+))_2c;Vk*3Ĺo@뇟oΗU!ބwu3g,q^:luu̎; oʫ 1tYG= 8Tlo\i(?xLE}|6[M;E{[ʚ(Pz:N26FJ/ЈOk$lz |NKX>*wE:^-hpW(&go7ފ1ڭl:11{B9P؁ui`:$' im�V*KѠYkCcawh�vy ߱1wH=5?y |\sN:$,7,=sG3O? ¼8䱃PZbL: Z<v]l:ziDz;c;Ȕ{7*=uUl!S?M0^ޞM,OTROd"C3s?z�ZL>gݱ:_{3(w78~3&||@=̢ʾ #(1δd_70jߟo\Qpw^Gâ)Hɻ&a9Ӭ-P{w_|轤7Ҹn{m5!S)//|z+\{+ Χv›houL=ή ʶ,y(ܭ2+iHJX?b]H�3fąDJ9 FQ1KA^F2ރ6#v8䬘lƼnj@cpw8EI?=Ҁ򝷻@\q(/͵O}LJ,SP'(75ԍ]Yє?㣨C=@ٜi~BٟzjTL PVf8ؘ$f a9Vö6c=97ޛJ;ޓ}h?5:ͽ//l!-sܷMCYvFꀓJ5˔%Grk09OKźa_peH Îon'!-`6,CY|}nB3O? ?-ؐ ߱]gC>QgA$RGY "4y{klۺ7p_u1ϾrqJ+=V> n92{ݺWi(yg$~wE~ nx꘧{ys_4w 2#j&!y]PE-U^�$EDfb<`^V\`維8|�g(JZCPj&r&axqzfxdh'lԠt{K)a*25S99BpNJH:XGՃbzjKƈ1& 8/*gF1VZCI+wg[cܯX^jU}jQ61qY|p ݸ4+ccJ5{{U38tu]�es <ٵ7Ju5n` {v{ǩ[P̶|<fҽxs0"c(MrM+IA^`qK<l]_-e@B?}P=7 o* #w@%㔓NF[/ǂ!;{2WaWvJW!n0qå7!yR‘fɡڱ::L:`uvcFE2lPM\mCW mw~lt˛Xi<6cuyɚ<Mz)B쩫^*{:N26f一,o35CWPoQwwf ̎4u/)+W$̍fk@i^/mvWܛmYJ`$ DBjꎍlE9H[l)+Ӏ/Af nhdNGܬ![폼D8iRRT:-[4mtDWlI5ؑ_/sb׬@j@@dh@(+<=\ЀR`S l.&&Va|Qp:r.j4SJz(5T@:$PF-G bJD,@<{Bf~젙H]6AS4#mŦBز6oFNJ"fޏ ap(7$b{n8,Gt}N5uHBXBԐEo6gTffCeٓyPn P5Vc]ƹ9ӱ3EܬR+fDh@zt'j K4\1oQ F#mt-zb`:(@y/ډM$̝8 KFûiݱ;'{)C_L7å^ yJ]t n3Be:F6+TpPr(�4ftիWp>@qIݻ7;<5ԩ ͔-[Ti|M5>q *vc\A2q"!egΜ:bI�X0rx"6aءJLFrߞM &H: &V(g_7f } o z뿘үꃩNJĶuzlR-닐�`·P9%V gBMDR "B0/@kpNerԁYwl%"[g8{۶)G'x|G}Tl*Hf}q3f;_N:8VeDD{׵}X\xXfGY?Ç P Pr&d$*o`Z|c+I%! Og[/>AgZ;RGz\$5Ӑ;l=;}CJs34 ‚8J8i!7cbO! 7*f25>;T'T4sңTZFN^5kN3<5\-[8~oڴI Эߝg۷;~+Pc<x1kg?\v*LQQiY+Rub {vn둩'f,W@Id,Nªh0<r= P0E$e6ea߮mXP̘xdDbhg77d&`^1 @iq s*:h0Xpk,7+Y^errjr;p`)~rwN4߸>07byR 8UZBv 7!qذab(utϮHRLLLLL�H]?b*q2,~5h ?ݻ'r@s}ĿJe(M8l)XG8QXb*RbkFOǾ-9(Zi^]y9khVj$UiՀ2OʂePfFᐗ@I|t@rUֿo>ɴV׵.˦뮻Ny*ҊR԰R$D"od(�%-{`ll63Ʀ`}c wyu뇍w?!o/5ܐ (ZHdLJ!?9)X0'cGԠi:%RcPf%!;5BbԽF;\ 4oĈUb {1|GUb z)CIӶnݪ:0w_unGduG_1ω':1eVnJJH$ PP@C~s<u &B})c:y%s8f<(f=,A3!rxD-œ8o<MB-F;=SN>͚> e] cԱjL9YɡI ׀ru2/#~VM}uvwcS0;Ӱg8{Vhe/oH2NmVCLpp<6'=--vc\>SٱcǪV((E"H$@(wP&(#`E _9X4SYX:qK6dCgacv V/_g0sܱtj>a;`*{=N<y{#nD$m7݀38#\eH] d& 75( BaVl_Y$>=W G$D"Qe+I1+PGT�e<@rTOFxtD̯Hɨf8gF!1d Fy�jKLAia& CЯˋ]c1yy1Xhn|л+h2qv"m?2Wacl##f/ 3 98|p�H$@%1Q}oR?Eց2;IKP.@TLDOAxjrV%-LjPc8|fÐ%0)a>3dN{nliCc܎0) Ѐ5xHӀ2r"/yi4 ƖI SMmC) P6m_^?uY*vy=uf9Dq]oYj85>l//h{,o||: ȑ#^Mr Y2h]TEwlg!<p*B|'`ղ1BWNYkx<ؔme\1{Ye%1-/:8;n_y.j AdDj�I1H[M9qwƜ1ؒ;ɫC63DMW;vPcD�L*ozHԭV!j>�Gb뮻(m>EWρ={m۶^=% KUgѾUb(c+c(#!tDAKG!Xˉ?if4SƫpHU7 n %N>--/ETw8Lm;g#o.@|RĮ̑(HsS d&"3in.A% P7I_T}N.jm <b1�sl|U\7wC\h7Sy{=O1ylVA/*9眃_|_~AC+TMx3ooK @B pAE:䄯5� ,yUCSNՌx*? wp%Z]s1jq8Tڌy2NҖ!Tzw7éj/<(BWNR@Y�s<{2ʲ&8c:24d|s+W$ P&f>to$ԭV=5Q3N�VαUsiV߬z(njx졜4i|AuUVjt~-=z4)%=ӦMsY^OH0=WE@ԃW_}ƒUx&U]\ci7]y+j@9ZO>Oi`'+X<Y}2[nL.RwV*<t4dzTl!M[zzGTXZDE*Fm(_[>H$@i&އǃ֭-HsV@Y0ꤘm @i[=_9f*Pr9]ǎSڼ^D2պ_~yʂMϰ򖕕T^^}#PRe^uGU)TEhG\;^y& >w)O)|*Yf͚e4Ǽ ;E[٩Nnխ7 | (8L Q 2>f%Ə/ H$"6|<'\pmHϩ[�euaI1X[=_9f*Pzfzץ6mX{Ūu:rM([nvʛ`233)PRʥ̷7fz0LDv&5kVW)Uk|S,W6oR64;VWuΥY}s:dv،nxZ~W_O4n/Wۅպ/ZJH$@š0:vXi}W[]Tr0tαy׸~uR6&4ι4orÙtPr}zr=uTT)ݳgcܦAc}qM/;;v"��eϷo6uv+2uUzWyp*W'lSJO:Ҭ9U2JUg/' j[v:KX⾝!Иݹ6{۽/ PD"H$(E"JJH$ PD"JH$ PD"JH$ PD"JH$ PD"JH$j(ٽԟuY~`s#s3H$D"Q=�^n+[ 3^C\~HܡHL\5k3!6}p Bt�IIgBDCA}7zc^ {+B`VA=Vy]0f˺b޲.f-i;b70z+惸Est\aHR$Du L&fC(,QHE5q쏰N[>55A ֦>"6m8bRG 2q`#߅ CcYpw $5 | >oj0 Wh e1ۧf/這̅o`ʼ1ik02FNx8GD"H$#d3i/#wDl_ W`|E6n^LdOEV4E%dNBvldArxMCZ d F#!g6ms1LF`Eoa)rUw,`GݰЯ v0(g,z]1}s4Uf=V9E"�H$(>ld rK~f+qO5[2k6ALF?Ĥ~fkDO|I!Ch|ŽAe/AXC˷LKz)~Tܥ1ǧ#f-~]={gk6e9f+h޼\eHAH'6d(ˆ!|RJ!h C$F<-o fCl#`h7AS4Ae_&AXB_ZATGSocE-}!;cEl֠rTW _ÔyaW0i+:u"�s99nu}f9DފB_~EH_8 ~3Ϩ[FDDD3WV8s?*o%\]?7]8ε5H.P>DbT,O (idr?hPVR"j@.bz?mG»#!e2-ƑvO6!/'1P.рr1uL[\}.xUSՖq⤓Njr(Aٺw}7~*9DC*8q"kAAcZ>}0y:͛7EX`>~ xkՇ{vcJEFFoѣG1f<c5iÐ~6РrR%ÐT<E5\R?{^EOtBl"-." *E; %! B! $CXP&ܒB<̖ٽw{Ι3ɓ=eX*ۓ'J!6pn>@/Xnı:M%[TƋy$mѸ1\8}HMYp0̎yQA:te~V?~|<cex� %Z9otiժ[twE3f)T@YYi߾=>S)S۶mFY0aujFR>(5[C O?/߻w/^xYWTTQPu˺zZƛYΝ;'?ۡ]&ϛgnn.~a?|3///|weL{osfL*7<<\^hذ!._/&QF֓ ,$͎;~\Zj?^@/sɤ8;PfMLg06U@S&d}ⶖG~x"HsDyxl?]cf(>RX yq21kF`X7cKzObX/JL_}Ԩ"iCH8ٹs'^~ ( G߈0Su2<?M& ReugϞ&Meخ];z.УG\xQ&j0O޽_ ɓ4qQ<`*a(M\ov&fI 5zKVC6m$kgKהT[(ioHӗڵK *ӧ*{76Rm#bTPHry sXfMe{2;fIH<:DJ<)H<2Ej/%\&O.1OƖIN}㱁c6q]I~HI΃HM<fpX!/$rvHQ:20CZg־-O4gnZRO>Ho>R郚k4 33|C@~'0w\ B3P }kIc1Sj֬={"11,͒~ԯlP:?ߓ@卭<v@Iݻ%NЫWi)**oSYM^x>$hB(jS4iٲ%fϞ .TPU0i7МܿެY3͛7… P;#Q;{Kqi'Ϝ9#o5W6~YnF. N2]-(f9#)& ,`r8=Eڣi* iS;Mg%LL,vљ÷%OL84Ii?RC=!&}j(\#DCh�0 ̋9K>%b.E2|V%YDD܏j~B ۄkᗏ},JԤᅦ5B_)8H}/hv!\r 's0>/$�bIh}ᇲ_e\?X['~ck=P@yc ִ)4Rˢ}p>]<S7˗>̥&YYYRҠAT(+s@ix _𒝝a7XOx^Zڸμey{k�2vُ~[a%Ϩ5Q~VM]V8sm" 3 <R䊔"7$,g )g:DM ' Nؓ,+ytPL_˩ؖ")Hii8TS|N؅p$mwDll.r^K9?n0-* $T_:rN@* B6U~]r/:cX> 73Զq[*ѴwO=T)57%qD}UX}4 ě7o.h PZ/q/mI?XS'May (o<lrrrRLڋ2J ^&MxAvGj}mW^%嶓6{=i]_۷/f͚e0w}Ϊ=K-\"**LVCX{,m_E@cn2% L) HʥrJSDN 7{KrJj.w I<\)HɞHLu ƅl.}#&C<a$nHQ*cRKI; EZyKY Pc mMN'zn:Zpc)P:tHpK}C#Mc5ѲhB͚|15gX/"CQA95u*)"@%SQ%e...^kB4ЇO:hsBI5)/{hy1>3WU;wF+ ]hFipГi͚5>?L%DJwQs[s+U=ANֲo>4ShI򡴤U4Yj$ L-bO t@邃 )$r_AK2g2Yj+ex!vCk r!=7 IY8=b=39r=E$,aR.P9LPb0/(),b)r`]:ت;tP?zLR4ZSY %^CmSTc)A;~a?,>BmFF|}}~(-kҔX %V@yc ѥ:tLh#dnh>o~^nl7|>u8`a2h[n^(ֶZ+Fqk. \o:\jۼ9~#[ۗ@uY3w-}Li*ڞ}87X=o\n{9=hZ57 kǬjPNb7'Pz�ʔ$ <L̞.5LȜ.C q31d}DE'7 (s`Qӱ.֤it9^ݓj,*2an1TQk2C]Z!P`jb%PPK9&l'oNoO/'k45@I3v5@jPeY+ш K,PY|KU%`MgWWK6V@D%慡4%#f~)3L#ҊݥH�ʙ8;IC�Ѓ3rdȠ+^c p$? Y؟]4wuF<G|'M椉*9@gHn$N;`ŶX&rj)? \=V|(` "pl/_jG }*~yB a&O~e3ᗏ%hW˂|W:zSDj jaJp0=ngffZUWK*Ғ~NZ=#\jp+zP*QDI �4h֢( u@A"W.RKy(dN&H&[Ι0ʡ&EóMu>|8c)rh26 ܰo,5a.c}4m)MRrw̺xnraX0(n{jf%U" F ((Qr;wsvHuJΎs'b酴c"U��G y K�y,yn2應<78/ No4lKvFBT xcމXg�XsJ v(,4G jprJj+bʡr;zJP*TD%(Δ>Ɍ^"y#)( \Hoj1i⦩PIH2)gW͸r~KEK/RIM%I_ʃ x>M=*qV*'@9 #jGrEP \b֌R@DJ%J(Qr-vC)/d&PzJ2M� 9!h#Px:'έи% TҎ}qrҋao vg@btl?Bt@Yt6 'ɴvڥR1˶"m봔a�E&\ƬK*TD%J(@ɸ=v27Œ n2%5&#'s> N,CYtz#]Px %<S0OLLG *tx@6웈(lj4qbiXz+Km%^nM η\~T@D%J9P=%a2SdiA2t.2tpn8ZH-�OyabK{}ŹB؛]iY<:S9)*'J-]3+1Xy b6DQ?Fd(,Y7֪ty9ڗ}QTO ~[n۷@100Gjs6<?xgl.RsH ((QDɵ� uWS(y�%G| tCalMOy x %ֽqMI|1\ L7N)rL4}oMŦ(`X(wLKr�ʑ(T(vR�qzA=P&06& 6qH3U΁}3g ԐrJn;#-3�oTTT9P*TD%'H 0-GN=&]Ά8u|5 NFt,(8'N-C ~ß/Gylfrw*ud'ʃ(Mƚ=%T1_8  %P3u@1XjڮM6ܿvK6fO"3h$X ,q BlXF'PjSqvcmcn8~u[Ʃܼ4bF?yoXgPT 6vӧOˏb:ؽe;%ڷo/1/YYY2)ϭE^*TD%7.P :틜3~(~isph. }QT8iEA<ܓs{jP>g/l[q۳?P`O i)r4{3m9IʩX'rV$r(5?J%P@ڑXnd PIx׆[w 믿JSI63~ ]|lw}I\ gaZqmc3gnbbdN{ms@~ҴMOU6? Z~�G-U__]V]:w481JSr?*sPz|սVUr%5ɜ(RC)P{cő$=P)M=-\& E/r_{W ;8${& ;'"N�eшY/DK#}'Gb�*J iؘ0qM8-5}ewy̧?a7L MԆQSH_HSZҲB1m ͙1e.MkP]P IUKoL4&E b Nyu2vA JSb?ϥW (+'gΜ?L\g5/*ʾ4k T%W_ 纙œUt^yINL}8{q%}9Q甕OfVNCyR;篃*T 㸷Lg @Z-h>AH @X䞌‰3q^ˑZ0/R]=S9/T|q9 g.pUu@|n'(GarDb UC9|Y!|垃2`PREƍKTGi¶Mi+'M'j ʰ6,Y~jd+y-NٲeKϗ$۸{ndxdQ9c5#E۟u~ (-[[[モiƌ2ϚgY%n6v(^RBP [vvv&Ʃ^^^b^p!ڴiguZ*~ȑ@/MH/AHEsH ,-ߤ <Od (\,C\t9ݑ㋔p,De)^cq.7#F#`Rj(' (r�ʱ@x(\?Ze@Y_֭[KƲ2e{傕?/�0<??_4<6''G+EG/2ᒠ[]@IA7>>e_޽�tȑr+W>)N]2FӧTh>FCʪ (-j?X_|yP9rd~ㆉ%MeyppU~5SN!C䇪&{ /5j[vQ^=-i~_|YȁZr^ՉZ('N@߾}7|5xLPPT6p1crsܳm=gGݘkkYOeF>CZ; D=~TS +(H D@dQCy};"%DQC#@3ܰ#if3t0de!Hagyb_;vbO`{L\_~܂;3%kvOɈ> &`q8Q" L1ƈ4'/+_Jkߖξ{*y$D uqqqg =zŋeՄ.,OLJ{Z|i 0�'O֗󣕃wϟǰaìPVE;zk;vlI|,>/x |g<sp&-"|yÇ:F{iqf6מ>}ܹsR)l,ikYOeF#Fp(4azԆ0M~Ȓ@32!2NKYplHF`G 厽2!Hơ<OQCY؝](w&pPtIYz NǦv5st@d8Dk@f (!vDJ(HCqݚ_ӻwo J?~EEEmjYy6˖}:hB'Ux… vJS4[(P&j&)Ӆd4SB- 1WSSg\{8Rdm5 cdop-s߾{&jO:p]b5Py DCqWS1y|.HI@ Iy☜`$SCPpE"2u&v! S0NC؜4 8c^'vr(W옄e(l cx 5PBڱ*'(TDEB & }(g-P%\1B?tK3T|IhA(F59 4PVT=͵vPR!bF0,<Al!p=5Un{͵ǚ~4VS粤r#Դ(XZdF6 eId @޹ <̓RC)}(Tk@3B2/r:2{3PcO(r(/`riذkN@ʝSb$,:i$q5F��5cTWJ(H2&f^:PR dx<f?sk˚XUU <dvzZ[(iСRRRZu^co,{=) ersܳ]@ieI?WE# E |(KA!O$_/ LuhAU=iEH/Bz~r ER"9'H�I73u&Ӱtl94C&tƚ=%P8+vLA6 ~,5cJCWIIMC9sL>Z$7=&Մ={,fx<1رcrO_޿֢79w-SGi PResطo_оyfJ:=zYXSg*\[M˒~7m,ES6O/jCɁPU6;?h(OJ~*ӊPP!}' >'vLf/rNsp&d\L?9KY Ia(gbk2cPΐ@4LP=v('J\I@94wf@~(Q@y{ gD #01gTjHhinhKr4џ(o_8{#6hB?;j!ɚ 4 *ƚvh3IixS4 (n75�us9d 1(n>Fj侩rsܳ]@iN&aM?*g $FfFVZyq(S%P괓Y(3NIeaRc8*@Pc~HyɅH)�Z7ةb8,(тY؟HʎDZ^,Rs?= \&utƪ]NXs@eb7Oҍ~-`ZʨUcJCP@DE!b` 7#HY"|_ VR9�()2K(OKL-EAl)E~X�J\#N.ő@ )E18y*_}'�~3|Uvyck lOq@#KAXoVv@)`RHۧ"6~l%"zXD )rXr@~ ((Qr#C0F0% (GG矗ĔT7P(3ϖh(O 'MPQScu@Y-`[,/ 4/ s-ß'W8qrvqC!MC=G#p(=Sc`�V%NEbґ!vD'P \#!j&o aPa?P*Q#9ֵJ!P@IdSAH; %PҴJ?�eQ"{p@; I9b=;XQfg3߿)8smP%cOn80OZ?ջg`[RR™l|w,~|JƝ^'@R%MJ2~(TD%J�Jj(i&Tf @) 3U?;)}%sؼ ;)KƝLE22/r#(3 X4.~=v SܑpU;y`훆"턕2 kwܩ4\<8[xY[i׎iŘ %EPa?P*QD%UG"ԝq�(GJ?rHR ]! q(_dzC̝پ8eF`wvzak$b2L-X+LHtF܎X ð|Mx3qG`,+T~(TD%J�b[;&l$ ʏȼ2<\/<#s}Y^8)őp<JtGa7ظ#K$CQ;)ar'ar*mi,Ma<m&KsU(GW PyP@D%JXP2X@v"G98+MڇR�}9^/ّ؛0±㨧-]~HӰvt{3tB'=P \E� Z?N\4^e(Q@D%Jn�L;N%Lc(\|A7(sPM/roXCzVdxc_/q(5ۏx"!@I3$rNN;\2CL0yNFLf+`Q;Z% ((QD:3 Ƒ"�"*Cvl'À#2Gd Pf#5cv{bwSÑt4ێxHd!3{ջL Lt)%IX?1'"z8,Z3 h^9Z7P_6V% ((QDuJGO<&LP!3?P E�(x2 3}qT�ebvzᰀɃGBMOrSRN%@;K)X 2~b6OD̆ R;hX1h sq ((Q@yӋS%75P{؝)`2Pd  I<\䏤?$1�JI ܟ/r�=^{3}4O$z"H(d<'%PNƃ4yOW&C ҭPq6O@x,\N΋+I( 5J(Q@Y|w4h2aÆr+k_/*Y+ UƱv((3[ɍ'SNr@,g<x\g\o=Pv~ pPPQ� 5Aj(Pf 5;\̚#{LzaWd�e)!rt&] l? k8rŠMjqn%ݽ~g4w09JN΋{4FUQDJsPXezwd^m۶_u%(\i7m$?G<~sSZՃ#]"KLis#W�ѬY؛僌RcI%21[.`qð?9XtHAWl80S^I7[u'5$%9{᪱(/%MscG dP4nRWGTDJs*zO2qqq<06ÊM0Aӄq[G-5,7v> M6d+V{0^Z(n9MWy:P{)!jJ ՗8q}禦7˗M># {{s Aɕ+WPV-Zl߾}s˛Jʘ$T$`I<T(�_9؟Ԝ̙y~ؗ+3Ñ"yБYRC-[6(\&.Z\8]d@'9 '6^,7 \/r9{qx>KЏ'IW_}fel $pgyF?3UvP\\\O/z Mpwwחrik3m嵾[ 0�'O֗E-_ϟǰaìzyTU;Azks}+5ʧO7qD}s='c/1vX >s[r9%/gJG�c$Cރ�k%]|GFF^ed˖-<1 [ʇ>~(ujWi&(Q@i 8|?}ՐJ?pkne,4iҲeK9 l901UOsmҔg\>khs[r9M&f͚:>g`ԩS&]FFIS3YJ(Q@y7|#!&VJOo)ٳGr۴iī^4Hu*7</;S?KM{LPVT=͵Vxћsπ-{ts+j-ڟc>_u*TDJ#2o< ֭[ˤ+,,,,u<;9ќڴBwqAȠvJjzZ[(=^oP4mrixg*5JT֮]ۢA7~P[[[$''+TDJsBs7L92$khv $AU_N={J9&kx|DḌ鉃7ѯ_?}9G2Zfe52ivtF9p&tM\ou4 [jCy̙|( 7o&Nsƞk/t=?K dqƕ:vvvfR (HsK/*2庡 /zIOFy~3">>^_NZ,9�Cv9ҺV|Iq6{7UOsmҔg\$fΜ)}#yp}c.9 \vWgĚ˺uૻ[~1BjM5`(.@j TR6H ((QDIUJTR@R%J(TI%P*QD*J%J(Qr+q5ocQ׶-PJ ((QDɍ�O۽ Gގp:fNΈxs=C?�F E#1d�Mݠxi<?c L(Fԉ}潏CHk;p&3/}Ap|\ pf_ }:/Nw޴G=@J%J(Qr=I%G!|z,<8< G[0Qxs6ģШ(8?cyxpD$Idzpo9.jeQw,<QNxblM Eᑨ;t.E"h79ӂ-=fcl2}qOhB*R%J\/mn gُQNI~<7f!=O {aD&Dn0j.1O ||,<qFp(ی cp)0'>3#OVÃfuvL$^2p#vp(Z<AAJ*)TD% (Gj>7fP|`. {EsQmޙ'p.j'E;sph1z4OĆPyh8t6j5 vYha 8Ǜ/{ GCQٸٸybb7|wX 4 m"v =DJ%J(Qr\<5:.P{Wqb3 =X,E+"_ w__pZ$y55{{HڝPK\>G-w }=v ýbޮM.A\"Ek.^<Q�ܢl/t AeDJ%J(Qr^hh片;;�{~y>Nk e}PG�bu @&ȑ) ;QY%u~`4e:X=\&]K\F�Ł)XA~1I-4x%|ϿsmRSr=꙾ иrtƽ>%N'uEA+>S@4k,6$@Q]B(�Ɲ$@6v @Nr@؈�&,t ECoCN_e8gN̯/v`_ S7=ʯ~SvؕOϿwy,pʼԯ嵪Y7>w.8}�/ C=w(͙\ǘO>]Ysŋ_cǎJ<kyJL߇϶6Z?zpnKؾ朷( $<yu0)R} |ag{lD�_;_4/!Fm$HHl%L,`%THM\"LhMDYcl:NSQ 'wG.g8jzPU@)~>wTebQFᾕy_kU :oϾ-:}C%yỿۅrCjBPޘ/ M68{L\m۶_U*K.7PVW;XwPVŽV@ycJll,,>7y?>;9NG7ԳF;?4r DS[4$֛w۶ ~>m_Hv A3X6Md6+9CL$P6@5 hJcd#%d#ӣBδ ($;%|ӟ2+:Qvk"{ ._xveL*ZOceWlVH۟΂vV+=$rZFcm}枔_KWn @%D_wy>2(6/s[[[1[u)S ..Nm6957L06662qy=z4ׯ/˃K>Ԥ2?|޽xPF <z(TPU0?Ӓ6JcgͳQzoZB5V (?lݦA{74n^Dj-;4;yh/zsRלwFc <m)D feG.ಙ�v0m)�a[vН�FB"p&\N_x]w?]D!찌2rfyyAW}s^kiBH1#Z{`ܪOgIDAVZyѯe^|η<KkK,0PZo�WFCVڼ~\|YW_I5fgћ۵kRtssC=pEv www},OLJ{Z| 0�'O֗7m6l/cذaVkƪT=͵QYoyEeʈ#bn۷aÆU|N"##h[|b l^'{`.`RCְD;٢L;24m/vb[�eKgb} l0ۡ7?\J}o} Ime0Z؇n]0(P)9l^W�%G7f/tA%5G?( |}:s45U+Xr^_kiB1! RYs<-_>C3?|*U+6/??}wiy{-A)!!z?0xG\/[nxO>)5 \tIj4iٲ%fϞ .TZvS4Fꢀ$55U%6ז i8qbh5:z1aQ :-eMesz:L [}BbѢ4<)P(MS?QvxK[ O9x_NXR4&]ѸsE~O`|/N:gZ=iCͱ}睒} �-1SkeʃӔ+ZuIk# :p]PC+M%jRtӫP<J޳Gr郙x5i_\grk֬)A2.5B>}РA<c�eea~L\Pϳߪ^PlI_[T?_y(+nruCz;QP4"iGoL85O78!} ޮ Z<.`X8 %aZ:HlAL"!L&G?=}t?b5Pja(~g $WN10 q"4vWPZrnm-J@#<=e4e5gYV@ym^UCI֭ëP:'sևצ?\&Mywq5k//zZ[(+cyy6^(֌h+O @6%AhlhJ*K4sdA-;xbf VinY>L>D[v @+z\ p Qh/XzwwŽ/ymn5PLj 35%FO%^k%Lܗ8 ˍG_+oR.WAP l 4m+e`Jť?Zn/ZϞ=%5<>""B;vLG~/Ԛ5k/kԨ<Z0%b?iV5<T=͵v�JcX5Fukc2WykS~@^7b@Yhvz~hp=hl+-G^ x|:So;B%<-one+[o|l?TD@V"ѢZ p|'v9d7GI]Cd8"bZ({Pү)# hf^%Os�˔q'nx]e .&V25ܹHզ`(9' m@}PȹU$+oeG.KM%Y66ʻ*5�b_e5eNNNҜ4m4PZRFs!\74'Wl92qFGy>js}YW^-CҌ~}JmּP*:v=RǛ6ުb6e<ke. (%[=J[O3zcO:MdHKҧm Xxa}bϐoZtim0Ƥή-a8ʻ { Ix~ :Hmd QFMJoS&o35�5yb)G%P*QDj3<l^_Q'zluq'Ȏ>L$/}�t 0m$ (m" x8~iuqv @ْA;b_6&Ш'ju3q�{NR@J ((QDʺ(0{DEjPiQ|$H_%˘t.@7'_IM{c2̊ZU.O@ <.-1xW�LvqNeؠf%#̛ K@lHְިaJTR@D%J7PjwF^u:MdelJOzltڄG A Ml#gF#2z=\V`k#)9!N?I V~i&$ nY/N /}f`Il ۺjuvE~UJ*)TD%(<7D@ xu:zI 8z(sx{.L� ;ރGj+>DTzxYh&x^)1^+7bZb\>`ޏnW.ų=#p9H�Zo4t0Z]=ѸyS%vJ%J(Qr�eփ SPS r799aGoވ(vhz$;(K7lkxdCy/DXx[5[!vftyo Gd<s\c&rd7gi#ಡ/ju ƽ=+(gXb|eU%T5 k2c8r}8\J%J(Qreݧ?DcGw.9T6q$OspM#Gq-ldR�ߝװ8vAm%�s.߄ȥbVr6m87T6eM`Ӂ>ry#H:fWO4yJSfJK{1*N7wKW@R%Jb@٨psx4hn?innl/5:ae?wp#hn+C 8KX%rc=``"xE¼M҇2:n#VJ#[ {/Do?PD$Z]P/U PzqF!hy ]vj?F *Z,BBUϒi ?Si#\0*22?)3̊OdE<!;vKÖҍih7~`V~-cTrZβ6cu5vφǞCşxZP{J(Q P膧{ FNt&n?9ccc:.?Oᠣ-fُC^:c�nA3Vax d=nhYplvlf.(v|5 v3RCY?juDWP˶j0)(3-a { kQ9'KgJRgjPrmz!k)$TJc./} N}+<|jNNTmm.qkk~;ga{J(QʺO|&vx4@ِS/vaM C::%'@h*@CѸs&1rc>^+0-Vl܊5]+)?xx~,t9]sLEjw =|QG" ?h,7Im.O7ˀ /d\j2}/gUIRO)B%5e !>5ϖX ʍzZ?%\+TD% (͆ &wi[m=д4wk"s{30́!h)MP>,۰ዩ܄+1+ ܈B΀ClWNHhe`f!rzf2/ 96e;خ= z/ċ\s]# ʼ>՗SgLCI ͺ>ʗSlM }_Jʒci{/ђmWײ3r4{J*#j:%J@Guc&aO4n&mEw4m!ke]Dj`-ڂ ncbڭx{|8cɒ[p`NGqM�9Î4{ӏNPRj䃇zysc*<RM6f}~o&迣GGQ@4<vOpʟ85/߲mK hlT2Sdch,S_յ=,$߰* (o,(36喜Wر@XU@iyJt_`hҤ#[na? =~#Q=KNLΝ;ѭ[7ԨQM6Űa_hb'OFvrBe74 -d\HyiWYFd~&P7@GqXl<CW%p%boŽDfCž>nVhiKh 4yr�P[0jBWlw lbDҪOem۶믿JwjK2e .]~ īzCObccagggY+W{`ĈxÆ :ujq@P;pt5e{oؼdf9 #SPrD'!i@٪s0N [nSk:JMd `dji"8f8!Rg٬8G{?5�5z:u@T*%!!..Nm699 &LL\g&;FR>zaȐ!駟{ / 5<�jƮaW^=-i.kז/pKɉ'зo_Po˥֭+5[lܿe˖HJJof>~v>?3dU̝\yn%oѪU+?~>1u?r5O?P{z(ڻQuPO70PI-a[71f=ia:!u�1xB4)R V@ٜDfSie*wJTR@ỳٳxg?:vڡ9УG\xQ]]_!ݻk1`�L<Y_N|?^PVE;̽M\o3qp)As}sa_cر>|xsC~@ttZm⋕Ν 0rWWW+dٳUϴ[[Ii 1'g||t0&!' fvhc  i{@)O�o&ʚi0�+:x[(2P9b:>X[P;IM%4;ʰB%K{z~�4lt�2JJ޽ +!!z?0Դ<#m-7<'ZMh6EjfϞ .T]0b7UOsmمƮyS} Z>!(hѢ9ư6}9M=|(NPM~gԬYԳMXL;5@i깻U$55U?-;;[>3999j';VqC3Li׉aѸdftiIj!uH]Pr_)HdL4?5 b{?h$T6I雀OaXFS(o 8L^ T{{{Ճr8l>cV (-9OuC% (MgiRkӦ :'Mm~3Unx<_wyLddeeImN cI�eeanx+ {udߙ듌 9&c oyFkULggJSݭ"�ޒ$L~zMüشǺLG}Nh[bQ"|$%)G(oN`g^ {㹗CxQ2&Bt@I375tKP!r ze]E"R{gN@Եs(9lPnΞreuC% (׺uk4qe4'Ϝ}&wq5k!$Ma2ַiioMЦ>a7L#Tqi %PPk5@YV3Q65k֠YfHKK3 ɕʧQGw<uI4n!49N3)vkdו7f I&�;SWChImnEӷ�ɎrLj(ѠK8t]PX&P:D]{O4b5P2am=R Ƙ=qnGXߖ~UWsR36dPoN#R+"N~|rxva^y*)TK)Cjc }cFJ&kx|DḌxѯ_?}y e|aEIFLq}Gi7p-GvSSǁ3ӦM~>!m޼YjϜ9#(@gЇ_ꙶ(+.yeW9x4|(vpǓ=\X(=E74m%aRj*iζ-1y3lH:I?=@r&Ǝ)1Q(mJMl(4s-:lKѤ@ AP?IM彎 l7y3'_JeJԪsg >#SşZ9gSa@r} ?k4M�rƪ1g{5Us@iڨݚJBdhnh:FtٸqcF3=ґ^իWK554Ys˃|+ ִKFΟ?i7d8m#<8@}2'۷oy]wI@U h=+m�ee#{k;OnxLhᔊD e` `yxlg/DK͹!ڈȷ}o!z \ǻyxh#yyRt=-m6 }Qhe_q Aî%6Bٻv 8`v@e+8M'?]R_|F.? >yF ݄;mŧO?.T=͵Q%J(=%//=[L(yy^ 4r6ք`9_\JM?fmChL Ho&o߼=܃y0d E w�{!`^,NT̠⸭p;s$o;Cv;ݠ[fhYx:Qg<H>~6* I$' k(s" ((bNkĜPE$EA9}} 7 03kstwU0=ujhzB%l=B@9XaS󣟽R[i)bMkRQh#h2o3ME(˫s@bM6M3>zH }JcP~>;̃2[:mWI0YԄm$eq_Rjn:H!he9Z[{0lKl=>MK8u\&!Ҷˤ}HvXV`aFr1l Por\m%;K0  %'&RRTP>|BIM# PV<.Z~T,ʞ#'J$15y3X{6V3KQr\ w]BBtơ&oqzLCw'?wc1i":N| Ӱ61XNP'3}'K_ LNjuB0DF6`z!Lm J7nF5\a,o^~3¥<y>h])67卓`:P<?ej(+qEqLCpHMۗWOEȉbXP굙C`XVq;-@iv\VȩЇehn"g +ŀm 7vA"|IbrCr4 SiBi"Aei{m5\|Ա{%@IM1+MMIzTSzy!Y~o<W</*_(# !5YωzZOt]+sd/E7_˫s@bX (mǢbԕR4yRw]- ѰPF<u1hFt1irPh6n $ r�KcE2[`äU!hHIu$5H<D#$Y,)ܣ"|0[yҗC/r@bX P},;̄VrڭJmJII:4%U/Z"RaVڅ¥21oBa*Ơ y0j5-^y 20 )mC@i(Ag`j H,-`ĉbX(@u),*hZv[) \°i~5 ]A}�N}QFX-.%5tY)i69Q87bPsENZ ,4-J"&X# e ,B-`p`2'Jbnm1 NKa67Bz躯Bg-% %p4,z伤0 ATm�HJ&dR2r^):PoNPۅ-l ,`r> $4Fr!%ԵFM<-Y 81PX,uGDfCvLݧzvBB_=6!0MD}(3 E .X=R+$:-%i?F #8P'E0CMd4l:ecjn>W,$-:} > 5:O"8qbdX,Jvв�{Ў`γ`s0u l:gIiuG}9n7 :̓X"4FQ�4kh1 碾4sz.u ]&4mHm'JE}'ou Ě1it"8qb|U,F�͘P|TC zmu]Ce0m+a an5<¸ZJy'-HTJkIJ:iհh 洞LH+`IIl' zaK`iuKHA0R }0u ,/|RC6c1Dp@0Fw||<E_CCC5 U_ʏ4VP*WyBQĘ!C@Į'O}TU~l۶ ^^^e_gu}t]ăDW**()7GjB gQfжNn8�h-+/h5-)OJZ`im(7 -i?}P/OhKIWZ`n?h#e/i -RMsiju g0jzA~ 8qbTꏵC~Gq=ƍnݺ_۵k:3f_~Wk׮UvO/yKeGe럕w߉4w\W*Rʭеj#|*DufnLr@Y8PV-KpX?1 |}}/SL&NQrb_Xx1,,,#Fয়~**ONNF˖-;vxB[5P:eSs|ۥ&˻+Va 94ix.J^iY|hhtqb,ZH.)zLѽT.3?Y{ ,]TP֬YSdE2=ER(9q@ES*}4i[͛Ŏ`oO> EAAAٳgEۯYX~-ӧU(**J>~X4ajPS9j۶-Lwyd�%_pa5y|޽ɩ|ҥ ?.Rǎ|vkzȒE0Le(Ν;O<huPO\#'t/~R2=Ebĉ]x&&&tٳ�tc֭[ׯ_/Z&kLzid 6ĭ[ٔ;2UfÆ xI<AMyTto|hll MMMpNڵke^ۊ%q?F-}@Du)ٙ0aDMS^*SE7|Sd,L>#JMϗ*=U@ɉ%RSSKUզ2~DSnV1YOޯ)r>?e4)??_X|tuuaee%*=EPS^=$յuRV(+c7+|K,~wY_Kesh}YtQ*Se_ 81P2PPDDS6jH$Yqe,d߾Av():6>_L|?vO& Uڵ/ʞ"Qڲ,4_{ZZ*@鉃 [W^*SU, ey=E*(Y,!`׋,+7nܨrP/>a4d%D>c&?'.Q� (*TFF2)<:#8#9jB߾z*:Ƿ]ԋzv gϞ-*寳3@evOKS(PvI!eee v-ļR1P,MHfU7o^1Ԓ>틁b|ǡ,sY#G" FA2dVi^IOÖzRdžzy!XӦM#L*DBOII)Aake΃,IcW֋{˖-Ŷ/m4u|s#۷$e9 IJzЗvOKS(>; '|ȔRFѽT.=g /Ν;s){~/ʿT%@ɑrX7Mҕ+W`ii7U(Y,JJhlI{}Ϗo @IiFNoTG@C]X,JRu#&1c`bU(;v5>&NCg#<p6g<q5S73)I;<nkR#'}<C:`.h%fIa"j´Ձj֩%%@M_i-#<>1n(ݾo]K1kXNJ3Ѹ9u'Í0@bX dXȬ AOJx⨏\>k[㩓u:kax T._8m;@6jLꩣIM렉jcIp]̞YmeR hS$4҃>F6M%ԃlְ.\:Ä飱e*$fD`灕:k\:Oɓ|Y,Jb.fn#3}o1z# P'C4-KC<C{=<]43҅fPӪ cu|j u1az16Oԃ6jk6jJ6AfimM|[ HZm-Am3#,^9n`[ahb1PX,5:Z94Àaambt<h;xַ5>6x: {4n񤫔~6x<% ]5al=uXi &tCFЕ۶ՆT]hKXGS�Q 4MI%#] 1eu:p2t `d=3[@CC2@bX֣-L%HW3<Z2_.8_Uyxh, /bk ێ#%AjHM Em�J)�'ysTց~]}A�&7 ͬPPR 0lhݑcᲱXx8xcT,%b(4oPz,wK<vӾm|lW<; O'[S#|ydO<HJCXjk46!L tQ#wCh4Z2{ir-¥s[EPjFi'lboħAXd<n-2PA B>}ޘPa@@bXW 7vC8KOg Ɠ%#Ax6'tx<;yy?y0\t4QSWjT6n\ѷF{v!}'5Aw8 Qupްqg통& 32bD @][i+kFurssER4қaJwi0OCj׮-TҮEZ)Չ@@bXW1`xOsߵ OG#=nx<l';<=[Afh~0k:u$Gڵ6u*Jc -ѦucFںPӃ9Bf'M!8t|;E8qgqY\hJڪ4PݼyS2uAݺu뭹oDkڵb,\._ wV0sby#Fƍ((5=Oܿc@oLGKjnVܮo;#:།>rl vȵC povm!>>)¤OfQG:FSjR>׃i02GM:40Bvظy"Xğ@zV4nĭ{~;U"HKK�QFYK~z_̕+i1#`mѢ+,oZKc"~* Ns7m$n:݇~?CkЬY3ZjbWf(B||J/ DtyIٳg(G'ZԩSh۶7lhhaÆgJowQ?ƪcU΃Hﱞ={)UL}6%*R6QMƎPK_-aN/lڣ3C`M>¸qصo5zmڨTӤ>)H~#AhH�YGJPI@Y4u,fd�k L aǞEގ.l\gp2J$5}Rөż9о(2AJjeUBBBDĉJr\r˖-byȐ![nܹ/]vu&M~W^[p႘W^ғ!yS(ꫢe^KKKry8qBX#K~ PcǎK"Zwwwkcc?X>EzۀU_c~ @YubȻl޽{J^sU( 6D C}vtFAէl['enz?A4kSACdd]ۂl3kh`ff( #j~a,B|Yd :P71ĬPZB]ZaĨ1 Ƕ .ҲN & Gcb*?E$]d<#=yD,S裏J2ˠLy?>0Pݻw7n\>菄133{i[7|#>cq T<>>>b?ʖN޸q|:3P2Pԏ?(,wƌ8p@QYǏ_옿0՗>)<?1I-TrbSŋaaammmO?'''eK]h9رcK֠AUGiǐ+ʜ ~IWگXB|,sDzJ;۷/{zz T澪z? Q̻ﲒם麑{cyE@iԤ!z a3FàIh3QS 2gm+fp OáPl:,={ھ5BTڇ%>u$'POSh tQͰ6A�Vb.LXm3tt]1yr/>o{瑔SF 2$ߜ]F '"TIeyC]ڱ*d.s<Degg}"K`+[Gr,3yY$ ^K,ʖDMu=z(ld,Mgl2tMRs]&M\Jlmm1O~oqJ,�EԹSV.5k ӧS `GQTPVy(E %){\{3D.\XUꔒk=zRU _ԲGV{ ͼ*]VIVRP^TL@;vlzfm$&hd awjl6ӱp7 @XjD 50xc{hXA͌-QL5M.>5 RZgzå9gV\3cj>n:3MYC*d.΃lܾ8yB&JRc2rERfY1+c,D_m$/URQLm޼Y�8{l۰%eY!АYU/џSLL :w1֭ׯ-_z͗,ߞ9飈*2bÆ UZU",]xe,nݻw +s˯]V潩&RUPZIס4U7.<gȠDM2n)+/@Yj[]sijVʶ)+vs7aqvl8;/Ď9p`"9cH[Y¾ cf€1h 롉 ~{"P8[eb&{wo۶#9.'|I_Ǖ (%󡤯#%V$k^M "@)AtP|?74}Y!~NFF([U%9rJԜM�O2<<\_ IIIIRN"ad,gEBK5j /Z WY&巧j $oM _hc|CX*@YPS9ϠW+{oT4Qː/2W}ǝ-yMTmw\AY/o_ Rz  #dؼ' gl> .ƜYy!6m=HNމ؄HʈD|^L_0 CQ}бgԷ)Ga13} Cmxa3vtEѝK9̣HˎAqI~#)q$z3V,AH2$ =zISzlSsrYJ�eUdj"J4fbbbQ9jo޼?Tު%5OӏURhLddd$ h/TNiǏ/NT50P2PReqIId\ %Y䷧wZ(,n 9Wy?\_zK>_U %͗eTZ~]Atr2@\2w*MUuދ R [M'WL C+~[�V>Q' ,b X+FxÛ{: 'u)i{|z=N-˧a}P[J3c4FOж0F-}닩sیq<>1Sg0c$p]6LƤ)]0rܻzGtzr!G7ET@)u[AGM_䣥2eB/DqԂ VՁ_]PPSkџ#}tD̥uN{Ap"+]&t˫s|ׁR+goUZPtt7(} P*:."%oFQ-)z)W(c2t\2 v,]8zs^eb`("53gB)g !qJ8p7&OHе j>-iS=n,Mia(R x< '  l#`>l; {Wb)1{Ek) 5ycԩ`(+'^WÇ?JjBVJj#Y]o?LQMM{TZ/or 0tGc[,2d!&k uNT<Zdoo_sV62Tt:P*:E^7=G&L(ך|QK mJE%7opsĪͼ@YwYeދ rq> ubظ^ .p6 FXJL؉әǐqΝ@j=HKَiz:%Fzaf.nƆp0ix1LPM#7FV5-bvhD'xR:6б#:,}q(z3Vo;V`L[ 4&uZX_,%ŪXB ei ;�{"Wc۞Eضo9bτIpo[S|tL "d$ 2#6~ 2#A$AШ tׇ9Z̡]fMt[v}3lѣ7pO#w-=#-?dEnw6?͇b1PX ,J s3j /G#D%ǖv3#f�Oة:wi9F3vÌYhQISX jƆfTM] 5M Y&-ѻWCx5ƠANIX(ıp8tvhd79.Ĥy+sl"0%d[zu~_@ddXNd@е<: Q3MZass^կ9uo~^8t0Cбbn̩ :5`ֲ Nflݑ89v]A8u&RJҙ#8p4vE𺍘<o1l،=z0`ơ,˷Ƭ^bZ�Uꗁ1^hu@bX(7_}'waOt?uG3  Mmʡ. ňǫ5z8y" {y J>Qp .<Dvu5 fb^üоoWsͳȿK3qf f (}K8yȸn0ΌFlZd 'ISo2P*W4E(`ddX,;u G`�uEpfa=`Rbq0Fv@` EzN2rSgz4mlȶ~kCBRW' 8֭ð~=\[q%r^4}|0%ܕo߿[.")#J8\ry'(i4566~iV@R;xF6'$ߖD S;w10)4QV()g/_cXX[6WY=J;D=+od~JR"ՉZg%]95g{v1EuUq(Y,^S;qL8Vm[A]a ]v=5Q'v")+. {z~?OEjn2;cЯX[ACIMs3,44w2\NJqY>G_\->ϤJy{voБP$Fֽsz;J`OWhZ?hU^4|AZZZQF5#v XOqL_E6n(_4@-Xr4%TwIPHaJY(RA*A,{cvU^4?{Ah ,zDz$b2c)=:7̀Y=lAj)tWng惋^˸Qp/2`ܠ4 Q5nn 5 4MPXօuݲVVLx:>!,E`yU՛ضcS *#ʲDceRF2GmK$:,,LX2ZG~2~1ץ@,%ECy%*:VGiyU^d,4k@bX,J@y,i?Nw$ +D&eF#r .<krqEzt _0yKI+wv)RfN5n ^ݠS.ٵ¸۹E lܽAGK/J>OISP.\y6tJ$>̮26lX%Mɧ2A!  bbbW,l{b!CU1,z:HUdS 6*XU^ [ֱeeյ=svvʒ_מbX5PƦE!6(");qf-FDVHa$#Z6rnHyISIlu9h�gb/z cᘱ`V.31*vmKPHy(R>~"IOSk7$Yg< (WՌbzxx@]]]Lif̘!˂ouBpdr EP)\o{%1?>G!T6e-S;A%MɧDHD>ueYu-y(<\׮]gdX,'ɸp#ypy\-# d\̔Yd 17]ľDZ&< ;`db>1;d^h׽քE$gaہm1qI|A0yHpY2ȼgqc>YL_^3Pwz;#~X(.p+K\)e^igԋgqe?]q(9nbKQ,9cؼ%2o&΁⹰q@m ( E�_�7,ؑXrH=kHPޗ=.I ._X+8(C\X E3e{mVw}WeCUSU_;S(6~vbiCh+B<s1Yӑq5iS{,NMɬӢM|v$% >' W\NDSȹUa(nۇ0oY.9pQPЃh"̕@k`,^ ǐO p5{*'pE;z]}a.Mǚ?{P` %@&:::V(-4<X(رcf^{N}FRݻ+2O 1I 2F&"R~&o_@Dr84\wE0앾f cپHyR^_t m[85%rֲ@mKs6n=0gy?# Gs: 7^ϻds Y:ee2q=JR~ 333ܺuB@I~(ʋ:ѰY4*%oaĉ"@+W|iBzwҘh:ɔ-[z077C^fxWz*s3H] Q%u.Z)ʕ+J_˒ZbIפIVں=x?PZWWW?DPIX+#~9Npj,]ĞOE)?Cbnro"PG {t2.Ò=;q$HB ՍU5 cyCS1ԭKA>'#P jۏ<lHxE /I?3X&"qA@650((3n8ZB1Z:v5iҤhT7oׂ о}{<}T$&Ѐ2Qer׬Y#:ұ,F=~FRBY(˫s|׀wx�6&999VZ X]nZkYXg/\u{𾈞e˖[ne>ԔMIk ꫯ鿂ЫP;Kq3q%G$ƅ%8VGt^�Ƞ]ᘻu?vH_6(wc8t~#`<_ԕa I#h耐-DFx\Y� q(AkBIf>bNaͺ qWu ٢[6iEԳgONÃu}EdW^2͗,ߞ"Ub@V)LMM_O<ЇhU",]JCh2Ui&(Syfec߳k׮y{(EݻK#44}L6(Ȑ!4hPB@?> yHM†(<ج$l:vk#+%aϩ'D$?Ԝ$d\LAz~,iK?O 3 VҗqF:g Fw7D%D ̋ȼ&ƳL-ȑGO"1- 8d$!<j<ܼ2PVES6&+jbm_~)}!�ϟ?dr۷ѷo__5[(Y (o1H%Tr_,IGey+\~{ @ߗ/,^dY-,ʞ",]ʲ'+S*ײ䱔g=x_ߋV-ooDBy4 _rg>KD$$H0d H, �Pȼdd䥈p:Ξ !s`he ˦2%>a6\ap<](D,<SW. 9<CnwVy%zt`ąʭ,\2PVESѥK:vX=Ź޺u9c޶m[ԩS<847 >yd=@ގ?dj$}(SG*c$+GM/΃mA W,ʞ 7 ?+Zg,=xߠ")4e,ϡJ@~/Dj~<^>+I8w%U38JИ̼$d' +diD垖2 )98s07x´n}Ξ}˺i�8C fYk;<s\:Nr qj&]BXvnC޾\}N 䊔.ؾ{5%̬Bez\Aʶ/GzA:ѽ{wLMѥ9gd1Pzʬ/_P샔z_G+}oO(ƍCG0`@Q9Ȥw\bړvyP}{U~'$KH^˒ǒh,wˢfjop TY>=m螓K&j7YÅ{+J@ya$_8RCx-'R2PJyb|F@ef~ 柑$/tD ;&E0g,Z74bPغ8 [fmp:fH0Yȹ'#9o9:N}|>wQ49mW v\NAtBX*囬HIȄL7KzK udYoJeU>*8e.34/>o|JMrF5mǏ/*>Y=D1j鐉:ZPs*aX+z'E=e=F~'$#7P,7=_&L(g~e>|XrVVM� u6֥{LlB]vӡC=,)ʬ($ 58{9$|A|4 3'A߅gt9b^J)y< ^@AavhЬ ,?k 髫MK .C!hf ٗp~~A.KoI+HEjn<WGzia�^ƍ{9صOǵȕ:ʳP|ruHDdGP'!՟bdX,?%@3 HxH)g. )?rRpl2=$%'bW|<Bcbz6EGcñh<˷/ǀhܪ%,5U=oM5[Ъ.,Y >{ D_\r>-kHʌ‘H(hϯ|<1)Z:(S}(;uTl{OqW^-?kP&򁉖}=޿_tad1PX,1'0vSJ(vǎcX{`7n߄`cTCQXr0<a4=cȹz=© 4oM?C{[4iv-QiCX5FM挫wrpU.1j&N$0'm&n\@\\[98pxT!]Ͻq�;vlQUpp0>䓢;w$S$j heMJ%bJz|HFaObz 9) ۋ5[ 6RҐԼL$])9sٸ|'97t0۷CKg4wC7شk6h֦Z8ߩGG\x(k2N>/[H' if}<%gr >3'$،3YK}#Ғ6%bO\ ڰX GXR4I\&!J&/g"%? g20"o;,\+`N!hN]:­WOi+:xvEnpv7 $ S)=y~׮K`4\1Χ!-5 qKyc^P4LƣGD???~X ,z?rR'�>#s:{go{wO%Ч?f,^CGn6L H):t8: ACeht6^HiM&aT?L BL틸 ._@bB2cN#iܸw33(m$!8Di>.&% @P1cb1PX,#ǐt.1HɎEZ)?HLAlr4aTD:K`.&͜&`=�=z¹S'q󀭫ں;tB' N^^{Fq1a4_!a֍غoŽEp\4RpA=G{{X ,z@wOtݽzǀ^ B/3?!cԄ173N܅sduֆ +~:lݽ "'G!\ 3qY]y Bӳ~1I8mbX!d _sa$8CFC=b0|Y,Jb.l׮VAJ)]GF~rcz>iq2(#"wbW6l޽붮ö۰^.])30lxS yk/Oxtꂶnpl 'Ws"&!>+A _̞7!aJڻQq!%ƙd&BAxY_)-aX ,zM@IkiikT2f0}dL,Mba\#1|Ot\ҢExjvӎt1$gi ϜEٓRA 5g!>;]#t&`r_0qx;#F ǰქ4HJC0r0aYKbX ,zM@I5v$ ;{2BmĮPؿ+7ͫlR- Ĭ3at?C3yO!7 zDK[;4j@֭n.ڽ# q0&\_c@lؼ;Cᭈ݇>KIȿ<.8/_�c#40@bX 'OMTMJTGjf$@bX7(Y,%bX ,bX ,bX ,bX ,bX,JbX ,bX ,bXP?~PSS{6:R r b(Y,�>CTV5Dj"АRՋʪ*>k^q(OCהRj5E]X ,z@II{a1 ȯ!R Hu,bX (j5V�cէ%WAb(Y,R]]5jg|R.ЀebX ( A�/7 N:@bX jo+PVg|Ւ>}1ݻ7-Z@bX7(X@2<}#F!>cǎo{1^TW###ɓ*?P>|gǷ~[@٥K}^^^Q^nnȣ7]ϟtMʺ.} Ԯ][�iU3Lu(Y,f�CY^E@Ig8q~'\v |nܣGPNŔ + @DqFԬYW_}UeqMޡCw֭7vZ3kXK$///޽IQDbXo Pʡ*J[]C%9rX˖-e_?F jذ!֯_/KP if͚ժUӸol߾M67h�6meiذab۶m+uVOQV}Zh,R+Vqƕ^EeڴibHKK~~~*_5+,%/KUJDP\e2- ,z @�=U$$_u?xP)S2ANIxYz5Ο?_l… b^zERސ!Ce@CVUy2SwP3)9,,L,/sߕ9YV(e͵^>@),'}gE@W Jy+/mUe2$ 6%b|k됅L>iK AoV7K]I�"w-7nXҲW>Ϟ=+#U_~}W\HEOeG}Pw 97C@I Pl4|||~Dϝ}bdX,kJuKF)Ե|)Tb°%STr=2B2UFbDȀcLY˟~iqe,t."P*Bill\B?֕oVz+ SzRBI@U>,W],Y"gUbXoR ֖=l<g;|4>w�zu:ڵѻktzbȱ#{A=kxwi޺zw#7og7-0@i>3^Ju;PGZeeJi ˖ŬgʈnU,P.[LeEΥc*s(t�B)2J<uJ@YR7oXCbX7 (+,Фa#8s6hڠ-vN.pkvNhYSã+L $oQ]ѭz<Ё;Upisg% Y|S�qҥbd ̧|* 2?A_~v`| eiY/oLɚm(2{yWŹW'e=22R4LW(e>!%\�%5W S]ajjZG{eIT 60PX,bp"(Nf-)OM.X,bTD^\ӹh2We^XxED F= ,/:@o߾?A3j^:VnڢVZ"֕,Iu)՝Rj%5%S}Y"R־SzlSzYM[dKk׮]D&t"ŋUZNu:W ,zm@^(Kt(0+)U" 秤bI-\oL.)bXP˒FqX,5zh1;5ySS@bXoRn?edU^{Ƿ>7%bXT-#?tRbdX,֛ j&R ^,G㭵P: ,zRUPVκI I@^^9*I4MD(Y,z%r$e{yܦz=cǎbTfΝ;�JJb1P~+]6{\4wɸÛ:}e$PGjՊmKJJJaܹSH+4V()ɉ/_cJҘvvvVnݺKŋ%k:$qcve?Yݹsڵw3''GWŵgdX,2cA)%5 h聭[0})(KnZS -4Ũ ȝV:`$m/ Z!+|%EáS)O?$.KgϞŐ!C)!!A@*A,).ΡE{A}5kVeמbX @]C1z8Nܲjk=w)?NS*JVYXXJmCE-[$EE!_?ҶO1„%uAAA2~ץ@,%ECy+.饼:VGiyU^d#\k@bX,J֐ୱNdoq.!3˺EWc,lަ8jECժ2 Eӧ܆Kٶ>(!"AYLLLQ9YJPy=Zl?EPW\B*dQ%HIV <Q&WWWTPV^V]K3ggga, Uq(Y,^ej҆0/ܹ/ۏ/|l]MYA]GjT/N9jUʲ|Jm;c 72>CCCOV^PP RfҥK011);.-YDeT,#!A;T?Pԕ&W~@YV]K޳k׮K ,b$ e 3/e 3X_޿_ 'ooSKA9Yr@r�gdX,e@I Gol~|,Y:ص<z<}+,m Am!PJ0f,,%bX(�J ]nC(BǢe[|#vEw? ?p#[5x9/,oЋ,%bԐ=]84Z 5hԀs&Xj1fŠ}0 Fbip1 <�X+-](|JbXo�P�JChal mu XcݿA3faL׾>0t0xtٓMj;k =ż�J;P1 40ePf1PX,J-5-tn]a1ݝzd3~|>Rs`??tUϺ 2'!BI! WQ4A PW?""E(Z([@ ~w 3$$yss+.^8(4"7-l<Λrjd8%bX J?-0+fMX(omŏ} ->~???9_+gOEk!A�(Qj빱9d|4:g5C{F7NMIHw'$$D/\~:ɓG}$b<>qDUUU(//ϠmlJKK駟h+@bX(}$â1o9?4nQ/ U./?o?C՞ύk?0�Y i#]ϣ ^V+~WFy9>gƌС>C\yƴ]ӧOGǎ%( sW\)9^^^XjUرcw:oΝr3 G(Y ,ź0B1}.ni1~{2c-n\eX4~  m Xm/۵kW_^hSTTtj;vȑ#h45 Bi>f^w)SsGDW& ,Jb]@yieO�JZ!lD/4J,[0}ܵކU6>eμϯۀɷ`cި HU m۶!99)))x/8*~)~?E >餝`|rXϥcڷo/Oj@bdX,u-:(1_G e96tPFcM1FL-iM_Œƣ{<`̚g5ځJd}7VDQ ȡpR~~]<EB J%b#I6o[" 5A 98i|v.| > x$</ݺ /Q>mؠ9M6J$ҼI|95_|<WzzѢEzŊei:"gΜ t(Y ,źNҿ�9KZambUun|⻯Ē` 1$Xq�yrde�% K*o<>tP9\.zΜ9馛O:%w!y}Ay}26m`) ,Jb]@S(11(+>/ކX߻//{PCD}hJ{PVCHR_bXNqN:e0rڵ;Ǫ~_| [_ {棴k;(".$+/߃RF-lL?.\s琗 &6%b@Y[TB0f4'Su'MFloGZAnhN7E#~վ@l2 y2Df(Y,@h^dtT4VF!CQ A`dcSҳ%@bX,J!??gu?BC׫`BQ!$ TI?9W _=RF-obdX,vQB?? /xydq ߎ] M>rK@bXt  ~Rv1vMzmv\wח/`_}ƍY,Jb]-$䴑`MA@ׇPc= K-i[~N#ܶM;~,%b6P^z%9sUSi#,%b!dX ,b1PX,Jb1PX,Jb1PX,Jb1PX,Jb(Y,JJb1PX,Jb1PX,Jb9^@۶m{olNm3H@bXk�(K: Y3DDk T Qi1^4 Fc4b)>7$۰3#ؐdŞ6)8R ;gxlUP5#jjT'x68V8ZcpWJqbT/<'Ɖ}qlx9^,}0j01qm.obdX,JL 0E! 2^aqjLn Xc2Y [L`3ck;[zJmp G[XW7 wSK{T*~r$Alp6T탪 ĉIq|L_[ZcQzƙ+3Y$t<6b1PX,*% sEbRf5XI[Rؑnl=S7?a8й%hy&v>٨ Uspv"jN-S +Q5NXUqjb_t N <:;WbmNK ;PPѶIn0I = -V` gX,Jb]%c fI1 tZͤ&|mvOžtDf@I <# G+8[x`[^\ӏ ÙMT.ĩQ7N%7f|'Gİ8TY ZcŌ[HmiË9 {O,!rhhzt@?ebXW (im0A|bĶVؓgL蒅Ce8XGz <ڻ5~mq|dĩݧw3qj�yq8%>fĉqrX tzųY nbوmKv%`{M` Ҁ(zObdX,v6ks033Id*vO1Pv@)`PEku &i>^986= Z2�V %"LęsPug?ݰOݳry^m#;b|lH+C 'c�mmxbZ LV+2#^w}5fBYY5JJJ0{lJJb^@UM2.+ zlH`O4{ pwL.ϒɣŧvMǮS&2XK@ǩ{F8V[x%*ъɞR( ;r!Æ1=k1WoPP/hr~n@xx8:wǏ_Ux~@+> -ZӶlق QQQ4h,gׯ)S ((:uL4=҇~(_2P2PX,�X`witxf[R8P&P�8Zy)BFt<aţ6-3OO ?{ƾp`|v3{NMZlI6vdv W&`{dl/0YىXj6K%qT0hdCj(P?,*PY$=3MZ_cjɒ%2dH|l޼~aÆ:ʕHIIٳg; ON }@@bX(MbRە,Մx%3<_C]2q\;-d,J2ciZ<ӂlX!&crOW"7Z8LwG{ ^ Ҋ6l¯&aG~6g0Lm@a1teӣˆt@IH ]{{{W/DL&|||`4|rk"==ի/ܹsP(zΜ9nEQR;g.].+>W'r~M7݄$n۞'#oA@@@uffN{֭=(7n܈JJb@| ՘bF]z=VxȠL>\qtd Ŗḏ1fļD30cN 3l0h@�qq@A`[; -Yf ݊m=mV)B@fA"fZQCrbhFBH-QZ$(Bi2:-[&ƍ'Lnj# ZbL#`駟ru|GP… ݶ 4׿U~U_]IOy5A;IXMiNNN5%O>Do{ PS((Y,;�+PcP 3z=V ܒf@yO6N.j-ݻ5Ljd3Ͳ\e%`H`8dG('0F|#u[+ ^H r%nVl/PY.>K-/[[�e�6qZ 1Z kZ7|qv2tG"kJKR4Ws/5.mҥ顇,**4[J_0L盺Ӎ7(˹TҞ{?sJJb@6ņ璭M8& KF<h¾T/r�ŕ8 d ZT j**+(G~y*JD*\ƣ ZLl4cg욄]@v.@YdKm-ؔnÆ0YQd1Z,`25րG( 5A]4Miv!0k&v(JA#""dt6egg4d :F<tOYuѤ%E]W_0k׮ddX, (MK<LR)2# NWdi p[nظ8X&b�)3tDȎї>pT ώGQfS3P%IVh<+^ڂ'rdZ)74ބ  T+CIѬY394mK%Bi& nWm_2rJi}u{ү�%͡:EGGcݗJJbZT)Q8GŢ<:1 a㙖6l˴aoA n8ص^K4CuFtUjQEO eYPvxFgP5Jjl�Vlϳack3֧.ل5&<h1lk4a> =:t@)ތ<%T_^^ϟ?zW_}U=א <;N8:x Gw-VVVHkJ_`Aʼ3gWOUvHcpm(M1P2PX,w�>+ը�3Z28t!�sZzf۰!͈R)k�Ni0@�dgZ�ŪP#҄jExJZ ‹f#^]Vg xܦj+:�ŀ'Ŋ8S:Ia@g56L$_1P҂J駟~¼ydDi.$A3RV],ste^ 6HkJluaVy{ү�%-hwxi!)9yd9M.ۇV-&ǹ ,jBѣR@LZp9J`* �8H$"@ЫԬpUjTps(@PI@End<z G qx5^%$ܘdsF<*~%/7ؠ�tzn2`Έ*#,2:٭JV;kE>)bX#PV CF6 X!dP0$^)G20E@|CgV9j5 СBe�1jazĊr"0* tRGnD<(b=m1cnaKDMbъ 0m`d(Y,uSL�-Si0+^& P)1d &Lh0ҬD= |hZ35:yc*ToL< ,s3; \@{Sg{VnŋfJ4cY< `r%5?NY22PX ,ź@yk-zɪ .d.3j1>ɂ)5=,i0י d6bŌgM&,Vk@n^!1 z|N8%uKhpp'+'`*'hXj4ȅ:cZʽ)o%@bXSLL4aRJ%&+xجl< `q^rsV&g&cjV :(F߈HQcgJ1N@E^EL$Fj0ӢF?]DZ(P[x$Fa{VRx8Me۰ C4Z0G7Wǘx Rh0BXa(Y,f@a |%p�sd$H Ǩ$d)c�_�a#-XiҠ2*©!"/:=tjxy#cbqRx-BT�` ó632[5(%Qx`R}c @_F)>/wy򓮛*h7ΦUiiix<P֭l}k ,bt7N�H>2E%h1(>}ͼPfT!t@($ 3aeӍˤM ,D*% }P!8 j. dah!ipEa  Ӵ:T  Su=il:Ǜ6v'q9Q:qG#G AMm~bX &$Y0^�ew�Zx#fi0q$`2 h LĂ,#eqܕf 4&XbD6`(/_d^P5k1qH -[<:J Pi8%dFb~C DA~ 6w<~ `uVFC;m&a|G^ R;Ǔ~2w\#IHΙ3g"XjELsA`` "@ݞNBv+ӴjU=<x-[GSTwޑҳiLs}3PX,ʙpfJ@*A!ݪFFH,"$+qHBv|<6`u[3:ƄMxF"1P@ &qOK$k1;Qq-r"㇔`t >01:a"@Q1h0|)�rhhF a~Co>麮]F:mNC >={޿L%EIL [oի_w_L'دitg߲eKut*"Ag߆… HMMi]M wO~*ŋ'5fdX,u-fܦ"54 a]0(U(">H FZX ⣠ B˘h,v:Da1H A~t8(UD"/2#BU<V`d$"!-!k%sX89Sh"y­CD[psL,X,T!6\ǡR^P)3v4s)Ly~9uMC HYcmy#vTkP()Rؗn;JO=Tޣzܵջ4;TRű<=˞^2PX,ʿ'pOI0E$>(X�}L!'< eEgj?m( rE44}b#CM^F� z5CQ&-, i$+": XvyQ Ob"=hZB-&$ 50-^@ICC4,?-`ч#Ir(sx޽{!S|5k ..~,)"G}6Pl tղ/Jߣzܵջ#)n8R^~T:kfdX,uo5"*8 q0 @Ba^>m#B2qK%tC�Km@ E~( 0 JҼyc3ygx#:f>0 QXvE<&Ҟ4w "$`>gaWjJhO3Iz+ +9ZC>,tbѼe>}YYYx7=Wc%@{vYtIT{kwGS+iNem}%A+y ,źطo_ W,Q9(hNIps7nBid(t r221(mZe"/3 21H)@|nl܈`$5l@IWjx8G  Tqh;nu h"Z-[ᅲ2<[ZV|v2PaAg5Yr4?+@bX=B9h$-J hpѩ،9hU No½1'#lܟ7zù* z#E]z߀Kz7J¢6A~|+KF}H|/ؖC9-y#nI ,j2?&l6aw@flvC\ l6fufl6@fl6;r׮]k}̞oѦꏧl6f6ricHm ?q8EH5lJ6f uJjeuكǏĉjz&eml6f{tL\Shg]'))`cǎZ?fl(tcQP<yI@fl6 Lt}<z^m@YUUդfdl6@`|M޹sn\i@fl6} %-ti+{IRg{e+jSN5(l6;EKb k#ƌŽ˖7(L/",X|/>j9kʳ],wu4uӧ/3-9{t(p~`yWbdl3]W> @wEvn -Uܸy3 l+(mwL}m+1}1>Ϝ=0/.+Z(2[ rW~8X~U!@y�ĺ@t%fopaU1u+k0d(^ڴνScL 1O~ц~jۿ_6}QGG{EC]+  "Ak+_P+/egٷν0w[u,J6f3gСc1Nxy+(Y)#d:'裏(Zc}o={jYh'_5S[?x])P޺[[7[j{u"mڇ%W m. oױm9e[;#]{ wƍ0tXÀ>ՎCyF,aԚ5.�||GS{yJ6f7PRVz[4̺Kp:rrs2x$9>|D͉կu>6>BS S[˗+IqPkϺ)gs+{m[m}o\%Ab&L s=YU6~is?(zzuW#LE? *=@YLzRf].)z lQTk#cv={U_SDKm8qd5IZfe׸;T_ӳS[Nn_1P޺[t>r7ߒ7z>K5nV[%e2 LjPbl,O:U4&+TjJ"rg۟*(l6]ۯ[zM|<{Z= :*BIs({%v_پ]¤㐵'}. |Ҥ i2Cu+PgҊ59^?ӗ$E8)>{�%G^ڣg|J6f7P[YhNk]]v5򥍛(/%E#uA'^za?Y>4P7WsBKJzCm]Jzh]9ԉZ#ݾ(si^:a*W_Ӗ-dnsA)DifyMW@f^u[Wq'IGO`c[hq9yB 8r5k*)wLkR4D78lԘzA+<DZ@w߾Qع+W?,/Jw;V/Oo4t ]mvɪ:{aa.a*P={2/ZF[)^g1Pl6�3>+>QVnݶƐsW=w! >} &s3W[~}(?ިs{k/E,iu}#{슁6B'P7_ZYʛRn{EE_zr3gevYNA=nJJg9AЙ4UvS>ϫ/P}4SڡCf$-{(l6G[oFAq߿x2;I ~jӼFJE31q?Hq]@ynP}/>PڹspeweoGe,@f?7_ǣ4r߅%7.\pYJpڀ@SӼ?@$œ{(l6}=h yI7 ?%mPS"z9tWJpJ;T~ J6f�%MnmJ7v 5%flJ'�PwS`dl6;rݺuryKD&�kgUUU6$6rMɓfl6ݻw_TF@X0Gm6dSǓl6ft@I<ݻWFeSfwlxR?fl(?ZkxZ?fl(l6flJ6fll6flvC/����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/covergrid-plus-waveform-2017-08.png�������������������������������������0000664�0001750�0001750�00001667335�14035600052�022535� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����8���O���sBIT|d���tEXtSoftware�gnome-screenshot>�� �IDATxwV՝9<}*SHQvhn%/hdSvӳ)&Ĩ)jLQ,QĂ"ҥ 3ӟ{90�Q_/^̽rz"9f�iՎeYeYeYeYG|ߧ#gdyxq̼9Ƒ#GJ&p=q^ZeYeYeY23VD/y+M͈ysgmeH!Z,˲,˲,˲+D+MCץI$ rjgӲ,˲,˲,˲W*RxKN=(n*uA%|hYeYeYeYaTB<ᩧVK4Ʈ@hYeYeYeY+r PR0Z#s]d!k:-˲,˲,˲,zJ1'KegLjgv&5d\ry]SW&4l&2qx|*^֭_Qz5DFR.QQ@k&I KX$ K#)!* qbYeYeS}..l#偿 E2>y.& Aj*Btb5KVGN'ArꩧJ%jo1!j& $jPF ӌLGa#ORH^�K_1NqLhNz6@Wd;Qxr<oJյR$7"FVRMu݌XKKh-g}IiXeYeYK9I訔ZSҢ˘r(Ĩw`*%ܳ6OZ<t u5ZkRa:L<k7zE:8>zzr+З+Q,U&"{|žRqL=N="{6v(T"F$cD/MlOK>{9E#dMuK_Doo="B I-=_Ν)uD* FmV|Y|g7W!>{ Փ'[NJK҄Ľv-cޞj;fJ.q7mwA㱁M]#'O|Ou+fնWr)<Gg%Pivu74Ҥ{EdYeYec 1\u ',)sGsC.c \O_D(NE8ÂYW,Os& |iK9g咻}F2M"m CGex7~͂3??@%M{ C G^ie 09焙L@Rʺ+f{`P ^|ଫ;')6/؜aW>`=7~: e�Bawzt ev MT }tn~]@CcktP'-17fs΍}·2"C,=t`_l"]_*JR{D '1Gd<g%4izZq~sU<[&^bI-˲,˲,TJeNiO3ƩJe�Jʰ15 \.dl%T; NnKxB2HX,F^lJ)Gӳi-^|~9EMk8tG Q,c5y&3;7o+WRȣ!|:W3(G\&ik= '^ʉMS38k.`t5ݵ QJ8C}ʡ.F!q̾vɡ7_-_4ґ']2մA+C)CEy>#P :o‰A!Qhl<?ѥegza0bW^Q}Ʒd(0L Hǡ.И {{*(hcbwc #I,͌6&|/ܴx}JʔvRRriJFo;*7s'>e2ȁcԑrԹ0'\G7)RжĜá=o?&T(G?HKzqitfӮE"V s!X"miрeYeYa#*B�zuaV˓}=i}BNjy+K"Hkv*2Z�qi9m۷4>qǝڈ:4>m pFqf ;κ.K[c'*s*_rGo//8iOtvVh,UM&}Tf'+8j(N=h4HГs{)#ik!XvvZ#qc) 0e׮^eg-1*6_?%٘8}dۀ\> б4FpTr7r#/$Igɶs W1_n7W_o,/uk\SFޜ!Ay6~~jb .C) .vX \d2WR`@@Zw~+"=ˢvZĤWӭ$BƜ|= žM<ΧI4[Յ Y#Hz{ ӇtZy?1wOMwrsksdԃe=!EyۧM=�$P:z,JI>}s9JFgYn~vbPv|vA7E__.t矸_o;,˲,˲CwiQ1ލ"=)Wx$_,r{gNeJԅ.' x/A("L! BJŇVOO~ʡKbI5М.B"L4 ,Սȅc.;?CVOC &547"8-YpH/G :*8t9ɔ9G21 a)K_~tNTfoӨ,6t_ GyvvlIoK\wvBoEOh;6cDO]C@'XZЈD1!ɈG!+4$<}:]IrLNCTћoς7|}IН;2F|.ds+]^^ i~{<[K,U׊2\XD ؜sG±(J ,|LmW 3ts1 hSpfS$Me?/I~"uownـ1]yz 96d;~fƑ-st}GV>|eEWίk;QE任 ׵,˲,˲1WO,0Rv0(35𮙣ͼhf=M ֆj76p~t;cM !?;}KK._!Iqcl*} Y!>}8Y y#u/==ZzZ79鬹KUᾧ9q<xM%_WJ2Φ XxܱP t 7k妵ɣŗ?Ęo- m/FcrS.f=}%siOjkAhO駶Ӓdc3A淳T7^g<U1} |F?1+Þ!Mσ?wf|esO#ҋàoϴ#N _7Ҙp&b(>73Z|NGkd\ȢWpC%<X "Lx^V>)"D$?Yxmc65h4ƠZ:m߰\ZF >W}?P7\SiF-}3Xo9"YnZ#hLgeYeYeZdlQoП/|X~ƎRD)wBP,sk?;l_yBi{=r`ߴcRuH?1#O?v)Vyܙ%&N"f0Z\ ﴂb䢛1၇wEؒ')='1֍=% h1zLw1P f$&!p%ȴ$m91& +'pnTlO>uJj•?䊯.%^B Qm!k7R 3U7,$㚵kNiDS'ay-,;2S\:x7Եc I 3-nfTHsS[}*ވ7I1<}v3nD [ wL<4t;<30#㹸%%]r-VA$1 C{i=Ȃ0ЌKcʞB{}+cG9<G\SQ' $ES̓eYeYe:@:GLu%[]>3E nj6FELIᗼPp7tlt:5]I!\G:L ?*Cvo#$3˗1}䉜1V+(XӻY·]±MTfI0`NR3 ;˿C.|B<N{ ?[ՃxڟƘPUr# BJ$`vclܙQИs׳ܳ9ԹL>l.?mM=p뷿# h6+CȌmܼn ufH �=g][Ej0!YVz˜7/fMM+^%>4_ϜgŒId~޽(`we8k{mG)$ЫidH2ƍn`* B-z0m60(GpAN$Dւ*Jk!lh,˲,zՂC =%9mj147  YLqqh݌ ]>p=w mؾqzp0qرsXiXr4;CRhc@I2#h m譏ۻbͨ/X.d?3wlA홶RFNY؊c w׷МJr)"q\\yНlz181ⴴ V0[61Z 7C;n_K^LH< ’̏1LO>Iܫv.O_y˷w%͙tu�(Ci_Yd޳n~hpľA 'gGv(ke:$=(zΆW~0?zMG^?~(ش9:v$,QN?<!AmcA mǘTTzVrb8G{&-a @gpicp0V?z m)C?mv5žڅs8{owWKnVy"Fma VH!0c̘[! \=5-˲,˲,gAv+=y%xǀ<{ףjl�])c!Y_,-8ӻGKoOfbذW#N0',o:}MkX5/ɸ >ɷN )) ю,~*oFv)N]7Yې9GmL;oGQwnRV #9IbDsd WM| ۰c)Nיo“Y"tC7Fzp W=m3ۙugyrG:>uk>MzW7=EAè8(v>Cߣ/!~2~ʜq1~g9z&ȭ<x7g5)}C%qy[_Þ:+לq2 =?]StF~~UW7TV峓̺B<cV?7v0}K+]=/JN )s;3,BZ&]5Nes[u|h:~w2qlm)S{+y{퇶7|7`j7}!ҜQ*Nc]EKF`3ENbqc}~iYeYeY/c >'K^%dyV0@+LX*Ԙk[б#JKݽz0Xp?@k׮#MX,R*sN8Xd2ALT۱'w'7;FFbt[=^ְ<8HSc=I7$۽uWl =1r0hG] dq7HykgcLcܳ&1o8 g[x˺G~7pbab.gM$Gcw!ؼrO477P!FdwlbSXb 2c(ZZiiLj @l(</~N INp&(u<t+~O`GQ-4'q"7ZQ+{Ċn8 #rϳ[&  pr"j>砜kq)i<%l =<gva64$GVxb+ym 1,M|:h2x/=s4-Y-ci1IS2}F$Q-B?Җ |x$ccۊzmb?=ϑ9币{h.̨vc>tLܐyߺibsٺ3[شYT[G4P;7ة˲,˲,eAqIFwJH]TݰԂ "w|i)mM,iU*[lA:&`w']"aC!Prjs@JɈ$nK*eR <ZqJcCP" <OҜN &EwK1,c|{UA)h$k91A[V>A(Ҵ =DUJywG>Q5թ֒u8>RVU`$�JKTXNQ7$)"!׳ӆOW =HaT}(62b䲽"X2=湤N"#S/):qiT4$ n<#_%! I 괣$_Ę<k>M"Ȯz۔dDRa`Rzw; Uui:sف{(GmAM$}I2'bP>_OET:xiYeYeY5\ZkN<hp�+Aq~2ci9Σaw HQ BR$LD"Z+2\b{52C|uPܺ6 ҇teqȗC?]~4 Py?-!|iYeYeY+Z90H.S8$w$d§T(vL+{ZeCm϶1JD%Oz75&fT!eYeYeVĢSkeYeYeYeYieYeYeYeY1fM,˲,˲,˲,z0;r,˲,˲,˲^Ϫ#lp,˲,˲,˲^1,˲,˲,˲,U"-*v>׀%UͅeYeYeYJp=ao˲,˲,˲K}l +eYeYe e9{ΙL0X,jgڏJºubŊ']p,˲,˲,z73wLXIFI].E%("Z8 @ e)F\!Ø €6€h)QA$mBp0A (a8FJTcF Ig҄AV <?)SZ~�� �IDAT%hM�8Hh"@ #$1`D%"p! %R(b4J m4DHc$@mckjh �tH?6W^=q@;eYeYeY̛;c4#;VTV"+qLӨ4FȴF2BH1HW  #`6`D+RPZ:a(0h�"V8(!`x^DB)Eu4uHh@rl7(NF<HetvƕЀ*FÎfs^ T. DT(c 4BiF1ju"aZ� D`(}_xlSïm&V p@qk8줂S,˲,˲s? ;yq8 Ay9DS I'1U> ûT""BP=Iu$H(Ѻ@v+^5hE0.:4H} Bu@Bb3j@b4?*ܲc|}xt@rF% t\^F߻;"H$R2m$,R3Au(BHIU-8PoLu1@~B"1(G%yw\IXWTPTQ(.彖~LH1W&q2ΏeYeY1axxb5F@")HqM1t|ȭ+U#Y0yvƅ@:-5h4P{K Q]1QzNdHB~A WA.S^Gt4F6`PG `P)е�DyDʤKe{@GTKy!`PYOij}*Nz3H"Bp1a!�Yd-b4@i׺BP(c cV<uc ZrHOx7o=u v~9YY9 ah_ΑeYeY:(VJ#Q/J E 0đ.)C(_(4Qe'4U0&=)fkK0\rlqbEDX! s.J5}QK*O 0yյ0�-J_ˈM.n6 Ȝ *&Qkt1Iy$n@hAW)Hvؤc Y[@ _BdP2K<,W"Hz!RJ}|Wy?hүr"駨 dQM$ܫ˲,˲,u5qI5r")q Q\"rG}KOA22P_%j j:sRP[mNjjG^`0B nvC@di*@pJp >o҈d�AKt%r"pqF(?�Ɖ( # A 5CIa@saHا (AcHQȅ-תp9aN=@(Q�cQ5Oi$gƮ9` KmDh~7lL*+@GBmlziyzH<a{*OKBϽ_?zߘeYeYREQt\^&e=SoFzaSdq1@2@A-@PZ/0@h67g]d s5cqH;BGU#8̉QrBDD.EhD]# .OhAI蔀iIILHN-4v-U5eD#J!棍@B!jiZ(P!H\!q_G.TToEB'Řә29I5jhaGqysWPpraNzr gXw׿2hYeYe=3hpN[ gkNV"$:&!A: 螡:`5m?o cDG (V�ȑ&\C$ISW|RTw<}U^o#t Ah5I<C2}AWHyNG=CR#CR=LRcD)% PĤC # P/ΑM4'I IAL<!8CE:dqPpà5,~|W�Kɳ8s8ib1>';?jw5R'679n}q'z*>G1Eo,˲,q\|lP$qLJ~ m$&ᢉ(<VdDwT7+ΓBP]/t/$kTG ib>eaA!R rIHp HJD&Bʅ=7)u*%iI12(^m� t\FwLtYW"dրp[4EldfpK :q4)I-h\mAQ JS^ }FbYc(h("EI@`&Czh X/ LDgkƚ'ӟ N<qMjy:,S,DJMmePx~'hrr@:  4p zDq8FvG RDJ^At<XǓCל;T(UBHWb'(+T$J!q\? jLJ2g )q]?#u-L5~*M&6D4I+i.O+f?ŷ6KR8 %,˲,(!-.Nc-#%|EȰ3@0PݖOT~Q]mtuZ%)=nк:(4^BSiwv>Ѷ2(6U8B$JR>^5) pZ8"B$Um@ ?`Bk hY`#!5H^b1G08FWn # bu_}�apRC ajw+i 1=Opd:Cz*:k6:Q$hJ};Xcwt bb)Ɣ/፧eƘ܎ <lit!tpS Y{߽,~E58o-?ːD#\)4.T tnr]T%kz_sطFQ.Z?us&wȚ_/Rξ(8]oyG0vD ]lٴ o,*e_i$:q[xG3mLi_SdóO=,^ ? oo_OKv\~t1?;WQ;C<W'~|Z.Paܮ?NIm kQAPÙj,1{XeYh+ b:}8}[$N6W_TB@#Ah$0H6RXa�͗Pn)A,D&hp4A-^ *JbtA 06ύS^f&R�Aa=ihU]$P %pH H"*,Ř$xʠAGԂ(!F(NmgjB8e RH$` ;CÑh삄0h*TPu[y7z'=TW$:yR3oڠ-d 8rͿrԠ<;qRǴa}_yi6TvܷBfa'qlC('p ^?Odh7Ss~<1+=pxFN'x`TH%o̱Mb_O8>~X AUJCm3q-<pjqƟxsrZ}cEQ0玏n'Wiʘcu^q@6q?–m>3J ˔WIض^"$u#2Sqׯ{uR?/=2\dFb^9"ҢoXeYPq1F=t"ZQmӮЮ#}3\jG' L;".I?*Dg%3B→ p-$u k(� @RhV3dޠaTa@Ȩ:7($8#(=Phj-:"�iP!Q,IO !-P]'*AhB:d T,*Oh"_'@ #DTPH@_9P$Z)@:d؄sgp FD%zzjon 49o~'C0;ӫ׽f[4'rqmc8ݧLg)*ɱ#\:-Q+︅ۖfK6"8iǜy,`b]jPN䘳A+Z(;?'s摿kcBV]"^)s9X1S>> k__svo)mn7l/rx0r:<. �]Ƃf޶VR{#<A^eg^}p@V+8w\Ě;4 Vc]F%G.1_S룠7&�vOi: GhbL%P(Cu*C,A& =!ooػx3?fnڰ^]o�k/]ؘ)p?sGGtDTD<;.^ntDX|?%HK#Ct*ٔ[XWڼDLBBiNjLwaR,Q "zē =Xyb+>3֨Z0tضam;meY_IJLdDjtym7(tP%8"ѵ.(`ؽ}� t0`-xB5ty=B⣋"ҨR %2%C?HGLD/!i�#8 / Fb7<Tn7 B(t-~m(<$0 =CNw0՝bsqp #5>Aut@;*2 Mu1]$k[ ) Bi0t+Am*uCXs}oys7]Qoo׿}24o}%ܱb| .G~/\|J%G[n#y\~_ܺ[n ˖<`^2 ?^r"#q^sM&]o`GOq4f3W{;N-#Lg~ C;]6N3g6r)Ԉ8gva,{) %X0Kʅ,<hn~v un+[UuwYGϧ>yc[8]grU!r|8>pãGhDߺ3gSY4|QO C枵}m=l|@|E$KO۞o)ɶR<|F>2o9_,Z8ƻgocVr &tҜIː[ozpjM~+OKJ;X[oVY2Ɯw*W|`5Tb{Gk޺mueT6WiQ559=oS1df7s_:qqaMrqShl~ſyhQsΙy])D#%$&x\o4$=*)]z}23 ,U1v9g9gf=y q}d]μrznku# Zk"%u#/"PpqBqpi%D/SfEb"m>?/s ۗ1ɧxc϶7_`ƈ۹w8!gЕ7P/xgӟ:/ܩdɒ%K,Y�DY4O#$:p;yiHZK%42'̯gy،@& 3nG`Ј %%]=1_c1Rǻخ`$YQHm " FzH4ªжB`eEZR )A4Zi=Q2\rڥ1 @WA*KjShzDBE pЋZqPAu@f?3Ts$,hB` a6qYNJɨgs%//?5h1f!ktiyѱCof:|Y?!+*GQ(JqQYTk>G/&D u٥ϥXQR(!fhwYW`=_t=o 9Sϙ̟IWu#vgYu''mꇌH ;gDxeO̾6}!�4cQtT=[#7i,>SJK,!d*GSW[GJ[Ph,NnA`|t#5M[Gl8g:<Yz#)=QX9i\z(zxdU !q|ֳftVĊ;RǴҴNw¿]iɷ4 :|Gw0Ǯ勘^)ho0}RY?^,A/_lI `qc=A|I? g[q7$~thN8`Ԋkb}z'GP2 W^ȝO51z6]fV&ޝ\4><Fs`Ԛ7ߩ<߃Ow>m^[qbudɒ%Kaj|XtZ!r"p<d{&Cqk c BȤ. 2ƆBX"C�Q( u$x+px="`DZ5NN p B/q},@H3b4H K.]dZlCMB~ V*(5N? *PV|Rt@hH~1BeB,$HeP{@J`XP"ACYИfGyHeşea-۽[Wn֣1-Y1''΍_yGSϲq_>bY+iZ$SP>31Sت ‹ϣ˼$x4ŜuE?wnMa\4հwOBwй- л#ݒUⰣk={n;$= ?d߼|6^֕>i݁XZkj:#9mM9 Z_Lݣ֡C+{-,8g%EH*Y1 ~mFso1i,͘+F6^=Wna'xJd4ưo?|L;x6=gzFkgR[ٰK7PD"9sw3뙧^O;;t .Tҟ!*> u6?ͮ>-I7+܎gAD"Lct�c̙qh\=[SeOΪ'woa‚v@m̅m~s;z[{ԟdFoM7;IE;.lwQV<{=`[Z*p>twvgY�SV!zz*=^r\sg6b IJ>ɯk)p姿N(BGA"0,J22A:H<m%K,YΤtf!Uc"~B:<;JbAAh�� �IDAToA@X@P7A #B�kB":C, hmF ӊSa` +!:}~&L̰:I+0S$*5vhI e%XHW[&1_t"RM/ 45R"b !VdF@a TƊߔHQոҥ*j: 믣ui1re8X<ʈ6r,;>%6vҙu'-_rJ).?C˓3gN|mh+&G9?A͞-²\3 ߂򵻿zj+*FnE @8b‚M&H}w*w1sʫδU(;S_b[/%H rrb wuKN,++ccYXX]=^>{DN1WJ*[?GsSP|񫅍l\9[e5a{"wLcc=#'&FtKӡ@ګJ6/'|D3}~g޷EۮO.tPؘnp6}_Y˂jb'6Q�YOȀoo\̲{ޠ%NFM䊮ͥmw܇=Ӏˆ{aʜL (cԅ\\F oϴ{kȑm0'3c*װۋX~R}֫;lA~/}ɣܷa#6>4N4LE%55TVYO+Sf%Y`nmlʥ6M{qz\p-(F0iRAnuRB"[t64D>u_rՁ$*He9k|cWʷf̒%K,HaqN4Bk%³Arw.2.T Yϖ~^BLb��: N[TgEA�Yqq=W)]'HTZuQWB$2=G*k f{-�aVbͤ\7b2.R ϐw "(~O0Dx9 J$ EṆhG`5E$s+>S%H?\0B?5ZV$4U0:C"D" $)le 5cS +hժ/t?nٱcګ$77Tn(!5jg9_ze/2b0OC10՜ߡKGmA;Fn-ykbǝ?3.l 8Q x<,r:_=Q\ޯe> ]K1'=l<ٺVy^Z^Fjr?cٜf�|^)?Z~~4^1ܹ^Dt\{ׯ`w C3mvþ|^b}iȉi͢7|+q]/飦+[C` Kv0,SbyzzO=;{ooLZm¥yW 5تy2{{F?֖%`vv $;A8mS9i_(qJH{Br$HкK:\0~7'%K |/Jgfv+tF~_X_1̄M ЦM =^ԦTn䶫.EE:VS-ΜwPGҽCYT._Џc YdɒiU\DF6%"\0I"%RȿTi#Rfv IJ QDA8:^2Ah $Z[O$bIEKrQʸ[<qKfZ+kZb V;B?k%JZՂH18Qm<"68SH)@ Od@h =_$`$&}Fǩ4> 2qfPT06TZɂ4HAH 4 2-f\4iMsr)-|+-׺u)&%77/|#s;nفn:*H4[yVW{CC'zbѓn! QqpDǜ_׭?tntSlo!nO*յ'],Vړ �,$ }snlCK&1t#|xLKaN܅QӴ+=2l 3XxֳjCSɞu[+͚!t\N1(0?X݇Qqo#/ig֓:<pE/^|/r'_c58;OW: R"Fbﶋ;n``Û-GFv%Nx6g07\Sʬ_)@6I^Q,%2LÓAD|{3 Ol xkZG*X>}9Sf3ibH M* n4?i rWfdjV:Sge('cu>̝6:Ydɒ% "Uktfݍ <JE4C{X x!\/4 -*V`cP[_@$]fM9=dVXDJkrPV8Z5ƅphp$"T8;1,8�p|kNI!�'W$X!Mc #=]AT8H.X~M6#Zbd@?䑯,BE ,?McCG~ԙX |J< ZE>jTiA�='1 U;wSoؖ3HzhįeoyþeKzywzF+X#kwl mKoG`<0h/]@Π YbD"sJ |R^'T\ENn^XQ_7\I3ǿʢ8a �-"Ě%|)q]*c8R::h],G7b$X9oo`Xl>Myskphz֮Jп'cugʓ[P1^/�YDQ#]ۏUb9�r3_Ǭݙp7sќ{yu}bԀes/3-\yS!) 8Gc/[w,YDӥ/"i5A.tR}hqԶQ`RvAʓ#{nac^qcLMS(w"Hq|?fo>k`"gp÷/$xyF%L{_iX mf,rFv6ﯡ޴6)ce=dZcK,סf[Y'K,YJ%|<QXBkJ.uH*P @f2IQiC]�!,B;$]RI�v7hX6MCMXéʠ4c pL�uo S`S[Q6MXQb05."W!8l �@@G1-X bPVc mX ,"M_U7 32J �ׅLJSZ{ᖛn`3Yǟ|kaP2d [v<<?= IOTVV�B:r it:'EW`mh!e$].]/)8n7e>/tӄr <1y+W4¶; <NKb<>9VY= URǘ1t= +\^} Ea3p0$aX5u:܃;պ~ƔH#[<x9 Yh^LޢyŬ]M/k~tײbACӱn9"t1i+&?F?}VZ|/ݠv9̭wƍN]$?_p r̹'c.:pŠ$=�a(۹ OfY6eorH{ÃC?)<넻MV8'%:|?i|E핳{ þnkxl sus- vxI~v,WzWPi%WDf2`׶XYq;HhTNyN>j: $OfeͷsAUS=?Fx۟\CvُO?ؗjpKѽ m4WZһVfQJ[A溰/U9{`¦)[tt=~}T:=)IauQ\=rrޞW;audɒ%K8H(r2h7EjibHOaA)BE}*?od8Ό�6`iEGevd$INy =dUa\mHiE: <BKJtʀ؀ OTkLLW# $Rk/B!3S{8>&Z@`=ܚˠ@"EZ 2hEZl&~qFD0n*U8RSi\QP/f,tJaUU<2ph]egz?\eMC0Iae<K7peZ_z9s[$β?ˏj1A^_?&Y25Vq=)a8&ź9_ ty7_tnFwP`Y<gE1x0ϹLaΞA͡Avw#nb{ʣ8{B` TsޘV> x>?򷜯q̀bN2?#޳ l+7aO{8Ģnmoı:*̱mۃ^]4"JOs(lcW1b6p5XsxV߾oox+&%w; Ù̟ؗn_^6Ҋ3:*Hɓ�±|GCHZ3CǜX'+p`xu?./2y<F.q/l~o5}>~5l+ :y6;Hv<d߶US^d_dm?w,f*R*ݻP;WNdغ&# ل$k\<DPT͞&Log5qk<'ئl ]u.e ׳im\5wvەIn=-nv3/ye\q덌9ٳ; S^w7v8<^].yHSlP'K,Yd9>KZJD4-0(c\,RBkBOL>Kr`%&�޴$:8 8q;?*#8"h.7"ޥ>mw;@8aC < ڐZ9C%>P”6K)1 , '` u S P@D`06"PW#""@0+fcZb2BX�-,p ā ZBbEqCH4zJY|%k֮ ep?MM<3w>7p==zt(gΝ<s2l 5gŗ^=j*ÏMw&GPRGN 'F4VQkV.eއ<lg}|1}F7:''W$QQ[M-l?l"T0i9}{u ԤUcl^8 <$m%%]:~̝ WtqͦgQ:zwMC|j|+*Z�z/!==61aAڎVQHUgVV=8A)̟ŢtzthEaN Hlz>}6�46mrgޏµ)jve̔7 {LcE_cT4n8U-m{61}V/ӛI5ԲoRV]Cu*yQȁ1iDҵدPm \D=:R&UG9<̩iR:cf0k@˄Jy&ě13h\?5/ĸ0PiOΫl'hY̟g%;h@ݛ;>>T\Ζ/`XXmNc0xON7˿}]z>>|-+}sxX #}XX0^XQNk[͓, dͪYQ^"XtD>u:v:knN,Ydr|<0ƒ[]$6E%)qc`  | a*!])D J;-P&ph![},"0IKiP4~`I cܳthF5fiI^g,Q)ljǡ& ր Zo$%nEjl!!Bkl63׍na(8/jARR:(l!B]k@ 7L#4R.'}ҁҴ?L1Q'4x? ~mZf ^yu^yCI)9l>54ojMKݍ{ۘH$y);}w<s'& Je>m}Qǜ?8]R4"&9gp{~-s"'b \q _KH,Ydɒ% C7$aܨ�FhXDLS4"%HmB"�ypP8Vk%ɵ V04VaDHǂ J|r'FAEzF )-ĐYAlA427@4)_dQBF5:IѭOF=_CDBԯ(ƀ`KrImqIѴXsDAynAh&dr{8?A+b* ,-҄4+ "BPQ MCe6P%$.F V,z`NxJ-թ׿yqѡC1̝;+WqW0b0"ȧB,ŗ'آ-yi,YrsgGa=/W/O3)e]pCo%3fɒ%K,YNX[4Rhcn+2jV(UH� O#\N֟ӤJV9FDHth 5Ðv",h#Րxِ/(2B 0F^ #+H'4j;* `EA@gU!hEW%Ơ%R$QG:iX'@H #3#a) P "@#Ka.2`<P W('m4RMsE~# OqvQge,Yeyɧxɧ{+i~2v-$9ƣpǰD͎a:t'_?"].h޲EV?@Or8d y,n̾sYdɒ%ǁq@`$FX0e6L/ٵ'@6Sڮ b_]'vmIQ>y;9Ò*]# %ZhFPuIt�PjP ъ`kim#(2@JcѢFpH%C/K!@ RCғIۇD&^9.Nb@0�|-t%H%0vhJ&/Z hr1R"M BQo@9nf<dGFYNr|k?VUO�� �IDATYCS)Ydɒ%?/&0H'MD]=#%XP/R`lɊe/g̜]#> .g;%Hկgն3orY^xC}L9H '>F$$P!פ14<#0~�)',GHN 79{5s(:CꌨVk(KdqI!.HM!vEwmC@ 7HQ %X|qo"p@`!ڂTXk  B(.3B+,(v2sY$D >B,YpC;{R7K,Ydɒ%K#5O!}E<&QYҥdlmE^$<&"gJ7ҳWW’Kж#/E73Tб]jA j W^"HoJQD95HafkH;EAS�#lZ. nSCj%dbpO_ pJ QcQ8`ɀt$V Hx�dPX|Z4" -2(#Bo-,5"tj,07xB@Mq?dO>J,Ydɒ%K,YXk>TMu�D1.%Pk5 ۤh4TI n[cT@gе{wjky퍷p$thͨ#f^lyO 0K 41+%~GXAX JBDEL�*D`p5B0nT!|)0pABqehD 0 !?-F{h*\D"�A�i$9]y}":#40` #dSlSm# eXa-)ş@q<? 6HФGg9Y F"OkiˉfWOdɒ%K,YN"Maqb p�k n$T5lgXvXj`WEҮ^xpoolݴ-kУg7NjMatnՕ'It n~@čS>2M8V)N HD AP7? 9Ub6 „* Q)@"zDJ^rH-u eҴSc�i]RMzEC4@ X?j f3 E A + AѧYdȴɗ&g7Y`<>EDMVD> %;?[z&Ί?gɒ%K,Yh KJye}kY.HrKrFヤQU@af>7><={k߹N)?QL  %5vc:úEl@Z5 Qn MPik5u܁X�4Y W)TTѴ. H LR]kA(FB4ƹ5Q<5j`-H$W%rBd 2 Ρ`81U d5!"`3 !�Н aخAS U |͊t=uܒbr?(ސ۪f׳A&lN!%y[T6 J Kh7lZÒ8Ԑt<8K?^=pt *꽣WP9t&FDY?ZDi^/Mc.8,>yk4DYdɒ%K,h#DXi9>>X)<X>YSI4V)r\իHΝz@l.,_R&w׷7BXJKsӽd]/e;bXNCGpR Y(fF$MiTT@`foѐK[yM`,hi4H1M/u e5+wh(vqwkj1DM 0Ya<k4Ef!)،@ Ԉ",h� @(Hp#$+Hcͥ<Yq`iQg~Ӂ7}|_A|x23>Q0!~6y3x?<rcMqznGzviÎOGyTl/:'z; ǸhŤG0UL=<#6`5D!|o#<@w_><<Vy:#4e9Dk x%qߝѕ?aEI4<K,YdɒOkxxX,RHl3sX=ס'!KSAlݽ['Fnj`rMID"Dx:Ɲ3’qHq/rlc;Xǂv0e Q{ZL$1c4:E6MwHKa #ZD:hwIHT+x(vG ޗ`+"SZZpM _J(HN09>e!P-FaZBbX́�Vl RJͤn6,AUgCjӳo'M7/'ܷ%l0ihH )*%"8IOc\gZ֮dNeCk˥߿['6 R44$HJhkt4yU5qZ䠌GcCƀQ]`УoĎْ ҧe;S_L+S_XBQ4?7hS&0"ϣ(/e{Pd|qD%/=ٻj_,Hn!rt&IPkcM4$=|mR+0wjuԛ%w9Fw-tp:aYk;Mqf2 nb\>#7wc9x~:{k)Y,Ydɒ%˿cFkQ`  w>IKנDc%W1s͡O]SO1b۶ᵩ`ֻ{hSs*"FrPNDcB(TxA"Rb 'IWV"ۧI$N#E(u}t j_1hF\RI;Cc@Y!vKt8Jł4j% qm+"D EZkhk"B䠱R"E�1` % ArE¬ a(8`-45/gKݷĆ2^@nUӎ|Qu:>8 MIgq/el:O߽aWv57_U{ƕy ާ< U4/݆\]úOE%y;Ə~{M/?N_Π"ړI_1}:Ѧ(U7,+}z웿*Ncs/#/wjm{2鋗0./A[G< ٵp,i%53s޷of  ":*⊣: lʦ(((!@6 owW7 "zGޭy6>:&x>5 Û>Vέr|09vs(PͧO?$Xp꩔9osGG:C}:W^β́{Q Kysڞh%\y#zRꋷcOシ7p? k*HgdddddddUUqr�PW" A1Džl'aV$w(Q̚g1~=n:]# gƕtw1vFԍƎ{p[~AǶ%Rʛ]0 NRc9ib*I0䢀\Ċ"OA ɨ<=dOEon)4$Es$,M˨P~Q0eC0 3'/J>PrV+�ؙZ8hh�Tj2u�HHb  ;t fcg03?dwM맰XǪhNć9\e줙1M}l/ɐUMx[˙?wv՜}A?3|~XGƿ}To2q/1mŝKXYcz:SA&%?n>Wb:tXj h25ޑ>xk]Nd]ǣ s+#W\/:`ȁ7n/:CX*I36~IEߴ#]8p~ݨz)VVv#6ҋ68(~ìs/}n@zL}?3*jbRy7o-`{~~ѫ/<sO=n'G^ݚiŕܸ2gxCFFFFFFF)kz)^q*3!L#&aT4zOPǐ2r,cOe�w*ͤ(w46jº4A~Aț+jqp}85Ğ ޤϓ 2=~\=t- %3pM7Q\G8nKymi:C\/䝇r%ŤЄJjHS#lG"Ouū`P1o)$q 3Tc{WI=oḻ)w"5Ԕ@U#-Я}#7sd >־gyvwLT)LfY/h@pNy[w_>V#*a 's 3]\gt6?6CĨΈW<J9uhc[2ck<8DfM[p(l}Gf>$g06Y ϤcIVÆx}xu7u XWҗ0g9um+a.G!Js<&2|}ݟQQnYwW,ΥU} ? Ο1n`?N;} }WKdWؐI|Okq qQTe pćx{#g)k ?7PzYsmXf<gZ]R. ׾M[Ԃ  J4T�Twt:⭀,.,[p0BϮs>Ʀ;j@[sbC^{i74h<5lZ`{%_ĉ'SLaR\(�Ñ/H4$q !*56Gks푞^#.0ힰQj+hh{rӄVHQ<nGLm %`LhbAmEyۃu!)j @q:(RhI*idz~(g"{SϴYnG0~ dueђ~W_qPO~0tK[Nx/槫 ٳ?.{7?>~z�9n\qv JNdDeHj- ә:~.A3PZm~j4s2�q̘jX T>Xiez׬ }`ƞQ*tG+9 @Ϳݘ{4k;>񱳏`1mu 9B)L)[J-5>.,!ǢyJ@Rb{�C |_v k4/ԮZilY0 GM[gOpᓹ{22222222ޡB-zM1Q!T9."91&%!((|o<[`Hs+n#(ϰam 呃%~ 4<$ux-FDK"P{EԣBԟ >2ޢb`y&1ÖxIcDDŽ q>V pc7z6E .ǃH\3P#6`P̮ߚD$6!�0xT0Dob Gp |9ؗ" –6S{dFzZ&K/bxo~LɟSyLupoɒpZqk:қiDWb1*fۑ1'0%K?=}-̉m$߅a폭a' #2]ގ}c]6LX}Fss)o5v3a*t=mCo9y5_fG>_v{2>)<z#W޸og  c^}(5OԐ9ܷ] #|ѱ!4r,n:ٟW3ok߾us8|?[ Vܫ]PU<p׵d{҈^22222222QUMR#94Ql#oC$!JdkXW1I2X/`Cʅr򉇓7p٥?)Ӧq1 _^3J okAAC{D! aP xSﱄ.X58Z@~O瘷T׃Nj1hB0'G\#qU xQ[- Q`TL$!P,jUyDҴ U0bX,6R# 5/ H9%$t җ, /) T ,Jwr\ǔA.a}q>>k`R*UƐϿ9||-̅bC-Gc[_.~J+lV! 9ʆM1nu}kTfwFfnf*NCxHɾ۩L3e]%M9ve̴us}uOa]Ϯ'Ccǝ51sZ3˶mkBzLm?r)叟'>ɗ~ ;s/ĵ|yuWwrڽ~=%}"0{rBZ=v>ҝ92222222aPv&i�1pدiwyBC{0% (!RE`\ zkgȌX ﻗ�� Mvd k=B6cEKяk{zLb0fr=3TWTV,*j#( m'Yh`UVIPLcDQ$%GBra `)fx@rxT Z6LUI뇥ES BGy1sde$X:o鸙; gO;Zn[C~ ̖iw-w܁ nekcڵt1SZ m6rlZ ;^NfUxv 0O͔u?5K=:.obɀ"}tC9ɬ],L9MmK2:m*]+Yӱ8eckQ3Q<d'~.ʰç .jn{)3Z[µoc+'qiYZzCҟjt`)w޷Oq> a6 Ս<vw ]p6|j.z-ŶnH*R';J8īFy,[xU7 O};r㣛] S;Il _,:aQD@ccI@W0oɂaqxp#7Hal>Gb4 bh8浰ng}:O5Qԧ80WIO%Exҝ|cXzbpVQ/ĦOF XCl閆~"br(' Z,I>JZpj#�ǨE/75P(ϻ �� �IDATsx+38} Ա︄o[Bpdu8V7 <^Rt_SǗJl|nY>2^f3A7yDo[yYӵq9w*n[ޝu= =_|?zꤙ9GQ_`S1[ne@Nt,ozx|/gèa/.M( 6 ]g2wg}\\�ە `͇iୱnsNy'_> wia?^AX7cg,V~9+Tf!n:_x}`s>3ay9b�XIs^]O}Yu -O}$^1"3׾H'啐TY<y ٳK񥙳c 77QbPF;kV+7>Bt܂-6QwQY�vb:SC\" E`h@UAHP P7Rst>Q i6PBhO0I%t% `"书_)x0) w "A^</K"%r^<]4 vˠ=_rm?.qYIc.S6/>#########9.q1oBzVET%`ݡʇbVV}j |`T('@9휳x/Ws;*_vQ>S7S_.Ro/7s:s>Jћ +<r9TtCb]Aтï2.<|R!QгLr'U$ԁWM#,е*[kz xK 1%81z6gjA ^=i"`@ŐH@*$䡒rK5y8 3^*ކ aacYt&dxFFFFFFF !7xUAHw18Ni ;GbnヒTjvOTKyIǥb|xcnU O+^D+"r6\5Q%a^= %161PE4ċC  {˫h`F$X/H09MX(Xu4VGPdKBcxWK͕(HM}XTZe+t=� E%13AŒt̤#9f\/,h #######e#6MiN` _ x1*aH_R xp"LD,\R .MaݕrkSQxf9^s̜A[c#b0HYT'+HRŨIs%-q|$Q h[;< "΢8i&lT7C0Jb7M<HbRy@ п|GLT `kb/s2a&90X15@ƀz%Gj08bȁB(N_`AEج#2<xId膛7r1X@8hPaT?Vŋi \ V"夽 !J8c>Fpq* \jM{ :ضm7~7䬁 mh&&I(B@W`k V;acm2h0Xֶf;)Т*ԏ�J*D( ^p) TX4oY_ulAWHTnPsPՈHՐ^IPb(DsY@FFFFFFFFFFFF+" G{LdTb<"Ւ>VmNPш!T4숍<#P1%L8AP4A� HvǨ櫥avmݠ̩P%Nb̔<cՠJ_ĥ|u# T�[ +I^Q >Mɣ3P/fN6kX0ZxUzRA $ƒБ {$/x)Q씄*DB0.O=X —lSaNua@SeҒZjzaͪګyϻ1#@T* 'jqirg<&Nhk`#SlN6T:<ƙX I?a༢a)e77TP Mu@hLGR'&!E)TXН$ i @1"FA3jv^9H 簁г$ i9K䰹<uvx2_V·ܥTJ9rԁ vU#ZYxT@$:4&󪹳lZ_)OSSm_Hes'I> bz*O'lpNB0@z*Ox#W 4ئk x cW 4 iZ&QTp8Du<C^t5 Ԣ*ꉽ'H%"&ZE#HҔ$Tw3́D9B8H9$*D;)3wuycG20EKxwqx瓼X{+D1؂iA'`1օw2nX?O.屇#gH};#yb޻K}!N0SmEE' A@#N H ^}:�kա"h$H!VTå ‰]Zc(BRC1^]ZBQME }O!"DдD g|A`b`bj@FFFFFFFFFFFF_"7@'RvhTCAf1\S&cO-E` kI z+=]8`DūC:N:MSCZZ5 47L0lLvnד(t_4 pBE!?|QQ �UI1fDPEA0I @<>y. [CmIݞD�GuU ҟ1 ҇ C8a0z 4B]4xe�R k�(cr8X{] xId/AE7I;Xn+i3yOቅ7׳ufp�oz.לAn<x_җ!5_93<|ǻ8hkiuÇ# ,t3c ۡ*| Pg)K;g-y)( M&h΢ɉWM Tc@bI5]!=L$RИxsH*FQB`x>ۦ\QO!L#hy VjE4ID\Y3K9Q1b' "Hp@d [nw7<^x[mG{t!+VW<:yԑ|i9A] Xq&.ԧ0+cäQXk qH0cB1G;@qĴ UOQ9~CP�+'O p! ,Qz!ol0n}�bB%1i"@-O8>bÒ!oP)34[U8(HO H{%##########c/CG8ZhsL7$TA-�-e歨w+ӇGgo?_)>,}4�FF&g)t4P_I{-]=]B&8P E%N"VF~E 39 ,IC U'9\Ǵx|(9(=5 DQx:0L?CxXHzWlIY0A{%0 eu0IPF`@,IZC@@@<TjzU$ƒ QUj'.;/x Sv**x8!BmtulŹ8͹Gx;g?eE_\ֲb\WxN= GԲ;1A4!>5kװH=;v)o !i#�_2IB2NW:�56B(] PZyZ8@NȘx}E'DO[z~:=$30,IހSw"0&7_# 4c4�O{6h'6uNFx(8CfN!am O^KTD0S?O,?QC)6 uo{0#?{6T,|\ûAX#|{eђe{4kQj''γ"nCW!'󰱊j|Hb1VIH;ځش:�c q~VCn%_>foc$H y<jh -Գ:@ ZaVsdph0\.JBW' A8 $YW1 '׳43#R'?W{]u*3 32222222222^�GAׁʀ%h6.!qq'FcC-93ܻ~W]ɵ^DO'رy3/YNekVgGB|l6di8,"LHB6xM0B~x�&ƨ!02&ŇEp)I}%,T(H_R^0Lihz{'EGX\M8"oh Ƙ"[xް犪cX1,GA GVJb| '>\/]OoSNNn+$=#%inm\Q' [R=*\]zp%o{6 eds/zW .ľǮޣ`oj5!ή~ZHF�ѣ7c5a R}T\귾Ee &NRc'Y=Jg1tPZT衆YSa×T\( !ka10Gxȧz3VzQ Őچ8*a9vȍ03])FئFo*X[nK<Qr�Zs@A/(cՠ}H"VӪ|B5g _N[[Ghii~{ow3W]u-C|˕W׿"'G|"Oi#Wf;L@;{"uc&J_]&r tMgW^u [8zB#vQ l}RHcsV3222222222Ʊ| O0лQVP/xc~׭?._i߲u[Չ >{ _s\sxW>skx;-m)u$ͅ%G0>j+hE %}V0#4/ڳ"`sNyR^* wroeHDTqZY/5d㚨A0昰8UTXTVMAZa|]B|mmm|_>J[[M~ک\b̘>>W'?w"ß_ݎkݏ^@_`:9t\xJzMy<L8l6'V-nnWm?4V^չJ10PZ˻v@^1^Vع;l8=) gDݳN`>ӣYy{ ҹDAkC Z /%usya/aA wT|DN*aϛtvQ4Owlƴw5v?O!,Kvn餴B Umdw;v#͌VwW;TrzeN?T9Vfr1= ; ,{1~~:8wpqᤓNPWQ$fy8?,.ٹc`<̞*vl@ [B4TG;&Ԙ T\ B"ɣ! BEă $0u jxc[C<P U"zC1ARl> 9@1^ 0Tj F$G|ޢi`BbG}& "N�ks!Ac0D`}s7FݥWY38Y1fL~䁇?wr7/¥+gV?ϝ8"{Oi\m+zVKh:5f%|?;6Rd;λ~Mʩ7dڵyw WA8o5P9s%_e'a΍,ze=Z23Kf&c9+dp5\m96`瓿<L_>y'~9=>{3$/eR{G0Gw0y>&}'qjV)n6ID0 >棙3 [dݒu j*########�QXh~c/+aÂJL"`U)rn£ qyCr+z0e0rR7oūt-`3j03CRrT0!^i~ZF0 (r2@-uTl*B*ːYJ<F#BfEHC$HqAoTR#0Fix-J#A3xYң1Q&W&.pJӛO.-(MU 6 qGPDkFb1ŋlBt |Z{5丣7Y3g0ct�ƌ9�rEznwusͦp[{B1s8>OHWKsm(+ARqvvYv m)`5(P6a_r؆/j!9nq6KG.ӑzj;GM4ն5RiF]Tm ozΆ<#潆|X2ɟxW^7~^eYgnK7oAd|-xu=m#�Jv6pijm`@t?v8\&s4/ s"@vnܽv4\Ǥ}$C ϫ@g1k_NTqPKEU*+#IJnXԎAӒ ^$rhA@aIy̘xl6piYA!VϺK Z:}5%)t�֧UmvlBOHNchO~`Cz-'{z%TV x&X Lc U?$]UC©fH-gXt>uB քCE X CXQh:#z9j$7l�ޞn�)݇Wxa{!^Y@sŸ]?2շW:,Y2>p޹;Fe`eO-YmiO}Pp]<}6!Is8eh2K.c;ա/ѷqjˬ~=q@*}~ :\@ Y9\x7GD Խ~=Z?sv�� �IDAT9u81wO]_F6ȳ! 6f5#/z*w<LÍ}JXc;;;z exc0c9?6w,}9wC020s,ȓwmW>f ?GOTꥯwX3#Fnjz6 P&sc|ꬍa'9Sx($P-`+'H.KRr5[xe2U oa IL})'<`jb\aE~\?tHqj{oGQ6v4 7z j@ A(H+?T@P^zo{On/=Ao>'=Sݻ3<A%e DF v3 0\t}22[6Z(j*qhDz`"4<oPxlj^, 8,S,`Ѭ$1#I h8hcFJl52w2�cPY8u%R>c~ \"g`C~ߖ4:Ţ`GSV>M?{CrL\j9v!|_w�$q�Rx㧐9O Q̰|&V<;[t?~6',k+:~k oݓ=pg58^fv6lQ9qTDvkp%_r9\z&5W?Z7_,.߻/ǫMmn7?0`i޵-i> "4c==Z̮lg`]IqY dVޫY*,{ݏU�6ͽ7Px|_f)4l.S93iA_\q+ReCq/9v6l ƃ*(gv#2}d\|DHHHHHHHHȿkXI\)RH&] #Mz XRP(y)wcO3q2y4h!�$Co.$]߀Xğ x{{a#6P=e (̶ x5I1BX) ntn%BXb"=Z#} Ҟ&\R$L LH` `99 1 q|Oc5 D RZoPJ"Em5t| $o˖:oh?afZue_7vm- fsmغq˷*s<GzeS)I--qa �}},_Cټ�ѝ/\GNlIG|�aԧ<<B�\<5p\v 4`Rf7Nw|XEfhj$FǗ݇= /`G<iGj@H0d +z_ݹ bL=;̫u}��h<4\~6!KX4wo'{m\2c:solfc{e 8Zȿ:yA&S>0tb |%`<LNNlO1dnOKt!NΤna!L=iOg|VR!1xG"zhdy/(8DB`)gAmXptփ!ê𥯜˂f2jv@Yln)aN;U:0Dl{&H sFF 77kAi!FX3bHT@ ȠA.MD nI{>.a'Am 0@緖4@$mA' k< <F`EYI p{gqG|  M5^l-9wgZo8 f&.5ufiB4k,,V8Dcp(*=,I'0K9ڼyN{ `wv-/b̹2s|_JT,':3ZRLv9v: ŋwwvHC? &!ZZJf9<m5w)%EJI.zP 3zC fMG},Kq?XZjgmIzb,D"6!P.Y<m#PM^]<-.=y/uv?ꞗf.IUIl!X$$N6Nw!Vhhrh H40$M~+hⅅ x`ҴD5A$֐O'JH&-`re E]]:V KFZ 8;}A:]ӏ=B<缯ʾ&cZKIa7<]յk7a邅TXgAIr *V\<h5  H:[O:f1B$V'ŠWxMjS"$5d=8&8n2.( QG/'9t%Z,aMzƘr$CJнW i:>vFhNܑgc[{b�JJ R^ޚo ʫyL�/^ `ܩkN3N,ѺhAX+W/SЇekhIt‘Mך<NW�6ُUC>^}GR^ydn4f xڀ5~oX*`׮@:T2b )Q4{I7Q_SfHd{EHiLt:Iq^Li1NC / %Я0+ݭ?3$[EXҵغOYɮglWlY;xxǬG*mq\0i֬ڌ7 fԽ0FkdZu14nmMPTjiI^/vq7QoW>jj* 5ۼ%;'(s**7F<;![ͪmX̄!WHjYK$%$$$$$$$$Ӏ1$(l}:i&I# Rc2h8aaI4ӒU4oみͲEo3r(0d&K4 DADI{S8#OWwƮm[q}pRcuO6(vW,'iwa-FU lG DD{ `j[<@Bx;-<,6iq"dQCH|BSX|p5+vQ85k0Ba``!&ːeX(%AQҧ_VqD(ӏޒ Mv͇9P[Sͷ@О~.]8?M{ȏ5bĒ3~x+ۛyQ(Ci%^.6.>2s%&m]A.ZkÉHfK}!bbXor̥Tq!Wgxb8sr͓55=/67f~:/3Y:e =XʜTkl|CߙM]y#7E;W0[nL??{iLAwAue` +wēF7νؽ/hQx4 ?q+\̟W`rx)rl ^®T4mb,^WXHR3|xҭ)(9^?ÆIl8]|ymj^ywHwF.vZ?lBBBBBBBBB>lM dc)&%b<x%|LIQjTK=o= dwnCFTr ,]K[_c̙j7EFx o jHk-Whd,5:X|# 7:@[r,#KSx;,ʳh+H@Ն7T!%dd012Q\lFc<5yi#" lFǑ Za6AڷxV2`Nu"A î&fi|$ }~y'zL6QrLnWV2lyg\޾Xx ^</HĤC$Db73WS =Zv\2BTk<9/rï/ fRn}y/߽LĻ w<|#vln9E<}?Xl<GqW M<[yl{[}2kW/o~x-ػ@E 3[xu>Pi*8Oc̓ӻWφOsCKIr/uc=;Lǣn,l2脋EꕼyJFE"yﯳecv:rUW>?odզ j߼Eu6QyW;s+b wrkN>B D-k);B .!GT3cM:ٶ[RP T^KxTV)~s97I'ra()+q$\GqQGv?d"AD!c g(QC@[<).AU"GhU0U+75s8"1>hiQ=" +S+(q  >(X lGj M !)\$%(rW%hyAJIQK<Pq08tW#?@࿼\[o%Ƅqd=Бɹ?ǂM[I)gtWR<# Ae]|԰.˯7ր4Q)(VBEDlkjp0Ïeig0f(oۭ@k^ymz b`GR{-iy9Ž#H:PuF'(6JMuϢWĩ}%j [cB!"HK4n"CbRɖX,$ ޚ',{X2gϐ ZAR\qSЧ!Lc %"c09{-&ʻ/>~2lOO2JTD(?RK@nl}UukN{d 0Pm+*<!5uY:xw2p8>@zFA<T)2E\אր4Bv.1&A!UajG4=`vJ &6DЍ)֠8(1b#&b !Q8Bc0\t'mz%&[8wY͂# `h6+4(Q!|lPZKa|X<!+1D[0M.|ƗE)"M&cb}vPB` ^Tʆz 6TkWͼs5i 8/ Xb"z'ڻ w@`|V@l)4 1Fi87OvCfK$aiq*2 --QAH2 :&Q`}%ОcZrO ʢJ$V:0xK,#%(+0c/$8(hNde# HEaA2(PB#zǨ㚚D Tt!q,V*0<wVlSy=t#=Мm`Fl[ܹP5d8ӦNaʄ ^EyE Li>;ÕkqFyÀȕA`=pd$ PBDF-CZ4 ŀQ4n2er&}KbB=}YGU(tEc,sB*˄z1TJrM>X"ҧqGh&nQ"7k,JdaH[ FxvmkN7X m;7+l&qFg`B>-Bb+cFn.>w\,X_x7|dJOiʦٱ׫<ص'#GiS4a<z-H˲eo2஘{@D Xc0lid"$/qHtc%ٵ'ZL"hm R*(F*>51$EYFоAC 1 h8j`Xi1-Ͼ&ygizAqaJ Т0Dxs$X9=/ "lਯZKf cȴH7DxO ς@c�G bƏܹ/Hy׹72i}d^=hnzV,x",}lճqJ^x1 !ӎ#a$lU_N1+j偃ǂP4B:d  "Fg4BNARKqw4T(T ]΂CȠ$P}10Xՠy(Z;ZHGd /0o4l6ˡ+cRA Hu>F[ 2G!I8VBBBBBBBBBBBv  48GjK9{X"YC4G&uβMAaGy<kV/gݺ5"/ZA#5}9-bWsuYKx$ŠD#')v5X5cɒwǴ#`WBEqWoXGi*C2!VAcPDTKDmfqm}|iP(x)ѷ/ P4? OY8 vZHe hZ"Dws.л+ D 66iH(\e3D\t[$$[wf !y@HHHHHgw:xT哮FHH+ p0IX)vxq ~EQnW3o+d`ʊ%A-46bAbIFҵ-гwJ.<ϓsWp=hfԌY a|,#hQDH, /k"StԽf+$j1K{4J,(AzTT،Kë)TMQe7[:6#�&`KQ!\sQ=ND6%>X�cA4 $_?Ә: c&$$$$$$SwV۝U6< {G}~眍L:YĤ>ʆ| nO EG?{n:AA>?TU "Ot8M:3@U =h�~|ݻCB�z'eP"B'WaH7K2qa)f!( **z,+gEV"a&˖m[d5RE$X!Ə.]8Q>FWz4aT4|>OEyW-|VZLNhZ=Zz8zM4FK7"DŠXt% ~[O|qt;-E|*Bo1`PJ(pil٦ٴŲa3dYŰf3bXٲjeF UL}VlЬ�K6xXe&, 8S\ӺO] _{yZ8$`7.'װgӺ 42^;Ǧw,od6X9/W Eh>XާuA`ckz7Pz 1frIǼۿJ"0 g᫽q֤?uˣ"-fO98ztS$8e'THؘoz!�� �IDAT]@7X}AC%S'T\{D+%۲pxY9"a`e~-poOZ{\Rݞe'\AZ& ֧߿}?Y.8B0�^1,h1~,^5@rTX><i=wgʔI:`zɁO>嗗JŅdM@״iSرK{1;v%DqcG3`@%ߘ5}O|::d?$UCQ]SChjn=j\_Hꖯu#.h1iD֮_U_Ƌ/ .S&ObqX 7l!C0nh7##s׮u7лOo:-eĉX`5yՓkt:nǍ3N?cFsaS7$Hpdͺ 0aX~zL?gc_?Ǝ!U< *va;'z:ҲRNq O<'>_w,$tlnQq 5*"R i%au;9IN k}90*vAIE6{zv, +]|iZDzTlQ]̫K3aAp"Jd1d%["b41tTR§e yKr_Z +,"-")bix'c4%P#婷X ͞74;k Ob%1F}%e]t,+C8HAAQv ZٗӬ shBBMt{sE`c6wL<enw.f_0~6g`I|`kanex.'ta{pZW;7"};֭2.Y/ZdP| LfZԖW4hC{]8m~/W L9 ӻ I& %8oI[!ֶG [c^vMp pVI-3L.n-lUe%"3[,#0`dכLkZ Qq)p,n )ar&E}%j WTJ|F˴R+z@MC#&i6PeInH:˭C$>ܸ6ggh0A ڕ\(\?( .`i69?=hW̧i$Wi:"ApJWˍ ݾG f ? V<0D g{ʨ"}IX d<< 'uH(A]|2Тmkɳz0U-KIR$ehAp=$ΙݚG ACb*MK/p|g% c'8 L<̹ߧMB<cfon姝z*|2J)5{6yxy37zBٴiU6@03;gD#nZ~??#J3G|~ǯ[pmsc;x:~ݛD"Ɗݻ7#:}sfȑ\xwC^s5DK.Y_s׷/g}KR-[:cQꚚĔ)S?rӭ+HS\qޭW2h ^wFuM qsaSpTaM%sVU \aRTTtSOevzi.jkkxgXb?|g%TU ☣b,X={b� e-<3L2d!‹ ˯e߿vPYُM7nu]<o_~?GMu 'N7ߢI3QQQCNmmR!UU j1DZBkMMMm븽k;ἼzAuɛo9hu0 l5DR8}]Rmi@ *x@q\pA$a|ѵ G$sc -o ) 465#D(MLF8kzhkAS\k7N}8V2M&" O[OeP\ 84lɒjp+-~ѱɚ G:%)<lzCXS8 IxAA ¢eh@a1֡_?gUa(*P( `wkjͲe#R $ID ",lK`[b\sP ?>{Iؙ͊㖡[ټ.X&8oI(]w \&S>~ɶuV 6fxV/ Y,#U]tY==p6!Pw o-;)'WYl+5>yW7&_gtܿ=0L@`lhYnvkSup iҦs/^26]+V WŁTO[4^|3(6].X$/mkdP> e,7{H ȹO$rt^)+4WoS@WMjO~l+xӯ ;r.`LU!*Ɖesː~Ee$˛;^� O d\̭ /y^>Fիqw%zF78KGrJ2XD0 d-0/[-0T0"W )8gm-+?47z ~)PG&3OdP_hq;k9OSbAʶFkcWh` vqێ;"nvXʷ}繼R1Xڮ L(j>;JѡW2zhyDg|slyy=(@a \u\zٕ蚫�nUb!\& ywIR�8v9uST\#<ʸqcM�P^V֡y3f9k֗6l(G O>q˰aC{7YGWU!kllb<$1r,IfM 8p�%ƍC*bMsԑTUUif9ri Wُ-pq#r'֧Ӻ9믻ߜ=;1)))g1 6Uճx5qc-SO`޼L<<Ofz uA FAfe|ֹ~= M@Btj7g}oUTUU1eDI**PUUŅA)E<^7gnO^v,HRUUwcjmwr`І~}2m!w1Zҭ~{ΚW]yyx;? N YěooZUUܱpmlM7Cg 탣"iFx+ :p;m-b>Q]ͺՒi|*zEg=AcңzDj]VVHϞ=ٹu3 ác"\0!@{D!o4l!߹2zooC"A.W F(0V )Crj##4,hLiHϒ8$A|n%-FOH%dzD<E<+J1X4(A44h2͆m-cVX,B hC.i_lXy4)BXX,Jjm-j4[YhBIgĢOV\$,x}@<x}Ͽ Yi;( P |>wh{VKCgR-CRt,hF<]ni7e 2[r^1́qYl6vv,_Ff ܴvPx� 'TtE[ raXncy~9}-+˛2OT[@ z{^2")Xd;y>,o~ȘZx1kQg)c[?m|{[?n][, z]_}ݨ̏mY߰.q/(v AX2kзv#,hO ~<0o;Wi;\CgcQ|Ԟ+cFs)I$9zijnw_Xv=W\~)@knk睻b vFaarƌVe@qdo}s>(WIaڙf+:ujPWadVƓO=3Scw8O>qڿV7 /질[o9Jmq4e-C=2[Db aAJ5k49|{Q8d}@ (/_'\xٔDQHs'~ǸkQCAYZ/)x*|ߧK91jf,x2"BJJf`Me,4za$$Eɓ,NT`3Kd 踏Yg}o+<G28nuhŷ) Ro8[2\ `1cerH!ZH/ $g>pu>c!X?qc )ٛEcl>m&;u{xːm7= �7VkݧvW<v7 @J(, x,*m;`wv7 @0Zn9`geϟ=(sokx~nLj?U�)= . d~8]a~cҶk6__!Xm? /Y ]0/a,Hĉs3[lN>s:U8nGin}>i�|vF#Q8"X_1 � -3c>8Ngz E>[n>+$uև,Q Yl)(%1Haq/khjgPee{{4jW9FH1()QJpW{$Ei X XctZQLv QC)Qtˮ \`%Cq<B(;% s]5쳖-Z" XTZ"#)JRS*FE6YD96J֗p%nQ(1D`@�$3`%B`;E/Db@ZDPJ5!s<CBtTfuQk;ӻ/BaY`vNM"Z {YܞUA{f':h3enܙdwoDRpZ=T?y>-F+}{:{wfl{|C]t{M^<}+^:'H"gu,YgY_"g�&MiO>D)8pճEH<>.pe |apdJe VHp- yY[[|T M^J1XaXJX? 6cm4$ęQ^cxfeCbMaF !|e1aIłzSciY#hXgqzZ,TClGqFwb}7#E*W5CJ b@X[*@H#}��tO~,o ʂY/5?vƍ?\%RKS6C7WvNƀ܆|P2`1O?ggk~C>)QeQ]׷H_�h%U#(k!bhᕹ&-&:jJ"pxmn91 q'HoAA,4QmQaAh"RiK,1C`P->-M.1TeDOPìZnѸFh, v+�ZZu%'Z7 "#N`8_vH!$`:[A+a@w `DRps+3?\€xt xFwS'U WV^lA޵Nj2}Q{~0,HHHHHHgzIH3iDƏ_iwY%*"q(@5Fbso_L:O 67e1VQ\RA])̎f5z~\ fۃe&0FhD/Ya,V�ƂcMoKa/_Hr1h3x5Y܃ء7(OUYfL6%@dQѠ|WO}xET@AE .`E dM2d3g鮪}Ιdf2@3鮮~S90 @1إ(< CؐWMsHb3T#(DtQ("Lqy>fY@d4ʼnK9[ڒgB2ҔMIkʴ �;ܿm;7q}CӐ~||jt>k}dC5vvʠx<yqy^<W6 Rv5D6EGO9pS(cr{)8,:&OBVi9Et$eny;JB"Pn#nmFɯ 66GG#2j &oA 8̃= >f,9z K"{&OJpEۤ҂J9K\kԇ3b qiMDc5x,B9K:ilfLaX08�qDcFgc 1 bLWPsy%OkwnGQ09zSw>;ەa`y<x^dkF-Gj@FG|[bBj2E|֕u "RvwNvJ9jkhnp6F $6 � �eє}eE9) wY 10PYKjJ{SCN?M׍1KXaBRDZ" 5&0"h qT2M(pQP[WGwBTLТPb9p"hYVISSP4֖)R_QqA&�$@}3| \>Eӹ\`EerApHԈ!<)Mɓj gGO5ŜԄ ox<xwY_m(Gǖ.G|lͭ Wo wn)!2yJuۅr(t$ȴ4v%<'I\ (Ff .L2Z8yM5QHށ7HETٸU6HZ05 qd�R*d]@�/iP{HLzoE,fq UN<\^c NSӤP3Hc `F1uFd tfR+b`Mc령>.!NJ `bE)V䋆ܠ%7X;0P[{�o~l| 8zfR6<u\:ZW};ffLJ#R~ϟ|$j$(v[&.}/vZM1.\21<i7x<aF җ>2;.;G>1WEKS1D}EO,_}kUѱʛ&SIM:m/u zAM)J{҃V! (J L2l]RX$an�)aCKrj$!jq$F DA5D'K6JA}FOߢJG) =hK j�HBz6�� �IDATy qS-RKU�"PsTU9rQ B!dC("T2D:i�cT)qndi4o~2,`3{:┷~6ϹW?MI?7]vY6M<-O8xb@j-Qq:_|$V(RQ\=x<&β߂w /vrh@Ri2~y-n/o]p>7tV\^aWq7J$@sDMvM~DEXXG (6Xc!͓'QE"*,8D)(p kEƂ"ILPI\\48jT"Hl *Bդ~RΧ`1&q-ʂa[S)=T9HX"jLIc\䈝Xt Ū^ p8PPN% J @)A4# Q$8y&BK65K0Vў9@ umakޖ,]7,�xӴ7WtJd[[%~Q,L㽟G]q"nr<x<⑭}yɧ~Qp=PC/O~Puifr;S|(7փີv<.�!5CQ0A!lP@ XR2a�9L`P9:A)& `r"p�ky 2-"WPCb Vw:&ޚapmL6ݐ9,$Gkq5y\mr?юJ̜[CuayLbURp1g ӔZ FE1oQ816PR; UgƉ좒|*PhJhPV*8FbSh43!kkL}A]  b7r?a}\'k#̇HӾd5N0K=\;V%x<xv's6g}/GWN(ѪF(C^giLcZ!r7Tn:ee8z^m4 W0&GR3 &CM\E@Yl`Q*!N45 ̘20H v6{b趕UMȟJ`rDI[R9%TFd�3?EHD' ✆ȑ/DD˄y Ej�)(>^wx68I<B.cf8ᵆa=Qq1JB0߱v>!g(<ȣW?q_OM@ӿ᛿YJ4x,La-C\x<񼸤Siկz~bTJMU"͇S>Kt,W] [OC}#M 7u46գx̞'Nl Yr8:U7Z"\kjFDi14}31}*)ָŞk pA`]%@b(o'P& #p0JAX�H& IE$*oI[PVHH:'Lpr-XKl[@&<2dQG_E\k}"3?бȒ_6ifLzvh,E2l;?Z8hDLntu<xȢ^N@VV榘# </;?_:!&2X 0ko~Mr?ą_.| j&՘̑oh'k�kk_ x< ;G.$EӬC9]gHs7U+ރ]$J[X fFSK\Y7RECp]MsK#`YLb%%U_('_R&jH WbFtΡä-Rtl\6P$[I~ %M☨hj a@pb'c3`(mhTlg ~i1Yw+XhPmRl9(C}}@T5 TrJ5k|P㾘C)x>AbK9ٯX1*0WDzϞ9[ >S\oO?wwbR)"VBP J}޶™_:74l*/Z'O~լ,$@zܮx<x&<9]G'8| ν G= iz4B<v7'B #1aJ /k<aJ,}5IН9x4׀8Wt ]܈*Xx�HvPA5%KbP@u11b($IR%Qke!G" N Gİ ΁tskia *GO#˵;~7KMD&@PhibQ(ib))(ZXR!88bLl7=bJPl>|6_S~pg]I)`>t9f|g1HNjQL'lb!p9jg[Gk+힤+x<ώ:ޣ>IIߣsH ׳!͛BMdRk8dj wvv(:Fo%/Z%E+q岃s԰ɤ ځ.no B TpsRP= Di8"" a!K<M~p9E+(#IE_[�@) %t}-*Pc!.9\9aּv~@wE Nʑ -ALJIC]PqduوژژzK:c�Y{<?ոr Feϋ@׼m\s#W=֋Ua5h=,ѽnk2׿k/W}Q3@L^_6 Pg?6qc[yIvfi>x<4ri'6bcwLfA}og%ܶހCr?ɿn74𮏽}:)Lw<zK\Pq”D r?Aek42uJ a`m +'3rXB+0/OHh^TI C2)Ig*[9pC�bKk:Io \RVPʹbn)Tlh IĔZ"넺LL]ML:+ӚTB+K"Eh,Z6czrBNQAO رdzrļ }h؉~s.ZGNFش.~YUb~Iśxax< 0JgGGzQt;R`{ؼ^?ɻ-L%}6ELh6XRHJ(8XtqvAEp%xfa4NJJ[9:(I5�W+ueÀC;ቁgĿbHJ%KC5_`*1H(X(v[t!bZP,bhEdAIyimC$ȣ\&T"r1A80 A% Bo1dpbO3+b-1,&RXȖ&JA 준z3Dzrrn>gb<Z~˯_qZCcmZx<g,~n7�6q%gs3ݯk_C^3Xȥ PZiRS,b(pfR(s!+h2SUj2z>RB$ TJFxT[ s/,/w -(87 U86MMtפD {i(.oc(ɐ[)I:ucXtw@w&)#P k LBE!J%RX(˞I`Z(rm6?fpWpJ [aYN8{0x<H :qPJ{@Akd pHY񆲢^і/eJc ʵr'q# 8M<* Ǯdnp`B*m%@?@T@E,v[?rȤ,Y}b45u]ڐB2Xj @)).@$N"L"C ihh2Xg*$ Xs$IRIaHC6G;8!Vğ;N53Zw I\,䀡ئu;L *nP38,'`I$ /ʹʂx<e߯+$pYl$.ٻe ΜfN(ۅC%X0Q+$%B$ 6)-@\ }0. {; > Z6D[pKQD%U,ͯwtkM hu.ɩ";b55I%f 0 qCV'!Ё%] 'FHȍT2W~,'\E[̫R{c;?iC<nݞ&&ciW>Sk[ of3h.72Yx<W6]LRns|+OB\ )nnNvU @*K9gpŀ0L59gEu("T;b&8rM\)k+X,HQ ]y,v0A K4"uܾ5B94Ha(".{L2(lƜv\ :]B($0S Ɇ]!!~Qp&Y6tX},"RPYsdQ0#5/ w %x*0s֍_|6''<<Y-,h'teժ̛7OȽϲeX~xlbXkqy|d/sS4[jw"8(šVг5Ų ,ŔFK9) @)\P(ߺRQ .TIA mEnbb %\ &^J%^6 O.Zx%BsF&Kz dgH0DH~ K9)!$ S$KlbZG١NfH 8 `B&eqFa!NaaSU- (kMqȾTyҢD!a\H_zMѕsk<^aV665n.;[=th.2-tcUetv9}wdYNh z$/+F0.ܨ0caѩ#[mS,h7rqgzw 4@.G]mmW^koS4?f+량չ|z y 1Y4NǗ(6Z6 sĢ"G:Ac[βT3z$64$IR0 @PDʢcِb`i%5Mc ٪`NɐIeBzV$&H9GQY Pb - [R0"dlVD1ؑEP'pHBQSP\0$:.81Z Igr ,b JibxruHɖ&I, NN=6vv1` DY Àխ!_%Je@%DFTStm#ݪXQձkˆ &}Q}U(KYda$Ƌa|ib$JGwkֿݽ;ߣ"p޽[Nwn;Q;{[lRMUclM\Cv9 K}竍1ßm3fZ1rۊw6*VFce~χU^ ɻ,'fm#pu߱sŞ敺s}|~}or w-߿wq.%?}KNWZMgg׸+e˗"`qLUV6˝{nnyDo�ʗ%}gV`LПfVna4Oo7OStTAB㨟g/婧Vо|3|9JU~xN`&}X&ERZ?c4& ʓ9,DDKWk,m)to M)LYP-%iEI##IBep®)oĕ;4qP|&&Иo(ɏ�\9*&X9+8J%ÿ%!?F}3}e;G=o:;B}}L&�q1 {zs TbCP w"^gGvPe[4Ôe/g8nRDN8z/ؠSk�Pguzxy돝;z )036U$^dh+ Ön`ooLd_:(ɑRݨ+|m~&H\JV驤ߥ G9lMqwbR�3Ӊck)ZǪp6ŲA.[m%FڂpWP Eh-$p`fԠ'rܲ}hn~YsLcQdn hחj:#x|@qdc7hO#HӉQBK8v], t~ƿ>veta>QppBCKkg}W3+BP8`[q¨PYOg4opefvުaZ .ި9g55@UYkIHO6++[J`pOorlv|Mol!Y+\Es[Vz 5`ZJƢGv5zkOlt<'J?KGeWk__FI[39?׌}3glB�:::9mn[t;-X9KE\~啬\\.i �pۢg>#ҧYr%tP^x!?05Yr㍤i. ~zaN>Q<oqڂ<SL> Hy466J=9\T*ŭ k-W__̡JjjZZZxlbf̘M7o&ZZZ~Ʊ7@scw}7.~}1oߪ<{J6ʫҾ#8|8[j5޶.o::-[S =YT%EѸcw}7Ϭ^ͱ3u;E-X7=SxʸOuGfϚ]=ӗOw:<S[gVmr7nړ8m4DL퉙saƾ=HGm1}VTyu P7I6Ò%||)W.KYЃljgn$(qO/tktQOLă: (0IQshɔεCߒ{2x84ĺi0�UWRRl[E]R_+=w {k [ ]c,X,β('l 19KJtn-AM_/d`@HY9!7(ttth4}B6mu<ǿh6owXe?mz>!9Z+kQ<ub뗶ͽc]om|` i\n}Y?~wh'* "㪼e}1i$Vr+g2|ym@o gycvc5_i}9i8qo/\l�� �IDAT_2%;e,v vgn}kUU81S3zS k—xHM5yaM~ ݿo{p6ͭBl L^ء�aaw7j.gȒVݦ,j gj^[DqSyr$ jeg5L1<ڟ(�Z{+W[4p&͙{vڀg5'7ZBZ혝 E3L$Tk5aIN+%V~Цy;%yɳdWʑ3CqaڪϱL*\ש"44'՝$h$!:5'il2ʽ猰x`(pi򎶆ahMvMl|zz= -$s}馀/Su{Au6lj )Zw1#QNMWleDߙ;5d:Θd =PP(u;zbE9QhyW%r;$]ڦ{=T?~z:;;\Hǜ Fĸp^W\yըgYӪ\f#?0w~+V\|='Ѷ Xn=�&5կC3q.!b~[;G}.೟4Z+W|k9^�*N9$֯PD'XP=K9c&A*`̜1~ ӦNpX|?su|j <j"Yf_O+�{#ŏY ѯ}-??$|{>dSOq)_]&5Ob޼r9%2cL0,-ӦNk{7qqƻ^w4Ԑ-Q[[K>_`T/~;[j5[;:[?K!_^'//oy7o.˖{Mߩ\.G[f~z)APsֿ<Yu&mm7o.k[[xqg?i6ů/|c_w4̟O&aY;Qa1}K{u,y㟯go0:vJ":fpȓm%G*?fkR@BiАRa $JEP:b>Ә{5|wlV1=$.^J#HEY)d#*Eؒ*EQ }Bh3,Ul!FEmVG}vji&i&)RHJ3=QњR1 q:sd9Auώ ȵ' (Cl P"Y褜X[A$FiAЉgI?+\0aH WPoX,RY=d0_&uCVřm)+{n'c[]U9~)8Ʊbprv}P{2O1tDBo,,h?omv.$o()5*T QSRZYu7' lXQe7a"U1H <3Rn1gw�&1&1|}y!T7sռO _MWlHes ԦĘ&/v?n̯<:荓r+ux;ՎMT8Ӳ4dX;>Q¢v_e9]Ck|w3 :v(4[U vT:ƽC}}Y?3g̤ms.z K|v+[;vtABo{g띜sŜ}~1z"sE<!B0`괩y|˭K~q{Wo΃?<8f`Kwq5`kGӦNH5Yq4ֹߤn=tnʥ0ןp<'Of|Z=jj*,|\~ckSMck9H6murg=v=ֶ߾V?_g񍳿FSS#=0{.Ӟ>_;-tl0X# \ROL@*eLYu(q8*A48I(e� X" pJ% ]A IһSZ!Ve-VRh4"H�E16.t,J P#vCQϵEGXBa:6"P�k#bJd؃QJTTX@*FJr`@N (Rq?Oھ85jjqx^ hX(s҉юhp9gc&[5|| ~_g}e</q8or/?Ş ryre{w kΜ9_?1cƞw%O>EGH֤qǛf:uj~Ò'b9s{Wo *ƒ<c3yO|q`,ڲk mf }DQIn)'%JdoܖS 8 B8Aʆʕ N$y"D~[QB]yѠ 6v]*@ JJIwe ԉI8A*a?JlKJ9Y9 CDaq+P#:'VeC4njj;n+W&<<ly52ggOפq'G~k~IrDqu@)LaEଣjpPT .)5ʗJ$ ]bQf8H"ɹ by7ݹBJIj(+&HY1)IDP/;k& C+{PXcFd8Caι�I%I011"RdJ)*hQ8\'JQSW ;'ydbyh(7x&7x<x<8970{ޤR!ET*a&ު@3AXx<3+Vb]7=D(x<x<Gе}̺j Q2Vy<x<9<x<ys1ux<x<*qx<x<W98x<x<ϫox<x<U7x<x<*'xx<x<b}A׋s~s؅ssz\5!@__?˖/B@PX,b {x<Ν0 "(PJ!"BsS#tzFb^9k-9/X0&MiĸgL{x㴮[ԩS<y2MMMNRh=x<S^SN]cʻ|.ڨgݥc͚ kPVuf՝w9:?Dd|ρV?,o~󛩫# DD, 0x<x<=Lcc#v7򎾈ИJٳ뮻21_==tvu7qw@EIwnb1޸Z&8q@Dhm]@CC555{Lpx<x&ċlWx `ܹtvma뺺8p<RI/!`<FWgMcW+:`L:T*dx<x<g¸?At0s|@Ssе/|a\|8J9%^x<x<gO'Rqk̘*m*8 cHR>x<x^%\Jt։L眃p;D}N$J&$֒Jax<x<랼?,h{-cAEѸsDQҺ?K,kᬳbɴ`/y䑻 ;P׸a0܍ƁAm6:LW?^j6jOTOeqk^˞x<x</5 �,o{(v1RXkǔZKkk+g}63ڋ\.y-[Iu\sA{C SrGy9eP6Dy̬k&_W*&@g/<x<ÒL0Pa<tO;E8o4<ON{{;]]]O/] 9#`a{ ǂogK-BS6!7x<x<W4>Vn}K1,N~Հ#A{-bҥd9뮻/|C=)r9ַZaT*qwrܼKqr㷲9?Jü}3G5@O=E]:)J s nq|p @y [r˱4\v dógsS晁οo[(}vջY<U=XLK{||4>ȯ>nwɽ̍Owr9pB>\a. .ECɼ5óە&З`Ikle|cG]Ϭ<+\S8o}撚}߮yK},x%o x<x< cy lYNܷcNl{v†?q99餓ƺɄEk`Ƕ[6oЇ>gQ=w,\Eߎ2iҘ{W#}ښ {.֭#78{q0(.$-\\^˅Enn5&饔=�-KA43<h. !]3%*7CDp=L}CFWd]J{|kΜ>t徇䐊LdG{i _<dm;+9?9θw4hxx j9愻8f9<G{&ײmYxƽ}?X}\G/S|_)ju x<x?۷O93 TfwG<cN:$N:|'>_:9N){ 甓Of…߹BΝ;f{,o\.j ng}x[2!wXAy'T<BuoK�!xxMlr<ϬC;BޛGKvw_Ľ73Rj$E2 =2O۞91knL#a/�>xzt=n``ՖeX$T[3ވ73߫W I9Gzw7nD/`?:Njw]e[6 jُ??uR@ ?ǯ𹻿ʦu�Ňxi^6=˷} ;NS?\]^jJݯ|%漓KsomAlv?<?/d2L&dNWGCB'c5Ϳy 7�'\{po<XIh=so*Xo֋.8#?~zS mq>'XanHv~?y7]6ٱ''g;x:B‡V|wEs1p0ʎo':ַf z9ݯ/}{2;xW?~?ue? d2L&d^xp>xoyg`<9?gKM_}u]ꫯUM71 0& NĠS &?ciwynx{A~g~愧}}/H�ݻ֩Dh6K+]^{[QSW?Yy+}o>o-l<1]e /x<ϸ`+_VЖu¤Fyʧ> ktӿޣ{'SqF�(VΧӬ_&d2L&D~_+\ >r'7\euto9( \s)19pQΝ;yWӛooԧ>unf>Opu_YaΝ,}{o&wBa`z9~w\\9m!, Og~pgfǮgvS-/]1/'H+8e1]plc>M\iiw+yQܳn+M>7~eWXcl9~s[L&d2L&䧯W~cOmW?c>W]}U\wpi$h0y뮻뮻U宻|ⓟwϿ#t777os-p5ל00Y/6ŁbrΓUlNso}y߻s|z~ -BN|?S4V k~η[fXx殡 d/U|ko޾ơ 9i[_ _z?o6S}h^s5'/o/v~yA\qeoa9_&d2L&y|*tw*2|ȁpwplΝ;ٿ?;W=zoJ=|$@Qav;ywoᢋvS _>׾x~aK.aUۇ]| e-rU%ȉ獜+,V:/l2 T΂_Ǽ~Ư;_Vn^޸&@K=@8Orc^Z+>ogm \Ӌ`e_yo7G:/k;d2L&d2_i€?rWS>!AC eR$nBºFp^ɖ-[_%�sa>` @揭+)L|gvv R?K6e6d2L&dC|k_K.=c1c׾)}{n◸7N +ojOz]ל<?E<ȿ][(=:~u, d2L&d2so'Eן c 9)_Er=c-*Nܺ=9ts|;_b;?>N,d2L&d2s3kT79} ñ( 꺦霶8pnXS/N"t:>5磯9d2L&d2̳ř1%-Zk-9ә(8'ZIhꆙ:vd2L&d2L& hE<tsrq`Ӧ9:*;)zuq۹;K*;fL&d2L&yA#rB<D@2s=\ysscؾm8=$9 "8U:IZA`-޽o۷m66l؀c &L&d2L&9*Ea1 [;ƁطovbM'{ENÞ=];wm66E11XcxDk]luW+p8r aǜzd2L&d2ˣ>_nsss޵]v2==8ExYZZo~%++}YOTMss޽;wIŁ׉L&d2L&9G,/-= ##։L?YNV0IyւL&d2L&<_(\8sęL&d2L&dU8$i�� �IDATd2L&d2 ,d2L&d2L&'L&d2L&ɼ@&d2L&d2/py.C&d2L&d2sw 3L&d2L&ɜq=GF rZA&d2L&d2/$&ԣYd2L&d2LN2L&d2L&yŁL&d2L&d^dq d2L&d28Ź.@&d _kXv58)izMO>d2LyM2LO['ټaݗ8'±{?/u2L&yޒŁL&yxqO]a�.V&sJ{]f7nћ>ޗo:d2LyIve2:&  qL8W;Ed2LyK2LyS%!s]LCUi?t.I&d2[8d2s5̷*ard2,d2 Jyn9%d23J^0d^0d \Fu2L&y^ŁL&ys d2L&sFyVā[no{w`l2YnK_R~7 gܹg粝HO6ܿ(c%U;癳Ed^vyvyW;+RyOzK-S�"/(Y Z"�<AUx @T)""ѵ`!x`@Ճz*Fc,8 x*XA4 S BIA1*)PTQ1XkfeyZP- :MAah ohbeA cA@] BzAChxAVJ1h x7L =u=|AEQXBxJz"KXXǹ_җzMٟY^;J0ۤiYXjWSUU@Qh!VW@(pΡ!0 FRZDMӠ#SG4^g0&>s!"!1WLl#[XTB=X\o3"eAA|v:nzתGCϭBI*Ҷ_[V YpǶU9)+Ea A1ƀz| ƴzkFۋBH."(}߼[o"]v)سS <[k@& k眛AQ,I9WoD;EcLz8k8cpέ:~eYbv-Lgž ^&eձm'^;5_딞5ǝkgc OOC[yqOk7r2p+?ɕW2SS]@0R`Lo A6`T,ImYVl qJ'p& !�FヤsUpVϩcR߶uB,c'9q2G?۬AB�g QQk xOFmϵ`9kH5꿝s I}w<g3j[>@ܪۖSAŀ-Ab0*#:Z Is?c�(+~G?_2+w? _ % ,6 Mew6yf甅S~k.ټ7<thK-w" `W: Yr N�n`XZ(_xj^P5lz6M;.en!*Y0B5ѧ Q:3S(b@axT3Ͻo} f[fݞJ}@uZ(B _82 W3Ba+¼J`S^q>;V(7Lh_4 Bh \#ҰT5#1ckHkB- zK0%KMt)Kl)xL ZV`:-ng)B="`*hl*,_;57_9+<ā[n{\f8l0XO Q  !!xTSX,xmr*`R''. w4 η$'T q\#hACN%hD<+>Dzl2i ǒ:N,!uCsQ\@ Gu�@%t]A|qabՃ7P`|,\:Xc h xL(]I hX_AŌ&2!]`#'јTP i {fG & ǔť /|׿Ϥ[n{ bL4plas u[Wơ>`$d<)4Py FP z'ָ#"M1?avnY5Bފo݌'A]I z8h�q q[FF2ѠWsj$7€P06|bY"=I}I|گiWD1ڱiy7n�*޷ߥ1H _O$0J+z8XZZ/ <"8T[jr>iO~F~m7i5[)m11lFj#D Ij@퉄? ݱp/bo{}@&ڮ=Z!E3٬"&˼k8g-ɶxmy壞l:r |V\ƙLk6ǩ!QQ%kFN;"!�јnIn$΅b2IeĤAk Ҋ1f$!XVLt7Txo'Nq'IR_4MoQĺ~[$AU8qjRk6Co~M{QX@U\J;ƴϲ*PE16BcSYxDLOOsW\/x^{V-_~9 u30JLwj2u%֔6@Fq5 k?0,ׄ +c+0Н je,p +`TGՅj^^@D@,/ cf4 %V Xe",Πѯgk᙮<nCStf>EŽ줳/ b3X2 p  |6x|gSl0rӂQꃎQ !xs 1.EEUN6RFa@'CBpB3| x_|^bNʲ(:*R)W'~Va Rt3f( @/TyÎüb< ^y-33nFVgpe;9$0ppHG1 Nz0T[ MFcX4(:rIFe48 @M2H*zEҀB2>M^T!|$;$8zj=iQ1  I -hX,*5Jx `ښխ!D|Y &N={ࠑ%!n�eja% 0O a5aKJ *ֆ1j @At:5llQ@;=0$D@WAc4=$QB48q Z\o<ύ7knlt:%=lQ""ÚJFn hcls4xhj&1b CXfi=kdMv;( D1'CTܵ5PRDCQ}*'.A-Bݸ$`szpΏ"sqKMadܵ@aC 1iő.hl[2Q .h=I 6!MF�V QTl'Hb0%M'9?pV>psE1>hO׵mIDkt( {G=-sgD6]]~oFV{v6YޓyOkr; _]:d&Y]I`2"~^{=cm;9xd7x#sٙ(hDB 61 1Um\ȌB_⼢Dq Lc }}|=?E2,8~VmMhi"A X<X2͝@q Z:H35M,_XIk0k2љ-6fRT`Ѿbƒ$Ǒt޸/;4 Dڊ>}ˉwXTLj !Xck-Y4♞?gmrޑGVavtzl{\p\ñ|N0/#CJ,|?^>j7T6FBt�zI γi{n/ЙjnG ,׽`~EyKwɲ{8M)u /{ OpT@35,͡e|ԁ1J) b0XC냔F.4!/0?,0(! [z r)=CJB=�mc@*Н)cP)4Q\S's(:h N#cx|<(UOƈJ i>-@"*S-cTRQ̱hC)xŏv93<#qQK>S ]O\?\PvEE 6'9V0Xa[1!vO*qi(;m@errtQԀAM0L2ON MlZRB )V 2,qxX5Hᵦ�u꣊Ƣ ),^$(U!"-%%․ϒ &^K UKF / Cfi C:Vpjf;]+ h{g00 Ou^~Ȳp2;ϙY>fX=!c4WzťaGj yk>$9Zc'ͣbH|ؑediv & q=z{4G\"I{꺉zױ}`p\1jۦI{m2J@톣{RXthF: OA(CSGXZj C4FZ n=IlĤ�IOJ 來xB (bƇ61#yxZ1�0jOƤcIoO' CIנhzXM,(G<YQDQ̈7$yɣҦ؄W#(X&40?|Vˁ~wq'ɪ['0WMXk\dmى<>Zm$2Z&EQF->] Ec<h9 A!7OҖ?*qvE@5{1>:a$(~"wu/D~I%MGTr4o! FC'.ڥn{nhH_zFL LLDsmTG{NܻTn%ЊWxL3R)[>6zi9=^bmJjä[MBik8aZ!%Lj<JN0mEgyRHlYћept s=fglc&9 #v6/GA+.w?'j w[cq�:<Vt ^SA1U`rB_ڀX%&J"E%Qo|:̴gjc<WgLL (>D94l|`ÆcK6J)@V=kRu@ ^4|Stc*M_m(U7:!q4^8mF)ӰeU:(*Pt} n<cVJՅ/zhe1h ZŀFD1 Fs"8JSHWl63Bl@xFMbg$ 'EH⅀Q2wQWGv�>̙~?`MIoirEHכb刧,: e'lop[‘@g:wUB2<c[@kGv"bB,Kj d�FH04_`sc6f-lyQ;+, ,Pl:[JY%L;(;c1 ڤ9QJu)&D%P WkvF*Ę"Eaj2xO g Kwa!9T 1ճi.NzݳKcf�o,;.kPsXEFMD$M5M<Z(1@ֈo YdhC=Ҋ}. 7Jc^3i§CZc8PZ[b8i0bbԊZ<eTVM\S1) %SQĴ )BFc!a<A$H^4( Dy佳6] 4MMxX3 06ې:&R"bʐ$D)v<Q U,"o Q�h x!؂CcSR`4Fy)>yJz0hh8MSH`i#Mń(c)I:2L{,P~u.ڜֈoCgBS$#jOd^3i%Fbb+ T9n<" ƌ )QV5bP8nD?an.%{>Uwэ4đ <ȷ8Q J#}hRLv(虱8p;>d$qRXph6<C>Shiz Q,TiT&&ļqCR`9Q_1IC(ؘ.$A80E1H];եPբ�ȡΤѦ�"Fcu(}<LLi@QI)6k¨HIIÄ1{F&׻NLԎxb|GKLyǹonf.`_ҧi֖qݜسk'K_NWz-7wt4r.傝zLMMqlٲmW/ŊO3%.T[-{N.,b@%ح?t%aa&[=& +XX`B|zq)E^nMr,<RNI0<`"@((@(3="1>4 HiRA}Eg`*F-ƺ.0e4ͱƀH*BS(njY\d& !S+*)uY| It5Fu4hg| }M!BSۘ"}DG') )6:&c4NQYi33^PS(Ն(Pn.pu bY@}$`b$Q6#1oNFHXxԎ(7҆ ǣE"7Ň UQa.[ Ԭ- nM-a|jUCeJ˒⌋æ:`1=^=^';ōXwJ܋T3 'jޢGz=e!,=qØt<mw)T3lc}M..ǘ�b1&f&jߗ&<iqQ Eha|{ )"U+G.9q*GiНŞً1<aEEGÄbw{^"F-TX_P$gQ5%jNԦȀIʴB4^5Dĉ1QMFnGAx<jጤ,4zi0 1tR4C)c*Zdr"!;^А&t4{Z׶QO1@je o?EqcGŃgzyCVby- Cx8'GW(ΉƠ?h  >G%qkFv'Al֌ED4.DR,pgWiZcڸfYM�� �IDAT`Zk<ߵB+ 5GqH0FG~D`ɉmڽFF|@ry^_wSݚٽE,9[pafRt|Gģ֤ _z�'bmĉ" &mISqBz~zĴh~Fx> mwC s9p�XkXxWoXGktx# VøP-W՘QAL@aJ^WESmdF]ta?Ms0r01 ,jƃ2Z1d[ DHAL174NF�q mEX:!~O~<~z.< :,/M +\?Vnm?ɆYuCt:Ry'(n2?={vs^|s*F8㷈9mXJe$.9wL z"{k#¶'N ߸lG1+,leMNt4WFpagQ(+W@8m*?(,QJX-3 (>M pI^wiAR1P) C3 Pk@(MtU7 ,XEFP(Q `fr6HJ<ӯkCpC7?4-0w=L�c'QuR)کm 0Z5fら!L7Fe\\1>jBh1C^Mcѵb`3F^p5c):ߣ(AkG(eMb1)‚ca9є{I [5=xꨣ?Ms;a/j%aW<>nr@=XFak@+0\4B!ˇQ^ZQj0bhi覩JZh+.k(*|qAQnEq t6 ΅0ZekVеn2-"5Ab񩚰0Shj?=K`BC M6V=vZ6*޵<Uj ķHhi,KCvgzO32rlg[^OB`B>6@){tIH>~10Z #*4&88j5Qi'x7qaLJQd4o--KfQkD.NN)z+x 1"ݤaLz $o2Jǵ T#k7)uo�ӽH-9!s/#e b ^a') vxc(|GBW赒VPm'Ј!.Q0ₔS!G .j1ec0"f3Ikԭ睎^ֱ9ʃNBwIk,D=djjaAV4Lv"oɌQd:?NxSA4=3?j^Ks+./>믺l{p˧q}=e9Mv]orQµ]k�3F=וּt;ݸ@5 9>ֿ?4RaX|6XOuR6(v &-=tHPUqT5- 2f%ubMx ۊp(NUbڨ[FAѦ=!-Xm8M,yB1l#FS*DRT(+CMFR[0i?{idc@C<FzKH ҴR EGyCLL133űcG04Bk6ocnn__ۭ5vmAm NJke' NwnL}}Ao*&E~I\ԜUB 4.^ 2ZQz6(MJٛ{77&-X:cZ6^@zBсz0xӬ!ѣ=@`<г%/4AylY(0LM)slϒ(d^8w�M >CaPd2gfQY^P u# t ̖Q()b&ԁzѱl56НrYlJW'�e&F!mhzh!.9U#PZTPzh)J16D H(%Gi�DѴIX#El ԂG0ާŻ,<y‷޳ m:=ZbXl0MA}P&,,QEi)CM;H [{h2( 8Ťr'4[Ja@)S(qBZjaX@C(4>LK]} 0a{60ډ5dboFz}(LXB N54 euP.n †`EMņ~npK%vazK|‹g (P�^RƶDP%v89 cq@ڨ&%ˋwQ}%bKP 4U" o+LqxK1Wm,ԇTCa_bj^,~b!F�$wH?I2qLڼ6 kL̓HZ@J"S|`hV^2GV!,4TB3ubCyn2jPC|7\Bm|$b$/+`Ӣ*1.@ :?axy/bL!uen& }T] URpnPaUbzFi'J1ѱ ֘j=j&Aɚx;$mS7[7>󱝜%F @6ľm17~ҀoE3^1"шVhɳڋ}"wR8<HGbbHV1ҍqf#?m]?`RJ}lG>ro>^u\׳sm^®;f8 t,<ƌ=Fm0^Wakt'6FӢ}Zcu?4rgS!CILeU`ЯgY.B:n|^!µHJbTqRh^1<[ЮpZ D``&t %W~[RWG'~YkGFߔug&>Q9l "<h߼S2ӘqgDb b\c""zJ۷6Ka3 Kɥ咋bLg|8A /O<7yne+.[Qi0Fپm;oMqRB Zr}W*ROQtL>E٣$/h+~A}_!;mV S Ikm3JYZ-b-/fJ/fx \F])-0׻d`&Wf- *7<lxqu C݇AQBEWѿQr)eSٴXt aFd c(#70XLlj(j^sHPݨi`JR`Yi! ^J4歉o0$:te4ݸ 95R?L"(hذRT8#"\qM6]5+Et}@^RoQQ5ė>f<cqtpavS_ 7XZ0Rb Q{K:{c6cCC]XLD1':ʭo,(�PS:5UJA? f z*V]\!4j ~`4̇>Ů@yAT�I*KJ%E/`MVE%PNX rA:8 l@p[</=$ 7C8 }ⱘkY(t20@("̈g%I+'_Zo&DbIU^}$qmvEMz!*CjjS @wiŖDX<t z[,ֲ:VDss̚GVIՔj! jdlO~v- 2Փ-Q%7 DR,5YYy3)"bsOfU LX�({=g#׿LH/ diئ ijpz*:ߠvA�^E[uHlǴoоUiw6'{[!4tD^h2S[N1Eh( DlavW9Ksߒʟ|�G|@s9f1]wN`J?p8 hh _tdf 5#hy{LJ 8$C} mܻXIm0k:)#f-*b0Æ"=pzɲ ]7I{1&Q7z·DeHhC\Cnbz+�4*}򁤨gg<ga5j3.loKK|ցXu<9n/ȯL9?.{eh'H{s{:=m0@A0G38 Ǖ<Hrk}9IEUO_DA1=]JK;f8FxѓlF\!.cSdyŢm:.^yF} ן>L_n^{~?0.=O{StUӍS?u 1i8XJ4-YM0Ц#YTٜ0;\8ϲu"LF=w&C]:g~'r+||O=Å aZQ P~o;W>_Ο=4,u=c:+_3/Oq.Gw;13v{Eο?/ҿ\_tGcu+,"d²yq'"W".dSI &. &bvGd 5vAK":`#8QJ5.\ |x/h 9H<!,H{3(PL!)E4m#Gj.m 朑[{ؗ`2\r\{ϙJbHmfd&& 1!+B UC^*n[¸f *MK'!i, I1[~}=8JgJ"{6h{$V&d)P u+않@]cH[B{#t/�t%xE$$G!Y M$�ykw|@]БK%f5j(`v|'!7& 3Cu30^Z}oN` ccrjn#j5TP>%O2T ց;#e  v ь (- 2b*6!5 1xM["U/a'Ft:8 !OK;nP^ x")N_`3u QjAr:R2 -*2E>b{R %2 ['*҉ w}$R DV'$iPL%)G1ga ~ }Xptޡ"g#]abB;ۀLrto]Nj}ߪ'Ym&>Y0?u7$ 6ÿ~F|C:AxE:K#ҥ |~q;[/^EdD}oVh0eA5yn-1*^bh EF3,F4ύડZqϑ1R<0)6s3To1~)KDuꃼ5L{{~L]|IULXNJcnŁNӃHE \`[8'|힪}Ud2Ite,KBkMUw-!͡ VA@�Cҷu͂k9ݦ{j/<z'+G.״U6'.l"y3O~-s]?@їZ$jpٸ{y=Y{ ٕuo=^~‡ 99=y):;>&&X M`92D xm)~'[+_7?շJmic!t3fvrȱ{y=uzHFBJ4WXb(D )@]VUMZgs8=Eٜc]6mMhf Jx `4C tW#;y'җȧ?Iz5^x/_ <'_Uē3OS75tg?JYNq /p|z6ּGwyg}6#~ 3 `x,{pmb&aD|Tƙˑk#ŁR nKMhUUB &JyuucBD3n%b}15hE !mAgJ@ۦ$vbSWX`%px渰%ϡ8|GR-댺wqb'tyLFBUԬ�ִh%%͔d>RJnPAuG +;{gd_MIlg^z: olT!\l,u)4iXRBo@�g;wHϥ%zzw o;2^ zA>Wg|@JG<2wA]Kwڀ-m9[%Pq!xHE7LJTTF@DO˹lJn^1RѠgFbh]Bό  ĕIMIN@d~բh ?c ұ|ے;p >*h Vј̰jv=r#\8-ړ}CY,:GyAg1{q[s-?-I4BAzvEt.#|jiK'^ruk($e0r+&0U:ejScaj:J#ToD3K7:Mh|ĻUC-٨$rܮɨ~d YMXFxhL;}L &z? -9BÃh?F$i]D:EE;OPa4&u}gQ+ľPې@4bjfo"#SHzzHLL>9,"kU,JPj`T ^_RwS뻔Oc;eK tɨԀ1sւ6>i% q؝)_p b�roI D5M@:I�q1J8,wCN?/fO<:=9b#"mv, +7'0IEJ8Mt^b]>T śN{k+Ɠ ږ4#ק|7y3$6`ꈬ<rud/.rmóBP$=`hY}d}V`̰g{7[B~'="I@\x`Π1_qp~\ޯ8h|G2;>cR\%׿Ko޸?:J ǞʯYû70E/_~쏿ſ`rvHc\QKNg(nb[^TE$�&W%B ='Ws]!=-^, d:Ck$-z$,Wm3Ŋl=\ONj6+{m�cTF'Ljm)O{OXB/r"rx"l1ſ\NӮ(ʂ G1V2Cf-𫿄1)Ѷ гIDXU+$Dq.u<Ou[..]C5O"Ĺ@i@Fi]JF�� �IDAT�/*ŶPl%a>р."3eX+QE_ATQ 1dS(!*L 1A\9-d:(H,QMB܀vʼnak0SIH/LLA[�6,8vX%˅1,Bx۰L 8S%4PF%@d`֛*y,3B]QV&$MucXkFјoFdMn,%;Hh^ZmAI(u)ӷ%+~;=ƺo!SmB&1J'&qP]wt+4w[قCS-; 1#|8{a0FtEPMR]Oz,`u͊ʰiHBro<5PaJOLO&3D̕(xAȈ KG t?twĈ tE `c_ُgtn/vȲ*XR@ ab>\3; ]ހ,S&6>e0]-hQVd#渻 #`&.Hܱe,2ǖ-dD B*X}!ZNY̸VT! gbXBZt0cămk@}JfYKy|!du) Ҽ}B~qք̈jjozҥ1*1*Ck & WH"#-H9ƠW^NH:W )ُ=4IJ̔0{|\5;Rb5 ǔ$uٱ{:c3m4w:0859)`R@ɫWn2uWg†iO+:?0P;,8@dF��{pF xs:XUk9gc\V`;Ok=s_^$14dx_=J9݂BȽеf‡ ,6AcP765(k=AbDww0ZP7?OP).+7y>= rnJ'M#YjL>׉=kG6ֆg D[c*.6:O}mf.uqXk={~|�BN|%Nt =coq?߿$xB0޳5ɇ9 9ۇ3|3Ⲇꍛd+OgKL2">�T 2Ɠix `j$ӃČ4ZX�=U&7-&j$شh1!@eM<Ӝ ~g-: Ihp]M"1)mj/BIiK )rb٨OTC\ܳ߾>o.k]Z<Oۣn�(+0"}'1G''c?|sck2KTu{Gaj&k)E冿kv.M̖y `Baab WRB^*$ǡڙavl-=Ŗⶓ@ܻJ ['7$'SKhN:-0}%u B}ѱcf>%ȅAIrJ < &]D<) $ԡI^\߻RRtJ] vXd:m0Y*0Ⱥ~YC /Я&wa]jg.!U,H tk56|Y͡)g X)@y5,[@Vҷ3&H!37J1J~IQAXVb=́{DL `5q&%E XEІub(uFy?Tp6F@Ocz78"#,md-}bq&mt% [nIFN!:Msh[ZΠAO2Ns}p uzxEܱǞEZw'9 -4ᖘ|gm%{]J$>ZS^,u mK%lF"v2l�|ˣȁ(TgBVa,/�f(+&zV [P xX"Ă(Qbi2Bϵ|`cDrESv[|+p.d8@fDwHOW$& !Q"[SH[:O{cc8k�1`]J^G!^{W`"9dI o3yQD4S ̙au6c9(į1mDcFb.w.dž6fYSz*@=GLF,s佚l[v(ޭ=� 4wrw<7R[5`'9 0ɐAka6c4ୡ\!<ޯd++yH;6Q"{?k-5dtck >FRtJBh ۓ1_ʧ_xƛh4.;z!Ӊby /t.mWl{?V!SU͛4MfD%F Wg@bpr5?^o,M&=̏z`CPee4ff a|ofg^dt[3V5fYԃZ V''LYi+VSGl"W)B!bxk&}[P Fh<c`U|9d/X- <#;n$21ҥ,.B5B0H l^v̹0k』kl*j@g$.~u~8>ZR5m[3ik׮3Ck(˒ɋi8m:^}]׹s!ymlM߸r/^mB)ժ]V<3Ll|wA5@TS5Z/22UenS]8el3-ؖ}IS䓿L '2m HPl.- '' .T_@;L-&Sĩ2ʕG~R t+- $}u=jJ B@2Ju3vxSR\z &'U!z(ք‘ q:A3ň+³*A h %pPddYa 2., II&",->D-dF1$-,QOY@Vt[Q>XM2ҢzDzs mȜnuM#mX0]Zm-s;+몉 Px6Xl?AIRD'9ׄuzZI꣊dB-j"rP 0'۶G|мd pJx.:=\n(#!|P~?"yMLL! ؋ϖAA:\p;X Nq\6#v&s9:"_*>Hxx#u^SZI z#e~ÀG\ G| SrrJ.*N u312C23*2:-YtDŜ5B8]a<̆*ZO`JY &ʘʚhDNksbġEj|$TKȘʖQ1vw;BՑGOx+ ED l]ۧS(2a ;W\%˓}TS[mc_=kг~ѰB+B[BDgRU`( 6=xh t-ķJVQs)& =@>BC[I0$.I4XQL|_gmVر),V=0T!á?fcc G%Wi5xF7YCh4J�}<ϙSrmgW/ \`Nؾ6Sw'/zz=@3_;i:܂_Or%4*4_?y?8OZUr|Ţx=x5f~ŇNѱHX Vܯp藾O]ߣ%ь\1ٝ /P[oqytI@0?E<bPVk[+Wٻ.` kK&8TCSbtJQC;vrTsUģ3)q6Պn~FYH�g𴱡fkYLaFdUK&IkXfg x` F bMLEMuߦHJvS]�cXE(QY\oHYB&2~{)/N_^yyf N lxgxWb]+ $=/E̠`ƕ\@%ezA)JQ0>zH:?CˌMi_!w\9˿o Lr[ ~.m0%0IW!t* >&�]B;Wd!茾w8!T2+E%.7VۏA;)!dYؿmӹ* ](8S$_U b7֨Ę0 IOHؙ0.>@*Hja!7""DȁlnɏIbn%rb^8ETН$ ,n6p֌I, "&R$v^K%H_dB}k ٮ6e("yRh$ ` no?i38BEjDgЬZ# Q6u@ꛖx[ړ|tJm<1Eⲡ'}UD  vEuHdxu@KHNS{\߂e'#+kB(4dc% 1{f_KW 6AoU~2/4Z1EV.JdJO&QcT2mBkqlGZDYꑲFBAj^i6AZ"]I+ oEˮ(e,udF)DiR&{:'w#S/J&IM�XEYxݗ,E,VQuF#{' bgDv5Ȧwh^?Dt*}HĈ; ^zsP=]i1FnPOxF-;)ɬI5 -1`"-+$K�m`-.hZ<7_={m[$O#rb[ F_`COZ8Z#w&5(-Aqӗ=9+g}"@jRؒo;2"m(^8@ʉP܄qq@՜@^;~}ށckO$ Kb1ʱ;M(Vb^pL<1$mb{]c]|8ts7^'kzba(kfG m&p/w/=]&*M_/Ev<v5~h#[~sw)vђՁȪ8N Sb6 ?uw]#TB6<w φܬ{ǮL}-hG|[[!riz9rM僠y~/3Ma�uCI7gt|t(A D#GGGTՊ6Y,[F[RWKHfR.;LHg]seV..]ƎvyjG8pԋ%Fiafw S/n N1V5tu i+ 9%U೾5(D4`0Dְ͈5smkAXR4@މ5>}5y|TrMDlZ;bl@fOyۣjvi놣.!!Ҷ!ls6;ZU{Tu*tDK_h5+wrr׿qh2N":aW/9c�1?$T:[e؆lKD3¢)9tS �!/|)n B[>*¢S%D\ aEv)%MoS?tU14U } Ϡ>X B'xS),NXԖٙpp$7gw;OzERm]&|г?@bH2z1FHUu)"d]*@a5)Cm͜(YbTǀGs5'.Bvy=ӍФkbLL‘$; $ ,ӵW$u$AT(@9( 0> 7_د|5zWQRDXӫK1WG4/+NI~=ǟUo{8Ȩ`$Wi=LXd^XC  $Uw-Kfgb:q dFSh?Qr};$;Lٜ f@Jas[=˖Ӟ񻬎 P<{uGx &Pv`<5kڝJtFALeJ%$ U%jR Jf\:D|H x+"d= �HJ{dIS,+!=Pt|D!5x A2Mxɷ&yY&]c*sװlӒU;)ѪCg ma1O?:1U& )Ɩ4Lz5vR\D -Bx<EA�A*T1bgy&mSCT zĶeۜ~WEC.RJ<bQ^`p׶0[VS:"smܦs#vǘONPѦdφ_ma)ѱc.vDQ#;.iNH=0~ol×MOM٧u{h&6(;Ɓ7@ZXqX;™<y_[l%eB}Ko_S ͊vM-k#yi3|U"l_6=>֠fia"xCzޞu]SQf_'GX̳mNn{@S?_{1,ƱXEzGh -.:&;ӌo4b)*j:+ے:r*~vOp㆙}f;owηoޭ[D[a$g(笂kJR"> en�qIX~vY Dz٦0�CAW {,Ogh<:A$Ҏr8YC^e`wć! ۋwsx?9x'~^ ~wj~B5W&,#MUoWuHm~)m$פ cXa0 .-M�e:ԗ遠A gu^I~wz HωeF!5UMF.kF#`.jt5'N>|MId`Wx`w#7n=<$ 7n`40ϙNw(1jb-a`&NI4)/&hĝt%Xޘ'HE(u–H?.IO]H"wӝDJK(أYiKBa~W񍡍9J ]3L4(Φ] <NbXynl[VJ l? R(3Gq}%-. Pj7Q�0;2| kT!>)է8?xwW**W%fn\{uͷoAua R pc4IX mb=PǦ^Q,ib6%6dRU+-ET):څW(wi\( )<)yёdN`Oh0[Zo1$Lx;Rn2 (+QM`�� �IDATu{zW\ݭ瀫Vgp!pgɭ@~N=[!cC8ȨdYU3"@.e$DD7l"r@:>w�AvBq`,+"4+ m-,41&*є3+ j<A焭;¶uMb*%bJ*n&$=ml\$H?1"=0d[P^Wt+]?Sr I.{Z <ڜbID5=VhC0XS.Q' ?_{ w$<InDX\=߁>8~i,dyL{!QN8>ÍK3(Vw{3<�gn =3`]aN-PFd=T7cOi^_N)!Nlj\ՒE#vUHvDT <"b1 ȯ1z�K qDm%ǎa*PQ( B�8[OF$uIHt0s<!)YXy 1Xc1&Hs#ȲcR))eEQd KLZd6XeGM(yBzqOk:҉`M!!X %�)qXiEHC(d8V9{T˜ɔ{O~EbZϏȒ,n+] K?ɛ3G&k2ʻrlؐ:2㰱`KX u4eRn"E`X ;J[ȳLX.Wpm*\.r(ό#Y3|goo3yq?|k $ʨ@U?"{az[5k[kiv=7? @{c~ 89ۓ=d]q}G+[>Ҝb}Jrɽg.\d%N\V.10mNɏqPհ;٢9<b^0.$&P8쳚Tof(K q=ϽJ6` Y'1j_Fb8!X;1Զ<5;mIײ@bbdL,er5+<]8DqT .umfloMy駹|27omj{d2<crtrB=|uUc#?[Řo4u˕W珿ڞpv{b\T9 `]dP^.\'xz)t<TO<DJǾ"n\b!QSlafUSnj:ZB+tRje>l^x޷$@("Nz̈-IB(Z}m<k-/̵_,ֲ}k|k{bM6gQ)ɴfِ802yA @ň"ۑ#[h EI$Q&nP5ݺu3aas& Y�.{~+Cui=?WI]%|p6l$I'U2z!)�{q$r;!d^oI` I1'!Pbou:.g'Hqq]<0WkDG4L'4k}r(zJ8( \IS vhR}24<o q.ٔe!) xz'r&&T3oJgZ@'%BBATE9sH0YEA##6#u&.t.d!JC.5dW !VHhlbh/9dd#vգSLޤl o.Un7X8%7 J:r5J19I)zば7> a#PTnGdL bdjy+6y#5u9:grY8L۔A4= ZFĜضi t۶dw R8q(@1ivӦ~XS=MumApYΩ f`9s)Ll!ȐV?/64ߨGf@FJT ?@G>=B}g/uKQtBze3 S,b KWή1}6y27 uM o<Up5(Q=41(WlEi]0ŵ%5/ln%Hc65qjZc@/XLMy"%8CmsbIg4͔R7%S?.fՄ:LZ3F?) M]o'! +80_{UPU=,=~ Tuq8 1^'sIÁ{|PW>_tW??{pO䍫\:3h ɍa ˧؟Lѕebt-TDLYm ;jS{Æ8* 25u\in++o\S_ίx{{gyӛ< 7wns/sgk�5d,^=e>}>D&@Бd#P5MYwhO𐥕:joW74vyMaB`ĥy|+UE=�!#ŋ/^'bCl|⧘}c厣Lvvmx=bs8'W.DXRaDNCӈQ%; "Uf(5yu9pq6BEg$"qg<t"Ϧ&V%!(Ǵپs`]Bz CN< 2*A#wwv8yy^op0y+,t{9_җ/|_16PKnsOD ɽ ;nBHSg&WJ3,}KM@?h"-e^,QI>{<B9ItGSWhߠђJY#1 6@PM@v:S@+h 1SlB>Pt؍f,>íkLKbTjUN9q]>z&T�y#`2UkT?suSKG,m3d} L8POsˢ#@&oJ,JZSUmS%,e tt5lN$@[bPl䃔r*x/4a:5N-ba+~)1+.T4Ú%߷kGc1&,Pj1d3G rĺlW =\-}lbry~8i=[H$;;Wt^޿Ls+5%[R,~S$HthqDB0,}4p?`Ό̧i v o' O&)BHEeFLi3Cf@J.g詀6D4&oT V5~NXZN|JrDq5h#&rXpKZ-`rŤIZWGsMqhϟT" ^J#;RssZvSӄLojb+N c~8!~$֑7)TujR3O0YʅOIUfڗ ղ]cc^KK6DX),Ch"ЎP\91囇)&9'Pp3pJ(#V鵫=Ǯf,u-~"/$U8h8T&FrZc%`DH/XI.F68 tT<ב"@ÈfV"YVz$k*cjcUhUE9+)gz1IbLTA[n=96tD(R@/V\^]o&;D.Zl6@/ ,ô .Ԑ -4s=",2wy橧>PЅo/??/ۇ4UNL\_d}!z&e)>Ҭ0<}n'ct\f8LNhXLٜ:ɔ63ܮg>rjW_sfJ/GM`gTέ`}}8ɟ4Ns^QK~\u''+şhڥ7r j):,L t2hk85kΘZju'I̬B`mc\(UlpdOyx@2ӁJF)6. iv016"߭;l-F>.K. ڨxl1f8h<?ry &ZOƣpT ;1ts)0*4&~!0$wxyT3<M[-|Bo=ZI*&1 oA즡Peaggg$d0XZ%+KUœ=ӧ81>ILɘ+|d/.]ĉK%t~={EնßwXǁ~BnHч`?ķߢW.h|ʆҔ:h;e6h7Pd(| k1"b; \VIb3R:@O@I}z[lfJx* @dȺ EM.5+=L>eF7^?< b]iV S?u'+i:} _؜bKSR?1j,+INНWKX45w#y~Է(6kCF hH�CLؠwH*13) .K^7e dG:Fp Yb3b1TļG6~$+op `XÖdFNVM:s\f@229NyGKK]PێpisuoK1XLRz&{Om!#xKCwg ۑl2=cQXK ^\ u`.p! m&T񜈀cXz؋(F94*[L{ma7[w^ZcB& R5-ۯVb)kؤ6%5|V(kT<Q"`@pW(DJ|យ%PIӴ 41Q!FK,J -jQ'jx 5Qzwn D[-.%Al'I-@&ǎ>@8+T%<A?nFѱujML؝nɅ: ĮM4#Ȳ`\ޙA73O m<{[$- Vp>7㫤>cllt4u Y ~(jؖ10zo9 O.H{.fMUB/�H]1aQ "-rX+=qQ1UshS^iwl; Js,ˏrj ܜ]U~,Kk `C,)0SRpDAn0`=Z 1x<Ɍk &_˯Uά$FN"O__!x<5N04|gTL= /:aIobbS]zg6/Y`psBTYt_2ܠ᭽)[C~.qqE' 9|W9<Uzgy�GFD/$XD90L~�d]E[@wF&p"E`T=Ź{>rmbA1aeekfXX 3mX6Ħ!VWx u]$7OvwPn3?"NijOBSMi6s"zើ)d&(�mUSBQSzNQYG Uj1!o|ztKlǡft4.#MMaT3k}iL<9*J')4 YQUݝ}N:AsMu;w`@UT6U5_e6䌆lb]feEWri =Z371kbm Ch$p?A)pzqN1.I_KDQb%̝dl^%A_O5b*%G$j BTzaAp:KJ/4Klj qbD).IA~*؃HE UE:|d@OD;_ Iˤ[$7B:x¹+N_O/D\3LNDl:`spYOmkt=bb߶F:J"<O=k% E T= |2 2xnNYr);i \ dB,SlW8 (B3 eh\jf4P<!ԷsʷX;UV\ckKm1Gs| hD("ٚmhMm)N]+7O4D%[uvW1PN@ML*4D{lE\yP̂!a{'JCT 3ezv4;�:╦r8Qxm8ӂIPz?G01\+ʀuƵTK<Љmϖi=Fiܯ@2ɋ c*! ̌l }X9_Y1lՄqCqd9FFt"FB, 6Q;xH2/^4Pt׼y /  6u^ױ?C,ȆqdgWiR/1ۛbGn1qi([?uc'о!͛3'55Lq4(6nIĨ'%~:G򂦬9(T0"MDaĿ敻dȟ8[aE,TGoY˜>V.-:MA1N|l"tn5DFV&-4آP2lpY 9Ae8U|hK2cBXHPԣ. p827#V_u8b3K\<OԳ'8^7o1:pY1xU~/ǟ㏜aoF=}W=7oɧ_Ϯ,3q}+ns|m~oB(n!gH \9_:Ճ YRZ^6NВ3+>#7S6>}z˩y/_~ޚ1x,O>|7ַ~qXE#9`89zKo8 aw@79s! w13 SBq.?N'+=0["aJ>UdkhE%bbla|"͛hFRuX<7\t ٓGl5 -Cz^%MIq,.$4.=k?FlzS/3g|r{V#v H6 p!fmDo_RwtӤ}YrgD}b@qeS<9ijONCaFzvrLJ ;�Eey{T ZacUyqזIzC\c|XvB)a\MGl 9n̜eh :Kw4/tDt4P5ͻQ;ׇ`bf ϐ"z~[7bCjKׯ\ 4Lԥa8b_YTVO(Պ rY;,gwW⛌YmlDm8Npi�� �IDAT0Aq.axL⊘X%"b}M5d_JvALj].hhBjM+׈*XYNjFZF聐!3ؕklq= ДIf�Y2494Npqr/5kfRd(vrɒݿG(Ci| Wjo m5&\=SX̆J̦Ʀ8~f4Vz" '6(?3^K21*D ˂K3d6lY` ? [h ѢRC"Ž˦aLZa3M�H"vqG+lN1лR p1vФ)CȈC2쩆́NG%':I;S`M4PD DciR7L[XTRaBJ1S'ϊOBlCI )qwF, (Tgd'{[[;D v |n:[ñ;⥎`#f‚Y<$;!LR<~&fC|uCCIx|;-M~~\{އNSLB4 2 j jBDž1%{\a >W 0)t # , O;S!,a4ö|o'~d\`\l43{ҴFF1Ђ})`&%؜,]2y/&y>g xG ql<i� 90R= œIq`=FoF xU8+?G?psh*W8)?{0߾~o0ȡ.*W.ny>u/ӫ Pd},9h@5̉k%`U51'+ [<vǥ.[_}ξ :tKO"3u]/deeoox3˖',ݚW೗s_{Y5KcWb$&@;bA8 L8!|oVhYG[Ud4[tiM~x򂨑΍FcM ,` a}FC(QL&%L֛P5YAwe2:w8*sZ6U G,RI{\2VħISb L F 7= P.6f<1 bY0;|UF{mLi$Ո4PcPDO';$ڶ }Z`(Rt("Y:Y,Y]]ҒfvS5w' L%%FO5_<#^8n\o^;eMUeo>ʯ"VXi?5IfP4"` "g : ui4<B$x 1ȥR}ShDȜ`r֊H_Vc 7;#auY}g)FV<fWy9w7g"& u+4@$ C)+ӧ %1`cx5{QH,Nr [1-$N<4#f}w#-$W$V褦);47@g]H$aGC$D 2M-/`-*9a6`BD, QM%&a 7ؖq:ФK\8}E$} dV1._ߣbl)v^L.N0]8ic{Wk}@]U)7yz1}B5Fw&Q3F`zӢ&ޱ|=5CHShA\ߑo1=HEMbFiA%Nf>7 3F a!ld=ܻ<Ռe5jCWb}$y."9؈DrlvP'@HzE4c<Ĥc*̛y!Ў|< y7O|9mstV#k뎘)~iFoQ <3b'Y)d,Mj4gF𒚪41m@ijMh QQBWJ� `bEj0Ʀd @ +kyq^|2jk%+u '6wb =PiP5 >v� a^ɱ{ tŋ-m1f8LG(^wqM&B<KϬovit(N,S9BJMbQ,&dZH`M0$$ڂ!i8z"EBN}8#[H6qis8:#K׉u^ e5H3O=:V~p8A=貃C�G-_c,'';&@u7$=A^sqbGr}1&fQ{<\kdy/b48bH= k ?`#$4 1%|yxIqke~OWx?-=Ŀ2(psћ| GXTZ>*19N]&wpwuNb#Ʒ0ww2ޔ\z6p5Y`w<׉ܜ6~m⦅^f"<sS+Z⺑๶^Ϋج_e\8g+ܼycN-4Xt=Ҿć~gq({'s։~Ov:)ﭫhHr]t2YgڛC̐ZPcʒ@qm$TInRV^ Bcg 0SuX]Zfg{+#&p5#>kcz <X$`TrUVlyXsl{7)P&k#d)bv FStE!I< <3p9밚A-3S%ZLcNYMsfeM]ׄ'kk2XuwS0>doox7ÅfeuhD ot2L[@\p*�byן{~޵|e:k?G.5C<`|ʼnO,uݓ]b:(TS3oAoA !:*rQMzH`b]͐l6\6)bۿs 42Eøm ;C4:ٗ~ IbU F0 I1=&H?m(vZ\2=L(|8>d&B#PƆPCUaR +3?}@<y (yhR3RAmb#S<c5_!ݷPm{h1'g{^Ux!)=T*=W2M G]J"63<<%4r[JB1Mw; |s3Nl#' 1q#7gQ#i@ILQLDIWu�T &Zq/ !83z;5?:f8բaRsE_¨!m(vz3Zc N&' &D/V"6DNuhVn|(=YQvА Y  L| G>0l(HT,3ʳe#J2ߺJF&?:PP 'mC@kVi.0&I UJUvq-f\-0GXb lQ$V!b̑/epkv O S->=l , 5Njmi ][{]kh2~d&Q^<3J~:#U"W85IXt)vMvKE7sԓ58}^ KDk.vM͙U`YzODWЭnN#a;"CP5 y]~ >ӂ[_#/,~G(%D{7>jZM#k4;M_뫒P)^KG[N[IsF�$*׎k_돃>4$^#ithdrK $w?/"^HO~5~_~!/{ ѯ>Jy]>�~ fou і̰?yw٩NJ ?18ë[Ռӛ>:L;Qlס!ERFc4!xr[@Tz[7\>]:GbyuddMήw (nOJ]m4+f^G2p5pk;"s\֜ >8vdT1F6֗2A'G.He]{9q @xb!` ?}@bWh^U` K.ѵ}Li.c76Ǥvd!0R؋[uŭٔ[>4LA%hhJeDJ:Q;-=l(Q1@vr7US<lYE(0BԢRa045Iic `VN0gYFYXse8wK/Q%CTe:CD{.`ayyՕbb}uǞxU޸䜻p`[ 16k8݇eP5ʰRb- 4FVUy<^ĞTNYA>';-FnN8)THILYz202`+%ĦL{.YLK7k9! g[9wΟO7t ڤXP&V!1^RB0pb}ܢ$H+b7z0,f0 e:3:"7^'SIqw=@DR1Pvo`0oRb=dvɠLVSKG9ۿ]ijt 6w@;y88C8 ]k'@oa}尜%T:3u5!M&-bkT-nM)4d'jp1ъTёo8Q=yӌVL cvسZ헏6E<&3 !-z;RߎpV&ئYFX-O)SҽQ>"NŘQ5%f9B/ 0dM0ȑXVisoPt&4##p Tu[u`Dw;.,X;ciVVGf #4%% r�B0& 1糍s+z\CHrF^0D\K Pb*w?] O4 nYy&b0SUV?v|=`D՘S)\YNULT9^H&/1 ζ4=V1 c81hwQ|H.vɑ?إ z6#mߚ`a Y * ra@VB0/T Tp!E h24J(.H5(VV^b3(a7}G vCJ}<7jz͌{N;'ҰIFL׮}^u\V??c$y(ǢސlFݤ@L&ЄRUbm;q_|e$82*fAHf=2 < 0w�1mvQIo~K~'G:޷^+,<rg>gu>{VwG?(\g5KE[|/p~\،)gΞ=u{"AyYƙ\}Mx!._>KTѱs=l8g<]wHǠVag< V[.[u'=y~tSWPO ?z<1*o]qԀ[%]pFf[//6eP8uGL瓅/> -X[=t/NH9,S/lyb ̒:Ŵ#@,*`<BK6 LT(Bos 4-a$FgMT!XKAtzP%ߞUlF՚1Beʫ $_lDfIߍDuVb)?~`Û-s`(ƤḎ+_2uJ]O,6T&΃XQ8HS9lU|3LYENYW RIG~t!sޥslڵ~~Cl߽CUU0xuyZnY*o;ǚ}w"G4!:]{=BLXyb1l]]"}DgB=$ޛZ}5s{nSwWwflIQdk,Ñ!y # bAb CٰHAb8"fOd5ݚx=<}n2 pBݡΰnSt-4\cp´?b)wC ڀI�-LUE7U*Tq:Ga7)>(tIBo<MozV JN51 I}dѥ`�{Pkʭ}?{w $gH5QCSkf8U$ZX@" bBVTd&hHJG.C5f`3b.GV7 ݫbC Bb1etˆP=)*Id kl�CIW5 ݿx ./3RU0:q(cTFUWktA](MlCSH$ P!C5U"΂ZX#XЀgt!~H(#U h  :Wk̂frIt#6%fCg/g5*ˁ wAqt[aJſ,5vU#l:0j},#L (ZZhR#&Q 4c%k^)CSИ"4nU# jc,Q C8^XT6 HW$m=݊F7|~M)KH Tk|ƴf(ey$BlVK^D+,v(2}w$i\T4N|H2Es6gFȠkC>O="8O]ŽK4ٌ$-R$Agѭ#h$ЂKqt+#kZ@Ѧ t=D3^@ yB_JFOmR>}Fc[ڬ> F#~d�V 4wcVIrDC?Yb UC~n!*&2$2[Pm7tYB]z"v4ivt<Jz(iO j/_' 6#}ud"?Imݧݦx"v"S2~EehS<p0axe8G6IHr:qk_VR fߌ%p%ZG�%OEBGI ij DN?$?Vh4/l\lռS(~_ŗo?^%78= b~>¯ ї_ɇ>5'0 T9 eal/-38o?Ǟ0y yrQ~~//pLK'8"W:uk-LqcCaX\JG?t}_}ʛ;ɟ'>ps>�� �IDATEO$;ϼw(C߻7f簞ŪG"og ̮Ad"o̸p_Q9ݝ(M;w%J/ߦ5t͓9.:x|'SD&M+-!x=J+9'0PҔ5FnojT J0m 㠸ڌh71܀|;'ֹ_nnsCw onZU1,; hDXYdё`Y7p<{\yVub }fP9jNCA?(A! U}!񆥽1k =BRbH>z4cHm1{ps=i(AƲGT%hiw9<G֎QNv+K;ƕl 1]c?v([;lomaZ=.쇽 9+)A\wcs(ox4fG#a`j]}7Zj:7 Rd4NYD *'%.jP ;&IzѤPhkWyEe Erª\Km QXAQNׯ+N)N~AUrbʷvG$Jѐ)In bjXxD001e0gSP,CPPG?Yd:u4eCSAGHZ)BBwh[k_!3?(Yzf2B JU j<EMMPGRZP䰴F}(/pwmx cEBp *E Zɳ,N\ONX<'F9(BD@ Ih"hCA:XPutk&8Q!Jɑ0*=j/Pvk C!VI36B|92sXDc5IgQ'h[e1CEچN%UAcGR:`pzJFM0LaP8y`f]`b.:IZŻ#˚U,X̉^M0_VFj"<]U<5vlx65@WXրq)! !a[Ue :ܽC`hE]5F,fmɻS^(_ަzmv`%àTno5p!ຐw 7HVv +9.$9h# /ASn7u|hTL*WC|9<B[GVH;1gsvPUM�I͕˛aV:@rGe@ILZ`: *ȷSzZB?M5aBeO<zY{iFL ǣMXW*6gIzAIcS! NtKWh}ћ hmbٌ¶ֿ.lx Zl@]wL!^Ǚa"C2tcfT4->ȧpmʫsc~x搿M ǻ||k?|3wn?W~k=VC .ͧ>s_ vCJùŔfgdy}b`-aYE[ۼ_*ϝeUΜ>H[(%?O}/m\Ӭ.НNY$U1 F7%?eOkWzE~~]AhL=#As9KRWtF+.L-%�>Qk}/@3j?J}Iof?v@AAO[zK=hB Ґyv}U#wɃ s]RQiEBCHP7{}暄I` >$*tt:[\xmW5D3v5=< r}X!5Bbi|�F)KM?Oa=izY1CÅD8&tmJtHp%Da)`X eQ!iWѼeܴ qGV+bPx-8n<ƻ vm~bg{=|"9VcH=Ӧf{gh8=T3)45<n֚dtR0:&-4uKױ&ŘxȹsG>ޭ[zՂZ=ρD]􀸰gX[/C"' 8Gh-0&8!B=f6,etT6tlӦŜ2Mk-O= D޺[<پ1falAs{M`:6QJ#^ф8h}<K:VeQdd5)F[d!oĪWEA&\ؼ JQ({Per:w*rh&XY 8֌Y"Nbţl�G EpAnWZEb-8pm`]&5-_`^czk3M#u4XBBitup56'')Ʒ(t<�GA$k뇿~T9-9,.#D@$C- G5!0&)pA.RqE>ljf(1:L0D0b)-CS{TW=jRS5Qt…@)g 4M)TU&l\!xAM-iK5p ZH~ީTAycTkƂm獹BD3@8QJZHnfiťج]k92iKweph*ql)7bOe*C<АEO#rm1DS-5:а%v TJ wm4s Hja*@u#JT T5_c*6m҄#GIEvKbBTbP{ˆp76j',uInwAz]_]N'$_Sf\K;~NSd҂w^p"1[c (pۊXOeS+ъq9% #8Ђts~,-p6X03K=QI[( Gi8;Jxh:,G7G$֢1R0\\d�aS2̜6G&3v!mSR9) { liz?>mFwg w&̢ g`AYo{{xwFy`9ʬ>Ex>o|#{a  /~,? .m> _W{<8_+GTUׇ Bέ`khmv8s$:W?cId\X;'xظze֎"I 9NJwR4ħ'I g?c9*1+4>K.5o�4|}GyXκ ܼqu~y d&ߋ:pQw�]RHZTgo0 np3$P/`GcXy]N)GC[Cg2d1c{d T=Z`οi)kޢŸ||ן}t$4Lӑ20DcIJQ6 {mmz}/`9b<iF'Ͱ(r=廓 WnRN1SwD|3ZoY!M遭5 lX"aڠ3*{/xYtj.,ۜ\"OIR= yVfP%BÇ)+,,qa{IRp)F!KK1UUtAu;dyKqewܯSѯҠp77`e%}ҥBzL!#!LǸRevR!*%% U0Beh/`FA<]r57oo @UA` :nЄS$[tJ1( {b4SӠpa1ϡ#+ࡩ"QOa2q^ӐVçzS̉MoQgi޸DF:Ha}9PdμP Aj[!(x2tFঊNJa%lmL'5mZ:R /C*ͧIN8C']fte+SH :-h A5(H0@̴{zr:r*LP~~zkm 8M E9<"I`Ҥ,O#k;$ ~TB MLL;;%"y&hRv3FhP3I$=Q!LdOLk5dhŒ &8fhhcuL$i$ic®iz¡t3IHS ې.N,2ER!iK3QLrM5(Bh'.)ƀ)|㩧 61B@g-4* 7n*`Ġ2 tb(*l>VLkrA#D6& Naܛ|iCKEHSt jQ4J8CO&=?I,Ae x=Zbu YN"+Ebr $UZa`HiM7FngHHOԾFԔbnPE7pP'}܍5z 8+cn~8K;kۢHz([~i1 X,𓊦Ԣ ewbdHs` %:ek=Lc8 Q Z.%F&I e8@Ȥ#tk=cM`\5\S̙x|qY:,F6'>R!oze&% wi5nUUᝣn}FH+ y7|oA<=cb 뼿a8H3o!~ͱNй V8"s ݟħ<ye1 |W^e \~e=M_{꫌RR,g>IW]k=.9gY;rp/gs2G/Cx;g8ulJ6vWOY淟zZ>̡t3ƍk`>~%߿a?8f�!>m}=j鄲*1-L%P[&% 6sGW=L6aMCC66, IߺoJ*/"@5)jS ߠR)C'XZ<o Z&CѿfQJ`8РZ;c4Q>*mUK+ +[*8Kxq<acglӆ,9ǧU CZ>ʫD~ ):Jdfd�iAI<TC3 x,QN[yαc�Q36ªXkY?|W{$cc oCf`4{O|I)!i^`gohpigna=#]a&ΗL&wl;ܽJ(0qP'_U<WF'找)\ak cc^H@w"]_hh'Y(12܃Pm-cuרVNR<m I}BĐ[ܭR~]*Ű05@)1,5",ZPBb*RpMlLzBw7SLխ). vDfhF%%($=0]Ⱥ͕FJJ" # _@昰4VGCrq olv{J&Պ_JPS@=;y&C!!$475kjXji.jȺ dV%oLv6TM;|A!@8rc;̱!ũ+va PڢuKmLIgUBiGDz`97�քm_ TOY EkOII2r΍0ZUm<_�=L k~P*FuɣoNhk(eBlG)&Hut?V1&(AC ?1Iق!؆(O2F|Ѣ#z=Fb %< 4:Rmk&(̱n]+DJ &$mղ Ԭh1n hEۜ3ASdž$17u˓)Ɔ.-3&<5؎6:C{E2,B2aSgIZAuuH@KmmPڦ-QPD_= ҲQ{&VB#!Rꀔwk' hxA>w&h7ŲƏ{Gd4J3}}@|BJu0`]R,\Dp01:#dǗG%JA :(tr0B綥OAN I9 M.asor*:Ƥ[J!6n=y'7k[{'d}~%MVQ7yrm61`!J07o.]6"e1_B{G>A>cH>襤Xe3Ō1" �]#B<pʔEI_jMCQZB~]/x kC>E.]mظ5\ۜ…>oܺ}i6>~_|iA(eXc[ظbPafoW >_N4 nܾ3O=<W➳K5? |~"ů<bcW}K}/րC莆?wU1 S*0 3~^KN�>Y]733UD)870Jydzt,s31_~G@'9E7_ #Sk*ɠk>sTK`<sa2e 5 hL{GcZTn[fh^w@ژie >g̤MW񻗷hg'TZf-aT9<' P5cm& < ﹤#/'hN9f!_VUC{&6Z0uCh|C㫆$I-챴D]95h3kJfȯ&a\Nh OW_#R>v,ƕ+,,>+@50744p=% 6�hŦЦ%(\MZI<dNJ$iψfКid(D!ssbg/Q^lnMP9+w/nFbh?uP4pUc\2 %P;b aY={n&X 87bZpkƚ~]ls i`;[ Kd̼!tzG0mBUTa� =I(.nITX\`aQX[ pr#x%=B=\ +g:۬_FM(vkwm-o XQt먓?O ',m)?+Oy@bP9*Bː, 5 @2ghVZ@E *Ĵ9Huf ^ǯ $I%;دӧӗM7q̟vIz q>V!Y$|4XbøsΡޛD6 &OM2M43=Rj\oD;%0W⃃ AHH;1VAS\^SRT倛T�CjQi(3�� �IDAT0fPGY̷as&X \?N))ъXpH QD>g%n UzX`t`^+ޝg } 1w/0^i'8UP*EuR({E9 u3N0G$ǩRh�_p WWn2yM6סQ< IPŷYƂoTk}2Gؗ{ [SrB`Vۿ6!#ұЉNÆl9#C٨3LTvv �&z@5QG0VTMw5(Dβ;_8#xjE$JLV[0C&ׯ\j((ezzKm C䍈$) 9y1.\|qw$IH;ψPD`ޖLp{g; |�$Myא^J?y߾5^9BͿxz$?ѣd#;>p{7S|+)w,.]j#Ldc w:$MuEKQ,s_iF\~ e,IڡLmlޯ`3|^+s125?Ξ_79ydO?~;, _QMJ3<M.o]`{{:rXw=}ݱ~G_;Nd |n ʓcG% k̙ N@*7U8mXJ;Ƶ~)`}^ 뷶oĵTkG{$=N1{r[ wSMPU9"(W^.@fs^�\P۶`FfSa`' ۦNPݬSw$dheӠ'5g=.86g0KfwRXϹ18~�boY�I%j_3J|Ӵ7> pnN&8נ#ELI+or u /]D)ڑu;YrQNͼ}m?ⵘ;T>JQ:amxN!u%6!1 /U>PB*&JLfwZAOybASD[wn[%z$h wQs=|Noeh�RNI<Np PNc^x/q$(Ina�hwD7l-;a"83^":("d`5 ~<JӅQ�iJb_Q:)w:]FZ� "s>: fPi#+5?sƓ.1jR RFsP  %<9~mh ,-|NCnSOJuTS}g/ܵ]?vԵo x覠 mJiF7ىd3LccA/L+- 6 Fx^JC+{|EvV<Ic6`Bb>Vsf'#xMRj;lBNr V.cfظ S1x RFD_> H;|MKS-<W{)rF%- JW?LQ5aBCVR<d VΆ8W t5<Kk-Zx'Dl* .ֽZvafwh JyR,e馆ùFUE]Z}FFӾGH%jɜy~=n lO0Դ@}Ŭ>l[x3HT>Т~^MW7#F A29I-:tЉA9hJ΄zsR%2NU'6QCjU6ԯܦ81=L0-gU4vz�fF`�+o4h8jiY+QĆVI!m(u'U+kTg2NG~ -AZ֚8*zk�Olp7nиI+3% _1#An )GfI`m1Ƅu^ysxlƄ־ ;Ylb홙^?d1kh|vޘ ~P[>p<=Pph'|U޺/~LDXI˜&F$} $›x<&Os旹IWk>9yd}+{~!] X;tg{ oQ;x?Y^jr bsX轊֜\N@?"5709Q\ح]XSWbkjVtcpv+ҿ%fzg3we Q<~GQkeJian1#=nT[\|7޼+׹z:{cӊPWXQjWB{\=-DTU(&{`l{m{@  tUQ42f|v޹(T08xj`IDH%U81C+-t+ba<{*1 _t(4!0ޠI #+KMLqٗ(#ML 4 8bx"[yw}, M3!3z'>nK_ܾ9 +s;ۃbȋ9t>J ss]6eF{jN]#MQL=ܸmpU`uU- &<cȬF!NP3v( q8" W+|#HruCL5:"7)H *o^,H h(\{(7!%e7GV"hOQJE!FpfZFߟVLH:`x0E[ Bg`袏A-BVųBܚ'yHz ukP */we)HA%7#a!\ @)ȻIXs-+(Uk͗)S^y|m;ߎ5/̕joHH,2$:B+"B'ܢ(=0چ|N),Fc㻶~O+h͢$FPƢA7IР+9y20ETV0Q *$K=0I(w] ^TԻR, P!Q4baMj-#GoEaz=iA.4%OLP׶ƞJ1eKcPPѡ5DUЋ7P )P gyB<cC~x^` zPnjz8q[^M譔22[k$$`EUc:QJf7$;~9'"7ڷ^7.ljEQ(0303ü <6 ??-A%Jj!ER$&f{Ww^Y̻E9ÉI Qވ6qHrLÐMr/!M"dixfoWT`8:intbF/er}Fϡ^+F,ٗO"vK  4nM7nb*CuqT$@|*8{(ٱ1Tˆ!\#]p U͒j\Sd9u(1A(_AZl P gHD\Rd}jwFo}DвO:LL:3hH/4nI'ɴMtHI(Xbt$v-޻WYZZew5gۜT35ڌ}k!-gzPdK{z1I^jU2;~#&X+ { T M_c!Ncit;,=|ۥ[@: 'r~wg `sh^Y:1S,9KbQl$#Bh$M�vԉ<W":{Nouգޡ%\|2PD5-doomen7^\8n='/ٹ869w$>K?̩>V"nӔ~uU=^<iۿ.rAU)1wp7{bbuM�;<ng/};\ޙP&ŧEQ2$O1p,B&iccSe*KaJXFZi%$_㽚T* A8�s͗LWM12ѱ,Nj9^dvKwઇբ` K7s&eM?rƍ0E6A$5&)o+XÂ/ť_9ҥm}ud"L1{;X'ɬ2)#ZԳj:Yx<fwwk(2!1jM.ko!EGY-,/fkwtZccX`7?gOı#yƬڤieUt"AY6LGwGZ߁[Д2+8Iu=j2Mm~7kd #$DY7=Mc0e#)v< qk*$9#?&l1_38+,u~D03LaEຊ]�i<WJu:Uj.W[&^c~ ʽpl)Y�[( w|IZ1iEu̓6MR.ЁΒHrȕEb>]U%;9vNHd e42md,N Ԧ]t q�nd [v-( 0uEkW.ݱ]?]JzKѣ>ラQ HՒ] .BCkn[#BTn5RĊjj`50|12)]Qٴ1eː b 3YnjF|UB}ݡ #Jz, ALб`;k|I/*gZ\.jd=1ŕ7f0֬)5ij"خ`*G܌TW+޽9Ɣl1)444BU)1 *1 TqIs~c2cV״gWMCh XFZEPL*p0Mi dj&љF`S\1d^+j7 &E@^Q_3ZU D:!,=>ab5-)}<jmM0Rl(jd:kC¤ DrB.DOqx sw|52J["@ʉ:A7%08 &FxWc'(DZNqzͱGt8/T6&H2L5cxfAma^;07fL^$Ɓ"}"uFјTz'98!2RW, D}_&*\idp&Es}+�!Q%6(5,�77C~pVz�Zp�)~z^]zی�A;=Ԙh"[@1qM4y3q?7G 9C<yj/t9}37ؾ5ty"?x{׾ܼACy[Zc8{p&Q{A(`#22^zmnQ ?�O};|#zdoWqsm1'Ϟ#gAcídr!T>=_c(S<?.,+t̗^ෟ}CW9 U=%3ҦUZ=!ޛV^rN> טOeG{Gb%R:,5^H&Ømn<h8It/hedh &gak:QR&"k1n-1r!VA6oRk7D¢s*S<pxo̰ B(˒qެs^},U5j*rS!XjC)91d& pTzK?,O/vEVuy#D&A&$twHsP*锸Ge^d2]c,!F.|}s|ӿ v# ޽dwB2xLbë<ok%f>ds{@([,(1=^)l ýȉ:P)&pfԱ ؼSt"̼aojpVXI) (˴עI&oy*#LJ/eG܎H-&' ǏSn\Dk!! "8dVF1JRb&}v[.̂BgL"S" A cd|pAUV aK{mXҜ(z#5% p"t ~.XY{ |91:*dɡ{41Ympk08x ۉid4NE" LPBRLu+d Ha.rJ؆L!MPd| :'8&tu]?>8ङDUh U!Z-vqV66zh&wvPL҅%C;SEX/hٙeg�Y$:T"Y>JkX@^.(M{J-g.;IC#3T}RnE: ۞G\fR hUkGli^5,v1$uhb{dn)"XRC;ױpcoDQq]%;)Cla!K�o0t!:MYg&̧ckbcFj^CS[5]iuil}ij-i$k1, X8dsvow[IIT=H$<WXQq 3M.@U 1b%mjŏfPTv >7^bgzcBus!|InQAz1\фQ(,4P~&ŃG؛!$fF4ԡ&g #78| BglN,ڀsdq9n5FmzaC0ϓ("Cڔ\"fQq0HQUSd}=$`-1< R.9&uC`u ??w&Ј"K7S&Po q)4iQPzx&ќVqwf!8qiw(>OD(N'S$ Z'| ?;~.fe^u?x;_'V 9�8VA6D&#&>gZ`.;(mEԌ#0#{yN<̻6g~o|%<ƭ+osto#/ƴ<C{J8b68}0_rx|~靫\>1F-XYq~q_<s㽜x YZVD_BBckwwۏe'r�zp׶wݺaoq;�Dj @*igxIqQXTtV`Tϥ$*|FedLrJ,.%Ы+Ne=v2 x4Qet�A&RhAW8z4-.)ת!gSFVS>ra6U2Iϵh @3"PkD ИJ9I2nvͤS{!KUHal slܼR,\~Ue0gUF<oqxһ9{O'?/_ewkXC5jkB8qij~k.޽B)-e'AL6P@TD Oğ7]RJ AWwdtb"CЭ`l"89'dH@KcAѓ]p9HWk\Qaƍ6q=2aczxhO"dF,הR$Cj>dc2 Dj�� �IDAT"q eH�ls0$)=ct@ϸ%Ӕ>9a!LŽ^G r[=(W0x ɔ4$,rK hR]z1Sc;:Y$o|Hr;yM=PAVv";JB(#Q$Մ?E:0RQ+^]! '"pyPZ#1%\HPY@,D=b!02"?av2{.JM-*kktq X  gu|=k)gߝ1qJDWS% `i4B)҅ 6P_)p p-5Ma&m甎WNPea䨢bE4=T01am1yow̕oڟ&kP%*6EFMSl1j6G-0m&ݙ#h%vCp0e߉uQ%ы<1Р̠OVܠ`d<fԐ8ĤX@ f&Kk{}Jycd̼P0iX V!*1Di_V.!fZoC(kWb_2>E\&gu]R1PLнn28;`ٌ]c>RIl'i0(ӎPު*R>$*9${zkBwRalXISjI]U0P,S ssuER6 ig>A~LC5v n5?Qqk2z!>iꎿC9#�m׾XkPœ@ @)stl(߭f{=tC^+uL.N Q=ϳk r>^/Vodjp}/O<G߽zإ 2x[n11ib+pWg91޼06h {{VL G9dg~|x퍷{H 1_|ͭS}^'asT{/_t)E*r"gZvv麼Xc#Sp{H?q@lWtM>7\,xr<gLw�b0F8ayyAl J٭-S4Jkl_TaA,gWg5:G\C~j1DlT[#zsmb]k6dN(d, c%*OIIier^uKHNj9Nj8r8 0iE0`$K/ 2@Qp9!=:.nt:9N«25b'P*|CO<ʀdĵw/^Q^o$.F:9zO>$[[;jAGL[8rbI<wQ2vS;C5YDϚoI)>Gqޢ"[xLo*3H)֌눏}j;LlmN >ZBAX%PU_ImIPLm8a=Jyz]C%kdR1ddtqW`U(.PDcUR$@(Acd`rIlUw!$A)Y$Kuɀ4b"8 HWIDvS .qMz"XZKtO)hmPdCK԰HcRW &ԘETqw,+UбP%H ^`1"Z(j\_?!aSDQ Ƨ:n 6.0PU.u@QT\sl CD>;kߢdɉ@nJ%s $LւAPjcYY%vVDq*R T}T4fLwpiǚMT%n OSζqh&RAX {!=AD1Xh\`.hላ6+�Dch$V y[tGsO'V3'7d 5`/ؔQ,(%<*�8| X}r7R@h:}S^rט@.CkEI(iȥd):#N-1$ WՅfoJ SE4TuPcI!@w}DucLx!-Wu+v@45!VU�TK(fEqm;W!E2 X~ eIfv$P:0Y6Jlr Rls2zp݀XM&|15FV*>)bJ<Yhp.~EƛAd"z̽44dtHp簲J-s60_z䷕n � Z P=l\JhB @q}[5t&Eyśʛ[K҅ ȉAi{}'EnO|g?N)-7X9**M@,7ֶ/s =A)՗^7~hP:e>r{3<z?seq)^:li_sD+;#Ո+ +9k@k/='p2>XQmd@zF? p^hFtK�i"F|iHĤ k\%3c%8QuPj(yƊ9>GEpnS&&VE-:s4E8€gE5(6FU%3S1 ,%5bB4hǺgYdj~�hӂ(NtB_Yi><4p<9!b 1AAG4&d[ڍ$g|Ḧͽ) EN'/u]E*N<ɬL&WRR78v09zǏqq^~[<q~Al\cˈI!cmCS= XxJU$%>1R @ I3C.Ě]B1$}!^ b{D5Xd,,!a6&.iɒi`a\Lхc!zp"\ɲH֍] ElД B]H<i$M NAuze\GO˛'JAPW-!@b4>$pn$đXdI1 L1Y}q~E'08KpE$_Ub PI*BMPXPǁ*i3Lg+2i>҄Y ՟6&K  5H91XHt0V l(j$J/v7fsgʅ\ J9>#'9>("Mx9~F.pau"gEj(R"?Ȭ`cS-`\ٜp~ړ"|In:f *]iŢe:D.5JW#=Av <7֜yKpHc +CtC5h\ {Wftt JIz%I1S$OK@p1g)_Eb煍!=ZC8wG$8+ hi0o(%1RݘDlxA#iMӤB~2Բ&IS6<&LE�XI=HiIIVdr?|h[ WJ⻛2S= ;ߚ^ݚRߚa4@N"ܝ*~~ i5OpVv^'8ڗSd"6c|ydJv <jwCpQ=fqzwFgIRn2;3 ĝ)J߰3&g�_(?MbD*xn@$[#Pi'9NF (%Cɭ }iAl$"M>8�ɷrGZKesnjϜzoX"'a/HXr 1]xH\s݇U^yM[μ&H lw|>ɑ|/|`? hHc; '|{8|O D~Y_Sgx0J2:|M^xju V/[ݸE& ۙ@KZ-?52<mvwf&Ot,A UWnd]N7~Am{x5mVZ^vlm '4cHͼkm)=և3ELIBӡ)Xl,Ss_|%Z@ 1(Je 7ʒ0$ �T In Bř~@ʛ7}cؚ\hL۹C XuUH3JMt%EQGLɩ,xQ5z7a%8CYC/xAr2ܕwc)2?K̑1YXؤب)FW!xX )w#Z%5k""LK<p\pGPP|jJKڗ)Yl:/5~mWob {䞻>FlNiwnwyŊ'5m@K9ꐆ0BúZt~ɦEEAKV(CTxB0s}tO l\md&?j&H3A3zJ0ܲT Ěͩe "24T35K13p\S5!ՐRC=ꉠu2  ܎WMH0zG*j2% 3&%`;*Ԓa0 *$o@n+! >#!V@SD@( 5,a$.qwkIyn$TML,C8γwsB3EivO_0$8YR#6ITA9D.^ WgOůGbq½buep{%17߸L;Y`s⑒L[7E)F%k\5,~X$,]3w" `<DjdTlDjȜA7IRň2̐qNXoFC|b& 3t|`xf? vVP*N1o-0D댺 t30In"VsR55'K%E':Q*ց";#Yr#YO`9A]2b^3KuDz`Q!zn gOPb|I-.6(wo!E)t;,Qz?cvAC<C]iT& lN.C#+OSe,' b6w/_<EV!G]lb RʭE U2XײEtx<T9VFw$cVYb%KǻOĀ>&sdPcrwάtjE]ڏf۟`woKʪvv-3�Gs҂S KR`KXɤcYdFK$k栴`SZ9s#u]Se1Jk RU"̧wsxki2ӵ13gϞ/&!tDhq&ʒ??ɠ?f\\,1Yɡ8{]r".^)@^t6$O! Jq3cp˽=pvnky'|󉓧X1Έ!`ghrn>|g/_axk`[ߠ>c ^6Aoc <?k\nCTD,r!=6&05i(ܼnM4(B\YBMs؀ V#>ɘticq3:F4XFkM\�0yg(~ ?(JHiCɰ8MD+&pP>|0i: B[@GB#֦Ctf^Dy`H2 cP$ydh`P̎4 C'ΙSgȺ]n^A9eǎ,KNܱ4ppkc[7ӱP7$hο!Ĉ-.s1Ze{k~r<y"ɏV$UIx`o{rY\CUlO j'\txJ%oلp0ڣ.oKE#'LoNQlJ?"B*Bo!KfDA]Na35.d,t-#4E7P VP C֦@V3&hJ (A& Ƞ 9Mרjl{=|0h!AY WT�4X�uXƗ;W090SBHk_ PM I`{GI) <^}9Hu˘&=x_7Jj�MMO+R4,*CħMdwv]?68 b*rK$7d v}L4ϩW Vp{cyy |K_.t=?Orc\| k?_?=,B&!%wBc=*ꛁ甥uR2Q!![L5P-V=VX̢,Js7Emf0YEv], ,M /+׸3ZM qFFɐ3,:jJL1j66ΰ-6O�aD-2TXECŊ!0QɂgG,ۉَ;݌՞;Hy4sܜ%F,yHn̒7ihmpƛo]፨-WOsEv.]fro_\Z,Kc:dځBWdkY!XjYʉkęrKue 1l gs}Œ?Dn ? E3JCIٟ 6SdGѓ5*fnBWiՑ;&6q(#}0\# uPzI�:筀F!r-hc_ 4RdqM!¤?ʍ mĝX>m p۔FA�g,KY5k_z_BLME^<tG\gXKn| OP'THۧMԬxd1ٛo=g?I7ָֻ kج1B_%k:=Fe G'_>E] :dep/]">ϳ>煉 sFA~}>xa>e1^э1Fr oO"$p sg}=�?ewp5SD Ч$og~UON9cF*l{ 1AE\ ;4?�(CbV 6RD!ֳ`>+1ЛE:T36]9Ӵ[S`IR!FX$LIaʉPqwS֣H!k(^1q%Fnؚ&7B4Mr3*nenY/z]XtTh'Of7"HQs`eG#t0Rm>$RTJ9|nG2޳g|ޫo}#G\UKcUbbk/pK1rNďIJA:KP5BD)C=^G0y[d\<FSZcv[V N 6SA b�غ6ZBl3TLd={C/o , zi2oSLqja H' HH)(YYSaOf0$E<ts)�� �IDATy) kR03K}}QlcLͲ`s:|vY{נ#HPp}ah+c<1&IzhOq;9]Epdȑd%7>9a( d Ue.r%qQ,K@RE:Hȇk~C;~lp RcfK_0hd]'sዂ^sܷj7_ڍ~S&[pt:]d<xlm1رUzx<BW?ӳx<?gAo"D5Tc i_e낿W 48PMkf/ /zl }[1XB[HjusƗ,*v:daHp.5@C׍8fL#:kS5Hc@eeH&;443?֡z1}ӽKp'= nƬP јMH4~,]Y?^giH+f"1è%ǔA%L*:5qf^$�5$ ;YKbmlt P,A䒚CV(rH,SKk<2Gwҗ/c(3GwSuiǸvX:>O -3O0F4q`brQ2bpD_k[>}qѷ7eB Ju)Q,%ufO}<Of<uWumz sf��HHȒ!{ccXr웍؍p`vee@b@2@0 sgn=3}9'Of>}䩪n{7:y9O>{;v'!74+~tǁ&OMv<a%Y\-ACIvi@ :ULM.e >tR;*tt%nzP3X%!z=(c"c&2Dca9@o}% >8Qgaڵ"^{f# '[ vX J]㔊4\t|g$M~W$4QLX,XTUn"KB5>G? ْTJP{ܸ<)l,rbw�>HuOT`< )GKm.M4exZ5޵˼k>}b=±>VRZ̡[~ӹ*@o4 \g>Em=<\װ{מ`;)H㰶]D5ߋ}c[m:'ޙip0ɏ ~߿#s:GX4DBTAE=b}ꞍFTTd^�xkG5%̚=>D.%csq VAS֝nMH~:XZ)$CĚaKN&$Da qyȜm:fLLn8jsN)P*0>g-)D'T%0JTd9vRT''iI:],l=ץ:(+;B6b\x(qme.IjrhFS$Iޤəkl3iZiR%$:KIHȑ9B\|vʡ}iCS%o [#*}kÉwϽ=ʡuٞl#s˱՛#I6[$)#!D??Zd$0&9)H�^2ޮ|-<@UAZ v8pqF:G*c^ew0yeғ@zRP:@2hw< =ϼVw;#iPyŬsni垮 j#K?y7_%WƆڟF` .ʚ/#�VEsÆ`W18,n@g@h),!kȅ?lҢ?G!*p<%=+M-v.lBϑ'ignVJ"CD2A;vf:s9ُ*re4~ aIj1*6Ұ V6J˶t[|ϿLUY8ʇ wy'_}};[:>[X" I<9 ;f:nio?xo]78;7=*>mPvcή[1=S.ԥCX=Ң}gMo^--E}Q3p TUS\ {5׶E/4xN$Ef WX`45AWc>o17pC7YZ,[{@68  Ŏ' `4V,AbDڲw̨HUAiax@dGrc&<"v6l@L/K HL\ Tnc$ !XNO(@h%P;EtfvV _޹qsk8N<|듗xOq& 'O]XXG?=fYMS&' C'9+!F ZHԢb^¯{}"}l뗩؎cJ9-9*nPA38hVk `=8HS,z\ځG>T (wͱU:}|l(B,n2"HIEBXz04y[SSe4ݢ\s:bS=R%MM0}|MTUy*Z:GG<@*n oT6)fcghM>jXtǗK?ֽ>lxkqۼ⦟*=fYw(*[F9`?g飑IN+|oE/S1\V7Y:;8-�јIť&.wsg%.\{΅@:�n?ps>/9)@Bk~hV v7YGH5|OBf݄v(c` g,Y'<>s]TP V_ S2 ! Q䣐)X^5"3Nv4AJTIsNDHfڴ:HѝAwjGP@K:UG$BCk:إ,1k("svnlA?M8/up5EULHyBy?'eZaZ-}!Ν>;`0ҕ xg,3vFTx훸)$kpe$<8yӵ]Ozeٺ ' )ds9kj]"9S@=YP9~eA@wz#Z+l푢$^-b-wq5PG|3p18ES7 s<m |EFc)V6a-^ <sI;f=a0Ql0,N<݊FIOHfh ЋGIFQ&6e;OU$ֹqoYED#TpiF5N,xws !Hv~>m"+HH*^% 7N逓.ܣ܉g+\h;ji\ t r }!+Q;I9jSx]'߶?58033Ƒ9ug0aP(3.''#{Oo^@џa(—Q>kͧ;Hg!Upti%|- _WWhy͕o6Vi}VŔʖńzOh TɄc*B'LMHy¸X ^%l\)E*S*:.3Boh'Do{3BpIzYM0yÓ.K26RaxQP\HY"*yW2҂Nͦ QF(F8TDŤGGԴ(TS R$vaP{Co4$9i .?6%)!7$<EXaݧz7_<~~7?Nb`^pUv}Gj!KkKcWyڛMّIOqo.엚vTk#8C\.Q{—؍ SPEpAw=m* ΖuU'n3/)F\n<B&α0 WBUej(6 .GK ؠq|YL zNtG6 L\uNeG2Ă˹Hy~Dh "(DC>`/{ǁޤ!vէl&n*~/ti0e~z`&OxkipJ=t84\fY,g ݁!񂧎4޺JqQ o?0j,Ӓqq!& Lߛ;J):ɀqV<3X|JCsL+GEJ=, ;^pkn6\?Bc\$*ڪf}}WTJcr@J5@Ge3`mN=aN𰭠ԂM:嚤 ŐDġBQB\`mK-M5J䡦swKLp<M9f̛6HHͩz^s\t }NJɺV4M H1( Υ0b="A$&Xl�:e_bZtl(Ʒ5z3s !yEa2P5Zk49G]eO*Tync YsV<ؑ#-nlsry͕JHu]s~יhkC 8<lh<8}a)/| l \1]tT d̑BM<mt2(Bj1ч)ɶ_y<N]xt21q!`!ar sD<B!\[1p8ҵ$ @آv v , \4A5Q[=y1;vjFE{K:a>b]#邞P";g#Prj UDcN'II+8nAU+ۊrO[fnL-(掣o\!1[BYjl̓6)j< #'/Jyچ&TJ㬏M &.. W0o|~8y/f;(&y&)żG*h2PIC9H` lU.Ml=(wu;Ip8fukrÍ7_'µuQ?xZ|>769wVVٹ UHusP1YjfP1zu ڂ]TߢwEZE)xpcH9A/6xLPis0 nTuWd=abs y7Ru.5ZCPzk7[-q5QMo;/(6{[8/Llᮖԃqc*q11_[;9(BԚ&P!@ 1E*%7 k .-^fR5~8!^)<ohnHH*_fqxJA�W gQǯkOQ3fm>_3&(.^<}A>277ř3K*khZ6gOW0"=(:*0XТ+  ӱYVaN'ԡ S^⥎Zp!Jh;FHLG7KH u)̧Q<2!y%g3{fc z9E.idEb,{^yc@x/{%3 e߇ P ;|6Z1BCJ4'FUϔoZsaj{LӢؗLMr3!zSd �%µ\~^79 seL]pq.&qkH)S%u6?�i$)&Z&nLS ֬n߇ҁ%$P37_Od@qQ`BB*{ϝFlL0-.vwOHM7'au2ሌ5UUt7j{7K6:Ft#ɤ#aU͍mFN@tr >xb  BuWF)m;6'5M>6jrH5*Ď殤G{Հ~0me4p$mscyf^N\Mt{mv`CЙg 66UC7 1&E\*MA>ot7<..,JLQ1a~]gN$IB<e(,nʲ9GUU8c'm =EYPd4wXZ8J'MPX4sgNr f;G_',DH-N"8߮yDqfpa}̓w(bTꉣ]yt]CB T=0V^`qóx?M LW`gR@mΪ@+H?b@hbTH nj00y۞ٮmO b<y#f@5r6Qzqa]Ri y|1;*ֶ`4ZpnXCI&-Looٸ0),B(GIS& :msG�tz$1@&'%n,;'6>`CNWR풪&Ґy;av3G*LbOQY؀6g>J`m.`#U~wԻΪR Y|`kM>/hL 㮱+v52dR /!ug~G~1~Է7y_8{ǝ,:(KYZZƇX|O@u{CzY9AH^IZdh+;IF=Ǯy 5 CɄ`A*%$n 1/@WT0UMV =p]a'󛎀G9|o<ͽbĈ3›2lXB)a F`rw_^PKQIn l49!`EXvm%ѬHE �MldC&P5bh(v3_pbf$b _+Tɏb~#RC8h;Pإ6DF>e)L[ m/ʅ7Nwg2'z=!>caZrIuBo~Y.uGZ?KG@g{_:b<:tkWISI_?r#!@]4DlMخ>x jxC`I7C+ Qo nm4y$Db2K$Aߊf1t/Q Kj9p:|m ;ٿ$5]O]j*%i^ XBta漧 eB 4#<=YXp )'t޺QD3 R>%i\cEk}psn/T1BI(*r?ɕ/�bs/}kϔ(ӟq7]3tUsbÍjȡ\Ni= .#yUj|ePX-Lq;0 n}?(~=wwDggIJ~WCL`06cǴ9r3`g"wX߆i*W` }<FWwט*=F0�� �IDAT$FqFUb $TKw&\ s2Q LfsK|.Ks,= Y@'CZiFkC& .#RS`p!b"vL=t4kZf }A\Ӄ L Bnȋ/=z6[<U&mr</s8D],//SU IQUGj$iű`�Ĥ!0`%):IQ9LYDAWN>x󭷹箏07wt{=|T(F\x-lUm"P=*s4z @Pث=P%P9 Lt#4av4ܠP[8 hxH50SRLAU<L&Bbx<-L[ ؂T52*!5@)+c\@ȅd0mx2G&UmAR!�u4nBJpq[Xꖰ@ I@{x; �F!B5@0*I M!@r>>D7JٛTd:6�=G;'D:1MaP6 nl=Rk3˯"u(Em=+cKK(J[@jE+ ;|>΁2Z{ez"vpd8%߶y?582bf 2 -(_7D5K]i+<}<EU0;GMvعr3ǡ\zxG. }&_x7'lP65A,f$sƣS9;!cZ$)XiX7B#1C9]+LzlY\BXpG&l-ΰO8ai  uĠ.xuF\A�+u7iEx-mE]T%ؑc0E[.mXS۰ �xMww;2! (D}i5N25j:b* 'Ip۱lFQY;뛐Ȅ" 6T v7ZͤF$;?A;m.\9C-_?b*;:i]R?8'G䓟$_뿀 geLFh\KZь_^mXFS+jBhbD:cH:[+V2�-Ϣf:\^ߥsC7SաT0g̵ܸ KyDa<P*Zz%Gu:a*@(j(VvcS5Y>Ѧɺτ5a,ρÇh.)| &;"n"B$f9,0-LE_`98 "Z~S7\)rPL*7}[!߾|B->׾*-J~>lNjXhq(v ŖAmp"e_Լx}L6 C\ U7v*K/eZFN籙6o\G5̟W7c a$<aiC~eߖU&{I$4<AiF׶T 2=`(!4;ԑ.hJli3Mdk jtl4tffz,Y`aaΜuI;{< F&:W3h:Q3C sBBEP uƉAo\$@%uU333C[_ekw}7kٗ QFf~5ݼ,7Vқ/I}U#|CwEek>ُ&`nZg|<yTUmg1Fq29 Gh8j?s"ɩdYP%eY[[gssN/#Q_~$k3;;˸(8q$GEY{3gHtn#JCvLTq߲a68[=ZZL g"~H8z啗I.na1B-*]YB2 .l¤LjT q3/)DERSIBfk7( !t:>zQ@<΂sPW$!R4r06 赀(i$aPVRǓa y33Kv$>d%k/Gf=k\;`f븋%Nڳh .2DV=i;dJ}( +VoAR9l { ^YR]ʀ;0qXEq!U - \ oakU D-Y15L5Yp[Oݶy?58`m$<AjJ;=CОbͳix[|݀LS f{</Ut(ҙY=Ro0>YQ(=)wrIO H1$Q!"{QK&V(4UC jQI*‘¶B{ӆ ~OQ懺g7O/hq\ HU p7<JlCn6 mE`qqACƢ6LF2 ՠ,Kӱ{|*vpcLSEa@tNFZ nL1z) H$M)u^ҋ {~W3f[kΘ)r 5$XQ`'5W|_&3Н=g裡_9~è;O9s*r؝-};GPC*$ZEMYZ0) C{})G*-ZaTSg+Z(Qc,t3̤3L0u)vkS 1mԷM!AqaX#O7JcKR[ cB8աxieaI9z/T0,>L.�Q:[Y+b.i>vL#DCYyd%t?sM;S]w7Qo1ɿ!~P3f B+o^ĩ=X2-E>{yΓ\|fi"(OҺOCXWc5XiQ^2vΒpEϮ Ȓ. ga7CgD{հ/\lcz~?CwUr(y V]M.7׭,  p_? 5>$?GI\@QT }þm ֨0IN,Q$!4 F $ XdkNũ˜;w'gϞ,.aqiVަ4=Z :M@)Z4 7P%ńc)P[xM];Q_qesyyF;G> Ĥ(_Lΰ/+_?esg?_,5+7x#pL佣8ɩI} Ǐwŷ$9]?㏿3R) G᭣%z6N W{ӔefQlb¤,QV% pި`w<!w GvM&u=/@ ǎsI}!<N 84AkZ5Q*xRة<Fo}RHG;7u(\/ E=ʍ]0PT¨֞g~:WYcӴ@t(M:܅(3$TBY`N,l<s k4PNu NG҆JAe`Z mATбyuWRom]hO:'K!IfV K –P;ŵ]v+0).4^& vIv/P#Tm5UUdN Vˑ$!J 2 p0B`@<$U4rleF VPĤ*gFytj1Gt0C3&MUhzEM; TG61~g`AdԐ / מI5U9skA|4k:rDžLtM2/"ߡ {#;ͩϒvP<sur~n8h2d*z h3~o!;1(PEHY|,`WѸƉH Q<>nB T 2E8pvd9r muM8qkolZ)pi "QuQ w:!= .:q.A%q k/ᵉX)^9|j4)Ri\ZH12V@Ѝq<$FiANjcZEC ?sݛ8�3Y=֢iM+PtQ !v{ cLkd/loHxOC=9So:s ]z'H:9NN П}OO;ǖA-Gd9Hő=<[PM~OU&'"(Ti8m#8xB7,EE(LmZA=(: hٹЙRzc[#{9avJT+Ō4iZ!M K]Z=ELDw?oLFVz ]\հ\bd0Mah,ʯiIs8ie;ǺR}`qR ׈:TG߹x ª&os{yܝd.ُ^w~?sۑL!ԡPxP|&{)wJ%cFz_t_؅%+_lL%x-ީ5{I ܻq:5 s9[oa\>`j��0"~aiFO`F|:܎L1.j kj7ۃ0ydJ7qp811hר$ YK=x?s>uŅYfiei6 8LI,Us7BsOFG?\pp֜,O|9H$ |?+5>zyW)'CbLMv͡Cɻs?hiFEpo6əCy<y[Kͧ?q=B+oћi33 ';NJ)m^F\[v69u~m B`\TJ{ 8zt,;F]U1r5I@kjeln>LUEph8p~rR0||~A>"]ЀON0mmj*m-^\`;0lpjY 10^]\yI Vp׻pׯR8RQՊQ{0Xq;T0=OAk&U,G px0:3SIJLBlf4פt“琔r6jlwmaųYw('Upo 3yӆˤ'Y!d9i=&S*~:@ҁzȆ MXI)is7 t;,@Ą`Gz ;"lc6n C5x/Tɬ:~hAB'!zNH9MduQ19_tn{`ˎ>馗'G f�D`(0,IQ$WEjkveVڕˮ-*TWRiw$E9�A9N䙗M>@Cp\Ůw}{ ڌ8C !fI2{<JiE2n6ֹX8nsbmICMwna'owk.!p$guCO?\Y{ѣ Gg>Tr7sm'gzI>v~vD:�G+A:4F&M2Y!r H"&rl0CT FWъBA5hM[|3u˓O|RCqZKh]o)Tܕ;ҥTPIHv;JlgBcL0 DM} З .Lk|"d"*~hXĨ""bE76r;#&$ε3 UiFx A=a)l?o慱uuֿ~/KmFf>?Ih:hx8;|/<7 ;btkB;~{9x<n-,#jƏ8Oӊ_{8o8"L֤M̠+g.x j-:m X5X_ztcyYR:.0Z/ `g7OZR JTV.P?mLt>(Hvup"͚<*!;$N:T*~/qQ"v AQl&E ք1$?l%r2g&)OfqƠaK؄ KOs;]]ABU%s$yL|kt_N${d˂mZ|պۓo'IYx2wr=2?Xf*K+\:mǔg}^ʑ`I Ԇ$?sxwc> ~Z92YN~crTV#1_ jwtw-ູ9ˌl'+KoAB/jZ`kl?U˩^ ۑ'ݫ6LPfY4V*T}MHnJ.@#9#˄^Nsٽk9pNuѢ)iDFS5+Kve5D%aTO?ʼn_uLq^x<"РMq~ǏkTՀ3 ?w[fcӭpj';];pvCDX9~Gy kt +ܩgIO NOcw s3ALVb1r\s0O>8.]&ISZyFyvT^"X#$IXZec`XSDMNu]P 7iHҸG!l'.4$%J.Ո"@H+ JW*fw=e1L(:JU69LwB`I0,a"߫`�)x3̡b $U)"U<Taߧء@U)ҰRYh#LU†RL 2ӡuM׊2׃$w¹gnN]{+Z|3^Bچ1 + C{qk #QTpmynM0ʸ,mXIRjpk1HNppf < .{0a BX2aE u$cl4VGIr)N fh RjpaRJnpÒ!qOoz5?|q L¸U&D&8<X )f>)TbP"1n{�5~!G< =v;+8ʽ߼O'OCʇ?Ak{?z/۠Nb? OavOaW|a|xj>Vc7ߑf W+4K/y}udgn\%l(1(_1Tz辄OZ!J r]OmPI JFzk 7K|+A#l3zcAXQ{:,>=${`{b#Z;bE9js=VR2^bPC�jR:r8U[^(Pvq 5lQOf+}NE^�� �IDAT1I$TOBQp [ED6 (tҨ1 1˲n>ʑ[^ !VA#i<<C\\]?N/ZZ2(V^ -GubD&Z+QG_܈!hWׄ+Cu$i*-1N1h+GWz4G/ M M i,xTvu MW|"cMX h>Bl 9_7-$ M)kM$4 bՉ5_!l,F$Ʋ2^9)EQl>$yQ+:'O~mI},g?ǽs3\u\&LbeŠIG|ROwx�IJ dj/-z2Ñd¹Kkc(\$'/GZa`R;ٴMm:~/|qHMvDЦ`59�?دR+Q6Wa4 FKʆ�5 P.-/Qh6k0&ix,چ={vs!Cٳ{;v̳k.�:"1zKaq[rt F=* tgRVk>k;̻za pW} ԦTeI*m~Y;z;{u9(_nVVkݽ&RvށM/ "--#ƾqzfmTjuZ(ļ~U4V6j$"@, 'HK 0D6=.U|lLOlWa@'t#?)~YL;OH\PF0,RE #J*YI\"BWT:/1tD!aZP R ;S~5bO=FVU,(0 U,figʠp2Lwf<7LWX[0m�c' g0kLq_. PցG+vRXZV C%A! hwV9Gʑe\Z>F$i[d*p͕$`&B(n\dϢo'"xІ0}-1۲k\)x8L“kE.3aL}OVX0F_[BVoY9 HEe~<^ ~hQSE<-|Pj8<丹ӡ\W}@o|raboUc.nH8o@G?'~}|ogp1iE=U%hJ#;:8C3O5~7ƟG& n0Fk!, A b F'&+RaPhtQEc^wGC\O }C^t R=$=ӷvXz#m�#1S "&yQcC0}RX!=$t/2`]Fݶⷦܔ`@Rji$ӆՐ{aݐ0b2A5D)^{=5A)`%(#ӴwK'?(+G/xa$A[zѕL8Ut|:G;hʲ;n``wΜ꒢;͑p˭73r9/| g/_(nc+˕~ڈ+%ҐRg0o<[ylճA ޑ  `1`Rbd 8B<WGzNFH`j:'k߯*,v0<ג⺅ة1Q.:ay@qlO`/]y1b2si >ߊ]$m6T9$W4]Oikhl utʤµ)&'kk-"LjIB_UI$ UUQ5UUۻ,MLXwQ1Ku_dˋ{1Zlx>@&j;42&~p"2Q@% k0EX鲴~qg-c[~RFn`_^~M0#C\|??&ơ$ ()l;ATl&=9R7/7&K0}&ǛH<-4Il2)MEܶ6,?8rI)n4 ;9ph#;tNiʝQ#`R"q'iĵCDJCfx暣q, Turc# \w=}|7sO_�o#YF ޓ\l7t#ss3={,+8x ̓&wxI0IژHp }KhXF'9޹NӜ:mQD*rIxPlPeD-$Ld$rtuMH6 n~֫xܷ;;ѽ* gXxf0*az�-Y_1( 9v"1ٷ|`@fC;C37]^~z"5ԀqiZ2}w#_0�Ɛ'0+j (lf"6\Hx#cȓ'`Lki%b)C40R7 ѮPj%t =dSJzF+B9ZDGgLK YT'#Jhw<Y+S"j#GB'7 y|⧏^y;!a1snĵ$^` k ΔeEjKbW-\)+ ~|?MA$ R$D>K=4#4HX*K*Z8"ĤLek1?C:;w0כ&8HV[#S|JD=o/3e `Sك\>`1K* #!+ |" h}d/$H cǠK9V+k6V s SIi,]zKѓ||]I5EmTL#ecbߐ[(%9f,>Aq`R<vtzbŀUEqM27FqaV 3i<Z 0xZknE[0u`r*X_D(ǤDAǏj! :|U#>A3H=$D4/@Qs I;35M=/c>D|?%vK~{v@'p]JS xl]SrίBxR6఩%Tq O7HcE m.$/Sw4hnK}SPa8!d"*7u1[H*f�538<tI\d;Rdg. F- ׇum 'hm$8@#9RPu,5of&<f#EQP5<Iqɴ1"nvSLF'|M0V^n&I="&ˆqD^c"Q'IXPإ� K#6u` =u9:L'|szj7�&X2Zj&f>oK*|򻭂vIޤǓGn_;�BDQ!HLD7x(z\sQvXXgffNǒq G*IT5�A FlƂ659lԕAe`muRH1nGGXurDej-gg ^ٱsuҗ? oxx._<Ghs۷ *>&)M6Cx\1J ]v kɂF$OukNQ9zc:"uLZ1F/ ު(Rl:ƂeMS#͵I""M`cF!x5zqQ4p"d7 UX[.p/ 7̭u.%..=wz^bE;jٚ_3QQP=Y^œ=7Wu[\bn23>+bF \6Xvؔ k(LP:XšsO;&u1mH ,'ٿs9Bab0"t,*ݎ$Ih52 iH=i/0ZT8);{=VFr#Ε"#&-W"H8 &>NV]|_ N: Jh]~`P$<k'ZdԈFƒH`T x8CȯIL@H=ž.*u# q2I0$HF<r/ϺCc˓֢̓.5IFGxRF(789p�V t[xǻXQ&6%E03)j%ܦIP+3 OHU�aSTt6`5 uj +UTnަw\TY "kJRŠ!5!V%5Dh$ %#Z|Eg,znH wf$^fB7bQԥD kb,M@Bz|'#٨cd$Lʋ163&55$I*e"KX`\yJoG_Yfzw0>wlC]Y_\H(~Ž\s]?z7z;iR%KWP1|@2x<e.n'7_8EJDC] M@Qgb6#KL엎u"& n6;9e3s!".c\;M vӇXca-7D fݜy+-|OFqZ3> bbjtkb 9!S"j @ &J%;%}D6i?+ۻזhw۪nn›<>[z0ʯӿZ&7;]Uopy1ݘW~ɇUHUp&TTv96]w\a愷?_q=ymph' :S?�{B`N�GyqMJ_r% ~5ˋ)///-xqZ j% >vj$SִZI; 9bAQ@#Y64 1CL.]t,v:8؍ GHRY:{$l+(6E1IC_cs?3mw1?;Lw^ ,#M-Yj8v h{E4R&PEȓ amkh 56 6qLPW&hƎ6.k$qM,lB6FQBmS M!S%QL fR̍5ЎTIBtl!DUw!<DœDZ4(0A]BQ()s(}eCWr*e mp c'\\N.[$0`CʡhiH@|'s 7N")*W.RX8<{ fer]c#qʘdy^wa>k^@:;G:QX/J( Ap^gR|Wi2Ze̓pN"3-d~abEȌ ^b~Zx^GIJъV2 n5#Ƥ]GAE!Y +%A $%V þa4X:S)ZhLCP.L0@\EscVx9TA kgp'j0fÍLy@Da63AEj"djJxkdc�00L*X!sJ+xӄV-la^Px$�Q"\e<J>)nɟC>f|C{|fWV;z3Ӏ23ef!VS9䖛p84UFLҢt,4]hl,)K: 6"EL=5j 8 Wہ6N@) !& %;`pSG[Hfmk!| Rg @PAY9_r[8 KL7!5&xOE+4D|x]EIUkmZq-!#J-2@QWv&a@H G#2QOZw3gF, ND0y_Fnzfz$&]th:\\z[w~Cw[,7M%`jٹ`y[eLN7s`';k~O:}!P?[^U!nt*i\d;2d3CFAQ~c7p3Ձ^;~Iur5 anxBH9$to3^LgbE}nOBR;dcP|Id$#K;dik3Mb E7GT%+qa*:AY}bk~DpQA=M8]LY$ۓlvX<6߇6񾛯e/vʮöh܃;?u'=~|m+[ח?u]!W9pАKrx ػ`xౌ[]!m7wZ<.ߜFiQ}YkL)s,,33t:-9{K ~"\4i۫^chKo>?;/lҨ[(몌yn ٛkAq7Z# I!A�xP.,6@$[xJ}+\|4I(&6QIUz=5\t~OQ5G'[Q cXBucx"Az� "@(AH Q ^`cLd5E^fz%4) QA1^"|[ ͖$krM-!5 RO./!u鴩}LF*20bTUM:;E]l|aj@Q 6L=6tY_Y%W>1>~?Ҥ�v�ƂQ(EUV).s%aǺ㘝|Nh_A G)r8DNjl|ΜƏ,ػ;u 6 ֨?$mmE s!:wOT70x d@ae,xNKÕ*ew* $r )7|�Y+N-rv5D:w)yǓuK b/,!Xyt"xǑe}E"kvnyZ]!m++Ca ϑF&5NJ8q~)zn[.f݄mAx7Ҹ�~C)/YFgEHf>%#۠B,z5hqXzs?@N8-qCZӒBj{0ڗao8!0d&q|ַ7G&_?szq򖻸{>)2N>w__f~aQu{'n|Çt) QAW1)qKMt+)F#T]TDYh6sA#աٗCvNaL kZt`J"FB2U2vKRBIX41hHr7%Ԗ<1j6֌ �� �IDAT] /,`xHƎi 1I\!LcU}Bih/5̎<ZIQ5i1 !BO Q^JM#-PdHbϯ (u!cFT )͋''DH 죘y7ε,_m3g9) oqϧ2JٯsD-m{gyL0,*0CKABġGhT(Boo ) @(knWwϢ"4v{ٕXሁyj)YSQ ĭƹb # wtSWCMbبN+k65Rp͡KdYƄdhLQ/5S\|{3Ȳ P &nKL:$V}Ӽp^[^]|n ?"vE߮H/A 1Id_rdDjM,o[:yM1!-R֟x}Cf޹26ygϜ_+^V:(MƑYmw#c3S=>ٱp?{{�h;>2cՐ#f* tec`B\;ñkŵU>s85L: 73f\e dBwv>Ps̈́]ٮơմ/-xabhg\Yie3G@4{KϏ4 a6%l!뢰[We޽ڵY?zo`{OYrڻYi8%48o'EFLC4ԄD J0ށlb?@Gta/啋"ިj|`}Og'2ԧ^$8qo<1Œ*07g57p˴:Z\ӌTȆG%i+'-r )gG~sj$kc++tmFPuLʇ~i{ߧܓK�-# m)X!;ڇa|2FOh[da F{e cb ޏIC{ A3N2%7f̌;,>G4R]*'T!E^FB`2=N%l-(#T%%F~sfͿ -vѝZJ: řS]صf$&$R+Z=׸rtLYLH16%hJat=it@!O'Vx݁ΧJ5  rQ6fU*L^g/~*|tTcAUp^>:{Mwi5�$zUjRPf3Hb ^ L _fVHb%u(:$ P-0S+a 1JZ(*6&L L0G} zs?tq`"kRUÓ{QTOX,ŏ*Yƪ1Eةʵd +d$e!ŚSɛm\wIde_|n3/dqp-w$VGZJPC-?'5ZBғ˲ ~^}ŋFB M;Gi:9)UPJ1D�QuRi_!v&orONњh"2qNRmF0BZQzRk7؉m`I' ^h\:O*7mv#%1LhL>K;e0\1-~sO%Ub(ڈŮIhVLPK� [APJ %K_@k&l*MغMM)$P3;_ɧ=]nOƷc/zz;SE�$[5-,%6LL'dI_<4#dIVj ;|u![y6^\FAc!Kle'B6iX;($72g" CH](bB]AЈgn|l{%o*a<@6J;71:SQX+3U)Y֡7}?s'>E]G$IrM@{~Yp;/Ugӧ~;}R0-];$oǛ$a3hmL_n>|wʴ8> Zpo߿Dxo+zÍW-u~Jr"Ĺw0_@f/p˻3n<D;íﲔJjjrM8M8r 7ts9V<.r=wa7XK&)iv;:ALja *p{9Րۯֵ<D66t'8cf1oG} 4;d<m S=x` G:WYUHnM%"TUpNSw=׿ĝwnpXSp-g?`vf񾵙7ݍz8iRqzud0$u0KkPgYgfy<)ck1w2^Dظv?{~c?}֡yF'.6)UU3g-E| 2& K2 [x?` 6I-XH#t)@klwS3<t2yzvS[GNV7ݵ?s o ӳm1C K?AdiN6bX;SbX)W'^Sۆf*AL FC{π[#>ĕGH]bg;m %ڇk#,w@\vzR mEa-c/+n͚d()N0BG$Y oB(uRk̴qdP% Em Q*リIpRaN/62"TL yې_PΝLpƮx:mGl ɐ% H%1䡕CMdDuUCU (S|H,18FYTW$g:lwIcf6U*aEF!=$H*+*HFqm3!x$ k:0`rA~&ȁnxC j0Q]hkM8%Ⴕ\WS -<Glv Yvo XR/$,]|C\wb,%aU`1=�K++5T<cN<Ǐ{ s{z; AR(Q$JiIYVlgD'q%qyRN*{gI9ٖɴvQ(ط@wwsqnLITtP~{sD[;CR:iMx@[P < CP ټs !;Yd8AǷRE윧-!« < ؖEއ}Ue2EZ4"5rBϛ! )U8M0@HϣX=wH}P&a>WVCD1Bt $D^ zM<Axu, 3 ӵhР D3;K!E/zd <9Ef5:#(YD^GG|{1~ ~]~C|i{Aϴ3kGp �콪XHk"# [nJ,RT'E(bgjUb`=ېhwʜPl7$2dYO GOʐD<E^>;fLƠ/ (0Ƃ$"P@i(nc)@  mF @ T2$@4.1'-`Xc޻[{=D!&Q]: VWf{l#?gqNZKօdYvyq2�kt XO ]IׇB5<y؎A)\ST/.ҼW�[8pfp…7A#[R` -AZ&]NIt% %IZVn O?HerCDlXNǀbX[nH +~%Z+.]-vhx-H^> .[) ?}WHgsXz�λ=M޴f6[[+:\O+�?Xzcek-gi uXE.ٳ,?Ob^b`u|\0O�dT+jNMC~{jf<u݌^^(fJ^GJGaltsIRXR?n zv(CLj ċKJњt$}tr',%<{52/ VB2(# 3JIP nRT3(+d:2AUR(Uq 0vaZ`+ʀ-)lѺ&)I( QV2f -)ƒF4 ]S!f'"ACD:UN<z-Bp%b-i_2Pyd7r ~* Hf.%[vh >8s%mPB> KʀH*d]LJ/v.r$-HJf^ hmԈuPFh($;vZiGO۔꒸Ec kg}2d5tv!dvj3a6ę$jYD ,YJÖb,U*r8!Tv+: *tAf!n͍ä^];&&HK@sMZt$еS�O7*RkKz\PEt,\JNy2&(]\u?9r� Z׽aMϾwqtBZ1cR1^K &UzC0)Φ]MFaO:dSQ?wm%|h$+R+鐉DVr] kš^b"쿑˻ &ڱ{H=)=!Q?P 52ovTfKXz^ k|_4"h:@k/#rBkс\vDNA MB&^@C {2 ؒDNW9J3 A:G$ zm`!08rxgepFEvɡmCa dD)"Қ)iH+1weB9+0-l"[h,bBy;im'Nl,E c`r_~~l߹bA?3&F7w<Ә$M@bS K@JǾ}|m?y+eXHjLۀ:yR!0}%eւq"ȅz{`3B *v\`%|nCIo|:,M1%Pa.D0IKUT(y]: *!}/Łքk'%uXbWel|2֎Z!Tkb Z*I=$4ؾrg/q[/ x 4]dX/\e o5zɻX'�z=s(,Yx C6ovqK200w8 6̵߰پm;嗾2if7n E#"ԥuqйfZ(3\HQ&"짚D$BREh7Xil'Ec1uD0`-_)Sۦ`,/)&ǏaXk_FhB%ţ}y!\,G/Y+xk. yy9dz~=q{~ 5\jtD~Nxx.J\#ġ8#z'^t6bē=G_?FB_`vsqL$ wNuuctݻY{fv,R1(P !S[7#IRF( ~kRP/cKdH* &$KQoX:~kSJmhV#ntodžҌtD*,:`xm @,\,TQ{7!]'ϣ'0 u+1ddff/:?v5Y|pt#/۔n❷)Ň;M[,$9s 1y ,)ߺ y09@,CX4F'@^?Hn? lim,8D9BZKThb>9R*_̡A%K T]T+GT]4a䝐H E�Q#YƂl`pd'^)2^ (n7# H$VnV =P X 5piQ3 .hcL_F<|']+!"iM 1&"K,B s jm̝<AXuE1a�BZ('иHc/ގ)--ByzȡI  l1%2vK58B{Y%DR e0 =Ӫb.o/#/J ;<d8l WnlO^ȓEJ*A@庂$dRs(RX(xٶYUٜ.2T_yǻɿ翹֙0+I&u)T$&''f_eVkD?V:{ 5}4t'p:juk+Au/p)ߤI5ʽ6~F y.HiqA,`6)좣}!tK,xdwD^&*1 Q{޺k"Sr} 4m#97ϖH>^tXi1X5 P,3A;+x=t^:>IVB"d1@LfKv孴h6l i=]ϵ P]naw@T!))J,kiwPJҪv-7QROlŁ^oPw:w]LG=_E׽zMڟ[ G8ue9uz9SþnD. :Ix4",E�ƂPW{& R+nL HIH4+<&yrg-2/IOwQRt3$e$I\٫zI?7)MB]t*Ç8Wj'^_`=$2ɐR Z5)z <:"k^ oc~iloD <CQ&oMo郯! ]}'ZUuMg^&&xṧYE& JyɽwЩ`f91�JY 1w1lj#fNQh+MIb=l_Anmj5p^:Rl3psq%MpyD%3Q{&bw\ӴL򤶗8cީ2^(g#h7R֋Njs=ns=-G�䅿 I*I"r7JrT.+Xb`y/~{vKLMmf~eDan7s/rþ}qpK_Oџi:T* RgxxU24\2i:C%C\EZJ!J/[ma}UNWȒ2%͜L06ʋ;yn.,4?q?Vگض뤟zy﹕{Oݵ( y;.0|?x`4n�?<A;.P& W b3�� �IDATOҩܼR_&*WHYZ8K)̞@Gؑ fn!GT;+-6(Td')7z +tտhGeQ"]Ecig=DG(hoa]h- HAF`1*åخ@J A�N@܅)8 i $K@?+'Ym)-fp3fu4 (Aq]I8'IIb+IeB).el ZD h- V$([% to*xw5#ېJ%Rv#ˑRpoucIhƒ9Gs)e GXtHi ʖP7v^:Ȍ BARyĄ r.̠ϿDi@A!ySrě I! bLBB .4Эj_S链"aP8,Xԣ.6~u&1xP axCYfCY/׺<o]|\)C!ȤƪwmyIR$Mӛ1N2?;ə/0: '$YԣOq#dxHkZcxY]\@G_`<XKQ15~G} b+P HÒ9 k2 g^deiO0yA\=yf/Dg-V]'i qo!�L uDHEJ#1+<PK .P.`z Osku~Ey.|w2<Fk*8 *^]2VbY-b!S'RYq:6BQF~gpx7<<C4kOlsޮӹ'wg5ӛ+Pmd1R.0EҴ^bW%9~-vŷr ܵKbD y*斡#:dS%^''sq׸w60sƌDCcB#Pr J"TT۩cJ=Y>ЏND0P'K=�|kɬQfD9638am'Y?7.(҅He@r K蜪sF!9rPc)-o#VX =t!l`eoL*7;7&oew؍hZ"bMf|9#i6-핔b<A:WmGh͓/> p5{) Ma-J)8xABb;Sѝ?U.=3h'Mt8)™vM\x wp:)QpeT.3s T*%oqӝKU@0jT:PZ\JϼFqĖm8VNSس|+_=\xnF4•aQ 6d~OhhZ:UͭS$)֠CXa̬$gXx,US)dcCRXXZYT%HbJ~.N?$aǥ9 ":P,/oGxǸ;( l4֊BXk~[;s�rjy|WbH4zyڅpzq H?<Ǐ,m2x$4A-(!XD/N@q'h~S:LC_@NSh[dAzl,v B :kGH/@)nESn%(cw3Z:M7$ϽNv&JgfHī-Da&Gr.?`e?&8vVj$qTH>~ J:WЮ@큋GPntdHRЁn$M|hE(3TlX&4zD!62lSFB�})@'^JKXm yCqHg’ixVBiP:F%]\ɶvSR29m0EIir8"`30y1d(iLnÜ\Jt|L`)e5s 5>{CWu9z deE3BPr!*YR j]xEPd$-3‘ZA-Hc B@X EiJ(v�dQG.[l`Y <:$EYCv1کI&bXFi%S&0 fI o/Pbkg;~r+CVKύϻJX +| % p4pBg#�@2mN6c箝|T/3P, ={?`qy1<@8ZN<Øo|A{sYCN?Mhbv+2 7@ /)lXcmN!(3=ݓ] qQm%)û.SRa0Z !NǸ JMhhDFZɑӍ#J)*,ո% .T( *8ŠIS/- E;ǡ Iz '"' bxg<4VKYre WPZ+}㕭̋9̔\ړ4We}$6MVWOc& B<5, >r=9^~Wivb WqLNti_7^^tVb͏D"PZJAsaM0l-]^:Nٱ&%X;r-0ր֏Uh>@\l]^?'VB:`DY=R9<Q$/T& SLJ:4 '@*zlR;txxk>92_ =6_LR"ZW Ed 'B^9 ?".ݘ|^R{. Ƭ'RJ,[7&"ĞF'[*|MzO!hZd)'y۵|?=I2LL_;sK\X Td l])I := gϷm2ycsTfϱ72?1: m-oo ,̦gu)@;l`n#+J$ TWh̲2 J Q X8,GjDs2%95ˁm{… JoL<(c/VH^a7/~eV=J)V0z@+Zyu^./, v8!hS.sgXZ\Ę  mjkal|SIo-l$6NZEX@+E$5}Eʕ>~?㙧^bv+˗8v$W�ifZMKZ1n} 'N`uuns<1ɓ;ټy6YO.1wS_Q8|bJ#I%NM2PF�i ]Xũ_z?<8KbbAfbs |>Vя?COM /25'WN ytsG,fդ&% |D<\%nt``C eƞ=Ewit2z[ á}@0BDENJ MT.EXQ"رtER#3*ilK܁Gd} Wcu/v5qtKĮX3MK8b6ͿhɰW(;8 $oU SzGڸwqE⿝,tΐqP� M_˯Ը_U #!GW%nudm92'68kGb+w Q:Mb>zs M PP҂ |͗/YmAkJ>w<#p5ӊp5ֺw<K 1iq7$D C?M;K<L"P &\8 G_6H},y &|]Q)n̞Kfc>2">U>'wnPP o0deW*)g}xŝ`n<ǿwsu O:潼f{e})0Bui<{|`ܾ?__W1&{Lq#߲\u`2NqEsZWA6ADW<ؔ1dϧ3y+ GVitR8B#HEZ<< <9w%ˀ SvB4 IWljH.NVL:ԋ=-oJ#h/( J㒔5˦5uء S\SP|nRli&V 06W"w6Xt.| -+/z(Ţ-JW@3cE+56vs2c3MahU/zp FE,J ~/ʪ./>DjHO9q(95sÃD9'sd%zkrVB*Ԓ@xQ%w_Nb< 'оKT|]*bB" .DYD_Xyať)H #14.`q,< F#&R"5>/tk$z5(<%(DAZMr+5z=22y׃F'i ߿w�2zPg# ]uʅ0gQVaOWkr LbA8  *HΜ??Lq;Z!玲}lEzz:,1%^aAi:GN7,(¡1*N 1|}t2~ޤ p|<v>1ɑgTgjC%(+6I9>6ot;|{9z=7|3ss/6G7 ]. +ֿ]DPJn@'ܛ-. #%M3 ^oC<Ӝ:3jo hpb˦M/}['aVxfL )ֿ4#\V~,VY\]b;W֯cRLM3::۶mcMrඛhZ۷zM7_¥9ݷ!ah>:GOG:$WR<8N ӑS2}/p z݀VDݔ2BVD KH/̡k+d7mہ(/W[!$ܼN4o¾6C_چ.d3gi<EwUT~*L%"Y�wι cwc'HŚ6NA*A:-Ra5H!'1-h6P9 2f.&5(+:dRbM -T312x<sLEO+V[,߸8R |m}UhCP-ᶭe|F9qP床")inHDED�/^5suE+sFR( *yQ%*5둷I7 C;T '"A1Phkf ݌Nk ZNiӝM_Ssn cxeSq,oC17i~qTfYWSqݨД&jmLt(HS)? ~~wn}n.M WhI5 /'�u)E,db+6~'w+f= &o%$= V^R~1D!r= s$)BI ˘a҇Ԋ?ehGxjFo0y!ˡ`h' Ͼ:[6S)IphNFv ء6b2 (N66ɞ sQB" *fJ?PVcHENE94qEPLhIIRA:pBaO>jH7##o4W@[:L\M>x\k #ޟW{2L.rx;?IsW dBcIrŇs ,#Crt=�^İ<ȹIv0UgS 4t^^ J_g~i #e`l7e~Ǿ u~}G;'8,.0'xヌ[FI`ԚMگʉ8IjI'ĺZt>!䆤 Sr @FEŶ.s[v$, Ȥp5J!K#R'jwQkyL39Kz0++6,rDiU)yAϩ*T"O0zw{Be6d gW< *BTJ:D۶H?ōE:H2js*sw{' o'q$ ?}%æ<qliGt'c.7}\{NvnN~-S);&S$M*wd#"b*Z^[%Iw(5ѣx`ֱ~RgP6m p�e^|Ynx_DZ2! VUarRIg-s-j]v6CkgNBHc O uw ]Vl.߹Z##׺ NO>E+{=O?Q+Q)\{^/-q):Oɯo{�:&AU6!>KcϮ5YBiv,VI\J|]�F #|Ԃ3X2neJN8Nf299Y&1kǫ�+(DJ+$a"ZR5i>uWcw]0x`٩Sg^e1{VظE`t!P"y 6 FK"!i҅T6mr# * Er(ԵC#D:pVxu @Y呌a2 vmXErh,YlNyhj dFsd Ln-&-+5dTA.(i(ZgOw(*:T3G2 -$glOC2GPb5BH,97~2C:s=/-#a`Dt ZЎ,|Ռ@0# ??:2)ʿ#bbe^<`+e UI=rt3Nr@f $H=>tSSH6&T'm#0R,\UcTTK3 i(,9xbzj,hZ?{K[�c73!|}cH(7\|A.i WH/x,eۮ &!Ӝ),򭟍ON+pn[)."PTK 8$)-'9=~:dR[K)5Eehf1sKy䩧[O3OӴ\L8ν,^kS 5B`?Jr>9HEJJOw@Z7[ܶtSDE]iǒ]lQU?0<)!EuK6R9ʻ.Dj mh(e0r;7C)SH5p6B[,bN%1 K)HUWKr ?ʉ|sb'zw:81.Wu*"Mp!VzBumHN(iqgB6˺B'>Y "De m![&7sOͧ? Ο<?y֭._罤asPWNW^?=/RrW4t$i#̶I/9!z�� �IDATu # [3YburjRp9Z5`T;T8d 1h;_'B c@BB],'! Uq @&tYmŘAcwNA)Q:;DTɝ~<QR5\KڊUN38C:=x=׍No[Ot.H]}k7-5U\GVx9ۡZ[g{z/a8+U lݾVısm\%œ/o!ڲ\P9FlY- n [!]}!vnzQRl Y: %J~UkI8Ѻ}TyŃ }ϝ4A jŀ"%:N48[n>DقXK~.Oxm\-i4k6<~ Wjpqt/̐&s|_4n9Đ ##޽bIalmTDHEu?z' xj>lل<A|fa@ۡr /yltCdrWYE.IಌՕ8Ѫ}}ǎ!MRZqKcߗL׊Z4C�km7 T }Ba ~#D�JtdORu΄$=wO>)BdXmbjMLPcfa]s"R;.pϽ@IR'6v)ɱil= B5և7{lu_v8ݯu�n��E4#YƲ]eK#{J.R$RC(%PtF'tv}}5U.U걪YF'kZe%^l {/뤧=p7VpWq848BH'ZH!}0 2!VvtTwRD )վI-G mɅ~Xӥi-w1 NF $Ȥtl3TA5о i{7ʽ~D dKZ; Be47協<Ux?"'+B# k+ ZsT2 c9 STk7zQoz(x1Q@zC\AQQJbs# /ǂ؀z%f}`9)y\o3cM,h$;^"}xrY'\!@,Uq?-y-J?<YiXIX7{[}|Ks&f} L=7[F39ep@q+bVEĉ[(!<X 1 !,Jj(ho8,; [viiM/˸'>>^{eVoqyyaq$b},h%kS)<>榦]c$vsٵsP'6 y0tiiU5 QPP_ҧzX}bPD.— QFiD ^ ~ $Y2S� AaCh_Ls*Gf!5E.X堐+I9$U.V I$˖•X,%<jh^ m"L&NB!%R$@ksbx\suQ@Lh*Q|{Qέ߹ Ln �2 =R5iEH4o;_?/'%^xoxSa^. d`yϕ7`mcV5CuŮ & ja,EnȮm`Q&l!%d#[tMc#XHyiX9Ƭzh*= IosKk}5q|z$gqiMol`RŽA\[z˯%VShY/�AXeB'Q =,˰@T$Yep5ސm,9·B!\Ύ$IpΓei(v6ܖkl.#YdB1C!FvjLvxn�^*3&+gbɭ566ko5̏޺q&~YyÇo@K+@zyŌM/hSam:s]fќ"#r4LѸ٥"2X9ZeG+c[" l1{/_|}s}s<Y&;w=V>鏳2b J'^cvacǎ1L>9}Oy0v?o<0,Az7u�bW6ycE*2Nwdﮈtj49u7֘߳7^r:^V�aK099E4~\~ ɓyoPKs LE87fP*lԇ ^X2dsfl߻}_ԛx452FeɅf 6D^Z@_y E£vTf,B*6N\^* : *GWnı']$GZ 7{ ={^CK 6*U'~ ^J\hR9q\fH{K<5 ZIrdc^_ޥr+pNә[kPYH'*l2U(aW<^0~hPSwfyHMutGJVBЊ2U"2xT\z*wyAч,/bz2\^v3ĔKI0(ҞX'9c{σ~fYfeӲdX"mG1Z�縖Y:37-G/\)4&,Y7Ek yG]hG+ǭ\C+ Xi\ARup0SKX/*IzBUPV9 :!jL)V̭)"ATT721ySĀ�U?> vuVw|@ҮhЪOpʠ7J=^!/{+h)Cx!D,<͸BKa^{y&-΄}w6%0,McǙw>0$ @`L쐑wAr {5d«9"%h,TH/m<fz4̡8Fcd03Ɔ .u"".8w%�l[%{*`Ctߊ)nJjA< JX/ޏh\hxgEsL. -)<Fxr3>"06H7w6Ud|HjPc@wHi l5 =R .;R`@Ye!t/!AnBxj=PAQ&H(7]d .~so&/|8?avW?;v^c^ Νfu=|cO-hãYqaF Z5dU^z�TT$F y0#wMAKf9Sk qދ{B I= ɛ0MD9;t#'"z+<*rc'_`s V)̬+;D3=VZ9t_Ay#!1JGF�P&x8bki1,=i 6vVY>'I#WJ ;vЮ{Զj@-RXU90nǶr VZAޢ}cӆ4-WCV {m9}NGed+skUл>Yr{kU|;%H2QnLզlܳ'fq:Xa=@:rHjc{:*U)=ΥH76YwoXu+ܿ9{JU(/-[,%b8iV XqCM9vx{3nP}F`+DE ;$#綍?ni@3\ ~OxhͶ3?ϑEw2n:J ⦅Mn\YBdL%+A,B{R?`~vhweY_ߠLTt6IfgwW#LY�XC`Zfg瘛[`1͕K9p`k X:'I1/-fXERk|T' q8"jF|Q0t^d &Z\?E>#c*sh3t҂9dI퇾o枧3G/S9wpkMgo?J>Q!3ɠWКM/fg_9zB%V̠c SBWՙ DB#R}a7ލfgPEsx<Ugދy G 3} QPXE ߹kݞ4UA8E7MkTjEDy6I;�W' c<&Ae" K)0#&b#A%Rxl!0ynd}ƄJiOt$M(IH'b\h ++zdǗj"j c#so,ȰaǎҌ*Z} /D_m P  \NJ{ KZ72^1'g$!`ЂlzE`|5uB("!#Cfl<a 2㇚82ZksBwN[!DZ-qG u}is ){7#;r.Z-"G B`℠{U ^A(A+=j$V(zdQc rIb%[(iG]*gwR 4�P *ǃ$�x(ID$_eliC;e@UrZ5 Z#$($B|NGzzV* 0q%TxY568> 5dH-V5l0y7ν;g S,}I;'LajN39k0Zn{FBb? *I!Xf)M() 4Z1M8Pc%De3B#Ф$$Y2gl<ǰeQOٺR'o[zxFkΖ%}'?'ouFzQrԿ`<Bh.<Eczqy_FCh؎fT*B*M(YQ'M`TBD9W*:09;̓d{7M0KEA$(;Z^xT![]|IlC +7Zk YI2pܮBg~GN.~!?WY\!V8˸|wzťat!+<y\%V<jҚwIӟaCrln9s!� yC2pR0gTm2c4&&PӚk೟4{&[qYaa~w<FӧDTbM>;dH0>s:do7&zws@k`0;'n:s~[<3?{K=fj*<sAG9rd !,O3guk9�ccuu.ih4HӔCq9:~(BT*�> >яуz8W $l|?"N831GZAe9O!v#eGr߽ȩiyhq[}b-E*SOO!]܏ z{E}3Tv'gW?OguJJtp7RF(}w</-3TU6Ȃٜ I軐VF=?(#NQg *dRb 0$sQ15Wo?{Hdc#F�OS!*m&`2 -h U,ބDUY5HƐTA.BDUeؑ7J |ӱmc�D c=mb `*+jZdL 53Y4HA`G1P-K:mI**tck|Ww ТPO,IIjj Q-b 'JyD1> ҮD`<L6: k+}<TB ΢*QβD=w5ŦC`qOT+4鉫3V Ws85Cܾw[,kC49R{@mHX?qʂyD^2%"(%+Gqu.eD&X'H3(B/STcm22hgo؆dC5vn6D� @st$).9 h&+[:XH.:QG :rR$WH3bL!J(_ph!Í+=;HFEϣ; sdxtR3FӗjVUDZIO,"„2)$M!i)OS ( F [Oirp9֜6E c|3h8@TJ`%8RRl< @&x"\1&83 wW4JA5~}HP�I;˹PI'hn^Ih*^X,m ׶X-"BL%*sȚF,L}E9]'s9j] m(L(E3:tA&X2-C \$)x 6 V#yx^TطQ۩bli:!۲H. :ÙZ@ E)<6"Q[%Էq3yQ[$Ii�k-Z07/%PJaC`%(:zy)Kڱ~.@jASvh.rhk &*ym5Of=vikwdξwPz%k1)IGyiM6n,'IZ',}=9YJOӖ+ZleH%(8+ gbfu~ラGz?_+]8Gt^TA!m�"0adtv2 w.(vةΔNTZ < J5 _" zyF[h5'X]]2.g~<_PWދVö+5gר[t]<ѣGy|_ŋju*jTlL666:&HXc(k Nz c|:6WHq~!b w=NzNk*֡a}8"q` *ɛR2r_\eP89:ud&>G(0VɊ Jj4xI 3'7# e4R++(L>b6 ,Jֈ'`F{Q*BksA!(B�zQhK2qH #av4AE6~s^IE ajO0t$y )mBcR *MjyA0i|ϓĒV[]+н!t" ٷa(@=? !d8Gj6PCPIRys@AQA"L*S(uP*j&*( #$"9TEXC+:8GVxfynNԪ_u@|ݏD)C,igST1hDcgzZ �� �IDATtzP lJ<~}T12m)HLߖRG$hj [SSB;E"D ^p䄾~/!G穫' #'6M ]9a)]6n$A*MFQLAK4%FI x'~VjITJcK2!$dÒEPX<E[^QE6:(!&,%D#14R).D sâE0Qq  ! \!1–ٚA/BGd#gi$M Z8F@*tb ^+,]؂KqD�#DFOmapJPQOR{ )" =sijM8."P�YkP({>?(l$sy@e%5(Ā[x7( C|0*Nd x5G WJ>U V>*BA>I6`>8XCUTnĨ{fI/vEiW2hR (h?$Dl QS{=~Ll VAbt;0^*I,0?w٩$4ZHR6xp-8_A ARJ,BvQ$GRW9i6rs$WR]+La{GQ(%J)<(<@poCpBcAi�Y }ƮPE88GW+|L겹GK>x__BG,E8M z# O-V]{Ȱ�euI),yp031áoG6>Ϟ. vZ|€\/$uTeSt*A|fmlgԕk}`w]{-ͷPi$^JSgYe{ťLc#-oRn:X2&c[n U1J*dZ  Twϲ9y3gdaf<ɓd=0P,ש$-:OțI/|Nr=Ҩ5M֢ޜkc\rk~Z,ȳZpY>ǟ#fiI+kpL&8»`T(09|k?wNa,/cEJDiuyu:h-"ԌZ|I(5$:":D,KEר"T5(L`Iµ…N(̗>p ^NZ$8+DnkoPhMt 9@�ޔ&ɐJ-WwTh`%Dgz7tH E]3SʣDhh¼Ozd#HM0*sƵ[)XyP:3 pY" ;t>][ہԼI*KBo6�W E pyKOZJ@jh 2=*)m?!H{4*P9Tb0= +F cv&HػQmbQQ> p9{ Z5G#Eɠ03S0 )4,QmC %@.]LA=_c;3oPYW4jj;D$hYEH"[޼v9 m.BBlaɧU<~ƿx,ܤWEAɬgQڱMeI V  ,zoDJ cQEz6KWWiWMkDRJƫPD z6trtTDF# EjћW%R`n?& Cy92e?/mWN+VB~|StS D4>2 !IKd4EBlzG:LƖ -[HV:Of  ȁ /0^b1.3dmJh/h<dHЂT%z@T]Kh>& 7=bE0tB4鋲a-AUd/fQqsrҎxam{n%dYc2roS@yGGlLn5w ~RY[-W̑P\5&yej7�PCCAC\heA2!)Gգ:G>Cty5�+,Rk>f[Fg$'0HYMw.źfG 3�`xޅ sN(7'\YXkRcw` �yJP>L%`%(qb\0P ew,4w_#c׸s4 WosB079ɍ {nnr՗0(VXsY^Do~a\ I z[kLH}Fŋ|䱣<էxk/0o/fyu~}os_e;׼϶VhG9z}AvBNhQ'|ey}OuW/:)c辰 7:qn>G)#rL :�xNIAf^xO=K7npM߼2wϳ$x vܸv }?NY'�mu^1|e¦LNmwa?k,// 7]جj!  a׾sٖ DF%B&(¿G$s$!Pw9֚O� Ӫ$!jW;!@8 ֤'ΓAV(ڮ e9 "r>|`}8 q(Ué8wO?n>>}3߸׿u?ʾr*׮^'ߎmMpYÒ^$ue\Q?C~A2_łBt($uA_-O@TAD;%<$|.a.Xۄv7ۥ (hp(O` 4Ab/JrQ$xzheP!DH2 w`z2v=ul�oizBQ^Gs⥅lTCc(ŏ 1@Uy%,ي .Ec-{@XP OYi>MO)$%�anT5:o[FdޖEnQƂއD jJ,B][p0w|CL_`L51yЮ`JڜcAP"ڽW.{>{/` % |TPpl I_%rT) !gbv8t yELw.#LصWVDR#D8iq, zUPGk]a@`�=os Kظ!Jt2=`eG#Zh.6d6RJ,)E{([I $${ቼDa]cH /!KurC=2G>]*jP- 4p>W'Y2vm`>ԝr]PG7~h$i7n3eK/^"dL͎�5ރmV}%ů>KmR]Ƌ۾9#FCe\QpMGAZg |0Vaȯ@{Su KĖub#QSbGgzx?|Җ,1X!B,@][@>Ѯ^F+ P;6zlBŕF ^!de[W0f %#$N׈*j251O(#ň+J!Jɽ(� fm{bͽΡuXcqav\10<Ze3x,0�&iΧt2,cqGq{r; ^s'pkZ٢`5]wk?D"D/mШԈ_ H{]rIt#eD>CY]WwW8r5){I<ĂO#-N)%Xhﲢ<-Vht(g߸̚T/>"$!;ry^|%-~䇟2W/$lU<Pacۏo_+C ۓ&Ɓ;QL�x֒$UEonyػ'zf) Μ;˯ANPD*=};g>D 7n?} R7ؽ{$ˬ.-5DQ5`X^vO;(|0G}w=;|-OR}m�BtQZ{B),-noQxZcpb]�4%i4LOPb,^tV: ?W<wuDG89Wu^xe~O/4v14?s?O+n$Xֻ}U&N<p/rO{2˿lm9w<klٟ⯾ۗp>__~/|/}^]׿?9z(Nby m� d3 ^OCl2h, ;U�y&*[6os;!@ƥɸ@(H>Z;!X\ O{}ݓxH3AaV?滿oePIH[Ȭ3pTwy I76 [[SR! &Ŵ J)L`}hg2eS쌂 TyLƕpZ?Bw%lp7JY<C zhb3J4񼤖4/n@|K<T'bmKK{}1ϟ|O/6:F Ijj1Lܯ܋o /Q]gUAf NVQ{coe J t+79w5.CwvOG8Ůl 1`c`4 ZT(DI~x?"7DqU^sZ˭U>٪ҿ֥xYp`U( .qºhTDX/@)Q%TY"zG*. YwOѨ+C|YXE3(_Lc ~Q _J*u`<7ޔaO:֕2kʼse=40q:E(Chc xPb"j{kdZ: DT*{*Sy7D|j/oqab{<س]LosܬQ9|<[ʈaI/rEh^pw\Lb3e|)R1Am׺=QR#E&<JBPAEA>t#:>|hӉ]!bfrć')JaD(x<P~ ޓ)R:|NH*nT&7T&dJA+TI @`Gr'=#ϲz&$]1^m팶FRJ(b\?gK>[^�q`bNs-Yi94{<Gڤ5bb~ֲժjv‚ �f]tiչJ,"v;AO8z+\mӜIYɁlg JP(DAWY̥'EqD$<8ksMV׸u66Li:8^2~h]hn?kAq^SCM- "BxxoIݦwhpګnX+A yC<25(AprcxIW֨MtSOo03?qnO{k3Mx"Zk2c0αncEףʮ5 ")PZ`_ ft77* ~f\-<cmu~cO�? cj5"59?Z�lZV5N:ϻ^VVVY_b<++tN8}۟ RZ-Ο]XZ\(W_/-r8F->D1;d+,-9+}m,gvn9׻\.87&8u<f]d/(~gfM?+7ZyJ՛Q]W 79ϩRdIep2PłE5MwQi$2lKdK-)%rT1o98ELeȆ|Ȍx^Ľ{ v MY%\Ulu\?T҈CW-޶Wn0AGgT <ַM?'�d@[x.\FH%sT ֬FRO D0~.%N`zIhy^b}Kb3s#*Xɢ4D:c& Y9{MǛTHҎ& \Vgʋ|9_mBj^S� G}ᄡ#Bf;:u brԅI/" "Ky3ñ`V5L :)b8A!VDE4?L/G5op@8j44K$ aka&hxB^5#}\}+ba-*׏rXz}_͏9︎_*riV:!lÖ)WvcJs5Wnt0 ruWXv7t-4CF54Д$O D#N:޾,p')lrՔ@z!3aOx$cI=uB)"C@NCrJ kl%7 Hz(24ZjrQ 8d15x BIY ^vz[OPVZ ^" )ȃH̵p> 9kQ""MzsoE8enX=LlϢPP.mC*I%c Ag}oG+~79GiEZpm}/匁^xGv ),APbݺ\q&xFsß$Ih]5wq]s k56DФOSDU5CmёFDA"s+aE#ZEӚ\D48kA8,kZK.Uya:8Dlɏ9gi0^lv�BAG(3@(uҴCƤg"nFn&IXMXfGyB%.)2SqUș<U֟=j K�SX7pQB+fRy[y;/_ N9MwM ,Z fgg8l'>Df ;6N3h ]!lO4W(Ɏ"o/= &a,yvR €A=s<7ȅ21Pgp<^hjpBBAƷPQS*?UjRp$87\ϖc<鶻3E}z_Hm^ v ߸W<�T.!ygHoKz˸is� R1<:=wƽ;w*酒{s$F禰'1a!�c2 XJIZ&KؼG(z(a:x-#|GX3<4g6c`5)C9rjfttG#zζ?;N̅^9>L)�� �IDATzcDdhx K,Rڲ?I(F4.aiILϳ@T*ԪCZ]WpN0;D ]wZ#GN`Rrg5&4VV괚APD{)% %:mVe app1A@  P@1F ?,lJR}fIjrO(ϱuV aĖ[7!]F[m+p a \IhB"m(#/9+HG>FiY:vTCWƗŮ`XT2@Sك]6d<LILW!I+g(;f qW4 EM-tf0(cEGAMr^xP^HPHV@틅H4@#u[EUt Ksb sT,^d<|&+Eܓ*Dfh;ªE3Dq% K!n(Ѐ(Jڡ>q 7) MEDp H'/an|Dcmq]lD ',{P)њ8(O-Mq~>%O\s^B4Y☝enr٤:4=͏swH~g'3}4Ui%8gV! Jk?㦛of Hy[1 Tr0 E"DJ`^ ~:\w AQ4L P lKќI#b\&\/'ZzlaRW%t<|5^f'1I{0ܡId'2D`5QE]v%5) hKu=x('2IX2PaAYbH2R<uTJSXRSxNf ƂWpgJ,<�u9G[z^EZ%>'jJ7۹v.J �':ıXv!ݥW0y;U,>kI" R (ꈝ7wȺ1'+7K;Gp0a\@o@.gHUĘ}h@*HB,)DSFC-5 "+ Xj0B|Zʊ 2]CD(L>6RJj}#S.CȌBI&tNv{nN4hKikCf1X>zI)h5R ty%4cECk}QB'\m#@Ւ[)9< L.I᣺g3X&R[&vە<ē¤:8ÂW$bL_:Ï=\A*27"[yN�D+UAfl{M-8FmFɳӬ,bx_| +"6EvzM[">*Cb||.K,/M2|?Xru!3T\ųGd]rxÛ9rEN,9y5ke顬˩nݣ{~'۷_/OOp$CHG)W*ܼ[okU>|4'řS2 *"B9I:@+h(Ǫ 9h[GݥIBW$3~ǎR9O) >|ZJjH+&&jߕ4m$ p`eNӢwؽ{ҌqZHQXP,𜶜A a%juXXXaff6v0.3,ϱev.\8Gs̼xvbnzQ[ooG&)i'L0Vl'`GGY^^º@s9`2lLda~%MReffTP!JcHiyER!6Dցcr@`Š#3]&.f%5GSS'[О{'&&0%J{Uvc-J8'qԪLd"`9Գh"Ƕu∻[N )9BL2g;= &Z+5?,q$IGU0kI%Yt%>,"/'eSMZ>eβEt-ZIuMi fYQ%qǦwUcsxPsw 슡s\Ƿ!8T'"Up lM鞍h^h~Omd)xx犽{ٳc Yfy_ĩd7mm~ o NOsد"gΝ`<F WCH(wZeALlLXXSRExEs Av9\ Qֲ%(=EaWX@.2|Yp\ >hlW` ' rV^ ~{lX2ipV@S #20k< 5ShC 6yJ!XNb0J@ õI{JubEN523*V>4𶒑 뒘R+QB6I6FeH1l %$%PYq DFEU-5?EJOjQẉ\qv8}W>3co8~!:+80jWoozJdox-}lܸZm:*~#xؼ}۷`vJ7SsSɺ~NRp $u5ŢB=o!]C>7#AwZ- 29PP.tϊMHCT"BL3ȑ28y`䂗`j >;+uFC)<ƒό[lvJ%Ju&Fz,( RMGx\}V{ ^B[")pgz6De>׏3=�V-pda#G ŒN'cj&!Kږ-x73;;AT :B E K <-paj?{2^Ѝ9ljH9dn]c )ʅۂ2o?GT^G?;NE u�}Ůڑ lAs}(6LؑU_Rp1{e[?Hc\{@֓\?K2ރm=dy wH$iaJFXCfV̓O>IA@TPZ{ynCRA%Yf(٪bCfs/06Tls Ngβc2cgvWIӔ#G~N: i!P,h4ٽ{;ZUkarz0; fLMMjvc-){-Sc~~aNXcٷjZB8鰸BDeݸˮ]hZq컆ǎca$9Gh07I=;0kn"`ea-$;ncqvkh$MLjٳc7^ PZ 4ehpsg34<`#GsnffٷoFr5PV|ZՋM7$s1k(6 9jG}:O5vZA8, Z~N_w$yyZX.KF˺ur$w-u̦:d/TT<?b:CGea 006�B+ig>* F 7,B?\{IP%% =(1`f`ڊ+iw46y0/4cJž1I$AUn=Oe΋?^"wm|ᕵ/d~ŀ6Ff&j%8^H ݮдddQ t9X7.L-{',rgqe!J̢ALY@-z[8?T0A|kPiPS"ڝ3td3arz'{׿6}!?L̐XoqxrjcGO{w+wbyJ 4aw݃T333|?|s?HM7g׎- 6$ҕB(C;ȚA-f9%@ 4d4?1Y֡`但i l E3 J\-rCi}N^GcR(@ B  ,v@dFyt3aG`RX66 vgr){F[P84zU*$* #f~$0zv(^HBP~ъZdY4A 鏗i j̑<?Gm[ \@n$ug0D.}WYߍ cu[))Ò٘ff rl@}Sޟ};Wv03? [zUGewsJSXpPm:'1u +0C?[Nr' @jhN-Rv Rb'*"A1Ekvcp@w<{ \xGwznO+r ~ŔY}}tVJ ݅PIJH>6y@lD| 8YA!ȦwD Ԫ^(i_r5bON_-(NJ \q15\jis إXs}WWPa?p)(K4c,s3u{x+_efñf>Gh=0Xh5)@iMR0wnZ2DҕeQVY:͎?93_~O_"%(c(l*+)p"@Bb#\oC!}A9~-N?VAb , uY0v\jZ@p){׸\ O۝\F^rQB*V/R/q\Je|;�& :DŀPk=#K :Jl <JkRԪ^o!K3(+hԽ2N J)("pY&F.iee 6me6O>yᇩTKu_%Q䉳T5$Fy#ǵ:]6V*c@ &'/0<8/ĶmۨT*8 KKzeoadPjjqޝ9N>E T%83 $7O0;=@ӡR.eFzbH&bp-[7quW8ŭ`,,,�pLMMruWyVJՀ{_jJ=[܍% :@ EO}Slٲy_)D"(Ƿ5_\P$԰8/9 DvH@i d!ww �2%Hgsӂ'u B JFG":L \DY,Y~ʐW, k{1F ?i&ʖah48萑 Xִ}mu5$[nmF, cl:vSR_ Y$NB#'*$af/q1o!JT˱7y.5 ޸>wRĹGNd&0 A$BwTEVR~jWGƫc6C:0rDAAZK}201_sGTf32 S!E#6@˵kG|\!5Yx~*c|_c?|#ycEZ,-7'Q( {>^y5/<[^ČV tyvl݊Vzk֐gH.<�ݯ ˄ 4*&H*( +L ҦJ0A wp5Jƹ9!0"kpD`.vKx1^eO IH|]1 U{(̠A h& yOSq$nL(0XRU8WB'ƫ /hMGb\e"3Tz죧'=)4�X^^}`Vv Yu+z C\;#β4,YZc|/rٳa"_҃_Ipy k𻙼p?X!<# ݲn{/Yxp+ބ##DFӻ!5Ǒe%Y"PH#-Uy2L.\ XʈDtA6VpT~[9]",sKõ V@YH=W׆3ݬOhs-a1.ᖚn! ?sTS^xS85@HM+#D'AqxPEu5R`}-*X \Y#Bɀ&e1I@ߍL{�Dk=sV1)J)K,cカ*ڪ~ !/jM{\ R I։9w4OiV AFy.wVFc,:mjEp~-ۯO\HjpGh: Aٌ74f%i,̙MaBK$"w#u.-`&ͻ0IDϻk�S$uI9U]ԏ&*D&o~fBP:yc߰ ɺ+?u gαc~<=w~( Vwc*9oo@гu.1 Z2dO®8+5^>&�wl3203t ofbTZ$Ia6><I'aۦ-,--Q cX,RXZYFiZ4X^nf]1RDLLcj{7IX୷#G#_ett$I'}75N8-7+ŗa:! n? ȐFI&,c_=/"`#^9ukjm^ӧ}Ͽ8ػwa 8kCۦ<CHSGP(xp!3Y֤I8/|j-`='~JIsWE!wyaxpG t;v0gb(~R޷yPG7w%0d0uzË6E}3{/'8"A8M'$λdnF2 phOv Z!.D(HEm+(X(+΍)]φ$ÚS:r,o'%pGچۆ ?yu9s)Yu`([CjQ?`yQ1t2 ji>\i7AE#, ].HbƲdq9`ےkEǬkd0T|e_ $2⏫ LGzyh)P7' S^Q=?_iGZ 0Ջ/72lB"G8R(5GcUv…巟*j؜" Y8S\G :@dCm|mbmFP4tEt'!}6E/DؠCpH+Af.I&L]8O@fRp۶K+<>C;z _by.FKEh, %*ذnVXC\qv aߎ|+aji﹛qp^x sg;P?(W$AQ]J%f@ ';ApUHVNHuy|%z!"u- D"c/)ׁo$c-Cf%rXIIvMpU RJHKtJ((Uה(2@S Nb$‘xDY@M"# DhP2$6mpχC oc5BJSD! �� �IDATҟH# &M"i==Ex+i~kN<q)c|{)};My멃C_}S"??3O?c*yuvXٹ׾NDc8?A'Gw*edhNv̥~oҡB /k"@ n56Ŏ Bg"BFVY!])\9LBJ^û\ |?aڀL "P9^ņo f:F 3lixE o1C /hl W~|i @:2Ӣўd³dn$86Ȏ-/4C1gR)Tw'1 Opg%8Gʞ4B=u)`-bVkWiO>K)_~&?G,K6w'Ȍeksa.tkH*lwb-̜fvrZTayN3ѯT=R 0)t3G) AsmRP42dfjyai�(<H F 󝃼ryZΜ:U>( -{nM/ƂJK S@ϥS<Gu`_Ue[G c\ |'sHx9^<ty<1~zJc|X4I(@ #Guk9vjb@wU!zq09555cc|afz oy[y'Ǐ̙39r[of? _ wXJIKݡT(#im�ZZk_Z.\J!IpigZpux|ױ86f(d· @s~-I\NZ% )TE8(A.(5Eϴ2Drl2^<Vi_‹D*C8�"ϼz}?o5f8l&('>'ȉkkwc%-X& 9J8 %a/Y&F ' jRTU\,Io?XP~.ł K I -Ďp8틸Q 5K0�hA %'%MrlHZ;e�GP,;nԟKCgE2Y+famɜ𬊾kIyڡ Rl* Rz qmKw^(|.h!ous/W:azO?r(L^X?ņzoe`T[!,; I.`%<za 8dq|rT3XȐs) Q[l|0+]L%蓎9 1(92 le~alO^0<w.1>:_|/=};1ٗ! D!{m}ok '<c+۴nرc>$#.S'yK$$rA �1 )z‘$na!e lDDQȂXX"]!B zTNk=X͐"9kVSN@A͗ 䆔Tf(!Q5_` I;J%s86 6*`CZK50) 55gIUJxDRBT͔)a&4L٣@wmޚR[@O3 XXp'lI̒H.#u W8 4ع>;�pdY52G,3gxs_dq/+fa4Ļ^<*ۮ'6o~mWoE|o]"Pҷ`e}'91u 7.:/_W\XIeB,Tdǒd!DCRj+Kt9d)Ȭ% u u {`" jy{ߪ`_tl1;bWd=BmhLmVOZPiFG7Q)dP!fTѡ\0N:q&ve-*ZK/~g'UX<ْ"hiH)sA^gYvZ"?~RWYc%~UK-4<PRoPo' G}!0}&NImRdaMHqWOrŞ8ԗ 2PQ6iRҲ1Iqe™]RRap*D#J/uՠx/iiM1\0HaҠFBha#Lwו=q*Dm h=ƍYO./SR&E3~_bEc|o~|q=3Ks WaB,-A;t9 /y[hnw֛5{M:RG C`hxT,.,uչMKM!2QojXkPPxC|_~CY?Ԡ\GuR1W_`WolbhD$�Αvcj2&&ٸaID211N&T5Kؘaʅ"X*wi9J)nD^i"M9Ź( 57h3rj�ހo[4bVEnfʏJY6_:2_;=#4r7?o(OWwŧiAY慲?ҮY;ӥ uvk#E.N)"%X?dR1[1mLS|(ƒL$bVIdtLp}RYj~;AwQ2=Pz&P㵎Þ`]Eq�P9#XRoH-JG,Anf1Nҗ31[,C r^#m~wfL/b<H]A|T7e*roD$ǻ*(VsH%^(%06`J}?⻳fu~BdBqѲj Y4?߁s  ŭ΁lP;:bP%6J8K"v=o j|O>ΡCر{7&<y]wn§Yn[x才T!62{§<BehKJ\pcqYyinVV Ysg+"Fv$$k9ul^U`ƽ`aYb"SV8T=&@"rzJl*^V{,',hZIs7;ˈ΋\@lPŐ,6@Y,&e#{wuZC&d&qUQJʰNu)*&.4S&fIbEXMV뢔]K2VX:5# lTgR0j�9K'͇ᥧ‚ƁOĿ]Ek_}Vp3Mfݼ[nLO^`|'R =]^sϝ :_+893ŧk PU2:Ff~v #U'R @(k-B4d9$75^@5Z>P E"8*||cujp#sk#:Gֱħk36ypN^Ѕ7c2 d]�0uwwhLU%|.aX\{G?]Zcքy[A/\}xzY`˃YR~Z"clF̻nG3eu{7oΙ5&E5SUP -�E}EvA[Jhh2(CQ@syμ^csD_<!`Edԭ{9gY{P lS~5t'(6xv_+Y:@c K{esP2Hn}$;] d8m1^i?dk]8Sl79j?_RNvnR1\js"cl|[Z=;`k 4[2)' #6GuhnYa# >|d$jJšdvG׎Gt QX4A4t^$ON6<3x~?d+GEr'Ï=pXj!Z AsQ1k9y41U!zC SNꫯ93O?k^>zaW&fxryI6HH1FD#bhpyA#qm+LOD0GTT:`+-_-E:_IO,2tUyg#WC۫ԂՕ(QrxbbwoҖ Zbhm4-rF!w-Z@n㝃jS*/կ7UT糧!�q$0taH(9 iұ pg{2Mdчw!$09!R ^85X^t Byi/E^R˄@uρ=Ot ; vX ߁ފh%k%4hW#mؚ{��]ҎL"w`7c 4G>'.3fV K᫩KΪ5 %> QZ%^ H7}m|-gXG;35 RF؜x],!@RN42\iK~5)JP;6=U:[@mV4@<6\؈5H XY.3ؠHV:LJg V!" !XhSCgm w�2i+ekxy3ɮ~{8_ۻ}!ηWq>p/J{rD|=o?𓟤h1\'^^`$eXw t}�b@4Cv) i*zN+7d/u*o#zTy!$ݚ'zCKlN fAS&X o )IC[Vͦw%ح   D9e ! u Q%N9E6sJ*gDGaQ\2Exc;?<09'SZJأP=z$$^5ٜFK }{ 5\YP"M3.#<1+%ǮFYbtW,A['G)Ultrw7SRD <<зbG~q)N8?^Ikog8sh\Q ]4oތ[*5 r&z)%`GlH<nk:XF8T&ds- QP"-!vs*F>AF8OEɌR BA3VƦ1!Rmt1c!T+Qf<`e �c!XK%CTm,!JtJ%EfD+yJ2ƜX<;r9 5lHPDVd6e֘Su!k&tG6@@xN.)Qi왻 )y`m7^CǏĆ"ujb;o}q/uoz.2v5%Pk_BNC4 fv&cnsՁTn0dB3=098qb�IT6M_,QI1Fdи?\><mK0};y M_\6넨UKX18E`P=GD֌BGM_}];Ǭ 8"Z)..#]]<z,1,Mblb <>»뙞`.r)}'i$il=zFQ<!Dz`Ѓw!D"i5&A+'MSoyVWر﹇iVVVr%!gx~+wlB(gy<ziLOpQ6obfff [\\diXk&qΓKN<*ei1~><SEA>;WÇL19!!8bHROujYƩc]wQ9J` z8W#kct]-(,Iqe1&!D�ZL`Mn | Q$IdM:|�RrKp^×`2wCL#xO[~ۏ@OO8!y o4D@! 0`=݁gކ$Ma͙Ӛbt:wCQB-{< iЁŠ˜*6iWre*JDRBDZ0)VpZ1RFȚdvk,<ƞ&Uϩ|ίK�!4ѡҺ;=xD/p.Wx{d;I G#,C_-c.c"IhY5un7q`2x>[ b0 O+Q<35Q.u6x6ƹq/je5&Zks33\cϒS')`9=ߺ%֖8э f]A6mԙ3,-]8}?OsQeydI5S"^#|UYWg)Yj (fE2 $>W!2"b�Q(甆):MIUT󇪳髎s|pm nʣP.!R(|a$8/(鴢>H !\#] .n #�12YX,<c-<[BP!A 0dkD;NGf"vs#!A6\u 6vm$ҳ!l4L!]{Ov>|C𶷿fMYz}IB>'&xǏo>~{}x{^Ó>˹SWs{ŚO"Iw0i̮(k)TKU(SO]jsMPj#2P֐DU A4PF7q"�ڄE`^q"JH rrN:V�""A!?pxA?^2L *-ai,FIt=>Z_JUTy _#\tBh� J4J%JD PC]C|)E;o�0F߁o+l*{Xw�|֊㍯wm/ @+ &ڗMQ0H4<H(=AI"eIkr_~,M9s4pqVMKuԒNkLL&65y ٌFɆ=$G쐙8JH ?ʮ.a|6s<tWP*BnA'Na-u+cܨ5Ͽ܎w|cwB}׼_ ͋Yߍww`rx)@=qlrԈ^}zeĢrP &8~'Ks[x/}nI>C7$hO QJ-!Y" Kk`_(ݍ)~rq&f'G4jX=nfqFkvB{6~1QC-ʳyϡg~IPi6ƙwK?~ = /\�� �IDATY:H#?͡g9zjm;fp;cOZx T%窴M $ʓm<xۤ!JRmc7_|&21dZi$[K$ĠL{Aj6ԴZ|DuJ.ٴiQR9v5`3 Lf}vTj8oc\mD*CSC8Ѵ>Ა[(7^)PS_j0+^: ΐ$k ܤ\+Di4=bKf8^ } S^=Šohb_ 9XP DS:HV(ECE,?jjj&`>N%QaʔrX.n(In_ "XOpBC-Wy<] T!#&V JHCBTM?+8ۏ5JBȄB X`p 4_6e\2Ն�$Xfb@j,)o{;)W^y^nF0KplN1KŘV{ye(mK1.贗9u(XZZT@gxC,,.#4#'w$8wr@e?= k$.SJV=~Zӻ[۞]5c�N9ܤIB1|T B:(U qs5;hp虤hLky+<2dA* $% <>8$cXrUpހ.LI Պ:*džB!ae Kth|H N9/PTObҷn"Xho{m7t|bW$B3j+4h3FNYFɨY( VÇ8hqƿm3l>SĻ;eS]*-o7qO<{;J6[8$_ ?$_PwweX/p]oގ? sB=!?;̗Z5Z*K+Pژ6$F ^;EH=<t=zKe" tS)яcXaRI5=F(,/1p9p~ 3Bdpʁt�'1CL.k>m7՛Hu| o>>c~m[oavJxRAB\TYZYN~ɡ5ťB1T07m0g]ۍlQT,!̣qwAFIkc+o疙Wp~aOiT\S%Z}ydE6e=e饫j1bf|H)LlI.-py"L"&X#!v׾&Jؾu+_&V|eWj<=üU?LMdz ILRѣJXPd3E.tX[Y+qրupl`ߋ'7kty*&|4�^& c1lʩӧ8�f4\yN<}<e*0̇?pg7z]|Y~>(Z98*HQGeZXWV8sW\}9IpQfg)6]{ NBpрuMTN `,/tLO333C9*vmgӦJy^p ^8pO|G~AH AUIW_M{шb*]Ru-}ݫѺjD@ VCFxoV>Ќޭ1lW(1> A 2 0nf(&k Fr8GsA5 B,񡚐[ɳ0,tNqbBkOgjzK¬aP?1°<&LK},sa4g#u:.k5p X>1~6J(֍$&֏г<y`Dt ,F:5偧gb O )0ыHf fs<V)Щ'I.펺 '5"Ӡ\q̈́"U0t /^zE~rH M?г)h˧G@gS B`�t<L6;BoHߺ<0p@Z0JfuRZm{\@[h̹�w$\{܇>繇Eē(A S{yɇ\qsE,} #d /JRvOk Y4=VBH2` $jsa-%#7 b5ŌQT%Z%₳FǤ,T?+Eb 8LiSaxm!L5ˠV&t<*OH%zd�(FB9 0(Kl^Š%Mxi#EJob!fXGxsQJӡlE-P|871Ub+j DR6[|]"KW0Ա>&^|& !0 #@heV+V]Wqͷ1>Кj16y,6lV]n0!gP|O|eld%{n/~56e:,> yQV}~:'xp%2y߇8f-,"&!uUK@i&*%";GYZ^hFc(|&CzyX<k2B Q _ٍd-E= K8,PIB@mfQjłD;n4<s+[s'h jf+=vw@5IK{,Q+8:CT1h񊈅UM[R“CRhqM7$"dæy"h7ڵZ԰&m҈l,׻Ց~Z+!|pFOMx>#%Ng=f*b;6?~#̟dMGkCVOgGޥSx:ε7 xYN z/ffsWu 92HBN|bZc,--ZcYUFA}?oy9p(W{ބOoZL h׮ *HEbPJŒx>V{O gܣ  $ 9u;PK,-.wI:E=ʉ'9Jkz+maxNX૨ =$Iu@=yN8Ac񯰅#/|KgΝr|{玗e[uWX8_36,q`~-lfj5-+(RFA@DhXgkø_*y2@^#r wrRV)!TkT (4~,ijk x<S?ȓO<ř3g[+v87wqR9uj/ jYc?N[fgvûcvs8ͣO<[ P׼eڹmGx{㏒ yE33Ao*LeN,( @T E452P{/JH ֦\Ċg[jyU@4&j..mX3b.0+c0._J Diȃ++l#%P:^7xCbg$#q%]7h|0ɫl4pA%$6^gJhHMf{bہ$8�炫N!! N1m{ Tqq DN�?&E)`|o 8t"h1)OyBѻYCs@\u!ezfg)Wf]$?̉tW0D>NqIs\F v%>y1Qㅈw "U$;$s>0usFo9') ʑ |܏^R&6QQn(L 1L@{ZnC hI@ݞ~0�tJW   p4)9Hál$B yp{8 ٢,O S!&&x^r{&yJ�A� $HHmj)D`@Q+A!QBPB-<+ ĐrأZD*HI@r.ĠkļzH OnW~;̟ZI4bu "nړcUN:G Qn~:|~8C4\z'h2cw?I@5=ڊL"ZMn +z[tV,L'qSxUDo$GeУL<I@MWfBB<;G�RAZJ2S'?ݻ\>EzfgzGjSVysJ2b>< mJ6nD`,c ,p#=xg=Mŋx#7?HU8S hjy2v]ŽA|k!IZm@vioᐲ@�[(lm 9EQkVYÑuZWek=v{H Qe5>!Mxa;^|M>=;;;eNr\w,Q.6ʋn>‚ɴ=B.SX%$U,XPDQ^%\uQ`>ON\v%o|4T,J5e48ِSlV4c5 l:к.! !qM D֒ P zW!B@Z=PzC3tyGx"6KK+bC5KU-s](\H1%ز:WPF%4(#Eu(k+]81X\b55ONseWR'-oWMs'CV_L> D y>|Hfs.v޵56*+"B^o?v>8{-tb 0pA,yy7pnxqC2Tډ^ V>/g~O:nE~/}J7y}$]9{ �;4G~;'?KH<z;t=7s=iqD4vn__3ֿ8PVSu칊;Dž +>Ă|QE)]Be{Y Ƨ>3Ⲣg/tA;PQA4Ӷ]q*}M =dp^IaoAQ+RJLp}&Ag˄YO:{TWL\ d%,vJVu" b\i4^t Xit5m+ޓ8;Q;G6N.)IPxB#c?f@WOlM[eLߵHP7b<=G4-_*JK-WzN iLw'>:XXM GLowkɱ'~۰7\${^oʉ>? 66˞kE/+FNVKc4qj}Y?X7ԛM^a}߷ -lٶNV)IW,u5tXHj !;uOTS ఢ2ʞwل [*c<%I&#-,~˫nOQȜ=ۓ=' =h좐z+5㷴@4y$Ս.ԈQ*!TH7\i:UB%Nl `ƫuګE(KEm,cޕXFcX+Mb"P\%+P]T-nΐ~^NZ)U"/|Wxo7wWJʲO^ќ1!I4E<ǟ3؀qqt#{g~b Sr} BC %EE20$hү3MTO eĖ&8U31SPFy !T]]65-~Pn}-Iί@ _QBel9Bwyu}#=%N/=-35vI@4&�črY%{G_q %;G8uf/y|(W88d(A"яzE Pۗnl,ĝs 5֯(Xe)ZFl*wQV1YXmѓ @ӡf|g_(nΏ5s>UŷY;~pۋn\ ͝Z8ˑ\kLx.|yg dF}eW׹/6֒C44솿{qG|1@a2n9r;q^䊽 9xF|JX{ 7x7WHw 7`?TJ$PVxxȫ¢|kq*fӌmK_UB=Yk1iyΜ9 *R\QN)Eۭ\l~ s~0??%9rJlݺ+/~.jSa EQ2>>5/~1gOϣlR%KK2`ann%etxٴi}C/IL,{ JXY9ϓO=3>tn>2;]dMk䦲,)KŎm1:swo^8ԖYy x^CO|o3m|Y]Pnbqix:.+mXpu/ុ(Kvuz}{_szۭD)f729UGk hb_x4S!+&J)F&!5YۿUD.f3s܃r~#7npQm`Wf,[q.f[\WZ^gd!x!( -HC0-OcTGnZlzg0 UbY"ӛ`<lbҳH($%Xp+NK0+S Ԋ(74 ŲXz@3R Iz<2\jP#+0z`/u�ضI 7W要2!>h Pa7S`߃&D#ZSN{/tg߸@ NؔnȑR?AGYJ^hL@4.lci#(3 a~=Bo5o95t]Ol;i i0'PKqڢ�̣TY }C/q-* örla<J&Ē:ҀU`<J씪tMs1 V92a<!Gzg߉|$FpmC< "4n-8XzB^F:~QAJx}֠T#q` "INH&E<v0j`GP8%d٠(Дl°QgKȪUui54$-4k Wq͒li_ƻ@FCHe} _| yΜ<CX\aˀ+ $B' A(N}OXY=WSԲ*> J-㜦v=ȕu($uܱ=X'WHfZ$:vϤ_ꔽ6˚)ERC@:(mP92M4PYjCҁ:QZ ѤwQ™j [5rQƤ}yD͐<?I_*nH,kW_·�� �IDATtv|AfJǂLF`^?4'?Wu\If#zG�ZX/kXd굍v V^\, 7G??1Utf"Uk:dYlKL!MЉf|k~>CӼsE#m;Sz<g6qۋY_p=Ǯq�N]Hfc==g_8@ps+V~75}eauyB+њ2.\y !Rwu %:&sQ''~O|͖x^[gj:[lY Y\X2,(j uu~[Z/#D/ a B-Blwl#'ΰD>, j{=4azz]w2ʡPi^W]}3pVEQ, 97ϱ^뱺f161[n \!CZ;wl}}cz]YhXQ1/D0Zkfg71;;KyΞYb2 +X8-&Ms[.,rI\}68Mcʖ~uYnhi>'{8p!ٳJ5̱u& c]jB`ɝXE"t,Nf<JB7m<ڲs dɆ;!ÀsOzD[kl{hA0VXÒ)NS:>"A.ϐ�)^\"K(PD-czչwH@:~ע}Bj@C^A^j1(O3Y?&@V B1]KP%@y܆;Q0]trAqtŚSF.�+K8l J@Jj 13I'XarO equ q! 0,ᢧPP`p ڿ"9f34oIpEI80 }Se 沶!r�"a5ˋ[n+n&I_q/ډfǹogЁjŲ!pA!۶ma檫زmS4?яPXM )uZ<xk0YGYeP=@5z/t ˆ,mPv=5u(7'$' uZ/n J7y$Q^m `. {S' H6 A,D {l:H/wkRTP0v5h6qM=5l'h^,hGPN ,#SIGEG re0aJɡ"H_B@{Ai"Bⅰ} K;t߁p!|ZoָM>wW{u5oec-{p}uNn42I�D1'*%KLz,klIȥQyF.WyƪKeN(%`Kh1E H F9{cs}MjUUd?w9Zؽ{Me$.!]}/~1NE1R-7{~e0Ep:N~I)UҥlIt9:ۅB3qY|'d>XiCZLjPd)L%X cV_In13Y]0x6h{;Sreǖ?u"m) )VDWױ]딧V2 b(Hu/w>"61kGqDmը�B1רG:s Vi*j"�gy?ߥ6q'czy>0ڿrLZnR;ZfQ2z9U+W ݪ3Q&%gEoc=~xM6}U ֒{pG<7ܷڧ\wCJqޒ-{3m#!o~[bhN73 lM' 2+F? #gEuE>OjP36!vU5>Wf+az~[c3kF_3FbmNGR<St]/~cħ=rTa8,u`HbuעzbZڶf=vpCȥm\zEy:? KK+t:3 CQ<򕇙j3ncXM9R+!T/x<SSSSlll03Б\| ֘L0?1Aw1< B̴MYRqd5s@֨BLEp[nԙyN<jJ Ë/FpSrN ^pP[Cǣ,5_(ݵ B=z=s  o8H%*7(|�48~>c0zT5Վi]^9 I l+%JM s  7EW Km@na0'dľ|B6[hvu*e9{dNL_M�\= kUKY6h*IelKoάDų' 2^$`HPF[ԅa'Yx]BE^Mm$(M�AGDɖ;]&|0p`d>kh޸ UUtC@Fj&拳ڂyT;?Ez :1?w{ zT /9z Y >WвH-4Ek*(P]%.Űm'Wa~۳ㅧt3PriV/$i*J|>r7sPA8ZGvATTQwQn[6a}%R@PG NJcxfPSZ:H\zE A (jgʐ]o%l2 BBR@Z+fWL ]E.[DQa1n *xdWza*!8�!&\#ҼE%UYnQZFhUJQSW <PC$ *RIc̸:q m9it*3KȪ ET4' 0V mm-w&  #Ï>Y y?\ <s$roN<=6PjJgl{k?&"PBP\blw3eea% J�J_E ;ٔh+&M]-cL!&!&@cqRЯ&EtHLV _-hbpO薔&%  Nj.$)]9*-|=қQ"k Q%V AlT*7`MgH7u`<zH[(O&|N>Iڸ0Nh&14n}d"9߉9An&$0]|>ioV+OrWS; ~oz^ayΒ6/ Q⫒P)^u6ͅl~ZFl^yF15[�Y[~k59%0%5(s8jF&Mc Z3 Iy>s?ͮ3[~'ѣ>Wϑ9$P =n"JBjE;>qmNn]};o9S/4jL̡?>.:VNp _,/AQ YZZѣ|HOٖ8kI9n6 ʲ9o>fffX\\`ypTXΝp#B>33 ÉgBBcLF,VoV>$bbCxe4h 9V-�A~*UUqq,*7, g[ӰM454ֵw%>O]*2 ֿ6sQIgk`E]YȔ\k=z(VK*h/VQˀn3=I"80*^rKJPTVJa ,K+Δ!\  &ꀋqZr`AfBxD[@(3$m"0(-/x -ط�r~Ԇ E ݴo*؀m)uUq_7ƎEpEd0!_`اrJJݔi;^c`af;fjjؾ Hᱶ>&n Sd؞.05\ 5zt9 ;H6A( ν*g^bk(KMC5 4uOPVkM'2�(2>vrm"/GӒU(kIXUL䂂Q|@8U1uňc_!;ӰX6c!G݀0A&PPeh&zZ*? CHwV,=" Z@%)[uXJ%*˫x5ƶP(&JjeeRTHӄQ *}xc"lH Ri &5|4e0�ikk;nbՉe:B(8(/bZ':7bB6T݉ћGVn F|9 n8Ʊm)ß?¯kOo{ԓnS:gs0^S׼u=G+Oz>n]Y?yd, $iX ɡEnہ[h5|jQ4HEzpOQ#e9Tr' #(Q]l<y/& %T/X)YZ%c 0Aih+{17TUW$TZYV?v|Dk[G5sD+!<ZOTʟxglJv$hMk[jwz>Imżwj"!13<sΗ{nul7e޾ȥ?e'?q[~x@Uū0$(Ьc:g`UՀMR?oldtxL2=&߷ ylcpolI**C̢@j;qѝ$F)Q1<;·~t={9c=|EQdyB⢋XlL I34ȑw߽9.;G|:C(6菿V{ ksֻ8S勴2B͊g΃ MȣO){wmc*Oر@"vpj=!n$:յ_~ =Q8Yp[pgGF8r:fffXYY3t}qLSEg$,gj7M k=TEŠ2;?GkpĠ d,,N3=pHw($>ũ'M=,k&1UhBe,5Di1�^o+S-%dJ ab ,t<\)mgj,2д,0 Jmh^ cDXp]ybhcfJLVJt.joڊ#֕ I`XB, %Gr�amqyRQ:[ZHCd�4t PB5Gc8ۘqM}1B@zP[dTr)nI6M�I Lg|!f[43HqqfSp~W0^ٞ`|}x:%kT$37st HAoGicroHA'^੧}vZT-`}Nνz_W^M]� UR/o~C?~?S39CzGxtSֶ]W18#T>[QԔ!JENT@/e"PE R;RfnY{LA!-%Yazezo/{_ha1ZB{g(ԾmE%{&]*k$xIS#Pv1hр7"u` h:@BLCUDɒ"յځE1dD-V:^&k%O֏n#[Z_^;j Um#Uhk+t{ y=[+si="gύX/#m xo!-F/;wәoc4/ѹt},Z캙45ڼx/"|G#TBT5PabJ(-úbwQM%0(G"*(&U}U:yǶw|"K FC%|{RОM2K%˟{zB0̵s<:pSȁ{y_:E Q�%2RmM"#Pk/Ȉ,uKj!5n4=ͪNg2 ] 10&5%U-*d5 \?I}qmfıTg}}m [f0X,* ԀCx}vcG*y@gagw+!]1\Hcs0ܾtc d\@ :#}yNˍ1[lh�0_;nI-LquL|1nxϷo??_~ !%Z1ILRcpH$IH Ag"|66#a "?+4֒)QDVj1%QGr𺽔euUC"7Q4EUI'$4Yd׮p v:-3;=þҔ($1i\BfZ{T`>;zB؞K]C&+WT˜}{صk7<̳E޽ݷ RfT !PUBQ#PP,_'F,'OaS:Ifx{dED?[;ab>@%_@hY,uPl@w%l2UHH/P d?H3%@9a sXܮN*~ `aOL J* ~FW&mӆ)} +m\ s,�ZĹ(fd*$uR-W>Dƹ@Z&TpvXH 2[ v4T1Q'ڜB*c]a1VH]EdpMeh9X|)+0NXA5# vc֡B9^,)H,rxϠ+5P _;?^ـ֚rsP,URTa h3yc9g<ϟkUL 73CjlD7Qc0sv| j5rSAк^�¥K|ξEK~%nOR<Ip qgCDv2j@BcWhfyĚ8 Xin(՞wWCTxқ-V?c #?Tq {TyaL]Q �vFi CYHH=#G< FMgD7%M-vH3\ʈe`j|լcՈ؃k8ȫ!q# UigTmKeBхz![S"I;|Ur9μ27gjj8~ \xRm6jûk*` gΜ&)=ewgk&so~4`-K * V^jŴ. ?vl}y@n)Ce":_ ^wL3NW JK(=s?�JpJ#ݸ۝F=L/eYQNo5uB$\u/QE"e؊-LQX%:(:"U`ytT x&0L֛VP' eݘAoj_? 7Ϛ|n v9 6~$4DJ,2O#09*,. ch z۞T�� �IDATkx˼=m8MA_| {3Z6ĎZ7ڹ5k IR3&ˆU3h6gP_ԠÖs @/cpj5Jk[k&m;ض Ak`Ҵ 濾F�h775NLL*,#ˣSUU8q۷v9<YquױUU�bqi<'@$\Mǹ[Z1BVׄ9Z6eQHtr{RV[k,F,*en>~NO?9VGjm;~Nͱg.ʞ{X\l c=F{jzoȔrI N B Ms'? TK~5\{�Ct~h=#kŵhEʫ0B>]26^_ ў/7+66$ccFV7eRΌ'5ໂ_W2=q}^edVg(@Qzqc9ۏa!+lF)in+.7<M #cl(/y\d`ۂd$5'`CI Q"kS?5 45[E0T8%kyp0bQ[u-C<.7$x"P5*MLR1BТ^>:/I;Zzc dcBUx TH E7sGW6_TZ ҲILn]u9 @⃫m ˕'�_K5];Hv,n2`l*Z;9<x?/<K h4nv6UD-!x^x=▻ b*a7o0B(j3?|W5UR=٬J00Tū%GU'bLEJh7NAB큲`^ ş,'۔_*P�P'KfoB&L&4!Df>N JMҩÈYGw%ܐ�T/|@DPY@Vx X8{Z_X! :J騂'h,/z)Rgl#qmt,~-=F*Xؾ>WxA؛fX]y|Mr,SoGU!iڅFHX �꿍(O-`6?d,f`\]_SuuZ:uF` dw66vsƏ:Ӻ~} #CPE@D�3ݙӺs;aBBk8{[L Zj]Mmr3�Esφ_$M4vthiDxY&Lp-KMMI4%<oӌ^iHV7f0'\]j`ESэ-c]a8_^KsۏV ə/y=r.E.=y6Xx3.(L)J1s؛ ?N'A6A7t59WW(9&E"m`SKcQk>iDϤw"'ʥu^<q__=wLQ4ZFO2,b+BP?Ld^G0MW< 4x4~}�؏}%:�ᐪN=* STUnY:i8s s j=Hkr2ssz-q $l$* b.ms,k! =033CbvT sxl Ud6rm7+ I(],N[:ÈEkD}9XKUԱ(!I5$ba؟w#~OXΔa]Nug0P34A"|GXS޴z{eiSeCCt@劗rby| vO&J@b{scD=( ;z};%~0.CUH;QUec:ԇnҞ $-Ŷ "m80IxŒ�g@_LH Ғ0R3_-f,/,{V1t֍3H%xyub?$٣Vx ǜ2ƃn�Γ/l\I( (<BZ _z| OI RPZj" la`|As"DbJG΀duť33eK!y<L^Sa%+C{~Rr=Lۣ<D؍pYyi^|y. 꾪+2 4^l?(MK" 1a'}$:RSmcօhSU< WQQ@UZ$o! Y|o0oV 4``=cl'pV1!RsWX.x|eU냉<Uf 3U0h!bcjZǰPec2AC\5bx$ ΐϵ)W99eI\(#nxhJ*Iliٽ}:|?.Xgp"V (W%.2 cuh>{'�ZLDcebP`xjuGiQ[0k]Y Ym6>קPCd= l؛*& ݱIbr^WT HEt�B9f%D/:bchjR\u⠑.,4YCjG@B5zk!HszmL~ǖL&0]jZ? rZ܍,,h,ʶ(v"t#?*V3P/`癊~oBr:]kVIBBkg빕e #&{lνyk+e#coA h>ܾP3 @Bcـf5`➻>!|;_Rn9~##Fn#Lr'mhCXΝ;?礉g?Lϴrh44{8qUG'~}#u0.rѼea UU9{VWW=03jamVnG\O+ LްDYm۔EQ2B7gϝ(J$Aע:<%ٳ{L֟:ǠG5V '�Tf,t0• | _;{+_h+^Vd68&?v/2ڇ;dyٍ(X~f�%P޶xF_(/冔Gڰ[)N[IJi =}ae*U)&Ƒ3Δ}XE ^xUÞFI%7bwc}6`{|'V%#Y.RܲQ)iKpiSsqA%(U% E9D.(1 enU`^rF\(WJ%K'-IfL<,poZ29ٗc78~.(&j KW e[xy.ǥ{:p06ۮ ,Lg38*5`0CwA|A]󘩔mG.^}\.J:v7|?il~;9rh?<#bc9o/R KWxoO̧?Koe,xLٳTcFQ|S&n4-$8g~`%T%E/`ZP% Ĕ$ �@X}2/L^-Pm^j1x O`!m*Q܁ b:8Ơ6`+ Gi'L{\gמ>r@d@ ;ofǭ,sC:Pu빭*-˥~32ŒǞEk4FIB(*%uT`%+@jʺ@b FaUœ''> 7gK[ƛx-wؓO2( {UתćRBYym6n`T]> >d5k'p],"h-9B]7WLdH+YU&s7p{ /PF>Onc֣UdgyOB:B<id[$ +5PLp>0VmEIIj9:o2,(r(� v5G!jB (ŘTd[;Xq،MMI|d+ `kFYmj7e!y$I(*^}w{g-y6Z* fv.RM=ŷ;Axe7E>aN5^Wgoma|lS_cLHtBصk=]2A<絖M~֤'ÏG?#N�$P:+++33=x 53,/f0nwxṗƛ8ph(*ωND3g^u{ؾu$ k| ky<B+++b^T9Jx,z5׹( N<ɾ:9I|5j] �gX^ZӞ5iŽ9}bd!Ts,y{055 ĸ{azf*3=r85"9LeYCWl3V8Z\9.^Y|.Q\0߲ݾn3ż T1 #)ْ^(פ|~{\eb[ůHW_pmoyc7X@_h'Jwotj͹a㜱o8<c{!²FOIGnNyCùtw̠<22>mV O(m{d.,.$$Oܛj)ypcJdHWsbnV{n{ i:/V~-Jkau6g4]J_=_.))~%v%˅Pmx*s{xlKIϷ; 7*(3D Tfw)@G|S~1?, k},I #vĉC%qw Z8l`{$ >j캥,tz!n<+2BBED\Ԋsȵx1z A({57[8v qؽ}$qPWPCqdyL};7Gyk_En v,VL@Z m9q8 X Ɛٌƛc\1fdӆZDZVIT͡mUDTQ�4N.Eqsъzb/(0 %5$]$Bhn`P\ʃ-pd繧 *(PN 9śhx)G^W)P 㲀%Ԁh3$s]~vƕFڌqr*L);sjE~]9H1j&X}:lU<e/x'S{;ǸxqW^z'>O|.eHѨԀwt݂mؠKܨE$1 `ЬDxKaQՁ')Fc:iS\x1&;-c}<n6%c_] �} 4noc cPO4x(ԭ66_JݯgMD!&Ԗ& :*ꮌfWjEdHbKAs_`3[iGDkR+EQڛu&ts ɄIZaVa|vLgҖ; +ރ >K)g~;(pL� -=s{Yz%.)/;_ ܶ.|'0dkŽ[l+O~fsL3\0>,M^wdBs0<V >L<ìwyoP%;wWy/ţ|S58>ʃ/'^G{\;KϽx͏Fݡ ǎ寳ND .seyMMsyN8}!pISQuȲ&G}ZVmUf(;F>ia:@{~ Im z Qra.4:p.Ze={ideFn`ei)d)ǿ RV ^7pIK`~vŅE._ZEcaky�omaMaCF :Pe(XBU/[WjI6$QS~vJ0n+=*YV[b%%.j ixEVSzf2C+=ޚRͶ9OqCfpvBX;S.bPBVx~m&К9LVbMA0nX}K[]dFYf!SU2J2>g<?:{֔YC~gf/B.WaE&>^d# ʞb-$ium%7ʞN*uE-8߾CXur"8Hbݯtߙ&A/n(<yȶEhz;;Be W.8ڭ?\wڥȶA+9cJ[${4͇<:t"W* #&jZUByhl5[?x <HCُbzQ*ztMmRnυW RVXhËTXf˸8("H+/p)/i~`ɸƼ3|ۃݽOX]4VVE:r*:8Q 5c[өJ(qUIū넱 2;eH* NIV-I+boiQ $ BxSff%HP1 J6LAR-P Aer@ŀ~䞹.k_0C= ])OKOx쉔nŠs=S/{Ivy䗾L庪ڨlw $$a؅g�a3�! dQ˵զ˪074$Y'򋊸q>>AiWQ@%afm,w x\+w=B 1A8O<Z21A~:W> tĥ^0z6q6;Kȓ|)rq(cj*^]a08087L{}g|Kc9-];5s8H bLr9ZT~(|}]\-SPa(BWHZ0'/T�kO\v@Şjy~/J<)ʪ;n@֣P; ~q`EאQD;S4sҹ]@ 6@U*!DBW޹%5xcjxFt*|F߲(UsWϋb){ۧV/e d[o^R~5caeLSAمb{* EQ)9G]%AQ2Jtyal"D$V8BŚ8J:{Z2C hy5;EZ�� �IDATǘ:߉Zb`%j׀0XgW#TU_+$WW-+r^kgThy)z�ZҴGF];پ}JI<{u9zQnMo+<|_xO|S�we֑fjIؼe{Μ>a6MlS=s[֢bbz6mXޓ—/6l8þfMx. L44Kp(M-yK[P}jÇwA*Gv{8& F93/ټyKYPt7(w|}hW <@Q^k BkAxN+c �T2;q/]&nϪqUx}gzN!bt#/sl G=I;g`Σ#-+[ d\Gz%$Bz3\ytӑZʡVl=8$HIĴT'J{*$ i7m]"CBj *Rw<;P# 4E ⅙30F=]^+Љ -~2&,c +(ڐ/ @ȐTbP#m f(] mA^(8RvJI3y` )A(Ϩ-TȦ2L*хBWQ#+ׯǚ~$JX{Yd. .jQxCkACX"/@Ef\Ga%!lE$ AuRD#" ݘS_$>y9DuO4 [:npDk&iOԪpӀ1UP5.(GtŖ¶J4gѻo-^A70?mZ^Ɔ#v'$0ftLeh=T}f24 DJG,塟[.[x賒#:CiM. z__[E@MF F#Tϡ&#_if4H";+[^* ZB!|XlZ1<DAm]xUa PWWy|g^U{Cqyaa#3P D,Qs+_z|Zoj8/TfXdG鈎bh7%o]2K zP2L%LN"`r7apafnEE]#!<QEf(vx_|?s<)Aue&RS*=TWW砤{>'ep 6ZN+ID:ѸDuH_9\7My.='5롙S\_;Lأv6zϿ?/=o_i5NXs%W JF 1Q)}Z w C Ta@ K-?).}-F=w2rm G<2ba/aPYpW _#|Stہ!gZK2h 1&$ޕ( JDd9)eͻlкE+ɫ[j걒}_!1:4}gP @I-C+qu< `f X\:wZz3]ڽeDĚ п_W߻ki6Hr�_z_ѿR@(_ކ'H4kXagd]i? �WgY>һH+Pv>Ë Y{n>w^/ q4ZrL_ڵ5h>D*O"-a->}YJ>*o~ ^~K.㝧Z ɪk "%/2,5 4YclAg&_QLEE E%:RiF%I2Ҵ: 0GE+lށJ2>>Sdo<7 $g-4^;u-5.?>͆ ر E R]PkG`7=^[R, $kA$ s2u{t%"Q{ |#AFTȌUnŢP/,\DCx�]\8+йFHU?:h/<4ɥg>^UسfU@TW{E:k#O2D1RIi``jNsiN >8mhPkKg j(lsv)\(Jk>V+FMJ eVkЕY:(12g$RK2:D#{D4 4Sjڠm`<(^CZEa5-\p6N@V|G)qk+hd�>m/Hxdl{$G$1v.!DF$M~P*:Ɓ)`l7r烸W]?u!Bn$'=~p <5KωmBXK9b.䬻,JK2-By)4,Hg `$JG5`+ r)8u ~/cvܰQdC[x~`!>/~%4$R:{ u~а<kY?#Rvb5f%P}a򆤫k!* :@>gIj$HB=E<FO(0bp(gh\aQ؃Hljخcr9 mjA,!ҞXN8xCj$"-IbE,JgC*5c9B8P8ıD* =ĐR|]6[eus|aHO7�jG,-&Floeu \ytc``?H{'argx؋|nt/~&*coH~߃ٻ~/>0Gᄧ}ut_ZVTjʲ(6O.RIy Pu"e 9)@ 9JJqda@[CCпG%qpg QHQIwALkmb0Zxکa۾}`++m-pR΢*Cnw<P9Gi󓸬EZ/*7$usuf? ˖3ĊdϕR%ͼR!$‰ ¯[ojVJb9a.KuyjJd9[& IEDR35xcf'7`=qpn ~d#9(^exX-?NW3( 6A%0o+,(?�0%X2Ha!sV G<u=̱@Xgw|JޝԉST+[XtUa8J ۷/q:^RP` I\Ai'%fIZK-;9w;N9 sSRCgٱ}'SSSڵYPױ֢$4.#SWX~#iq>Rk\KXk'@$LMϱf:6oɚ5kƕfQgzH23Eڳ8*ZyjLu`t'4/ksmqedY,$�Ĺضc]XQB˦Ԓ@-5F:.Ot>"4,-h5;ei*. 3KI# "#0EZʯ'*wv ~K0F"CKO|,EI"n3\VUm (n߅VKraFr =lJPWMƠGԀD( 6<*UT�ʔxis97Xe=Q$-l^E8/̀a-KT(x2#$^ V t=($&T@k?t #RA'Iu8'E;<(DX@"-9DU,*(QBԶ)b]Z$:0Zeڌ!N<qU+KOz=*BᕣkIE$̇5{/9@t"#pNRN-> xlRc$)DӐ&[I!ɑǵ`\~վQ(( [Cf2MN#J.Ţ+^x_epws 7P*P\�#|>Dvs c9~}YA?�*X_]tXb@vLn-"dmB6"%!Ig*C99$opg2"l+6lB#(j԰A W!e((Zj~uzX\AWHb^G4 ŋډɀbnûMX8ۥk.]4SՊi/XXƆ$FH9 Z_HJog,'Ke-B"R]b)2r؞.ȸAc6ڽcOu�Ҁ*uXp/Rng^~kz<C(7n"4gЧ\5T,9|!~?:o>t]%* :i 2}roW'R+L Q 8!*Fٲ^=Ӣ&&}9Ğ\w2QXF:tR&GF7)S,|-d-meE E0H *`+:kCe<tpR2v>&x/ [vQBFc )&43|ILs=Hf`}F,NHbժM5DEI`oXl/KKVIPUf1WJrh]:Ix}J(+)_[Y_NW~n}ɂ�Z|.+PU9sS9m!enrj;~2.wRkƪk*"KbKL'j3L#U̅Ԍ1K w7Vj\ 6W7$ܗ =!zƍ7gC/=[iRϚEF5k2;7Ǚs74~=%"Ij ,$IvlQH<9IymlٺazzI6mX-1J)ٶmz}vx/Қkg9d$l6K.1==ͅ k.nSt8Vt:yNRe${,ijRu'ZV <Z'Q9x`3ТM4(- Բ CE[6o&1i>g)R*p [099?qzieBҥbXK_Fk Y&UvTYay^UmKDG)2m8q0"hPɷGH»Z' A8n[1t X'HU =I/[O>F*!+y/[<,LKZac0o!qͬ m+L ('Nb(AYnB!x& HF<qB x[TR!k`sқfL%v8"MPV:$-\CV uQ*lNJKt=HZ EU:ԣet@fDkc6l3gT@$`.&{D "1k{9. 2 6فY0yISXbD.<47@LAg1ZTEYOѕdEϡ"yJrh8yX4:iƆGXfiV&H{^3<xwM7222D5R Ae|p}X3g!DZ%{闊]X:[+9wHQOYzޣ]61=4&17U Y|\P^i :PR:.BOFFxkA0Cݳ?0ʉ G*#B?j C@UMyCMO?mXX\ؐ{]&�Q"P2%?$֤V hPORHRl7Jg.vR{2<RFez3) -(u4ȦpfEɟrv-a/o6vnN-\(Sqh_c~"3|Ih)ѿn"%8e1t"T\W<9� sKf+2FDl%;٤$&Vr< i;# b4$B-K2xBEe6x!ё&VUJCx˕IJ%@(�Aa2ey+μs ` /<! 7@[t2UB\~?oQ՛7y=䲬W&-I˾e:J*28Yan (uz$uEC.m=WI}dՕz#H,<:0 <i2l! 3E\MБck`� C; !rc {kL9dxTVPgB۝-kAX+W{ו<`=W\$H ū/K^baֲgf~G~ #.ːF3>X:߾Ww 4 Avް4urȍo` n�&4aNMxv1Ԑt-6s]HYf(si4B(a Cqt((QDHy =:(E1QTAIV5q#$u@p 7pwfɛn8VaxxYS/07@ #X"(>.w$D밾4E pB�Oj;_~v7g 8MGIhI4 &Ұwn{]fb| 58z=AD[!L<Ʉ ^Su<L[py@-@ ڃb-񖪖<̩*Ҳ:")K{v<{1r7XT͒eՖVН:2H+mO5%Ukɫ-LeXD?x$5bҦ$o/9wq#cT]=#WȮvEd"MhSQlY'81c'%=D3;`|doC3jsx^rٷA!+$%|nGdG& uN-G+CliĂ`ːJaY5/C{t_E&CsH5J3jyJg ԡH/-ґ D`P@)Gb=Dn~XL\ooe/T Rk <#:Kjݡxpcffy-Q!*K)NnIdDG*д{r<<9s^y77mfG+% NIA1f $µD8U.]Q:'HK,DW R59 :ס^ydtb"ɶHF hȔB GT@4 A RXaqZx3%Glx)IbA&nmAlb_@�M\HU jI·>p,h"ҭs+$VƌV{\<?9Z$8q=7n("tZ)V 01ХֽxN$ddC鐔{Jؒ)yTJugFɋ ;Okų_xW|0w?[LMkt^eH)iF+)V&%jti9_ ^ʥN٣lj 0Ңhz0nM6јDrc i:#3p&2%SC�� �IDAT % 2AE_Qb;M<XD WqES Hd٥ @lC_翄Dkh{Y kf]JDRAZ Bov`s\!-O'�*"4ʆrM@C[%G. <^%"6$!DfR \=zٵA,`IqvQV@IY-)7Ң(4WULnE"*NXėG ci<Ϊa yQu&o]dd"G:$soE.#4?|-V|Z^xL VDX-5bQs.KY!RRkB.*Bt Ζzf7zς[kyYڝ.Gadg~9͛6le&*bզ^}&Մ>l {_x/퀡$~ՆG> !?%|yN?=wK�vz}4 DaC k׬A*0c'eqN8^={qk bq'>Iš5kx1ŋ#pO<N$avNя~1x&/i&l/œ $)ɍA"$i *ݷ5j1ϦM?W9^|Ewŷ?pպ=﹗=0 E&&o!�Ejnam<p;n !=jE^5�4B,[j^]X')z ѺXLa$y]OV2V" b29=s(<Lh!Yp>OK1ϝp#GYϲsggR7'/p&޶Xqo,QE]P،(2w9To-n!>qic|p=ق/M'NЪj_Z~;_|ˍQiyQ;I^>;O$֌k(ᙹOLnx;q`??0ƤEw^gr.k_zf[5??L7r<rApt63L)M7wc{V~(C s5>zpԸ- _ߜaT ~_~>;siyJt #-<?:g ,�BD,# _B:d]I%4-g%q,VJF_s�^w DGʁ,L:Hݑ='X?rss]Kn|8 ~v" b3`hFM!BPmsw]̓=ʎ{9x n<ġX~=c D'*{4?m>ve�e[(}ό>BsezO.<**#uᰡA8Ow)OURXCPoq jhw*'&dE+’ Wki;CBDzAGM%8R tK,|ŒLA%ZTvZzPC8QC z& ?( XRA) U%VRԧ~z\#YAbYu_)MqGUێ0}W.h_M+pxSd D�LqYH鴮0=y=Up㾃lA<\|鯙gϰ㥋<6R'uK Uݥde²DR\ I4ɺi8nB Wkq 9hfKvKX|%C"_z ա:l Tp�=z]eZμ`=3HhciJg<!)VBQٰ=6mh;n;?i"I/§ <SC[ uXHso?G+Se}OJTVRa]ZKKʜ_v%.$\+Օ#|ٱ`ee/dzE!W3d2҅5#s.D^8tR YOZ妡DruksŵZ Ae>U)V>ڕZRDZ8νO%½�s WQP 7cb}d+XpȮ~b  vo+,MuW* ׯ:T:58c:Rժ{(8إPO'BrAyi~iz}266FsE{�8{kʆ _3³>|_3}S~Q(/+<Ss333˩S 2334sӼnٻ{'Gᦛ_s<O>Q%'^~eΟP/Y6XJPRǐT? kEO1EJɾػgR͂]6B,,tת4js9{jSxk8IrXآ7ݴnSO^vވ [~⮦/}ݰ&O[,jt�!67G@gwI@kQ *>BP0p.i)jZda7- n[OLc-ڹgg^n0Jt9b"Zr}q(wlDwf|=糈g Rghf[l[bC/|v&}^_<dUK}-b׈w|6~lSmn6gfw㇏旚X!qCKIWc- 6ON6-<zh=Q "Ysw}|a6jU6 6Bp:iA"R~�;- eidžٵk 6T#gPpARGJ%�o vރPe.2E' #e~k|ci$-iA<$0)qW@+"oG,m4[kaINJ '|(PRcv֮[ǣ>\2C:gX֓.ey3>~~r!˦RSv\Q)<xgׁʪe"l?�EG WVb(-o.DFCNx/Iω$>P9I_csChF#C&3v^BcEt!,Z*F3q%OV0^DyD$#«3H"`)P^uo$Fez[P'}hrsHD"]Ф 4u$(JjzO:v),ɔNc.Y-ZPiEkQf6:XWZ=<o2 x (+XaS˕ ^xENv߳k1R(UNS@݆'j|hl'-s,K~E+(erާKp-NׁX[(8o.X} t]Q<PUBu:IrT}$a$kuE-P\iJuh�SNP^ǶQq DkGQ*PHdp6{w25ߙ=Lm禒[fZ˜ ->0[, FQdGXyFDV5WQW&}nUea5vmʿ_@gexDx"Wz2 tT*4|.*qu /U8yQC,E( :Qe59[Wja%R`iNUUX#QGY-vq>&Vוj]B!Dw9o=Y10wkEuy ~P(R"(h qnJJa2<3dy`Ƙ!eUWS%}SE/=;of<3X㎷˯]n֬Y֟?�?o~awxkHq8' T_u>#Q c#gm\pv^~;|1nmĺ&Fid)5`l[7G5zy0Os6 "&:1! JEXg.+|Sʫ'"}`ǙLQ![xQhcT^?{/~1~|{_]._Yd^??;M_m O87VߝE,;\1>4qPx.ދ|r.W ܠ2hvJJ%g%ZK]SO,I=H"[B)GseOk;\lߵấۚ$O{ga:}?x8n!/ /Hj<gO R1axsi$BAiq~!/OΰeF nܿqD$ ^¦u[5% f<d!nɆYR]b-)ɻ k34PЈ$ĉ&NB~n^QRѡT@M`U5߳{}efQ#"xн WE=qd&-4y�DT5W)zߏaμN񷿏1X֕T{T~&X,`2k4 (1ރH/I!'@mUc9ڄ4a2Lv@H5WH:BsNt[عF&N2StF0Kfmb rz3mp)~Iˑ8oA5VkCWD~ȾRP${dוw~NhFj�M�H&je<UZɫ]k]{K+Y.^evcKkό8!q@ hs~{qnU3CTp~7H&,A{%@01>s*'sD1 T6* $fq1H)2mF V<bAj%8/C7XT) 9↤!IFod(0!-UdW~1'twAgP+;ϿV_~(c!s;7I{]@+UD�0F2Yuw̞(xZa[=vA,�aIXO3TDJ+ tU!~|tUzU],!b74̙_&NאVɳk,Zjuoae^>ܾMYMVƎ D3Nr;KD%kNTEWk�%$;&gjxgPZ^![#$MEC"Kst߻!dd1^K*}?lHD4rTa}(dP1֓lg(P<Hw n''e)b(1*/RA+ͮ;|MJI_^zu[N w5Rx(-Ē+S-K>+17_�V- 3s.3VSu% Rf؞nӺ~vz{m 'Ԟ*qL^^Tqq:G lYC:yqzWneCL#(ˌ}VJ$ yV,ùBbM@i-/ tI6:ߍᗐ"Rٳ%MHJ.'(Ri)+5`hGiLqu0KӔ8׃H+(L,@^R-G3?S²-};_O~FKlBFFe8߿ɥW8y$7m%cJS@?pn.[nEIR +hl۾$RH@Xq,yӨ7ٹVAGdv;cd׮^( ,_E`2I)pV2=/~8q\8qy~C/4{~rY.\Z).]L8뙛[ 7{>xpq} :Z`ڵ8"�|<xA lӣvv5Z!� CQb FyH۱6H�-I-86Ș/΀WsW9^[Q y^{u6և4篒kRQ$!MvE鹫|uzc[=L_tkd^Y ъnZ\ Bfɑïq&>D-ʹza rSJMi8M,Dqx'`B,t|dMʣguSq�XǏIӽ<<:̡ 7hfMN9K}p-ՊD{LŒ-o ^ԍabnkGMƵ Fmx~#bXY�')<|i h-]ȹ)`h*T|18WyP A_c-:TZDgքe? qƶGqsYp. Vd:t]xAF˴MN]:ǫ[ǎpI<k 5rC[.'79S7ZLpQ^x)F׬g޽';vla  cx~Gxaط' o<FF:+曡pp>PmiDYlhr^Xq"zc3lYAHFapF[ ѻG"&4YAdnAv ek Ė= ټEeT�GEE|^vSVU(14CAЯbadHycغIO p=g/uquRPdE x<4DJh:'8[9uNJAR(lN[XtoQȪBD"W6iAju-~hLyAG,%t /<?ɉjM1G"Mא$09y_ 'Nܷ=}]l۴uëI+B(^r<;T@ mB.C<  '(<:%J x? <0tE3#p+$*(]_w. אYwUAnl;5 b6ia:w_5L ElY! |PIp o<^:*EPx%LT(8URu�(pr �Pȅ Ng"޹6;w`V݇#("KW.EcYX %G:&I(Zq-Sonf3ܙ{a84ơ>&Ο⭳y'y{/1kncU_?tcD'=N~+%ߏq+#bժ#ޡ,733VV'_B�0lP 7mҹ,b)N]rg|mʯ Y:=Q�!@ȐR$xO:RvB7`P zfg瘝emmوc|> |?Rre*7R} 1q-7g^|)FV'b=\tWA%hqWċ/>~6o\Ç$\$SxMV ལvW=scҵi 8c)^$'9ѵ,,֨M lt1N8Cm1_@Ŗ9 [Fz lħ?![g8N֭_y.^ٮexxUZA bu)ZKM o]�� �IDATKi'Ab>d Tws(R!+*% %eeSJ?֮Xm[%nq7=='0ŋFЯ< X#묽#)Zwg9>airh' m=bUs$l[3'S r FWs-~I% U904/fU}-/ k[43wqܙ+[ɑ$9†.;Ù>6ogLOISU1xCLɮ;vy~;Tk&v!Y>tkZOb`Ӏl`ӆd 般њkʈ}%)3Ԃ|Qǖ<>x y]-Jitd$/8~gm[C g-ERuwġ%YhgZlUC <xe(i01 32+]Hu]\zv<gسg]SO>O=SI.BSxG[`U/h5>sxٴ6ǁ;m[]eݪq.^n3=b~!e[J6A$sl&ddN+i$kmeH6ĢE.hE9myO Q Qo D"[ 5i_-.h#mEHq"z1H I4k +Cpz^p6xNpĆQPoEf9~_<6s>ȱ"$(L)'UAf.T<;ޗ3*G#YEFhlMW`ڙ썽2Б^}>G?�ԇ8z'#/q%Y8Eњ03x!ayf_C<ٽo/wݷqt>*J(}Cݞ.49|(kQzK=,BPeW\ Iz߷/"8QAZl4/.pΐݘ'g#.VP>tBKh<q3Op(k*AWB,AS,~_SHh6@1dJH'<G]AˮjCDKSR;΃ԨJ7oQ 2Mmʘ}AZ3cv ۜ(ZX'@Xށ)#~Nox|'eY" 6|iLPXέS雾MqvJ}{?6B&"t%ea = \j:7smfɛ}dD{އW8xm(fϗ#oB@*;ޝ+W.@ o:@sm}$|Q,)\aQ Z,]  o"*AbPLs/lM)"kuB`%YV:2DiLZA'x/E Ja4-p{+W.eǷu&�Nӟ(#|nڷo|7g?ij>Ǒg-}O|ìY /kWY32>>N9E 7IVZȚ=z[7c׮^aUdyBR l�O~c9{x1uL߸ଣ??cvnLX#銨7X,yw޽w!k9~+.\3u#wm&KW1~.$(Gi;65څ"@g @[<`$c�5R8RXX+0%T<q$-_#N^N1*({\L4 ~nMj#|`.un.gΠE8;kW0dhV=iճ:*w&6ڈ�sAÓχzB(h/@ilӧ2>ή\�w+TrCwb:t= ,X]} !-3_GxLJkx |EPqóF[R`^7 P=aWS%JcUGIp9fx“F"D!JEZ�B""ؖ T SmG~fWvK F$2~?&p W%m@ܘӵpsWs;qFb |!"t366N$Ss) Fџx?[7atwmO}٢IX3Dhb,8C"/X_^ܥxyq?}w]_w=EUؾc/N` D{G$ Nf@ 6R44TF(yЬ0(B$kրb zR7JfѼHQ BFcYL ^+LV*QmT`EHEZ)+6twYTKx� Y[.]=p^?!yŚ@MU=; iry;)_0[Uuwo,A]upɈN58[lc[DHIīzNז+}kt‡8.p mgc\:wo䙧áCO1=}vzL3{mӜz5` ;]=B_EOa]%A\m sEX#k,_Rv<Vqxg4.9Dimq 9eݒhmJ^�/&43L@% ?t*UD):QxGu5C>G*Rt/tIBӵ.6~epl !s:}i\2Hu>~{Fj72ց*oNA^d Yɚ3L~o!2C.Wm?񟱨Hw2tV+:!S쳢( ߼!K p2AcEGf V-yk!iWRo8whݻwra3\K;6 C誴P|Jys";rg&Lw9SThZ/`yOQw5J= ;oJZXV@\q,G=n:,̙3dYFEs#/,Ubwpi&`tt89kT28<Wc'o?ˇ^e?f~~|;r|ރQ_wş[[)~+w_f[٭vu}￟mxCIIZIyc%M*8q-6mp?(|ER$O|^~**;v7~򌅅޿4%"w0pʃ9癚…˘¡fpp#4@U'öTRBkFQKfR_WҌ$w jZK*iJۭ ]hYB֮[[5fghэT"osp+u ИqyMAHĬ@QGWـ)0 O$CSOƞD9: mPJW} {ix/ `VIbAZDi \4$q IQ#8Q$FhxAz@q~%k{!y"=ʔ]QX dTsO X3k) #oB*rX) SH@z| $\rI(FȚ 2O=Ζۆ-qo86ۊ„c`ĕc#3.9 s$CFcҚ(+GY_6S94L6lAr%1u I䌃B�r"'޵K<~`ph{(+>CJIqR.\jhuD:nQ bf|>|Msexr Ҟ~xtyN^o..r } 1Z)w#cG^ajsR3ӭ5*aS^u#ҲfGܥzIИYb.OA U`*tr|.FT%Vx]#Y 8r1dPme-m(_T )ԑG N(E%)%Omdc9@qu^' }`'ő$Ц`GV<ݖFҝD*FW|ʛ'2oh)J /d`Yg"t|q" Ԙw�%٢qyb!l4D] z�}]_|g0ۀu/M䃇{GmGK'i4g_?ȽwgO?^~q2;AW iwm|i6u]īo䣏8x;Ȗ XKSݱ'xCoR\v]2ˌ@3S!ȠէΒn@2 N ƟZwew;$ sȭDI8\<q#Р<^)Rj�˭E&(m"dFJi﹟l g{8/ w%BP.\$JԻ{ O Jc'NP;:Fg DTA$x5HP%XtIԣ.wnªPǬ,{0ZwF<[_lʉZgnrAxk[f:Eо6x \}h]e׎ۘdbbE<4Bۢelٰz˰v0K3&5__{` ~7Ȅ&X!~ʄp=<<qz, RN2w,i\Q`ߨq Kse{£|i]\:DXPA�X +霙Y/"CCCٿ7\t|oS۶m~K]}`'ϣƇ :W?oֿ'K '9q?ULp3\]S \zVdxޘ)WNn:Rk{򼠯;VU^y(ݽQL8in:zz{CY ۹zΞ䩓_qcFzzB0~6�N122™g bٯBR.%Uw֊zP ' LJ"F MW"yTǤڡ(@(FnVzMO#3aXv'<zzm0�u&j8<j̖ilk3\1AE(1a:Kג%]oկ!=Yi5$L)S)<ZkߚPhZ,b0baAA($U]]'-D(b-Aں=2<TWgh$ؓ琙`CxLtXoW:Xw,dmH.R|*eLy@w{l"ѽ)c-ABETA2QM-ɛ9|$N0אB2ےz#xk�GS{:.H ANGIax7o lXH>۳zp],D`=%8S$=5kz򓳤9͚4%IESa H,??08 ‰ !rF$Sv}קh$s Z*h#<}Z3mbӦͬ7|ϙ 7-fg[ْZc'塇2>ur_} s&]C099uZptj\+\Y7C'HygnErc/<CU-!RdMhDwDGn#ȌHD yyM>bȪ/ 1FvOVj{ \C%¢4=#6*<yR(J(aK=wM =-ANWC7 RkpA<H(h&<Vh43v򆧞0!B+%p#K~n߭HtѴMRbGhM|e2]CNxMTֱIO̰<ʞ];m:zTLצaFVV:ǎ&Ϯ2R~{DZלŵ&ihj\={7y'n}<vo{܉ ;jDEKڦCOĺA2`e(�R8ATE# t;0/$V~HJt`uHzHVuQNPTAiBF Ji*0@e<`3aB*DZ ;0@0pBJozh8W^fL<,&u|^x?to9�–R@8iL|}+ ?`pN,9үdw|B1)(Jm�VС/N%u}t@w{ -ֽ{y}uE=;mgvrW8J/w= =!H&<ovK'9p>.;K{o}9ri`$vQΜ9sӾjwkqqqe|'w12<̷{V6%$ӹ2V1fvַ=P.uޗ݀n>Ϸ>\+~ :`Cu%:׍Fkצɋzőc'qcZ-'N[fM)%+ ܕKڅ R 9O^LLLԓ_O}Y^̷{ LNS%AaS76mW6lccc<yZFoo/333cعs'N…̠"c$Iy?B)YjO=]{'gD:!MSf׎Q~q.Ja F7fh6Xk(cǎu+Cѱ|V1(֐Ex~̮HaU5~$4EnB{zzH*)7jcͺB2fglyW]xZz$ [ǷpL##FG׆k.wa%N M$k(ddW@!Vl(P>|< [3Ka<IZ' 29 @HflCZJG'jVƗ$A>Bne,V8a% uA0};:C.\tT"p`ŵѹ'(!0\P $d|DTD%fh<jJSJ_2i7}b(.LQ"D!U;--HL.Y8$(m"bf&IfkDU)$tgͫ"ЉCxT/df e 悦YSD1x+( HU?ÃThS۸ȠWX|T*sԲ&cMxՌ z*=l۶˓8s$y  DX0Y!Z8{l:k }/)|Fb5l#uqdb<y&\ns"?a~d*~<AZn*h KBY"GNf-rثlD\̼l19 T!#NE $;j sR",L|-} j=ahT[#JS/<SjҤ0R|=|9yFaf$ F`N@y]:"<ګ,-^7aD)`}U.Owǽ;r qtȶ ,[c/gra_I;L_VB_ Hصcw/W#&0�� �IDATs<RJ;ɕl[UNӻ*O7)|Q |9>7mc1yql<?w77A>O{?ݫVmN=EmCDʌ( \X ZqB-K ]4_Ar |꺲3Ed<2I*Cp[7RX$ zZ d xB6I\Z@Q$yt}k :R-0a Meҋ12PR/@m#Nf&;{㯓_X"_jC |*#;5R(I%N><W^ ]5+(ֆ3k풓JhaxPJ-&|g;ow,4Iٵc/|vVaSoN­>+qju(3;vG;|}#|%f܍tV&*8ohmO>\Bݾ8%( y{q~ž>_|o;J:dv+V�Bt+~wqeJ~n97%uSz~fF^_ ŨsZ^:DmaдZ3sabmE^, WUdRG/@tw<uzѵ|s#$ GcǎK3<-[Q[2;7[RBQ!I֭a||+�۶aR`%MS֌a RJW壏| VfZ("~w$iHc "zY#k֒4(cpΑFQjȗ֡3k-(]&sx R)$A0>՞?3| <S5{E,+{LL]ӟ$Cq<y#b!'f:AmcT!`mT*mZal2Kjs$wmB( 捍9w>BDp!9!qt8 �q&4wK1<UPI͂HBhϾ=}msH-CsȄD pı Q(;ڂ0ONth[j I<س>AQ@x+PR k2dEDY(D(#-<6(N 9`! ҂ %hLzҊCū'-(6ގpO} ? "I`�ㇱ` YB[' oǪQg}),EA, T"mKQO$UxA{N1!9~qP/KzAԅZ5$:VīsXNbKtc:=Œ9P]lB+^>O;k\3 -haqRHV \p:trKܾ28Kꒇ#cφoǜ/v?{٣mwӽ33+K>_vxohAܫ aLUW |읚qM6Q%GN5ɮUdO . a$힑G\,UTvj᰹$o:z<NJx1'$ 1bj&fzX4h{VDp怰z b]M,7 %U BNJ<ohHbOowPP*?ڱi'?%!2qD2:XTbDEă/"ڂ$Y=$#�U&>n`}\+_9&[MV!LϕJpׁ=,[,Q`'i_aYzڥtW;^;C{|#2NP@,<(!@;TW�xE-joѽu*!ʼp! T_0\|:5} =O*L##~Sxmh'rR+&XB<@efk: /Ft$(FD%uI Om'\r)ͩ ^<‹qʖϥ "4yh-b X$~x'hh;ϗ]!^bhR);κ+ttr;"/>q3n5}ovkm-S[/s h1=7Ojs3\?F9T*JVd[4[\F\rӄ&ꡨӨ4]VnO؄eօ_z.\\O{6grUvLuK1֕NL,d9 Swe@Ȏ}JeyߑUk|ME@=gff&$1 wNt7E^ S {g% "->Q2%fX-IL\Yj!-F -B:Y-r9b/)TŞImh(֬C7+P}#`|K@{odu}~眻_f0X $%REJ2-J"۲)JHcđIEJ,nDQTŝw`v{.q@J!5Ut7{s8*tU#(Z(iZ)\HXh4= (1&ѣx\h/}2w"nj�S1t8T�6#D",֫\z;$*ԤL(<^xEw8=I<ݵMQFƴM/ #NHjFqǑ(dhҞF˰{UATlVn<UF{"L:&�vՑD!|Qmkb'ϣ< T'*q\x ߚF/&'h{ vZQDЈC^^ 0XW *6GkÈɾgdnhzT$$&k0 *Gի@Ƒ۰D !C4hU*t7RK+r!/ |4d a ?@mQ=dXZk_ {py(nmW瑑÷yD9uN<I7<5(/.3+DW:\>X¬,c4đ#a#+w W(0$T ZhQ\(y%<ʈ"Ҕ%1ʠ1WIґ{+EaqqpYyϾܦ,^;(ϝ맸㶃4ҤҪ=9Q{(K4Gk]<Qdq+TEA.L9S<l[|KLkbs#染h(K^הʓZFvI,("wQڣEG#~OCf~<b#?1| Kb$Di`)é`$(KRl?h,AUԧq(Ey!D}CYpϊܐ?\v1wwF{$.l S9U?bHPeqbמrZ@%e?M@;BRX ?$ -50|B<W N Gr 곿pMTZ%gΝam A]`xs==5Ib)C#QSo 3)f)~<3qv_y/7_慧~W_ ;rnMHH^F޳}DCfѵahc|)!ݧG4߻Q,= fjijM+=j}&JB`zt7d Eߒl$_[A i5V;ji]Godf]Kp&(W>x+T ]vUсBå$4iyu8QdWY{6{d˧T[:a0Y"jysn\lWӇ% 9! F*`-S¢! JBD�}uy޻xm{x=)~?e(=|ϯ373\߷!k.Z4>#+2EΟ~ٻoѐzU\>˻~}py/WPzʏb̢M1Hp,p:)^zj^휿pɓ/ϻvȍψFl4hA[ul8ƒ笾IUI73v`"uC"inq]ɣ;VPZ399EelnnEG铬dYV`Lp.h8O,S|%zgOLLI{.>] R@I 2("2Ԙ�⊪X88>YWŌB9*䫡FiΑĆ# @6phDDfuuvk:.25;RpHѣi`0x @sT $@!AV#IBQ8k:HhS7(ffY_g_ONYLLL`K^]Ɩ-.q l@,W:giiJF֭P}o'y-`0|= 6J)E)PFևD�ep2R(�:j, όI- ViH@}A{/4VԤH> BVd˒=QQ~p'lQġޒ֌&k&rH 2TZtyoI$ Baf(i(|1x"f7 <}VR*GbO:f~.@Ęla?ŹsuK:䃄l pJHM F(tuP�;ғ(EpDDU=Sx|/'gP!+L'[[68Шװ,316+6XC/D# XD\UIݱN3[kst"&/}g/&|)9畫yX[ʳ/yZѺlnK@_Ou{Bs">[iz[bC'5//pw23/o- Ϡ&6ȄBpU VdI(,h ѧ{ ~D-$2jzII}5EJiTAb ب�p,M_).1\T"GC2TP:|w?~Jhr:DFܸe8B |ڑ&FZ&eU�܌VE  (E^@oT>2*shIc„Z*3.AG1Fȧ4!(BՓ"% %:ir߱ګ@wXX{v"W Q4Go'pڕ+$w^�$$A_iEyO$BcB&,2C v/=@~/|صkO|,-XJM:@lQáP3Ӂ&�=W.m3PndϬrŸۦT;_G7"s2 L񽸁e{g)t /7*mCBBQ[6)a,YyOM+zpU=ê+7Q(b*!CɂG+6Zٻ4>_-k 7pa~<Zo֢=0vMqy!TMg~Qԓpe*AMPƓ#izPЁ9Nܽ\t_寱Z2(wk/^?[__nk|{?dN&('|3_}<['[LN8q^2#X[R;((u>Oz2 FW=Bc.v-Mqu~j~4<ci(+WΞckV<&-2dZk_9epVH=nv$|7U3(pK vX(Vk670Z0Ge?ߣnonμ[I!1G>{֠`ȋ/BYCaov6O?-DFӞhr}'kA._?WuEa)[X+ӻP yNDNi\ɉ^,Y]Yckkj~Z9~v_^?K;1>w d66SMT'0PJW|!|˲aVg8*qNk ?$KW6x׸zmNyW+Jfmm,Y^YguuHٷ/48hv(/z%:_AWE�+yH'8Z)7P ÷9(HD .pB-&"4£LG=숢02/cz{ӨL-)GIEHա%x&j_=tpn۠p@gk m]bgN2L <�zT  w* faV0=_C=u(W!NAł>w(DWR4nx5ZǏDGindWRd{se]p<EB7`KA $Mg?lje`hĄ"o tw{eU"f?sa:nw}g׷]Սo4Rh.$Xs4KKJ6'yC}K(Gq.l=o${ N쁣Q:a0B!lmE)]Ms'BĢ<D>~ԓ!H>>@|jA ye + 4>8 - ٯaULMQjubʃ) ٵ0c ^/(C,$qwLxb)lˈ59ol[Ү0}*EO)u^W@q^q: )2O(4,BֻSa"~wܙg)gahkVz0]rNQZF 7G|أ s,Le$Z.LJkQ9ϕ?or$ݽEь>:t5O:d'IꦱB qdRByO-= $Ss~hFɑyl5|;Zt:<7yr)c|2{~tz:|0>MA-},p֮}OrCG3uX>8i I5Q @ E{d2&n lB C\'I.>HkdtG~a,e'*ɠ~`F(Lj|d7v# |3bi-'jwQ*<Ͱqh)ОZ<Pu DFU WV`Pxy'+L1&)\MֿU%"&q\}/bjx+xj6<BvgRAx6hMΤXg8uj>Vj*VO \f:[ &DWvuVMQid`{2"'fZ | 8lcek(Ҵm:Dޠ2f Km%e@a'56Vwg7Ɋ!˫'tfc <Z{^ zu^eZ3DE7Xvܘ{7D;~yN+֋00>\e(t6(,hc9vg~M~:VE@J[;v'>P-z!<1!dnnG}_W_m`z{0+˫#C9|ngh36;w<̰7 ǔ�|Z띯^ ^iVqx7O<Nf$n,Z6˜~ #fg4afq[[RЉ9V�� �IDATF'8 J[J2V6VhLqe( *2&r8« h|5mph8U|hL 7zg49zuf\~ΰ0c;zMgkg IJވof♛30]!|w׾HXF)V{j|ؙުƁB[j׳4'Ұ>�5)s!k(H,C/6%!@fq+%?2Ac=*rˣ3D'>3A2"#6 굒Vۑ6=&L@ryHP/ҡSm /DJ۹0)sfG68 $=`ڄcA'. $M ԡ\a}*<")c)J@a29$@ {|hȊrG =)o"+�7rD5GT$t  E^![s5Ot83eG ޙ~pST& fqͫ]-]{'%)Efa+`+axa 2eE s!F; O ΐOkv 7$} z WP7uwќhUeR'X\Z@4hPjŞ?q͝& 1 T0@ N >̅7/ vMO<w73uj +hX%I z,&*9=Х^ukC0H &YþVҚNkAJ-驍bz!?.KGHenP6 H p:Ay۝1?ݳ}"Y.>b\ZZ+0#QA;{#}EP=W*( +kRLF[WPZlo\ =]},9t&LEBTo(t)8 ei5IzrҋL|]5?BY>y.nTxQa9+ zQ+fYzT→C~mx^g>3\tݏ?]D;+9b2q$QVFԧ-CO- KL~ْ__fpmHݘMwLҸ9נHt!;[QߚDk᳭ C]{}KXS?8KK\ Fa/T�+\ѹ,>DqT2]E)ŎcJ. m~F$>E*ʶC܈'_>WEV &s@OC7f)zпح~ �+ \-w(Lt 3m޹z"Cxur͌/+"ԩkt2+ҡF)Ǚh~/>uZ̠oY~ @z "3٬9Gd@d吕~~c>F'?"^}e"/QXoIL cE#qx�m?IJ,+ 9FkLlس'%W9!G>YGhWbҩ{blOr@֫qs p=֫Wn}\Nd<!OC&F )3wvyRh*oG{677h30O?w"SDLBL݋-5,Zf΁ D:F#̲w&R~gi^~e͈Nʋ'y綣{9zl/?.W\{nHq3,S]SJZ9$'`P8nEEGiʉ'x8pvkkPJ@w!;{ړc֊$IH<i(D$Ic"C9eQ7awuƑcu�˂<YXGDHF3e{kpt:9IäiJ ajeYܸI!8$КFo-H #A3l Q+A&Q5p ֆ(8+-puL{nUP@k$ |T\c]E+X+d#EVO혚)hMyZD  Mn.Sĉ' ߃+$ZhP)=}'g3W*VI,ڀ< 6Ph\}62Jè Bp6Ș%ȝbkSBw"GǕPMDDw`'z1ՠY$o%&ykKg{Sv1Ũ^y"%ɄLL)HAa@O =Q>E#(DSK(-+/a%e;}'Bc/6! SĝI4Ebљ8kiM(jĄ#@*[Uc0Z|DB}&j'Xɖ[<BI' EV/D?}7,*C=- Pq('DM#jz%ȱfeť ɮ]U}9SD V,D"zR(#u#Ui\c7s+ۅј{acT[ψjJO %Ld)KFM{pꕦ:J@*8Lf!͕%U !5g2!59s9<T+65pF;[M^0:Z)`5X}dy2BrGT4Qw(:ChlQ ^*ˇqk{ъ=|"!IT>L6:L7„ĤxW?d0C!;.? Y\B?W:xB8Jcl .s//>]wx#F  zH*=pDn2Ǯ# oɅ>oB֩?@Ml|ts`;;.͙&5ɤ9zѹ'Zl n5fł7>Ky(/?^>CԞE'i#˕z娏;x&&h 7ե۠ 7bQJ޺]y쀷:~LuUbU=ɤpp=b"mZ_3m1WL4xMμa$h:N_x]g8xXkrd_DT6Ul!q<EbʅqiN$!ׯ^k)G OΞHf 3Q ?s`ml(oq2N� *^bMټf-X[#bP GHA cx[r`o zen] 3Xc=zUY{F [$NT2jIR7!b9HT͸ǜe* 8>ǻ{={Қ8|w!N=SuLN0;~ j5yDڠ!ML٪?`0Ш7Jqs(刢`5"1"J"8w#]@Ӎh!'8GQsRBoo^< V6y#{w/|9%."%i*|9a(A`P[Ja!puY`ӨМYeV1,(Q'+.dg8N~W~z!ݒND9<~ ـT  >@&%jAR>#Pw干L C#kf Cu|^`nWIu d/#3b%U׌C8H>l~9&2jo=#at2 ĎF&(7j4 <'AXt$5Q`2[X'YJ:f D8> ,Ba BZAfM ē)ash/9UH"Lm tꡩQ2v5Jl^2<e 1wʣtS6H ~2= .zT@-'#C=ypt<e6HL*DF51W7W�ݲ]vwc] 3(b7 ][v +"mh0(GwGIa<UYZ:O<]o'TZL0?vJ]K臆4 /7?Hm(ٻJ޶_x'WѤ=RD ޟPv[@ (Kzg-j_D^I")Og%#<+%S+B#1\mZ. 6qc3X# ^c0TV0zC>'�#CrVw[~(JB`R@ w#J"Ur"(W.U*]5_lp8Jb aPvȷbeX ZyJURKblL<_C4Z!)6h7X81i e3>45 "_G@®^\7Ovk~?.]CTAi~w?ryl8t wy=*QDMS') N>s'Qk5W9yAd:%>2E:J�;hJ9wz N.#W~Hc(Μet ;z0xi5\ڀe'#\$蹄ڰMH/!}Zǚ8hFIV (Ϯ4 >C4DUq伧"e#5_~҇>Lmzm1(PQ) lkOu6!Eq39GYD%f_7I $&mRjt/RN!&V^cRy3nDQ^0ǜ7wlye.^ۤ!)CIQ5!}yKՐ[l x<H7g?5^=a`،R+vćzGu'4pшV{ |ȳ_�hrQJSU=buц<Ka ynKσ\|ɓz+|eai?g.|_ŇK㪤$BQ#u%v5yE2t[HbU sdǑoUEOr},1uMN{7Uo`GWI "c``*՘H#o碸ء;={'΁8h3n:3=q"L òzQOoh8) .:"bWJ;8q*0?9rE^e˗Y._ʹ +Z&^->q=,KHGoK "7=%8u ,-fkG &>qG1!3ت|O~ۏεkWY\ FEAaĘsQX csc {vdavxe_?}t 4m"Q JW7i nrz Ibg5RW@MPb1rx|jv•yh\d8]"*�)l# DaR5ߺBQ 15mi8&!A�t�–iCsbp%:0)+'<S3ec94enΣc%:8y= y�X]Ei$ 7WHP60\KJBZ2tSG#(( m ㉮_!I< 1z' 4{._Q[^#Eo|sRC?a<{TX nt%$tCO1\GheaCQQAH6Do>ίop.+DF(2ҠFŐL&H@;q2wܱg{L"N ._\=ZsK~,L� ٿ')ְk`QegB#{cb1Gg!UA[|pJ.^(QH2P"KX*i}(&S)B<~>G]DsQd2:i輒Sn:T&D}(+CyWYlO7 6؉ + KT+7k-{ Q\wdyh>h4F *M ƀja(@GK-[;Q*h$% .։$fxG>B&z%JK[*mhjyszk=I  NceoнBkfiJwūf ~IwF&}JcHgn#Y>ĨCz#aP`btP"pJp/+F/m`Z )j 3>d__c5bvd F QJٗ ~VJ9|V"FXMh*bw3q"#s8gw�q) MH  _c7YlIuUw5�5J[:z'KR:8,cǀMqأzT𹸉qE` cm9S9 S9ƂxM$yQgz,y{g+J�jUMh瑷gu^ƗlhKqB}>v& 9Q<ME0b~ŵkq>G9&* UڛSld :d<8ݵ5F/sPـzpbv|O2XWC}<8v <sg7v4roq<o;%z$EvWfNGh&TNgHd�47雿y;ו = xܺI$ul0uHqLāFJ^3t((Eb^P$uy b01 r6i4;qc1x7B�1*C2ׂTr�\8 W[z=$頕"2)[[dY8<066AzE 2@ǖ%x|9s$%p޸KK8w,{>LONakky^~O�1kÞ c|ΕWC5֖q2FD1n&1F' 9}43,,/&X/ra11mXbp EKADQ[(P',•#x:# <Q!cJCUVIx0ѯMB4CH% jQn8V;0 J!Q쑚~OKSG{Rt$MP5 ""v`{Enj\ qlM8≐"¨ [3RЮyq4&- )ɒ9yo޵ � )J Y≱#;a=8aDL~;fDk–4DDR R }klk-޺K.g[U ʎG}V̓'.&qH4K74eT(+tB+ui2W&"J B!~o#Cy`=xl(ML,K0&HjH[`kg)v5+Q&z&9UKkA2 `RKַ B@1* MB\ Vo`M9+qkATIiB4^xLˑv}Q??{h0x$Mh8U $NGhC1-MQV(UɹEu)o\T2p]qn'!N#f�eqjE[5ǽ<(mB�A:~6xռ0%mX\z ≚̣5'Z\\m@:d1$+�� �IDATC5 9J_MdG,rҺ'ɻBxϒz#a~f`$'ki5K.6,Z t,{=IM Ҏ6v<3%K#uMD`tޠtDX1ot^\QTVuͤDz(HRǢl7evBeFMPTxݦ֥^-J\"  ="siTaU$<~sw2$?{7>iyǧZ }KzuN~=ﺏ#ۊdKV9䆶.~ަ}Oč7O RڊC:#HpM=Aتm{$a( ۄxaM- b&$wN!ZMEM˰FNft4p 8S(1K0iB=+vKMI�!7ŵX,AW ;6} 5<NL 7`E*4l%J ]s{DzySBD`p_F C,eY$Ή<}ڳxW b%Ig<U81PQvtstRo?x̛lŸ ]px y/ ZpKLXY_ ]yi:2%͇&Su㞎( <u$chcT7\S\9N>brm~ }>]oGS}o/p+n"hZ|c< )(Dqd|w6N79cS)ɳ)ݵ! ǭKaЀ@,A[5iԡAv \[Ykk^}VWW늺rXYj[q66e84]h1C<fs{C#*ʲ֎b*p0 b$cmm+W>Ƙ $[#4&-`TUP,LG|EY n_w2)n-.oX16ӱ"ABhSWng=c<rQ.?D՛;v<cƿ~_{ :a9tzo\÷.Rs\r >ziBW?%VmZmjшDX\D T M )f_0G1ܮN߇ WATL4<rB('ϼsEkE 1! YkMuybmb$G3+18Z=|QR_"K=h ~'L Cmc"Bw5$?PUD1HON&i Ɋ%AN4H\&ӂ VtCW[IS+-at<i׀bk~GH2Aw'A9ll| 5ȍ)|>.5Q&=g<vۓ=Ohz<"૸.=ah+A/@C@JkpB'miX)iB �Tuޟ$BB4')]E~<#&U` fhu4IP kjFoࣉB0휳w#'H&ڭD@Vb.�@<layLMw#^ _2^=Ly28ϹtA֙5Ŏ`Rܱ`+Ο$ 'e1 }nD] ("tNZzwvXgT E/R($ޟҴQ=A=P}Gk,LS|wAڂxn/;m@-g!EC-X5C\&҆gChGgNF38P k_$[tѱ*J!Peo_Ǻh$*A! I0!4a4G o ]q~+==+ul?<;ooNy:C4hk_{ö٣d((io!|?`Wdy`ҍ@@25ë6=B+#ZخƆ@5$-h?B!1Ջ;pӚPy~~E~O"1=Zf<,# sԡzЊ i0-R�c.SKھxC'6ēB@tcC-TɂC-[}0Ra#b^%?0G3A�-s<�ZyPJ8utZxJ1-O|Y !׊fݘ&ݼ0!N}<yIwM L_7>>|/Nr.0[$ۨa,dBI^tQ;Ԟy Ρt,>őCm26 s+Og/ow9G7ୋs'~KsTeƘNM;Jy,ugW&:Ւ~r1.}pYH{d�Xppٟi&޽Ȳl7$!R$Q3h0Z'(c,I45VWר낳g0O6>IiڔUIeit:ݻ'뱳3YqsvmyT`PZF;TUAfTUI|OSW^jq=w$ قW;f3+\.|=f3>׮^�@mmU1iʥKsYEd$E1s)fsF;;{Z ?ܼE];mC<̯?E7O׻d4s|3/ÏI;x(=|̈Ba; {Οi�nan߂tӎ;Sڎծ&v\򊙃ԣZ*'dNHщ͜@G`'bKtKZ4K0C!B9dʭܡÀY <F(,n@](uGI;MRK2GҘ JfѷMzhY|Mh T:u4=%` cYךguXw,"PNb:3IZ< ]! Y{e(:[fۚkEX5 Hx|X n8,w6JH@ M�s 0TBsb"Tied=5U%f-x\Aڅ; ݄ $?58 ZQeW*v_k1�@mTV,&+v׍@t&Qx/\޸UJʑYvIt�Q6Ҹ4Rb4B\eI{p7fA<89~Q?,PG41"j Sk5P ٔcV IKT]i+3$FP]{|0J=iۘ_Vc+]d* (lXPM2+Zư;vKǢ.6.A=> 0X{A!c2J#E,InӰn $O5t0mC@rj%Qs'b74Ht9{uTjm j_W09]ڰ')8HU@5Kph$(3kN;*(\=v ųWPO~bYE@UWȉCT/lMPo"G:b:DM ҧ\Ž3xgj*\阿;c| һrt/k0C:`~}a9R8tCYM k9EyHdl͟?ǖe<?aujb ayR<&vNq27HmEPqasxs`רB4Vܦ-ϕOtyA{ۣ7խtw9{lx_pMy^org'rSUE&ǒRkr/GP8K<uͧ;KUyx/=&؃~>=ZO2$crbK" vRÇ׹%W y~' U剰5((!M32<|lY?C/[_{׹z; ^b6/r]vߪxR_ܕ{j?F׸iQr5m>nqjgGC4NsA[^r-? zs'ZP<"y( P^mD4`41N|4$1=sဲ,IӄFFV:2Dy\oB1q&~τbFUWa$ѱ=){rո7UDX]]emmvޡ*vS>ƌ"Ţ Z"v;mN8I+K9u$[;( k"SC)!I{q>'EktK4#misQ4λW^e«G}DeTuha+$C1ݝr<'8ql/ xt:$YZ<SFȲϣtv+ȳ;sQqB-`o?y&]G@$M:覆Q�Vb ~FᦁEבQB=GomPB"zI,UOي 9F 設+1!!K(5T# !$-H(`SM"@zSxt0$MxbS' 3H$Q'5nNKul4 Sѕ^aZ VJkZ=Aao$;Dcv0e!v U$`V tObEofq"77#jyER#0TȖǚ -XLkJ!ie#u hs|.v1a& `L'5bx:TCm.^vEN\JAPI;~n/o$M!n! a'F%1c~t\cnhdB|xAC;>ZQ+O 30EV>ᐖfgdǀD)Վdj9)OE \RӾS?RLv߱ 42WCuY58E FPm3RJw Gۣ.j}[ׄM@}9Q5i!X|Dޗ@~T v>dN x-,!:s8g<[Ը:EfVxja-b L~ ~K Gɳg~gw1! cfr-҃kOBܰ7toC RVgY9B^Ѓ̏cehgPT #%8؋#sQvF𢨷j&x Cbo>enѿʄzH ٠EՔsPoY؜sMv8Y #k|4'oQ f̒vPq>9 Ȯ#&A)9\[ (B+i^?i�b!'Z2"3Yz DY/{JΟ96) 9}&qxJԐ˺ msMCϝb&;Dx@auk:A0o`uBb<𰺾ʯڗ_y>0.{h]/2J2tm=J?G~¡txx{?b&- w;ί}!L=Z\Cv j|=8JyϹOG.G՚?mb> Yf$Mp54[`I�i9Gk0O|qp2ݝiZ{!I6{kk>}xN0"[ M+kG QTۂͫdYsu>66v;,)C$i|>o`A)1'>>hG_P}?8̋Ţ9bQ0ݝPUe$" xY,fNi}bcHRMYwDJ[V׆ t{m>L&cp׹;(ˊ<]usΑRq1yg9~+Mc'YcY$ID8{g)"\`ǻ&Fju@`wl4y6'5 %`Z%\hF,GWs1V/J"5^Gp7Mq 8I9x ),P]!!5nJ7YSv~׆ΐھK7ZN@ .N6nWZ "0@;2Yud@fWnly@gDit}Y;ۚK4s#ݎaj; 6?}�JvzT%L N &j`w(ų\9+v/`z@[;P^{crX  5Õ$ez+iw|G̦qh$ @fϠZWqx|`acؙh ;t>@P9d[$&6 Aꀱ$ut:d,ԕPׂx|OXЩM0%A Gd㔠 7_jL�}�i5(P|fepB|ٍxu1Tki6dMe=OS<)pIqx'{i[ʉfyP:cꆐd+PG9-c73̩@:Hm{4}RLSQtjRcjʁE ڊ$$2yFc,{nS-~nb-Z4ϾT1/8wRqd¡C/->\x K G'@ )9 Ѐ6 2ȲG$#,0TƘm.ƈ T dGa`%Kfi\M_86xu&m;ǑZ&v%>U Ѭ\5q;QtL{>{mȽ+REExG�Y! upzFSE6zCB(^TTP QA ;Sd\R!T Tsh|8!~x<\a'm4 R|YFyBl gLGE7BP~9tj,} ayєeN|X"7!j6Rd]I-#TF%g4$�@r,+~kw<FBi]p @49]F~^0ln(gWW9_c_?ʟ$\|D4r #w'eɤn</77\v gN;*+t:oK/ny<HWA8 ģw뜹x3c97%X7|=_3I-ϧj'M>ct#0i)x_Ln؍95l>ݿ{AP K ~o?[do͟<X.$y=Imkʲb0mnv+ $&ch4F[ ᐕJsX]]ݓ�t,EDra<׺[kC$IB@ tX]]E+5~!>ħ<o3M(ɔhJMq.z Z-$ʕ (rۋkL1:_\\�� �IDATuD ;\!Dxp$IƓ(JEK)1' Mp 8}?|nj, |JE h(OAY,fb|w֬K<q%KHR3_1&5R5M a3]CKlS Vt]QZa"(ő$uP QCXT̯xTzZ7<zy-˰=:xw6+vo:À($ ��ՁVTmO d0�_/71yEdWԄ Νݨ Pv8u6,󑢯Q,v˅bwTBcHZ1q>6NJV: @? ) ǚmͼ ",a04�Y.&8%P46U?nliV4i'&$SOmZ:t,}\ZXY@P3 3fk 4s"B (*"X0hCz!4a~@nRt֝ao`(4-jLx!FHU:di(ܷdB6z׸Fjs-k-KѿjAk=aGCʀ؀Հ=B ;]'J+,OM( lFVQO~$q MM)=Ev[OAkv9Ͻk  YRԬ Y+U̫)tv7 A7@LoG'F)Q4 szel@jRfma V%$xԲ+l6eC >8bּӬ zcA{OcU[V# 9=q&D_ Yro>P7&;xI0L3"tagݖ=N8 NM]p-eA[ܵ-4n"Ov1Ô$O"qGk|kQL.0U PYi>TL}ǯ;xo(4FW@s.,gcI@oeXZ@NSk,% n9|/@1$t/,A~9Dπ 7BɠyeŽ:ESWfhN8w\ #~_ O~8i[<bا7lA8syW~!϶… c<裼L&=E'?=:o~+4߸<?]P&{; wU#}]susſo=3!3g[<_%ָ+ThC4gל Guyڔqf}뗯_l[ Aɾy}+vM`Ɋ{N�^ylclǬV9yow{/nnK&^5IRUC.]w @dL] C&1J),ΦL&<*1(X,TUE$yNZn5 (- 2UϽl:BZ E5m» DEó3fk{ ~hCL6`$`͢X@Yձ@5mU$z=1 uo~=MzB|vB촖e&Fڦ-D5v *JA|J4#`ie A AP,ki`aBᇩKhbtʙXͣIqC@@P"PWs>Ր@&\o+. dy zLP ΜUXB*nt DrzE�Iϡ"t A(u@U Ň>j`ɺiEɣrP@4%JHN ktAm4[3j|[&m_wj& e<kt ~-" :9oC ^$G2)7 E l4]iv' d+HF˜ljƆr쌅PHtHE%2 LU#X]6& MA:6>~g�d=wi~p\P' 7kE{I^X:%¯EHTBۏR-@01%% ^mD@y!ıO?fs$ҰP@RVMڏH<2[ޯQe_,N N)+$#_Sެ/}$G Mh(̆nxXBsI;>3QG$d<9f<+ ^[<!dCחe,~@Ҡu jȒ@"Cb|ӹn$TӼ}4iNnCvF*Dk\a!j<#K* h:,͜4С#=v^~:<xr`Ӹ@"Z'(ǂ@ۜ 9 j-HϰWw>y߾+TM[RQk qYDhSV#^FmQ 2HAb@=%$Mۤ_$ yiJ}iJ!jF $:26V*e$֩~ [o2uͫxO2/z>LJ�ZRKFρyYŸOR[~�{[=B�"l8y8zvE@ĄJ.O؉ByGvڸP/N=}w6'By<rqʅo|o͋/IU8Mth\֣AYђIٔ~gΜK<3{`{Ǎ7뮻˿K^z=~CLSǏ/#GV߼M[ [ض;\l)ax<m?<ι@gM3t i8$)fCk\5O^vC1>d ̛sgDZ\5Aw ^p^FYr*V^[ȱduMs="(˒@`6ri\c7MY[[#RZns^t:( h4Mk,1&AD#D%,$rc@; Z=ѣ(%WR,<7nxWqifΜ&*h4fww̑#k=)c}-Dt1;N:Ƶ +loΨ4՘D."BUbTqPsϽXbtAw=i4ECQ"Ze Z9'2P Di@x. J$JB hIPcF:}hWfe;jNgn)j0FtV fI)7<a0*=PL]Քv6Iځ,LJ<?0 nCkh=HP9\;J@+V~ Fu0Q|pMses { mQSv-/X\X=Oڊݞ((v0K}zד: ԝʺhʊ#-^ !)fЌq%,4#88Զ}GJKoI|<qg" LǚE �S'2 W=Yb&yHdU[A@J4*\0mOgŒdf滆|}Sm|lOV<AK-ٝ2Z\1Dڣ Ѥ1 NX,ۙaO3ftt3nc k@h{ݧ GS%z'xGԷdYRCl~FZ.݇yZG5p+ zOuh;QcE@B8*(Z6 )%V L!(MP cP*0m9yD {PXUƕEU5ƠM9DYēG(Zׁ͡~7!:mM]͠V2K'$"k i"m+nk._O?A,-ՆtQ1N߰0t {oŸ70"<&x=B{t,Uy`Ч&[FJ-oi9x.l` Ir#lsNتǑTnW;RV8t]~<9cCT#,PQA6wj@P:oSSԔΒZI[S >Ez)d⨝Q.*;1>f0ǝ *1++@1$4ѓ`47Ab_mJB#}T7TIMZ,=ò;*/,k~$`qj!]3d[ LN_+sV\Z`<H+2229hv88 ߭z?w sw8Ϸmz&{_ˮﷆ=58")(˒%[v<Ȗ݈t:ht:$@A>HC΄Nt8eɲ$R)"cUX;qOkȇϹ!*9}^{>3X!^T6Zf>}E{1|MoGѠUԊ.xe_xo/�0ƅsj -G.9)^IΏvԧ?³ xWcqW7koedh53҆w<r&㱸O$>)€{QD*KڮKe9"xSSƏmGd,+ r->{Xᑷs;^Ga^5Tql6q,PRX, $aQ,6cˆ`@ӄ~UUyaWi~҅%F>X~lтy7or-7rv&9UᙧjXLc֭[LSx wF+pZxk =s]k󂢨8PW B]t:9^`0`)zUR_ >I.4|�4p$kPR,VT%(˪eGASV)JE! B6kpS,f3�itzL+Q`-uܿ4Z53Dޣ衣,DPXW`C!QOǀc`p'<:D_&!YO98㉻ːx ]p[n=`FPS4t* u \0 HŞXz}K |. LևX!a;l =q&BRA$d|X @eLֳ$GyfAQI[k8q0 Tu-иs\ D(pۡ; ĽԵa54cքfOOBԘ(#{{4s4lz=L*C?:TTPTX3Gzn+g?7yDxق]1 ~P2~!SMBa=-ObUA \ OteA VeW\ &d1˃\IGl,*zD^%zCs7x"eҡţU Uh u8`ᡴ4G e:B~ i#u +Phh.X={~QqQ[$AkTl""!IgV Ϡ{zI?~wkTi!mZgeX<EX,{RbДgX0/&SlaXԆIa؟Z 3!k^O uݐN[#d>eZ]:'KJB{ҭub }Hf-$#Op' W<O8 Ma·@h^$$"T}Mi7G ՆdR+߾Q…pmDZdiSޖD'/K|;);D%Q޲T% JDYP5h= ۿMlmW|J/<;"S=>_ !hiRHUpPm;˞^ &o|ۡa!XcO˿/uKm܈/VFZD<}M\|OF?%yzKƗ.!4(8e;;i:Gʂ=Ǻ<v1~vgݧ˿o`Jl:Dr<P{yxcy&cؠgX"B%&1)7\3Sש%ed5$©$gē)ZTh*ߎvm]͔w65Us4<O;5~F?G|Guoq;{>M]+%b-%ŸHOxUcfC[A- ӽcNŜ/ zfmH_QIQV8g)8X,U t:eooo>>>ﳻ#j(Exu?z@Hk`yB$Q] N#$x"e¢(yw~6k\~:/l>a0r6AwHudcs!""QUιXQMh5%"w:Ah^K!Z}G`e0D5rttD-[vP%9-UZs#t:x|4MxᇉDěoR`xBS:� ~OUU( Q1e𐢮x8<8$% VOz25fi_DܸMg{C0Z)u݇d8[] U_WZW ³6PMz\-IRZ#ה7Cs1 ?'@f"ꡟh?<Ĕ44հ<kY: <2ӸܵW4ng\ڲd=<>4FqpWr(bhJVfn?QXػrA`ͣ{07<g 1x 2T 2)a``9L4,(}HR: V"C;z ]YPg$E=,lmށbйEӐyZT4D<!f dz5&O?c*FIK36oFgFYA#$њk7/D"KD[GHe^o`HE8iCE6Ђ7V q!t,)+`}vNGp^O #=o}BMU̯JTe>!Hr~a8ʄp  f 0ROY/D[mS)IcuqXK,ImqSXQ@4oP2�!<.@XXLPE´ ɼ2/]1Bc<΄ X8#ϻ7Kp wkPH4Blw#uvZ0O,̖_ >>V | us"<j٭CNXeGˇNm%y@9 X&١9Xլ='f#>L;4aZpL\kЅ>"Sh4DS!7b"-( رXUKt` 4ƚ�E[)MXb(akiЖb-* $ R!FF:+J"DV9NkH"dE'}teT%I}T!Pyrn-VLxo$vݟ/M OKiYv G׈�� �IDATOKbrՅ omQhg<O^>p/ܩF\ OQ|N{Ώё+pIx㷯x.!z_:ǝM=޼|{8>:PY3tx<i(o8h@;OWkPjO;*.>\ew| )uk|$'.әTx:ޑS~=Ŕɋ{8 |;Ω_3nJ^C]}?oo]a6;i΃¶hN_==G_u,e·y$^N&Rg/p7Ǟ{<{_pG=g~Y",#M9[[[#c$!IZ1vvf3Hp݃pY'eHya){c k}xG klmw{RUw9h4b22Xkthgp]Oo<v\XEa a)˯p8boo$I0`emfmmb�<7޻˃=իWI�DTDQpOɷrZt{}ሓ.n:96dmsd Ωy^Bs\afkȣG`-D#Od4E(br uI:Y ,v(0%_zcL;hI {45fIr/Q̳owpb["PuXBQ5F0/=qq1;ҎGg3/-fcg1v@=C<j] {poOqg-L T XҎ ,O!{OSO&5G;THGHG?G=U;䩡i<>V02O8ddM=i&x:[{X +sNѦ'zdt'8.X-arʼcsł,#w\RyA,<J[ G>:~B'cH($];#߳383 ʌT{ރ 68 ; R N^K']Epx|!,)ße@(ޖ{d,dM -Om`59m؃=O|ҁ4$Ht"ͳ ǛS#gNu.B a?ms(SSܨӘ3>v]X{5{oz;Y F54$H+[8'NX Wn96H "%!d,jCE$_bO @XES%>cTA4N{ĂV4[e.1$<Gi6r@a=8̝02A.ߒߊ&DSG[fRLJ_t5zfbД& o8껸y.[I!$*4 rU*vcT%4g >C)BJ렁cktIK\` "<om?ϡ;=TGgtE%)*KQicT uÆ 7)fLأ<9s?=0GE<P3ެ(VޒȖҼroERjopN. Yd9@R^9]n.l'}u}_T5㍺1dU+Ŕo" &ʊ6wX|<6f<@q3[ܼy]޸xGT5Dw 2.&)WHom'ČJ7ɚg?$1k;[<vkq4s=r(So)cR! w^DaS7ݒ?_r8<nYH+_p8 @[2})Eiz)fǘ;w7ȵ^h|Q .!0̡1أ}q�@e`O CpmeIxt:Se;.GRNR·|c V2@feJJ(&MR&LNPEQ'i2\zUUDSqzu)ᕫWid`V?qzʲճMkR,K @)?Xt<Ӏ`Zkb:#>EQpyfY0u#>4vʠ,;)%4^ahLgأ3LQ<PZaG-k "iJW)Nhbg5!ZRA-FЏE$(kCAcBm Kֿ(+'p_yO ^E9h FdEa+weD'Fֱo4DUTU""Y?[M0Dl*bXFk$>X STH;>gF!h_L$"\XòX96twkNdġ0e8;opÏZ$zFG'>mY+jSqҡ,=C9%=tnد)Γ` Lǒ.Y ؼ<S­@{;ˈbF] L@~͟{י!XU:1[99@ aa[:s0 Qa(H@zPb#O]EE#nK[ գ gxټ4x_[F)S:R7.eL^jk%:[ ;usN v}Q#Ӕ?[6ez{oAVښ+Zr=A+m+%IOaeah֡P^9oiБi)zxEV!^`xBX62�$&k<t%{* VV ΀f\(9X<~r=)yZ D[hhQVc}y3ki )@pt>q/zhA{ɽd8[4bA�\hoHRbGd /4nhs=$$ȵ /uX|+(: Ϋ@.  )JԷڈ=!nNcsk<I;`c;0[`E~0Jj.?ҿR#DH߂m̝8c9^`fS`Y̨gR͎WW65;HiL'JΑEоN+=?{1>}ۜ O,erzޜ| [\:9ImXLs AGxyx]w~gY~+7j[Bg^NGҘ95mx_V\zޘNxyU\o8q{\l>)TǨmH9v]Ff]3i3潌7 MLn| F:բ&~&rWR[4,+)OtF<$R=s_JrSM<$Fڼ mZGt yύ`#9v|wLj\^&|p.^SCLwpXZuġuBS ^{W0WnTWnGC ,?ӂdL0BmhB)͹M֤Ν޽{lll#MRvwgpG h|6{!б&Q-x8x&Dq=+ `H ѐzɼ.-Li(놤XMs8BJKLY 7np2'λ8q{kTg-!0mĠ �i!1cB*(`!d*ǼelllPUk wܡiZs=u \.yA<c }66)<\Y'M3LYs{w.0N1:p|%1,"e#0h*4@6LHN16S #؟)nMe<r�YMPAN`%b%[ٓ4B}7S H$6~{#Kq!1pɆg,x{@)``*qHzt۱#:A\3ah 9Oi-utdZֆA&3/P=Di8L_KD^_D:qr238K\*րHGx |" _,Є{$Bgtݎ8SX,Y^#n^_|@ւ_7>dyh p6:~8WlZ!'vD}~Oq)Alǵ%aL[{iK#)i?FˆL1֤&2P Ay: G:h NQ]]ʥmIJ z߿,_ tW$`8`-,>qrծߌH/d*9H2^rՅs 8%0zIc’nk4II߫_w3>+LV]@ jhBPƻ ma04^ ;vx-ڢS:oJ 5P_衲(F6٧wOhrdErbq$ٲ1[xאdYp"dY}׼8Q@VB)W%[a ~ yRfÜ.B_:ND68jOses0eUkD5R,&t#ԥ]�TWh\ .!Z^ #!9q(h&{FO!z1z0B rGIwr"ewws-gޣq@q" ^Pc-Qaw;h()#EcC&$^f`- ۹?i9NK 5yuC:\2>cf'�-'Es]?I>-v^{G<}lP%4_73nz×mF0Skt#VR38eSgT9WqYv~h:Ru)kOz#QSzGlg Fye*$2z=ajT L3\Ť\lxKӹEW{}a'.^sϯGgKT {MkQgXkW| {ճq@ a'alFQ>z-s_gmt6947 }4{o<@0}us6дBJ;GDQD]7h H)Q{=G�qLEm N">xcBJGHf)Y=q< ʲds \o[}p&wxч{llǚn7oc=cE3dd`gs @Vl$:BiubVCRCF#.wnߦxj]2Ƽό�z>P4%;t>霍-Nb(, ,9""HN'C"(ŜnCۣ*+iLCwLXc*Z1{'=4K63(66< ` 'pw_X$PԂi-؟ Kx+HPl< hc|f -8:>Uc)^>ZЉU$T{#YE} bZ;ȓuqߕP8=0(H(fS|.8;gz 1>k+;V̭8X6<Бd \f:O;44arH@75LBAGe!vVP<utdպQX#!BKk AC5$c)z3f6qCd:\~⁧i ~ȣt 6:~1ɡ+얥xđ^hL-\S@6 #`'�F4ga4E-ipF?Ţe-MAiǛ�!C^dc쌰?2-d<z,aCX#]c:H=[H k )G,\EhyO ĖAEcQ]w<C6?]] E  R(W N[g/`iHS(b4cC,ùw>/#c< +V$x&A?BG:&ՒE1QaB| ̝1r;ƸЕqΡ͉-AI *Xj)ʊb'Jt`8$sH;3<j[sℽA0i=tAV\b.`AM: 7؎ 95NB=L ރ/R#@k}|8թꬳ"XХkEfd fHN<C ٶ:B6 eXkN$FU_c-rR-F,"/*ĵGTbQ,<}c$˹ԅ/5*GT`p> ضJ[F9w`)q9w[;7ڿxzgtsbSqL9sDN"][~kF9*9lJ>9ıv6;8FUJN-!pRv<8RRLx\9j7)r9❒ .02]>ɹR^|&#z|7fRk<|+{|2V9׺O?>#mB"nOKN6> 82Ms]~MASx{Syb0& 5٘K7٘NJt n/*::]8eH]g4E3[̤B\{hAԤ2b:yGcN!EQ>Z_GF̿[_aBh!rU ^Qcy/|>0DdpD-X,O|=G@ RowgVܤer߱|9DV(Yi U]|>'cwŘϟիAQd2!Ib~tzG(ȒES$&p$MCi̬XP55YFޣ,8nْknA' fa?i,J<!>ԡ31\agxfd\IvK DO9@*MUxCUa $<iL@=Fq.vR!6 Qc'SdA*H; 52*uJ@.4#pe�=q%=D 547I)kYl :D>(9'yNeq* [/EP ~kp-$#@]QEb D)vU YB(UڻL@dЎd #) Ҿ@ kǞELn:foS9R${ A'QotdǏ]]^E[X\QȏDD#=pq!ڈ&qjm<flثYH*tgsOe5Q61t[?$Y%n5"sm>Ԓ}j,?b{|εLO"W3A,qG$ޑYV%Zd k�� �IDAT-0}xQmBOnwaȅ޷=O{s- -6i./J#1w"t0!Eb|g&lF|cO}͞Y"#V8>KzL qW;<uh!8'vq!F1zbㄺhpcGGHJjPBmL,j>X+sd1`p8$H9!ªKxvʞ]S˵o2{wL4̑¢> zp QQ,'zL$CBWcoef@9$ z~k-oŒq$S^bl6+kG ]TMAIզl['g[r)[}` 8; ` 2Di :a,/p>BƩ[nko.6RX1>,DY)9)e+ G:De ԶKہG 8~q̧3 ߸^dr4Hx^xą(84k KIw j!RA,!1 q#IY6eõM[C&Jܥp( 6hQsèS}Be=6ӝ9ךI;<d|݈a<?z�w6e9ƽ{?]8|MI-As> ? 855? @X2[j=g%/1ԳC/{.icӉSdG!w݃C"'nX+ ̝}zy`ŭ{FO`6wz thԧvL8뚵:x) wԦ˴�s-ˇnxv[y'"k ѯˊ,RR*( l6EIE);wAeamZ'?!oNb11[g8:3Y[q+,9IGگ"1@T1c1&h4e}},!q"IR1$IJtyBiF{!�V9G\xqP mNxLܓv?{'5xT 1Ĺ'^ 9j} 6W!6˪rІ a|؋{p?f8:8k4\#( yO`#Y1(9G hmXhTkI�d4C& =`xu9kplm[u^.bAܽ+ޝkG *Ol-YX= LAdz;ѕxh]]S6_ DXۍLƊE|I&Pң e`CuȚzWԢsGqDO)svBJl#)g݅Vl%~O( 3O!Dɏ %9WfeXeb- ;|8'cfLP4DQ\2ioT~\J6ULJE A BH$r {Btn'燵960*WaUuMg}^{zAU(1!ȝ%$Bv&^O|H#Lk謬N̉+q/c)6> f^9uƢ3D[ْ̓vVP5U^MnZňtIh?U!_;șWnB㲜xu@58Q 4"H$SӉmMd-(\ԨZQ uO32'[S\#⁆f,.G4ӊ_(G:cŷj ~ŃǞN/y83k)ɇ1xbsT$ZжR uE\>}+?ab\Lp8@%CzG5U*=7er=ʨگ0ʂ8 <n8Dpt}i<xxnɱjPU0 V<8놼sQ04C\shzOL."xcR\ѩFGԅ�ItmVd[L6*P!6ӦyjB]D(QCUC-z 7mzbI2& Hf(c5- 8H q NmLi/H7QPfxJ\YRW#( �BxCiuaQ1f �5.Ō*E/V qvާ>xg-*܏XMip/~˼* ^>PO5KyξvdOiKPy~<⡨C:J"t"p^U:DDZŜNJnQBP#DZtbŭI6t*X"&I iBKk&UUm*?/|zʯw3iy|3#ͧy~giCbr˗e^ynYX,*{?K[+1n<؊S 8^0l}ZX܇ܱaollApn<Os6oy_W4f&;d{ׯWq+ϱ.RJR<#F7/A3l}%bO{4ؼ^p4([F#ZYh$43]nܺ5oO~(v"pΜ;Ct׾WW{u3og<K~K\z '^R;>s?kVVWɟ|^z?駟ao/<K,p C>ԓ\~G}$(kJ5b}}v(eYe^7낲 ye4qExaeRpYeJ)vmpޓ =`R"uEe F'ażCntۂ1 >@2f)Es&x멷_zL;t1QqX(b#8~V xUa5eQQp43PIʤqN!8HFrU瘸y\zć{8jR(S b 1crKO ZA{(q!l& Zf_czm[v*M&ZqL0¨y-LX? XAr FJ![ K)Ow(&2RQ r( 1l Ra:DeYJ#^:?0v돈^c(5Ѥ'sߗ`Aمb\Q6C2^$+Hu/;?~ҫ{^(h}j VqMu-pj\*9Ea5]㬬@)O]iw<SoY^Ycu}$QMP[qoY΀@ϩ'tn@c_wq(- $T [vt 9A97AׅNFPbxT+U_늚+W_q ٯ>fr?ΰUDT5J4utϴɫ7(xs~?sk+9,c͔/ kiٰ#g6'j2cU4 :1^Mݤt^MRSO.aާf,f]N ,H`+xt%G;(4ΰDt՗�/Oj^aS͟JqjC~Q x5o'3#}:z3}i-GIԊjwtCTIUH# +2> z' JUDR &6x[x%H^.O)KzAgoR\ܗ@,dG ?ƙ{,?r(D 3R5Q/'n4ɒEh(O}gkcPƢufDwȯnqϲ&n-rlk3m 엺.7ITNH`Oxwb~< y<<k0[E-W/Ȼ?z7:j?ѷ2檛hQܬXeى9`BiRtB 2;X5؈2d#Ir`Tl<V_|"IdC>n5st\iz=` %|_MI>pf}sn {1М;-vjqgy~Z?ɬ~I`'"eI&"Z6iU]˚V!ICQ" O<d+ k7{s+[,? =Uى=:7 XXjoo%E]pr8I}�^ I>W`$ NBP|?z^2;Lc>gU2/{sck,xk{:}h)᧸u:=�N}ݏ?C<mΝ;ۜ;{3gΒŚ!_/O ^<h1PbLdZ# }xڻZ$afГњ4 Z~b3NuGX[]jʚmDk&)!vڌߖdzHHN!*`-�Ʉ|s(o@g 2:Js?; PV[6!WQkX jqޒ=SeoݘW2zH"ÿZ:7(7 KE$L]%H۷}E?`Gk Mj+%Y7J]ߤA .8 _ P RnNzto"Ht)KpO}?>抢"G %=w :U!hm&jRU8DB}�h(x\_FO?O( w jcFm/;>~v+CH5xQM+/TcQ =s;Y='Ԥ )=pJʠ60GQ5^45tmԢ8y><AMEĦAɳ+"W`Z@mRxkg!&팣 `3$K Ŵ`Qtwặ2*/KvĹ_mqFAtU__))22#E N Eg_(pk<` lvU㵥*^݇Ñʍ_6Œ EwS. �'U@;75_b\Gh{6Y+,p/2-s'^K$TO f=ڱd]rGqx829AQ'D©][aW[ qfv,Bejo=jMR* jwgHjVU\ �Z nJq{8<OdⱩ&2Z9s)3ha\M[rGh[ ^c۔`P;EeeTڇu3+T1eLg#3fO]]EY*Lؽ<U!Y*Vhc Kh&gp+~KnȢn;u(f �=Q] ?,)= &ӬB� iY 3jZ_Wyÿ3O<ʽ1xaL>/,J%r62A ]oC֣.yUQm~!5] 1^T`e)i1*R9z Fbj/Qy jqF'idbcwpx4<bv[&y~u7,ۗ3m _g{Dfo)d�%[zeߘ}9<ksZ"B̟e8<<$"4eggc pthZ)ZIڤh}CLߺč^[x?L;ÌܸZ5$wܸ*#p7>NqAŨ�1A$;ԕJ0V16F3q>Q'ahM}!cjWx|DUUln!3,_z Μ>.I `x<볼5IA]jg<'2q`J'?atdi\@<(jy&gΜa1"^(ʉ&K2�{{{inLӔZ<x.+6$1IW4E7:v%(TӖZi+g5Sb+n\QSXB#3 u[EpA)0&e E-4ĩFPG *=PKkȋ_"UCēf:Ԡ"kE9TSPc(L�؋S!kL j:P*h@BVl.{l [~ _EƆ_u�va=@%`Н 1rEyȔ 0.4;Q h bqCh=Uq.}�1h퉭`k4gj #R`Q( B f*ANoWSաJ`B>Dwmbg*qhDTNXU3FاY ";|T (({ 76\5JY^Yg%4rD,SOn"xYTBsbz<9NΫ=WřB1]B,2h(fq%hҔ6vw@@2Ctf!c#,Y%wZ{+Vn3)0EQ㇚|\ϫX^9*Ussd?D#RJ hB܎W,^ s#UF-c=PJ%+W(mho +Fe !pBϟW :?] U(7U4|UE`NjMǻt=N=O7N$ 6x$H̝cpל9}LiqnQ56DAk t&> ʮx?Fu^Ɣ3#)jGG DsUEeFߤ΅7/ix{~&9J** ;`hj 0x.ujxS bcߧ?�JzJPPծ#_ UWTc-HY�Túm%0J̎9zc fmUۋf[+;FC4 Vc0Btwٟn_}ݺBnuZR蚑|u4(<ܤY1A HkFC18j'QLqcةr>m2LE+K2 k{l=ls(xۣ%.ĆDšk;<a"wx/RSsk3c^-֎Eβx8DXfܹYbY0fDʱy�h[CnWM[AiJYu=ˋ)En c,鄵UGĞY(1w^cGv8ԡ9Br8xco`<G?0 P�>sY5Yspp@^L]VVVx[A x>ի:t:駟&-UUو}=wUZ8$g'�n<Ϲu&oBDH -ݛĉfwހp<V[)˒m>~K~h<g8m\pCYEHz(#8.4(ZKelmm!"9sdB+ML&)7oZXºhZo &GlU u3?5j _!$:+@ 6z&3)vo(^,ڐHB+2�� �IDAT#H SH6L\3*iwh*W^[%BL+TPafY(@ށJpBQhN R v5Dm!5:PLv[XYBAp5ȆX!.Ǒi Q !ƙjϸqCd!n kqk[S!ϖ Љ=㩡,RQԚ+&$m*zEhPO<(b- bmyM5(SB UO@0-/?zCW{T)YwwxBp1hLRZTMi!%^y(QDa8VHRV$ŨZe\e"5(&*1zYYhF?|ʼnj `]xM+Հ Z{Mf(FkV 1tڧߛyХA6N`$*t B͝/5)eyb4t0+�zfRU5JTEc,+L$ tcSj2+0x1aW91K5)H38GL/�w R!@Y}c[8`I n8 X]_GfNށbkfU,yIjѼjE?1|AKBa{4BͼHjҥV`;:}x/?O=|Fh_a6BAe gN.L dg#{*ի/ mU8 x uQp6>ˬ<~SQQ2ʄvGیoN(w}7/R P9ރ:V笗YǷop_d|`/%Q&ĥ$}QU<H9U79!1B`v 0M%./Zs6'1&H8WwY~t}|cg6\f!fNTK�"J)RmIh_Er ujR%c kXT}⡥2|zBܒRiPȥݦ˷6zX~A^q&&$ ϭ۹+xSMIWj9׈h@cW? / +3br16ُ-P!i?=Eth49Geϲ섓py9T[V2J6bsZ|4=2{{SO?dgқC;7qPغxw󖷲uk;ιV^2XsxxH�Tp`<27n창R~ύ[{g2k>N{ cV'hng~3L=FXۿ|fgdBe8<v%K]xws.^*hQ}IQb8vMOFLhOQ8N�ĈbmNem^NOO}"eXIiWㄪHQv Ϭ5?:v m$4mCYt/Eׅ0a�v iSmNV=ZV;&zwF+#*W^F*A[@\ L+C0m#*YAlT͑bXiw<QSTR8:b ~;B=M@H): X#TvN8б@} %3Ɗz$NRLp;5vbY&`CM+B ^4"= :*@M꓎vQuAUΪpè6W5PC9Q13B0otJh TS!Ԁ ̨(B`gMC43^�Q /M'TñP;, :qXQ59xC>| tk՜qP S';qۭq_{B%TJ/^ `BK⼣8c7klD 5aT�b<.\oeyMKyJJb^%T‰k^yII:bH#H!N-qijHu4I"ZBim Thg^Z5iIE;PtT="iHcpr ٙ`mAR<-DIHw<iEVPMv?ҠClg!t`\z~xxмW 1;29Y;n윁y'wҰ"ME�ZV �X`stt;HI@OQ X(\݈)p?D~i̅!/].0B"?I_a7b ,\\48HQ UwqxQ>-tl7ֹD* -APݝ׮I̞7v-?.f8{Nœy|.Fy;{. wR1#޸OItL{+Wo34?ᔧRf׏8F4Wx-mGN&ȚvL'8a}} ݮHt*aЎ<ƲBʭi 3O[dg;LN%l]o|W^||<F#j95 K� Z:XKZpbevoN b |;$b5sZL&DQx<>1!qh4& UYr;oͩıyAwD{hm 0}ni>w?!7Rj[H:و3juuڵt:-SDqxg{Zπv?˗~_su#Ξ=˥˗(�iEox<"O~c\p5|aM by׉cûnyK|[0{pH% CܙxBB]W$HP5^BfLSZnNO3`yb#:xmL#1>IS2bh<$Y^%J@jhq,7n,يn$t;%$ Sοc娎\DijoL0M"b({$eE*Ad/yUS /WMxE2{NH(G-F u*Q(ַ�mG|<^S8E-P;B,D4N5ſDer(]XӊJQH 1ܳR9lKn`ElH}eO|֥|T"I)hk?bT/ש*ʱq8߮:A5|ָBAЕ#m%,RMs=m%xVz"Ln1~(lC=:Zauɯ DRP:̿x4BuF+A%5&v(1=$4>`WfGU9Z5ɩuH;9/AkL΀cž�~2?̃+>YUf$QGE`wEs*R>VJa")4#qHO*c M" ݽm:&zh0AHU|䩄A:=ڭVZJ%5q8 #_+RQV#J 47 W IplN*GQM!Dgƥe|�y"5s2  T4Q*uT0I0nh[|&Nj|I8ne[W!kcu#^>-B-J9x0oű'^w6 s,HҨK!Z?J-* rx=>0Ȕ1%ez<B)r5ugRy"">'9�8 kAِh1e^J!xcϝc 1FOu2ҙuDx!!REY;jI8PkJc_pG_jCizf>'j1c y('9Hpg[,oVwl3 fZ|Ws/uNW`TDŗ^W_}[vt~c-1ǴFY8I7_Ư{y?HQbbǞ(gWX~-MFO6X Dמ{NSsC~)^t+g-{7oSJjJ9bjslߙ{?fW G-$.y%Ǚy'ۦPsycš7<`J$ YEqE74DZJݦ0Ly1ߟ>h<nݾE;Iius$i}qWbV;/_Uehu);5tU`Di8<<ȧSvwoEsVVW:Mxat:tgDcC]UwȲ>Nڼucvx]P0﹇R?^qy{PJ3F޼uW>ηqz!$c_lƉZK$Q{$!666ǴY9V7p:|;}%As, k#8#2Vڌ:&ܸ͹s_85+kC؎@-xaՊ|/$EhI5;녤]/GDC; *5lD`ahmH`N(,<5csr H5!Y10$Bg hhGȋ`ZP dMÉ0uWYڄ-Ibw%`m87JfGVA HkjSjBޝ-F52_F#K` 5 Վ=Tc[" o3į֌_P-h@MGl lZoK*Ҵf:CC5D\H,؁B)]E\ P݂dS[)lr/;?~v� GyOScc9LDBp6wH<&QJ TԕVŐ+.ѢqjO%=dP%IUO&OԬq5 YuQ[3@] q=%>P q芃2 R QYSuC UNWxqGRQ9&Cy #^(B]@)R5*YZ-AG A(f4Ҍ׎Ixb( (8)4S0RSVjS.XHh>$MTVW- }^9@aIK7 GZPNg@|m+tZ Xr5^Fc6BufD61pl;eܙD b ̂`DDϨ1fmB}I@3 1U#5hrDDRX{j\�<PMĆ4MbN+2J+i(p EE6N2$ *mw:NLnc-t;dLd]lg1Qmus�{.Lwƨ7[۴~ܽ1O4 !0QϪ$rV0c ̆x*s!ʆ)�c?!vgU\Daph_p<<8V]&as[9vN9D@e8xقyσzp8o7_g}iR_e !ўi?C/{Z;Q7˗yҗF$j>,oztw30wi9/3=Bo2?c4,?ߛ7-gTUd2nKYZ-z{{{L&3 0|Űxm1k+hzP #~׃3|"r*v4`Ej>#Rt7x7x_F!$ ++Xc*Ix,_ď1oߦ*~w~v;cww`~7'\EFl:ŕ1O)˯ņ$x˴Zm67P:bv7oկ|�<Iz?>8gރ1 Wl)XYYT VVu <gtU4ot\_'+n̙S޾h<{9}+WQUuБy61vŔ"38 ys"yř>񎮆V`B\(e>T9( ʄ(USA*bZO1*,T6=nHԵmaƕpPkDC֒'Z=PHjmm1y8b" uqm-KL \QTㅥDg垐%5Nնg4U pNjE &RD^+PN4 6hQtm^ƪ'yVpKP 8ڇ@ S%>$K`A􁧸% *0 qfYCrJ #:p+4N*4)?l]GkU/@9B4%PPP9m]5Z_CȖOb2\T"(%B6l쑸$<QTYeAUaF7S0vIQG=6ϝemmXW1`QsB3BHg B/؟pI;)kHD E]*2(Xt[*jQ]-ALEA1!/{cKv޻Ϋ}o̝pCh2H1RDY&1@q$Gl#C8H6 rȀ@RlIEA9Cp3ۏ󮪽ʇ]utK�=NzڵO(ÿվGV3x"1h*oPe[om?*ljIS(BchH!jIlRӛp&Pbт\1'p.TI{=ژ6%J<*0E}L75J]g Eꗖ<K v$ќpa^1m2sf~1U5uث(kvD˜ Y X�V �,DJ MqӲ&G  0&*`z<%DCxoD]qB fvJE[KBi=#'ILp (隉FXa<ð#g 7XVz} S EAֱ)81I5j9a6'5rF}ݒj6O1dDN?d3l<:bm} &+{a ,'9p^جya)&9zwt`NVw:<ʝ<hK/7 nx9{ g>`Ɍ;X_Nޕ1*%lV2}q>#]; 1vȤ5a2pFäTnw7S޻>Ɍ-Q(* z�,C+89$'cﱓ7'�cUYǏ1 Nl{k$S+6zw{2c05'˨z �󜍍 bLd=lv m"> xꩧxꩧ HI1TR4k+t>qOUyxETY樕zN7#Rt9ʲƍ\ ٔ7x^Gףﳻ|>瓟$9"F?_W c%g8!"t:+tUUb2Lx<I_ƿa0ϧdy&oq^h8ݣ8Ɠ!γj-泚sjgт_~C .,Md;0c}}[xyGͯGx?>ŷߺp| nZ�� �IDAT 1P+}GY:fGrYm#$o¤QJ|5%VO Q|P g :C-G1$׃!pJk7KSk@u pm>얁y Β[H甒mY!SEfzX?d}d$-c=KYƂ/LL +]윊lu!ΕR\Ug0By*`K~ q2X͕)԰^7�IX*PBwK )6E߼[*0,R*CkaGZ.q7ߥ^ۡ>ITJ(Iq41<΂We" fbJyx`?Qs`^^)򩽸 sa<q*9PZmp{W0GBb)V(扉]hbs݊|$Մ2Y!##˿ŐVٺe|0Y޽魭s܃lnab]q+iAm A`>-DY铬E xMqIW)Q4D oe FFJgrd^MN{pGuQ^'ߎ .LaP9Wa+֞6ߔ ݤf4rX D!:K#*6RL5! B BDMH$[9Q (K9vC94C٨QNxL:j2DŖI@CJ xƻooq ERGyNҀD1E%L1},bn<=Ks~zy]%l-@ ާEMceh<:ggO7Jn-#B0z{#fO#uDzB�l=Z$IQ2'!&B"ʙ*?P*?+$)Z4QoPD` Y?%}H+_z<j*6l׶xzo:b�FGtwգu# GIɊl/cmhi]MޞۗtNMX_2`9j0Ȕy̪. nlK.寜ԙ3TyjI}Lvyc7c?b4.M4iňi4LBrò}�cf񮒻,ˠ_~&V/ϡILmIeĐ՜sfB5-EENd.c2Xw{}HSii/vM+![L !8́ YO!&c(!~^G]9k\ǖ[xae8CSV3bΰ.<@wSGd2s1c4L*/O1˄lFɱ&V2\VCt<x'pe<oug?ŕW0Or%u>o˧? U& ՊIYVLFcΞlo3!.鄷~<1ur}ď2^Žij' Z:I4 s~a`P|Bw�#C+ W@0jx=eNuTFu`# 7KLs@~Zɶ%E]%!C[dURIG# jf~'i :mX'yz l-w&PdBC:LAUz+  @QL Cak;/"4/3ߤg)V0?)N]XEQh)VMaة<&7/cw%= [ }#_a3֌*ac< }c@A(#D(N qg4h.Gop|w9 I%\Zb!]Y PITA۪#OhV`cpyװ}vΟec!%|^U^XXU%Hԥqxe.'`F�Rp鋞pV:;Qn+Wc6v,;/Lj7j\sd]O>k 3Pgph"pHnkHFw|g5Yhg$:-eC1&%tW -�4E&Sst:Jc~.>TŃ$5S 2LV;_*hڤƮVxcmoƔWM82@_) Cv/'t@@Ϧϟ쵏D".${F=NhwnG[m >0X"􌟽9%-fg@رt6ITmF`6dkM92{c Ei;hrζZ)сx~;PCxATdrI f) .i][Z8N`mIurP Gs`"/3 ڿ۷@b.!4P`){v܋A[ueW`4'J&e`V9$66x8Tib[Mk(޽~m4Q6$,شnF ATҥ96NqE6N<Kw'4Hw_ {1ף_[ ~&M -eD} m&FW7,h^y{p2G]~2qM<u]1Of?bfS(˲y{z{1a›oZY<w\rtB]<3 h祵: bj/F8G@#y40gcu`sX]]MsXɩ LYAVÕemllZ/nZ Hk͹pkb [|12|S`89/R%ᥗA((Fc]7_Cz 'e6qM1NU> 5dE ]X~0ɽĈ&4k!4SI$[~GR^2 QȰY 06cƟQk`´N! <p7fy> W) B1@n~ SCsy55sUTp2u[DJxa< +Śm�:`2&b)y7BV@fS'ȃµˎFg}1r7c" Eu0 |8d+HdEB0^̀JR4*a<E^YbdMK=[ jku#.PLrȷ3OQ0TeMA߃EAA󚚀 r/k^|քLJB!Dɂڛn̔.<ȹ G=2}L_LоEL.!b2m`v$:|6,A&iH4 "i7}$czTؗ3ה%H@ .On`azjzT"E*Jt"Ld=&)V|GXX` )"ŸdYqcúB&T 7 N"cmy&چ-$!$eVJJsz]ȓK-2=dBJ X`;D(N4hEj4 TX)xZT6 7=}쳜?&Uo^#J@ \X//ĭf,SD"gil%VH SArKL&WRXxjeje-GX=7@vzPe T; -Ω3]1? :#L N0 r*6�9L"4gvA+Jг@.3ZJ,iVCl\aFNZ=BtZLkr>|bQ$hYe =Ǚ#`�:$X$-G:-XS-,VVNhdu]$f 6M1fTU7$IZhhw�x^9 %Dm.(*JlYF͛Ɉ,ZҖ|[OVc#2ÿ4wa@}'TG:0LS&ɢe�ϱR5ʲeY7 sI3<y/k)%yQDS/򂲪<y_CUUEN( Omrf,^?O&PR˃H\xMStb=4)T$sW]c& ~HO{Hs/ ޷aoor^bLrJuIH966!TXkrAiz|?\8l 1&bwKfpj!f@$-!xvvvO98Cf3*/LPG6הs9gsk9<'lֶ�bhDEc>2 `3ٶ dY$+/X{۬|_Ao]xcLr_)Si"S6áp{2̖|K0::@_B+֑4NYoބz*:Fy3VL@Z4u{H}kB,NU �[`kҍq�fYtCAf{0pUGӚQH tCK3C0l"%]@Ld$WIm%0Ɠl22`wR!vui g( u\oBN.•yFFb?ƥy+ 6+U&jŷCj*C34u"[V}[P%jy"koG *Ũ%zx9ޞob\0V!L̀#ѣ$hħ]Bh,iMPы chQ?MaO"ᛁ+ s5ŜQL/O~a-qgmszr1a,�)7j"JlF4OGrl QD\BIh(MIo0UT$\6@ctlj>.a0p?}T[p(1G",&*! j<C[ᡆ�ڌyN**8#l  cP2Tkl<O{Uh{mH7M%,o)ؿWb\1le{?=\Y[ xH>WnQwr2WbH?FuJwe@9ɷsBqb'S4C 93 vK3L7)v) ΀7UBXX ?a ťGL.z HZ#Z5G[ ._:}61S$#MYh ܫ|/t9 !4`Aș W{8Z0&.3 dIq֕:YOݴ X {s^{c}{N,]-r"i\^N~@5"YjkA!fZbNdsڌ1˚nO Jߡf  @mkHP<U9am(+<E#"y\T=+dii ,[٤(2PŹ4 E71J;6H,sАB$z+W2ϸwHW[q|3?sevת _-n^Řh-FI`@4/U5G -ݟ>8}{| V1acQ*_q.:wyJ[p+XDO?泋L#>Ã=Fazs3>Cܸ~Zvv΢q&1 QH9o삫:9Z@ Td?KdY6u]SΦSt|0vɝl(C) ka0\Xbخ BQ`y! 7<nG}tO51A3YxEW$O"ue*ĒThԄS^)UfSǤvӞӧBj08I9[4Nym9 c;Lr(ib!dED^@``HnpTMc>ӪB̈́Ēu"&SL71J03%t.WCMq{+ :Dy:�YfȚ!;a3)}=ʧ^*??0XD?D "%ٌxM6�6)aMe]HؓlPzw"ݍ<p"kQ|#./^~A4Hγi"$,#QK6WDDR"ּ EiZ:.R,jB:]ha2M2 %ԜHh¤"5X=YY\ fPNDԓ)j hJ>b*i'_(`O ?>JI2ľPIP׈FK�KtIchb`lQ%:DƳo_~~lZbp$e]No#Ct>-:j! #*22gwxYW/#̒{M壘IjHs_{4%X/J0N{ĭQ2ͻMB2y&#Cg=Mg> C^3+[쿰2 9p]&w&9?^zqoW`D'`#]k'CBRZlj0Mzh7]%@jE0KmE#$<l2->QT%cD0$E&6,r$$SK5@ZJ[{s` x;;TY$x[>㯪j|r_8Z]NM͢U}>ﰣ9v9]<c'q9ӂA{uR[@ZM%89f!X7`QKr_8:~cwL?h 261~<%$\F#BAS!..s]\WsnkA& VljiYǥA:O^00_( dzZ.>t1 vvv`mFxBBJx7 g-b!wY3,qe69$ ulme82Lq:":*gbss{;L߷:p4dmm7oO3Mcc::ap8duc c {VW Tuz!Ԩu(9yfI}tYR(Lxi pke {$tb<�Vx%ʱeES&!"rf%raSY[䫊)20}$S;mV5:Fr5g~ư8 MA.e Yb2(g{#a[ȩsH=װq803IP#TްA{M2*ˡU Q'^\3 :T tei)rm-9&`6qO 6 H4b. "Ecn &Jd:gW(RGX5T jl: Fps2Z#O5>-?=pVES|U0P0q .WĦZCe3\x n"HĬn} -ܣrd8ŦBb Q/@�w 0r1U }ifQݲFL1#~E</ 1"UgH/-"KBYfYqM:s.ژ|mǰnXGP @P;⋞ɨ"TXК/h󊐙<K^Q-M`cb2hb4T>2-=!V&$xFnMMh`F>\2| h#!(f(I-G)HGKL\}~0�� �IDATsSKFPcbL= _mZ "M]jCA"mO)ͤM@Y 77mˈ.Sclښ5:9F2Z+ |}h@]=[  /]%~S й wfϠ=JwV aag")drs3Ǧ<m\ CY?wH `]N{�3ؼK1SO3柂g~ I bD1bÚa)mEZB8J"ڞe=aL[w $=GX9fe_I`;Uﮀžs")I>Qo@h!Bm~+$Ц 8&=¦ݵL+?I׽XX|}mk " HwvVVV?t:g:1`1OSH^KޡainzD T6ySMNW_c<g_?Xa2{gc1K9g8}zcMz ):ES5|x+/§>)nK$? gq/1D'xǟxhU46"CV,ſxbh4X@tF~e%M6W`k{S̭˗/ȣ y3n6nɈ? +6@Y+<+Ծ;}U:A@71L8svg-}csPKtҰ:Ubr L=JqkF,*h֑st3:3xV3C!(ȠI y>(&B<] LT5fl);8iijI)fO`qGb#HLUaZ~-LcjG>bֺ(#P:CS5ؕ1 akҚ7Tsazdk%ԕP֖CPAF"j}EppTЕT#(Fp]zN#XC(a΀dJV]QbXHn5xzFzk{xLL(T9 9;!8<�hdyr,~"+ RX%VRe:%Iа)s}Λ:\賽NnSg0&kxնIXKo*(t-jpj!dZq3BY[-pCub_YH|i`ĘP>Q۩( T5 oet(Y#p9'}Xp+'jY`[+ ՜3ٕ@gԡ%M4` ze%EƜrf|QzcF^n|w\Vk 5VLSM-9vTT o/X,"1HNeo(okCg$ )XǤ;x*qtɬlњb`5%_f<ԓ&3 s.p̜4 @{#ZuL]DD% a,ݧ&iHto]l&ӥtYJyUG9L*j?^8ĠNJ5/`Sʛcc4)#t,PЀ:TN#9Nsoޤ8Mu6,G5bzǘIZZLoF=h6ӀG@S` -6fl6xR#dGpp+J'۷ ӽ-RE$%*wUM�UU xd.H Co2qhgh OJZk ݃6n[Z9E8Іg؇pl+K۶|kZ/+-Xw{tU 9/҉c eIIVNpJ& wy'?~'sמGess??AU;o7�ZR\0Y{_Ĩr gygO}Uo4 s7x lZ^gc}ټ_假o9='G~cfxIF529<<ڦIz>Ν…s8>|#Ig$kG%[\|bssnt:ʕ+<L3%s9׮]o,Sd:-ʊȅ Q\`bJ_YN'Ve3Sx;{wNCm!e:b0?dʙ3;t=n\F&¡֩%z 5_OYFWA+ZRwAj-Q2eI-X0Y:g u@3%?g0}y7PERAAv! R ӀuJ5R0-gɛA`*[;Iog !|֒XJ {R-'(YU\ͪ2xP>΄p*U 3@!kLމ0 /. @JLLd[՘=76a67|@Q4[_@aNb᫚ZDr�bbbE8El�vEp=AGJ(ЈYcћNhbC [xL5-KoحX 5K2 ~w dj#~mFi\H'cn,!I}JTKD}DTj oӪ[la{x`(= eE.` W,P !ɷ Yng{R ~x2> t63b_) VHT2QDJH%д;_"q%xR>%CiNoEfWk!Ȫ2ܝ)ݏ(O͙] S�\Y@!9w^WLQ_LލH8D|p%64D X%OO>?˄2#U7` ya0`$XQO̹9104m1I߫22NYR;~%HxnZɜGn.%VDwP1fZ2~>pACt xwη}m=ǀ|UL4%U! H8SUpyFd`"ƴ=i;`#5Xs%.o9W*mxSsH'OЌ(Lާϓ,YL l@.nᯍeN T'*n F{(Dj.lQm!�=<lj3}uB{2,ϑ~ jQF+FWj/־7<,,R5qhϴ_8$#zrz<5,OG^wߏZt�|ߖ Z:NJ&cL善q6 ]+G߽|˭! I]ljN|wܳh_ S5_WN^|5>o~/xLgӴ4ģ3gVkh4o_'ʕG++\r__اxk_e}}9l%ƀzxa< ->~׮2osug c Νg4y'|:<G>buunKl6e</[v)$|0 ^@Qt8}yRV_sg5wɳd/>o>O=UUOQtأsYN w';("0QUvvvؽsC78<<!PUm|*ϟg:rMN:0Y_Ye:@t05 }0(9ʪԩ3TU|>[NiQd91$clUl.`4Y 6سpn}pi_1m Md*ڎV¼LȬ2E} IBj et<3ԵPk!:J(HI4ѴIu ps&\c 5%縭rʼaBmquXVRLa,XY:dKrVS+B=f@)afnj2f+Vdʩ@-b;J>ӱwt B ]*/L|GQ |&TI܂ S(A`TumELOL(23t)!Oa"TC@+aww?]b=W6ϩU&-,lMLc#36:ѕiO XW;wbM0ucW0A &MXTd`dAE&23Ym:UCR*$x̊#O{odY<5l>Tb<YH2k(H BЫ8|{{'cSHמ "IP{*J-:S&;zHG"ĺ* #"<D{k 㑡OiPklnBmŸR;k o%i $Rl3J7벳yg[ORJ DY̚)pQB*<%S15xG jK_L?7$>#SC4#kCX�\T.~Q`iDJO}mޙy%}[[z^g_�  )Q"i-dPёD/qΡr"DRȊCbG %FD @X֪{/ܪׯ!i/ΠRu֭}50Vf&l<o@A3̧}Āq&U %ֺǙ7.`|*^gae뢤ٚ<';ޢ\…-4Nw/|J)ImjBi9+R\㍐/{Sw`9F+8@}xZ;UN7?I\):\NH42D ɠ}߹Vr☴dzu%Tu^Fw$HfѤn[{vGߤZjuqñ}=at ؕGZubTt)_@#vBϽ,lzLj0z/PClUm˗1xD@wJC%`Xk vc/F󂱌�x`7+cg-{Hh;\={#kk}ff\ LlqX^MGxaz;^y^zϳz]nfΝHC̰W,oK|ا0W.m13;_n&y43Slom\Ƀ>;DWɟ;8~T>M1.(Γ)4M]F!2rH?`jj$It7x)/-ݱᦛoј׍4<(]d-.,r-B8j.pQlf8133 B~[yd2:,jj56S]D*pY`ZKn~A@'MR7֙_\`ck0(́ij1LOO7zw}BZ)B,O,bf[BݓTyi�$. };Bg$Ki,ꖤu!8t1(~(m2b $ :E�_@9Tu(`XBͭ!VftbZ&T,O5cԓZz.v>n5\`rv/le3b@]Pr�/# ʠ^rf,͖̖-EAs4Ia\C}0t7q]8 `LJ`a)CFNă-btFEpfd<حuJ6\2(ÍhtFkL2\C\.)va@;ڃ& 8<sGIƲ3O~RYy)>?^ɉX\eR 2B?Y<[S0ЏqZ $4s )ɶ|,q@2ȱ JH-u([=v|ң}5\-Oe?0S_?q%>bKM3LxXLg7r#Ckaa@z5OE=Zn9xcnaƟQ+P($iIzG:ho-oƘ%疑sZƖ~j G6AĒق2KPꑪ^ 2m3$R"Rsk&#R0*1‹>itWϓi,$3lGzNlHe!lFjSsR:U J$QRrR<T19&kz[ G.邍?F@g̑yK H(P N 4mf5o$d^Owq$yBoe@N3uGa*MJ0pM9LиR恬4 6KBQ$9_)+EW vflXWVOcp".�P (}w :CnQD Ib,}~ӘPn 59ڵT׎w턧YB<YoC\^塲ӭ�*kO־FLK>vj^]n{Ql[nX5rS{;,ي\ݓ?w=z#prߕI@jZ;c ^xa~ছn5zFr77y3rw&Nw=Nr(y'_5NDg/m~hv0?|?Y\܇IJXc|g^ĠY?泴mԧ>́ˬ^>n$zχ>!INת^Jb7(Y4pᜣ(n㵟 VQ3)`HҨezGy/|X4MYYYOϒ9[[lnsڵ5ᵯ} z;0pСQ5[S[3,/-Mɲ6z z;=iBל9p0$Ͳ;h]jլ*8'e: 4eqt)튩Ė۵*e d @b*́瞃4#\<:NaN.F@h)ydI3F^~m-42x1y-<bZK]EmgDZm,OwS*\8<T#<=/ JC3U?<pVgWoJo0P\_>jn h ~ͼ38UT[1 oB8Ih _"4HH+l ]L RTI$k_fUg}Ō<`?6?%-J:EeZ}SߧXYm@iIY3^ a$bH'JVHsZw8ta)x' QVՆ#H#w$_塏G|s,;iJDpO|[Y>ם :]CjE>3B!a4%aBY:iJy(KY'`M907\?'=fyO?R>Y6YP>HO0J*^<:uM -%nyYi,!ZL `pA(G鵌}920txʭxCZq%_SKk,�� �IDATO;{fؑ s)S%4Xs#B; 0n{ oqiۖXh&>_l6>;y˵AM@@}Ln)Q|44W]% (}JaHg`zZ Hd<g8ړfnzV֨{0<palEOqzԲEehDgr]\}W!tb-"z9ӡ44NZ&1Cà\.%kR<? fN Rt>*JKW;$Nac@c@˷tI Y` OqzA6ȚWxC\g-U0Z;bfhtט9~'SNh -8#5>nZc#M#\ibD_⃋wm�J(F4[$i>Keu Y![ e k1%uh,:PgagN83fg*)'yk/>|A+ǖeiKB`w <;~3zl7_a#'v."Àˈn:_%+s8Ni\�?j9~<P B<w_wۿ1ロ?ݾLa7clϰx)Ο]a~<뫜v~?v[w<v1%>˯hMMw~Çl4pKKKr)?AWzלXVDOfzzVIYF1 .PSSSiJJjEq20??wJh4s25o=zG?Yn@{"#@%WznufPkW!1;3G6iO7pt 181jHӄ,ŗi C&^ Bfu*XT}bzc�p u6h#Ԫeb…*IE�3% {v߲UKXRD9 \?a)4@4 6jIՉDPh]�`:z !9O+-Cp% y<q9prΰ^sӐ3+W9r`49>^Ju=ݧ'p`ʒ&>.e!N!M`&j 6EB4t}ail{/dY80-`ps$f0 UI\a! B'KܓWSP<GHs-Lj[ŞcVOj\CSM^&\b �)-p#I2xG= Z#%gpGZf:"Eiuz4 <Go6=?dz x&06:1Σ҄:J,a1\I^p%A #9AFqb.Fe*$Rv  ͞5KD4i/+@(rQa|t°oMi+!`1`SAڞp9í&l?a/jK8dH ^`X,W.i6-\Z.,!T xJDq%FTe^ 2DDc@aS/RV5Y�Nm()(썻cE !k郴͑#c H)$؅L-$$(*�'>w?>g$Xz[\ң~3azj$8ڠUb'W^%]x f;T$3!=\.&iLbZYn ;YI,u1<_lXuCTNz92E>@ZV ,` wJ|;a2@q}5ҾPl!.v>epzbϾ J+nD|Dc�U]@o̿g,X|h|y  PAUogrmc#-}?VIJ8u+}lM~e.q?,;"BY C^ *1@S9bۭqy)Re߯[]}1x@+)ߕͿ_1XrQ9W{Ok-i· xC|Ϳ`{zF5w ^ y{ܻJDFQ~eNm=c lj*/e <i8:~*\rƓ G&S?S&i8s4.l59s wu7.[oc-nf3qBkt?{7 }4EY`Ξ=CK{|/p ;I dY 1LOp1ށQncǸr !v;,,b,4y \bR}&lmsQ~,,̱z [[k|k3 zr?sm?mdc:۬wp<vÜ;w,pΞÇX[gn.];_?I78~|?dvzǟ`qq4K9{,ɠgn~ }rupZm.nNTJUudDQ, E+A]XA#XjP(݆ bX"a ]'\*{za(F|l'J F۩JThohO:.dE6U-<RLӠ̈́Ă)+Ї|�:x-92lg K0-P ZiT{ѷr5t 8o7oYOQ@Ykcu$Y,^\162%B(=#H.Sd*$!*fsZ'0L,WN)(x%;4 4)#x)e̒ۘ'!ڰ҆ɁDƦ1X ߎ҆G, [xO ~y54Loʎ#2V1~T ״ e:@�&#rL}SԣIH"6ᚢf)>%FSVH1C$$b$Tt V]+0J0)I#Z3'8O&AKhvKN5hDy8 AXoOp᭐lMB-I !XI CLGU'xU۵MD#uֈp9AҘطJUhXm'LtAG ct]EQ 잘h7 `ܡ־HWU9 \,)D`9wHml'3j.M C(S1 x %Fo{w?Ǭ]䣟<$&!}[<7VWEp[jjniOC^%&2f[<RױsZv$s n6@yqZQ!LO)\Pl2[HMRuaεހ&br͛A:@V!^ݤ;AIlaѵY,sRQjz:EPSj 8jEH</9b*x}2޲>ʈbPMP$@7+Mccmb-ߔ) p'7!3r"@: C0w #jքVN-c%EcXS=j{[;#�^ǿcDZ^?qxF#/Yﴺ u?Bq\7[mTJ*#^b)s�\-u!Wz_Z9{7FAt4q& @xV~p"A&°???qg>ѣ4g8ukre7}IRU w} J)p}겲rw<CgYv[ouǮBpw7f3'`Х(.^baa~6 K<Ü9s/~I7 ΝDQN,(puu+WÇsE<&8zx)˂(7|G-0Y߸J{`qyZ6 }+9q&Y`vvFcGqUE Hgv_e9}e)[[#,,,ljg~ G~123}ӤY>>:0ư~&9>|G<G٧ YU!rQUx_GĒT ZƠ 4g+skչI+0[e*l/?P9j+&�Y`Z-R:c Fh/lXZL&4S yCɲb>DQ^q1Ėj@ H`r:Z䷼??{Er�= O^6p jO^4j9ts<8N浞]@*ICm%,@p΢"b뮸/ Jak=ek;az&<0L ۂy0&A锎l;hZ1BO!SeC 0\>J㮻Omu@2̉f>(Vm[z] 42E H[Pnfe2)ֺ%`Tu]tHvA FJ:Rۉ$jM0xp  BVX8$X8)aq,3V]*Jp֑r h q$8J:lhR\V2'Qz^¨VʯqZl%B ,rV2cH|7D![RΖHtH&Bb~ <HU` ~'W?*!;NiF]3A]eE`XZKY_&X=[_B)r8lE(؇ZOp\N TU[`*ᑩ�Aq(&0tl>\;GeQ_fcl$oƐ)p>&爵]Ū!+]bP3tyKkA)`Dag@Fb1ɭݠM=q>`7gIZЬj}ԕd=q~Hph쨐H')[,1yhXB_Ugj8 \N [#ܰ1q.KљZEҋRugRY љX ܛe ylK Dxݛ>vj5z|o*EbW< 8R <￀3:P3r3~;0×q΢Ub][#c�͘Z9cRzw `i_y@٤3=5%::>gϞ#og|Gq:snDž(KϩS+N8mFf{@C$vm=yan~V,yϰH'c;~ @v[6"sϝѣz}ָ뮻8qM G{+s{8ym[=33F ǏgR܏@,,.& ‡#G+!Ÿ⍍$m33;5ع{M'P5tujz !Vzz'n:mn\bff)֙_z{<xupQ.]Dh~._D377UhZlll0;3#(g0""4[MA%YM0Z7>H3 Ob^ $dd4 Ȧ40î%ldI``nG]4142ˑpBɾv 7BP *yFs 1{0b)IJ,I"ufܐ#=靘EȕX} RZYcZ,E-֦&5| ߞf?l|SV -b*+!kqk2PHzR[M-ͫyY" 3& IJC>2rZYBy/U@j  3U+$npyn^AN@vlV$vcJ,Iلjj3wk+zHgH(a Y2xISN/UF ebg~с 9j$zw Wb͈&B-QVì2b4BJ4Rcg2pjPe}Q1A+G96Bc3B0 UV< P0i2)4k  % $Apqj2:!D͆#ń@ DPMIP"TX59Jd5vxNSYyP}j8)*Um('U]\lOS;xQpԩS/e E8u]3DZwsC4DGx6ӫR^ޡaOz,0)^b1yUCNJ呙&D@l I)%]x`Uq6 _їA JQ3�8c1֐kZ JF%D1n%l@kGCV~!^ ' R_Zތ箫:urqȨ~z.~GXuvʀcQQu6_0!zn]s3>R9c;Y{H5 #;Ȱ?^juavvs08{;;Q֩:0Q;l/VR"czvƶױ;qqm{<+|9n6|峪NG?fvErv7܀NGC`}c{Muk^#M KsS{W68y7.[vܤ}3Q4eaa׿u<p;:Eczͭ #G1;; 1`k֝TǏ槢]-u(5/,azz&�h)8:OPvRp4"ajN׈A!Kd$f !k`hZx_|VxUYDtS>'nڏ|;8ʡ#Kyppy_}@ŒLhv@ȫk$ NG# [yqU\zc)4N{#OS1et�&3=o6̱ג&'gG*ǣQo> } T`z6`mdDcWr[J nd0l-sBzf,, a!mҁ2 )!i1)p̃%fė e :@n,M2N gV2Ld[إ}4IUTbl If;`ĮP#$tApJ5ϰo ,m65ObCB+MD驖K+}H  J$"&[{) Jc_EyL3 ޠ p=mR؆ -zwS&mʇ>/G7dO%~Clm:XE[},::0JfDuQAJx:;eV?1a A'Fj+Ncqǎq\~4. {=y@<Qxщn/V؊~VѮV1�;ץrF#T|iZ.SS9IR561u1=4*IRb0֕,J#0b[iHujcSwTU+q$Y¡YJ3y*Z<J &GNXL�k$�6 ٩_S $XIHPFNB4F''D։1da9DM?�` &(^&1X`h(QXw&z.Ch4[I sp%! AM)�� �IDATcc/Q_!/ `'5Deuu8nVњ5ɰ# TM0W?"ZBk2TkvlI9"1V-HcXv 6Y2V(i!(* :2vJ�HC7dsEY -JUNAUf�({Gƀ.v\Wv~[ %Ut9#La/`#P]γǞH(F8ƃ#^Qr̮y9ߊzu>` \/2>O/5ca~~XW^V/ow3==]x$:IHvftBܵ]m ݈w 4dNܼtnY?u!1DT "dӞkAxa~L܍( 5K(NXP76eW7-2^8d/alZ.JFᅸ *Tn M1a/?!uA3*^=SJ61S@Ar÷1|Oe ]6ݐ0Z7 kΰ OZH!11V+0am[-RB.ҔJ\I e7\b6iV@d�/Uz[)ANb[Dܾ0 y@fakR1̗%zPbA3B30t)""m*I$IR煲(c%Bm`+@uds%:Опf)#3NYz!&˦rezc,>\[60ZZhzSm̑Yҩe@m|af4x")>`<[ Gvo~-2xI"+[lwUxOJY\ Wu!V9~ԨFhPéc{@iɑi&Q=wJʡ{i|[1~Hͯ#ѓP51flGbobi�e]j_ ZyVOoQzZ"3y:x=*FȡFM3%!dT+ajn꣏CDl@EV $23};y|2"נ?&XZMb#*ˡ Ij#}/I>>`"i̮HLu !3"VQ_3 Jh&Ibn&>ꇑ)ĵicII4,ixS:B:;X�E!r23oX/(BL>%bK\N5NV%EGW*f6#e4۪\Ul'";L%z0<B$I6rCpqAI!E$^FcP(ңIDA$LpaοaN6_fcsp8 eFud樴 Fȩ3rvaU19+J`! {2#t'>^ q{:PK dm2 )D%pMw>P宧S|6 !M鎖@`^$cbocbwa~7̼:2o}[y ##?}|KP4e&":x@ROrx /cf.]ѡ|N(<f)PkE �HԐyUv֋ v{6j\1Qdջx/X4 2o5zuWPꅯ;~V,OSFc%x&ΣVZaÏKrs̈́[IԢ>Ni|+c$ #pX姐�Fb B;WnYL5j,x  nh( CPzkIS#4egߒfuT3pmK9{-R+4)ҔÆzKBhCGa1 i`:ģ`޲\T(iDi%x:eX 'LnH�s2YlYP:p"dI L@QʢAс0r1&G?0̴CaPgmHf9aZ7ifHrCH!ٷDֿF& !cerin HfPu.aeÖϳl>yw7dO@+)2'>>!x≪M2h6q}7:F^S?~Ae?{Wg0qZ 0p|2a˛"gΜŗ|2_u>_&` &| L0L0 |n &` &` &` &xa` &` &` &`W9& &` &` &` &x%u+` &  &` &` s` &` &` &` ^&` &` &` &UIpFX㉏6G/rpȯϮ1i*v_?LrrcWWv8?#DVc Bx~s_LIp_ᑫ_{|_?^m.W9^kz]u/<e靴{,?}?Y>O2S6srW)G~^{? ~-+{?ί̿>o~WxW"x1\z.u_F^?o)~ӓ^Zp$=q'γ;\C?>?˾t?r߽r߷}>s!jOy[?Yn۹x/|?/Ǯ]ܵW.n<uZڵ g[_~dƫuuVci}fwtE[iBMz %tW *ņX>bAAEEPPP@PEi"w- )pnB)󜳇Svfoywvf]\okQz*!yP/yBKt *j%D e gMmB7 m}.㻏xuDu m.,tmI d Y''0maF4BAh�\b8)0ЦM8cs!lb WPQҞ}lRry6y=;ޅ~#؛e6@]+N>`Ha ho J~~`t!m;:>ҏo$0 >z?u|%Ah~@a41Sv|i‡WA ,x٧=#zC˩BGJ?%z#6SR: JJW-er.U%H!~Ip *ǵ/$1?H2H< Ǯ!yF˘v\vq*Hcn� ;/H:d�dl(菶b�ڊam&yۤ_͇9 ר{|O|[pH; Y8r fc18"{.A7^msgkCd4;h쁿r=og.H~yUG5g̻/R[g1u<C-} ;?Uaīif3 $-2uۻ:kdϠhZ;UY뿚 7n,S`r/ƽ3T$d=*l#؂nA*(J6Jr{P>Ka88`'f,\g=+]'E 2(8r_#Q&Uh)F=ڐRGxόZ|3+fsw(Ţ0B!O[%ë˕pJ RUhuOnIi;[ey%!qy= uƲӁ2[Xꝇ8}1d6<7u:L9ڰV_=Hӑכ^wYL_R,_&ݞb쐦8|Eq7bcS6tq.f>˝nISٙ?VHZϑbuG8DS+1(][R GqPlE9ybR܃8@AY[sAv˶$o}3+gc.⚄twrkŵnH.!p`AIOB4[+厚x˿ߐV6@)\kAE0%9}ˋĮ: :_u@t~x<v˜+A\c(z`kJRO$=!Q)=_AsHPѴ޵lf.^fb@MfǼ,?j,OQ/2mM$]>ɾPvSIf7Uv#X !H+BPɔ~t.KGBM;.WӜ5I6Gn]ε\}aѻP. j5>]>ZVD*?>q3^ƅ6T[д> VpsfFW�5ͦ44iu=ْO [l'7U[ym)4X!Y~y~>D^!5iPo_㵧]A`f93xxƑˉ4nxPcA _u_仧 NNan8볨)u_װYyAvM?sva. 6Wm G@'-q\U3Zo 0qyyZEoi_Ԙ#>5^]|JtT8G5[Yxۿ- *ݣ 2&1g IȮzGα_`/TIWHIyrnqJ4X5z0]=Ο핗8ʉ#'PԦW 2>/0e7# {hh_Ԑj%@W~%Xlr@ @W>R`KDI9.f;d§owJlC|T jE-k995ZwgGMUՀ'>$ZϠvв#2Ȓ  % YK/QU bwP?k$#!%K9j{)o DMͱ(hd^Ӑr. Wl@.  U̯ӧ撃5�:q"5éW:w? zPJ/mw}5-4xy єFe}*gDȁ\o;�*Gs^[ZU pp@IdP>+BzW7Sd טּ7o<p5p!юl,E& >Dsd~N^Ǭ#v<7c[?hb6 [l,$7g {.ZPv"S,ɷ:J:<B %4dXnpg1s<7GvŢ]M #ׇ/3\HRpq|}9_Im56!`h$Ը|i̚J 9O0c3krhH58h؎l{sW~$Ɋ 5n#W,y|LY2k+V=ƈ;ٓSWzSvOrjۭSu/Y[+xm1gq}8QH",H8}!~ ;.c%$ambtL'A_&-km{%bIGeaSM'qټX'w­me$43&%ŒTc<~zm oǹ_$ADdq۳( wCH:)@xD!qeگt4 ߤD]/K" {fq~Q>lJtr? 8^! *I?( PTpq-o/ExLa| R<԰|J\IUWZ[D wRemQd_jHH꺷U&=>4+L4uk-DU/'۝< кX+HTqI2*6UǸ8'yb/rs{w @!:2ٚbIVzӛ}m3 k[=p+o.;/Th#}Уiȭ M"VOd\5kmʠP-]g\K %� _Ƹ=iMFrMNRms^x# j8 ^rYJ%leGIÍz#fxV%L?8ٟ3?3J\@MhsZU0 Ypx?ߧ93,y#aaj"P"`W $ZblRHv LHq<Q'㶰:1dh@e!aZ`cy�YN#6<]rFh�%!kyj3&3p;BNк#:R}];QTMn賝aƶ'̩ ȕѕq8RZth* F#Ѹ_K絤2%Ŵ"* ʱ_1_S@EWqBk.72:_;0GASp)浼% U߲æ3fX&8s7в/_LGG6OŚŋWMF'gKʇșy۝[֜ѓ<-6:3ٗ&덌JZE,!|55=nTj'/r$.J�[x<- oO^ͩʹ+.8cW@{CF)3(q5{ǀ1F54UE2ԧC['6�:O,S9"ѻ <d�..ϟME2֥]+4ו0z=JrR2*ޙSRHJV� ^qN_2VǶ~χ;[_0^gGUA҄j@[*dԔJN;5Kׁ?sYL^ 駷9ØV,KL9rh5>l�.%FSBFѺ#=N# n3kg[uaޝ8b%ã8.`޼[V~ E2fz7A\g;'4hk5xW.bj@'`=BQǵYktuóV8EOtz\lLxc3=NDW0 PBXn<;U|f{3NLcsYx"|Qis!0(N_9YJ OA$ƒ"{`!C=OHi;U_̄E>ƈY\ق}#sRY5c2Xbn_[=gH~>ѺtrqDң(JڎywN]ؾ4e/'zf#橎mdlxKs'Y{ƽ#I1+ _ABJz$\-Olo$*V)a`m+4r Xv[VF%&ќG2rH?֍n};S.;J9sof*ע^B5ep lV@S=yɠql| NM'*2!!9gʑC>Kթ{]ه�=$'Qh JQ{c2=;moH #WmC(Sqȓl*HHI[5 Hc-oxqmKA -\cXqcoqY$d]1Ƞ\z!R} x=\ IRP8W|ӚIOz#) PRn:x H~*q|?Iڌ �� �IDATq n4hjsě5a<x6nRBkE8X{9 ڲt#uɻH)Y%|.2_@5_{`5GY?JӜMtlhέ665 J4ֻ"B`p=~QwVE`U~nȀjO%|f�جv@!q_NP@.C:/_!El[ߕZR5H\e*h3%ŒJtLRQA5sg3fMNaB5*e}횳� )iX: ռ5?&Qj2G~dۉ޾&Ǣ76YϜ&3#Ed˽ԍDąuL.k ƪx;�$ B4TIKP tuO^} Fk:36^܁!y2R }βc-4bKNŢʔj34 פM�~^ MJ<{nL4eEfa'O2AS88ˑSj} jZ2,9IKw952T&-d\sw$T|g>8F) x; qᙏNƹ)qZw#}߭v|�)Ɛ{c4ri CҮ]Z&$O$YA9vTى8l uG_taǿc"݀Ŷq6_1,RpewM&OthSkN\6LH;T0[ e[Dg.@SZKHZm}/$- 8SyrB4IBpՆ=6 ~ѸFkJN�?!Pսn{cЂUi 8X=pm a2)EԳK{=<X,IB߿ȄS[F0sw=ϐjO6ƇgWlEch}S<p譥 tKvg%oBZY""8_W1Lx2P KsNM/,s4\ }iõ{cWݩ^3g~ەn?|$kH vK4oJO>F㮑ȸ7EJ:R'$׼.{[eN9#v#>s]g,Cn~?ꨭNw2LŮXMuy)3V@Ɂy9eI-CNo}4nЉ~ )z.]Ikj_,3z4? ќ+E˦OSMcaYGlIZphAQ^ǧqo8O>Kwӡ F0'ime*x^ĹQX+ L~"A0cl7U`M"1MƫluzދWBgf2cLWvÞjFW* 27 3ywcB}dI<X +8+`z^ ȱ T@&Ek˖GsV;O;:Wߕu  CVȒzv#8{pF&4pi%K+h0z9JY_GM¼b4V%2Ul^=-MθGI9x j@ttcuZwٵ_5/pm:,`4@ L$o^5]A1A!iT(l6bMǔ{8QIN�eC)̛!qܵ#ϯ.l)vdO?$5XNEECEG`:|<zc(kXMU+[b?ksd[p. n9?ܴ* TFx\Cj̹>TJ(XBTTEACN_ 6}=^[m-|חj1| 2|F37Qu ݛ!1y[cZwlL`O " F>/*IG�dl.4Sz"xg\wr� HźM C+s`L6Gatj1093u|LB\*RF%簂Bًsهi֒H͕R.]Vrsi)qħkDu)ɳ6JX/lUŇaTmFMZR,py&䀚C0)YDP+WOM $?AQ D#8']vAE6[i>̼/,zHOú{ί<AבrJHl>J<47\&?MTt$R挽܃6łM'‘|W\>n&*[is9-#TE5>J.ӻ�ߢQ5tw10 Z #(h+SCLL<[iGX_Gv蠦 EsD` ՒdH/@P S XV A!@ @ @ J b@  l[L$=bLa֟й FީD|s7d8>Rm0O\ Ȏ18^c7s|.Bfךe;ʉo^f}s2Wl4o;O f䋡{*i|0!iӡ< vS-A_2 "Jq– !tйhQ,k;ٲ8}PIGr6p8"W7Ek3! ?;tcț9r稥itkFXXl2f%|p{~-sQ@=Q5[uǷp;aNQA: 7XzIHg H)mއ HAzm 6Pj\2jA;>F=` og߈<xLP Q7]:0c<vcЧ!lyaC<\O~giC黰f}K0;;oG~*t.7J¿[oqqnpIܗg0Ysi peNM`gX\7zEͼt[*]~z֯_o9Z>0}t ۓ2BlQֹd vQ|G{ ($ZmETUTA976mm'�h@w'+69%WH=ļґߝk["ڌ ˵xx4 Hkat<S�Jz~&1~<S-–.3Ȼ-<:7mbӦ?X9:|:܆gͯKyaf\UE\? TNۮ`T~ݘTPϬb'�Hh|S^Ӭ_oq!T,T!usL (\8Sc΋w~f3&uC:jFi@S}tnXٟ!)%H,~sVD>܏M@ddoJe<xB䆶H#I�RH㌿Cl5{FT5iikR 2D !.zтkGmyX-Jae /=FH_l&ѯڃٚ%bFMϜWIp XH:dj Da>{퇐-mDKRG}JK!t:G%59 _ z-:W.r12} Z(T 78 Q0};pɜōQ9c+'%- OɼY y.cݴ-xynՉj-v?md`~ST bQ~(i4eB)q MaЪ\mw&X"?NrފJ2A:w.sq {% 0|s[xd:/PTl;j| 貼 j 7$_ ],at[I?| Ҩ  �FaPMYlƮh=eqУó3n[ q ޷?\>ڸ*olbjQmyjoWν0mɠWӿ{ t]($%$sj_ըӲ5f ti\-*OT:EsYIop8ڇoZ)ii2b_AmISc::Ɗwu1SIؿK4׍97y-*tT חJ HfU\yO#\ }Lp$ BbsMu^|gg1yY׋]tCMbg|)ɕJ / ֢'ĵ} 4\7uT%k!{d0% z%0"I׆ioمr:m,_ƻ}ajr/M(7�mru7y>]f7>Bg)e C[~|%x_˰~fҠ'~=:VXrй)�HWiOXnJ9&hY!OSe,..͎:٤_.Ht33S0zF(mfO`8.$2]OAAQ5[lthVpn?7 TK1]zZIJ{/C'َ]Ald%Ñl[ RBJ:ʥIxm67AP f-W-f̲/eb{Qgj,Z"t,w{!qF"Pf <2g9+V-czXOZʩ`B{�gO*BaTvB�W]~Kzk`DugT /]2I@_<A\]rs[9!|7&ÔD=***jg8B cAMvd T450{:M}d~ҝp4n D'-(6Od׌u9^dkˡ1ǖѡQ7RZIq~5ECz t~{YtPIHTvp ;<ZжIHqy?3J#t.WtRwn9 Ǽ/gC{^4OpF\D#xAD̕}DiQLg#2j*]_W?MGAb33_qkAlϝZ@)Ԛ-:WbiQ.^э_fM(+Ct%#5⧽J$ZvNSR]p <Mںpز R Ms9lWe\ބ)1n-U.a_!S/` ʡBX#ߚw}uk @S3`?/v@F}Z7P7 l\a叱Nck9U%da BYȫb>ێp!:S[jNRNro{H3sl%KF\ o`TL-x̝=ZE4~'J>QDBΏfIӄ^+uS#M 5.Oܺ M%s4WNe6 f{:JP2P ]B/e!05=FPu}\/)-:WOk]KSxV#c}E>|$}7t^2۽B,͒_6Am,QZ.ҁQӤ.fD]Lš=oDBUH4eaݚ[\ AXNyHkz`Z`7lyy}xTKPV�[ȣ<3Mb1JQ0,CQQ||U9'>E=B|ARU1\?H/ߡOU"cK'dyuy9Xuʕ+Gzr.YźM{SrwӁC{*M”Zx]/""". \P:fR挽\^V # kyo;} .Zka3BA/{:M䃱[_gq?-E 1sDp69JvɷqU({l :gE rh]#Y "RPؓmw q3– JBŠbp@ 9bp@P@ @ b(X @ b@ @ J8bp@ @ (LX2O8"B炒^Ϛ$A l$ t.(a=,Wعb ?I2Ux@F>т>†{2#Sg=O,Q.ݨa|[n*hNҡׂVh74N[b1+ i xjvܟeFBй$ vnM C&X/'yV..廚kĜe9:WlCU-vK/ǻ?M(Lo1ŘWa%sPҏ|qƒ=!ZzMg?MgV2eR�?|ʆl"hr0C!%![b;|4]9_?|˄GymT*xl%CM#4 $AX)OE?[l" (v$o˹fTMC_鯑G>a yVB gcKRhcxrt?m /7o=21+/r9&tEw<< l4gopTZ`jGgyڊ vK&}Z5ˑ1)_" VJeQ62PZ9d!kDy`id%+?g8vՂGt:'ۅbpJ{cmS.ߘϼЦhrYgAA t.t~/u{R>K҉,a?zOM]<EIbם8m E?q b=x#KVݤǍh=W\! ͓mla x~g[Eq(X/ENvv كUNLh&µ~.䍾<ڶAG 7"3[.sxiSFgr4&u – [^::5�?Dv 5 s9x|5edџ ̶!h.s%0MJ-&Se4/ϧE.*yx.ę̀S߾ʸI44;"QB&ApWxmPeޤqsWgA ty @+ɤL{Vn&kߏ"(SG@@뀺i.1Gee; #zA,e1禬I7�:t?Ʒ'_?yCxr. ޥztokiGR]|micHsWgA>#l9–�:5r-2jV=(Bдqt@& Ɏ +㋒GNS*m)ZO0y F}UgDռMyKg\-"`' ?CjhPL[m 4rlcOwyUαoyk$j΂E\DQ̷ 1ۍ X.ѿ;C5RcYJ|r) [-p#s_~}hR8ٯ:NWϐr[־#IhLQ}~sOĖS]po[Iq�% c[󹯳 \ййQ| فI=ؼ<R %ښ=ʺׇ2/Y0GNf4�� �IDAT݊2_V,})z{?O0ڄww4!McH- 8E3E!8'r.)Τ@:No[ؘ8<Y $ PQl, ՟DzCv[ ?:\F-oӸT p ۶wI<gѻ󕪽B 'Y!Ǔr8usQIprTCk4`A8>j,7-$ t.t.(ro!nv>2f S-\I`$4P5Qӕ{tF~i[βoK-Ò|ik<yiik a+/w^jB7?ʡܞ*yzu3ΐ: sAEl& 2t}; kAve Α6 *pm;ϗ}}5 jGxBz.K/ۈ"e\+Xv G (7i$ݚeZy _\ййQ|fc�R's 샯D\ ^ Hp<3 <SK~bk3<kUsg%*TLm5eu~9IPAS*]9j2Us2hHLD AQJ,'΅K}]E7.SaOsf*WOLa|M+P-8w*KFIҗsxĻ_\=썾Z>䅾ZUz +w)l7Aأ#e9{\ййQlf |(M!x&EMy*|L_ kM;U;8iv(;eqU9|*ե&^N~ŵp^黋#7Gxm`&k-ZxʌmzG #Qۿe6=&&rKn-ث/Ѱ k\lqE[йyI U (M@+P`>xnł&9ekku Ѩ/~H#(VrQO/$fv z%?5Ԡx?Hmn>_J3:CkƼxV.6m%mi/h|1ϽYp[.lyI@\\P(F 4yR~ 6gi՘  Qnd&%y Wo*6}&w_ X$W+5dQrs6<cC^* L`y8 ]<G<>^YhŽl}:NS261Xn#h|ZKڣ\gA~ t.t^"HN⌑X: õѳxwBRQ/c9/VS'm'6oMjnL1'@򪌱TwL9躕t,?"<;`w w8'fb0xx>%ywNħƣh;x%XnE: a˅-/  h'@ >Vrʑ"WOo""".@ E9c8Wf P@  φ@ @ @ #@ @ (= 6@ 8dP+*?/Nz\,qmAB\P=VF "#f  sHPhk>穦lck ؕ|ߞI1wtxS"W3pQyE)Mu }xUzpT_| �m!= fe myCN%P՘2o#[^~1}1n WWRl+BwON-,8.՟'<,0}<.ٻ:SGʟBrvz] ܇ᓖs8P`[M1sw/i:ǵ./_tp3<s-O!9V|7m "MF3?EvQ n`EJu~䣤o߈^ԶR Z4 * 0aXw:wߨ(!g(g{x?6rWً1(̔8|^ahwwWsʔk#?9'@9NğK;RP%ro=r^wBa+Ows} 91=BȣsY0:$$<uNET2R(*kAoh~A 3w//:JrsW WwnXwg uI?kLjjMnB"9jw" I/2NmoQXv!nETzg ؽ~[s<Bc栱}Q!}'1YR0e:ы[lv}=,ж͡oaٻs9x2}^X/5XPy@4DI8<;c`fܘOSgq ( _s n{T/I?fnl`adT}Ӯ}5EaÔG1yab3o:ӹ;.:MFz7iY07-;togvwuQx+C}o~oFcx'z|5go.2YQҾ#z'J2׳X~3kI˨/^N7I͂ݵ=»0Y|5ot}>hԤEVǪ9֫HC~hRu2M 75 'j {󝞧wlhE҉ ĥK0]ZҎtsm{|g[mpo%xo6)�+ MffR#x[MМ3 R~ƺxR 6| Al'xEm%dWWxT%P2զb=[B"M;04gxՀߙ]d r)c0Lh@ $$@衄PL @ �qƽKVo[f#i%cdϳ3wܶw{ιy6aap{\|'N-Ww!X&y4wOf}JpYR|w-}|껷m10@o^)췄ZonYdkƍZ m�feEyB2g{uCoKri5NN]jkYmf:igpYa|6_F=YlM̒ù37?;|$G aڅDn9t{ƹ|a<WI3o?zƭ;Xb~@ G_;gskq0M_˼9s'ň 1M?.-+azǯxYr<pNj(65og=~# :W:v2+tm֤,˯Q=n5u</5xTs7?~΍v&]F*?NrA=Ulw  N{.~}L=x^q<5|빣ltB/yr%Lew�q9D?_̕ ;sMD޾aBI3!}R}4\p 0<BӔhc7ky7T<S O!ߐlV!&6=�7+ʁPkf)]OpmTc.M5s̊ͨ5T݅DGdcvz9?yXO0w=ix]x YIZ5 4}Muy~pyCۿvն{s/f]I#ܓ$qw;w|69S2v$QW} `O0qP)p̜MP7Q[}>?xԍ<zC_=;2f<m!j 0L07Yam96lz1}ݤe.?N~y9ݝ㶛q.l[ϝ5XI>K=ϭVO0U4˲,S\F~Qm~  (71G1q֮m!6-ލyВ"8"pyDn@ LB!X1?o� wĄ pq,ٔ فt.` o1=:sٟq/8&{o~؍<mOPHg?Y_:#'*f"Jw!;ֱrE} yEW:C~xP=H~7ףgһvN^eoqGg1g'3"սdof1Ӯ!>꾨<mEsp6Uԭnre؍߼L||Ï$? VoRMziq6AV9 n*uzT0@Qv0qts+1O"Kvzu7Nd'Rv9uVTͥ@b#Wi^4kq+?a3.v!v9.=t,~_Wm(#|́D_Jdގo8ǟ=7msp!mCsvPwQ[u>Lm؜y?~gr| ]Mwqiij PCԜ_//8筼?bBnʐa{݌saتF#D&33w R^r'p 8'lp7;zrV,SV=WAor])Ⱦ~a]4CVl ~Zyb={[pԅhS(KL™ahnŅ\3L8lzR1sɌFW/ R0b1Ӈ2odo1ѹbHw&PͫdwGƉw5Mh6>rvZ>Ew9]|8/n`9S*_ kkM7iyl6bkVy^hx)x#~تfoR$Jo:8MJM-. US-oP5ǺiobG]ǵ]|0hO>N% U |}øaʽ+9gIy-z57)FFtWAӛtϡzFmeS s/]kM}Et`8LskH3- RS~7%wOᅡ)k&ӿzn<{Nwj ߚj9`eZ1OdZĈUlz>]3?2oNLy6m# 5oA3n%,~uڣjqKIdfС RNіD1^FA!It:YѢ03"ínkH>ʆ"PWMmK)o]d$U4mV|)<3~Mۓ'W!djFΡLjtRG|] }.&w<jo̺LWQ(?xn UE머n܇3Oė.n2k!n9v$]ı׮o[9qn .m ;:h3.9nAۺոYYXw45]oX|/)yr#|}Â=Z<my99=|am#ktOO|{v5h8j^p9兞 ;_b7qXٽkq=sv8΅f*1~^l64lg_a뙄JKXou뺉c"5<XKXmHh'F/d,jib v;l!<GXq>6#g$Kb+v2G5p՛K,b -cS?"0fWʿjf^uBSqsZ71k ޝ9U+X=m9@ﻆ4-F?c3f`OsBy.8ǿYG F�a=NwU0a'1ց `Xf]md{BtAy+T?ọ#< F(0Wfd&NCu "Ȟ4w ˀ= 6_~1!ɞ>Wݴ3CVZ? {8|e%w6RxJ Ym{ ֞OsI-cY~&pO:m q3G}G{`PNٺYzZX{|=AIPwQ5ÎֿD#O}Ҋ*-e\m;5)iO}̪xw`$v,ZuM"c+ѹF=6Jό9ݝ㶇q.l9[י)5Ι֓d.>~H\N0?sKm =s>~,Noar;WWbgAm׆Ɯ?KƘV3eʻsE~;oKp7~~sL-!rƍ0>�seg䶛ٴ0`3|nK3-V>_xn9y]\IKF?v:'p~u^n3anaD]>'tQw'a\+{Ylv <4qOF_qys wT6>I WO;V/Sof.R?_w[Ms -Sv )E4<tڮu>BQxDH) S?{Xwe!'_Dh`F؜Q¬dB|hYC[~mYLyEfAK%O8@#jzSb^Ʀ` 9=m; ބ]Z;؛\ZG0~ߍ@Kq{ COwfZC9skո CvwQ5C}s?sD3rəMt?aqf~\lcv|?98糠r.=3O^S{s1΅-pѭa{mϜGR^^NcMuOEe%TL[\^Jf^>+V`ש {(B/D B_@ƹ]p0 .=ٹR*"\; ?AH<sG,Asr@AAr@N#L}yN{N+v;\9Djh+ B+o)@ցa,18=g`dc72 }9ވ2v͸ rq}ֽ5;l*|8>\H豠yߚA\pA4tm+||.d B:zra?/b?'pmo *hR\c8lt [cGsUoQ=̹+}gŤ'pЄ?2ݞ̘e;{"FXLt?Y7w^[9z:9jdxxϗG}I \Ώ#N༛^bN<5n9L:hκJtcIgK!�1do!~~D g9\G5ЉP$; �� �IDATD @'P#1=/|K)/dۋkߥ){`&|×.T]Dʳ~ow&E瞮)9'= eΦo痶Cjt%Ӌ[Ҿ;t=v.:ڨ{'|n||D&q?3밟|q.\)zr�p;pޭ?fV0Ww}#U2/]wFNMn#/~F+QSMTWq՗}-\?u)md/Ⱦx[=/MdGDYuV_ޗ2yyr8^�κ7S|4My >YȜ=域ɻΦ_k:t0YoTnXJ nvH!D{/n<h/ٿ4q.c99Y e�;FݔӨ/!w!]&kF i�a̜j+NbSo^ג?ixep0A,Zy8KO#D;%F1{$t�#~<�z<pw+as7Bo~o!|i8Mut0ߟ~76t8ֺ|q.\1zr2?~L۴>N{zX4}/#,bX&[[CM]6;lƳPV:_ˆˀ"#3sgZ̪X9i͌i xsY>`?حr& g(E} 2"\.ON/'ۃn-QO:w'ӟHd%Wa#9jl k6Emϯ.IY΋;#=:1q6_}&O oE ՖżtO9n!L<dyu($Ro3}ޜv> a 'uoegvӧK7ot2οJb?'^S&^ِ8=_p ykpΙ?aP:O>A˪ėBӂF+Fffe.CLZN"3[�6nsNzb d¿x,o8%p[0v9LMht0Zֽyw%wo҈DH3)dH1{?\v ;ӧ(_/OϾ@n9\7wH3ߦi;i_J|vg7fe̩|>8q.\9PWSCŧ3ɪFmU$̞,n3`/Y/}Jny><[|2s =Ka=c5@ VE-T71+r"_bAsDygvk_6ιg7ϧe.{ |?Kg=~# ןdW?}]W6xQ&y*c ^_7]f<Crôym]b~}me:/Ā`5`eM+Xb,o;㼻;GVEε3(k~^}xgD* 븉 Mw{rh2C }v<P dqȑ0A03 gOB -_815_;V.ޟ< +faρ5T'MFIfm׮YJwT-g^G嵧SAg%ey#MȆΧv ydMՇ~^EeIM7ڽ;t>v}$]uGBGB>kGy-s~6.@72e =F/&/ҼnϹcVuf8j߸Kt6±t`@}S椃6k|:ٙM]]`ߜqGO/ƃ8㈁6l֍݂6L<-̛=Ï<Vѽx0G7Y*hN!^zyn='n~Sw~/&vZ6W`x. *n'QgMsFb_qᙼI3V(vK6F `@A>JgԌ \XؖywimƼ!|,CX눔]Nab_^4yÖ8>3 v Qym,`wi5~11ZWAd^wG['3> e̜M˒ <=N;M/|һE)`9Dtpts+1O&'oۭúoFFNN4N2:s$^T/9jv"Z^M F k n*uy-:S-mݡ[#is~m#VwHk$?3v\;ui|>8q.\9`#8ij0Y۬ŭS]Q>/N+yO;KiCvd^ze }23hnhJL>V{)z^.k1QbT}w4v-<;EXeN}]?g%9dp]F#D 2Ɍ\W0exd:0>hj>p` :s6_PS]~b3MUU.¼q婜zݼW|~7C-46i ]%mhw>f2η>N3Ϊ7{K{&r< WȦ$-3<2Nܢר~Uҗomi&2$ 4p#!%ѳx)l.܉~{o #QwD_Ⱥ&S5kTHX<;k48u M>2cKuߌ<́d2w2dyw#vx+7w=TMo"|eJӮ :p=ޒ(`'iG�Hخ2ti)1 ؅eg\糌sB˕:>ʆ"PW徤9q<,(a3Ȩ5_0co65D5H.Sxބ1hjj|PPЏCvcy,hJf~Xɞpe? ז1Ю':oy̥`Xv~l`ŊF~�u-ʛΙiZ[#9K4F}nYǑޝ `QPЁSɆJlLON{_ ;n{5 8jWdmn,mK㼻rސqs.AhI'?A L!ojіN�YF]X*Msx63fFAezo6l©^9MoA߮=,'[/?b-4qÈ1;Dsı׬oB6^@_D|ȟ8ck1?VAsXy6N]UD߾Ϣv>u>EBnww6Hڨ헨/iżYƹsʁ2>+Vn`<6#cvQkrRłA TM4$�b&r{O<cF&Tq6$6Zj*Xc^|Ďyy:f0cg9ĚXwō>O՝ګ0QM{;f8^͆M|+,q�c M|ӏ`E{(F4%;;UM7ˆj46TRU67{Y_zZ/oڋ {/d,ji:iv~ƴ>fy;0aR.iƒƶ4vq7F_nO~$b!>|/Kgr 2 \^d5gB$�|Va "8qp 4OqE,abɗIy9EX#|,$ZY<`4/l^& FM΅7nJo>J`] 0N k8ܥ_sw\3})'QבU8n0 0qASk]1=+p'4/j-$z+qa0ꭤ{û=i|!|]RꞦ?ӗNqT|3jcCS?t}h>e8z^\-?O<+iN.؏9T~wzlU:ݟS9==?2@AslB3\ӌK*?9|s9I1qX=s&8:  f MbDvWrCKRͭ]ɼ) _̚[oci2^uBb^?XtQSՀy H09,yÆҥD<@r haK7r+ \ΡP=n]VC9cһR[n ㌫/`7w&לAH;tqh<oܩyCV!kGǞEFI!-T6?i_(%﬩d8kfQCDb@y_.I*BT70b->.μ{4OLXa p ȼu8nzbKޣGܛvmڅ+"l,#T1\PBGbFbsF?g%"13PˣC\o(< |EluD^uF͂'HEcv M`u g/Ng4>"dv܅psNOFӴޒ9!2_#k#Osjp~7d~Rq|q.\9 u{B~YςC;Һֽ'ɸAdos|#)//`$G L?O{4[̣)\{!]mE XbN]E~|υosB4vzn&3Wc#-do9Sp/iaCs/ \X l$-7tQ[_( ёx   BG }�Cl)AA4r@a;q mb:ubAAA ؝Ʀ?" OK$Bx=]AAn vNS` ,jb.ǞEAPa;'gIlZ_CYz?qۥ)ҊFSwEAQ p~e,{9|='" Ba GGI^{8 ]ct!AAAA:4vĮTAAA8AAA>(AAA#AAAAr@AAA8AAA>(AAA#AAAAr@AAA8AAA>U<({I9nGAAA^X   BG       q|E&3gdڴi,\"KA`0ȨQ8S9z8   [W]Wӯ,�4M\M0 #y u]|>mcf88u] `F2-eYX8|mz˲e,+yO˲p]x<N("nJ95~>~?Y&JOѶmlN3 #YNqDdۙX,g<O϶d]Txmt>/W7|޴lNeYbdiTwģUYt){rۖ B`B`  f,fΜɼ(*+" &Ц PBaaeZ]ª*Zl%lBBT·;BO˲u۲1]8UTy+!X/k'{f^SP $Ӫs ]!UJJ4QPP˭ʠ+h1˲|o;�w=u僮LRev]Z GqiYϙ5kƍK3JN?t/^˩IM蜶b`mX˲qy{H  v6mi`&2}ē£Z]6 [>Ll1m\l oZ)Be<O mFRUׅxuO "@)tk˲0Lm3kpiXPhWv ]0b۶J X, Ɏ@lu^^%Ew_Yuoݒ@W$@;ꔬ3&>L!?|h9ӦM̜9ŋ_i&Q laPZZ2mM6__3k֬.  Eo-"h]70Mmp1R�>U�oY}�>/E�I]T �2U@ �똀 `VR^\[ΛOQ"iz¹ZWuS �@ޕ ibvZ<jHKkyUzYT?)2!9[ˡ faY>vl LLä_> .ܒ!-M˓*BwI&Baa`tyJ<g[E &  mȭ,|46MHDq4-beZ1 ۗb@{B H tELu_wn]7M?>, #@[u]bXRU~^|U%~R(TWJ8PZV1t+@_F_ z ][6$޶VMoDZ0ĘQ*f455}9,Z>#YYaWqceOgf(AA:XXV�%h%kf�Z@G ~'vHU.(AkaV/+P(:XVS~.+]WUyg4Ier#P@(хs%^WXE@B%맻pxmg@k, T\cm5hnnW@W 1 =ڽ0`sm{(AA͖oeh`ZaT;_)UuT_(KO_!XTPJ JU+J(WmqdD=^GTEEЬ0 bXPׅxu=Y@[G@rBSU_HBŕhk]"'--rݖ=u1 \NQQ!k֬b  [,]Y:X8{=׷듯) qe(J}u_{ߟbm|`.!zIMu{_ ؐUop?rmЃ +E�P5hu\m?Pe^ {@Qҕ*u(T^wIYYB`;4DJ  Bocc*LJ@)?*Kh[U] tr !##]e"lϗL]ׅ^ 䧧mN-R:soہR nw%WGRxVX5hj*q"!lXa0p�ql ߟF*  Bba`-\\M*a\{C%*%&~h[VJhT镐 m⠄\]Y&wXPt ɾM3�� �IDATL^UZW }_u J!ȫvT *~|! z[n^V_W6RGX`6`BM)we aYiDa@%idAAAM|7n?ß4V:|(JW؃`y p1 HdJ hr[%&LUl]+T@CbTu]!Uy]ѡ)t7 ]iz%+^O]uT(n0ZEou~V}-utq;)K:ka)m &E6_[9_ɘ]FkAAA-|' EBLu!_  )>e(}+VUy+^e@ʭ+TZ]pVB~-ͥu]h\:Bw1]-TR@W¨P )}Y r(^oUΩok:lP$(xwaˀeR]Uƍ̙3H$ AAAA-lr@YD"`K]0I!SS+"!&W@Y"z�;e׷TeUT CU&o5BݎPXjDurgPu-[_e)xݭ@) T9tH$b jG]iЭ&tt kV296X4j+C0010pwWb;8vXp͊+o.   X98N2ʽ]֣낸n +ut}U_?5`*^7}\W芃vP{cսt NX Яo!TPuc1 \ u^])G/Jݵ!% !'�q0l\\[ z>Ôێh�D"1.]o1rԎA\ AAʁ6l8~?e}BNG J�ՅN]w( Pu9}+*럯Vz�>unY'^z]Vyzztw]˧ z?z롮Qנ(^ŁЏ &bJ(�q0h;)\Wn]=Jׯx֬^aX>ہv$ `PRAAz ߉[Ah{]ͬ<5]" A_ @n TBPpbץ m?JPWJWGn}={@~d�޶v�_] (E^֔v!BnikG)uL (}n" eذ̛?X$թn:jkk΢|    ,+i[Wv'Pn PS:u@+tEss3WZ 6gebє`zh3-`ݺunpuV7l H)_CC+V")zWUUQQQPy-_v+z[IMmMTUW7a!Q[[0̈́BS__ϊ+is l;ʺkhl0Z-L7xFwcZ�h6Î8봺\`8֏Qd46ֳpB!-||~?F  ;ܑ@WfuW *@2wׅJ]7W[)u]֬YCAAAJDpYjEFiD&Dwjd<U"\%;;;%``ss3XWjjjZQ8HX,F8u]BP;]b 46ֲj=hSJ*&\%''GNN%ڀm`ZfB(IJޫTз7LXvEm;cF҂�ll'ҮEQq?rhjjbC6-.rMMMC`FOWAAVX9?s}V9 eY)qWt�ޠ]$'�[Xz9@9c5P]],C5;TW(0 &}ht�ijj)6W;nbh2pl 6qUX<icdTeHvQW�ޘ ˄QvtQ0DqF{ ;< V\OM}=!?.@nq1CAAb77MH D;R,tk$c߮ 1i=  NOT[&? R\\Th$Z!7;~f[>~%%%)u,`0HAAAR}m&'{TJGaaa F�###ܤ[ظCAAPT_`kbe֬9TzQ߽&T@J>.TD@Bh0JZ�B!`𡸎7,u.a oia>{׋E   [P(|e5GWOQ+z@A):Rtv] B) !$%K4MB j$h57 ;a㘚*cIII[222(,,LQdee%Lm NUz 邐n"@ Yy@l oTJDV`YVe[8Nr15@+!m-Ɓ˗c.YAu0]LuYd ' e  B;9\ lNm uQ_Iu=7BSPPWHlV╒0 \L;28 -B_u }Uwաa[$ﺘfb9%Z~z{mmCﶆ~QiT|6WǍq,>t%pPm&< "''uQSSC�r! c`ׯPF!C7e  b0EZMu!N ^]7@ zC%}hzT5JV¬JQL�ݔ^ORzoz6zy�6x<6*ņWA -UpGuL]׽#偮,Q z_')TTxO  F 'g޼c.FD)K�hjnas X;<*ĐAAc>?)BB$^Rt=e T@HPU *ux]WUٽi*.H+ZĨX,RG]+ZrMЅi*^f]*5^uNAEp;جu \'Ѷ@ۖ Aغ$7n7WXX@QQ!,[ebp]qY,dF&{   ߁@ ljJT+HP®F_9F׭ VIWuz&Q_ Fc"+>JY!r׵Ao;}CN)FteR x] t -t傎�HQx Zv½!QF i @l<PUa[.JdddrZj�?...1$t KEu.'''v1   =+q7EpjYX,%p.,ꂦ]%*eCLUD|@QA_e *wLpUeRwU?'- T@[J@-7.@wzQH]U0) uTĘqp\ juS$^i<z'aEZb0r]Ẅ0p "(ge3ӔAAd#KnY T0B}+Ae osCj@A}EN_ׅ^]u ݍ!Y -ݺ@_e[�.^Szw5^/"@_W*JjC@*B~P{[Q[0uЃ&vTm%ôq\a$W|)1z QVZBKKիa`&0H"@BcB�˪ii0lP™DI   =+U@ۖwft*࠮@Ѕ|~+z0UpU ]}JAvbOؙ@ȫxm'c2t勮)=ƀpPuխ;^7UWFkbW;�0 L4n& DiT8b9,*6TiB�Å8=` ,Z@bȐ   l}X9+~JUǼQ@p y=^u}*_G-t.* P8^\O{:Q{t=B]P|EJ uAƠ[wkʚDy|ec; %iۉ:q51 ea,\K2Y=j(dѢDB@? wuSa3 bqj@>   [-,iS¢77~L_VJB8I=Zn ] <P{W^|o@?ew�u_=V:D/y畀X) `v)FFjRo?"HJlDl'na- M�uz0M?kc.ibV>33 0 0 @s]|߅ ٦Iab.^B}}=Ç#7'*$  }-f=7>|sB ~ C2Xّke4S, wg�}=pл}V+t%Wq * eob m[_x- 1MDQԯU S +y-mqiY5F8b&v\ 3`@S>x9lTCMumb C\LF @">Kab6߁F0 C[   I}[)@y}^] kR+j'�}E]YAxk PJA_P~?w_%]|Uzu@Cx8JYHЏ)RzU�4]l[p8&(Ǎa~_�\>|X 8>1cF-,X0gM,;߉12 3P (hѶlZ_?SlJ&H")I P(@!kʪ߻7^h+YŽ gՎ'A-`-((4˳Ͻx葇(.`ۯ ŠmUUIՏH%~8Z~Y�1!חSe@ZZRtA}^&^c9vӠÔ8+lc >xr4<1* b |f%k_sCv$]<;>D eU`<{P>'V(l/xǼ BG ,P+S }+z…79qC$6Y,D.GX F;`XX,O|?K 08V1)if1O!ƱO'w>EY#I.Y6/^,1f,טZ;fɓn;KFFNHHzW"!aR1Q=UmAnaͭ\z"BOF]Tj(tZ@xvvre{MD22222222222>}|br$vcYőlA>-6geiiџʳ2zZƯKHɌ4 !+L"kB5n L%b Kْ&;1 ,%ui6@$S>ts4 A14biВ#^=j hx-|o17|<=`Y* P e[{5BCׯ /2ȸ@D, G>>k K4$?iћvӢ?*tJ}!?))vӎzJf sckF1ޛg5Ue55?=lYRu=A c4qxxx0kH,4Hq-cֆ1*3ҩP`&c0REq AmQŇP%)1r)k_@bZs‱?6UjJE}~-.N?DOH鱀LY$b2놧$ll!^WZJSH JYU41GXSPvzTU/ T):UESv CxZ<Ǘ>G Qi~:>(ƀɔ8H!Ld4Dc$!͵D<އ2R*#2}uEzL+ (~c'q6/]BQ*pE=%@ ixoqe+>19vt^Z ґx䁴-rb�0Zb!`:Ktk?u=ǯnnnp C().'7v참H۝_5L'pN`4Q8nj֯\<O`eehޑi1#!CĵJ E#%½DRh4PUP SԨ:%DfA L *i`eU{k?8�]� VZ#{)(,q Ͽ]wɹwɳ>>y a; K4n60-8SR!H Y�{i`/ @gV RL"bAQxe{{;A0E,TUE== O?vvw)˒p0U,@d81~oj9uen7p8߰~FťEi=>9fGdD"6K(  `^k @CE�2UV�l!+y[^#,"-puxL^1"FZz嫨 gΜ>@FFFFFFFFFgO<0G ^0 ߛvcW68p>�"5U -�(~2 /^H�ןu:vwvظz B23,0 -s:/sAO<5U) c5e?w_~ڇk,/|$Ez.s>n^r1d>. bfCCҵIa"[bmEa;1"DŁk ֆ0B&DQ+Pf(d|&PVNenl7 ̋P)/X +{}Y4RMy]:݊<۞/@>19vg3�b8!-NX>0)NJxt~)I0k+H%$0,pǻoK(U C:~ޠOթcsݝ=_7x.m Å /sq 7lm3<ǎ/s*s KeNp֯ӫZYa0!G5 ^6MӴſ( J*F,FJ%"xCSGBT9CA˜V�!-?㳆nʔ\tݝ=XFP<NA� C(6g`e8PϾ*N /"F֐Ɂ`48 cJ~~#Ehhbq>H >w,I,CVso\cw„ (z}~q8h¾(�� �IDATӡ,`whUb }wϫ/8LuB]ݻUeNRt+1ut Kԇ#w(-ei^IQ\?}Ύv(˲={hH4tNՠ7ڨipQت?knYfܹ߱ 8u P"`bSpo(!B2�vUt2[[<.^r@FFFFFFFFFƧOH q:03b1LĂ9_"& T0)NTt$brUvk Cpm_*n޸kt&v  alĩSmO8Zkγ;N׾{9lmUU}>!`1z9T\xt:ϟ-fzD1L48b;IA;+am]I v1hI.F(Aݱz3ϰw]Ĩ(B*죌PXj4Adaz(mnBeg^} ᡇ] #########'&` ="iџߧ},Zst6P0-f#%!S4tonKh[ z}!.ɥKk{ }y等=U+e-,~4#\wJTU<8ieYRT%neznD=0S$Lц"![}HCMk# dḠ`# S%ʑd|6{(ׂ!(paTQ@(*ABwzAxǨ  pK0-́r0+QOL3ދt4L0=G&ҩ ιP8Ǎk׹Mt(lܐOgG#z SEBTV$.xwpM8oǎ>~O Z "h!ز://pb ˌw6ׯLߟEj4P2fCIE7uEAa;ՄJyI!#w?Kܽg~m'@%JbX.JJҴBA!B%S÷׮qx3gV dZAu�]j=H'?GizzjN%f;˳ib>kk8<<*K> t:g VϜoҥKlllr}qxx{?j3z X[C\8wl[o hhԣVNc *e#)Y{A:! pT S7oS$! ZdQtEjEl00칳lo`D!0Vu -WAl t@T@_Teow~xsHMWWS�bGN_> aH r?юټS0x988lll NdnneHm=2ouӧn(J.^h4Hxzp̝\]a3{sSi|뗞kp|q"uS>ӂ] 3B!J 0tJKHaWC6֯vwJ\D2(n :#q.*%#숔\r]|8w>l޸IyExFExi_C(E持s"| ݊Ldddddddddd|%ʁMm]47�rXc c!{_ۣ?ihm676qUUQ؂pp8@L4b0@Nbq=ws˗.IO6F#VWNS ی Ue<zK/γCa~~CU12:88_,h76}#%M{0� MTr(bG ! !G@>ƄQyQq|MӄN"fr3><�xMG@WZ2GԠ�x i7 *m3-4t?J._ciq;ﺃe #########-!~;i?n?Ne;Jv:`֋&<ʧYkwwvY(NN$Ͷ�S ZX1P]zs{C_s5.ZcwPu[^O]xܤrT=A?fa sޟ+3 AREURK~ˍ-zsssT)1<S"bGp=v�xu|JdzAaS{6l+gsCnh o^)Z $@C@RK%B)arAG (Ғ\sr uÛ~ȞS{1lQ RC 3222222222>[A: Hq>c=qI_֗0 >T'vSa4qј` q\z]kCQT EVΜĉ\'Oĉ_4 npcG}X'?qxp>!w{x« `)h?z?tUcxAtlQP¯_}pHUT vG:%t7$uXТ}\CGT-,XŘ@"X j# ,FP!X:6d|z{sU67S"tU)DK$kDipC<5 �z}W^yjw~'A dddddddddd|J((t:)c7?U( b>K  ">λfr2;<y7n oy^񓧑BZ x߀ Օll^&w~wy|Sad[POAVZ n +0/|79ؽ1ss$KKK|~/{LFxg[w>;;;ұea4!_u`('ki C"@P\" yU@E!M0@5HzfB$*bksi5�PGz�UW~x42O# S D0 qha-P'ҥuL = {(x<W\e.sӧVؾV{]iQ  7p7)$va,<cQkGq <;J1UDB=q;;?<꯹3<vuopr6x/"Tp8ڂׯs pes>c4F#h<Ք{8@.s9NFY!%VfCڠVP|g+ywX>vs>J鱹qӥ?\`ogŅE667>b-H#u]Q�!P 67It 1Ɓ#l ۉJtAƧ{T^]AwCR z 0R*VC N/` B^~ޗxxڠˌ[[Bpd4s ۧւY N理B<GoV0Oɂڼ\YPڂsp<}G{VXc]Tıcǹr Uw-d4nxw9hT!7n^g}}[ٺ6 SX\Xdqy,--p8KS1&{t<^րknln~c ,ۻ\xs>Basϳ~$h&KTwEgz L@-mր`MAQcx&H4g" vLifq?u+DP"{ M;-Z?Ahc'Bx|cCO o7eά2rc{ȸ%�L tL!0vZ vӑz(]:i ŧh=?4!<og^fa~X.ˣ> /7_'<X[2G|>y {ﳷך˗x \^M(,Z n%)ꕦ-29~|G~{~:<ƔF0]!n(6]ȗU.^?Ϲ1*27"n#Y)f LHgP X:Bh]3Y7c xo$*>3l?4-E!<4[oQG ]U;` Am'HpVOҒ`3`# /~ȵ./s*7GFFFFFFFFF@j%G$豨TZXQB: B2&/21beEr=2xݷyzϯ~3Ov'nARuBv2{6x՗xغ5cNs*'O0?7OUUk1uSemm.\x<ǎ灇㡇mt:=?6H kUXomR㮻õ5Μ>1Pu~qlfaa##)* ]z i+kN=v뉵dhѐ"$ᐻ '/N`C5 Dۀ"$fvU(V�#aANh| NJ0P"\oW_; O<|s(3222222222n9n 9}Z|V?0U } g"9OMwssus?eYU v|7/\_G}ﻗ ̹L'!]쯞_<Sv۝?~ssTU`qa\a]\ߺƇ7.q{/~ݓ\91]lػx&Z*o=(X]9wkZs FCaqq7nLF, 3Q+O!FA[%@aAM;q`ty!>}zT}VI/q}a@% hK4lV^dRZ(S)oK= k|w>Y_-IFFFFFFFFFeqQM�Lѷ=�N�&"VUi=P5>}D eY&*c,<(C>}._½gp."rG(˂]e<օ </d~~ =v+:U(&uiYbpX]=̓5|<o\7.p<$O>4cVWW,իyi}lop*󬮬L10S`0`pkW9r8†bÔؙ K޻~?9e!߸^gQ E|h%h?Gfr{7kԟ5Ef69Tyq^} B`(9( l62"E5*1\z Μ>ccz|c0qj]1J&iU{"OZ}=]ʚ81%rh4UaT1 -4#########>19^T�Ă>vXTq LTYߏ"4% bje<O 1ڥnܓ RZC)),?>Hi,wyW/]ؼz5hλ ygx'9~lCJKEUa2`9-x&y1q-//r;xso?'?>xm~+`&n~³{:Pt<uU:ҙR~+W 樶6qŅ@Ś?ZS=ز &L3!D$}^$A}ncO @dU ԶVLC[ki;䱠|I??ޑjtzV?! $<gJ_”3N Xp?{Z׼sMhG<:  �*~TQ $-bD"+;W^5+WșN# L1 9 "߅$j%L3a`Rʴ$@aM "&*b{j)5ᵪ�2XW#?~Sqp˔i7Pi?: ԳbZ#E,dSAt BvX[n3ŘV+\#z[V<#pe˙N3W._b&?я88;Gβ) |FۉT1cڮk@Q F =c =aI{|ȱ㋼ ?SAy);].VVNN,iVCڡtXZ:{UQ0N^N cȺˀExF*J=vAH%D8ZÓO=>Z,-u)}v `4:l-.2vi{m]MOcl .t۝NJPۖ(v㩽6-x HKin>@e1Q([%''d#4MP!XѨ"P Py+> o׿pjui!;LQ :# h GSp> ރ@QawHRe{;pxx@?( F?3֌F|br`vBl^@|}SGAi΋iIx޵+W (-@1}U$D7w/p&g>/qJ]<#<9zNtB9]rJ(JJ57H[Qx\S#tέ$Jc_ ް2q5eYq]w2k]yAwwe8N_ߎ;2e�-: slo04xdv ҄U-*Lɽ1H9LSޡ*x᜛yΏ[B-O4_|Eկ TR5ML%:~VL~888ū@R]#%b }c, Wu@K26#Lzp=LsaY9zn;;\|= }U¨}6 (VڎTB"}EC�(]=׷-cäN·JSG|;3tufFP(M0Fpηخqc6iTi3AITJPxf)6Çh:y!ocuqgn'>19tU)`R4iX`V]A.1OG}pSg(.(- { &tj`q"Uiwx7y{/~K+j-lMP +`"P1 r=v$45Hҍ Y^Z?[7e܌8On8z^q\p;XS Nɕ// C y#m|US^ZTV)Zr'ȭ6$XAsm,q AZn,:<ĵ?6CwtJ[FCPD8NŶB+-?j&ᝩ=,4!nD y]~r!'-s>a,m;<B :@!0`7foշBhp P(h0ԄcB"$ �� �IDATG lS{~t4e2r]3iəPqmD"ya& _|k˷?ǹ_|?}7w?2222222222>ܒi0ߧ>TQM_H iRH T&_MӰqmU8q,'4 bmz+GQNmX"/?n/|> XS Ɔv i1X,Fi.:[0#>zŭc ϐP%ĪDa0<DU|ŏ/rtam޾MeJbfN<7w-7F:4HqS,$H|&6kai;یZ߹'9 41:U|vD /K9w>?'|B׹-EõX&N?o>N{ˤ{!s d$~P('D8+QBCH އƄ׻FYVC!!h EkQ8E8lɓwXt $Z0 =h0a}P�LI^$T BzDNT QJy H`Z@%(4^OKxW%6J,Ac]c@3?6O=$_g~wh4O`FFFFFFFFFƧOL4m(XO'"<ήOiHaD cgmAM]\ZeXhÌ�`85X !j Zظ /<KS/?9awbfP6%*!pL=-TjYwANH~ ňwcP::TlH/Ξc ~~+6  <ȓ +PxO[^.rliN>ŷ2`:o( ǖV]TubŜP؂E bVL %qT/_O3 [7ZǢz\%/4~h;"ŷKȂhɆܧ(^tCіQJ!&�F,-v/J"!FD=N+4;&TPmh\;Z`AI Up',7PUěo?Kc(b,'}{S DW^B6W5XQJ۞oe 8}*_+VWWX_/k4 222222222>KܒiE }/X?xQzinAtqTARbpckݽ=80)B,a$^KH'*87k UQv}v<yᇙ_DѸz2QhZ"`LJ % iG5'FSXi؞X!h|__}$X-K3{c5�eit }vmGS'^xϬ<Bؽ$!u'﷙(=<G"M0 и&K�GRPvw.7~/};_|ﯸre"(U\p<O$HEgHuIh" c}1 քӄꛠ8PR(d"t 'B%rAP %QSСToh|ij]>Lc,P"-4N%0AT1࢓T wZɓ2=|,mx5QUFy0qĝ7V%wsg]oyoﳼ̕+W?.A @FFFFFFFFg[zMGMG%Ţ$`CIt(-O""vqcAߟxcA– Ӯ,h8Th+)*W]| <3,..ѨGI"@aI} 6 +4cbMWqcĴcKOG <xŗ?œt:ܰp\(lдQ_)#;lQ`hhTԲDEzri#=o!8߇? |[_gqqEY2’P~ mZJhsG7|4ceJ UT8S0n5{@a6o;&d kQ,AYw F}tz<7:ʨ9;p`̍W-Y èJ0e{nOCK0/|=UT"t{|sOk]D&Mڌ@m!v4 ÖQ+mAY<|},y |/o]]21-V�G MgOeYcȦix4m2vL>w܎}CQ1shM<"V6MLٺ/OezƮQ=@đGh0X)qFPcOhKzZI=(^C5mFoۆF/ E<e\/~3z 'PNQR7!рjZUMt:=F^p8X`)>~j 3}tPU^y5֯<~ij?}oq&B_c<02R q$m<6/ J?G\&w8 ECa|P7NwZ:$5@-%$R քBݵ9Bqbe0<67wmGQ8cKJluEC!.1x Q1^r(_Z⯟{_{nc`$@NQ|hLlCI,4bV@~@Ԡ2Z`%(0JQjbrU^o7x75?C4$(IQO H&Gb!'^d@:�82Ϋgw |U8^8Z+/Au67./t KRQ5& @M4:.>(*"B\ϋ R4Tp`Pz>v>?|wqzL9FzԄdPx7&tq*vy:f/J޵1ŭĘ履CY4շ2nC(X{ P^|?gggyop ~*/CtQczt𦠱mȟT8`PH)gC :]g JS3pX TX?-3}Y6#ШGc,=@ap͛nG|pͦ) LQxaxb=]SzʖG#<>c` τHC߈3LcDֆs QT.0_h*}>kyAA9 B,ZqsH)Fغ:rM |%7_)222222222~۸%Zt~q1E},&>6Q0Ioj#~!P-.B|oi c{<:gFYthTpMCY)˒gC(*_௷9<JaB_4<ޅw c= j #ߎ[ǵau9x5x< hzEapl 참;"Fˆ^g!b߰=vRhظqh&&pk[;Avod:ⷍys?wy?<S ןG]C/r s^(}7"5wN]v갶PQpmȥ.i67|Tjb DĹygغqg|߿~-|εVnb@s٫oN<c7P2Oؼ_+YZBa^+}Vn?WϰZe/tEo{Zjj ]旔Ns#Z ךv~ h"y iPF@xtN=[k׸)%]w?ѷ;6ϥ˗xZ;OFFFFFFFFF%@,ʣE OG47  c0N'hckk;NƂa jQPGE1b-MQ&oxN&: -,RF D D7c m!kBr&ggDa+:n9-B|&A ˜ vRx>.?e}yv3=9`03`AD(ZֲzK/w%miWH<&�CttOy_<iˮ"K@[u{nxso|os5콅89G^'B|vȎ6^m!?QӶDacZY)w^wA(ZtP8+WN|"\bLN^_~ظ~Gď3N<ͤ,Ǩ)-혛gZkR@t-P8pַoz;.CY 5,ص. I3aѤ~rNB8Eo pz,^ K0}<suyKl M$CIu0$"%]ϼLfq,#Nf瞷S ,2$ZZLR*  l WBLs˿J!A@90޶ ơupOoqqlE1f@BVGT8363?5.[e)P@ (19`nu?R *$:ΠBcu*/sըӬ20O$ 3tUnD6|?tdfه h5|qTsÀvҦl@cI`0"!V$m*|%iƑިUyT5J6pB"Yrw٥e6mQ&&.sY>VVWBs~uzRX A$(K뫔J%Zu99ԙC:"Rk~]s^ TYƀ,$BxuC0yyቧd羽/+zqgIGЅ!'{JwPU!K4hp:sȫg2HpD!A)K$RH_4J(oŘVP-Ez ߲!2�eQ$[OP?NݎHҠER):5@JRt_g*,H{zj*I ,~]\ � @z{ QĚqEA ž4Ð[QKBJ8R5޺@ZA %V9u^,4ԝ e~!P⛇y/n%,  (P@2|&ʁ xm8ϯq9G$kC>4 :NR`Ph,Qc⨄N~qpF)Vߖ:s<uMmnPblz}fk)aF!l@_#:*|>k#)M9Oo-ٓط&(�|C>@c@ʼe�k^v ~.ݔk]$Ir6wS78q}xr6 JkY'Iȉ06!˷WxD5p B:6*k~N<ش~g,./1|9IcLrp:I;8(weJPZqXm>$0H"RJHaA+ RwRL )+1B"p60H7+ 0=3伦Z ²X2EP:Go-em4c-j-}u0R 9`pāZ, JZuH*RHۖ.ˡI(!|+F$X3)4A auEX&xY CepxG2n92_?[GAzS@ (Po>*Ρ{݉N\\.Ngt m�`ee &IS+ #ZG<T!q)ur5D*EfrrEfkk'MSuT*eK!BwR/+P,ΒꄪL)hҒ_Y蠔|(އo06Lb- 7ͥ44u(L)}]\">Ȅp0.k% RD*VaP $r7ƢFXY "1YgjZaxG9{'<<$el,G_=#O>2w]%z{[AB*-"ZMKkH% @"4[gm# $sYȅ y&ӷMC^7Xd!N #m!jZ"p TT; i4¡0)cn,'l&dV"ZM:̺W 0&@4Q%8B;kVSE}Uq᛿旗yIeێ|'`nas:yk2[@ (P@w|fe~]/p tZ :~;MS"̂Nv;A3Zlr3f{ENRu֖'OeG�ZmMQ% 8" 295&Fw:APYq0~v mhݢeR)HpaE8E$!m4TkVXiqڰb 8~&'&b``eJ-�k.|GrJ_E9TmBʿNk֞/_NH~\#ҭ8R9q y=8:kvpI㏏3u'vl/~13I\:s3gٷg+?\V)$FXLM/4s,a.qG.W[5E qڑ;w {0m2F(4zSǛlxM&|5K#5gQbilS $@3m0`D+aV):LJV(kGx+ڙ$p^R M}Xm:8()8*{B!Bba6EGOooC;isz j /ܳ31>;>GDV (P@Ɂ|8lW;vs =*T[#k{NlRuuT=aq*`zo68RtUzp!j6 \x~׭F勌o PY�q�N:J+JTgdh ÃP"e5FS cHKL>G3 L>eKtq\̥1f.gMJW(?9,!Vfǎ]|\;HVk%KMcSFh-8}s@Vxn.Eݔm +VS{\�v^6kc4H)0ifA@dN6ucS=Zi+ `l x|OͫoaДEަA<Ȫ OOZ!Y Dߞ_k1 "_' 2ɻ�a0!d~p˭[H8+6MBsꓐ&;�8 鳺E ED v�� �IDATf�rH;B&g$izH \_[ c-H!S_i(H Ak^`R)6m ٶɑX"Ht)C-ҦU}ws/0L-P@ (PD9�  ;杤An 0 *̛ :-cc t eX^ فE%n<³<2 *Z3'XmNj;VyrFW8}@"cue3gpyjW=ezzj$-6gvc^" U}gcGN:!n! L>E=|[\<s<SN}BeU)C]si,QuՅYz78LYgv~TlٶVbSs.h,;vFޠz &އ)J#Z0XFp͖}>-e . PY4 0RϙM9u>?W.=ȶ͛UZֲhZJvuJRB03@jvmއ }zO 7 6$.eLZK?{EXhh.!B K) S@6\0ʐje{: Pe,.jji8K2Ȃ2J$�kAy/[ .cN'0oǘM - AhR"MA_c]&‹pͷ( (P@ |~y]aHש \ tZr�.c V:k ;'цJ3$+(:\66ob{_}vN<^ye:FGعs'qTfee_St"6nڭ&pԯ0*[o{0&ga~*ݎUmZ-0^8ymN%'PSJb +puf.k1mEpfc1fαkFزi3DJP*JcS?f9FGv22ϩS'9~{ٱg/ɉ39n)&#ﳴFҞ6BҬk/aui Z/i(m#P*BQdU~pzxpZB~xGj-*~ cqea_9 h[0YiWsC'cyW`?N^Rﲜ|)iBjH,d~*L1FPo3 u^XlJwC$O=YpάeyJik|u ېvg՞5!SBɵ#=;K2  zHCJfIRJR*Sh&5!_N(zI:2phmǎOdp(P@ (یϤ.;rI�TU'$4Fb W ŹK9}vRV[GY!7mG Οz$+Y^ziW71+\:>i0~ lRUHݦ[fW𭷘fdhJy.L`/r).O_f$iv︇H/_z2#!ViNj}!l\m[F ?̶xi.YN?UaՕ? %ჷ E@PB0ݏ[fg.|,.8s ,\^sLuv&7V}|!m4 ! E!$MӵuJuSz_[cHI1֫E'>>n1ɳ7bm^˴SM\VzɼfA .w*`&عePBCIIX$c',N7}8Z6@Bby=fIp ,VjAjF,iV )5mӦYā B+CV( m$*P#I U. )%J>@X!->z% &;|`g(%]fހMV`$1fNʕ $[~~(P@ Ϥ� ɀN6Nb tR m8pIUBItBO0*S__c??0KWh4i6سcB_J?.-o~kT8q/= +s+n P \{y#sr'lY`,ߢrOw$ Oc+YkƞuQ KH IϞ}9Anڻ}?;~ivJǠJX'Ͼ6~DpҬ'<'N$OoiVW$FSVA]̮ؠA!"brGga$APyt\||pٮ:gۿ!7=z?x|zi E` p C),2oslXxI: !$"`v&it܀ Bjp[:r=YӉ@cP`[5hKjq)F*H(+0?_gZ*'bna1uR"�kH0(ur J:𤕔>h4NƐ+`1 -Ji̪j$@i*<|Fwsi)1P@ (Pτ찇wB?") <w t hN:峤I %,(E4+J /M1WJP_ZaiyK<7,Z gϝ̹+,7$ƯPͥb>:qrw7߶u##g(fa~(xMxZ-#eLay`~$II__KKDa|,6rrןzj\ [at/b=&/40*Z[Z& ǎ]d~>s 3=co>>V#00eک:K˄>(ω*qTkm7]ޘ1qXbWaȎF_y<Wb:bI@I$J[ ϏXP Bv3AF*8A`;Y"o7P8$!N$q l4 8dNb4tF #U4� E%mI]ܜa`gUrC9H);q&j S�eW5B։�gXZaMW ezXq h *<|?|[?H�* (P@dtՁo0�R)NA^}[rAs[A~]~{$IkR_n# i'H!q&($BN aYr'N\V#.͏.e)VҤѰ͟Gfсv_{>2w]ݽy #hjRhĥ~4K)Ξ;ǾRNCu}D͖ ;xc8EQJjZ^~5H4$appU}zP_U! DWJ?FWWz}~I\Z^;}-bp/Ш7$Mj*=}lؽ)B Goh uTm, /*@gTI!HR`aq!3W XJx{&|p>PdHW䄂r6!m.\p0Vn\! R H25k�M*8 2Aj`] 3<|y#l驀! jE#tH:dG![/Dhe #@иbt)҂5i)qh $ZҊ9>/?M7}$;-@ (P@+~crCEk;J)pcݚt0i/ȇ\5+:%RJp:V4un\lPu(caڹs3Xg8ySFu[!,Z/I{شeTGO2fuɱЩik/GXRc||8`udp w~ʊɯK9N"*N|cNrsLo1SشaB啗{N惣s8*lݶz=!b*] .7(رm7B&bKϲ_o#I?�9zfZ p;, Z_FI5?Ru̿HN?0Φص >_f?ky9 -D Na:Ā|»P8?^ ŭ7Kʁ!% lh(I#HmES[zm- LNLCoEj>=t=4m J9DP:8-HZZd*aV Uz!JR!*GRjr[ E ƒ&W!:H$ъe%DžsmV"?R9{{˗gQ (P@ |!OW@~)WB+\Ln$;pMZv`,*ٻnksIVn7T*A@QQ$  'o6 QhmDL2;;΅KDQ#<ʖUV.Witwl&()稯:.WVyYo涃_'i4颩AٹFh,98a(Q"Ť)V,-"U1[<[^v{4ۯr$eqiiLA}TD#GH$+ lߵMZBaQY]?Et6]v΁d~UI! �6N(6(%08+ZL-�$`$u+ml!I86$mрF7%C ,%,ځ&@ dAtH Di4 ;mK_H ;o]>7_1u7 +-#% rجoYh-@|wtmc,4Z!ӊob 6D[ dlݵ͛7sh6\1I(P@ (oLY \VK-vJ޸üFwC};@\!JD(*QHڭIh瘾:Ɩ-غq7w9]gyȸIS^D( (|US05(JL7Zc64ccK-vV#[ؼu3ws7\zcߤ6MdiffNr-tuGPfnnv#drqyjF#%$8GwٺuՏyգw7{9jgر%J7OFGwիi:W:C&MJ2ծ**,J(7JbVYEpښB8̚D,sͦLt)@8 º�e,V:RA! q@X,*}(HNz #?[ b f:F@ 2#,*" %9R-wLRX7^'gQk-K<{qPB&s)ƑjJD")#R}| Mo<28btHпr Ͻ&P[O`/Ipo?K`ye#G>%F!,8Y9 2@ (PI-J)?dqv_o]L ຬ\U[ !SqˈR)jl^E:ML_ce)etcCxJALR{% ۔D@<TY'h!vUXcgaR}6Ujf`d-6ԓ_gdKr_ AȺ[:+%*~iL-ΒX\maUV(W"z>GPpW)eCJ!ڴT cn~QXf3yy<#*{<BT0@I!#Wиqn5 |}a%BX:?ʎ싂# ȫ -.p t</7 #>BanN<� \kAp8A$-~^R@JeYׄ5K+ =zJ]!>#0[qg?}a%F�%:�{n[X<?Ă#|Eٿ<Bh"'`U KSufѷ/1yy.lHP/‰<! (P@ |'wu~~r)1:|(ʆxȇ4M9AЩX)HѠڵ$;yHHJl߲w _H!E1cM0l!_inuEzG^٫L^#/s﹍ﻍ{v24< 8c'q>zX]eqq4YWD0~|IyW$EX\Xdp),Clݱ-yGz62Ԫ3KiZ& ( ZHQZh2-6yit#'/3ujdC wC)BlF83av;3'\Zvʁ ;okD ƦYݞe/"Yo-kDTgH?]\X\r,.Fq҂<2BD%kRBH:2<R(`mFSXh^~U,'!$Y2{UΞb``�m }6s,hɛsGX%c4g8Z{R \P$M`ټ-_^oz;ﺍ |Gril rk?b.Wk뉭 (P@>L 8Xy`Q$-yǵ]kQO0pVsseփ)Q3'8q fuq7k**4`YdTM"\ 8MTCR RC,3y*7ٸiZ+V?ÇBEt$>>Q\ǧ`e~w-fVAS9~<bpn_D_a: Kes iٔEOCt {/1=y>~{h 5`- ")ښꐜR^δ!�P~!&lQ Ax!! ڥe3a:Ҕq̖C�B`i\K�:#p)RX$9`o!$E ɞUdk%8a:BiQ.RZaݠK/ZA%@sؐ)I,r쵷_~?4zvQ+HRI9IC>[;v;9mopE&/O^m#\<U@ (P19ua ' :|0V]O"G"\sӗމՉ*F0W&ڲeAN}VDEh$QgXAڜo UĽpoZblN~:i/R +<pݬ۰M@DٙE}}wgIGc )6l  =TGwV#f&i$M*SSGց!֝^94 *$&X!I|Ubd+cLQ�� �IDATop n}P_]EIa!5 AE-P|`I4M l-']:"B>e/+K$W'!VBpZ`64!AmK\jcQXJg Y͡@L}ahr%زʮ=)R<y#PRRD߅3v4C}+%$:p@N:wDɡ5;}}7щLIɌĢ'R|6C($WϏqc<7xߑ @[h2Daef!ɡ;{x.j}Umbp7@%x#{;(,P@ (gb+TtüZ}CEkq<8Ou`CJI;փTa |XyO}NfqF8AIf -]Ԕ6Z| &O-`2{s/Yeߎx\ǭw܆13q zl8<J  W'rᾭ=s?8a@ <Kx#IfY;j("i(V^c}_эٟOx+bLHx5sakCzm-)eGgR c49d6̶BHo>i-)0 ܉7r|:GwLOo9ueC ) =&mXmX�~_yOx e·8^z$TF hj R*A] #JU r() wNb`n9_ש#Æͣߞѳªc5 !YhgpDV`%HgZ207x%lI1@5$(6e["_<*SpnXSOrv .@ (P@j|&mpm˛nl-TC~gz}>1 u<\*ӔR.�;6^lF__R h?B4}+`e-;JQG0K9&bKX2`Hp^B.^0]bht?SSK89).\:IwN6`dOs+L_p Tزujm=QTA8LR9uv #+$W`8;MMiY )ذq#;=j=5jUn];v Ĥ8gQp.tm't0\[ ЩF2 _ւscdyc1Aǯpxi+m[!2 ӶX-/YhyK $riS␀#g=!# mTuA ʄŘ+?[JP?HX|x)䕀Ƕr}8Ao5!sY$iۢ]JJѤ&'!q( =^'|/}6yeY*U * "A$ Նvkvo3$iH)Y^X]*\K/N?_{':uO(a n@ (PI[p]b}w}:{;nl=謬ϑ?gnKÀ0i8" KaCv16מ)+�y1%2J!V;tc8;fˎ n!+Hꮡu- baaӔdTqeN;׽ϵ(o 2gN{G i[RfS ![R*@ >҂d-,�'11.A>A:ʕNYfu0 wkP'WN:f7B�F1!:kT&B*/"?7/ c*&?{ޱk[c5D -|5p ! JȎ*D/�kȼa쪪gcUIUJe !A@�Qqhڏ=<hkjm+( "("3a&y$s*5ם9gsoM $TCs>{8goi\KVA *P0ZI6/sژ:=oe݆#`TI3ܑZc\c X"6&ǩMd(2*іF ?u1czj" +T,@5@.K'λbW\QMU|aY]EDzDG GiM۔$z~@~nMwo ֒`0 hTw˥*B!9`hWL9*P<ڶ=(_#PElF 㸮Mu xO<B$#"Ÿ�V0)SEӢ<Ը ʠ< bOiiAf{/bӎ]EнF <"mYve,^t ű,FyE{RGK͠R+–RӔS@_@/֏D_@Ά @-$TAqK QYQde)])k8*d"ZhmvI^ PK w Lg̜>zfiiEh< yj3ZNMX F Z5 # BzT\$F|Mcl5\|rC!-`(]q 5ͬxIRq0wfzͦu>ӧqcET a EglZ/9՗&ۓJ5[2")4\;Yn ^Y#K1k%KHv!%Jh5Px|f~Ox5N}C`0 `8JI@2T/; BtϹ;J=J²]rgAPy enƶmHe:ٸm /4--h-<hqb9 "awbyXϠ$>OXG �D#QO$cr$ =n4moG̹MXf͚C#|DqV:Q[Eؚ�Gs5"5EA@Hk}>?pB@ (:nPt``9=܇e}coGM~@cK,xm(9�X\}{Yz5GTfz!Pc(ߧ% R@+,!Q@K! J:��%dX@@Eٿ3=L:S'V#\CP5E 똼ty4xIDd^*> D=գIgQ>7Fsy ,Q P8:4K hI>< wqӕWz&/yǟyM]¡u͂&O(RPDbizVR۠GTpU <>XvR>Or`{Z4 `0 cRʰl۶=K<r׿^-N(H~4:Rp#IT/Ŷ]O{3ˤ\Jъ@F1ZXbUA+"!% I{ O$35:iљ6ϐv ! z@)Eucf:klB.ї;wO:;`&C/ʆ�ǵhx_�Z$q̏tåv.<%`f RXĄFYg/6ښqa)>TW7p΂gR*)؞r+mYx*s'N+Kh*,ck^243f2cV^섈THkJRrJ"PZ;B) FA(h� T<_  ![T.wO�˹Ks9 =AJB�ׂT_?N_¸nb73!5Qn#9_R]cCg1, y6YOMF?aDMV󴃀n}WS= - ==z-;wv�6dBP[+pmRZTT�E 3`7L$7odz>vٴi+ҡ`0 dM;ʎje˲D"C~`Xp(+8.4S'#N3NcsH$ټdž@ԗY)H3Ux JQKh-( t!ЮŶTu"u2KmO怽"&NDjI("( DqU\<UD1 R(,=k1~Pw0@_�rEʢl 4pIC%kIVKv%mK(F kxp^R 'sdig#Ur<Oa[|&};>F) vtX|e9i!l ; @XP=ڸq K,] R?CwC%\XK"U8Хv_vHg6KZ6i<kG5}%ET ?@ Eo@IXAIbqvIU<oMēϳmg6=8gi~It!hrR)ZBNp!W^r);}]4Ծm,^I `Ϯv$J (I_J3]`k"U &L3: l޴@`0 8\*SW6ˎg*I!b !‘΀t.te  b1>mxyyݓh僖䲂^=0Yg<(lKZ%hY^4,rr'̕<<5HGWs=,+e[w`0!QUGCc=`Μl߳@jǏc=;wqW"<<pUA!#Ȥ=)Mx0rUG^IVe v""j+ZS#=RZcY(\zRydH*f05̙@\_)6Y,kXN!\Qg˟;6JAm;a@fj־R /q ]K>ǖ6¶PZ5T@ qR?,JHY:q#R)"5'ס5-Х� Ʊr<ހs.MDsCZ0ڠlSBT GmYzYH:E`K(r;bjz9~׵ΦkzvPK,&(+hy!ӊ�Ee]@$cu<#tv'M׳Yj5kgFfΜNuU$!%n hm*G!gڍtvtK.C `0 ' o9P+<aX@kmV9,穏26wP*#&sbg_}u[@<ٔO&@! YV'HQsQA|TPԚcc>gm6g}ΫsS<gV& :c~v)-KBo~2<AmChƺ w = [p]4ECD  "\n˷xjPqE͌OvD&b A:UaeȀj_QC1ڍ3eD4zlWFJ):=#dR�_5@@ wq-C(E {U.Z*RaBaM}N͛ku,K @+ˆ0b>GP\RU8F(5]h{pX@RkxlyV|}iΚ붲MđT MD,$"qqWWs}#+Ex?G.I\X,U؎%S_|B1Q)@85 `0NI@%e}@eò1_\)\W68+FW #zx`/رU1% gTX͆\~I)-|ФҊ:HAQJVe,5D8UJj' i.d}3yUh\*-vr&=:I< ċ}Q0Je@>$JK |VSkbMA1?.U90. -}@Up( Fr$4tb]AӶr|\>O__;W`C<@+}_N!LR *IPهe(BXh! -+Z`K^9JeHsG"tp9hovu4M,B( ;.5.@S$tȕ_2,/ LVP$fXqZCOD)�RM3ٹe;Z ;GBjM\jSk2ظe3\>~w kXb#y;|0`0 śvTjض=\6 & % ˔ ʼt.WiPW逨T={F  T?*FJd.(DHmM{*sj-fY`]foXI&M<gG⺅}KI{BQ)I+29* i< k>7,ࢸf}csNR/aеpѸH"UZ߽AhjPF(9"OCFg|TAPPVR L*aGBH.@BJbi[(ǒoz6hū6 A4 Hh"P GBBH-9V)  $}7ޱKij(5H!XZa_+@/vѺsg * VF [u`0 aR#*sˡ ʆfYRخ|rH9VH qjEHPG6]C!3qlZ[]"q%mv$AHDl M5yZ3&VM "9EJQWik3N� *po5}LhAŲ%Owy\@>(D )%7ۉ',_St#|\u1gִO��[JT@ٱ%1wb<_e$}r2}dhaDI lFt"/J:PHƾs:u2Kg\R$VH \*QJTnpU*(-Rrzة %%~p,Pa 5V2oے �G ! HD+MAkBB{^КYڈE#d3Cޡk8 `0 '$`` P6@)t%dԗS RʼJ5*E˟/;�eJtlebW; 4ZjV$Q&Naٲ3YzYTW708y3)퀸T?[=Z6Oc~E@>_@X"+{صbѫ{:@GWؒ \A>[S Je!D<TEdjƥAHs]SNAZtv6W\˕㛙8sf˖ ^r"TϐY⋴NHAU**#E*wbG+ (S%vru A!48 RVaB D3kV+BknF1_$h|4ZH-"*,"@KA!-¶@=aB96R_ " ,l|<(Pujb&&y�� �IDAT-Tj!dA$bT+*Jg-pI E4_{>l_gw;{wfy\tk`ۖ]dY 4a*A}vӃXU,[`0 ae#vX7Ɲ9e#PȐs࠿ e*+wffk;Eٽ.^Z f͘CKU0wY I3ɏBMˤ`wHaKldؕi'1] & ˑ/d"J)jNVK$Zq{<7; WO˶5Y/r\$\6C6Fe2,]rfcoP(L&2y2S'N%LR>[ff¥t w3IԀ-YhO]=,}K܉6 -L:X,6iA}YZP6QfRQ; &,3ߕ"}RV%18C蘃k10uz .u;y#l葉D%Q6a{F -4mcE`9hG 2.5Y$ЀrXyi) {i0BM![ F ع(maNj- w:quv>]8AZLo˛_%yΚʴjw}8_q2y֭YzS;.Z~r^WW|&`0 T.}`e$@q+?SyJdڎEu]-u74 F +T/a8|Bŗ.t|z:XH}xDbP ˅ Fb[6렔KA:EiE@2q x*@iAFZSE|*)o)3~�ZDq#n"^ +d\Bqû`Ʋsjj&Ph% v짺iR"5Ǹ‹ٴi#Q]]C2Q_ V]޷SR[R)P0";}VN H<,BU AI)'ѳm /:X,NOW Hw^Ab DcZN΀&* 4P+J� tA',,4 Hm$'S)Fݔ'=ȬH9@6Y;BAGIP-y{HVlۍci^v# B<gDޏ`ߦ0ӡi͆;@MMU+:U<5!/g\?% V>nwڜylX 6 `0IZANpei} ,W0ʰԂsUXW2@JҚxUyTlR AZ)"XM<0Az\h^zzzD-x|b1TϷ,7o~x^s]Ʊ0^Jl'SJ#2 ס!n6 Ke,'],K߉놥8ڣخJ)$3f̥m|Ct*ŖmohE(P.gY>sh8b,^ Ba?Rg@R:B;Be *mK mffLw5g2MU\1[F,6ڝyEs%^~<,:,;γuxa)""|m2\pKUM�?AϤ)-jtb7#(d{^5V PmE@kD9Џ6) :}.uQ&%ͻUMn�3L`UmgD,s,G9u5!=\~Y aA0`0 `8E8&ippaPaY@;u;,$8TIC!hDi4%܅:Lom(_l-b1p"Izعs+3g%BJI<Ƕ!Aوh4:6�_\i[ JBo6 ~ٸw~qmeP/Pd2^^"6 / .#Iti(Eo6V@WD,$ Gc,ԋBNQ%)z1CT4Z+Pa_+D 0�:Lٳg/s1g&$/=pds(Wh-[i-y^zithz,;V=A]%4}9R$–494 K*$BQ-u}ŗLdk]4T $,u�3H2I,hI ֭aoZ-p Gp<}J|IN P"P lA1Ao6o6$v$}Riz{ja`0 0V9&΁8C6ANqs2<n^YڰR�## ",ilh}^hhh‘PBQH؟ĉFHK u&O!3g\mh4:th۶r˿, $(Bʿ0!LC ax{s96luk54}uTWՠs0!YSEpl;܉/mXjAgמ$B0JAy>weHYTi0Rґy^ɹC"e_!@}Ce+FpRīz9D-Q7E΀"v$O1]ËiTŀ.h)iQOaN[̶-;<"Utn(i*v֊`yw?Kɢ;lkŇ݃m%&9=Ŏz.~!ub`3(-VF-#YN3",u-4 yVb^"#::2,\ڣwP 'mrqZvw2}`4dfzƯ9Sj 8 `0 ccR l°3P\Yɠ10dVh TR~0^6N+ʟ}˶Dط{/ 5`kYKrX0-mK d̘1ի_%KaqD1(AP(TyE5@J!,⋄kO8}Ȇ@{�|Ejp ֱ/ /E>(v=צ֐)ٵg]ݝ?/4H]5Bc2R2E,k~_b[n%@OVC&% KNar=%$Z'Yj}{r$ ϖDZYB?JEmW{ؗ%ȩ"`'#L;�&ǸznÎp\qRD9AI}aG<y fs&a^R!3HDRr=iIJ.?<g"Mi%c|M }"VuՓUhW<@\DxL#dG jmG)|`0 U+�ځtTW)Ch N۶^9\ j8ľ 445�lAK. 4U%21gcŊ<={g-ۑhjm4-BJ,@PT EA)d(X!|T}ٽ|y^¢gH@ay/H BD!%BR4&˱n밄3"4$S ʟtTtUF BbcBcWHT2<V,i;6(( Go*`R3x'U=B<E*P /7cKhnPyiA@Ef=;h/!/33ɪ5Z*N}\F A۬ɸR$z:iF|_ I4M-yv\zY=_U/)ziL%]YZ5v|Fms@#qO*pz1U8 fLw0E/o@],vTDA`0 `8kWl^} `0 `89`0 `0 ){7 `0  `8J:0)hꏃEIH5 pc`0A,BXGg `0 #`0 `0 S{ۖMo5 `0 `xZ*}Ï)ʽ+0xe0n03?6Jvv״ws{5Va80c`850s`8<f~mN+8c䆽%{5Va80c`850s`8<f~mN+8crJ; 'fl f ̏ͩҿcc B3ǓrJ; 'fl f ̏ͩҿcc&DaܫÉ[é1clsXil$<A+jpaƖpj`pxۜ*;V9q5 {++jpaƖpj`pxۜ*;V9q c^L}k1jlqQܹzcreé#ΰ呟q{Pǂ1NT|LYd_fC?姏~9y QV>q⨾8ϓ?@9e%v+ww_$}uܡa)'<zm?ë2'67=F [;ٸȳ?U}Ĝ7ucI&N]sd\xxc 8ĉ:GsGw듇=pԜ4{99M};'U;=_pӟ?ݯ"Fk;h߱=_Jæ-8pT߫l}/qw>Ϸ@X~X9I/ȚKiUX'1 \'ooEX҂O~ҳCݒEKÂ9X0mry՜39vt.)-_ ?\rWR&Y;Wxze7-g|yP inx._ϱьgGͿ4^I&N]yk>qGá `R:Q> .x׻pVq~dw<n6 Odϼ)qp{>(vw'V1&`|g2 G }c|7 ~wv=7wGɑ)fϦ&ɼSu2q$Mjj [%L6M[WJs/bI[dQ㭰ݕ8 9by ԫOK߱gs|֯p#rss ML\GdtqxG?ќ}S4d'#+^K_+ՠxC} /_Z'w[N^[sVch<=b<̱�0m2- Y;ɸdV\>|Vcq,L}'WgFNsO֟/<c$Z .G<t?+P0>{ _f<r.R 3Nг*T<;X!M_oC\p\N=wx|FJ^cCoԣ;\OF=?[϶W ļmcC:(2o:v9yy?v :le>}G >_}oN%d ZhAR)1Y8:ZW%ErJq|#FV"9CE=ߥss\rxWyJd3�B&\{͜U{gן,v=H^9TO<K?i>lܰK۸ټ?T27}Ywvȸ;;~>@�gM'J- xlN,F9Q` ?6CタE7a簅>c.ZZCGzc},]'wa>x_S=ySܰ!+=Ȧx-Is 7sqt?/߸㹝@ipf]ۑkxx0m �(l!d-S-`Ay'Q󫿪XC8ю _3gjNj٧V9C9sOm97sn|sA^{M`U37Lbc?懿|M9z_f`v~<պi0CF<i|7;܆_ln4dw$)`#?[֍[:ĈySf,g`} RK\F _g�ges9wrm>ӧEõ]`�bqϳ@f|qԮ//.*.chk4i4;<ؑC1?zsǖ%+KEz>gFY4qCrL7ۯ0J{psRy|^:S?>h)Q&s,= _@|\/@k:i6J\;u/;_9~+O=Dv\'_E7|{\Ǔ܆o3r%Fꥣg%DI-Ī؎]=?_>IuQpyrcJ|)~n족&_r3~A}z+l>Oıjqv=xh/_ACEfM3M(&H&| HѺ&#et?|bA;o7yo|v;zpk;d,:^t s=}JA hS+cj]r3Q[Zi׎oH]rAvC}j[ D\81x"Pd˝_p-M;_+͒?WfFzWr@<Y?;x'tխ9#ཝ(C{G|Dž\ɊՊ,v@%瑇r. ??S[m~D-w9l_O?ZX{߿4k>7iN;tqTpl\ϭ~psXw9a~*>5_�b kq^u?#by|#D {yײu轏O2[or9a38GӖ ώ{>Η7`v9n"-N`܋}o?Gߣx;z}qmGA<#ܫQ"y Ϳ~=tk?]Jb?#FNIMsOcǫi50V 2pI+]+/4^\4-|ӟȬh1|cWǣO>Ƨi[r'Nf !uk0sPcƌq?k>F{V/gaԃ֒<A7\cIPVue0s tn{ch3'"Ŝ3SHݴ'S {~#p[di6\3{ZRFۏGH@9^ l1fؤQh&5$¦XD`t:](dEkFQAd߿9+M\tV%>f|p'cV?x;팻fD?w�ptg,*G<tkpb8qxik9.9Ęu%Lnx/Cس)^/Kg!ϼ9 =2iN72,Q�� �IDAT{ f9mqӘyV~޺y`8"뺗r8V`\;?7;LA⫸s,|6k8gp<lVXÊorEtV>od)0Ni̚"yj^z2&<m_M(]oǿ[eprf~;1_OF^~=L55H9" px:Ǣ_GmnN "S3y?-ǺO񏦝Vk CFJ|h^kuhAƙ:! a0B3oKh"ƶ]־Kp c14aBGݎCQuM &G<Msxn+<a g_9xpUWqM .Gi}yuסF޾*sBDkO\󟥟Igs~Yρp=Oq_7D}=)9梆)-TƁA4ulT`Ç'F{(f�.i@"Q(`l Slj _h }\ao^_49-B5v抴u|Vu1k`!(H)%b"!H(;DPBEF,X}mxkcsy9=ܙnvf mR<ϥdB|t`ɞ*~y.%hYp!<r*xꩽe<_eVgȳ:6B='QF5gdDڒ2 y zP:)R6_M3*MF`WLO=i7OPؘ;r…ҟHn{:K&oa_t]^3vJW%[* {kg9OyK)BlJ+A j2f 3΅1;yI�*qckٱ} t{]JIBo3xq R.o"IiqƠ!ҋEEA:tz(ڗɖ>_(Ąo?K/KNf SəR ˌ5:�G_`H5٭$?9ZFBբC9OCϱEܽq5Z2a@9uCeRY�5:t?NySkKeLt2 IH4w2-{&c !.(4w4(N9CX5|N( 2ljJJTbuؑ;><oOcߩ^%JjbRpe2+^+AA'/ᬶɍRNV(2ke;I଍!+"s;5tslGoR'";9ufY:v;;u׋&{M�AS8?֭c5zK~^gO=a7[r!goYoI*E6V.}$H(f ݹQPE%RDuze' |stDx s#vNɒٺ+(_A]?~ B+U|9pE`K":|<=D5&Ì7ΘiE;<; ]]m?oz:IBAa\vmVwlK3S?~(5;PmV(W23#ةaΜ,c+) ~&֣/ m wכePĪ IeOHHVx*n\j6f5v ס1UKI.J2 ,XΜ6|je -*d;@B$M: ɺ>?K ?|-|=}]YU)`/|393 {4;:ټ|ϔ#B{9cAp[#㦄m4(=.4Vя[R:1]*7|]C)S"Ƥ`(LH,zÙ};[wBƍL]֟Y4G_7pryp&r/\;/j'W,c_Bi7 uہW=\WT)_~UG;c-;+ {|bR?,Bxn)k/Ӯ^Rq8/B;F*r*x^{\ISڡo.I !)Ŭv+DV5Q;yE'*iWRHo]N/cCO_xTqqI]v^Ζh֬:Uޠ@maN%Es 5,۔>8B3XX==}~ck臃7tOEJZYF:{J4wq%ڼ`9~whXޚ3[8 cF18Dˉc' G"ԊΥʅRɮ-zR0qܼcA5(cSZʟoۙ*Xr,GM/$$YDz͉{X}x COpp=ySDgKa!V~!Go9E)Hfٴh*sּ4JeLMꀁ$uQ/7X^E ^gn Otx;c}ijU= kxN@ iSaܮ8bC/g|4jdTtAr:_H,vBNř'pХ2vɶ)T C/ɦ&y1VPw,Ek!O-ڋk!+bQ+tiR2Lշs+&B+:~k'Ft@є:`xf|#'9L$CQa\GGbVe ޮf 2R|e1lw;'OfP暧Pח-{&4djU T72^аyf5GeiK|b2U(; jK,Uj+;dIQ$LV; "mK OO;ݴ1W&M15IHqI'�C\mFkްcvVQ꒱A!kCUʘVgtλ`4י>=|~# [GW9DFѥ'M'.෱CHt-'rdfkTy;I슅Rӷ](XؘɟuDkwS"7⩳ ;]vrͨCv$m<;T< υ*ߤ: v1r 7La4l˅g<."fj@|8n(3ڵ៩똹*>n"|W0_GlZa!{sіC4^nВ:+G۩-Zg))cπz=oHaO{rq#vS (\K_jy>".5oaȮ˟R2obܰ<W*Е52 ϖ?%R JkGJrߎ~,i<#SL}!ChGz~IeKYGcTs"PdCv@ |o%gD$TlݏΏ>R㐼 6lျv`5zڌ6sWyŬ!Fol޽ţsu'Vdd9Lξop<0vIIyz~>u*]Z7\ʝ'k T vxU}iX]g9ܗ?'wcccc.3ZUo%>[wI8^R^X8{vxBmiR4[F]Ut[~_˒?Aw*K�XмG:ذ]m6Ve|*x#x{^7LJIRV)--HvJW/Sx@IB"G=NYM{L8R�ү= kyLB}Է+÷̮BE⪤ C%W%(ed;wII<`%  9! *3K(pّ7^Y&-V 9dȝuc*_S':~dldy/?B_ws� }cFk,}ޤPy ,]7Ong9tYNL˭dMKydȕ>yig)W"椃:0F {91:8cڜI@a+P #h@NBEdGRQ}Abp<�l%D2qАnZ(HC:hlݕ[YdRCBD\q%ҿ%G'{rS/n (a!<9s_+0'y'Mk&Nj:%c2OmE˓-W&۵t_ʙ1Y4g<k36 gV:n[ih$/b ͱ_hw5ju#8/X(lM1Q.L ($Lu<YOg /=J#/v"c23mPiLB ߹udjWC]%LY1O.٢VL( zep".cΏCyr𪌄6Sfwpc2%2OYc@KYY^ G Rc@_9ŧ r g͎K܉MK't.=P]]CP(}K{e/n8SJ%�w]/N JIA1iߧ*,Jb9/[` s[W9(n[KŭoG϶b@']/NO׏bվE*V,�%kϜg5`?ubTdPS8BD+":PɦoQK9 J ,G~LD,̧UI)!@b t] 0Џ͋Ҿ%%E)ÒSiEMIRAC-@@`%}KJ9Kb9t@j4()uUR!(~%] #doI)g ,J*cdY(/I*)?D^ QyQڷ$Cpt qy@ @ \^@ @o@ @ @ G8@ @ x@ @ ^ps@ @ @ G8@ I<iΣ}&Go|i"R 2NpC"k4tq Ssj?.<Dz]@ (L ٚ}9G%^6.\bOvW_1mQXuQr [5x&QNʡ8t@z ǰwuB73}<΁uo=Ob{)44DXk{.VhRMi:[r+<$ag_GRWU;-15'tY]`7uPKj,TR[I'=:3t}Ru ,w"ZtnKVOD/m8&37y~2CMgQ-ǽhC&f\WNUbE`Ͷ|E3l=QMFz@rcEIȳP[7ePK@pyˌKng;ZeTJn8ffjkJyQJm^mM])w YQanrYハW1T17znc9z hҬKX5?kO'C+=Ţ=<SXdGjK]Yrt&x <›ylRҟ|b8{N-0|0Z&4 \~~Q>oO&gX%~dއ3w13ufme(qb '+[3 DhGΞf٬| j&fQ/}֞Z-rhb{,GSxt24v$@ J\8C8뒈u+0)AӧdhF~qFǩ{G;94b} cأKْcF~ё፝)6k<-Leak #1o"q&{e\ϵlz$#bWl*E F M2Thmxt}gL[K>:~\Himw}U_e |70I3?&Dm⾥0p5}=wC8Bп%'%!&&I'3pVbT¥x{L?(Z?L?;9f.t'p,k+t~ggsRgvꔺ=y1瀆ӋF1T)4"L6ϴL~7b{ӽX] }cd\+$9=~`KܼGNW><2:s 6Ma¿8q' N>PW9 β`˂ @b} NB%{OBC=5f.Xu(Bljߧ3cnN}O5^ڃxciܺZ6ro Z|ܛP%-v\�5.b9ϼ^:8G~5]?qǫY3ٮlQrX;Y )(]Kcr|sS~B@&n״)^+¥/,ڎb=Wuy2>;/p^)P׻tKrXL\kkX]V~3lR9&$T뿤z�ӟM9 2g .ߎ%UHPױLIdIcTȦh47gvDXQ/l`!}2vLe9AFOvqv2*goM<z4g`b1g432s7J AӁ >7p7ȑ*bڃ1%ƣUR/3 gbEb_�~6:gr=`"41]/ߗ7{fn5~?9V8uQ|N-jqDH#"sLq$OP*x!)s6fq ^NO~QNd> [kD.l⽷HxA(ARd/bVH(]ia[8%8ǃrR2hb]EK~߰*@ϵPS[8?ނ'� De0蚣ltnU)ȵGхA}`}53Y0t&SJ~/;|P=]kwOҍdDlG)ou d$ %p~W]~`+.e>ܑg1+g*+Z:έð36ڼda m kWw}DM9CacnWmCӢ|IRP(bos>e ܃H?rXmnIwi w$OlI9^gr07=:Mq%,.H1asە3gN!+ƽ *ssqٵ#Y'յycdGX0ID= < /! w~ dXFA FԣG@֢<Qַ$5:o|1g92?JD7O*~m΍FVg_3j ]8.{7`*M˸9trRIXQҷ"\4㜸&F֙Qzێ_@ۨj-uq1J Kqʄ`I\”lh(#,]#F]Cl h.2|Nnf1*h9IE|t1;hs>�� �IDATm]]|R!Mi6-5;\;#zT7\JJ-Ѳ\ejH^Y50dzP,m=]> VRDu*!Q`لtOs0N[`ei}=sXO^(l9ʴ]ҟTDcy3Jnx;a/~Nh| oپ6^撌'~wMG-0ƍ[_Ѩ)[6i'm]6䂺*}MMVhq/؏lẻm#a#;>eQhpD</EP|v"2W\$TNoЪ2{a p2XzQf5@Z8wety+I2nsdlyek ʖ+\_;^ v?AR*y%* _%ۮ_LK+3"CuKFsO_Li R/k֣GqXjOësP8姱1&3Lۆv÷dg173 ;7O1ƙm)Sq^РfHZLN±Zu1x|@+<a/cЂ &4ژDfu '\%bGF,$k2ל*,m)s홦lk[IAǍ5?3/?ǎ{cvdBZFeO7vØUe ? k)ҍ}ˠ(8Au~++_Q:Yk~4o<{-Q;gz6�BO#29f Ar"*jb\-ZQƏSb vgYT*rhqL\Ai&9RZMJ3K#rkobR*'vIOԦi)}R>l>Lۅ3eF�ѧ>Ѯvzԉ|-e\2GT /azk]h*l.9ԦQ-+FKTv=.Ԩ^"(inåh2)+�;ZeIK逢5j3O_}e 4eu~5KV<qDY ǜsPU#v;K(c!t/pUü4tnst?>h2f2-|ıEѝ)3[u ̡ooJ^!c[wc)||<�j;;$P'@..lM߄>6וf/+}]2qLa@^qh pH0o.߾LѫRv _rYNW ,yxٓe:I[%1-?ؓ9x.(geˤI1V~OLL"):� 9%J%:9վZL|/lL%^3fei⨂0C\74h\ %<|322",#Kw2eL*wTj$bNyG,\ٞJmu80|_X;dN9+C/QP%͒ݞگsv5,&K4nșހ%YoIj6y杼 Nv 2-)9™L?sŶw*XdPVC1'edY2n^s={$Co,: L1;,,T6SV8"ҐP`ɺ LG{`6{>Vx8gzWM $NXp`'$֮Hq<xAcK!-Uwj{ŽrYw+p j§}ǫqK^z)k}1̫4G̜?_[NcSM 4( KD2v{nvz8Gkݥ,3EOA;E@ʩ {/~21�E8&aRVK1Nጋ3ܻz-xlf~\~cOD%|2M,ɪ+ysRHn R$= 0y2(= x%!G�d2 3�D.^M>ySٲ@e.QHXYBbBZK[j)y s5h.ႶotkN +ûhDv-yY6o>=ǰS*Os@Pa㟷89s2Y lM9khωc=3tt0&m@8l Ws_WU\ ٧g0kN.O,eL̯뱘az:r,Ffr(hglĀ hor") #IHhN2;|86z kzOIS,m7iV^i=7 ''9#!GY\|!Ȕ rXaaaj2~ձ�/Zy7o捧s 1%GE "cC ă8+O󯿣1whV˝v#[9[Xg[ᅧ*�^r QydEyr=#$s <05K#1O.yr8(R:} ԫ9ZJ:]-yڒchd`^M�]&swk|/P}waAVٷ{-7%JrK/ѡW ;wiYߴF뺔*XK ʲa_KXV%`ԕyzl^PsHڹ^K` |JB-mXaٝ7ˢ4ٮop_P8[GYʦEiZGu*cdB&eWӢUEV-dꎨbr;nbGLy:Q@샩WӺޱǺ~ၕ_@X9KX̝26[.ܲlMD $3_3=ɄGK mH>nELՋѱ:Č9dϲ|F˪X'&U̯뱸61Į.W=6be_+J~FF۸%:9wzN`ؤ fx qhN~1n I\(f4 UߪwB=5d.qvWOg9mXu06LhOiKT%+a?-[rN*RNǒ_^UzG v K }i<;nRN<DV2=+|F΁4L]>?7p8kogS }yvgRHCdaA pgԩ/Y̚$G5R^ l$@§ ~8+G3pvJ'JWQ9ص|%SnH|5A=[sSr/xso_6kN֛ϸ-iT:21Ϋ*MWuۊ8f0x.x%e] \撂ɛ?NcɐZQ T/mln(pLis+&,8>D# "EHlFomL\<kISYaT K̑]g{jOӪ5 xΑػy;WnRNٱ��LoXq={g l:i<q[VaDΰM29Ηɍ[GGT>+T8yR! IsucA"s\V~3c3g/N@-CH!4R &,,OLtŬf1tE,-e*Q#6}Vy``C?g& HbqDqGNJl^=x-e ޙCu� C&ëJi}D`Fuz)Sx5S&_eUZݐ+ʩD앃nD?BN@D~ԙvC̤ε<@9W*ɲ@\ʢLu)q[ , 噽V "WIq~$7ap+ @ 9@ x^cӏ1l4 [@  '@ @ ^pĮS@ @ ^ps@ @ @ G8@ @ x@ @ ^ps@ @ @ G8@ @ x@ Їu3eZ@ r6aچf7kY|g@PB)S'{5CVC:8-+i~sڏKlf9뗳 S9p!&[r !ϩeR.yԯߘV~6(l[-<x_šCQ"?+TTS Y ޅS} U8Bp<殺c9z hҬKX5?kO'3\Ċ?pF4IXYW:QyU恭NKFLEM'-ux%>#XMԒ zIbϨ |TH*K]ր6S+ыGPaC)oo8 gu 5E�MJ )K?Yt` >}r~p~;}PTɭcBmC)/*TͫߢIKo~%Ʀc?c7q7~ULܡi̯F&ZVj! f/XwI*D3>ݕnJtw8əwg2<<SXdGjK]oҟ|b8{edрᛇJ̳)G~d9u]6+s9ftC^)&<s7;;]WoVb'0p*:?5phBhmǣ{X<c<X]$,%Se{zWM,wh| pN;Cf؎XpYԑG;~�g]1Nc<ŀ#h=/浡-LS,</r w\ʖdgc6ˎ oLY9~6u?k y1o"q&{e\ϵlz$#bWl*s瑤8t+1VY^sI`{Q[R]:{e.,.?=IdΰEԪ^魋tY;+fܩç?!T}'4&KHRxrZ{eHCgT<k:n9wtci ZbO{vr$5 ͮ]\;NXj5yV-1ϖ|A̟U8O.{3 bީRi2E8d5miǙNo5ʧ{4b?]ɸV.Hr4{ݗy/d'}ԛydt.mąqN*O*QϏi}kop7ПXGPޓt}xMYp,kʢqXwaS׺X#Me檽{ [k-7y,sIì6I"pL'rjLfɛh-(].WD\u >to�Z.F�jB?]ĔvZ09[Opv, Ger�nY¾,!M#Y}^ xAМe(vnϐڨ˓qVfyHޥ;]0`^ocYN;/PL?RRuĮxgj\8~$yT9,s-";١ aeF`+;2Ԝ 'Wdo8u;7{dd=$;㶱1Xfx+qJ\+zOs+m Gfԋi2zDŽAwo;clta4؛ř7֔ &]"l"T̞_Rӵ8m @1jIߞ̇vO͙%^/oV*:?^CcGUG#,gs^q&ZX<8/,ۉF|6MNƹ,{Ԍ.$E*F <Ki%%vSri<() ZF.U 8t\ ;s Rwz3ۤVltnU)ȵGхA}`}53Y0t&SJ~/;|P=]kw>t#~#Qa*#[zQ +A<*;`'<HI4_}<_02؊K9wY n F~yʊ=󹷎sk0u0L6oe.i׆9pa�{*z2j Xb\I@P{ԢS:xȉ5әa m kWwme׎ Sg9Tr(P\ QI¹ L2QAL蕻BlI9^gr07=:Ms ŭ! 9aLve@s[™H?^K85qDBʌqE!?4`@#{Dn֍$Vb+/! w~ dXFA Fsbe-#e}N# & }xD{=w|aHaoe)}v5S݅c hov$.EaJcwlrODqs�@ 1щ(zk=3˦E׈oW΢@NJ +HE".F..XY6q)n8ZgU*8' u}jDǶ6kt-Mߥ}Xɍ,FE͹{8'(љ.q^Ͷ͜K:O. C ئfKc@w$m&^'X:U]U) Th-UVUS8~<]be;*ETr6MH7,= cq$_6&gٳx9t"i?˖L|%(IED0w;3j:1v_ʧP�!ZN{n:(e.i egp}s"> @cbj_W?a v.m쉟qR*ٶ[עƏ`?1'Β65HB gH  9^X(gujVC TS|W/^OWkN$6MƖ7Cz\2۹J|ؒ&ǕL3U AJ]=xVfEfJsO_Li R/kcqÚ7ei=m&;C6C΍Sqf[bwTF4(ϵ.:ny1qD8vSSӖf̵Z5wyGj=e;eZ7ZPVC# G 윯G{i)*rhSId9UXZ=>Ŝ|MShف ,ڣpY"~4iv<P  cV54t ۯ<vjJJ7j-:G|~5n\~Fd${d kѼmqcTݙ2Qnz 6f: >c$]&'ތ9H^x9±Xd\PS]LؕߠE˖4 sCQOPb vgYT*rhqL\Ai&9RZMJ3K#rkobR*'vIOԦi)}R6^?ŹDkc${O<n_%9~. = T4f>äT (jt7dR4 w˜S Z�� �IDATq?nRԨ�3p>|)|0^&lZgʦ0t_{͌qŐV<qDY hU:CH{c=#F*c.?rjW^W,6~}'ddZ<JoL_pCFlA'gnD?];竷:nmYR]})5mz~ߍa�쐒$B]P�ʚXkgw 2yajEY Mxcӫ]]>&Ц|MSrY(*%aW/`,|5B ב=YvoIU\b�u)|KX:^m +\QV I3ۓQQ<11�$ HK( WzjV2ej(1]\x�}5A qdӘX-Kxp)zȈ,J|3IQ-WF^PE+)Qo`f G?OCqSdzg/ A&7r&*'7`I[ ޠy'o'BlDa1es9g g2<`l\)(8uYm-w 2f dY \K6dZXfuw 7 <72ƀMz?&N愯4(A&v싹 d^զ=ҟfgg8G'LjcOxny_[NcSZ^TH8EtcN߿O#cBw)nAMUx;}K/B9Twd@aG]fkJkW\8Dkx V1Ex4( KD2v{nvZ8Gkݥ,3EOA;OIB"4c,i\4 \p g\k$th#f3 {bM'*obLV]ɛBvï|�"1a~AHu/9 $ s[&rje||yϛrΖ*sI6T[Écɫ;*{XYBbBYDͥ3\Vnͩ_@0~JP ( R[wÜs,6r͜548v 3�?Cۄr1is{̲&0{\/r<Geg|^mV+s64V3'H'cA&fWXYOGL.m T0a͔\N$A h!c޼y̛7A*gЖxjO2;|86H95AcO.�_ nxvh:{7ܕX0o7ڪoҬ>/=O:E[ ; *FX?󜯁r*C qpq3jop%?p w⠮<Ϳ^ܑYk/wڵEs,o]`u$o*lXw{1Dʒi/<by$9ɟތƶqYS<sr7 -"QKN ̞3ыE+3Ւ-Y{Po;6w5^�ǿf&,"RHU1b+%]J5KY[FV[ڛZIIF֍{ "rG9ѧ7:7b,}3{V}$C6&c{kF~f8؏AAadӏ "Gi?ܲ"ڃ!&YOBbKTkDɨ]cLlU\?i6} ŝydR VƀT|M2HW7ĝ]f3M!<VC P{9[NԭYƾ''j{.<>% kNY2o6^zU ߘ~%;W&p.=VœțNQg2}+ M ޾(m1cM-:-ЍcVދX<&ƪ <^.}u]:5cZޛv(Mkdl7+ط̱&'F9Lґ^zBMn]w Zh.Ħ8nvjl)]Wۥ_p. J΍'ƫ\^/[}KX6eȐs2m$7Ty\D]䗰̈́k@]Ǖ1Deb'3O;{lz "Car Y(&Txʰ#iA?zRo�4aT~͵h-omNRR"o̮U1oW89 [˙S%JQv5X�2oʨ婘XSܳ ]DЏ[X💧2+Vǘ.b,s>M>a ?#4fX.diXڭ2Gϡo:Of1n +v.ax4掸;$\]cDʬi6[#é|L eZS/h" #܉GS?hk=;͈h[Ȩ*,/NPȳ!qt1~DWE@=p`IW�@ḁi ``KnԿ6zc% ߘ1@b9EPء[),ur/lG_ 獹鋲V܈1~}g2f10f]"%eyJǷC 39Xu7)Qdy72?6қ_(\[2jiL&>{OY3ݘi{;_.]UR2Oh ^8O-RjQ*V c2JJ h峷%s͛Èym ;1_7򿂊J/?d qk;Usa79%ߎ뇿${ OHoOA=t+n # T=V Pp;nTu~Z1E5f-&AABGLPHID]>ȏs?&7oZ?-p  Ppc   PȉKd   PȉAAAA(    rbr@AAA 919    AAABNL   B!'&AAA   OJP@ñ%_ˤLH(/_$B[hlۀnKL(IE㜼)77),PXwWXѧ%^ҳ^vnwgtnшzjV߶1F~U摐sR<wtRDQI<TR,G,`l4-o6'wn௻o[ϝqҷI0gBm&OsbTjGFר9z acDHR%oTCIenE pL1S,$qdJ[׫Kݺu nИ0lZF!)9~{y4-=?ڣd;47<n4?=1fc^i·Eg1H89 GE3;S\2y t;q/iLz;7OdaS g2o%lrVaSB:ewynx蝐6i0d2%f(=`_]Y^ZB~VD cҠN4oP;x1ry>E6O@Ҡi[>&cRl} PN69C)Cwil ~p.2eހٗti'Ȟ5 kG|k6.X< ƹxfAqc3ozu$ vY䧖enh}I޿MaxK',FqB&R%֌҅Kb?~5(&^H$<~L6C8Wg,2,N{҂SlZvKxhyz~Kv.vtabcޘ- dBBr.UЧhi^;�i}X|78;M2ț޿Ywd&wI\zy$dAFYgs6~EL "bъO ,ϯl>`/YYA .Q[ڟ \! '$Z̄JjT-w|eJ,Qʿr6%CቧBfowFm8=mJcmL'pB͕SXygr-hS/0N7[e1PbP¬VȤ,Uoߣ8ػҼvN/*n]5r12 3eG³ E22,>vY NDas*q'9P:x};FҴS)8.%[sSl<д�zwܘpk9q!Kz}j?50fOz sWym fؚ)̌+c�hV�7h- :djZǙ1*6а'h+ 1ᕈG7\rwf{Hq+%FW?o>KYz0qvqañœXq&PaW5> k`f:zQ==ë먟F/-]_`gP"qjtB_%)r;|zLg~wWi}5n֊K0|Dfhb/"-:Ys:0vIa1ǥmKY$ppFLGco -SʌGVgŞS܉3h9>B Gy\?wy`E7cTzgfܒe(S*Yе(Lv熦% -ϧ"m:#aZxa3;N§TWfy?)=9Ɣ(y>}+Y<ѕ!xo&%rs OJqB%6&Fq�&з=o6{K D| -~Ϝvs6Q{M;V84.o{F}={`-=+ ȽsgϹ;`? *G{w N_0 'вΙ6Y|9cOfRLq͢RX4| AkD*Ps#K~B3ׂY:a(24( z++G0r!'򙻖;pCN83g=O �Ȭحvg|\:Y=5L`|k7Ȱ,UZfkDKLH 1 PҘjQ*g`?q4N5K@}cbei-`b踮|@I~foluTft bN HR"wΞ?n|G\5u e|S1="Y%þYd(lQѯȥ'\?~E0jhuxRfAf=46H 過02"jnɰUvȄJN/GDGƤAҠV?iƋj-/?KfYf9xcv=O�? }_n5.}{ {?8P&-RRIX`gפ{x%r(4[\ݸߴ Թ<:#䟡t*;9 +WtL%HШhc~e v^mOm>}\yMW ]*@>x'}&+cJXȸbr'No<-ܥ"5^Y[Ņ9~ZI{WGh5R5? ;L`<zy<lZu8G=<8N 'JE/1eN녻p'ep>YϠNȁ ^?<O.Ƅs >ar7=L8|1ƾ\) yVXx֠g2<k?.^CKa4^v 'xq$M7n|D%?Q׹*ŖRƒ$]r' fcvY uV7(cSzL5*a߃vѽnJNR띎_Y/l/[gJ{zx ~YSd^ZUH7>M=f ]ZJWhcI'5JvZĄ˿T˸cQM8UKFs_] 'Oc!%QP隞<=F-c#O<~X^I'=<{$){r6mх,<Xdq寏?l6rh.>jI"jb> Ty.K05)$MyCb= 3Y#a3cz0zn8=4ۍl1j(HByv;;E/obxu$ MWh%$dȳ(&}~"LCWCf놛U"·8ļQ=އ &s0q2v8ԧg6xV/9E<}SzkIvTcU'pk"noR s;hދcjR5]Nxei<8Ұ?p! 2,j~)%^^kLDk0u}.ŧrpfi\܄kE <x 9-br@_ڈ_uMb /AVANŁ8(bTKrC- f1ԦS4W5}s_< ] 9Mc7RwCx@.&M9a-~jOel=V۱G<~,&[d|Zz[9u9ߣ!LF|7Cg2̏Z4u}[Y ?G{E<s<O9+ML+3tZ i]P:dzTJu\2Y^*8~÷zG20MT[?1�ʣp,>쯚T4gGZ.N,J"޼ חJO㉍MDa"RZڛ0j[0ﳍlh5ᠯU9RwHKQ?S L�G5[ xf,~ =ᶕ$$ uͧ$Ca[y;f$L+$] 68e̘4b͌Ǘp2/Xe؍+%�V.Vֹ;w}2 $XAB<1ʵ={˥Oq̔ݿF#ݷx2]iw/6yU^/}Jn%_m Ej=3HgXu1$$I{9^1 r۷4'08Y~;PVQ#z?̝O9_kPȂ18D=&٢(fWSy|>_&&o -2{1}G?~L|zy^P4~h~_n˳̵>}]G3,(x$",YvrHƁ#tOZۜ㡕?ַ=QWt&\d|5Oɰ?UkװjJV\ʕA#wfh\8 ׳庞ptGw۞Vfs`KOZؽ#?Wf6td~Yʶ;ٛY:Q^0n�ћn1zensWo,[ꅧy"M`8Lhԍkx9'D._Ǒ$W|vʘ2&3utu|ث}<)Kb:fޘJ $$92@P80h,dXZZ %&5⸂Tg}<L#t V<Q mwt݆.s-$W/du@IE2_))sWp0$WpꋌMgh£[~Rt|dY:=y-[HoS6d 47ɛR�� �IDAT_"o61\"t`W.:<TW1z>剿Jf3%L.za4мI-]v?yR4=Q'9Aue,( @qJ[_}<QDcl9t)kܾEIvQr,QR8r[g Gs&6qsS-g!g%t�nkC rQВS35kcyrHC ٺ%Q8;Ni(U+m o Ybgw0IlMN ֌7fq#jѵ&0ɦ!>D cQ3jDeEjѩC6M[Tq*5̩:Q˜ =F—)۶_I,#V~:=wZ)c&.kE؟al H4(ӊ4ZLu{xz݇Grؙ!{02y_ʘjIL bS|{9:HXXY@b-oτK{9[N,~c^TJۓ[X=s҃U5 oԷN]`묟yP +ٹ2!Ňs*Dw >[9mhj(]EƦ3F2Ztj[!HyLU%y<N7i ұ޴Fn*%_+('c#y\že5<3"a<n[JWAgUf1Wn&ܻ sƳ=asheIQ =\l!d]z\^yj@?ƌ~;+ǣ&Txʰ#iA?zRo�4aT~͵h-΅6'CM>_߰ul߿aq<Yb[kW q,caZ==MM)y*©lz@W9Œ>aIdSчY?Yg ˅,:XU9mR'p[,-a%7x8d3{7e5L1vxWw\-Ì܈2fMO7s'ʷM%3G:w]Q;IUX`m_r Ȣ/4^Rrc›DbX9� /^14XXZ"S',Y ~RG#Gq{Y#~%�\:Mቘ!x t~VI:3oqCqb cnAɕrMM|27/26^p{m_ߙLYLYHI*tGF/ 4OŒz`2m]MJ&Ep(Yj>ōL쏍qŗ9 זz>g2f Ϋ[ 9/ڍFgSU*e(CfXьq u_[\X5(YƗ*'0un<Z:iSrT$=̔x$ISx  om83>' B!M   Mbr@AAA 9X    rAAAA(    rbr@AAA 919    AAABNL   B!'&AAA   PȉAAA'%q}_(v@S ǏؒzeR z&$/-o4ifm@%W $|7 tXm^aEtzxIz٥ѹE#kL[ GBIQHqs/.G%LPOH]wѴkۼ-~嫆uS'ÿc86bۧ9~*zykԜv0q1" $7!{2S g}|88j�)f Pe$LiKzu[. ӢCMYU>ģpS!|[tܐK9>'m5$n]7Yj?_T̀(47<n4?z;/nSLrɘuUVswǽ-2=e`X?Mi<l?,ɘA̳}XM ԗᓗrLMwcl3 lQ gL++5$%>iְ[tfw9|VU*TjDmL뙧x^TwmzjLо8֜zߙҭɫJέG߶Miظ%F,}9|KG~әN(rܓbOp<>tFVkۼ-$䮄Gkɭq6Tv,fC 킕ZkWaVߟ78w\Jr{:`hE~jIPƑفAD+聗tn'D"c ]ǹ:CdaqM6/Kbb!.2k{R[Mݺot><D B]61xrB-$$/{X}Jևw$;5p{Lfrw?ߘDΥבGB!3E BG{wkaݒE|ufؤe^~KmPҥUX _y-8,Ṿk6.Ƕ&tßNpyy)?cTh$U?OJqx"%cO0<YNϷ ӫ xr@BAΦ>t;=<46o)>SrFL͕SXygr-hS/0N7[e1PbP¬VȤ,Uoߣ8ػҼvN/*n]5r12 3eG³ E22,>vY NDas*q'9P:x};FҴS)8.%[sSl<д�zwܘpk9q!Kz}j?50fѱKVv'�$b\ֈH\ g8z:/r>=3޴ٸPBe@@5jz&sz]O{50@eO9J#hV�7h- :.FA WA!5~|`,6n~I1[<o(V8yUн fƮF,PG-d46>U׌#*T)Z.�9E[Lۿj|{'vŧZF ! _1~haDd%qm)Kd8ȣj ZĨeLjQ!)E=|@<_f8j>+N EPJ>ZFϣ(S;3rϩg`�fdDj[ReJX4>P|ºg 478q2-ѥVERA8箦2­o{!p$Nd\ϛad _w%P9+oǣQ˃oS<^-a(m=+Xw>)�{ ҿۘ4M�d8VC'[8ڸX Gĩ0".s{oY6wWxD;=,�+M4/eI8GW9ڻ[~ƟXv\P<%t^1oȗ#*0fd&[,*A×llIDR�57¾d'T9}-:)-cL7Or#Y2p"kc L:t.4ًC2V̥=pYl]wx,Kc0p1n¨qI)b|ZI$?sʟ>5U0sK#)/rn*-H돳\ByY4 m&0rdX-aTXFPygۅw[ҩ[!~COD=:|^5u e|S1*%!: Pg^v _2gLuFaT}E{'ƿ{owfS|X\EY@GoH57׍dتXdB%'PF#r"̣j�)O3 j-/?s'&';fiL)Â.nzL2g`Giyo5{?c#<!9<+ܭ?9U>vJt�}V(3`ǔy ǂ%mOe81nw񤬹DQxӦ[tsBNFLsK3E%W͟g&nU,/D5+0NYYct&.9HDJFEG.SP,_j~"m>cpu:HmIJM9Sy=Nyv[KEjTK gsh(%kV52k`Vz1v5.:yyش$qdݏ{- yq6x2Oڕ@_vcʺܩ w}N8ƭ}A͝4\9 y@kݠ2l hӍ۾g/Qu l`gTeuJf$I`{ejU 0S3iSo&HZIB&wYA+M:l0T\Nc);ϟ檹 ||풸p r[|z`JOW'-3P^ud <#=m՝@]G iUq#ێۿ>sWjV)PF%{0{.AicI2Poy{xv1ugږg5s6{<҂tieD_+^ 1O:Q"&|\?^}IgDp_7tj4r;|2Ag-Ó35TalL!%QP隞<=F-c#O<~H|,/XȤ =E꣓i=zZvU0[>}&+cJXR …2iW|9yLicl)) C8+K<4)$?*0/b-z)+7X=IMzn8ۼ̪fi3a~v(j(vZ ,'L^2s&nvp>V# V|TFz2$Nd*Lpm9>ae,hpOϢm_rxԡ!t+@s ג\E&K\OO=DߤvѼԤj((Y %$^5vӥu)>ݴ܆X5N&\.qg.EQ[$GqV,̗Bfw,Vy=#޾:5}%BO#\>u&|d3'/hZ'ϦRWմ^PZ]ck W-br@>mį:S&�a B`Bt*y1%Wq3Xsw*hM7䴾p/zes.jބE.|7$wDbҔRxK݇$lTs6&S-[vla8146yVB $)vexfJR)f?WG`d|-bRT"q8O]ն.qpM=Q EH+5Sf|tfĮ\Vf9ȾzTJu\2Y^*8~׶y-pi aw6Zn.pmTJ D}7 && iznZ֓èq7vl¼6x~z,sБ4S~6 pi߱]SJ0on[IBPw|g,L2%P,o;)rm݅eܹCX aU IБF,{ϴwP~(ncmʒN^^kǂ\HpʰV%me $Tl1"Pyճ'AZ*.>OXE2SvAu\V.1Xߖd^^֑llHpO{f<7}ΰbĘ@$fxm�2+g}+qLc~w73~z6_4#`;'c|=jD痹>KuM z,Qڻ+@!B;jQ>xLEQQcm%M*#h~Kgymu]ӚmwsSKΗ rǢ8∎QtWKR3I'XiLVָdd8?wL6Zp5(IDYQzGx׶yȞGJ4Wr]k8:HmO+9%'-girDʑ̟+j3j|: f,e۝MR,(S 7�|7J L\?^|VDz¹n7^n{7x<王yVHH3Ksd̡qjaR;YȰ@JL 1/+LbfzXrJ֩o ~߲ԪhKUIO6?ҷ>uJdU&dXCbBKZ˩FWAYz.]-cTC[n5]K\< Ջ2Y5:˰: EɫϹ+8_FͫbaldĘ -<JΟ'=kO7UnjaT񤌗/e,ΞFv>D۱<Npm9hn;^Ŝ~XxA&CF*wȰ?UkװjJV\ʕTMnY^I%!~T}�y ?*8xw3QV,G֮>T?OTf}e8?rJxeiշ E1VLʖCGБRYD]止_Q*b误YR0B~Kn׆`?l*.D:m535kcyrHC ٺ%Q8;Ni(U+m o Ybg0IlMN ֌7fq#jѵ&0ɦ!>D cQ3jDeEjѩC6M[Tq*5̩:Q[KLb2XXX@sux?dɰuF?ƌ~;++.?6.sT<9o6�4kvbd-dXTioY[Adbz`R VƀT|M2HӪFՈ ַBK{/bxgzӭYƾ''j{.<>% kN eX:˰:)zZ1mK6&Dp.=VœțNQg2}+ͪJ}icM-:-ЍcVދX<&ƪ <^wֳw><4X Kr|f,_{ӮER#~ q9dψ8 |X:KWzkyL+K 9IuvJ4)m)]�uqܭ3l\Mqܜ0URJ~^6 کsp5o[S{wiG^4Prpy\B-2ML (η^ʏ&Txʰ#i>_2WP\Rꕑ[FJBy7xvb|noM2|p!aؾ9x*ĶX)*֮F+ ãX<-S<+{{Vq STfS*3E݃%{}NgQ3SчY?Yg ˅,:XU9mR'p[,-a%7x8HL;�k3#:d ؍$P;c{v ?rNxy\W:3l)>-ŨaMDFӞBZzȟ{U5?6/"l0R̝(~44./br[,�� �IDAT@)X#긽Zx,d{Oҿ� d.mŦDLK<d[:Tc CE3Nw]}1m1HN;;'0vd Kl\)߄ !ycn"cE ,;6 ݾ1)I.PU:䞝fD4s-dԎxRX\b(t&\e,ۺ񛔨MP<|N/r-54}&d~ |lF M'%%y9QJ]vL;4@/XѻN1ŗ:C2~~^56Lx3Z~[a|Kzo̚7d)<AA6auAz&EAAAA&19    x@AAA 9q    rbr@AAA 919    AAABNL   B!'&AAA   PȉAAAA( B^/Eo) T}ñ%_ˤLH(/_$B[hlۀnK>A7)~: -@ViAǩG9,-|7Aw{g|FW1o%mcwdl 9'r_\J !EA�)k4r [Nĵ0$ndۖ=>}pUMlEMS=ω-kIFĐ%E]Qn' d'UFbfd "m8$c?]S)f Pe$L}IтLaMQ7ԧ]rȷ>Y+*ӪkGK[!3GnE1wwKb:NŕXTrkJ@<ӱSoyhN7[F/[L^Cp!_N1pvubT0)sϓz8@aӨQRA)̗Q%(>Zc޴u16 iimpP647C6|ƨYYk|Ez DE #d<s8μ\ʾy^̑SXg.ؿVɹs8pԜO>KRyVү|r"GfY}&@=ǣ'*ݡQ2( -SM5#=IZ/MZ~HW\P)J_ 5B:2 Vj%ïq.^YvЪbܘ̛/s+)`]%AGgZmp`S^fI4BwTE]p-M< {2n!!cT,S15y-=l8Ѕ v0Q1\8{O e;`4(#orzf >7&suBblv3We^ڔ fJQk񢁐;6d $>D"LXFRyz^M˱m '%\^^JIՏq^_ɘS,r<#oIII$] ?n),YaL:Pu)NO _;ĶFs瞶 ߡ/ .t4Vv +//6@owfX޻lڬ?rfrD&pdw:|ő5-ЧszaVqkI(l-3>*L³ E22,>vY NDas*q/mƾRuj2viRȵq\i1KçxTi1FszBn;h h=j8a8k^J{TՆGg[[{'1j1"bTmJQaO>s@JRv^P?Ȫs;q&-CGZ(<M<*ԕbtm^zt@A~{(/6gO1g2xtZ:+g;A}7ǥ,z=˸M۰~VI8xGqɫt]03v0>fOkYQFn- : 7PhQI"$ !UA/%*E*fm5#V(?VkTMK#Hz73>99<R=-rЙ+ZǷIWGC oܜ~|h *-Pm9\3'-kbYntn 7֣!ǫ~yPtm\/_f:/s3qFO_gN^as9ʹ<Ssw;GnĹh"6cJ{<eon݃q1W-ÚC3yוǰl4;b TuMG?bOG*ֹT6laD %5S_=P;ɩ۸{n{@(A2dϯa8M�$LiݽA/wM?{ޥLrXem)%IEٱAjrUʎn&nA4))m7],T-"ɩ\9vQ :kcX2j,g]*O˶V ܱtѺR)9G堊 bc}g3.ҽ� y!dc$ 8%<F`=ˈݟ[|/ :A ^cAd1|̺hfTW DF[:Nv&ILp' gb _9̒n(#s1|Dx|R;X6n힧5sutbq2ьj ˒ŖCK;v wc%xH;+j+2s=kO_P^N#\w׹6,֗#3#!acixZ\Pp� g a_Kv J[WHFu#|Pn<'!(-*.Zd`*-̀ЛNx|Qp62/*$U<_Xh+c}#6WD_׳zcߛ5u!Qy㨯nL.$ [6jK<EvжAp(pi1+ԧy N1R@,sfQl;q[\QL 1$%(NKRv$}PP9T]h61ZfAEs3vsFRR*_u w"_T6s:&wh_mjj߫0�}C'2(_VmeŅM6Kg,wU^pKI *۶DsʄV^Y/mp"$Ɠ([S!%@OzV2OGo&] /FF8v/]7<Pc3n=Q9NLXvS){X*z,O'@E5 c7̯4j5T⯥ؗBZ>(w(s[t2 <gޮĠk#e^VoNَ ;V 6@Eh;t[0R)譡RʠP_d\+<\ ^C{l_RqPڿGYfaGU*@`;3mzt!acV¥i?֕ޏǨ]z᫠ ,/k¶W=�[Ξѐ8J*<YlMz{ SQՑm0 ;e۴D9e6//3tö$Ols(5\[0~l0՚صm<bFRh=MB<e[K5 {J:H$޻OVgS<huf*骇sN%Ϸ4Y W,).]}BcoKPP9n(-G3?h-SFEJƣEMĉ݆1S&N8U+ѺVEA2GײJ9jdW9={n5P?S3[ZBjdd$hoqDJۼ1gsCl= 8 hNНҙuߣYd$NtcLpo6/`E77Z|>5^5|O".͎*U}ב}9:V_;LhKTgqԲ0e~}PNs~H&(S_GXbbsR$,U*42Q|;s\̲JG7tM}m!dA##R1Yɶ&ݹۭZrn:R=8"xu\GJhf� "pzv 'I˄@Q>04g3lA;4ЫES>][W +VR(~=򅾋xmp_zNؕ'Tl6y]OeD5&͢׋X^KnQ8,к( nlY~)a]!OiT|ϋcĜj4Bwo˒_&q;yt&vB QtTJ7wJ?+\ XD%Sޒ0MST+0� )(%ɩtVL(]JAbֱA[ 5{]$wX9+T24�& 6c&;a´,-zd Vbg(f|.]0Mz~ĹegwqQLTGu6M2s3!,#K60y;yБQkg-9/˿0j2~ʗ}*dYAOzI21o*JKNisS 5߭7qwXW'*@8Xl6nteQؼ$S6q=: "G_uOѫg  g*[DgΙ"j�@eI{gt==^$+W*>],(M,ͣ|#}m XUKhV~1ӿ$\B@$޼GEI\I;{n ksӐ٨I܇̍\- HM*K(%_ţ&D;?G̊x&J:Nƪ< 1)N32\Îe|9^dסTdZPNq}S{_8Ǹc.\OOJ[/ōyYʻÕf] (B`u&e2VОG{ iE!9v1=}a5'*Tc{ k.H!Y:Q>5$`e]ї];tyxH wS99^^x=牛y: YP-k�ՅӜSW཮MM9�ʕҿZ/6=z �a1 ANg`9搚#kU=wؼ0vD@hde7n?ѿ iۆ.'sdwi)_C@K8] ە"'sl"J.M&հ0Tnm:{>A<?b`~ϼ_2 k kl\ >&&"N!@;}TH?xb/F'%v1oT$>f">\pDE'' =o9rۜ1-y+aO@ MIBηJ9?ڋZ’zp'5i77{Y4n"vV6w}sf6@y�~nkʐW<_f.dtn5#"O7K-�"~}+ah pVm_,\ĥЬbIiƨ-XwPMY49y>e�v~/*C<@)Ol>i షڇ>k1˼=fnoӶV.DVu*;ͩ"ҷVS/o<YƦ6;L&7gF6|Vte Jd_\梴c%պ}N#Y.l;e҉'jYG'37)_y+beyP66̻J0 YXl" ҭB @6#<m Ic8;xWs*~XB9,'/PބG[`ul6} 'V3Fߵ`߮fBNɣGd9mMG2pݫE-2bO ټMpQt%+oL +z|)M,Oa|#m\qڒc-[3z?1Fܩk {V % PX;i' Gs g<\my8u^yh: s1ѫ^ n|VϟzC០?v-v-2pWy$R _28{ם1iJs"x eǹ Um'N Z-ϡosRb3g1Fgr2<uMrg[0.6,Re\:$@«?΂U +{f:;W"z"YNyx/jڒ]?=lpQn?>!S!yS,g3w$WaQCӽAΥN*r[PT&cos2jsG<*/2 "Eݎa♱t6C%PJh57fe 33|FLDeR\,}Sw,Ha Me۶˒Ȕ(Kpj?ZS@?ؑ4wBԫV 7i;FTWK9=Z#x<YAu ȎM<WOeTL] 7\Ka} )O:zg)~za((agr*F_F|1%b r ,;&eh/MA*QGR/W=&Ѿ6toƐpw̪Ua/]/?{ZDKpU,|q+H#1d3\ȏ (Nn@Lr/\ >!mq'jZ̯-$˺N Gsz`wtzb*þ0a@ xCya @"ˤKY]?ɍ\n@ 8 o"+l)?\PАO'|Fgb@ +8V @ A*@ X@  G,@ @#@ @ x@ @ @ @ p@ @ o8bq@ @ 78 9Ǽ/.lx-_/䤑@  932gcs_/@,$wk79Fu>OyĤKS,)m&!YVNl:Oᇊ$v)9[OZ1@[8cɸ)ѮimH/VsU1.1@7r2Dz"رʥ4ab/ 1Z^8�;[y't^pF9Md@ז4iP вk?,˭RU)lAî38Ϭhg}df аnԩCx4m!&Ğkϡo6}i7[ pdRLux_oI{i+(gi[L%qZSlU geP(-qqv2I|?;wtyoOڰٶ;_[߂xE1Z9L~krҥ~S&EF r"'L[8> Ϸ93iPed*HseϦ{pZ|wGLȱe#D4lFAsyAmLxʡ5#PrmߧQ>Kt6hu*p`܊>m�� �IDATK2IeOV+i@نܰR%rjǒ30{:1r33'\K =%Lw+RnͷI#)veh3 @&=4 \c#"s2w5+#i+9b+@ x wXƖt6iK3{c>'^*:8 džoͷ}ñSxcjulp*aTrsBF )tVd]ysqe7def^}~]1(2j+ y ~ɐW(ĮEsČyP"�Grk?*Sr莯[ʩ} ( ^I/ffڹK;Vnq^x?)?˄ť,[pTi+E)46Oئz'աgA�v2꽑$YH}vv]$5{~|X53gpaS43~PںtfbyWk }9 ]AQ8QϛD/;lT '\ځf܌oݶePh8sjdaUw;[=O [峉Y32eӬg?::abd_d,Кi-2\kx8!~"2߆O6ao.iWMߕi(2mל'o|Q-ǀI&;f:JOȠz9$N橾v7^&TqqZM\Q}hg;E$2ɧ:ATm7 莚sRw)Dt k` #SC_drgW$.­'x3L'3+)c%qs"bŢ1,!ԋ>[T@]pA2d> Fz4xUpsX˵(lP1 j9&ŢdBI_JՀ܊׎>Bu_eN|c&Ik)ASϐ dɳ҄cĹ\5w3yF{&bc?>|_Wò%P5S̊=aSL nŌ42X%tWg-[g >1MNE,s}I!|~ cl aLO8Y^>-ƶ�q%¾Kۢ r*WkCa♴vWSIJ@uC:w,]1#rPE1^RX<ŒUZTKP eČ-y>rgqj  >pf]4z Z+냆ĄD$V'̡&_PPa}X7M# *׬ŖCK;v w"Mmf t`'H >(k(עN<}Y_.~w{"lJAԊoG=і~ASz9KGpݵ_ڈSIJtX_nϰHѧ;L|4Zx@² n uAM _2KELPں4(ٷ%3 d2Kf$ka([7䓐XPM-2^0@H]c-Ȑz{jT,2JÓ8ՈdgBʙ ̍{3;$» 6$;oo0zV0PX4= 3)ۨ&�DM]HTpk0 #n–y}wLT=ܿxT%y1NCQ& \ZLb $ibb�9tWQ]`>]JӸ m&3f_\3hsfnHJJt⫮N_8>rbޢb5 +BmK4wLhU28f'Mb<5BQ _gU+#;z4KfկiTi$ތcQx)E>8Cֳ"$�;7.튧.S|U*XF&N(>jN7io|_<HLGD5Y{Gp!yv Ffd$&&mHmBƳ[t*B}c'q};2m_"m0 On.f]s^qG}Y-}8I^{l_RqPڿGYfaǾRFULj'wfDLYC¤ѝ-of~0SR4Z7Ml])xIۥ׮xՂ?`Y]] x詗"mu\?k֝_4 G]0UA3~?O P=,T@9I'a򵇜SBuȭ`/vmf7oG$Ols0$k$bjZ^i;'4a`ӄx˶Z {J:H$޻O68Zu 9tWBJQy G22 oq@aK@Z˔QlhQS2qza kFÍ-k/1]=w �hdd$㈚Jycx zaqDМ;93GH"(*ǘl_ nnS |j/%!j\?:*Q>E\U<6lRoLx[},2:- f>Sn<R”5@NASk,jҾE>Yהc?d:g]&,mM"B-s[1tzϓo v>Wr=ANd{uhW͵?Xf`p!y 'gǽp"fE)Ӝ̀wCm*Xh|eWtPr+-2vՙxmpn\[ Rqs_,19q) *Jtl\=,{zu$5m`TF[h,yo ʐD4Ńd!ᝯJ[G#d)xRD9XPqhz;فi/NKgϷ , / k+ypF`--+*n9UXGjtE>nPE2p'IHH%C alcF6dei1.#[Xz3?[G10t+9R`sP(8>l-ke( <Ys3!,#K60y;y#VnV-Ss ~vKi?* dJXAJ22滵f;;n|D~H;]2,ae}u=/@Mƍθ̿=dʆ?ѴVIPWw+NeWJDgΙ"j�@kL~Fc%@r/"y1ϻXpF _FVOO%L=k ?M\ʩo#'HE Vg̢/ ׶P(ЉdY~(W:[ɯ'Z2 DC{[=767F}tM>d8JIWhI >Q Ǣ!-g() 8rz oZNӠԃ:,YU*) ;oj_y⼂hn`y3B‚1Q`u&e2VpҊji% \Csbzrmjv\aAl1=5[,(W ً_v^e0q2.<c΁> i[y*/P G<qs0/R_iRR Ү7";-*� KK ԔG7ZU]86o>̾)Q.AV2["_(go jwr'Dmh|'(wI,\EgH-g7m&N6t9/ PNFHXCjJpšە"'sl"J.M&հ0Tnm:{>1y=d.机umJ oP7X8aQ}#C=Gd^I\,ȏ$!Mv6;}TH?xb/F'%v1oT$&~# \]p)Y<WHXS90@+ytB3o {yzp'5i77{Y4n"vV6q^E2N,>W0[$Tp�Gaa^\l>ܰUdp[Ԫ˂ U,24w%Qss)ゕ>'G %Z}Ƞ" ->46Z'v4cm>&߂[{cnjC#6-Tmڶ1|cօȪXe'p9[QvʢI'5,,,r_*ЪQih]3gIXXY@j Ь[Y6V zz-lylަe|8(Y{ܷ ~eœlt{lOv_,G|Iן6#<m Ɏ8;xWs*~XB9,'/PބG[Cuѫ{&e+oE쟱,&4ۦy7$U+ݴoWy3!'_#i2xpƦ#|8UrFH}Zg1'9_1ˎ7,cOj식i&Wݨ$aog?kE7ZD5%:VFQɱ}}ƭ=ӟo?qB)xӷb ֿt-]P)(l)[%o{$@agS+%LlpÔJhȆ9ӘՇHDZH>]ċɍhr/E|KN˔OWR;}׾28{ם1[aj+6p&^Cnq^E4ܺr, _J^ɡϞM@Rn]$$KlKrꔳ� 6#`: VMdȂlLqJs\dIV8JὨ],s3.2iA'1r6sWOb|Uh8t:\)zLe<6Q?'6wģR+"p*r_UHMܷ� |4v0HRernyQޤ-,Rmh\B�Tmpm4× (M#Wِe߹&bP¾w-_!I#'g^Rw;EP]7cz{4OSYy5SMw3'JG1!v�2͝j(BJNKjA7McW CA ;;W1*$%N6-igX[dh=KOc ``~U v ό.l/RBI 32z>V&2)C Tw6Jf |ǬZnR#rv6jWw-O)*`$3ϣlkP31W,^9 ,a&唓H@ h.SÜ^(h,7 F 7q'@ xCˤKY]?ɍ\%f@ Xo+l)?\PАO'|F -ߍ@ 4ı@ @ pĎZ@ @ p@ @ o8bq@ @ 78 @ X@  G,@ @#@ @ x@ @ @z"'oEŚ}Gv© %4ŕ@  932g⵱ l@ xd;5<-Fu>Oy^9cWd w)}ؔ6,n*0448nN{}L8pA/IhӡIqZ6MvMPnCCHPxde/fQYb@E #U2΁~&r ^8 2?Z kS:U+)W?p}Ұ/uq0J?Ja|w+R^zHse5_df ؔj=ZvjϭDo۬۞T?WմI8KGaE)OO<Kb* \D2]f֖zS Y~9ÍSdMW;:=VN9OFET),P*@ˡGt(xG ˌ0eL"Lɩm6Lajm)|jҠ4 p,77kA?3)SVL{<C6s ǯaHT2ȉu1?m_ A @*# +j6Yy1ǘͣo9 zIV͊f3vBkW߼r';n:GroM(%֣6/|q@N_Nso%:{{Pq\)N^FSK@NaǗIMTNɬGbh&mu4? Ȃ8B#зVD\Xrf/@g?Fwfk v$[mz8hHq+c?nj_xQ8oS4̭?0q[i>E%% mNx9r6\` wXƖt6iKJ6~vMbiQ"` @WNC %ףg1hs>s͵a[mp$:{>ǸJX4\Dۘ#|WU:F~J+Okf9 Ӹpl2l>! p'rHZx䶣šsnMeYŸbۋ(&F}ɼ[m*^f|3$1=h^cV$v2DB)p^- ^I/ffڹKѿpq$b[)Gٗ&+,ܧliv΂w:c3in%S?M`h5eqf`V~n<vv2꽑$YH}vv]$5{~|X53gpaS43~PںtPJһ*o][1g@M rN&N*ٸ_RΊ}p jq3j>uwۖAIeު]WU܋n<17DnM<&fؗNꄉe~=07(wgK',Q(B޳*�{m=n&i_rw/_TԠ>e~ڗ98'yѪ8~8nF\刨Ƈc?1sC<LR_?2D�PsnQW.ʩJ}~"#pjD>#Ds7?O=Ge D;w,:ǵId`OuՃnPѰ<x-\;7zHz�%[|>8d2 D2vw̬<IW}JxDEcXPi C, }hkdllC9z'LGInDB؅ 77e\¦ #yFxϨnY,xKI&] hϭ۸^ ł(ASϐ dɳ҄cĹ\l99Jk[f1c5M #$f,_aKquH3b�W++wbu|F(S~ KYt.o_Ɩir*6.bdJ: k;$g� `ZwoE}zl.d3݈p-so&N)M2W.B͎1+ZpUr7e;%j{q%¾KۢMT;u(J1,53i@syeہLyE�� �IDATuXh!9G堊 bc}g3.ҽ� y!dc$ 8%<F`=ˈݟ[|/ :A ^cAd1|̺hfTW7 SP:Ei\;ySǞ@s]}E|=Vg$lJAԊoG=і~AOUδ }ڹr,>LtEa@?2M|4Zx@²dbhG/\K)u8E1ibE 0 z$rv\=G,K dH=cnP,@II¾LR$( Agb _9̒ndM`T77 eƃ|R"ۢBE  ! l#CHըTYd=%|o5f8ٙrfs'1ş:L:Gb:n gwGN)t<5 l8IF4'jBKJ Q6Ar ',XI}[i)a9Iٷ1KhBktys٢`l <_Ɩ.H%i܅6i3/eT49o7g$%B:Ur'҅muMj?Њh_mjjs(C~z}^5+q/'K{4 +BmK4wLhU28f'Mb<5BQ _gU+#;z4KfկiTi$ތcQx)E>8Cֳ"$�;7.튧.S|U*XF&N(>jN7io|$,kѠv`4h뒺أ8^6zZ@5!MG {4k-yњn-rfU՝|z#zbN9ooKL}i߿;-fҘ\=Xѭ)ҊW@/F葹{ jT}rg-]OTΔ5$L1etH˭lOKSw힞غR񱂴]렅gޮd ?˚jCO47id4"m0 O/[w~y0 /Ցm0 ;B[t2 <r6VoNَ !>HصVX;CG?lKCm@'=h1t3 ک(hX;\ai6QYR&]޹% @*,g *_I22*SFo9uf*骇s[%%,݇"' v-*vOI67–֣)~%ѢdDn)Go[Y*k^#xt-뮔i/&+Lڽrt86Z ([jdd$<N1Yt7~nvp<!GC:s{4$"Љ| ͆ű;Fˡ:<§RPSĥQc&fiΤr>-3`<j#,LL$wCW>0΃SnMIh\GJhf� "pzv 'I##P9Ҟs\�bɢR|WliQEfSh=Rz; ([PCϘ)۫oLנA:X[mѣ:)_ [‹DY= g]yB/휸|K MLT:6hb=U=:XT66 t AtL3n_<oKo |?TY,oN<c:f`doۼ �E];1M`jm&Qg_NcĜ.*_>9AزR-C1/訔oxc<VPAt!<$L8Ubg5uXePЂV돦3˜Uptí=.Y$$0Q@vr3dSei1.#[Xz3?[G10tHi+&-C=#b8iҷU!8&t柛meY΀Ytۙ$.(M W7|q*%4~+ϘE_^$9q{#6#ɔ \iGOF#$!mG]P=2_XRv5JGHMߧ",^G dY?Fߘupz7:XDE5%B=sΌiU,K5&?0"YPɯ<b_5|Y ?>p2Mf7q)fa}#}mXɲeJQ֯2!)t귒_Od@ěH(CUN32\ÎyeF>+w$=R6LԷ`d̼晕SI@I|Xָ=eʟ[Na֑ŵb`9^dסTdZPNq}SR w؅ iIT]I?vy=Dž$K<<PRpmf7 a]gRv-cՙ (ptVTK+YҌcӗkV;QMu>>fǰq҉r}Nog%Qw?|,8~L"?ءs]=ZVm)?ŐTfAQG0xhlc׋8V@l'p"=7!ݴ8mg5sx=̱0ԔB;&@`E#9/ PNn|a􎹆ꐖpz0خ9cKWri4rkEƎ;9$rp:x=z|P]89uڔޔ \)oq}GU ݙLdHjY eu׮ʢZV]A\&) *MV@1iL&t~>as9ss)x&WGSy}+X4`nl{y =P{!K ,x[=GsmqMS!e'vFn%X]^փs1[=~EVv5x%a¿f$͜wqn-u̮gbm@nt5̭[{dq[|DJXt6 \ѯ:=^ur!kdFzw1%P]3Q 8A,ow39C/AC߱fĶ-Tss0- %vĔ1[ydi:N`HqϬy{`^v9ƵEB=ϙ-Hi#I{/t9Gq"#{$ОˉS&̦Y4~)x3sub]toMɌkje9t'z8;g`[\=|hȢl22wU!|Q4_]DxY[2k^%YO<eoiy *Z=A3؀;Z ZFCb-XFʤմv6w%rߘȣK)ݝ5 Z'b>+|Ԏ>ÓӷAӼVPScy}V]bm/ ɴQrf/}2BIُԤ0g,ۥב0=lXWs%G8v:c{c ʴ#1Y}qo\ϲ}9H[vt 0l<>.k55ѻX-<o***sz_^*qu5k5˨X*1c:3i\{֑mAa^;˥HY7gƢ|ʕ�B#ڿm@Mt+OÈNUC|,7OQ܋;A@;͓֦GI㍅ O}wbN[bSޱܪ'L{v.dZn6_k%8L2#/#uMah9ɤ/aU[lmt ɷrEWrYz6}?Lu}-ܛqWg}=|1dѳ8vz4w"D=9�+'kщ._x?7N3Qt?ka| BGٌ4y4 @hTKu_ÐK)|mr?]~!o7y":,w|ՎtI7Syx|M!v?aѴAL #&հwxg;<l ,1)vjw#qW/9 b}ɧYh}ۘqzeӳS}�yG|"N攣mA۸wKOfW 1mR59Ve/QT9s툏44if !BPOI#B\.NQ!B!B4t!B!9V B!B\dB!Bq!B!"'B!B!Eΰ;2!B!7ɂB!B!EL!B!9B!B!.r$VUMkYWPi捷kFT͍sU!B!>_c٦Ğ;ٶmyyX)//pdڸVcNr8(NCӡ( DDD` 3c2|>iXV ʢMPUC7.μ})GsG!B!ą2';;ۧXc1 (l޼#dʴڭ\7bOPY1gOFii)ٜ:uPk#KDDUM r1Y[}B!B\4M#s,[oLrrRc$&&h`0T h,Gyi&T(hl6M 44c@iZhA,CSJ8I9MB!B i呕X[A{}DFFJHHH@5*<FQ ڵ#+;Pо}{tm5k}B!B\%u{fef6s())%''0+4lEQhAFFzUUݦ5 c�4!B!9aX-{:uy.֪ z<Z}bֽcB5Sv;z t=v}×!B!|vhZߦ8&,U]an?'NQp8uΧs=UU1U4a◛Agoz �К(EWp79=g}B!89,G=aŴ{ydNsf%.~:^s*>fޜz;JO %X;p8I,=veܦ u:K@܂GҨfJPc8wc:Jgo3!ukÐrl6AAAn_fy*6͹Undkrrsb0+1x#B!Dse~{sss2;Y?}U_p6& :`7#q~hEXQxysl3/Ovj#<D?C6~M;*m_[1,qEchΞ  {<G`;Qw)/r/+MB|f2hL>0c7en0 db *IUY+uv+w!0Е{#( c9~9ꜰ8o[+xgfΚEyy9SWRSSt8UUpP+q�Xt)Z rssYG(:a4>B!B4V΍HNBtXke҈ ٻx*^Ƭo7퀾^AtE]Rʔ?�VU2�v+t+CceKyE1l~O}Ĝ7Xq.Azu_Ȟ僚sRMƲ@U@ϕ;m^+\]{z�N'8sk5u/xh+EF}Ԫ"}B ip={0klJJJ�9k׀[`m7m3о?ӦM㫯9MsG!B ~d#e)^Py? 9fL_f VeCh;~hre,۰vR?c۬q̜B!) vƦFUQՊ8Ň|a;2QDhM1T3J}QqԝkW?[\D fiU;r TsGҷ21Ϊ}yZ)SÐٺ]3(Lb}$ k8~yݗ6q`xsqLx'2W_*V<+� u&^Ec,|GTB[veMw0mCĄ9וW\/?dنm<k`߄Ǹ Js]Ҿ˩Bd9DR}ht-ͥinc.o ܭP"əYI~ 'G$o^:<ipN9k25[0H[s܊۵7<|G!BSz ^8Yn�J~^ Jt QCē}JDłfvË6z"Md\LJo K΃hdGfH#j6~7b ks%fȥӈ[x4%C>]þS%hf4Fh/!F<SGIB1߲iO9 v\Q_G:_~?`{fzͤ# [.~-2uSJG5U�K$ 6͜&0wĩEI O2k[w͉el湮Xʱs#&HG d$45YƾyK7-m)>5�Jx2m#}4n wԊe)++=d~m:uNWӯx5GÜ9sÆLZZvYg3F@yɫƉjn64oH9B!M(>۹5!jyh$t}b /%r3<02 ?5_qhZU$5F{ @Jb9}2쿬[5O�[MkH.lV9h�զ#|5%vѝ3 hU=s.U| l_T2]S:b#my\џHR(=;@Ȗ=M<6lղ:,κNnn\smk*<I>e*_NJe\'ok5*Cdt?crOlG\g_gVζM'ǷT^" l*wepk_c7Tٻ%6lwuWebVn3"rS1SVr4>B!B{Ϭi5q*wtfd,|qC8~#0GB9:@SfW:GˠF]E nAL((DÌz0%tꞌB+jRn3Asd;/\;x Rnur_JYҪ,pB"fŔhx&M gqƙX#T*y(C|lZX*K|F<GM)-0!tܪNDy()b=_FL&Y}NC,UȁxZ"݇#%B !I�� IDATx\`z޽y@zPΪ4ƍCV S2j5GT6j=yyy̜5#GlR-#B!Ĺ얹xmz?o~!'Ϣbç,|~=_ 7'ATćnz nt4�UEUt轍kR #Fs1%PL'_έwe.RSo!>B|b{RJ'l<0R01RsqA[P<µMPPt`wԓ]AX`-kYfvl|@7{go9zʟ US<aok"rHפr 24e],{ĉ.,\�pNaw[Z5-( 8Uk�8"g$)1cA`z90tPHW7v,h+Vn3o<b.1OC4, ߿5$ 11UU9x �>u!Bq.Y}BiJ+9??ԴqcŴ:=sgZ!|b! 5ppi[y~5#ZLTYk`r/NkG-](as4eZPR\zhL(!rPS#|iKfvXנּ-^dc$O%F<Օ_'`*`'uvVokRHku)kvGxmG5jŲy[omK,;u2t!>^�{vصUf;CHeA@U]۶{7C Ή=cǎEV\IhTMsnix[@UUZ zWf~�,^LAAӟ �=-5v'0`O>B!BZ.[V~1!SǎUՊ]|A|BZ壙" S kskA718H֏kYÏ^&A:W{1G^O6}EP9k9\ѦmkX}t z-6S݆gN_ʄU1$"2PGiA6\ҮQE^Yyk`p0#d;ѴIg< K*ïO \եNjU=ҖI>zjg#\b]`50tFcr+%{zqu^UF1S<:ri&  ^֍fH/ޭkR;@z�Ύ(w;s}\UYKXup})LGvb{`:=Jq yUd?S\\bqyޝcn:**u@hhis#h[rs*wp GyLs#B!98t+ւ̘ ~}h.^R}֑wm7(�@xBgF=p یz,l>rt{`eo)t13.fylWOǠ.ѳ7IKױmMQxr~36$ q#{{b9Y*~!Ѵ<㮣燎@BoϜ4;zP"Zu5ϤN?үK$oԐe}7֕0n{b֖ wii7n* ^JKxmM F<$~5iYa9o|RM9*nꭃFm u=-k(XV;pۼR]UY;VW 2k9[l!>>�oBOGuGX 7<vZA3$sU6ámvR{3ng\z%tΞoŒ8M֭>B!B\JՇav^i|T-NjS)u}W<>/%2ιx ~䵣puvcY_Ԏ={tm2Ac4]>Vdv@S&=МA\|Z^\䱞|͡<ē$$$p1r>#B!ECjOr(C{`٩JA PPx-~Ēdn؎Dh_!gXڇq4!lsĞדGUzw*pU?{;=5c۝޲RL3c ӧ\NEQ_}B!XhedokALlr*MGƅC9@7~neO+ T CcYoƞWaaaUunTEQ@Q8hDy.(dee<VӪnsY##B!EC iߜ?&3ˋDQD71GY*b gOUUq6+ ^ .ﰦilOAAlU kN t~C|*zzξ}zt:/6g*oԉ?G!B!ąOUZ|(Wzz}ԉ=]FJHpɜ8q@EiC_7x۴ \|!//L2N&.6pr(?qqlsbcblCӡӘ*!B!)d">aϱn[Ae! ?lvgϞ%;;bl6jGEQWXˆ%6& vS4 AQQJII)V+>9#B!W7-j-z=∉i19P79,{".m*Y\\c* ^sjCCTvjT6B!Bqkj,kqMSW~~~$_o$B!B|Ų1 !B!9B!B!.rkc=����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/exfalso.png�������������������������������������������������������������0000664�0001750�0001750�00000160760�14035600052�016556� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR�� �����c���sBIT|d���tEXtSoftware�gnome-screenshot>��IDATxxUUG6c׮3^^AAʠ82& t҂P!I�I $7 F$ޕ9'<k9{W;]5'OaC׭[dPABQEQEQUKSmڴiٹsmذ!ҀB!BH}azGqqTVVREQEQE՛.]$'îJX9EQEQE59n:w֭ xPEQEQE5֯_Rʠ(((".\(((jP{ЀPEQEQոEQEQEQ *((߀TTTPEQEQE5h@(((j|R^^NQEQEQՠ(E 6yƐr`?`tJ_0Nm]5n3f9(j(>ĔSʋ|_cCʑ#GOˈˉd==;'GVo"_Xj\Ϧ)vnn(h@(jq$TjCX\oꍴܼ<9`rLeeޓ=pnk~Kye4?/z$ضvn㞋4Cpm)�.,*oΒ_6o}22hd=D ѓ 5R9�nէT϶K]o{pBun׷%Ve3AQTβ.ǐST1wWgRZZJQ쥵5>âc'C7IaSL>ްYoΕz|;cIψ1{~w. FgG_`'95MFL!~>T͚'3jC&LQQt*+ʄ>[z οa`гѠ&Tr üD=.=f4ueI(_l2wJ;r|d(-;Tm]zu_e})@`-U=<0g V-pUF<Jie$m+gZiឍV9LPr,ŷj5|4 EX7&'[AJ$Cp!JY95ʯ&Ny~2%'$ҏ'q'UoBy"K֬3Tf9_P  shgѪ2ԆDF@y_Rg.Yۭ+Ks(PRWoRf. 5Lu[g[XyT<X`nb7]6J#y-ȑ{O3Ulo-%(<R ~&(jDJĔTe:?_^Tl@CQ՜eTc{ҵRb5Lf>8F:dZa31BT>'Ҵ�ph>eRNm(@PxyO8hUjI8Ǫ[#T,c\Wd\0?(CinR=ۺ/l09Z3,\8% c �eX~^нž_~Lk^PO>ELi9ֶKvh@(jA2chy`gRmb@,Ky`3/@ l̔VZ˹s2kP4 p U(i mkbe-ճbn,a@2 C90 Dx9rdx>3I*-`}&(r -JCb{W#~ـSE5Kah$al?><1Q-ޣe*O9n+T!mXn&MWf"%Mjm{U2tT=ô˯i*eO꬜3x5մ<ᰴm-ճR[YDE`'̙%8r-\ٻW)iUôfdν>P3\Ɲ^?E5̃P+U|=^c_mGBQT`a~[vyKc kJ;T306߇I裦'c1ۧNSgL&9ˋs 1X i]6ϝo0U?k76¢b,~?OWeiZsҶT϶K}~ʴ{2 ' @/ħ_}#.PC_{ ijNI`hogU@3~\ EQ/sBTYpx Tg[(,jq~-X}΍y�8c,іlҶZG0?wi srX~K4~o[nKlV֮I[XqЖߙ{4mdJKku3AQ՜DBQEQEQTB(( EQEQEQo@ (((T4 EQEQE5ϧ(((jPрPEQEQ$//(((AEBQEQEQT\(( EQEQEQo@rrr(((TYz5EQ-HΝ((jtr((BBQEQ !M((EB _СCEQEQNK%W @AB D@@JPPEQEQTF5 .S13  0(Z  36 10 !ˀ)QQQEQEQ /g8m@BH6 h>0bbbbcc)(K @|8 ȥK$&7le+uц7~k稬�Yj͞cdæͲ\w}΀ C@uY*U^Ѐ0 &EKEtt((O @|8 Hl Pa)P0!f11Bc{T 6&l=Z>~׫I)r9sxЀ0 z?7g|a9((r󓅋\տH@6^6=.*.VEEj-1>f}y 6 oT%%%&eFϊ۲,EE: q€h9 ~Xn ~SEQ% 0.&qE 50 V 6[;+-t,_al%Y^].'9%'i@bn>m_ZPĺjz@k i0YjUq1Ζŋ)_~'i b|F3agQ?(TVWK߶qa4h@^[P~\&k~]'GBBZ2 HMݷ& HXx>h>G9 a-޷_r*5UM(W]{ AUY_D H`>j{a/` |s 0.>On߮ HӾW{My`A>z/^*P0{`<t*X'N&-[jV.լԩTٶs*ufVOBRGL5fZ[0ޮMo0_{^k 15zxھco7gj`xڭ"/rs77BV[^O\eej1FZxQ]+d԰]wϛqVbXRP.=pBm;ZgP#( :?XTs}6>n^Ybgfϛ{b6Ϟ9k(/7gRkBi2u*~Hh2#1^&N"^ԽPv>}欪}Ǩ5G|3yھQmvZ [3�Gm R?խvT6^n[-]}@_>\qI絻*�B�y b) m2 z-{uf}Fu m*>u{^xР=NG﹣Ϟ#eo{:ܜM !^ HPpp1yNjСCj1 povvW5ZV x`drOy;aL wz /<h~(PjpTg HxiyQw|>> ڽV?3 +Vغ>{8/_& 4 yV*C6 ;vOGZn`ixLzS3eÌv՚5cua< E;GO2.VC:hV]z@ϷRDhݖԘH93B,<h7v- rvl{:LB,= m}Om5|V`~͏z@p/hte�VOdqp h?UcxUuBlD3AA-W0 Kr8RWb3t:l !Ҿ{n֛==Hۀ8/s!-j0怠~~jULlݦXzOP|;~*9 }?RvxxhEZN3�  F*т X0 i@vzzs@eaHCG &N||L s /4tę{=wvۑշq=_$tB H _|`-qQmBj &ҫ[}OGVuקj,^^ )hU*Xb~5L 5ZPӀ0C>ڵ*X i@3 uGޟ &NcU}}|d?e&:9rOy앭!V/s^B H !"%{YMWPXAQT!œZʀX3!OװH@a5 !0 Ǝc41mܴYJ4%H Y7E55aS?(S'wpJȃ4k&0QVvVjߩR/ [1|1jNƺ(տ|5 X\q<]5>l`<0= EQuu,K{@!b@((h@!4 EQEрBh@((!Ѐ((BH>0˄7?j4EQT4 Bh@,~@i 1�Y(W'W @AR *s2.wGJJJ=~]usե-r�EQx)//UXX !!ln{j.ܹ$%%5h|%Ȯ]ߖoQx۷dgg.]QF.wq|jzWs43!BiHh@j+TrsuIIIobǙ0 YYY2zhy7];#^^^RTT?\:v K,_~Y//_u453@B!e% @-K~p, 3<裪5^Sw4*++eԩc>}HqqnAAr-&͓zH\+4***drwٳg[A/B?v֬Y*=77Wne4Ο?/s Jaaz믿 ^jժ[� !Bh@Z�nc>u.mx,$7 'G%C"}HZ#[]vde,&Ol(H6mT+>޽{ˈ# p!K.r}߄ m۶Ժuk8q>i$~i=ݚ?~tAj׮>x`>}~={Lz-¶m7ԷaFNffao,X@.^`3@B!^;4:i*菜 >mLn馛g}V?ogddr[&BtILSRRL<j ?6^[3 8ױcmGQ=�=%ׯ W=:kV]wD=:!!! 6 gB!4 -#{lx,p, 3}D8CƓx}ҭk<|>@=(3<#v-|}}8ps)-omB!Ѐ�~lsS+!o}14Qj�;5kW_�tiubaNK]!B ˰yHM?|퐴㑷ILǏٳ^ ȸqL`y[Z3 8xO[ok\\p.ԋ%0.`K19<dȐ+b@mӀB!*dn>gh|b  7p<ju} BpC ׽ks,0`~)S7y?æpmu -  o԰)S7n^xA9z`B!^9~s29 +(yMw?HB!Ѐ\%LүVBޖ VªNXm K>\Oϗ~Z "4 B!LLL)!d0oC0jYYB!4 ((!4i!aBixȬ_B!4 4 Bh@!4 4 K!B�K!BR,^L2 HSxV!Ѐ4 wlfhB;E]oc\4r_z5_~]l}yY|REEڇ4c *"ȴ kiMni 6ӀB HuRZZ"e $$$X-_͵{W@ؚ"P6>]w%;w d?Yj1 ;w?Ah6d~FEǨDs j_dtƱr% ܆U޷O!Ū+TrsuIIIobǑeeeeѣ7hPrg}VMހDFF=#;v0<Gʌ`;**YGU{Uk*Ucpyh޳`鵵އcTk?ɺ $&6Q -[AQYY)U[d-**Rupߴz_lc?gGz!aٸɂ?c{˒8$<qssG}TnFy$&&$:u<crwH>}ac@[n1I7o<Cr5ר}W_}ݧا3;SϞ=j}fR鹹rw+S�80`�eƌ[zJ?^>}Z]3g1Ct/ݻwW[[nʽo>y饗Խ=\|C\]]M-ZHz, Hn^ l5{OQ@j°hC *Al\!!5LNC#ix6.^( :W?7ӀuU'NV/8zsC!4 4 ۘOgm[*!?K:M<%>dć oH-.Gֈ*3k׮ɓUVziF Bֻwo1bCD1>һt`„ Ҷm[IKKSjݺL8QO4iJG�[3 Ǐ:Cڵ,ӧO׏ݳgtرViekcӤ!Cdɒ%U(,]T:tz /J~~*k~͛7>uja"SSSMaoh ӂĤdI2<xK*G |Vφ!܀sҥ[~]nҒ_XXHR@VyxRkXgK zKlݿ<7BB %˿?M3h)o#馛m /ZAFFjie@45SN`b6'COxmǹ\Y@>-=11Qy}zJ֯__aywm7(|Q15j]vY<?zKd?,\ 7`b4#S\ Ȯ=*C&Π+Vdמ=-C C=T njeC_S rrs#\RBh@h@#{lx,p, 3>뮻NkUikˀhA40�8(ǹX >@=(3<z)K{vZ}{͚5&)Z> -–z$ ~[/^Tz`0-DdmyyNO/}ٜ֫&6YS)N)ce~= ܵjիͿU#T=okFECSBh@h@F|(\J[_.g9#g{@bcckW_U?Z!ͼL̜9S 96zDT0)7hu[-~hqzb̴h4cbeʀhû M>7VRDz``zҀW}6=]0?Fp8P3˜LH08T=[^0 ̏sC!4 4 ˰yHM?|퐴㑷 G�&::qƙAO�rh`wp5si߾}Ī\o߿vEGM7/ӂ ns9sm Ҁqغu+LHwܽzR& Z5y_a6[?[U0 jGp$g hø̏?q2A6o*+~^yg! șgU=X[ካ`9V.\ПŶ3l!sC!4 4 œ}Z yˀ A C˶mՀUxȕ'{6WB>N;eM @Q0a׷~???ykĉj[[bɓ1 e|Թy]Y*7 a5,LdSX Hs /!R4 Bh@ 3u553tN<3uaV|d𫍫4 W>@=pPKJT/zC`@ӀB!LүVBޖ̰a^Xm K>\OO?u5qՄg}yF4 Bh@ S?(S'wpJȃ-[P% ߿ ^:Wki@ ~ !ЀBh@ ӀB!ЀЀ/!B d/!ۀ7?4 &)(j(Q !BBBQ !Bh@(GaQğ8&qGc$6Qʩd)*.=!Br4z1gΑ?&]~�Wc\i:x1)-++6sU;ϟ?!B|5mRZZ"e $0(Hf-X5e}@ SXvQOI j@U4cWK.IIIJaQK~AIvvJONI}{Mʖ- 11MC?XIc۶mҫW/IIIԨ|޽O{6!0`�eEB |CSV*ٺ So.RLD{kil ɑ3.nA? cDEG(󑒚\l$%'JbrL8JnI޽Kr fxtbgy`4i&yk<xL6MΣWz{9r#D.^X{9馛_hӛ:;w~>e޲d' ":c@7%9^&_I;._gIFy)*(qOד,>)e+MҗȔ r.?mWrQ O#*O }׏?KpKҋ]xB >^P$TzPir$Xχ2l(<u}ַ3.#m u.8[2 /Hqy8YgȨpe0^\ϑl2D-.R|͠;ݺuv1cᆱRϱ+ ofs嫯GJYY,ZH^|Eӛ:C{mx,$7 'G%C"}HZ# UäL ̖8�4"D#9V [r1>L,}x# A+Jd]PkPUҭ9\|C: K?vƠ> _STN282˥ߪd=v-^ v-՟qYo~6hC*Z? M݀DD)Wz<NJxBN&˱[$^ h]r1>͇ tPYY)SN{Lӧ󛫚PyUЮ!}r-rˏ?(ڵSX{[oU=5TWeРA?ʻ+*v.vm{niժjа5kʪq:|MO:%=zo]NUF[e>s|rwg;wVtz%P^;<<~{5\okn}m]τr 7(c{ Gi2:6Iv4͠j3uNO]f-:!.i2`u;:$#5Nl霐/-g/Y e\^c(Za ^gdsbs0dkWߖ}o~;o#b,gn@« z<s ʔL>'$U*$+79tOJZxh|uiF 3͕޽{ˈ#Ue6gsJff a�nF9{+ _~Yk'd֬Y.2zhi߾Jǹp0h0vC ٳ5/]T]/=@Z </a~̙39 7c Pie//*F�?j(1o<5ܪuث{<?]V>C]/fBdݗM?ecDcy2xK5*omFf00$>[ bX2kYU]k0jsSvԜ exv`ZԷs~ٽfumr| z= υj]GE:) Uoզf@L?~ܤu- ȑ#k[ڭ4}m'D ΅ Ƀ2A q:vXD; z�z_PTC@ݼB+3@ L0kmrJUVڤ[{_{aQo&M2?d{֮E H҄ϻe<[_A3X9b@9\h)9^&_oHq 6 =t,ؗ!KΩz@ڼV}~&f+5e En\s`T\6%'9VBÎ\5C=:kV/Q9;y1?ފ�S1qǙo?#ǐ Կo3a<hIoݺݡC2o %B #׆b>}b^Ke0} 7@c??jow%01)11tc,Wf< C]/z!4 MFw5sF#e_;$<[_d_!PdkS@|a9 %j.0y U` wZP5;)\՛Zxsd0?8,4u\IJJ3~$Wj.; #j3 @m {X seFc Z50楗^[?cYjz'-mr&3yd5LK5iiiVρaZ`0Z,sHi5Wwt7[Z{ Mڻ{ugYуqDl/osZf1}ߗg 9C o}|{N/^dC0Ei@0ĵUxV^ 특|rRQXE s3!2_ e^]VUu_c~U?(Yh$$4*XRC.eFT0w-YIg‘F3 - c`K?mVSQQ&7?%!5=ZaB0t??z+J@@@ז~mհ7<7ҿ5pϚޓ-[lm�`":?z:0_=!XN uϑTf̑A�L8s)0tIVXϓ5Iڐ*{X{_{a17sw`b70n}1K.g$iigɲ)_Ț_:%YGaMQ2Bs!-w@UHQ{Iyf)=#gwΔԸ`9}df6 8Q>`1c̭   h8so߾~7,4TMF]`^&kh֖5~mi0008߫*7nzyXx`, BkίzX/QzTz\\t???eD}xOz˳~z"zp^~s|AWBg/kk:= `�a$ad1bų~Z "Ѐ4)}6?jJ?<ےÆV²È>t;)s+'m@TX9wJ1ɏ(Iсr*55#H`Ұ'k׮R`,![7~ceB4w{g y%*`9a8Vꕮ�Fи/ӀH2d󺕲eE{Kʱ`IN:)钟'%RVݗ$(TҀB|L"p-G1e!4 EрDFEH`dJyyTVZ e{ !D=0:y1Cjh@tr 9`CkPmB(B!4 !e}PЀB!BB!B  !Bh@!΀Jcw4FbhJ"DB!0}TY-q̝;Z'_M\niݔ cR~&X^`>`P23<^LB HeO<. \5i5VkjwutY4A24 GtL!’b)*.¢)(̗\/̓,$yJ-[&bbDrB Hdzc ! FVV=ZxfeKre0`>RRՐ+DILN 'Tz|A-ɻwIRn0!WK�ҒW6B ¯=e~ ":ɣ>*7xkc[YY)SN{Lӧ;-b>o<y衇kQկw}Jx}2p@;Uٳ~"_|;k,)8r[Hy'T%ҽ{wU[oUufR>{mX}K/ʉ._Ȩpu?^\ϑl2D-.Ruv%)4QBh@IBvJ9MN_>$$?5Vr@9'iޒ!Q޿|vUU:ydiժ"mڴQ-v{-#Fp|Hҥ9sF7ai۶)nZ&NO4Icދǹ?^:tkNO<xL>]?vϞ=ұc:۪×_~Y{W^yE~GJKK%??__~_{cxټy2jN}X H^AHL:) P 9/nC{%(_bcWvyEqlhSssi%9f>m2Bh@Z suS%tB8*A9eoM7ݤo?rq};##C}1Մ/N:IBBIzJJI'm6Oes;vLF>-=11Qy% ~z1 pѢEңG=?WWWD` wo,?, .Fh$ڀ#;7ˠLɔsAr|\2K~C$(6J3̥|[= lk !Ѐ4f}N(AJ9 ":ekk뮻NkUiy$VƲ2}V/[kRh~|FgQ=#ZxdffBBBV{n{R] c?W5 ARB|Tĭ _gcanN-K{˶' e(C!4 ̀ۉ1 <[_A:Zn//Z}ق yW% @>z \G}$sQ$>c?RNNZٻn{ֽ@ !5 a!r|@~K2H-9ɱv =sj\{mO6k!~me߈&9$<[__W]GU㎣gϞj@ƍg2� h`8 `c}\ ڷo_=1ޒ7~Zx>[�-ouۻ7իW/ejp< ȃ>𽲷}PJRR[%|xVwIi0IUe6gN-ս6=d>-a !Ѐ0&i-[\1N yl160n^mV_h2d>[Ih {mNDN2EzC1&B fP> @=[<jK 'ZE1! Z VrKU#]2<fKVR#!f@SKu0-i)/ e!17}hSB >&ͨQX9AT ȑ)*x/)ϬZݪ􄏜9SRӒuڀF7{RЊѷ~lOKyi@(C!4 -q!Nl?)!d &bb'V>|0 e#U$%!V]#%)RtC#7JRtJMgHnn0#f@a !Ѐ4:~J-<ے 桵jM .iY$HKyJY2SҢ%X$'tY͓)+äK|X*i@Ue!4 &KRb0R^^& e{ a !B H^^2!tHWaM~tB!4 B!ЀЀBh@!BB!B !B!4 fj@ %1;#P\RN%KQqo"!Brؾc̝7D}źrqS.wK5Հ?&7>j,6sU;ϟM%Bh@/T?(TXX !!ln{j.ܹ$%%5hS/#sN_*_a@c"KQqHAaJ~adgg$۷Wܤl2ӤL. /!zcrsu"\Ǚ!e,=z 5@1괾EFF=#;v0<[ʌ`;**e0`>RRՐ+DILN 'Tz|A-ɻwIRn0!4 W7g!+²q_ K%c?qH8yי`M}Q^J:u<crwH>}/SrIyԯ^s5j_yy|Wr})5iTTT;Tg϶!_|;k,)8 ׷i:Ոݻk[[n9XѣƯ /ZHz HdT2ZG^~HN^fHD`IHÇH^o)[B!4 1: ڶTB<~puxJ|~A![$]x-KU^g]Jrr 'O,Z]\\M6j޽{ˈ#bz@χ.]ș3g}&LmJZZR֭eĉzITӧtkCPvc#;v@!Ԙ^xA|||Tϩ &(55dfo@""Ô+Q=I'%J<!'-zhKllJ.Oh0~ -siɀh{A)n5~ C|/۷o3fs=re@yٽ{Nثk{ `H~[.\P<򈺟sέu!Ѐ@\G4AMSy\GTocrM7ݤo?rq};##C}bׄ/N:IBBIzJJI'xBm|>6^[3 8ױcm3z>�zJ֯_ Vz8c@n&m7݀Wxdf)9}N27HT&{IVor萟Fw\f!2 ab cӶ_ye@"""S_z%9qCumqRqYoqcڴiC}"ajA!4 -#{lx,p, 3}:kVomصt} -++ӷ8�ǹX>@=(3<<{Am HciHH۪5S++i= ARB|Tĭ _?-s=66;b@rrrti  -cok{ `ב7z)cm #>mcj%䭯`A:Zۜbw6|צɫ*gK sDX6Նx?8sC Q"zt.W9D*S.tْ+aG̀8c.ږwĀzޚ| {״m6_zL?OյK 04Nػ58A!4 -aeJ~!i#o}W =:GGGۜ\2n89 0Cc1x؃� 2Ҿ}Uz-ٿ1 UuVJe3`|,&=l&8_Kb#@mD3y gVI2]wGRjY!g@K[= xmlnZi@l_>/_. ,Ps%k{ umg>!2gh7q3VB 1qq…C1y:X-vC WkV<me+cUoSL믿P~ g] R_u驂 \ZjqN䘈j`1Ƽ<%y HV|y`)!2#Gdx̖H3�GB̀3母 :^/9+9~Mt+?yU##umqc 3c>نBiY|?P9ԅX ~|>V5j+>(9T; E%U[;gJj\>sZ2U_(f\Z[ /4q_x1 9 شi!AO#umq9;vj`A0 Be'Y5_-a &{b՗ÇiXQ駟Ve#U$%!V]#%)RtC#7JRtJMgHnn0#f@H5.Bh@-S?(S'wpJȃ- 5@ Z)﯏&]O&-Ӏ)CqI6[) \fJZ 䤓n0yRZZ"eeX)JB!4 !%*eRYy0!XЀB!ЀԊ\eB鐮Ú%,<TM%B !B!4 4 B!ЀBh@!BB!B !¢B?qLH,mSRT\ěH!Ѐ*s2.wGmr.+ٔͥ:r< ~x`>`P23U<^7Bi.Q~@Saa˲KTv [SC뮻sΒԠA~c ]oʆ)HC%%RT\(ERP/_'Y*=9%I277)[L.B!4 ͓UW@UPg~s!Bg0 YYY2zhy7m0uJ0$*:B d5 f#)9Qd pPbwK]RtLHS7 4+7"X"//O>S;I&9k.yox@k0٬xBi,/YtloY2cy GU_VVVԩS;C#>r-ϛ7Oz!kԾrꫯSkӨ/{Ϟ=j}fR9 0Eϟ{Gm@Rf^_ҽ{wUztMzJ?^>}Z̙3jرc*Ȩpe0^\ϑl2D-.R|9 H32"ϤW^ԣG駟NwKKǎYBҴqsmK%g ^'ѾI\ćP?9-1E¼߲Tu&Xڵ$'' xҪU+=EڴiQ!ݻ1¡/t|Hҥ &H۶m%--Mu2qD=HG[3 Ǐ:Cڵ,ӧO׏ݳgOSk3/G^xA|||TO 2D,Y^/^XKCm$"2L㑘tRr2!^"JPFc3ݶ̥aiLhG&`2{rSXX!&^;4:i*菜 mLn馛g}Vo)׾hѲo ]N:IBBIzJJI'xBm<6^[3 8Z5OKOLLGyD|�_A H] F'uQF{К!$݀Wxdf)9}N27HT&{IVor萟FgmKkτ -݀dffxfovٶmb#‘=dx\6I<NtH8yי`>]wҵ^02}V5coexgT�gHƀԥNͯͼ5ڵ=CD100Kh!7fk@"Bu^xI[-9['E$ w/ {ۖL8ۘВ ȿ/O?<gDDDBh@6?PeJT/t[֪ɫ*jwC0uSgWv 999jYY5>wߕ3gaj�ֱh$,<D9й_%Ll>=fKNri4bt2֞ gZ LC0tw8]WKBh@>.ú#6CҎG ϟ=zTK={֫7nVˡ9"1±ւtxHk'j[+b@i}D[nU=B~9.X@n6;wڞ3g^pa0 +ȕ9Jr6`>V =rz@M=siigZ1Ug`V4!Ѐ\M eL\E@7p<j<s}bR ^j+[{ﵹ  0@?vʔ)rכʏVI\ە0 6cOOOt1i|'N(O<" HHhU v\ʌ2a1["U  n4bt3X gZ*4`h"=&c !&Aee͌/!A]X ~Ma\L&AT ȑ)*x/)ϬZݪ􄏜9SRӒuڀF7{۞D�IuiLhja`ʕoVC1Ùtk?T9WBh@,ӿ$%3l0 Vª?ÇӰbO?ZI6 G HJBٻFJR蘇Gn@9"gϞܪaNG̀B!љyG2=ܿSBm` Xje'MxmB %ټn,p)iޒr,XNJFFIiiaK|X*i@!B HmHO2hX,K!B HU&p` 8_CՏB!BB!B !B !K8h@!$ !|PЀB!d(娩¢B?qLH,mSRT#Bzb)(e)ǤTGMÃyj"'Bh@(qHC%%RT\(ERP/_'Y*=9%I277)[L.\]JS-mۤW^Vӓqҽ{wӟ$sOmBaˊ b@#HIMVC`6%19AN&P%{$%EJ\ j3#M0<hf[=fӦM?x`6mGX+w9rH 4xby䦛n_]NoܹSLjZ WCϕ˖,I,rI-e˗3oe֭,s/nj#}]=zm_ .\ 7|6@[+9zɢE_t8,?<#JBh@(j)$"2L㑘tRr2!^"JPF [QQ!;S>={}K/$7x<&A5 &#<"~̝;nnn*kc4̒i0/ԩSy~پ}̘1C;k,{UA5jTVVs=crwH>}$yT5Թ~D?G###C>#[Ү];J#z:XJq=wߕT_;Ώ끀<v޽[ZjZ14l͚5zy9j\7h7|S"""SNI==}Bm̙3駟w߭uYM~d@yQpQTT?okn}m]τr 7(c{ GiU(`5^m@㑝ePddJV9 9>R%YQɡC~pPCvҤIҶm[9}I֭:7or@WO0!F +Æ 39G׮]U`*8rƀ$Ȋ+T@H+brv=^,H6m԰(w2b]t1 ne6gU-33S0�0fgϞ z_o7eU}=Zڷoq.\̓�.2 .ֳgO׍k^t^̪K9srYkeľBc /@QlL([6ڻ{u{ڵ�}Y^9! !e}P4Yz(%Kj]GE:) Uo'8}A5g…zk1O=I@QRRZh1 h̷k|=5?~ܤ7= SRR~#G<xPoFk#4ͷa&Nhr.-GiB AcǎUA ` Ke:t { 2 +WTeMwc bb]Ç9yGu^7ywOl6}7Om)M۔n vܝ8 qq1`mpl@T#zh6� FQMQ3̝<}߽w,sKBHN9%(5-:+/ڽ˚/9YL;ޖ`9�Q|+F,#c9z06p)J;eeeǬ]v-6L=b3f t7]a{9tF&1_|8 hCHT,D=g?Y E1#M-X"A~*^3 # կu{G-Ay G�!$D&TTX~l/>IM|T͖u.;E@10P8T:$" A -%C 1٨ .b#h|h z&u5[|P֯_z衁PSXA !MKup!T1~m6ft�HH Q 4ۮZhدu{v%=G-RNi2B(@! &μ< 5SӤ!O|l⼊Y:y޸�X3w,У3>L Uч G j3P;b,S-Z:01iRj|;m4DR^y?{ddd\j?L:UwOPG{ur-k׮�)B#G P/H�"\hX#j̨5'G-7vX5fDPɄɓ'U|*:=jPNя~P_⠮BBHֹ}iio~hݪ8̓Lm 8Mj(ԛTi$Ap2u0n MmV rٵ𽅡},#>>^]"cA-(#/ Z۶mXǬX(F'@c֧5.ZG$D{{|:ɘ2ٳ*n˖-* *G@OكO~jرcnj#8 xČP0]=n{0ҡf+韅l05{-;E V~1WUE�!D$3OTZ%&U=T\<#UՕjۥ;2\3B.i!dY)[ sN,BF�A.Çe݆֪ղVw]P +gk$yRsTeLjh|ގ^9yZ ~P"rk!Z""}B "@{PLkeztm <iZ::_ i{ !D> DRPBnzz%@Z#%iےflxR@(0)o'ںcw|*㴬Yu?&SԸמ}:L#Cx<n%BN0ة8IVE܄Bd㖭J� cRXT|{.hb@<ttvɌ ~0ݤ.$=)-+S-:ٹjۉTA' zRU;B! jٰis@4b5J@ 4lo韻Uo5 \}~oD;"q1[?;  U B(@!2 @*UmmɑM["7o؏T(l0 l FA؄jxLAaY-֠B(@!r #ztcͺ_aݲm{HDQPR6n_�! B $%mYU"P19y5  !j@" ]Pd> UX/A�Bnl,%ERPxIa*-L$BF�;{uj*D@ @<@͂]_rH$Y%ef2&HBCԳU( jvutvB!M\O r >o'L( /W/-|Viim&ij-f46:~kexIҞ(݆H//ʱ׻/B!D#HB4/!dt + k[-Rf)UK2Nȥrt$&Zbh 퓟'|@}@ } pVG9W|#|F֬Yx9p?~~>㚀o@BH8KJd$5#m\vJ nrBzuQ\n&F%;)urq9tPWj5R~&vǣ&y饗_^k؄pLrr<3%>͛6sٿ}O0Aƌ? B9Jx\*Q^Q&XyYJ.>uHΞ9)豣Rp`h۵ pn'>by4ԡ˧>)ṳITDWns̑/}K\{챁2.'6N^QpL�)..&$'6m`bcҥWMhBG\!r ~G۩Y4X/ug2[N9uꘜ8!5or53'|Rƍp/K`°<{o >O Yf [SSQ@k!G^Î'7) !#՟T%:@P *] GUѠX? BH� z(Hͱ :\΂Ғ]Μ<!ƙ� I>[PP0/_ֿ:uh*@ІK.:7 zTVVs8{J?b}D'Ν?(,, W Q_~<ސ]g^^�B(@! Frr)Agl_yY|}]\|ɺ. >;p Ƕc:Ї=xk&@Fp1AhO7?E%C}cW?ezWlGz>&vӏ=Ǐ2h7d O[**,b?^J|ۤv&>*f:}}"~O``T`׾&V5"E@Y5 ! *ZAjX Rڐup9uu$@ȶmlZ!#OܲF$6ȹ˳`Y3)?MzG68+ΫHWWd˼.ӟ޽[Ô`рT,-Zj9/}g*@P#`lm#Z]]jb88! ^N<:ҶB)wz血,cHA S!FQ:w; -M-/ }[ǞyR])6M�7+xާŋ_!YĊpjA݋o}[HL8&M`۪ވ,E8 E#4cƌ{! D*xd"tFb2HܪٖORlIiS%q+h BfV�K֡M<#-E{{mxF+ᰋݗu B!\ew܍!Nq%e_<;dȜUW7IŃRY)֊2#mm>iooӎOB!=yr[uU/u v9^)Ņ*Çdj:wC0@ yF]mttk_�"B!d I�)))VouvytI3F.iKKG}ΥqhnoAd2+&lm+nI/l-t)@V" Ӻl?B!"nj%@"HRXKtٞ$)RX\(sM%R!PA;#Y\ɜ=vwEܽL6i>: K!P �Yf*ǖBE@`y}>KJJeɲ2fQqD./ֱ\`oC>E:oLBl<픺.m9X$w-+ 86x8[<..ܭ"6O46wIgOնKʁ/)<x|=ʰmƍ[^J 48vIjmھ[^: K!P �YbUY[WGUMXb-KB)Y]TuwЖ$V0 w{[ jfE5ɮwg[U!ߠ 5>y|]s=miQmC `R.yU>ytu2D%m8<r2YtNڻvzY}{h]7 6ƶS*ZS.!B2$a%@!pX~A ߘ'cF fm/]DzW-Hո;e: 05aϷ{=xYܹT: QZom7qx",ѓus lmDJƭ3O¿B 7樖(H` d9F@@/|#LjSE:˝=QהDZѶʖok3O20^Ii^|X�JK+?F!ZsCu5b̡g}-sg HRHnftFD6H,6# .: MqIo|\ ><ت]]"O!+TzaQ,�9{�APf >EڿX9(ҞR4G-"6dՀ>L Hsej@0 Um0#�1Ԁ`X_roהZրP\ rykfinifxmHcSVV'X!퉉ҭ _M?b^Wnkۿ+ ѣGy#3]Nq{uzn4N �ARr[IvDnN$Gz .n̂h쐗Q8۲\j,̢=iQpYlL�g¸Pna}Ю[f̠wF2\@|TV[UF\ʭ)}(\:X9 -'NH&BFS~ }kl {̎;[obO>)sΕ.D_y啁ſJVV֨q4\|?|CrŨt#ƍGI gLaI@Ah(2:iM ' |u0(@�9!Wѣxс.Oz b,HnvSǥAi_d;U&r2{+sSp׃n?,mmm8xPӴҥK__?ұZo}%!S<3mH _[M::ڥߴeԔ2f =^)o[+)@h HQs<M.(( T,%Rtbd:$gϜrQ)8OzJJCn4 (g//6A'> G?j /|A>oΖ~hѢ}+V/~~P?S$:g?iIMMW_}U?~<˧>)ҤIi/}K\{1immx_??:uuuG>5%Kȯ~+r pOT"JOz[hcs;Ca6m<@>~\c_UU%osó#nˣ>*'Umݦ UTŸsss#n7E=^}f7u{|J� B�2}zcT55ye?- Q(@En�AģԬA] l3udya:uLfo=-GQoQT cJ҄Y,q?>`n}wqrKqEL8Q[$WV.ƦG/f)ò1o/~ 2kx駟x_̘2e̜9s`~_WA9�_CΞ=;0Ls=|TV]>+- }E{[8w^%t.v}En\ʕ+D7j"ۚUHܸqrO6-v3 4n55{D͛�PG?Խp׋{GWieSe?9^⟌Iq2a0q=!qS]s(@/@,%Rsl.W⣳`n3'hH7JTVVix; ) rRV>\Q7}pu|>z{�c�-x؂|<aP\\@" 3g ?3W8'NxݺsGCm!=Jo N2b9c6et^yD J�܇PSO=>f DNpZXXf+`:=۬YΟ<yrwOf ![h4 k)@rr)Agl_yY|}]\|ɺ$ssx5}{ >޺p쏴eq@`y{7}11E ,kņGL<cƌבEJƨ;8 +sJgo ׿Vog !/z�!PcFZC �}UiFP30ǼH~ͮCG-Adz<#PhDUTX~l/>IM|T͖u. P ~D po\ ^ |%bFEI^ Z2b`LUHEG6Aɿۿ ~ejXd7ۊAZҴt RLCh}%$$PlH3�Dz FQi]M?Oյ#_0Koc/h Fb¹˳`Y3)?MzG68+ΫsL&39x{{nք(H7aQ}j@N1}L (�A^ec: QtLjLy�AJ1|GA׽+b{ߓ+C#"5uT* Rʞx UShA[nEv #E�PHz!z DBP'A=@;PcF "8q<j)ԽcǪ1#N&`N<åT&\favQ#?я Z.B(@h4M$@ΝyI%o#3O 2fI_UK9fiOS}{JYxqq7j&p:CgQ DU03^ŷ"@Y0x%\jA9˶m.GòU0ڇ8A]>ͮq9:0ha[36S1{RBmٲEF C`';q(ԇ#>q 2'))Iգ\ڤPBg?p]ٽ�o-@HB"+R_J"\g*GԽ4)){ewl$EIel:u4Ȱ'@*-uh*HK^[*.Jݗޔu ruA$�|2``۹s'o!#Alٝ*.wrSvIٗ&Ϯ9FǎF�2gk$yRsTeLjH[Oۑ+g3O=PD"e("Rߗ!p=yr[uU/u v9^)Ņ*C25;~7$=(e-^Ȧ3 yF]m"B"HC>fFds%@JJU~q$lݱ]]elGKZ;#osmFV'gʬv|O:{z-{德,19ۋbmPp~Hs{dUʸ'@p1W9yҞ%[t^$&Zb]QvMp\H [g2 vj2NvRrrU7!BF�Yq }kk^)jX%rDlON),.9ɦϒubV(rB?ZԬ* w/+S^lֵ؄k|&@C ߚ(E'@7ȁKaik+p27߭BG[,hG3utB!\ZBxrr%|˒ee̢d8HBmЎiޙ?S{-tMiqk4t7]"xܭKhhVQ'޾Ȑ&6vJ]S IkOlʩ#"D5p\OQmo ;<AFb8?}i^oVX}ݳP!9Y>}R]g8սGvTS<yܶtXB!#^,k*@BUebK@Yiy,HxS.*Y4:hpF۞n/k_-&Jec@jWI]Ψ�A+{rLvMJ uQEtuݝ:钒ھ*M0Α&ٕs g<\#w,-Uo4GC"8�j6D G}޶iBC >OƼ3H,� 5^\CGҢCuW[_/o86O3.WajLb B!xd T, _ o̓ # |3ŗb+vLm6yK8[-1-oQ4dW^1F37HӁt1@@`_S$E D3PS1hK yq+LJ^I?^D(T @Qa<6n*oאB!7�ycMlj鏂T۬ @Λc*@W]b KBtX䭕*j3 mxRr}Dfȷ�Վ& `{ IUv�Y:Fifz-" }¬\DNgrM$u`XuPB! >_8QW#vl}VgHт�=w�5 ;Tt۪Tp]T6&p@$@_G 5@-@HgL:+huѐP(ƛxh�A*ج4:H5ʤk H,rHAB!B,U^X9 !@fΞi*@P<YZ?MhiqDj!q e˸xIr&tڋXf53c ~`B7W1A Z h�,Xƚ5݋}58v"xqmYbH[6uPB!d fPqQ^(OSϚ D�*M #w@t"9oi?#p D 0>ղ#Q G* Cr[K!= {,cT1MfN1D١ ߓ>.)ю#Vu9ֈ"}Uxw(,{0@ �g}G톔 B!X2}ƴD<0-oKkZaL&@ pڕ<Өmו1_BV/B!& L.6|m6h~ӖSS&˘ 4!B(@!@L).WcT55ye?- H҆섇bGBB!P �2ytD8yO'$nRL4A&L/aOHܔrלtin BFQPB!FQB!FQB!FQB!d U9-mݥNIٓ,`;$9u,J:(Vfө(@!B2tew܍[ )ZKgcGQB!dhd{%6[uU/u v9^)ŅÇdj:w77 h4 B!X9i %%rҥ+,==]5%Yvd/-=9p8SfJ%[t􊫵[ DKTmW6vU ߶Tqҁmouv tq_4;f<!BF�Yq }kk^)jX%rDlON),.9ɦϒubV(rBzݠe.dܻL^^&4j_TmpJyӚ�S מr^h Cy.4 B!Rj M(d+糤X,[,cGt~bm`A;Ѷʤ7!h<?Dt*_c;vMyH5wIvNQmo ƚ Q `"@ړN?ƱGSW67vh-/ٕHù 2mGێ(@!2J_ }u~TTL,b)(+-/T oE___y9m`HҜuUVhSBXΰȾ^(kK#JI-sZ;" Qm9(yU>ydu<" hMD ˛qFjePwUH_/oTۃy.4 B!Bd a# |%@1O.,@j(A Xx#?n}Eڲ#rY-VюƖnH ?X>~R4wx$nu`ё!@`U}oۗ^zXsQB!d 7樖(H` d9zF@c6RJjԵ˓:hDqҲ0$�TXpֻ"!x =QH뱴=B�!B( >_8QW#vl}VgHт�=w�5 pv:vڪ 1֓jlykL"5jŽ{dʀmX;F)lE` B!L,U^X9 !@fΞi*@P=YwI&h/R>cA4BԪ^m9`~ǠF Vxz5E}D/7d84[6JpHm=!BnBJX<Nq4R%xi3ף|nƳdLK5k}pv٫0SްiSfhBW_@XZ:h XfRhPt<{DB1խzTq%&@"m\h B ?DX-kQe0uӚ�)/_նi BiS�ņU}&o2xjdB!  S1ƚ2i䖅t(@(@(@!B�2ytD8yO'$nRL4A&L/aOHܔrלth4 B!P Nh4  B!Ph4 B!Ph4 B!PPh4 B!|*GԽ4)){ewl$EIel:u4!B(@.@NQ} $غ:Qk}icth4 B!P MlOޢFsKx.qꥮ.6G+P~{LM<BnٖQ2t"4PB!d4 I�)))K.]a!G..2u~h#%~i葷Ϲ6tq3%[[W4{6ioFceyxU0⣫ո]QvM4+Ŧ~7]=j&y0BBB!!@m\H_!W"k=.ۓ$55E eNbpX;䱵ʰ^7h<|V  )۪=`m$x&Yqu'sؕ{yB!7�Yf&@RTT2˕YRRZ,K-1#:?Evy16{۠h 44w ֘-2sWZ&gۗJJ[<eXƶHc7np-f<I+2aߘx)uM]*R'evŘm.~DܾnAZTQ <i;*gk$rT"&9U->מt{{{6ó k��!B Z,~M} QUS!֪2XRPEJ$)cFt~|~e8 ѴWVhTd!~S\ pa}kfi0ҁ`xKlcLB&RzSqFџw &"8뇨@HQqsEQq ^=dѡ:iKwʭY:dzqC{KhajL ֝r! B!P �IX@ °X~A ߘ'cF aʱױA F+ljjd[ q"šmEnMŠR"h(mwR[^v/Uݩ"@F'+l=M4p6kD"5^C4"⒜(Fwx?26 g  B!\ RY 3bA̝7T\R`U/;5C;8ȘAրDu }^ݫ Jq|֍/٥9:g<'H,}FzFCB4FBB!!@^{}n�qF9ϐ2{lSrk@1p;^vjJ,hgvYE֜l IE{Hb3Y H{doWu%3SEQKPAJ!B�yY(r C̜=T,=\?YG^i4mta`V$m%f�cB!p QaDXX:o`#iJ9^qwc2kw0E6cJT HCqgP}j@l9\wm8~\ՒB!WI0{.S\n=G =^x�A r&; :I�AQ}&*,x(mWCc0$}0׎`3bi<v8jNA8 8m`ŝS?�g,^(^7hq@�uk׆t0LhדPPB! ,@Ϙ!’mimV_2,ӞH6=J AeXF֗3K P~ B!@<3m J[O;ڤ]::M[OM,cPn��!B S1ƚ2i䖅tli  B�]<mLzjL<Q'Kq7)N&L &'$nTk^:4!B(@'@h4!B(@h4!B(@h4!B(@(@h4!BF�[#I]픔=ɲ; CSwʢ2ne6:B! C [vݨl]]⨵Kʾ4yv1:v4!B(@&@'oQbY<^8]R`JjR\\(~_=|H&sh\)b6JFY !B(@ J˥KtՐ#[wlGd:?c4ۑt\jѡՉƙX5scmf eyxUy'TJU|~"G<k}?tpg[䱵#C BdJE>bj{X-b=9IRSSP$&:?K׉C9e0,' 2ko r7`[&x|=H&w,)۫%2*Vn+-C6 B!PD#@VY rr%|˒ee̢vbXrA-Zˬ)@~"Mm=Է߶Tڶ-꘵'==rpDoJdi5u&kYY@p-?wֈCE꛻[Cl?{FkN6Dy>ya-`ۉfY}a؜۵1x`Xp͡3ښ( *rf=u,/.Z~bUND<`(@!2_ }u~TTL,b)(+-/T oE8^FmN`Y{�"W*;c26a" i!9}ɪh8&'.Wg/ <񅓎 ̑&ٕLyK@ [+ry7pP3ۏzG5Pt!-֔H}@H`Lƴlc{A_ws肸!%KKe%oı�!BȈ K(RXX6/WddD;LE  ZD?$U)gpƒ ^sb&]þ^1pnFk@5^.߭ t׊J|P3ۏۯza|60<;"k Hm19={q2րdjbB'Ա i B G@lbsTKMf 0̈2wSr# =Ԁ,m,pm,#uJ_U9? ~'oӖ43 l n?s%bl'XhD#Ԙ %Z|ڧRt&ϛB!7�y!kPf>C칳Mȵ 6V`8ȔmUR\ۮ4H`98"))=:+&n_g54+%5+7tE >-RjZqn i7Xx]�!B$@^~e*B/, 3g4 Kif/iV& 'h*{Љv袭M 8&Pec}c j<7qso?xԄ WfQoTcX X{FܹTU3h-PC-ҹA CԀ D;V9{w7Ę�AhA`:lB!7�ya %,\Nq{uzn4Q >7YS7nw;{uCv7pXkCfWcJBJ u{ЬT[wϪD%8iD E՟~,Xw@ V1PP XYBP`a.e[K=/\K!=hNJh w8 B!2}ƴD<0-oKkZaL&@ na "^W\1:!B(@ @6E ]lZ'm.-L1 n>)Um+S(@!B�2}\Q5IS$,,Ye-(@h B=Ӧˤ&%~r?'qd¤ 2ax{BL쥃GQB!dpFQPB!FQB!FQB!FQB!d U9-mݥNIٓ,`;$9u,J:(Vfө(@!B2tew܍[ )ZKgcGQB!dhd{%6[uU/u v9^)ŅÇdj⑛ҙ#-g%N6W B1 J˥KtՐ#[wlGd:?c4ۑt\j҉ƙ2k6isT/nYt.&mVM*+o,8X;}oYG^U~} f8X{UDi<B!A۸Z ȇC5RmkE,9z"]''IjjʜdSg:wck+a9!nY{OlJCsZ vM+nYxȜ=v{Y<B48xA\^sgz{RBg8|jk!Bntj M(d+糤X,[,cGt~bm`A;`fAl,?Z?hgdi,=\Q.镢vT N脯/%|gK_3Xj҄X8C&ZG^O^m3ufgܿS<5==rےҨH"۵Sܪ?o|)g[pcxO̸}R]i;Î)g7G{d!BnNHm}_U5b*XJ,J UdA›2vQaD9{@[7Xb*]^zaܻ,jgKEM"9ħ5їɦ3[%KKUiC!R<SkDZ4'X>sWdUG8aןWGV+f횢 Egg>]ֳ1 D ֢pcgyJC^VvL<H;=!BnJd a# |%@1O.,@ԛ|[}&Î4PYWO/;wjNhgwoͼ߭yk}ׯoE.j"!?}9nu`=~UսD+@"݋PϴVk;ʨ ??k 7vQǘzƑ#=�!BM)@X8?bZj 6kaF, k !Boˣt,q|O|?PԸ;=w;#8ƺm?cs onhqC B!ܔ 8jĮC )Z 6 ׺$_[6: u x滵m؄٪bqڧlv:b5 Rl"oK$^:jLioH �32b�!B)@^~e*B/, 3g4 (,XC~p f,X#y9,Xf3h!)U(V9EE[LYqw"@r 5 X&ìmD)&mضLW@ " I6n]\^(>0oq@5-o62g:H e B3pyr;iץ>Jg^G5܌gMRc*M #w@t"9Wf)Os@"t3g-; vOhKԩnXq>f񃚂1 y$DXD ٷ0 VN4gd܆t#m`a�R@$9`)DB0ղ#&@qQ߃,X Bdi", x`Zޖfi(2:iMKlcfa*c*Hmd!BF�yf%@tkkvwIGGtt 2Y,�NC ٸ>G�!BHD2eLqj+InYXL'o�Fh7B! =Ӧˤ&%~r?'qd¤ 2ax{BL쥃GQB!dpFQPB!FQB!FQB!FQB!d U9-mݥNIٓ,`;$9u,J:(Vfө(@!B2tew܍[ )ZKgcGQB!dhd{%6[uU/u v9^)ŅÇdj:wW챋[=8!BF�ٜA bt{d,Sgf;]ᗖyKm3~O'g*t|٩6l^,mZܯ%SWPb.j[qԸG3=+&k5Z%ILPhPB!F 6V/{mT+ZmDHI"Ņ2'1YrN, eXNHm{.;sQ;k6WG^J=˔Sul_DanO]ۗʳ;%: 5>wEܭ=Mg|BB!7�Yf(d+糤X,[9"Gr< mvڣmOvyduyډfYv>`r9Xm!%-_2,c[mweeEړNvs{9ۇ=*Z>D2,-rˑ[FihVѦ'.GJdi5u(&d,8 bR]g8Uhڎlݽ B_ }u~TTL,b)(+-/T oE8Fm`H9YS5�ZUQMfƨ@R朏[_G_0,o>s g<\#w,-U%eU 1=B~"s/GVib$ڧ"PwIvE2<*POO_/ozFYw)Y BH’J �<4ŗ`c+ ѶG?&l䬡7XV87UuHw+-}۷l(z.5Pָ;ekX꛻" ޲ {͸u) 'h B䍅# 69? RmfĂ�;o�^f-@a:wD!r"D .ΏTRtB.x|cU AoD]iliFUOAB!P~G]5s(Y}!E d٦zՀgޮY;!FΥ3R+W?rE-#)\$滵*16DkA`Hq!QB! /2KEN~g 4 Vh{~W:5CՓ[fWpngς1<} 5vqY׶LW@ Iڶhlj|"B;ιT]C-5&(lRH UnsCF_ CԀ<֠ƎkD͕c ƍUKUd $�!B *@^=C ).SܞFq{]꣄[<M}zTxT`*lJU샞"UN1%q?"E*DLHcg},,S a= cgB-"FDh5ߖRu!8?x,X8#~UDh_ԓ(@!r 3$ iy[Zע `괧5R@'oZ4B��!Bu L.6|m6h~ӖSS&˘ t9n B!P BL>S\ƨkjʤ[ɣ#OBB! =Ӧˤ&%~r?'qd¤ 2ax{BL쥃GQB!dpFQPB!FQB!FQB!FQB!d U9-mݥNIٓ,`;$9u,J:(Vfө(@!B2tew܍[ )ZKgcG݄Fh4mX-Jl44^bsTIR ˻#tnoa\6G5o9(e-JB!Ċ�ٜA bt{d,Sgf;]ᗖyKm3::8Sf~]dV0,c[,Nk(nF2q:wHs{-oV\wr[5WG;9 B!Xnj%@"HRXKtٞ$)RX\(sM%RߡC휚Whm.wEY.fu5|Jh? r7p5JB!+@VY rr%|˒ee̢SlX.08:`fut.][ƶ:6WJ+ ڂelþ1 %SꚺTd`Aܵ,]8ΖnՖzӬmqxm&ZԱkO:QomKJ][Ns0,n؏c^soVX"^5ǵK:{z]7UF6?6ٳ³n*kQ KK}U[3Vh}n!B(@_ }u~TTL,b)(+-/T oE8{FGm`0N6ֳL6D[Y3)V8?R$r)oHIDņ Z[YUʰLpQmBO]@?_߯_W~iK_MxB IH6a40 g<\#w,-U ܇w Q ݧ;=qtfbC:V/c(@!2H’J �<0�SoٍoO1kN7ް`٘?GA@,;Rkܝ2~u`Pmlwk*jU]}2ocظۊdr[ _H /;5G3Bd)�Ԇ=4A뢫A(} щu\=wH2 B!JRY 3bA̝7T\XmA{z؆}p!`I7ЁN.aH2Ru,Ǻx]5 ܫh7n3fԟ*p gFu\oהB!J~G]5s(Y}!E d٦Z׀t^ݎ7�U-nxKn)vlvZ4k``yhk@N;bv"@pO|VP&kotF2.kJ I u; BWf"¢)X2sLŜݬ=$,X۲ AD݇MsHazTe|J9^l.fmhk醶@e}\F$'$P�A`AEӆ=�qeJqB ҍQ߇u\lfB{@h?ԩ;lB!7�ya %,\Nq{uzn4Q >7YS4lw9vDN$ʬq뭒]y; Dِ`3b%ȊmyWOXrݴ_Z1 cgBf=( Ω> % 88 Y)@PKfp( U50Ǹ5'ohsByh DRB!dT 3$ iy[Zע `괧5Ro~oìe_B'BH̴)Jb*m>ihv7m<5eY@2XCRoGs4 B!PEO).WcT55ye?- +ޘIIwK�!BȕFxL6]&=5Q&N(%8'&M x7e5g/<B!dpFQB!Ph4 B!PhSv9rlڴIΰp8B�h 1~ijjxkkkGB!Iĭʑmi$u.vJʞdٝ!ɩ;eQA2Nv G锞65;fڶQq-/O�z&}N|%^Q]}{ovI:1q1SMC0'ETA@Ay(bm8婢NAQ[ꜽ{>U|o1 HЅ266wX.𨋴-6Q*@_|葼�iaޢŴk>j0SSi@ad8`0"@Chmkf#uT[_Ez*\2Lt-}s;7ǁ9kkk)00P5jo@=JN^z>r!Zv^?QH.v]}=B_|{m?@cO}?~ltޜ4E֩%ˏ^>~m2VZ-kӲ☣~IR;B?y*<x0E=j8r&L&;y*8۪K{kebR}Mp c8 3'�)(ȧ>Lt|0N4~& O1NuvӹdLS 1[s[ZuSPbӆZYC'-;7O.mL_hNC b,ÍᕔUw?%'O accS9ǝH_^aH][^#~49|s.Z/" @Cvi`"^a_Yi3Z¥1Ku'BRNڴu1ۼ~RXxs(u]G ciּT^QA--ϻj_k,ND7bnJR]SClek`0�QMU5T^UFb*Ph 9CᔛK[|B4Z*/Jb{_t퀍QnViw [i>oMBl�U #ZWs̨h-0qN%4Pzy b0ܝ zo5^3[a8{&~JJKLٸO׮0XW߭{:KJu*Ֆ�euրXD}Ls�0S3δHHR93SKxtN Z c8 c�1Q^^M 'QAa>yO;4~;hCxy9Ulkχ 3mg4M4wt?%_}#c�W@ TXzI "s]sN(MDmb^actЂSeϼ?mʧOG@N.<!T|. !+}Sř m}"c~̙mʣ'bިrŚ3DOxb>G X5Fڹg/͚;ic^NT'lkL :D�x2vi;1mquTF GPuٹ4{Bwev~]s_վXK٫bh FБd'}E)ET˧’\ysܽg7ס[16 `~|Rjsi3؆hlx!$tJʮ3%iR|pnPXjRC'}'  oxNf5kz@6Q' d<-W+66̷d@A|34|\(Hb;0 4:]1h$ϟ_TaQѸ~̢n$ ?�O g]-Â%_ӱ'4�A؇GđQ>b 12Jz*ρjWQV]Zkܳ܍1/ Fdn)@rssz@ly1߱ˋq,@OCmӁO?Ҫ/F00)Xmrur 1gގ'r.{Rg!tt^0^ 8 <3K\MJ]{�oEH�tTإuxGcS#fwa}s8;.O#^eeeZXl\ Oh qVx:l{'Pt欜ڥBGE:V|u%K5 [iEe �j7'_gx2jŀتK}\f%X8�d[`0$@vrW, @zm PT{' rFKʨIwAm *3%gr?@- GiZmʧ.ƀpʍ]rhaKeonFeOZuk}qXAtR*:g 0 Yz�pA(_PX$ 徽w~e,Lbʏ>i?l.CG}/;q4mVh�j7 0Hne~ fC2n{ك+׮1U a!`0H^RMյT%X-YúbȦ4c@ly4 Hc%JնO�KZ<Uǔ{u)j`G6C28FP[u2Vޓ~l[{@7W:ˡQݮ GbK`JH<€"t: NOi.c`0Om Bs<  6 ve,t0h_\mIj9�SU/'n`#Lٙ_*m7?jUsLA PKU:`jN 1 lĀ G)]1·XCIII2+\FD>%''7�yLEŠ^Xj΂EsKX2  7d c(_JHM-=lny wkWk ɽL_;xGƟV}FVªNJ_/V*B3zWJ'R!\:i#&�%T Uham:2tVsx?GU[Բ`a,wK}s`M281,Ѹ`<!䰚~3F�APyhh(SBB&Q嫫Yx挜iCnq1x, c ׮}a=lmYB~e ]!7nܐӱP="/0`0 U˥�QF::QgguvKhn lh6`0 1(dhlpfZͷ4iO>lh�a0 �yoZ{Zt!-\,Y@ ϧӼEh¹4w8/F(`0 c`d�a0 `d2Y0 `d2Y0 `�a2,@ ` 27^0P B.)$"NQd�a0 p]] cc|5?* HbÎd`0 �  bd0Qm}UV멢sd2ѵM6\dPbX +nS ,@ `0<%@Ϝ 0::ZVd2u4;I,x>H;MM璍2M"7ξQySg,?<RLo9Sk')eW>MA_<'.H7WR88ƇO(:>)f`0 c�?)@z<TUSAUe+/b]މ3N'D񎩥Nx$E׺lH+l{Cmܮ+Yi(з irJ=dy=yvrJ %`0#@|Dyyy6= D}p?Mޛɫ Ϟc;^u:�ah{BO{'+{my,=/0d=hIz04_nt<6 u1uu?Zpaǯ Ny,P 7gߢ2i~lu6ҐU>:ꗺmi-m9;>+QIv� DAzN[*!e5Ⱦ RzMSǚ8O�a0 1zȡ#$HM]OR鋨XO9%S{4eoC㧽D}6c ]\ %mӧ|KQf^ 6mQw6sQOX }Q'je1 h[d4ڿ8VBײuh0 *p[}t/uOo4!0 tb@08}Df4{hZ)qΔ}{*eџE_@lډ1A T`0O,= 3ARRqqdpppHr ZTj>b^n~FI)}JG)T[IuöIA>)))}h?`ꆋu] dZat۟m$:'' }goQ̝t^xIZץO_ViUap?\Q*7D.�g}.Daweax#u-8~'w_S6D8\H3~x'E]|e|-S87W^3~ׄD}Im2=ѷvhNN=#`0! ڳRIT)Y+bAlBSNu`{דR]�>~@f~y@oueCBUM]SӠ?nzlQǴ)NF}QԄeW>b`0O`2,@ ` �e0E `0X0a-@(44Jn"6==9 2_7Gõ�ʕ+V;<\|ÇL7c1fpg<C{mdd2,@䣣:;;ndKKkGog}}` /{c=F L&s!@%Ds< z'p'+^Y0LH{{;)  & Q%@n߾MΝx` ڌ4[ <փ*@`<U|=pflCy[NU~*/fn9ڐS)  G4) 3(3;Y!"eff3okcDe)/ u4!@Z[[=> UFYUQuN E_<E ,@,@1'/ZZ<k16)'7+uu3e: 3!B2AJ%o޲0B` X,RO4wg,@X0X8bZzUF265@52(z xlh0PqI@BTPѣfB%&Qr}a%@C%o޲0z')4m<J*i?w$) J`q8 3#t>4Y0 )°h{&G 54Qco"z,(G�cl=zDSU9BS# FQe)xr]G}h:}6rrF�_7z60ԿKƗi{'.x_n\fy W]l;x Ã$)9Qjχ TT\Hi)2*JHu<H^~t/OTq8vL!֭T^^N׮_SOs B]TT,  li6Pfʼ2Nn|JRRRd9~ܻws^?m3yuvlC; 4g#)(ۅdu9k]ߺ1A?ZiE`koNGJl;97*ܻ1ɒG ;p@n|nG(jnn8އ˧~99t7>^='bsYܐGG!Q6f{x4iy I#Y2^SyuTS]AEɛ$e5u.]{tD#E]KUT}=F' ԋkfep0U {"".g߁_Ʌ9QXx8544xQ2РI]ʾ;ʎv%ҕH'OǏ7KRccp2G�<oOp/yw{sҵJFXKҾKqZ7T6Ҕ|辚*E>gI$o.j[zxv6FQMj~dzvkt*ܿHgϝw12nX{U(n)  sY<={z&iHc<{wL24IRSSJћk+՘O y3 ٕ .ߨ== yb 2m2Qw?x{K)֭%>!$.SݸAUն8EEEB<H8QWzQ2fO5uCi tf�pyAup�'ٚHc9qoAeO>wG@p# /@ŝҍtd:=L7iG:Q\Ry 4g" s[ӦSn^9?;'Wgw'FE ׮Qݙ3gR}p934䣜!"r~q𰏯ʼc'NJlP87Dayyڭ엋q}?)/^4](Ғ  @ R|4Qx 22Su7lS֎)XXc_VVF9`W__QY@�ȴ,q͑6f6R6q]>"W8R(&kkG@&KwRaD7SaX6KW_qBmcⴷ- #b UWO#|X},ZLDH4^1'5%`}__+WO,@Tp\Owz^~]ON kGSwfcu]X pXx[؜)|?po[RYUcjq<u/{PF-[  ;�޷Lŧ=#>})Y@ ĔEaiy nߔF0Vjh hoN5sORw5VPi6ʉ_;(gWH �)~,ȐQiYr>t:YzL{] KqZ\s48d`"c�q&@,*B$~'_KI~E`zMO;oSgO2eP8|JHihA89"]o0|b=zڳ>;fц'oip9g.]Leez\~YȜ?sl9DzT`a9DQ5$\IVqQt\:;?űJ=pMBHC`eT1))C+ߝiMTu\ LalT9#*KQE` U!R!DHh :2pME<"?a~zL}GO (^Vҵ<ѽ6 TM^\TPj3\'>7SVA??8Ƚ^,g@ (CBeeIƲ@>:sf=7]AZ#CkG P܀SōwȐ6+}MԲ]xj'CR}r#eSs]韵�*iďD #:QWG°ʫ6m]Wa m,V(n{c_'oN"Li)7chG<Dg{�x1v!T^xov^N~{bil/m)C\$1ϥKU} {·8~Cgv�q9_[pAn-aJ̒ipRn?ă@tL1@\g͛O9_Ιg1ZC%r#k8VP?I2nq]~ҀH1 x9~?Bky 7c@tj6c 7JuT_H,/IDi'<6ȇp wE�`zq1l6VW( /FLl QqɑB;O\�'~C=!L ^djZC ۸LƯqH&nzBء 8ɟ̞gA @o%Ϟ(-Ց]$@vC-P  ˖KU?Ks&a{\p Ȣ߶z4@kb .%履wgϕȂ%K)33K308 :˹Ư)@ TI\ԭE;](y2ͺUy烏* cY^7lZ�ay#1Vj廓#e^H<K$ cT?.4UbP A\~ż XCWB֒.{;fl2rA}ΏT SMX3hmiAU Odž4e TRR"W 1#0ZUl r~o#z|} � lkSƾd8D& ꮘJuRwǂ|}SݷGH[˝ tZSlK*SSԮGΰX H>^=ORT\bokVbab�?|{c^54x |<?.~J�/^2l୧\&N>yʘƛnqoM˻fgɛ0e%%ݘ8m60>MxW,WIG]j,@lqG"?('m )t!O!q22ZQ DYLdne ` eo7PeY }xjuttPbb!�q', l Lrf ֨d(z9oT;2~Ϩt2u !R9S9vQeYLuVzPPŠL&1 BW Ch=?2 q}#_] R/.Dηm+ Sy`(:SĈe?=3}\c%! &>ӳą^!{0=xE?|Oė(yO U'5G)[8^mw .<IvLA+xLx,@X0X8"+!߄CGdm5t+r%Dҥs yQ>|UNm<Rd�1V#ed4L;}ugM)>LeP`\5o?ja(C<}jSqiVreD}#ߞEk#VهU#65yO -1?&s3ƌ,ͣHՎ"ϯYbd$ysB< Q v7'%mz6C^'_iCO  i@-}v<"$&b9 (i �q�+m;wPtL4]v._KQQt!<Bx<ީr)DK8k`OO}:u' ƿ)?)O'EO <_,\jAZs&NHO쇇vmv V[T#6soI/}@'A9 m}b4Ⴜ|6zc[jFWZ-oLm[ŀ'D�<elxu Ȭ펱u J'итHx,@X0X8bY]BäP BWίa!0ҒQ&]łj8CJYh SN_KꊜAWߧϩGSL@Ki+ϮO v^1Ok g.vKV'K) Ug #A敩*WCmp`?ͺlNq&OWհo Z/ɪ?J@~oX`b{BU&&OG~O6#HV=ej-U%@Pu%y>ޔrmw ŞL   ! Ui;r=4j2WJI"-X Yގy~oAx=!@ټeE]Z| IT)BgiirʐlNC9DB2C-@F2S= ,XM`zA`]k2-e~+*9>KKI޿3W+S`Z]VAnPF"@? 4ĝXr477222sǟvy<3nںM%ۆ\3t?FdT g$k3)}/(1'VJ0|MH+"e,T[گKW0"D 2JY s:'O*X |lN$mu\z:338߭[/j>0O�a�a�U I<ƓyExX# yx/l#ҕ%''exŹj>D~O= wg2u oTS,<<^@BCC動},((c<` %KUsW롽6:%@gW2ͩ16̡ A'cvt.[obUsW롽6 2.\2[g.|y`0C)2/7 `0.@C%o޲0``0 c s i)/ u4L `0Cr! 2U/ u4L `0Cw,c'ўlAh}.:3L `0Ct�=pvl,@ `<d�a0 `d2Y0 `d2Y0 `�a2,@ `�a2,@ `2d2L&d2.b����IENDB`����������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/paned.png���������������������������������������������������������������0000664�0001750�0001750�00000174275�14035600052�016212� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����R���j\\��� pHYs�� �� ����tIME0 g���bKGD�����JIDATxTT׺k-/$wz7k=5(轋(*UA (E Ěi77]ѫ{ηsιg)aF[0>e{~?~ ~: ����D%78yItttt����ag9+/g{@;鵣I7ɟ%J=����횒 b79vd=>9<)yIOI/�����9>/g'MΒY J$nO??�����ِ3ot=!3=ri+O?w}����Y3cuu>ΐr&g{uwKn:lP����'ΎR+ٲI{y&''y9?���98C>Snr`I_Æ����[5,g{ggy:n ����l_"vTΘMgzJ@7;����_W-=.g{^M셍����-!&|#'���� x����'�����'���� x����'@Gt;ڎ3gRX=YMu�ͫ/칅د_x' o nF'Ojs҉5shrZ: F9�סAϜi摆wuZy`opA/\E|>xsFO08r;5v566]~ƌТv xB<_M k˞~t֭-;,2J,?l ڷ78Fۏ쭣?:DsO} xwzW#;N/]⺬ܼV<A"xɯ{~p>]F:ߠOh{/_~C}8xH\:]ܹ盼)+x>M^KY&( $NR~s?3}-\Ο@ih' pBcӞ:q[T̸&;~6pҧePOQKJ6[In`x9/: 4XFuL=ZFx£ioзr63SfojV%uC<DŌ?qm4kms Y۾涝cőuM>sqݜqyoq78ՃCy oۦ^e灃njۑ;s6;B]NssSǛ>v=bn⫯w$nM+6|2inP̕7nИ?/[.nncǏ7vK'/BTm{G[m3gϊ׋Nc>&Ʒi|B 'íwpO<xey\>28Yv)ݹ|;o#]l3Sׅ'.^[zlrh5KRIY{f1ķo۱C|8d1dmZvT<^h*YjwsS=|&GE'T\_]Sد +-Y^'gsçr>hp+Oڕ8JBySa[\Ur|qy..ȞnvP+(*-xk-yTX1iYW7l0\J*'G^vmj}~u̝mfj_s?<,@ cbrlru=_Pyh+1cp Y۾- oJ3omqjͺ u6ڜc3x?p@\JZvDDFQT; H xB\[R]D|pn`}O:eqSsrY `93g˫֬NSQ4e+-^"KJI[4fe)JĔÇl~%Twzi]|m},[DgJfw5x~s& h[ޟZCֶmgklz oTϾS 3jiد \q߈!VlGOOk._B~Nͷ!xBj7+ݨ< 4<GE%x*'2r+:Jǣٺoh¤˴. eEoZЬ ^nK.Wh8;imvGUI~yF`=N;ϝvYomOKQў%mrgA)S@6<׿}d1FZ𜘘,_zMv׎tx7ơY<q9P(c'$ݷ80p蕫W :zi]LX~Vffd 9:nǦv"8Yk;㔱'Nl2,+\/Rc8G嵡z)J>Yr NeV;ONTgدUkSwkZK;5nvOh֭ě,Yyb-3sgkN.b ݮ={O`\,oc~y61WLMyl=%GhmV}Ets |i~ֳ,O:eQSOy\c+^/] xf9NmOM3 &Yk!F ׭צ�_  j㽰=Z2-mc5� b הp4G|yh'�(fȓx�'@3p'..5!!dW%<c<S�������<<��������<����<��������<����vO7[�����<o޼I�����<Ϟ=M�����<����VjA�����B����O����@����@����O����@=sܵ .}��pǃoP�('uܱk'EŌ~\ۗKoRب(3\GSRJ*<xo}=f DbRݾ}mʺu׭5 D��O[N<^BJ:<;v,ZDk^})/\IҪ5k䩓t)zsFʛ5MO嘹xXǀ0OO��@-xxrJNB Tx]V}S "D^]eUH,n4%`YБD8Oi4.m|2 pB+V{۹jF/YߏYT#/=TI/w2\m[v-MHLR'/5t{xҞ{ߥb|ecRom^(PͣƫxS��OSƍ5ZTΝ;+¢_�{v o|b5g~5 "Q}o&<v٣ԣcG"ĭ\Z}\Ӆ 魷ߦ^<?\3u{Knɏ}IpXE/mi#U'N6C<o@Ϸڽ\P!WM[6;<=q # GA]QY75��hc<๷n$/{%JegJTգ\:s:QFV6-TO|zU0G2힘dAR�95Ɠں}m=E}Εi>:QWG#}mq1ij 4S7o(>dM ��P4<78o٧GǎJr,W'/8>\-Թ;]{w*'x.iUlI-Okᨊ+E9a8vMmKA/3Ee+Dx[X[>re5"zx˗~LZxZ{~ɕ[e9<C+���DQ5w,q>Y owphSonRe2xjs+ @fK۸ۜST\ 6s>}-,)q1i-xZ{~T<��c<ã8SN3,_jJ)B WU 8A1X{fU>Ek-](&(c<Je1+tV]+fkg,8bvֆX{GOζCyG|OHʇgU 1Ο)bl#Ic<-=q )wWl~%���Ҭv<|9=Gl[R|_a8s( ?vLR7Čv9^RVn mh(=|gKU2nn\vc=x8āXkR1mc <<)ads1ٜY枿jX2-'8���^L(x-v1��< I@<s\T&� x�� x}<wټe x�� x����'���� x"x����'����p�����l'��������<����<����1T��� ��� ���wƫ4\<Gw[\"' x��8QrB FRxoJI)nA^IPIYiA@9B~c)"&MFqCiܨa?DϨ z7(2ʛRSp;Hoq#pz+3n+XIBQ#0GQ옡>ڇR|(}P/TOʟOI^4}'e'yJ𤄱4)֋byQx_Jvw>6@O���_Zb0? hٴyڸf2%"+"bK|5=]AǕ%B|=VMk ) ihz gb-=RKг3z."WrhtI!VSLa1=_C],)&BWXHQLQ>UʥfVSfU>ϣ Ɍe4`.=YKݓip|rϪ^GًfR<_MW hƲ2ZJ6M-Ib x'��qk@8]ݑHE3<z$/.e`D%G{>u,<K~R3_=w/.#JNW[B]ʨK$d>u cGRt[%uUAPN*sP9u9@˷=X,]TJ]K)u).]Y&G"-|z@zGё=_DCsɕ4 +/ yb xg3OVپkiz rF=mݶ}{[O�-x lz|H9'4hj<rk2򞱂F.A/䜹zO^@.i4tZ/%%4lRrJAKwj HY@TNYDNtR%w+-mz/koBGzI47Q`ʙa"c'bXP2tKn'71sLմ'=k!a0_>gfs}gЌqb惘-T`W6u s!ܳa?Lm�,kDŽ@'ƬݥqN/;VwB�ִ~L9{cEC;NneO+֬a*h ظ [׎xdN6}ٰ>?_t:sKXp5枋gLxҾ̽`R޻IJj3{2i~2J!Z:b?W!t~-jG-@N)fv<@E}v?6t WǸvG'B"tAD#2da;Ҽ%]܂-H*ۏ Xډ9툘߄hkԢV/4jؼvlCnk ߌ8tz'UBq`Yg-,kk ݍ[qw R#<<ϗBe̸!.WCX!:$Z|՗t'au:s<LA+[]@?[^ o hL<rhz駱v}n" 3Q IE.7"86X(>OiA&z]ۍ(jB=NuSʋ;prk XIAZqLimHjC@dBՁl-vLua{LfZT߀ ^PLc<E</ :Qv؆6aFܶ[PaO.^!D}+WslC0j]Fo߁bc=dA ؒieڵg/ !˜k/n?( WAߴ/e`[G͞#,<>+{Zrh8xg;wϿ]LKWcO<!Zzm/~銕|<σ>-E5ĹW^/ �}k~ũNzx_+))+ 3%McGHAAu �B(DGY]- $sHu!R،ТSy( 0k@نHZKŅ3ҀFDpF4,nDXA}#mH.EO�Kk o wⶵ3[VGj<laثs:Eo[~˶je O<+LUjÖx}pǟ|{ ',X( O Nj^\Q@}W(cxo_kdT tܗ o 9Y7|#[(yƇ}4k{wwDٷ}+sz\WGxg_,_C=4(eH))+QClCyB@$ t" 1./"ǃz5M A8cntG*>1MoeQ>@ى8xz`Gt#LiF 1<zLOxmPQ1ڄ1Zʶ1 'lGC\چE\j3g1m\юq*Qb7@c܈P _#V<մxǟ|ͷ %mVVnPzϜ%'>'Onp3x2i?.]6djkZx=/vu}wß5>}}}x*#[$_5X2@O=; x2ӜW?xXڳVGC-0FFfCa:DY:vD1*#@1`2 3@22Vq!1RS}=�41LY.Q�e<Ab<7; dڹ :]H>I''`&SDR,gDсX7e幨.F Ci܀\"kZ1n]5tZ><dVѿ`SPr: wA?ppk]r�?ǓSآA&2zCR=ju vg}/ڸuۀyc}5D <}[|ݭb }x[{}ß5UMle8s}mYsy\{_~-B[b~uVuMM7Xk,.J.AAJjsl &l.M[naA']mnJ: D�X>RY#�2^q ۙ R <&.]ږǤ׉d )FtFzlIc'Hz;y~bJ}fM57sڦV/hF:L% w!fx' o /GHin^?<=utҰQ퓧˙Uiݿ_sYo+O2m>O_.o`ML8}Psf٥yY{-lYz 1[?m-Z8`J-,:ݧkSJj]c#qBtbaJ "{cGgˢ.,I IFttL6ؐhg2n &GhiDBv#- HґǤ6I f~ Ln/FJ]SaPGކ}Hl:#M$MŲ�4@70QGΩGtqWϳ=+ hh0 ~$x^xjRwor' puhT s <90Jۅ;XW;ߕr<{7\kZXs=Mo0zmu^Ś+| 3x2DrГc=RRC{9z'V#97+[OGv'2 NaLr$D6wڨA$M`2\K�,>))zDJШ3Ht<Tf|ZN<7Cuʒh,x:F"hJ;#bAMs嵘XJT^}/o._?zsl+?#/įf<*ޑ|,\<(d%ױ^ El/+hE"h%,'h9U)LBl5{_~Y4oƮ5ß53X{lׁrm,@y{|^vy=|nns`1Ǐ:%4|�nΟT ;KP W3V 6s2PY 3kTԫp$$K3칄4A`-zR=ά@TG NS N)31C)Ѵ<Dy47vV`TPTv. 5M�i6u4NyoB̩6G%:]Sʯ>x.aŖ9I<xjVUW˗{dk 'Hs+V?w;RNa|:܎y9^~y<=ϾI$?x3apa CTA4@}8e9Y3[9>Y ~ϩmS}uk֮K%s:~Xgx?k_ANLdxw@c=3z1sU[󪐐 54K=lUcz]@a$�=])ڳ%2- >Y~ X3jMev) nb.k&&s=;TPUANiJ&bbPu N#54(%K$'7mͅH}OHעn1ZI|Шޣpr7RCsUsgxw&%5Qv#=wxf% )Vg2.V�hr6S!3PI.I 7Xq<jJm.<ixc)su'o: q7ch4I@3{ ^y!]4 {Dm|^x6 rlr!LC%x.8 /`'f7j3[xM|_cvk&\yNfn]ۅ<^_G0i'8rvgGdLvɧtLԿzߋ8y3?v1Ӂ,jB-&Vl8 {t$N:Mj|r &ky>ux7m82H࢑.ޛ`v-gHLi.~RSgQRRRajfU`="2=V$qw#69\=iWԨ1,Y="ӵג-&7ʭǑ?C  hmNmyz}Oܒ[ݫ)x:q6oT+=U M=Hc�ջ3]Q-\FSlt(wnq (MiÝ"A2L4)IIIIII<sUp sj#"-B*`9'gRU]ҍkNOq&)\/rzTM%la׉Fy"6V<M0lS7Fx1ay)ndĐ .*xrP]SWl <Pwf"5 7KIIIII=%@q;$6M`(rd:8]Gg.'$J9m4_*aڦ}4N&'jW T}f1~(Mڧ*Qi_[p47[~R-"uME%2Ջ q]$pwͅ@ce-3FlT%L656eu39#ܓiBĝmoKaHdq �hǎ/"ZεAHh :*Yu sWQswc ?n'݊6 1KS2^Grq8Z_9N>YnCd'xJI=j]nJIIIIylď ]F9&̨C&I6|J8J᜜"AM<NʲD'8lߌnZL/!\t<n" J%Ҵ G.z~W#D|iu(\z[TZ`S_u#zNljg!̰Ar R7xrC8?$8gP' .%%%%5s$ߊtv=yg}MvfC[=3,$65{{յ/' Rg�5XҎa b1DKL. 030X((Rޢ&1v޼11&?wfxGhbk}u{ͳܴ$x&elhǃmf;`L&VFdXqr )<3],>.`OA=S)cNeg$=]y9B6#B+.FΣ͍N# P 碫݅CiIǚ`?NF;xmxNFै_FDh\BY3ቹi J#~#(m#1i3~*uD>Y(h[ :svn&{;[1LUbmezQrYw?HƓF24Lq54KO6:;\X. ͚.q 5xjOdqm:0YjufV5]Zucv.fiƎk*d o7ؿO?Ŕ3@; O1&N;{d q<c]Jchk_v% xSN߷j_k礥Ͼ>hbmD*gGZH̑gE~y`H5=eNgl0sňQ�kJ|jkص߿ϗqiZK|IJJlkUKO1{!>1FvDaq9 Pu. ;9@m-:|蔠ڵ)x\"%7:$e"ՏoG^7ۡÇ1slFY=�o\FA'v ǎ~(L(4a.�B:d՟Ċv &:7[Z^.~mxM[9YKKK6m( {"MAeB%dI{mD= ]غ1gS+Y2ϮwG;ͷvbKY-»TcCTga{E- `X[1~$= %ޗc7*N4s�T͛f xR ٞI`U'iS𬮩i.J(N39x+Pxs]�. a/bRx#n(O57փ7x=}$Z ~mj͵sV6h&נ7)d#Dg5J9"F #rv[2|} _)/0Y5smo�DMXec׾,K6{oق:uPY݀N@ ՇNEE()'1m~ĥ'a2nfQOՆ<蔪֏X)NFij$`4[ۯ^C҈4tE୦'Ma?FXL7p2srmᗌD *P#ۇ_ 뿶<~vNZZZZZ̓gȀ}Fذn(U,pnasM'lU`EcRDK׻[,8KG~!(܋ p=.ު`KaM9v2\7%ivbY>$L7z&3RD_gME1 uo<KC$I){lQSz#%6 G%%[7Y+oSsxZOvi49]Sȱ^1 wvN۝9 [vIKKKKoXf>:2PV%y0 :#l <1(–׸̃$lC0Tj>U_zY 'ϟ*L~s#.||<.ƜUϝF=8v<$2gOCQ)dKY%3:47)ȺgwAŅP< z>ݜ^tHc<)x>?u�ӕot;o  <NI9LXǣǏ8Rzsș1xNr<ʱ{bǮ9ܰy3{\*X\.oҋP^Q"m۹d: <k_Kg---[8\O]ДbQI;3<Cr]&!4f[by·oS[S^ۈS'"/6`BKH ;(~jj1zV[7'^A$lj$@/MBɀjJ`G(23LMG*P)ًywZtVZijY0fs[ V9nS}@ő$_UմK;MrV;#VXcPpQSR#ng7vKYwvFD>l;,] <[j_sg---VpkT@f_M.,/Fx§Y-7;xB4dhB"һ=^ b=xa_m=&Y1,c[a<5֏>°QYL}[bמ\pHx[)hr,BڞNJQTQ4iDn;&{q]!-okjy;"t1.b}4 y ax4-}K.GRtKĒFvB<}>6T:M<lڗb%SAˀ?N?6+,?|[J+1mv|2PvO_.cܜ-quǑ VTaʢ nq.IX!X`})đ}"Ś'TG7~(xj=e+WI$T__---- <,KwaR,V4rr@h[pr ė84ؓ6 ~': Zvʫ]K\1~fԝ8q?`XړۼΜ %0KG?k. 6maUSw{T+�5ی1Ƹ<ΈDtsgd/:gjtVΖ%<,d75ZJ*;kgaA4ZZ.VYEOɢ&)']lwGc9C r#IEJ)A8p2+nQ8 /#nb vVᕕ;cA6`1q;2; %[d3,0c-In3ձ Tw<۪m˘NIyGLtL+AG ZjW}91ң#=xIJ@g>“Ru0 "IQ`4" `͢V LjכJ ^ {`CS}Xv'>6GOWC|3i5r efxp@7T/7,a5TA0=Z֣k[@O-----{DD|&EyR3R)>q`~&1C+]%x X Iڎۚ,u  I�2 ʱΘW w}*O`j(; "K[Q3-v2(FLάwF;Ud4Q�S5Ĉr~!0q<4xjݞ +_a˳15/Yl˽q;]?V`% ٵg|IgW\gBTɡPf9іGV E Te5M݄2 gmũ'co)|s.VbÎ*wX?GD{=ѽ(VfŃX~ ncyw:F(Zg*1Ӿ3#y0`jQX<x9oZ&e˖eLmZVZV&^zuNs/q7b%b$_f%xXԞmy>PuhYfXRl)9xn {~Z>gooy ܿ',h7oo] l&++b>jx !ρx:=t %QOӐ,Js|nxzZ  xveme}�O#,e TV!o~mB;+GUu->ہa0; (P^U={U5_棝E n9'эjӄ\D(G E<x74Me�谈;,32v?p<Tw}lVgf|[P>{**<vM�O~:{Sk~</ s}爧C:~$x=ڹ{^xKn w0 .<9ы9C͍<%JD.YLlciWW9mfȘ]d%QYUcNKҏ^"t0/h]o+@D<ezsdq]Fj"f(WD^mE<x^S78=Ư]EeNo8vL[,^\X蝅1okۚ,e(|iFQO;Zi]^_> |Duy~?seq~[? iXl?~栨 N7b x`mپikd٦[޿yinNdg'۶iV1k?9<)g4Qt L!3ŋHMt'Ix x;֒yOV7BW=1.bݤYbt"9撑O{i1|MCԶ9nI蔬x@`�k^yw{ӏQWÇz%xeLg=lrg&IXdw`J*FHٮx7,y螜xa]Ƹd] ծx�c8!Ӵ++D'w̄2@ÑC{u@'=ֶ  }~Z1k,c)%mzxl)mOS+8y;5ƈ'>|~nL |ɟzm[x.[Z̜oܲ厎ך3m8=i[;nK yiz'yIYG8 /x~M~Kq'ק{׏TvԮg| Вv2a<O:%۹[L65uuU~99zD4x9xv7Q <>x&ݑaN7eCcӴ {-OrFGM8r]z` _Mb{*F/NTbt3V 0FzwQi, P$3 $"HH   ! d(6^⼻NuV9wvޫrϽڱ,TTt;Ҩ?ŮY/ANF[t]&u)<;ZTRvQ חݴE.[B_-rSغ{v G=f($Эm'{ev2_9yl9O[D@'x}(.g|-{sHðӶJ(3`j:{Xx7j <i bj u!P:uC?}=Ã*N81vbObO]_~_mOǎ؁ oY߱m#2l&,zkMX؎N$j/v*ibQC7xb>d"OTrcX%}|Y~IԜűsocړ;a�11zZ @5K)M4]@3-)Өd-Q&uG}V"91E- q"zms(O_-0@H#y37 VX[~KJcK ,,Q__t=cD I`/R@'xk7%/UVo{;Oc=z,+hnvStY}7WPb<y6ٮׯ^u Q2lFs…<{ƦI% Ñ. ³@}dk%W <g!j?C<oYC*nMjLg\MoZ=$+rs;6 >ZcłO_ZCz^Ny^B'-r*x2CybIK\ߊI)cU'|zdRj[^c1^% x>o_,i~@ ۮp%lA-2 W78ʹ 6(Z1~-חX@ȗ8ՎYg1#Y_}4[8C9VO`zXs(' y?Cy }ݟ?.- 3RK&!0g9~ OKJ<ylp'vg<tf78x&<BsH G$IxSW/(IŊ.mߡn�ef?[1,Dd &y0}armd,TKm3VIӭX;pJY*DU8^=Y8>)kPЎsSX`#'O~e?5<Ŀ:I\y-h]9.C7ML+>j !1Weߋ/>ZV+c<E9x'_N*Se^Io1pVы {,њL.Oԙ3=c<i'Vu?#Ps gxm;t[?\Ͽ't}r|O>x2Oz|%Ch1vٵ?j7ϛ\TT4n<ک.i6wLb8 dLlDzIM&lvk' j#u EOqXɱ ARjXN& p dy[ڙPe,= EX؉E2%L(l ǝ=H,>9;F&x?J{]w>?sI$K/^/x.4~R LhVFe[{n6$EϤ&_04>2@es{֤dgT3O#V;ZX`O>$`-Lg `s,3oil"!ȑ_|T x"<CO:?y{O cX=I5j{࠺ a>W[V;ϙwϞa-0"g~k{%˨f|X�WxTo=ZIE L,ش]1;ns{$8u4j{jEI6V׾h3|Ju٤Nfv[ HtS<B9'P|B F;pgc qw&yb:16;ec_?1t$dd4tJW6[\p`z +ޣq)8rjaxR M:c=^&9t=V36-,YV fd'1<d2S=O 4Gwt4=fY@cB찺#9tu!L.Z< #3',$t t)O_}D 8/WPLĔO/޲xӀO#LrуZ)=gF�`7OZ=lIk&"cI[9SXO�(hQ'xj|'*jucFX"&15>ٽ]upzsHfV';Y*jNֿ+Ԅ7._ZGsFFo\SaLq-FƸ$k"cĕe {A�/=btGiȀofgR, ߠƮ?uo3+h.rղeZu'WqK7^@K\zecWS*_!Jc٦?yuasȒ}>/ KcEkUWPP~/awvO+Ej>]S tlqwjyK;Fx?l(3:C| DX\vO#### xr$793J%=VjI"BZ 8v8Bo_ ')﹊W~}o7>ǎ7\_(<Opg4.oXz9K:_˟aî+~Ulk}gv\=pJWWto_=ڱf;L6jur)W&ق{[S3G3PXAMv`{~4=pBdiJoW [~Z:ن0~_>oŀQ3H5ދ)s^@bҒDpZ>5VS87[a=N]~ '`.;ͯay,;x^<ժ9oy,x mGŖPQ3f.<Σ(\s%.ccmMW,?͗_~+k^+e-Pdbgv}!˞(0=naՊ_Ƣf>7:فiϳhyؘ }uvsߠ˄]hHjeg{%FFFFFFC䝄k"(H 4!Imbw;:[+ӎxOY>9Ԉvc@bQߎbNV<ۆZ<1Ի*d澀E2-噾}X_Z17Oɓmeb-߆HL#-'OL \r#Hk_Ђ0_)O6:suݮw{n\,2c=Yx09zvbm0yc422222S~V!,m^ lBr~RB17;-!+Dwjv>"@B-Ƣk,JbA`'*X)* -ۈ*Sw$F~o@w6bs t֢T /+cO&21-%)ɞOvJJu|&q|i_̔}tSwr9H5ml:QĻ{ODobO#####QIy*<? 11xH;0jCga&j)%gNhM'w;ս`%A% ݕӠr gxom#2 |Q%;653}cntIm-̑D~2>MViWNV)?i"f nXLp= s=[g=�.^2YFFFFFF<'d:y/@61،vнrD!fcotY$#'T~2F�YXaw-$hfج'�Ҳ: (}ZӠVKLW3]ԓ+ɶj" D)ml٨X*Uؐ�+i*jo=^onU@1:3n+Yr[ū.ԫnKKub8ex ?x}OimM(jrQb IEH$TZR),`Tvve-pelai% 5iax2٪hteWxtKI{&kl @$ݲ5EATY_ž`Ҋf Ϝz:uӪ,zO5cbZCRfl-3 ,:'˯4-\dddddd4&6"uQg ڐj!TgbU+[ns;3UNk\M͚a*kdcU,kY*.3VL']}pW>8d#(zl)}8 D7{ [1vGS+G&x%B?F xV3=o5^%/ EH(N$DJqvr33ܥOV?.$w|Y!ꌍ]] :-7=]VL!JqtSo tB@+cL D$n x:eέpJ'yx:uC`\wΏb<[ Gx4222222>-,?Q#HsmH h<K�TSuRfZF͖KK!;R&u6L0jA{[cIGV’hxƃ"xOB gd^JљW>/"F<\2-='#;P1uXS[ڛSmȀmK.V]f_ܽ/8EH :[g6xM"=R1%ԆFR$Lr,}*h5TOG<}VY&=[H5C=`gwbW3v3} 5IVP�(Ι{5ޓJ76An3B x422222]9nZc<[(7cL έCJ~MoT tJ*I!d%^KLluZbw_R Z}XJgI%%ߤN'3YD5982v \GLYN u-@Bl~@qܕى=XYSo>5< x.td?%-gk7E:$Lوa(qF$$0W*LFM0'˘8e,1[2m3R3�7ÙYq@Ezvލfǃx ˯rI0)oLk]W:pf> O3XIkp_:]{sl}Mx`+ U61ŽŲ|nT2F<nxCR؎ˣXs?ne-xlaK:1caLiV1dEG1u1L+=e'0uQX*KcfIL=*c~ƲӘ!3O"SN`zL8!NbJI&ɲ#zS2F+gEVq|Ø)甹]Υ 3K-ZEw&QT>ቃ0 O2n(8O|3" kf";1N@cB  ! ! @Pm:I7;w׷nUu)h;Tnr|to6X*."wvkza{}i'ēB)4oVj?Ej6M>XOsRiQI%%ޭHV+K-s]ϑF^zrQR|>Ja7Yzxil |atouL硈x#c?ϜxgIEz,^k2dyē BHgr=ZlYITql=^k+|sI:--ZR~[ZTTF*m)UK[KߵV*~RR͚W:[˷~kaqg[HKzjT ZPRzzsSkHͥJGjJ0kRr:Ij-mBjDjHn2"$'!RgS{\0Y߻ē B XOB!xB!ēB!ēB! B!D< !BI!BOB!BOB!xB!ij}6[)!Y2Fd|Zu.}_♒]3g���Gϝ;q II n@!>~Uǀmg({_g3..��Q<7(9x>|JN2u}yO'��O[ t<}#|'��@9g~~^@M~}O�� ϼ܀ƛzB9e#���'ɾG<��*x hO/SQ= ��x"!xVy' ��p%3oBnݽf!>}97 r.[&<-IWinui`{N<?#9x -)��M: Ovd5A&mKs>y\TX˓>L*G89{, ��!!H2:N`XSi1<lޝӲ(֯/7oV֬nMKFm߿C8G˴Nx)֭s;7Jrr2 ��Wt*ii˯H^;wy%Ͻ{oSٓ.a-ZبOÒ-Q˴3|ZuvRmCv}ZGBBȣɿ/p& '+n,L< yZu.n})ߧȧ&X۩.uk=rCԩS_ʈ#O>͛7;&XoXI&I~~HnڴI̲ʉ'd޼yFvnj#iVC᪾j=O��Hf_n)'{sr<,12,#é$ؽmzF:l۶M^4nn wKTo֭汎23W_s?FX^0Q~L\ 1l:ޟ_0>yveܭ_3MRSw9K5\]1yy#|11z.Ll<;Vv}z׉]p!ʹΟ8q,YѣGiӦ^WTФ$ZZ��xx~TWb9+VIw{8UĮ(:OI*Ҭu[yo I2uKgd]8ju<Ӳ<W$7/Ovfy:dsUݶ_H=>lev^c9rD-o2yZu.*϶|ڵG[:\}O^H\t>}ڔIoE\VE2_XÆ sۋ:ִ�@eɲnW^56K}x7l$^|T!]aL=^Rwo𖦷wHJvSfZs=3fΒ~$y>7ifR˴\i7QZ8 ~ z39y%:OkzwNҩZϢ:Ι3LA֯#>L>ݔ۽z.M]bx}wl��Ͻ*(~ ]m}T<$;Oεכϛt}"w19}'^s/b[ז"= l6yS驞uzxT<uH߷vCA%r{;?/MCCsIGv:ԮxZXȳ~tǍN|- va$5jzڳP㙑R$}D<�i!sų|pF:K<&''GX߳Z16m4bG=uxWT<23]fyŴT C9fwAF~$&&s"uuo-.+A!z}OT:wwf2z]i!oO?qz]O$C*z%=1H{<݉Rt*>��ox:^)ˉjV]7YayMY2֌ԓ-/ǔKu!`9A(y[L2E=n)WSTOߑIyf>plC=#SM7Hr?\lmVW+(4Ǿ׺ǎ5^rJZG2[{eƬY.bbrȐ!2rHY`<yQG%QjTU@+V^L]nP'?sa-~ ��e%gFFe'77Ǥ4&?Y&;;SY*:%x:.3##QG-ٿF{N3e*yz No2,y78P=IH׿쫯$M;s__FYi6mT(<X`jn^t>y\t V}rL���z!!#"}7k0<nxjґ#MO]G:O4zNjvJ]ot}G~:e-sŒ+ׯ=§N3gNl /\%Qy{cz577:O˴N!���~g@ƛzB9:@ǻ봎՞\}LD<��Q<v4')}=`'��@9px@o_({�� Hs7 r*ʾG<��D<wH hO/SQ= ��$o T}x��xnߞx@o_(2ϸXs���.۶m X+cJi@nc{o♒]��gLNN H&^/_lA[)HLL0un3SQ/ig\JE!Yx32 81Jbc6wq}eѦn3SQ//I!B B!$B!'!B!'!BA< !BY< !xB)e�<_ �x�@<�O���������@<�O���� ?i8IN:ŧ �!#6:�9clڙLcǏ#�xsmcO�@<gZz/]R\O�@<=}˷"�x"JAA=fI\Zf̜%SMq=yĮV|eK^;ZgNb[1�� ږi5oB󨽟YGͼ _:4Ls01i2igұ�+B<13KX5"yj QQ/WN8a&L"Gujh֬1G7.go � mMv3s&Òx9}/]fֻdr3|�P{fV^dcy;w:W6:oæxfZuz̙.go � ♑Dj7tOԓx>rL=;v2ӛ..i>d�>t\4szů'm۞r!; }h:n5t=EZ U^nk�xꉘ.YW(f=|nK;tT<.XL +[\̇ �' T^=^� ⩇uHɶ�su;w[z5 �C<u=RP:d%?pp/.oc<&�@Sikc)u6G|,'ퟶ8R�B^<=|5- ܮ4arU/)Ӧɢ\,if:-]5�)zYINUu>s/m{QO�ų<u�j �x"��'��x� �x� '�� �x� ��'��x� ��*TB! fIBHELz<6l(si*U[{7h@/Ǐ%11Q.\ ژ)}u㦛nϗ;CFoxO�Zj8:s-7p �P=}M^^<Sj*t]~ٳͼ{ʋ/(aaaOԩS8vY6lX_Fdܹzu֕QF9UT>0aھ>Qz{'QQQrQksRvmӦh^{54ib~<{z]�{zI>I�2 öG^!��!,z{һwo>E�8'�@pa[ǧ�'�� �x^.W_}m.> �x� >^٣^zF&5;wD<�D<�/k׮uHf'� '�SOT{̣~j/( �'��M< FF$W^m.Pϵ���&7wQ_[nf%O�@<�٩S'#z2 .4իW7'� ��Pj<zpf޼y'� A~w2GV6kӥgϞ~.Jdd#�xaÆrUWIffGy4z/`:uHBB:�Hvvԯ__222%**J5j$+W-[:6zǴ5kҊgXXi#4?%%̿kÈ'� So[;楦.*UB< hرDDD8u%''G;&۷:8-sZ"]j�@</S<Gaz k_$jժҠAg̃=^eUe&hYVC%n2JP|>qåQq{ OeDQX `� ":0 303y9̹v.3[}o}|1~n-2{9ꨣ_nGvsk׮?9M>}r=X(϶�gͳ˻tWCշo_}pb裏U/O>9o){ B'EԩS͞={HOz7[l1&Miڮ޻wouVk/B*O\`N[xb_L81G<Yve `Wx �n&swĮ/6z[~饗Cx '>|̄ e]f9W_Y漛>)9sXC@j޽{xBdp' ?O Ȟ@?}AhGckL:ݥ7n-A]Unرcg۴8*af27Mx.\0󨜨UɴiD<Ahjj Lg8 rFOA$�:Lg|U<cbO(> u@d_luԟN2%Vx ¡ %6l[e$eAQJ8wOAv&a5 (bjɓGaG}ԦP@On{M]]U$lAFK, /`;G<I 6, ph 1c l( ԑ3zMM BG&�"Hz#4r9rd}s9'qT;t4xTO~bziѣmBMō7h{px D{=CSS@ 'ֳ`РAGeD<AD<Ax_0_SASsY" " "NS T�}K"?x7ӑ B" | hr$uQ^կQ&v4)k<ӆ 3߹RSN[oę[n B%kj$:_)8 [D<Aډx1"v<Hn>ŌC?f:$2O<񄵶cj{UM8%x2 OD-}͸%LCUV }x Txf\F<! w/'|r?lq]v5<L"\x$$QXtu e7c66=P5vx'Cu]Es=7:?gD$0a7}$I[vk't%tK.ytNҎXygz B%0}tR/>(\uUt" %&Y҈'ɤŹ3*O<Q."i"QbBDSO37I&=3e%WD2MwvQFM2w\\UUe*m Q ĉbI/ik \Ri$dO,g}nUf‹/< ~L#)P@>\0D킸9RO H#�Bv۔; 5 v]Yirui!Nq#/Xmt= &D&ϴstO2E]dI-~yc*-+ kq}EcrE<A*@<KxRnjmz]OifZZZ2OQ% ֭[f$gb:38c?ک5ԟT|vΝf|;,7, &u>/xc.Qsݺu @MegA"9:pq$NA(1,E1S8p~ g<4u+rPOH2*kZ2j/xV1}i'L1g'@%!CӂP [䞲aÆHR`i%/LoG<K11 YGAF/BҐMWQx5)|󍝣2*"B0zɓ'#8̛7Ϯ?m&exmF3OPUZFRʛ7o6\sի/uuuuv-uc˻'2xpaÆV3霤bR /0jGaz*2.Q?e\^bQMMMyg^s  $#= ?Rwyut*:yMщ'lȑA;8K%K,=#)b�a];w$6+C'#Q-ڒG�YtJ[>:A,ʱ?8 =ˢF'b'/X*-u-9&2j^ ~ s1|ͭz)n4{Ɉg!^s" T a1cƘ{̎@FU+rj1c%ESLv<<$o:\$^gAL=RW45䃖VN7xΞ=g?#|Ҽޞy{PLA(/^{5khaPCQm$yӉx h5䃖VN7x2c4sq,^o+<HyЁ{<Db1Do\7]AD<H<Fy%y͑ŧzʎxt2xf2H7@y睗fp/N+NIAij3k.--í\o,rL(ag j {)t }7?4oB AD<H<A\Pj7GIBS= U<e$AĄQ|饗rӼx Txxy%y'A's:} z{12LeAQ``!Ԍx>e*x%x^BPQv |В@7[}|HI'd^~e:7Aʋa9<|Ϟ=m0d<x%jWgP(% xϥ!7BPx T" B!) P(" 'hFd>cirS|ט\5]Ul޹6b~ͷw<0jYfǵmA )݀wZͺ]fw^qg._V^dv5}g{mYnٳ3Kۥ&3afWJ=a=fڷ򎵣W[vss2RO kۍ ~3z ]nom6rځˌo4uOܯʼFa[پ{9\ٺK~_OA ϰ|ͷ͎ߙW776].5|l*N<(F!:YKRJBf?t8Vrv;K9K_k=cv-6hֺ[W:-v.Է*eu#j# "> !Η$/7X*3k65g.Ӻo0Kj-A-tNmAl:amF<}_ >5sȭl^oo1w3%AGyeyRtlo 9"P YomL<s~rU^Ϥ}Z^#}MY*2αVmܧM_-�$C!3n;lIc!{[eZۛ{]#W|{dGvxiuf)dvOSP(:�նEՉ LȠ([c3wZں`lkmdZ't@$~5GNuvi~sY<:Ʀ ԆAob?篃8+l_<<fMd{^L:VGhJfgqeoݶ_5r3iQmEIrrNjc޲O2gP8P@v Ygv8?^˼ws{{!,;gu |{҄4Qs8D|p d܃BPTxRI/sj`=iժNb⺠G#ttvAbNWۤv AQHmPGԥgұ:Z;*HGt\Yĵy)/L<]8P(̐_ xidJlsxmg]6=VEc']~|pͷW@0еr}k_w_xlm>!(" BOv P MI,꛿E#K't;ǃT$f vYA 3qfK\PƨaGCNPPE{I;3XJG+~] Q ϴs?5$ ͩhx676r@G( xwLM;|Rzun?-{>J;8.zcEx^e 2--PйoBPt>b-mT5͠t0)UHЕ1'9$mV`Cꃘ6x #TIU*3E]5R BXҖdJ)`M}"ue!lǬ9(H)a  j<e5 %SB7ݖO7}HWA8H+^Dae),[c멸񧭣-J(kqЎ\[ŵ6ˀ Fn HJ7rl(H'7e;bgqe/#wQs_6_rBuy ˰J<ӎϴx2W =v r$ U@<kΈ_0WUK[C26>΃SKN<dZ$ep;+ۅx6Oi6hBt9:M~=[,uitOA2hj#QRDFjIwI "Ԝ2IMHx7O)A z.<Q8Y˶}>xk13&9RF'pؑv<d%iǐVc \Mcv^ /a M?t4Yk1[k{qO ?&;=8<ᕺLx* deF~5[N<KvBq t<l>j[dYw]7][ 8z(瀶'e#f[U⩓[1~sI`QXP v|ڸl2٘ؾB} EiT7jcV4o:OOBzaYS׀H#o%h%ceU<i{k_f t}s ջ.͛NSSPTxRdJcyZ [1~sI>ZIX϶=xƵP_3BQ:o:j�(qxӉx* E5yvhGފKъ*xYRQ+LP֛V!$,t" BQ!jݨgVV?DVֶ?iwsC9gT 5S(ˍ6 ~óy9R)) g3~d[|4`ڪ+3϶6SQ2Y|y36D-n 8o:1*uؚ`WyeT(@<8$,f ݾ7eT{mGe;~_Lj_n {Q6фTR{C suiuYD< SP(:b7BPx* EEBSP(D< BSP(D< BSQ|bj}1PRF2?tyׯ|ma%�"P(&g2>=Ѻm(v fA0�Fu9 Tx�IlpDyP0 e`ieU9ժ0w}biP$vp.1*'g}Oa<;q8XTƝWOB0-sd(e�Km(vJ4?m k -],d6VxL]_kj|G|`-z،zNU8A{Esp(O\;&}hul6JpYnȸ∧AbQĨ^# fMc<Jlݖf?l6TnG|K]:ѡ36XBG4cƶ{ZUc- :7L|k]g×&/a�:LRqv;3,l9gL2wMR66}2s^'oǿty+˾|œ1ޞ<n'sB</,iR =I]ھ|yopo#L]N2=0mqF{_i  t" &T%De̔DIyd_S҉4 mG3C;DY-@%jL<GRϠÄ8v|YɾWcMV1=`wWs,N\|N(ǐByd[Dyߕ13n_Qē)QRͲOL|<ob [4ͅ.˾s@.@tt{VHvtޜ7(ׁpB< MyD<Aځx2cO?iߛD_F;P5tSZ҉9v ޝ푦,VnMj9K}!ʙ.5>LFsG<syptnlsJO(I[$ Bj<l]tCc֘VU>uBAue_sVUezH3M*K&a̼/ro{8(" x@Pq Ň5VIb]2WDrSh;fmod:}NCɪxv[e5>dʆ}r8"DPAEF ?"x(" *`ʙ GB  D  G�r* =3KU33=3ݯl8Ooކܠo6 *ss,;7tb9S2{ꝛc_#O1 8K[RlȬlIɻA� HEh'“B @xb(yL23"']v&گZO!y03K- "i- r1T輼F<Cfy^o5l4tOC-&w5zExZSs+<t a"҅'N6? Q ?b,; ;,S/ݧO߿oYfMu6W_}%h"{̙30at%l审kNo:+^'Ԑ&Y`)rqpz-Yh`&ծNÄ '9" @�@p"jDr!xxb2 0nxb2ʹ*lz&=%k-%YNb!VѼ3UJ#3-C&l(-sDk=uSs+<{_&-�  J|]LHhkז"EHfff͚aǒBIHm&UV-[ξ^ʟwbcc}?z/_^ 'y,{|f.Cy&tݯݫaÜw{<1t>!57s�@2xծ*"Rv*Yx J V>;}X.xfn.Cqˈ{x(Vx"k8[.J+ 5"<\zVxDnQK"[|4o<Y)V{?QW0jo"<kժ% 2mڴInf)< !K6m;oyNN۷o?o] 估 OC+H;uP ֚yAaT&O}yftRF 2e7JƍL2CIN|%\"w6>Sz-[tF=Ξ={}rW_/Çw,<WZ%]w̟?:!Lbb\uU Hrl#Ȉ#(<i [iӤyYRre2'լYS+'%Ku֩uz 8P>,ӧOWB382DChŊ3ܴiSѣnKOO[nE̙,<.\} p^x޽O?T>u-ZcRx(<)<i)<cǎ2{liժZgRR-[VN>1zju0Դn:(8*T9qRSSwkܹ:-<*UTQ"TTFCzm4V?+an='u:t 111R~}uB#<L}Yf.hѢD=is!ϩSl'Ej֭+-?Cω'(<i4 'kFyIOOk$p֭[ψzx")H%" :OՌ:-<1̎a>:!:o>[Qz饗Ne׮]“FQxZ1xb&!2>>^J(!k׮5r/r/x6iD;vL}+8TVDӜw8z{YꫯiNj׮]*avoŋ+a^„전'!\p 222tRz2ydc@q]vtj6l8ΓO>3MECd"3:vLY`GFm|C~|X)< !$gae˖>!òe{qQ'!Px9Ru6Gǫ!{a3B'!Pxxի'  OB$ OB$BI!BI!BI!BI!#<l;w<ogXv(< !$“BCI!ap4Fo'FΚkiPi4Fh4FIh4Fh| ò?CP5h4Fh4 OFh4E/<9Fh4//;/. -!( C=!QxBn !G[B?yBGvK?d!B(<y#<FN=FOZB ݺmc[!zUdmJ_c&(ώ9o<tunF~ Ǐ޳gyOվ$Yw>|wcĉr9qd26o,, 6:={yܵ˧Z{gƨmtñB/~_; HKߔ!QYtLYb/jylB(<ƌX勠i.Z.51׮ ѝbΞ/\X-I ii#+炢8sXt:δ3_D?:'mdL.%ն3C#:;cƍW#=#C-w!t OsVy"$5Aˡ\r@@.NL<oɓ'UT1|e[238s:zT, y@8vlٽ{c`ԩӬ( Ӯ:s62-ں+ =lْ#<0 a!\"NӍt#< :{h ˎ?ǝ޹KM7?1r','MpEEK2@.Z,ϥ0Iȅn*wVv lvMغm8~S}�>)sI?NQ >p||NI]HB+M<סkh?ێwd)ݣun"X\N~7N>]8?Vt8~MJCtFNy{8FTMMgDAMg O6]U Qx3sV?"D) >oOCXڿHĥqs<;ȧ؝Fs4W<aX鳽ʮNZ>'.]HB^ڹ66Yhgy #JxBZi^Diοݔw!W/WqaO@`$H`%2g<Q?D\! |$*TF@C|O {N^i1K 2DB菂skL۸Q}i\cH5*<2F>. /ug玬,??8E-_%i3QxƸp1پcz5Ɏ >3}9nC0FJ6+9 yG!ws<O|JO OB/<i6#S0c `"<mߡgu"ݻ'%S:unҒ&ezLjfN\Z~+FYZ:SwB~u!tn*|ιDgB* `W 7dz=|y9?*Ǔ“ O۹ s<w97>^ - Qx"1G˖Pu]G"j== C6gϟD(^_kQ_7n3fԬe+VN >|M[}H:GɌYjƸnf C偎:w$,X'8QQv')< MxZ `ڹ]܇Y3fծ:MQ !l^A2u0B%K) A*<B ! )9YMPDCx#ިSf(<Ya!lV`~ e0qμ8d!B" O!tBD Ca%QxB#B.Šh4FтxF ݻwnݺ|RreYpzjTT̟?~k׮-jՒA6m$7|\~{#|qNk֬R(_>ˮjIKK G)d̘1sN͕KJv[awΑ֭[xRzu:ujX _m|ܓ9sn{ 7\(Zn--ZVZN Ix&''gy'|R{{gE 7tL0Aڴi~|ꫯe]&'OV+"w}<㒐`NdɒҬY38p|18 )SFݻQQFI˖-U:tXB>|æLb{(믿.*U2+>vXiڴdddeoܸ(QBVj4jHo\~ZtX>>9aL4颮.2�Yz6={Tu+WG<is{qʬY˷c7}}6 z^{L8Q+套^'xBNywes)c%&&3_ݖ_~Y_]5o\ƍ ,q׹}2w\q|7>7nܨ}ᇍE~qotԩs=kƩ|~qᜭuۙ@}?~g=xf کu_xmve3,R|G*qUW)'OӦMSsde<bY͚5o߾*:u֩uzrLxK.1"pB 4t[ӺvѣPPVa[F+9 OtR"wlV-[r^CڵK=|b5j(sCOvTVM -[Hb|"(m6A:D˖-D( "C Q&66Vӽq7P?P0kxé(<\P88t wurR^=y= O;v쨞 #))I9ӧO{"p4иvR_tY֯_"$v/~"<-{ |NDH$ŋ  o纋h%ozUxϿm۶JDi>3ygCOv"+G 6Ç`}|]ҥUu Vx#7*T)"n/$^OvB$ �Ox"Wቼ+c=_N{ҡCԯ_j'a:hѢ�pcǎy=W@DHA Os'^S=}Ux#F[5/} :nlo{!u^;@7`:bwot#<|1&q ~֭~3TU'Qx�Q$�-z�EOn#֧csj@�o>WRŵ �L i9iK=~j;ȯ'<Cx:'uB9/]|veCCI T-<WZtoڵ'%ۡv:E_tO NPӊ9O9RSyjڵk|| tF\3gH&MW^w^Q+  �O#HwrRl3C$0\+9!,<]j/W,LBq`F~ `uB:ug9&`]vLGXp OZ<XO\9N~K(9^ugVov�x N`Cv9@8 $} *UJӳCِ2"DֵkWtЉ!O裏`ƌj1N#eGTAّ/]dLݝ9sш&{1FG2W(~#?gc S( +nt�Z{=~~Kx^(DI!0a OB!$A&abr| C(<)< !=Hg?A''!B$B!B!PxB! OB!BI!B'!B$B!>}eBHYfBmB)֭׮][)">˛5kR ³rʲf͚|/;!^E6IIIҼys)]x2`�9z(+w5oB-F iUk0 WN1c_&e&D2X3&3v2BZKC?b,al!ط>|{sν+$799yN>KH1p)ٳzVxx|Ν;CĕNY7.`-f2iUT ϢExt/ /^H:udܹ/7nܐŋ˦MX )g>,O<C<zעEYYX R@7n,znԩ2| ͛<rssu6Qzuի$%% ;wHbbHFdٲefٳup@$$$^\|/_^l۷'Jrr}NDHIO_~v hff([dn޼)ڵk'|"{q~ҥ*xі WiwUkXdeWgjk=m۶QxLMMՂȐ7oި�3zc�ù(2eۧ.묬,Mk̜֬9S=z$iii* ASN2~xyv({{<,,L.^=~IxZgNt`´j*ZC_vM߾}+ >\E˗eҤIn1&&F_bnڵ~ O=ۼSiL1kY6ľyy+B5h'^b!''VxZ]ʭ[B %(<7n( R \5k֔W^ 6Lԏ?Nwަ<s뚾rJ2d={V=6n)j۝}vDHI O &B8 b�V^=\,8 S_mީ*<o;otPWsԨQrr-BJ.\Xk_|)=zѣG[CYue-c9v--[to޼y2p@ٵki[ ^Tk1  ޢk׮)y>}oN>w"]VbEsbef xI>Ǜ߳;]_3 ӎ�O*6w]9By>baÆEb=6,E Ć ^뿳4 ~5m4=nذ3P^j{-n>_߉vu5}ϟk<*|xlz<v,l;;Tg2tP.ZĮc]6g)OO\$؏ ڿTRE䑆x%lA'<1رVwʽ{dݺub ,ZHc>|( &}_~PXlC|*<H\Y{'BJZxZ}qlpN6+ቶ㉯j,Nڮ' gӎϝ;'V1Vo&&Ny9!;VW`v1XYt-&6<wLYHw͉?_e�iDFF֭[бovW;<XgĈ1 5j;t KVv k;!<z'Bʊb:gg%<?,xP=7ڮ'wz q [^=5L./r ͛ [ bES#/PxB!҃“B!PxB! OB!B(< !B'!B$B!B!“B! OB!BI!B(<)<<]b~/R6_!Px~ܹS:t ҺukIOO-ZHrʕ+n;wӧO�ѠA9ydN�>8/_U޼yCI`v꛸8k_0`TREׯ/VrKxJժU^zڗ}3%>>^N8!?M6IJҥK~ `2k,\^^k^e]x턼/s˖-[dǎҤIILL$|0[bbblȑ#{rm9| ?Lԩ 6L=z$ΝFIJJ gQ!۶mk�[x4nX ԩSen b3jժIefuW^6@ܹsGĐ-e˖ig icƌgϞIBBzsˋ 'Nd[މ˗׉(h׮LzsK.  /^p .vTV-=z|Lkkv %K{ԯB>l`E)<qիW=r䈙6bqMPXOYQBk�KMMnݺIFF.x S\TTL2EӂҴf͚̙3u6b 1?~<x@Ο?x޽r) S78 z$<{'BJKxϟD%` �]~ܼySڵkb6m4իy4ͩYc6e5#/~a>s;~ ZpVu<4h Q,cUiӦrA C=�qF-={l7xPj֬3 uq][l\�q5}ʕ2d9{z+]?3P۝}vDHi OLf̘,ţӵkwX2>}L4-vRq ښ=FN !+1X}ބ&ƪ'ؼy*o\ OyzǭGx>yD֭d!v--[t^+ƍ3lvBACa!p ڵkW<>} v'ie;RZ^D#^Ex *Vhvjw1H�*<15@Nm䛝&hBȇ &ZRm$<<DΝ{aZ9sPx <={b+<5Wg:u,=`l6m7lg�KX24Uxzw"$ aO"=5^N%v dsBȇիy1niSu´K.@=vs #<=qFlA9�iM`f\c`#f'Owʽ{dݺub .ZHc>|( &}؈~z[qWXlC<>H\)<{'BJZxcoj7ؤspdBϮ"<۶m5cos`\~.VFHl:(-ēc3�{/E*< ,%@+uV: ۷O"A%XXF 5jpH܎el]텵^+6+}VDHI Oc9~sӈzDcǎ{ /sڎPוfeүBl/G_<P#vo1'!B)5(< !B'!B$B!“B!PxB! O OB!BI!B(< !B$B!B!“³̃do*B!ԩSҳgOZKJJ_hBʕ+'W\q;߹sg>}Tg ɓ%n;!?ر-[&ѣn.]*Xhv+qqqA6mf͚IjdԨQ3 @3f>|X<y"g4DGGˬYsyyyZx*U*³m'}$AI)iz-111IٳG?Cٸq8p³֭,_ܯeҸqc)((sSN绉K.Ill7o.۷o7͕:HեW^&<ܹ#"5e˖igϖ>HPy0 IHHpXOQ$o6'N(ɶ9!%<]=K,kCCCM"<a… -֪UKF-/_dBX ıXm>3@o޼N:�`fp S\TTL2Ee߾}:deei3gΔGIZZ9CxBvIƏ/<KDDݻWaaarEqcdz0; O+މ$<QOT}yFQy<aW6m4DիyX0*</^hHޢE]|ws 0n8Bw�xl`РA6 o'N5kʫW KǏׂD5n3g轮+W!Cٳg[* k))ı7቉V8;]vi !`}&<}A/__~ܼyS'[3fPxׯ_I&a'֭KR!v--[tg0gzz:^RG߮] Sg; O+މx<4m 1V,X@+7ቾ�BCUVk|V:֭[A ]VڵkGYTL<YÇ/]śnm+'ׯo`Zc#6m7lg톇}zqw"_e[o=KOSweĈ2vX7I'!ĊիW`\7AXuk֬SxCG ";OO\$�ww~Rdffjvcb<1x}V:vݻr=YnXB=0Çү_?0aއm`SDZʕle;RVIlC{ò>ڔS}7ٶm[!ϙ3J]/:{<tb.ÛjPx͛u`4c"Rx .�ٺuy7vÓp|ӧOW/L5$>>^xD@]텵Q+6}VDHY[g&O?IӦMOBv ;"V#FiTB/݉oA:>“B>0 bB) PxB'!PxB$PxB!BI!B(< !B''!B$B!B!PxB! OB!BIY~Rr^;5!Px ׮]`-ZHrʕ+n;wӧO�ՠA8l'}�uucO{)< !%Ν;CkZn-ۭ/Q[z^^Cjڴl߾³(?>&&& -fr+pTREm;!ܲe0PxBJ|'NǏeӦM:_tRlذkׯ%22R&O,= =11Q.\\x4nX ԩSen +ժU͛rssufRzuի$%% PwQBBBQFl23mH3f<{Lf/˗//6ۃĉ%99>w"Ozd+44{uv}L !Xm۶:Xm'<srrte_-?gaf(7n,<SSS[n:xz!p.**JL۷o4Yf2sLM3(N:ryw޽r) /j)))rWgalwVٽ!eEx:}Ocx׮]}ժUȦ a׬Ď%`DDޢD `Y(V Z{MC9g]{x~3{={Ͻ8B/J@@f끁oJll>d6SL 9 7~x/3&&F7o.Vݙ3gǵiF-Ipp˄NMPWGEEIV*[i~Oo}fY!UN(>'Ĩ;j(P*u!>CŲ9s$M4 ?{[nɦM$((H= Bʔ)j|oߖٳ�m9No{(]q#GYb싌'(cb]RxP:ڼs[턧vD?]ӮCx&sҎk,'25yf~8DsA.~@ `GFeAڵMRxzӟyUTxm۪ﻈ7glL3#X˕+^iuyq,<`̙3>dNӝNω)<d<:XFfm}SېUX~=?B`8 u#ƥvwg &Px&d<aă xpbk׮Uj]Q Lɓ'RR%Dٕ+Wի-SNUñcʅ ƍҨQ#޽:. en%|7Ա!}#:VDHrv}Jx5I'NP7e(M/'!W0a5jf׮]۫g1O #F9/Pn`3 O KӧW_M`}*T`T;2X! 5`�=Da0R-[۱mT#+v{xxhBV!Ex}+$9E\`ԩ“+Xt;i$sx+HZ.؎J=jSxB!@I!B(< !B'!B!B!“B!PxRxB!d <Fh4[s,<4Fh4FIh4Fh4FQxkH/.-uMzkA\r*U*9rcg.;vhOxj*۷oi.Rڵ]/cƌ_D I"y޶m۞̕+/~F{ }_YJ&Mٳgy䱍Hi߾\~ݱ)<7o,ժUK|>/h\RfMI.,XPkJ K2DDDȩS^gڴi>M`O߶{nM6 F{Q̙3߇zKZn$q/kР3-2p@9w;vL.3f`ђiӦOr%Yzk׮$eʔI .t^ek7o^y8x`o>Q-ZTbbb6|!C S(<!^7xCF߿<j2~NǏO2߱wIuΝwޖٝO Cb1e6bul,YL̘1X QF.%DDY'4X|\|I(&|iڵKk5Xe8b56%~z\|O՘Řjcq6V.!Y OͪTB8HJҥeO`~~G̅5mŊ=zle$((Hnݪ.\X+ϟ+1M>+V:_B ?9r䐽{vXbGO_|fY xjJa3qDז!do~K8=zT?Ք)S>?s{L],֭[׫)r?VMYڲl ??COֳh1A{q'<StbJ'MxVZP%iҤqr8ӧOMŋ}xC׮]ӏkѢZRߴi13eC&~Mk?aU-FR/ O3Ή5Ȇ!v̙gއZE)M@xRcCc.]߈} 8SEo)~ B^vmYa6]wرcȎB2h/96x> u[\j}GٲeS>r&pwPdI $7^ʔ)L& k Zt !/G ?B'[ߝ,h4/k,'2qXqND2 t"<ވ,owEo)ONڲl>/]s6M4fN?V�pmnV?\A=lRkBi3aØIJQΜ9Yrw':^z׹sv,<ciСC>dNՍszN4?'2+Wmȴ\AwqTxnܸѯOwZkblANڲ'τ&Vl_tNZ1h4jO4o+įS1,a9CpW I͏Q%4c$ 1iVj "꼐1x޸qC*T:>ꓦN*_}{G5Qj@ԩ:I %n5i;P OfYXv߳g0 <+.Μ O 5OX|ϓ8ݹs4kLAWsneyu7]'w?WXh/96{۶mދu֩Tm,T' Qfo.o:|MA"E$::xD,>5pcG-2 (_^8wߩ5,iY=h||4i9qР=ϥvdW0 cJx3S}ėk߰aCu#gU, Ow4N!, %믿3Xe8bu=̄'D24jhoFu]Q-d&F@/q4 7Ԙ`4Z'F%c<y .b~"&ay>r,FIhiOcTR뒄_+Qh4FhWAx%4Fh4Xx !B!>@I!B(< !B'!B!B!“B!PxRxHw AcCx!/͓EJ }r]FRH!Ov^J+e!<s-v8峍#Ow P9x:!Iٳg/ծ]=˗/+-[VV\NtUqF}Ⱥu<K,)C ѷ?~\ .,iӦM3}'Eɩ'9|[k׮j$ŦnݺRfMSyMiذܹS?%01:u+Drʩˀ=n8ɟ?<}Tm۷5eÇXV-u ^xƑ#GFƌN:ҲeKIҤIɒ%͛W&N:tcǎ.qz6eʔ$=UTr%u=dٝ!N1i֗v1o,?^ hff + $uk1|/\7Ӟ={,&)ƀ1c<#<8W)R,Z+Dii,;V ҹsgwGؒ%Kzay38w>a[%O>b͚5*w^9]ts$Ir*qu9vWݻwKΜ9ɓݙ3gw!N3n'<:'B%<Qxeo];bB&#>>^.\ٳm ;ቬGr;4 M8OBU<4Oŋ% @>N?TwժUS7꽰4h '0 4o\XΜ9<|P?M6jy |@ &cUVr1 ?*}fY!V}(<7}.=7o_0@zUk<aȒn߾]R@U@I/X;<x tkDi=.hll ,y:!{j9J[&0_tiF)b qOB(x)STwxP@wXxz뻝4FikqDxk<cq2nZ \ ?v @4iUܖ)SF=zXx⽨WM:</YB O`m۶*SY9xf˖4\ruhf`y 5UWXxz;ۙ3g}KszN$ YybJxzc k<A9d…c�2؇sҖސ^~qL>eC3mƥvEM60:qotPTjU=Ç{5%X'|<kת,A>& ( cד'ORJҫW/r\zUeԩ* ~ iԨ3g�V Y ;VDY7 OMywg+i'&KVc�,k֬r % NN!BHbU㉱7֨Q+<I ӚXrR;\ӧbŊɂ a݃S$?XvDN.d62eʤ-[fT#v{xxhBV!Qxeo]']<[ OOcX%s<L4w\}'YuI O'!S+&MJ'QxB!@I!B(< !B'!B!B!“B!PxRxB! OB!BI!B'!B$B!6BJߠ'Px4<zѣ6J*%)RӧOlRjk߾}ExΝ[vw I=Zԩ㲭pn-\вbŊɱc˗8 ,YHhh&j'֭v3_|Gȫݻ%,,LҧOƲ3gsYI.Ԯ]e|;vLLn߾.-[<%K!Cێ?>i&{ؾٶmd̘Q?~^_tI6 .\1cdʔIf͚7o1)<<\._h?Yx#< !@ n޼YM6)uVcpYfgFdd$gb3w\)XG`�7nϟ_>}WF"N:%jՒ 2HezG+Y-[OL6M4Qyĉ}CU5Cܽ{W7nɘ2eJ*U*5Ik [<p@KΉ2�u*hVP!۾ 1cƨ3ҽ{w֭G9sf<$̈́/X/UYf+lK.j0m85k&׏7f< [BӱWիƹcOGjԨ!ÇXx.YD}6lPş;wNoVD ӧ^YFeVݫ-ZT,,]T9mp \tU_&"Eի$3gN9yjuyw;i9XSlkӦ㾊%*Y0@ȑCvQGF"֭[ŤO_Br*zz Q |'.* Q9{lSi^՛aÆsAB@@�'y@`\ɖ->|ح88OGΜ9DFxHeժU;w,Ç0aI=..N%>t68߿_k%ZlQix"<NxguNdL\ٲeq“ZjU7oWO<icŊJD)_~(ȼ=A\G#<yU85pCгgOSi^l֯_“2@(",X9�~N9{&PG={v-{i wڥKv9nȑ&w&06^aQ(j-Bj'L20EJ--2ETmh$0%jvZ{wwl s{s9Ϲ75:DŽm8xaaaڀwddcp!6"O> XxkIovޭ>Dp i`~K|+v? ' Eg!x)s=Fn�&f|U]}+"]PbEM'ڵkk= :" OHFۈYxx'ӊd͙ӿ#""\ `mΘĈ?^!r)s%3f̐]zC|wJ޼yu Ν;9O!<|ҭ ` h8uV8?[C%<F< ?FHc}ѢE~3QB/-s$6�`r)o߮yOǎ!a ,ϔiܸ6K!W hHI6%%%ITTn�X[|`VlC~*"(Cn!<쳻&B2 ""9w\(!V̑@ρ]Ŋ:CfD;|ҭ;jZv=ZEoןF'#xwː!C4M2|/xf^3P O..v®YSi%v"/؋r@TsΞ$ 62vvD_p؎hOc(}l�&8cg@;F<#in}7QN4_D]Ugk'@Nj=}kuL~`# c]N8'!,&HLnHB2W៍56lafq !B6IJBɼ(JWCB(< !B'!B!B!“B!PxRxB! OB!BI!B'!B$_[*!$}18B )/^֭[/[~͚5%GreM6_ogƀP\93=l'$;6n~|ys_WΖ38EVGdw^* mZ9ziFuPʕe^=zH%<<\.\H4i" Gɹs|nS8q؅ ɓ' PNHvVb'Ds,Jē“}vsw^yٳG<-[ʭ[O, }y#FiΜ9S*T o޼ccǎiӦy7f0" իڵk=8{4lPmi׮k@}tM/xΜ9I&I2e ٳgҥK˼y9sjc4?~}NDHVf͒N:y}Yxy8ի~ ;v^ԟ>}YbdРA.+~Nsq?0QE?Nj/,kwNOB0V?@+<y6ӢE nxFL:)66V_Aһwo%#WR�׭[j׮]k6^~#pF2fyl۶Mǵjժ2a_^Ŝ1 @"*;l0y?^T"[lxٲe5]�Evǎ>ϴ$<쳻&Bs.-ݻwOChAС]"<ֱ &aX ̨_n]Mrԩ^˪ί7Qk׮͛7U.]>FXOB1ܭ!YT)9s ƍSx Jj</2 mʕ*b7oyx;r-ZTgXRÇdɒ^2Bƀp }|ү_?9yF+ N>k"$yU�\;v=rWxbfGŊuk߰alƍ^iWnWN%6qȑ#]o52 w'!ϱJ O_}!}L8nx>3� 02e$''k*~ OF.]ZhCmڴIjժ>D)z CiߑZj*i޼n9>} v'ie5M'ڪX6wnSC$"wk:7GTfiUnWNyi>�v,$xfڵիW'@}/XB1b i͚5 Xx]3rF<ֶD`]dن?p 팋ӿ#""\ `mXvǒ"F&B2[x#ٺuʕKWHf ~�F<ʩ tFg fѢE~a㺁]Q�R" 4!oC#<}1Ib3�6 b 42D] 3 $+|fh9Cٲed1c\%%%ITT >\߇˗ۊ`DY|<>k"$+ O0zhmn#v~Da) '|9GyƮίP Ok{n'!ay}2d0;x,Y%4=@7jHr+#5kx#mРvD$# Q"EHΝ=!r;vvDDq؎ig5Մ'f i�lC[;3D-Nv~τJx:]/X_] OB.<9o1rC {ZxBH: &攜IXM 1{^: '!,QcŌ]!j OBygAKؼfS'!““B!PxB! OB!B(< !B'!B$B!B!“B! ϷVo(B蓄B pDFFJRJvڀ_fMɑ#\|xӦMWO;ϙ1ȕ+WN �>ڸվ}L?teB1sQiӦ,XP*W,/)RSիT}%^#F jժɨQѣGk.N h�OM8KAɓ' PNHvWP B{ʓ'OdϞ=*@8`)<WX8t)<̙3{X׮]嫯 h�9sTPA޼yƎ+ӦMo.]֭[KBz^ճgJÆ pҮ];ӧ wm֭/^\ʗ//sM4Iehh.]xL͛n̙SnݺtMdtIvM޽,YR>#ټy^z1|Ʊcߚ#v?5kN&QޣGy6!DZhڶma+(<@d3,,,D�n:}~Zׯ_7Q3F>|(۶mǵjժ2a_^5c lҤ 6L<x ϟ*UȖ-[4^lYx;vv>k"$O:_#G; .|!<[j%׮]S tR>lBao YT) Y O,˗Oԩ#6m<_˖-eK=Z?~kcsʕһwolC9rD-g0`�];|FEh w }|ү_?9yo� 4�[gwMdY2|'= "n+V'XZ37n_Ky7:tmXٝ>}cdY|Ν۳cʕ+_ 4�q eX]" Tx"t-5 CZ7uTٳlܸQ֭\BB6<lDgр76DUVIpΧO,<i�itIv[('" kF;O*Cz !{Y :x0@*vPxgϞXZC΢pD*Ixx'n8;""µ v>Sgk"$3O:{'"'|Vvi鷁D<)< !&{6/؟ ձBJFLKߗoVs FxbΓF�lAnuIl! dɐ/ָqcm4wܑ{ɲedY1cs%%%ITT >\߇ ۉ`rD"ȏ?쮉N>sO|] )Q$&&d 4?5x"'!@ 2DW`{A.Y$D?\O*%DI`;v;# O@\s<97Kxp 5kxahРvDT ְ9y\"1szlذAm=# N:Ittg�(㉤z>i7tUߍsP0ӟߚw"'! >>^hZ(&6.b%z")'!BT(< !B'!B$B!“B!PxB! O OB!BI!B(< !B$B!B!“3˃r6.4!$kc=uJ|gǎq#5xT?=zH%<<\.\k֬)9r˗/{oڴ~_)³\rKzNHv�mՎ̟; u OBM^* m]}W"E(<0tPsҲeKuݻW ,(heĉc.\ʕ+K<y dwGiA OBZr%<+\}|}y+c̙RBy;vL6kt钴nZ *$իWkzqYiذ.\Xڵk'}oߖnݺIť|2gO٤IL2Z{tkv2o޼t=gΜ* F!ǏLi3~d[f1HNZcg'!'L>=ڮ.gŋ~:ƍ4[NZh!vׯ_k랁jԨ!cƌʶmT?~\˪V*&LP;֯_b4i"Æ J*e9z-[V]xرu$; O+쮉"<.hd'!o?+KS]O,˗Oԩ#6m Vx4" >>^@ʕ+w޲yfC3#GHѢE5j0`�]R?|,YRC6' H~ɓ)1 ?1Զ; O+쮉,<mۡA_{l$zg֬Yb2ɲ|rɝ;;v3ʈ'OtҺf,fjzԩSgϞqF[n*[ ᙐ6BFV͛fӧ `mwV9]!UxڶCჾ8@I ZkזW^9@t+/3�v5ќ/^Xࡗ*U2≨,vۛV3{g,]rSYx5ӟ;f'ж  OBn-ZmЧKnؿr<Wv׽{wJUoʔ)2h =U.YVTIsC8z͚5:p`yܹ*:$͚5+a ?4h@~'=OJJ_z%~f؀X{~-rg#' vllw#豽o߾kDذ64܃j+P>3,㚒4Jc޴?Z}grcG^!!AۆO̞=[_Oۆ\n0i3y_~FCh}l3Pׇ lzF=l Bηc<j_PeFݻwKî8<C)%O<8U̓U/3 6 6)ad/$brXBBFjɅC,ַ3;v}n6z4,CTUUKG~"lOћM޸cB)ŢY<E,̗qW*$S]8~]x\ʦӮvD1;g͚%Xڵk4Ӯt-A322KYx:nLxE4`UyWן Zǩxb]^ϝ"/lذa0rrB!ųx޺uSB!'!BxB!\<o޼!JJN�}D_g𼍇B!č0W|'***:*Uǹqa[?SzDb'm<,qQQq&4!BaOXݻ[dn#>=x-xF1B!79;_%(ƍ롂vg+tjx!B|ŷx-AV"n!B"Q\ y "QB!ċxFrkW}7xYܱ\ x!BgP^W|իW|ӫ_)]2zӶm\WM(C!YrXg~} E$AyW_ T<!m:t /D֎IyFSe5R< 1m]h8&SiFG)'xBy8r:bhf+ѩkwy֤|O,h)v$6l̎…MrLZ2s\G7ZIO.kg@X oMbԸOj\<\z +\;E--,k[$nr]̌3B!A�A@\\)ϗ"@?}l1a̙,' ɱ~a4ueޜ=gmx_xQ?A:rXT*_eeZ؏1~LqhNxyל\Ϙ+ųS<yDĩS#m;vyn+U}vh_H0>;#bB&pF.,#Nx!04tXq*7dĭ`~=ڬ앢?;H)\U)btHF&-[ex;F?]NtK# o}M[GM-YڦeffJ8l(dٲ@XsnILgh0]9WO#Bo!$ni4/G<(5n!$x#ֲ]{Q|XJҥz9McCrsdXvyHn>)GsrCry\ &TSX~kLO6NoFk'5Sd+xZ=w3DBٜ?"1>[.u؜޿_`kg…z~ub<BHP@>k&Io H7.mYY]wy[N1eܼu[AҦΘ)|.vLf佇K)+#ǎӮM+0}UyGoݶMis]s7)!3̵.#&vc]*ًyŷnh䥬V{6iTq] >k(cUWM(C! cDCtrO+ "V^##b b靱&L.N7i;{Nߤ{0iݪM9刧Ɋie܍yX9Bmho.HaMG*h$IV+%l5 S<NSw$*aB ̔35OcTpKzxډC#vmmJgx"D]Mcv;ߍ]s0v- .K9yI{oLvi78EKz># y(n.!t%O.Ξ=#l.b<BH;N̚;O4ܲ53I4jǑ?k֮4/(2vbނRܛ#EGvOD:uD5vmZoæMSng5c;SsnbNV.x+3ZX_jm5d(YRbYPos玴ksy!eP\W)%Xh=)8띏Sb<BHhk6ars<|lq:8p0M\qBR<�k!hgΝISH?@Վ,]µM3^8jiAXES_MR�ysQ*u9=RKZ~}9z9ʿN7hz+_eo"˕-iwg,/@YC5וx0xȧtOD:!nG1B!E׽|74D f+GYbWO`YQq)(*nƼ}xت>v4N=_x!M[#}D l<%>н yl7^K҆ʥێSOHg*ޣ!򢀍8糉#srs\RϠīD7=OʘSt1x!B!xϠīϲxNM(C!E<p@3/ ۩)x!Bg.xX(-1T A_gx$x!B|ŗx{f"OЀ[b'&+y.QB!č0}Wijo©9/#֬YٻҮ}ϕ}{ӬrQB!č0}W[>%TgB!tSnYJ<_Q|XB!$M|]uWTL u^"B!ik[6^R_U WC šB!@uKKk|Y-PW Sw#B!F=!N9izR:_GB!7Y[uZVN+@"B!+'/^xŋ/^]s5!`����IENDB`�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/plugins.png�������������������������������������������������������������0000664�0001750�0001750�00000113513�14035600052�016570� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��x����� ;���sBIT|d���tEXtSoftware�gnome-screenshot>��IDATxtG:::óf6"hL9G9D9"EF $P crph(ߙonݪʒ%KFޠo>Bh4FKf/_nѢE'h5Z_ٳ?Ff>!BI<x@lOccc~vY6| /!BH:B'/^M=wB!˝;wM>}aׯE!BI;vlOB</!BHܹs{w]B!b"</ o!BHƂB!B!PB!xwB!b"<ՏB!$AG!BG!B(!B!BHZi/T|}vEz)73^cym !f#$ 5X,Hz+[x'cpW (RLG١K8y2M<PBҹի2(dZܭ{yC ,,y 7E'ֱ/ fx޳Z:rIzr-!d,~y7<]vMz  :y q9\ʲ#"ž'bn^ rz(15Ǜ5g흂>7o3T%~%*'MWMt}2Jw-ݯ:禭NΓ*JyDr2mL]z'xU|E"ٳa*S(\rFֻڳi׾s%4/Y!<EKVV˗/ۥQ>]2s܎ul/P<uZ9@a"O3bhyCƎ>k֮z_ !Gu[%$֕(]TZ3~=!\]rE:4ꉇgϡ+0.X/.>RrU cZ-'N ǹh<f;GxsZbʸ͓e;x<v1'mr)I^?G(%Nz(!I*XW.^>gn5 ^]xz»Dm;kM'PփtfcwZ+_ݏ6j3v@EBBߏCGH&h55kqeyi8+<g>{3p` 6"1x-ik˔M7"%K9#oZx,YQB.𴦽Wf= /)*J ޱj#Q)|oD!b6oQ6^h4{ވq7u=I<cྸ iAqmؠ:hyp xL /x :.YUa<tLϛ!iMXɳcNջMy2-l鮧ruۚuf|jx>6t<u85kY:o4BD:Ie)r {+kӣwPc9kca|C۱\tdX7AfW>},%~|O!}6CAG9-kϟǢ#xٳ{Kz%{my!)͓'OѣGN@,c(!z" ͙A0}T!Պ$dXܸqC!,,T!$BGxm!"<ՏB!$AG!BG!B(!BH ׯ !B1OZrGG!#B#B!xB!B!$rڵ4GV*H!B!B!BIիB!B2xB!M!B8d>}B!C~M!BHƁB!B!PB! <B!BG!B(!B(!B!B#B!xB!B!Oc˖-`NLرBW -y X&ǏB#yBgߗd͛Z݇'O˗ʕ+$ߍXQFdRdiɚ)zl/I!~xhwIFpqիWۄxBO{dĪ5kIVP'GN!O^)TR4ifjłڽgoݻwI `$͹xΝ;^ z+ҡs8xPΝ;'cbd_Fzi"^$1x04{#f͙JæMKj5${N"g5Rf-ɖ+d˙[*ר9qQiۡ,Z\y  6Yʣ-mR^ɑ'ț_*W)+V%9fϝQ?_3 <BHxn")� U+isiWR!.\pw;%QjE^uT.]&gϞcǎ jږx۰AGZ8iӾaf5k6U2!$] <t�x[&7 ޣG1o~8fv7u5ѳ)шmi4q/^t{3y< <6l۵{}[LLVtY׮m޲ #ow \anܠ_H*VaH}ҌC^rrVi6i rp*s;z옥<v>w ((!V]~۶R+锆er!*Tf֭P4)𢣏HN`Ng&ð1fQ> <BHx {ImL=0tL Ǐ UqLN6цfv .Ty,k5hMw.fil%dZX<%@Xƶ&FiGcP <bIa{ѣRqSרVے[y&(uRaRDB�/];YԬW_u YJެVx<1lݪG}fΙc5N '𬌦%RISv횢^&x{:Tv┩qϚSTz|BӧϤӄL-%ᢪw)U10ٱäUäT)aW'ڬUkSXhm߹wJ Tq;: ܪm;ٰqWfΞ#EJRT|E%)!Za $4hL,[f_?p4hx[NN.],bh $wƎS]ByBYqVr9>.^fۤ#Dbbc?`WmHCk+"ۼ)Hio,[QoLO9{V5oǨ| <B3%;~t=I>t;a9űi%#\Taam9xNǫt4,'PBC' 3`۶'پuvb% Qmw\NhRE&�mxB.0ݻ: n6aS)iCSX|aRʤ# <S$ȣ#BGG2b\ !< I#3B # <Sٳ$#xBRL9s�xBH ӧOHhf, <i<ShT39?s:dkY-X@ԩS$QZ>`XM0EH7u$WJ/5/ ǵ(眞^f=}ZݻeٲerqILL$�-1}Xfzh#z#ϕW]7UriMe< <^feL;wd޽+pmqqyHr~d9ٷ-_RM=΃W~ [ھ}݆ RqS 4tD *!9v:+/wujfsBKȴ3=퓧NSժ={F{ZOseҴe+PPr/['LzwXXFke3~jJ u=Gt} =5{iPP ,$9LYq~)Z@-9zTǣǎ}t2ꖧ@S)XHbbb;;gk]p]_,]\]Xqٰqi9&&.0-y KסÇTvU*UqgDzieځUqf<hZ pQY%4C`˞[Q2|TQӞnt|cZ3˔ kׯgH||tK:t 6}>Z}#RN=CҨYs p!!RQcj7h9 ##uѧ}^~?<X8ҭgo<y,)SX2zj0'޳ZONBBL9KΫT+9&!$s4`[<-_!u6}8 E}o*�Ĩ:q4Ixttq::(e�_Fz#\K 5Sdiٳw{QQ8Bwmec9gx<yz"𬜇yƾZ;`4h\5oFVZeXfCʃ?aXv…~OF@YzO<i@c.7!$k7\&XO%˖KKQ0%9hZ>ZS!ؾs ((JQ/3_cߗ}x۶u=xo0e#'<= S?_+J̖y9}b)?.>^5#BdiPFe6kZ-XAeʪr;>,лzVޜ?ox <hHpV/7qCnYլctL8?uj1{|ou=pt͚3WyЉV^HI=x{-9Ŧ3:__ߏxF <衣G&t--s֭RjumN~DYß am^HOeys|QB2:UA"bʔ(~;nD3w><-b/eJT E=A(ʋzlwKgd{c<xln+BG @|xqӠ9|\\:}bVʬR3vzΌm{,V!NDN<9FGIs/uE sK*)s՜E!i9AΞfb5:/]S S9Us6ʷr>ZW4# ,d64u f//Cf/6!x&qfzH.gt^#v=kZ?x0R87f{_gF6={x+9F_+:x*˛s-MdAI_P@@*kAP'k <Wÿŋˎ;$""C~4Ҝ1c̟?_nܸ!nR[=*Ǧ7o,cƌS}h4Z昪L޶C*8`˪}^ <Co>իի\2 ={T 0¾;sСC2k,9pXb2qD4hhBqw3{\c8"4ۡcpWtq.I`┩x=x)eW\M6̙3ƍUFBH:x4J ;~2Lsל <FainF:pqzVx >-K </L.5/#>(h4 $?p@ r/['<_vIk 3Z8>BGQ(/GO|8RCG)0Fff@ݾc(RLu0S6Řl`i}s+_Hʸmzi6R`g$cS ]+c8 8]?c}O꫍/^Fw'{{}\&4fη{>le|=?b<Nʵ2s|{: <f^ԀC+tK:t <*ᢲ%-:;=1һ C w<Cs`yoݮt]+H󎃌}5knEVLVEr[2y\™2z|R /v f^nFg܌'z8$i a$;8x0=>rDjԩg`m:?b;r>#)h4ZoŸ)`j4#nsbGm#k^(p<&F+6[?q5m۝}1޹띛xzi6Uj6hT7oFVZe/iaLnrzo{⸬W_sݕWtO͜kV7:?b;r>#3SDoD}cX3B(g roRn=՜57;{ܩ< !<xqj^>xl&m.u:^ NR/7eѹ)w/Sǫ&(ce:/eznFz86<} zϬS3Fw_0S7ߘke{!*?ś7oz cbr31Ő!Cdڵjcs<Ď;&;m{Ĉ*g|x ̕'O)>< DŽژۓiۺ`M.7C\Ml+cwfT;1@y{\+u6ѣU3%kofVgY=7zw0wh{j|d}Ϩ w<#|�Ki._,O<Ǐ|nJa1SEEEm_r %.]DcXXQ%,Y"P_.S^CTރe O>xh.u|pB|hGXvA|]wK6Ȇel3/s3*1Hs,QBb6m|WY(&N('ф3:?W{bqӠO =CYVuG[O!wxS7WNʵ2s=vw.ZATݿݓ9s={(Aa5-:n&go߾-=R"1͚5+!('B JX&yO (jJ 1 < <+XrbAJ,=-\/z!]B4téy Q>ℾ1SG 8.vLf^>zfT>sĖq@/G:Cxqzr>v]> <s܌'fNu[wPիG{j|ѡFQeF_}q7usĨ\,3cw璮A`YƍjnYgCm۶MPϟK~ׯ˝;wW7MF1y;Ȓ%KT} kժDA4Sد_?y7v-ӧ|wxtɂze n =eݽM#g$ جfU#%&&p:yM%nyl+M]S"Pk]oSWʗ//cǎ$/K)䫯jY=x@Zl)f6ݱ\\ǿo2|pt܆ethyw孷ޒMÇ(J5z<衉!@zyO7^L/1¥K zܢu/gϞ۶a{Vېh&E}*ҊЂy�̝;e׵kW T.j ݺu3b \t1]ʆw`GTNx|z+0hn)(X<yU3,KH 4HA JB>4AX!.zXƾz+8y- "j8<x# >L9b_Gg MGFRh6:s,;::کl! * �/ޱի7o8 C(s\ !=4)yP<x|YxhEͰkr!;ud꘮OlZxHZ<3{@IfД&X=�ݻ[vJ܅o٬bݻw+/ g@ - -t([Oy^K_|Ļ el16gHq6;aУjj3 !Ta7 Hࡣy c{ ./*lݺU r!3֨zѢ3bѴ^kN"0n �^Boh<tlo- .]8a`Z~WʕKz'MR… cGxu>^կ 6JM(R#С93ȇ(0!H / 6! 0zb]vY3S9ִiӒν1 ]Ř<�;)K=,ڼys{/Y,6; 6xJ^޾9r(O'|"cƌ؋7ߔƍ/ҷӦƐ޻}L*,5fլi$wơ#BZ]Y18)ʑ74nRbO=}NyG&Gy^fLhknVQ0+05{uXbX<uꝈ0sL+ 9f:5Ƙ6ٴ3&$E>/MݻẀadlݺuJࡉ4IC:e4f8^ze FS/H5W f,02<DYvW~2+C1*<]{]uyo_zom=֪Mu#eTwwu3蚺c ]A۟JpJě{:x0fxSdAtb0bcV(0ˀ E.QB0*:Z:tKxWxb%0˄ȇwidv 4 o X Qp2 <&1^Eu4=8Gzꉩ³ aywH/PҫUvnE>Vk=M:]xGma<&7O`j6#|YZOyh&CO 3Rw"9@EMX_hjBp_࡙q ,F~==M~DZ9bI45jMȫw z6kZ-X`:i j <>F=Sw6$Zv3X2"l_ڄK C.:OszMfbh4  х:O(o֜DiE0l٫P۶c'`<&V맿7<ǀ0Ń9kgsĄ̗6!Thxqת[OPYxy�eݷOyw--G̕A+:\X JZvz@lzc} RqyZ::gVnF]S3t"Fr[;i)eJ  e]B(h4?:&h=.Tg O b7J\A,[nO_2Ly#C^!nObcߡsw츀h󤷏55#q&pM^S+aFh^:ak鈡MM8xPh4^zr0tHĮR8$!x40JeU!4-zbMȄ <{t┩|#Cc4v Ru!FQBIq!LC:527俋v ;mMQBI j*y!?ƺ2cMzΔg=Ʀ(!$4a/_'O9c@>7|99qN!$H+l"oX{+fZxWlaBH:x~w̙3Tqt^VFK^aRMu]a2=+&Yf_~Y>s5mzK㎴Pg= <B!Pa۷-q 5kicQWc%Vfo8&ן%U{D^eϠ`(22RyYdEUVx(!UAYڵk }d2mx̖d?AҤI'֍|2vX<-[{ァ29 '9rHTT}<{̞v!y[>Sy7vrr*^03Tλv*2d୷R#ؓϨ(QF oU'RQBI.wK\tP4_J5+ 61l;pTHY8p.N'֍  c.y2t@@@tI)SF@ٳʕK?QBDw}CBB`jPVjժI6m-]O^}a}+O&ժU+ע{*izORX1upNh"%O:%u֥#\j9Ak$ RY+^l?H1gqQRD ir5x܎cXx(T{߽{W^{5<j(Ppj믿 $r,ӫ//pYXvMxz;G'[G+ixB'y\O;n5ʿJu~ aD믫Tb`3/>t,ñyן<mkZKxFpޮe߿_y�~m/p;4 <B!$QTج FW-g/:{@ĨQ'j7~x<xzBr2x`VJJ5OZbKn/^ttȃ׸rJy(!$C\Y?eE)o΃GIAЭj\w&j^_t-:<h֥K 0Bqwp>|*ѣsÇbŊ墷/'۷Kgt-X9-c9)R)RJJA}TpxBk<x bcc A>xfϞ =˵O?'ό9iӦ95 6osˎ͐FB&4&WE bKLr1=[zѣGҹsg{{ѓzbw}װ^=Pn eK^z%{ܹsMMhxBAan={(z^z#HG{0|x61OV(J_~iZҾahX-]\,-Y |fBI+Mi/;vHDD!ȇWCsпE"d_n]C0z+!eZn͋K"`ܣ$?BłTٻCBҒD\<@:b!:Y|NkSDS1hׯR2} R:!X>!4&h4Zx .>^)Xȭ1?y:}dϝWʔ}#PI6;EBjc�)P*1·l5k}-4ի!Ph4(< ;^ISmwP Q듧MYϗcҡs/P%ʖ?ia}DbOn={>FԶ%˖3gdƍRqSx!x4-}4jy0L~`Ot|9摣G:BLC-O᠒j}\3ș;{u29!F= 4UvGݏ6ITo_oe_mZVKCOeWChiJ y~Mσg�o۾CT +!Fo7nDe* ^aT\޾˾\c0MLqe6O/V _< <`RUrͯרZp_ov_w/\zѢ 4MO11V I;vCIa(/71qΝ?kgD,#2wm˶ryidxB2X[jܼy ٲʵWݦ=|V&�DmޕgoNQB/s^|Y<y"?6?<<4{ty\\휜xFΜ?%s {\>}*7Hbr=kV`\i4 <BVa[޽{2g×9鳧Jmd7o(ˆd0%�W's۵ͭ[Ʌ}MYXXd —_~Y>s:ujhdszV^]}yW$O<bŊd=A#Aݾ}7nܐYff̚<tg;/ $ 9#'-e62y(<tP#uˍwyG,YrjJPB/)<xŋOzQQBD ׮]3%͘^♓c~Yq]J֬[)KV :Ȉd9ңgwYآ<\\رcuСCդ/چz[>Sy7vr>111R\9y뭷_e˪hw^0͌t?Jz2-[{ァ2y:/9<zեQF*u8p6loV^}UOdĉTcxBҒr%.]dJM>QwQ9yDFaDj2h`/1DL`X.ӧuLҥU`BBB`jIjժI6m|Igf͚Izt_FeZ޼yyr ]v@5>nݺ鞗< bŊc… ;ȢE<uԭ[jBHZxVA,7y/!F֭_%k7XR"z=QRrq2l@?ad_sl2N۾k9~}ͤ<y2LOHY-o/RJ'gɑ#GQQQ*PDz r>P]M#OҘ%3oJ%ʉr2D.!'|+h⮜D6~WN/GxzB7^_|Q__*>5ۻw(P@5jMȫ'3xg߆Ntb ئw^ <qE4L2o˗_~ΡQBIC^+Al1ɦMdo�yw&$ޑ)2v(S1xǏꫯ$!!>Z\zUh|V4[n<+<WsW/3|<x^+W4 <=[l 6OI?p*Gf\xc'Rcߝ)g4G>wʡ&Dq 6zl)^_t-:8 ÇGÇRbE{: zk: 8^Jz :tPqyu)6靗zxF狺8)R)RJJ!>C1 <⃸[z=ha=w8xA|Z͞=ƌ }>ųrzE uoWúɁoɎ#eϾrXܽ{WFnxM]8q 6mDK D{饗?VyA7x#I/Z2] Bc!/Dc3(:ahhd멣k<q4hp}]իʫܹshEoZtؠQ?}q@|;~ߩ"0={=dT #03Bu dLre0^^6.wlJ\ tCG 3-h)kx$}'d9ŋ+bDD!ȇBGS1ZUJDi/[Mm᠜:(W]7!Kc 4cZR=p0[E#$ЊAxDUs^ 1q^N3ȕr yǼׯ_)& 1:MW_TIA !Txe 2m:|a~g 1@&M qq|hxRW=!$!F#&d<(h4Zon'w@Aiش:|8q!ns$پfzKM:h&'ARf- xׯ_7 VˮP9q{z-VGB)&!RZs=w^1'H%k6̫<tD *!9v:1}֬]'?U$-i3fu&f&*c\mСҬUPPr/M[SgPRo~ݲ y ڷ^-=u:.>r*)lC`a]7q;fZ֡#<xktJoԬ=v̾mʣ\̄Һ]շ==ᢲ%rYV/tv]"V(vP\vMz/vs۬UkIL<%7oޒQcI՚u>q)_>6jŪw< NF(Wl;w>M[6EI-F䏦+JGIO^MHQQNI?`_?<DzbeI}$ͬb,2FG2KX,)ІCe۶l薍.]&+VLls<nɟ~VN+ǀ]ռV!&NQ*X)3U^.ߵBm6-=kђf^%ڏ 4D.ͪ۲-ΞC&5њo;qFRedE*fK.H[޾cԬ[_5}j/!\[ǼxhqOeo**U+WM[">J^5 $&&OI"FRM $EJKO$?Րo5!7h4>$RHŤr4 I/>eX6+%"u{xhҪ9 <#.64xJ+gu?xOG9VE.U޿kC1ɓ'*!C'mB_Te]IS}t[R*]^W˷O\Hβ 71U5`]wK6[i+{>O (\y Ri{k|eX6tMގiGK:cԪ>zưXN߷eo߹g!끠XMPOsM֝3 N}ҪJRWXzfKJ39 ]w!U^led=^Zx!tKJ\A,[nOpԡ&zӮ]qə/Pd4b ޲Z'Ǐ*bJkVz۬]~]͜)%qW]s^B`žjun]q`SS/R!Uu$R<}"]sJstiPVJS;ԗʃ7tVܸDyʍ>!u#7SHP2d& .r5H:$?>Tw Z6op,SMKHF"UQv.#GoE龘t/5_:m;+PY<^0)5hZnߥ45U-;Z:[[2joh–KXYz\Del@>y&z$#6\4Ls5l #3v^7OdMxdZYFluZyܺ]#@?ސoQ~XY4s:vvAN]1.^l(n"gϝUߕ(yu*vTu}z<~![d܀eC՜+"nK䙳<uWjLS:sWbOz]yN>64W5q%9xԞ/ƞMnʯNy=;ԓPm8 3xZz<bsnj�R(%O=g(O >ON3&ɝQ:{#6c!;Ȭat~䙓͝59>I\ 3U잶~c7Q/U|PL8U&T^?ԓd|G <v"qS |`AKH<e(~\AaңwWt7Q2o3\qn\US awKOšy(2=se۪imYSig(çt7#_aBH#UӧܹkCo}(7d\˕/ :T}ܵ]hb/VW.pi^^!e1x1rf:%y1r衻\T;_=(=/dG x*#"B.XVئ'h$$|&KKNkw)\Ե$xމsisZn3а-: ZG/uh y:E+sm۴-1B'8ݙIs=K8 VWo6KGG2@B2:^|B:uJbccg -�Nu0*6p)WAZo-6oN I4 n_[\oisI M#{bٱ)tʻ&R茩4c, :BMGla-{  $..N=_ !NMPY~ҡ6a;|KքKڣM.ya#I<yKՊK1E:m;!xݻw˲eO5!$3~}\]6HdŚMaȲ՛$g[U$[ɳ6`Y-B"CrRj TܹsGݫB?=ww<M}Sc3⛚#%O^O䐃ҴvEݦ7_PeZ9i4Z0w~xM>kf|BG! #!xB(#BGG! *h4Z1 <B(!Ph4 <B!R;wN6m$3g7nKQBIbmժUrMS/C .KQLF_z̛7OƏ2!׈4"6o,/_V#.?~Cp×eʠ!>"D6ow,K,x$%g϶ϙfXD5#$ތ3w̙34"t-]yྜྷ[nʞdQ*ݕU+L$k֬/.SNM"$΅�G… ٳSy<|N2! yn߾m7nȬY _NƏɵkWܼy]޽rEFF;#K,Q9yԪU+]< < <B% <xZ_@#$ <6+\v͔6} ";w9Щ >D>ca˗cZ6l ~'ĉy -[{ァ29ݻwoy7WzK>#ٲec[#ʕSi-[֩Ie޸~9rP2}&MALI;>|X,XZm0iY'�b2x- I%wK\tɔ` <# :X坿O?ӧO{->YhJNu۵kW 3g([nN@̠ʤI4k̾wy}.<|Y4D=իWϩ2eHBBzSreO޽7kzx|= |z-39[s  ~7D%4J@2},ϰ/J%g�ə8Hm;N߷rЃ֌[b[fϙ7jw~-CXԶ++8y <xBCC +w~gr:<Usիv:ؾNe9Fkf_G]mR^k鮷ҥK8<e -Ŋ˜y%..N/mM&O.*VC+<m!01x;Wжe\*2qA* 8 =uV߿_y~m/հ/z1%a<cn\yl+yp/P&_|5vWo6?A -.Y`'<tD * Yyi}|Cr|e䘱N;6wiRx >gnX޳Ǟa bA !O@=q©y $qWg4/(=A*Br|e, -s'OUj5dE*:+רKV <xQ=ֳ+YdQsxٿfDn\ ۖ˱MsDnY&6.]a3dp(c/"aXir'H={&+WTh ^yѼxFc[ɋc^Yww{@K;Qr1Kzտ`:H郇ZȑG%vkԩgI(%BpzP )kוj}]{4-ߪk~nSfo+K/Jv$;=g=~2&L;>)m<&,OWE՟_:txe˕GJ+/&NR}-=GNbcc՟7x͜%m;vJ/v̂ m[A,+ucen6J ll}QS<]=` C�[T)'qQR%%>�?GQѺtVpp_ѹVBpg/nC + V1x�`F >gT'ٷ}xLiEK={]"GcǏʖ3/Uɣysݺ˼ ^OeqkU*_@(kݺu$vZ;wWgϡZiVT]mZ ߾GV<ul5kq C`=Գ~Edd!>C[ls;/iӦ9yЫS9f'q/W_}ѓ =BBT/Sh^l޼'+}xFc[ɋ:Kx9+°QFwMҋVҎ5b F&hͷ�ͦ#cي�2*h;ҬUk`:2e崇|zex#IJ <ЩP:p�ܹk<pS@cqPh']rxвSJ"an=xȇ,og[y[<gHK? -絁}i4Z <mFhTVR$ ^7m8g~FX2o[n U˦p&2(FJ R^^(MQYJZN <Y7bMv' */^,;v쐈Cg}> էb_޸ U}ԳcҢ/t`(XCK�6mnT{d]Eud^FG =h܉ؔ0߾}7`_ae|_ouNMea[ǟ2<33[:ͯh=s|/ZM_^5)pcZ#q0Fq+_^'MRrKJ\A,[6X(I/Z<0M25I/ZeQ=Qv`+ izc`aTtAOJ6&0)6x{E& <kd:Y,\XʔhE`:Yާ;qM/Z^f1)_@g:hǘJ yശ}Q%!x4/Y@&[PtF2g5n&(ג <F,u@Sah"C`1m{elChBG2#cuVOFX2! yBG(Hc݂ ZelC /!x4ܲS,c{BG(!$8xp;8xV Vm۾U/+#FS`ېF(!Q!87ozܸqCl%ȩzY\|7J#/k׮*mHCFG!O91iD?~lFFn.P)TL:Q.]MI  m[ī4I"/K,i|}4 <B!iL3`]/M%xn}@Ǝ\}RB YxHeH9$ iOZ?I>CPL33 /Rzu#ݾ}[[nI}."2|Έ ^:.kr-=Q!"&ϊ�x葜8qB'o۷/S ;v_عsgxz#Lqu~<\wy ~f͚bZhCS`xWn=sI;y8yʃx߿.]کcG˖-S`Y~rqQ_xv1gر'ȫ*9r䐨(;,&&Fʕ+'oRlY5f>&Mt?h CӠAu 6xw}WߴiSu<޽~eٲe(룏>-[TϡCwu4!Py)41.]! Q* 5\^Doə+oՁ2amʃ];ywUSHnTZeܸqjy̘1Ja,'mE)SF~ٳʕm=odӦMr޽U5zӻw8oxXvM+`G':L4I?k}O06=xxB'ț.:w.mw.hwQJa+o޶D9zDY;kxɦd8b 1y}gr:<oZ^jT\Y-+VLڷo/%JPCb8Cܽ{W^{5;;8J3u_O̟?_ *d_h(cNu3#0&\_yꙘ&Z <B!x𞀈]DFCrEfhse:uC)R1WpwM;ux1D3,c&!p_ofh47B}3ǃݻW (5?⋺ ŋ;a䱞zurf֭ٳgxxB-N>*bn'3_;p@/js,@E2o{lMyN^mz$<74bZ![{-߅6Eʀpj^&ã1:q4tՃ/' ok!ȃeǺAAj?zjX<!PA+۱3B$%YݧiԩSq&&-8(+ɘQ\iw=-}^L <ϝ 5ҥSLg#F_2dZ<xZ J,Y4T >M89O)$$Dj֬d{:uTwt,ˎ+D|! qK*g{Q; <Be<x bccXG% :̞=:qÐEcG$bN 5Lf͞!gLukOC9A3$:ShZLsA~$Ƕ"&_}K+! QF ]zѢvpɚ5n/Z߸qc60<y1&xV( cMxErXyz�؆4^#&ݳg:=t۽{'O6U:^�mKZep�YtL:I:tlK FGHPQjq+,cҐyyH <tXx6""۷ˢE1Tf ͵C X6- *);w!!V|hxXp syhj3=aې<ȋ}xH <M_^աHqYRaC)Wl޲ov4% ނNiz RTx4/%@|oRjN hFS{j /(2=(h4Zx^&70':bNv Po}Q/:J@ :L7?B{˙8Hm!O^QݷF]G!{.]Tyl km;vmEmdƬO6]U,V`yڌ> <m9!1QrPh%OwP)TBmשFMGlopv2rXS٘mHRN±mݨNx ͫ׮] xM}#Yk_ȫRՐaX\F,Gb)>gn <qf/nݮt:Ojk G#GFz^f?^kEIaX~|Q؆�=`3ʘ0a=gv\mL"ư!)?f=q¾}=\=x#Fx4-Ma6}8[.T}(hj&m}=^'OQM3ZZVmd┩]@R|x I01w2Pֺu2=kmΝM?m핰ڶoc~P^9GݿD;)h4Ze˙[= ȇOh: <h3?r,c:&Z xҥK>2P "o&CP̓gr\>mKCAu8xV1Iqh4ZxAeÞG7JOox~-i+ƎS12x/ J |M2D;fV_k 3li9*]z5kJ͑S3dO<Qe"�caF7nDa�'pҢ/ xfQو+^1hD>>KSMZgo(؛?gޙx0.\} ovJ/]fiCՔcZ=DڢIZZ% AMDҊ]زTnyω<$A]<lD߽<~~?LdT7MVU1'oA<wʇ~mMз?v_7b@dfes<J3tӚUWk8vcq4K9U)oo(ZsHYZs=G4)6 idHu}&ln zx x6c!hٿe`~OEeN2w uVU.=-,Zl)^2|0IEK"D4Wz#z򾾚ȗ1|p7-ٻҨ\B>}T�GuI."l+Ⱦr ~ lz=mAS^n޼Wp<:Jn#ѓ #zzQ;={_|5k:{,XW^yD#TIĉɓL9r'Ⱦr ~Y\Rz{�6-sX"xWu9:q4HE2Q/1du*f/^VZE4i53xLv)\l̙36l:^ӦM1tP9T̮O :t@acc>}{hܸ1ڷouY~˗/G۶mQ^=M^moo֭[+dYIRSSղђ})))\kbPK$Oul( Ve&eRG/w/?CO$KKgK*ûg9:DUR+,GF9Efy\Gp?+<t znݪwV ^~ yi dz'3O:P֭[7L('c̘1f}Ezz:ȑ#`(gﯤKF= Hwr`IʽHWV+WT'CSLѼF<B2?eddL~2cYmR&uώ<T33F/s.sդ駓%bKRIK6!l 3tBC['z{~=HɳF𒒒 뉉ԩI*A9X2D2S殩K.,t�,>? VÓEˌѱcGAM9?To6f͚wyGKG}uZW51(xEd7鷾c5>v,6):Ry肧*A%OO^}wz8SҖ ^vn&NUJrjr2r&I5n٬'T ^˖-<8Y؜Yٲ18dĕ lHd5h55iDׯO}xgs)sYϞ=M޽kO1"{+$,VirgkbPHNm6ժ!ȲlhYRO2/dƒ'Ccud\dT%q'M;DI>oNX\|edْ LU<_>OTF~[YΝ;VM6.Mf.'[oaѢE0`Z߿Z%רuG!> $;'s<R|_jVg٦/cG1Gq:$Oaݿ%v̒ѣG̟?_SyHH, >x"}DlvڥI 0W2-P}d 01P(2' [?)'''>xtvv6{zz駟6 &YtZ&YKQ(x<B!i<ȉCY8A'Ob<p".{{QO/N>mRG2Qad j4?N80zԜ,o'#@o>jذe+d4ۊhUkԨv@CE)!&8,';\i.0'S*)heٸVsOd]G#rO:FGGȖ~DPeH;~kW'Rw,:v#v5&A`P!<'&i d)$SbȀ K/`\VgĎǠByO/y2&۪rɀݍ#vu]<Bc-x#d�H4%c0(xB(x G!`0(xB(x G!`P!P(x B`P!<v2ϝԩ O`a<xsw.v~EE;VE> !/bvEbL /Wuw݉+W*-+\wMyأĤ[{ B(x5<[&d"bX%տ( |gfܽ{q\A,d#BΤWEgsppWQuk?(ʛ+uh[?(xB1fRXhAg/O0pwܽp${C Aq>%A˾֙8<m*.-\bi GeX*)U-Q!Am*1s\~sW|8}eJ.'瑞u2lz G`"|Na= WZTQ!<R'B': wodlٲEJ2sΩ]H|h?A\]2}/͟ )PgOhѢZn%KT4#g@YfhӦ vލ/B"""L.^ZR&MR׫X:t@acc7oZ|oZ5=Vf̙36l*kڴ)CyYY&L`̬Pt7Fn: !'K9.aYN'w}#>!QյD6l^2Ӑv>EG2ΜKBjZ"p;~7Ke_ jgΝ~!77999ݻwhEdSOaɆW^yŤY7o}Ezz:\#G{*ϡ[n CII/wtƌc(wvvoFx  >}Y+Qѣ)xB,ӗf/9̅ìن駓%w2M%5^|:B8;~Ϳ"'Y<K iN:!))ɰO 52k|mzѥKT{*ϡbmְޱcG嚬zyy!;;MBLgI3<==zA!*$cfi8s)H\-zS[\Yb3,'B!;g,W6^}4i 4Pԯ__՗ޛVyMoG5Y:D {'Nヒgy=)xB,, cM$o={#I5_^ffY+֬[k 1{sd%wy&ٰMj45޵"xP%JDիd8׹sgdddT޴kz<9IOsi\Ӻ}QAAO B'xҗI\( z=!:&Vmӗ ҧ[[ }5rwÝ䍿8m 6Tk*Z<g˸[U"ҲeK$''?P36Yvuu5{xxk1bU^זpڵKeΟ?\;998pU()2<B!O<xiKKKSȺdY]z9|8\<xy;דE\qr| D}HJI[C'xk'N?SdjUheԧhFh&Nh)B,}ǤYڵ+-7o߾}* װaCkN]q4Ɏ7pk}lݺU_ze4 BybOAt2BʪBʥ0{'w`P."k8#?O?2-^_Y$x'/N>?O}S!W-毀�DFF"**J#G'dVxJhptjQv3QtWHo)xx6kL:U ,L2m4 ! %կNlB%']Nm@aQڵbܾSu^ j&di;vjƧBY(x+22ӱ XԀWK~e1-׳7G!,x G!`0(xB1<B!<A#Bc0<B!<A#pW9<wR*]xթSqp[89q&f ,at1s;';A# ^uOd-88׮]#c+ 9%Χ!;'SwMQTT;deTG\G> !P+xNقϸ}&ROꇇ[1'Oc;fINM4:o~C`P!]WZEII |}}kIi&6{aJR$a`U<G! lqUc˖-$;LZ2l'O4JG! 5\rESm[2;Hakk-ZuXdfxۙ3g0l0ӦM1tP,m.WUFΝ;pssCмys͛&/_m۶Ezh4 !PjG "??_Sf#q%ml.öe8ݲ{d—?͝;Cnn.rrrлwo[njT4EN<cƌv5jZvwwG߾}xȑppp0Ȑ!j$3A#RkgqdIV.:6JIv qUN4Jmz9Dv5שS'$%%!#%f=zoz.]j(CM̤0(xBjW${d <Ttޯg {IfǰQ55nX ч,[#x111ӧjRc 4O>ݻ̡>4iׯO޽KaP!Ԯegg[ddcsa;y<QIvR8:[T,5D}D�oݺeXd |.EEEZgUR_d9br-;wFFFl0(xBI1K<S{o�cX$%+fXi5n8i<-YXk]FL ѣϟ; <ؤM6صkϫZ'}V=<<x1ǠBIFN---M')cǣ0a ƌ(|:F6?14Nbp֭((GF}D&LX[ju(Z믫L[rI}TaÆh׮4(Z_5j]vE`` A#rO-Yi )zGMހa.ܽ?pt Tlş$+_x0,"ŠBybO 22QQQH=/5nلUkV`]z[M<B K^HHj:U!塡r'!ͬ*ͮZVV lM,A#BRGH3qkUܯ&YG!`0(xB(x G!`0(xB(x B`P!P Bc7^XXzy\|a<xԩ8-Ϝfa8f`0g:f NƝB'k׮YzRҥKV=滹PxSp|s2utEEc]@Vv:ΞKEx!u䓝B'-((?۷ok"~xxUpT f$&~ B(x<yXiiU׷Vd?s%xg0cqÒs<WUl<B!<ȍ7[l&ٳa'JΤ%vGV(Z !:!x"lpMIv񄁿8Zu)tw5leviܹsnnnС7oܼy丫VBѸqcHHH4kh[VȲl3.0aZh/^lr,U݇%bP!<WXXh0'+i[d7+]`1tIV/|i:;jg^~eCBB+ewwwJRG P7|ѣV2x...ׯrrr{o, 0XZֱ݇<B!Y{A%xRnV8~ iahv&YiM8`?ծ}𼽽1|pC+VP]tAjj,//Oek<:֭[hҤId QԩIyJJa]Kⲹ:G!1<}&R$%x;$C1m(<Cn7&Ycԧ~FEV;wU4mTL,6  (ׯ#?*ڤTCeqqK\:9G!1lT q}M=y6تb@?K.Œ%KGwY5[Zs\m{d2x残< !'D_deei Ìؽ7�ѱGqt,I347N4,vX5֮_]#~wӟ<<<T?d#>>#FXZlε999ӧ g\n/n&*FŠBy H[ZZ&RO`>>>fLǎGagcQt lFbh<V'y(--[7QPpwGHYxDR}5j]"00b1A͚5E[uI3a,Wl7n۪U+|hذֱ<B!ɻeUVIFUK sqoL`+&Yx#)d?˴.]^bP!<b'MtDTT&RO;lŷ[6a՚ؽg6~^5ViiSNU_%*ӹL6ͪ<G!<I5i:U!ҧMK$U[U_JU7Ai}RBmV5;VMobMymA# if5nz 62<B!1 ! B`P!Pd0(xB(x G!`0(xB<xaaary%U;tƄ>˧8A#R'k׮YzR_ނ`m6lsÆ!}p[{G!vO)[PPoDIp͇SaQ""_"W/~>g#لl>sRM#x ~*JJJpUr wUI/_? ={*&⤤$ k-ʨ$u֮$ju=>s2(xBɶ7nXEqq1l٢p:OٮM"wpU;Se~;:u )T^}U4^zQ<B!GDجʕ+V ޖz4v,Rmmqo_DdG8Hc$|xL9F_'0i4haŋUVhѢ&MrCݲ2ۣu Ym]|9ڶmz{4(eӧOWT &wCh޼9lllpJ8s N!gܥ\iɒ%_s2(xBZE~~U:|8tR3x0b~/c:![Si'؎^O? vם'--Ͱ_~yuqqQrrr{y १_TRRRLwwwG_g"uEG ֭-"ߓ'OƘ1c s5ܳuɠBgqd%ky 1[z ?Nb}?mm{l'b`$''?}D-[m3g4O$Rԩacǎ& &fffh%{[ou]tAjja=//۷\2Y2xOSq꜓A#RO2R Ko&N[Ν38ЭB^}ۛ7G 8~8|tu$Gk/,00?<ڵki Ї,7nذ.e}:2/x&MA2i\111ӧjՋouɠBm2OVU^B ﷪d°S'w;u{7bccq9S}> ^Ϟ=n:xzz~lUed ^Őx\EΝ;###Tv.> i|̊<ZV,7uɠB#',%++"sj8pX UO E8$'9zWh5<T!綾^Rro>xlɤd͞e˖^{er<!=bjӦ vڥ') Yo\uɠBIFNM#h!$p`cǎL5CYO,#DE:"##h읟 8QҼ8qDQ|igggE+͛I h֬gLdKkԨv͝k߾}Jh6ler?++]q9'G!! [6::ZeddԪBʥqҊϜfL4FEEvr.*<E6XFZnPB<B!OIi@@ʢi!dbpo͙d<D2dջ~a<G!^d4JPN Lx{{tixxz`pvq90k&N>a#>aD A# ^M~E\ILr uu2`0(xB`0(xB(x G!< A#Bc0<B!<A#Bc0<B!w0~YsIy$ h Bȃ<`\v͢ԓ.]w'6A#rO)[PP^#9|8%^#' 5Rohܸ1/^̧9A# ^m~Lk %%%|8s\V (*}~AN8vIL%{Hae<伵qmUCĸ|ڵ/Xcun<B!ɶ7nXEqq1lbt(*=?^i Mcn:[rFlbF%.IH]<K*kzQ!<'f W\_Id%x{0sf0JakkkmSq&AVZE4i u`oo֭[+dYwh۶-իgQ:Z7}t5PFAAA0aG!qBKcU 3x^|#8!YUOO^\\^xOXݻwGZZa?9GnnB͛gEmQ&2du\ ֹ१_ݻwն^{ )))< !Q=< g8c{(F8np*%ۤdy69˖-Sٶ3g엔ӵ$&&SN;'$$_6he=[#x?كz< !D$#e qD$ދAϩu f]ϣ]v*Ce ч,^}Ȳr_i~d$BBBTV_64eS(xBCζ bҊe/ݐg(ooowm#驮֭'lllɲ!}񴢲:ՆI zYQ!<',%++*S&B<s]?ýiS&'*:wl綾^B||aɲq7'''~q}􁳳lf:Z纟gG#̃'96ȀO^K7W֬F{!OR읟 8Q͛7ĉMFJ3ad,7V&?h֬Y1ֹՅ<B@ݲ*$#dDʥ^LL N掽"F@!|9~c0(xB ADTT&RO;lk 8ڥM<Bό%OFWJsԩ ) 3dѮU,(x ! 1 ! B1 ! A;BQ ! B1 !G`0~YsI::,gb LL>wɸ|3<BUWDւq58RO_tɪ|7W ArJΝOCvN.@w Ns8|3<BUW䝲qmMA5cNǔw̒�iv|?7P!'׏ZEII |}}kIi&6{aJR$aTF]ڸ6ɘ?A6mШQ#ػw/G!ȍ7[l&9MG%xgҒa;y##Jӧ#//eee*G#B\Dجʕ+gmߒ8b "t&A[x1Zj-Z`ҤI(//7qG֭,یϻ|rmճ(XUsUzJuU!akkKdUv}ܹ777t͛7 n޼iQyUTc0=S!Pt "??_Sf#q%ml.öe8ݲ{d—?^O? viii\,ϛ7ϰږݻ7\]]M;d5긦<sU7|vvv8{ls5ܛx;t%#GX~=Fe>5>}<B!j<@?IV.:6JIv qUN4Jmz9Dv5'"l2m9s~IIIDtɰޱcGr?33VhU1iv„ o<裏LDSx<kK.HMM59_-.8zϲiSG!&` M<Ttޯg {IfǰQ5ڵCJJ~2HDܸqcú,+޽[+u.s!ߥdzix^&MРAEU\~/$&8KQL#Bmζ bɤvx=f<}rϥpt;Xj"x">֭UUHU 鋧ձ6W1_UlݺudTqyΝQ̕KN2wGx>)xB(x ,Ms1 :(NERr9iX&ىcђ؎-x^B?K/x~ 0e~oNNN&}gggmٲ%^oeuU1d�,C8{l/ϸɱG? M=<<>r2A>#FXT.}V;:fMˣ4zG!jσ'96餮ԓӱQ0c`Xa>#|џd'OIK nݺxԿO:~~~&7p{FmʨΉ'\y QlDX@f͚hb,́'8l0]gѤܗ_QzU&O\Q^^^ߜk׮ Ԓrsh&߇L#D [6::ZeHdlQQQHԋQTsqoL`+&Yx#)d?~<BUGbcc~ٰa6nܨ*"H=/̈́Csyq6""cϾ@l]`7Vw/u7 N.{xzjRO6W=i8֣BZ<Ȑ\+uBCCCqẼ4Js4JkYY%Ȳ5Mh~#B3#xG # !BB! !BB! !BB!<;vp B0o422!gի󄐺<Bi"Y!,B,'!|!P(xP!P!<B!'뗳qar\< ! ޣW͸rd73!<B!G\[(9K߯@qnZϗP!P87nfq(MއĽ]e4((ޠ}Xf-<HJNy' ~<B!'h䇯GiNĠ,+ WOw?B@'z׮]ٳ W !  Ap#Q^Toq!xލ*^avRiX]m݊CHXfBe߰.˗ձdR\YU<)?zV[o[6sV>gҰ-^cOBRCP-ʲ ho ,#%ћp9EQU/MCBp*e*`W .]Cqq1"~>[Gm~~nm29ntlZQc~0$ڂ'פŪYva=B=8n\_FmEy^¾ߋ:dw*\/4A^_\{'g̡<Oooo6 '7װ.ٽufRRRdyG@�]j=pV,_W}*n3wmUfz;<!(xB(x?Jx,=>[Aٹ( 0t"r|o7M3&Y9fOYm5%Tj5\~$YܵUOff]wG!`wW 7–$Hj[I7lyQ\y\1gLievHQ5C?C%WA %<sINIQF#B{ \>Vؗ(Kۃ0Qy!(O?P;"/1{9*,,ġÇU<KepxI?m;p8"P~q{4~.͠[𴮭}vݫJV]7 ! ^B+nwEI'pttT߫e{KqczQ=Y*:i\z vޭX*S"2B?RUE/\gegu)U 갴%umst<ٸI}26YQ!P@Uf,~3RPv_G� Omӱ]-?JOoTu]wd+?CB#Bk\س{YU>3$<B!:7ݩႬm֡ۧ01!BB(xB(xP!P(xP!P!<B!<BBC;vWfIH'??_;BV>@ r'V,B,QYi!Mߨ[UoX;BB! !BB! !BB!P!BB!P!BB!P!B(xB!G!BKyΧca����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/queue_2browsers.png�����������������������������������������������������0000664�0001750�0001750�00000337054�14035600052�020253� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��Q�������� pHYs�� �� ����tIME.)���bKGD����IDATxwX[W{~ν[d&qJ@B "b^cN8TM{b79q{&IwI k=9}9{~}?vꪫv ^X,bNo"vmk_ llllllll'#<ϓ ی~!,bX'|kyHب *XY,b,"禛ndOmFvUWbXIW_} HY,bl"=A66B~'bXJ'bX,v4 dX,:bX,v obX,I%(666(bX,(66Q_Y,kVnu$:)D}>i}砹Ax'f#YAeduQdtodH=czF_M |&D/ɎOge1D4Ś"Cvk*<iy6wj:7߈tҍ[<0ř[ѾhM9fJíxͷFŲ<-~Φg@y5{kp卷mzߩD'=&z~LvT:}|ɧu܈!!u‹v{镸󁇱Mŕ_cщ/w!7,=2Ἧ{{t};dboE?{iuҵ9zF5"}&soE7bmzG?~{ݒy6`\]?{O6%GMnMֶ{|Eo|W_=.o G׏E։xzt-YD21DXY-kZHtqu"gλ3wH�'&<׳/sdgĨ5.:}y\n,p|XNנb2oi絻\/ǟoםC}W"|}عwg]Um=,?s�׽QDtdc"MbD:Y%lH+bdGп#44Z?L&ɶ]owk%<?o3/oretTBѵ>u)Dz{Y+{_DT61D1DNh}_O>\,G;x{؇cI0WrrirP%㊫'bзbݘN9mgcz;k7b B6w0'âONDDKE8xK?>4z~$.n|g ԋ0R`9O'ש-g/]H {y/:mJ-ΝހWx\wj3i/קqx-pÏz7`ẍ T�>N@ٱ}_'k2(66cQY,r2 )<~!81/֍X69_kr *'dxэsJiyX:v5o^1b@0@~amcsOtou="`"5'WZw_iwM 'B;xd-gsгlo.OGq=6UyS;,CFp];ٶ+U76f9ٻ5Y%|%l_zuQ]b6ugߊۉ֏ PJ@Ee3=CC9eԵoCKTǺrwBǯOtΉʘ7ߊ<8K/cC&_"Cg_t*Z:?G(�ъA@"v{1Dƺ#;⯭B]%`g S,xQɶ[φdx]ʨ[z4ڔ#vm7%#u}&{&kɞDϏ?ONvAEj:j8uXDu8VuWjn||.؎ D},֬%/3ϿDO)RϊccJb_Hq'kR2ʨF_|S=dGs~4n'V~52Cѣި;_xWnw趏>h;"\w۝3~Mt-gɧ%L@;_{cs4Oפ}8\.9cN"z&k1_'uOLR w#?fvyQxеNv~RB]( h<̆:лN?QDT61D1DNxѯ?:_ico|{>bLQ#b9$TC;>둮q:VF!*;?LXo9\Pht#jMbw7Aeb;G^[φ26J@x{XoJ7JһF)7!8jKq�>F:2d4_~95Y?ۉ`zG&j41P].uhg[Im6XՅEbcb QlllWZx9qIm䀓%ZHdCXh'6ajm\_~cB瞨KcN(S,XJj*i+ѽ&j< m@I }1ge6%O)C}czKfwkc'Y7<QČL.1'gfXTJUUp`=8,%8i"#P�xWv@w}bSZEݯʛX<16 bM.(666($uѣS4Wuuۆb؎ D},8b%/(666(bX,(66Q| bX,I%(666(bX,(66Q_5bX,I%(666(bX,(66Q_}bX,I%(666(bX,(66Q_~%bX,I%(66CO?bX,CCbX,CCbX,CCbX,CCbX,CCI,FbX Qllll3(rv^vAqas쎖HO<uwgiUy?ןp{gol{n3z2DX,CqQ >1塆αKD={7y[^E'$D})p⥗^>h6xyX,!UNU\3Zvcd)#{dA~ ^~ń}G8̳(*)ێsqTO>YgoE~ \ .{7_<g1Z~;/MXz hKS~<Ԥm0=&sqgn9+֬=G_ktgx/̳ϊۏ{{9aaɊ1bX,(66Q/Ge5AɜDQ`׍7˯%y9b"*oрD|7G6 cuciuƧC9ݯ7vps ^ٻWT]cX_n1CN;Hu]u=&sqo'BG (hkM\/L\蒝"DRwU{{LmMGMcbX Qlll 賵K[n MIG|Y^Q1ο X$d6*)F/Hʼn?楗v7UjyLg ]n<3Զ4n*�S=u=/^l?ot2T6ѵ&{^4g֎7%!ثw{ɼWc1mbX,(66YQws%_;kO=Erсh?q-#EDQ/'֥-vL,b̽Hp6=iY$M}=:3Ͽ unl&d}4QDHR0.*~yfX,C,(S!*@r>cݘyciLUN~ 8@T?τ puAi$j{ &:hFH=kűz~S=/n=\4 q"SG{5>EbX,(66Y Qmq44и@t(r@ a/pNx-z(z3όwcPe=_05&Ñt˭()AlƎUjjƆMg& QD:zHzrMv\xq L N/{7 bch9~b؎eveۯzvN=7yȁ<]p)u,p h?eElB|U"Lv.qϖzQX<Z 6DM3uz7zܽgJi={Η{Fh<dX,v!bX,!!b1DX,CCbbX,(666(bX,(666(bX,(666(GbX,!m:K/X,bTbbcc;$/Y,bN*1D1DX,b1D1DX,b1D1D=#pe*Q|IbX,!!jv 7 ݻgNbX Qlll QBٳg݋W_}uVD0Eu/,b}Ͻv Q�VFwB)݋{!!j2Q9^{mV@_,:zQuCc܈6;*WQ(3|%żzQ3fLLP4"1n 2FHCF,@2,.J[0!`0d4hF@دuy)j,]oAM+ҼZ(*4W'ZR TyV5UU;!-AY fHsUf!wS#S@ c!'4f8+q Qlll Q jTL Q,:*T@g3AdEՋ}Pk6f3B m ÈyU:H PWfCVmK46d Դԇ rjѾ.gzZ=fdyb&BzdA7FL. ~RtXӌT)*ي*3M%{0jC�jbdBRF�k+j nCgF^Y-(֡*]ۂbʹ ΦG4eCa@F `* `j5C Y_ʇs!@FSF(Cߌt\F肼€@ D(An2/}gŊl"/)@A UBtXwY'L%Z `PAP%Vп�QH)UWy 2EJ3ZhFz%, b=u|O?ŶvSlETF5zEh:h6XW_au)_vX|՚1qr6:zɵiL簃b%bZ\XEv`"âlksжPhDfR Vy� wS$!jVa!S�Ue!<v䇭!ujQ3gGdmu:`7 )zD74*E)@ת(p7`/@&]Rܾ`ԡ �Su% `ؼąpG.͹ G1D1D1DJ}'mhRoą__] n; {^X$Bƃ=<Ze"qc.>/hYB,+.v*g}wD{7Gn񹪍f \4zkZOuxC{N25l|hBv/ 'lF-AR+&7`lC7hs Q rِyQG 5gEvG\jHzfҥ!`AIƈyu>:X E0 0:u(cM waP=2HΧEd5< |8vX`ՠy(B3VP@A�Z Qlll QA35uBE1^fAۖ\%n};7r CИ,0h+{Nz-D!q/_0�*FjeqJ_[ᦛ,IEʫ_�; bQ'N MydwYZ$@W_{A{79!< gDžad1eM|m"|p)o$ɞi2Yvd'ŚBÕ=TGgP {w):G̐!R-Az،Uv[Bd{,Y-AP$:Zː_G؂r-5FDڐ&?`iHne s(-mX:ͨh LVl"`@�`J[-p4Q g B W ̀@.T>j3D1D1D?+穧ڶ{S67 !y9IJPcӔ[j(񦃺,)"xLe K,Db}?I_d~ ˯ `"UWOybL׆:CvA|s>\kjÍ 'i]3=E:8M{s.4b%12%-+zQ؈lT芴дT(�)=hu` 7iQ6aa;<ù(@Z MU}dUz5aj!6Ψ Y:(&ՙ"[̀ ֙Q+\WCeԄ6 : nvrЇV]ujUaΗ\zਲ਼!\e ldabcc;!D637oGsHF'+DQt>ԭQ4h<<cg*.]S]>E{GSԉȣ=ȣbE1/@ݻ5.zW_p=xX}~/ʔמbF+ŢhxIuop~shgB9D0*U]>D"Q>d+ 2lFy F=5lW‚zF QɆR�M&_'�W lȨ͆:J#C]dܣK*z!+VDyS,A۳nw*jD` H1,TuгƒJ-\zvAWoFdȍ Y |ia !H'&Pa)AvM>J=Ypк|(666 Q1GXrhziY�QȡNRǟxbtǟ|r6l><c:5q]4Ή\oSPXNcvMuKtDj�V]7fxXD;K/<ع'-B.%ژιMdkj@7@/@ܭiMX"& A8ZW KHQ7lVʡMPHa `%@N@ iavĮy ц\(}тU-C` E64/Ay KU.zV`T`Ѧ!4 6c%hΫ`/Wc* mK<ԏ*aP/R"Ƚ fB�*sGf D%>^-(:eJMݗqI1}H,V9}19'L *RLk? |;ӂqYO2iظ3<Kzv .7YN d!g"GQɘ$>B7Q$*Q:<9YxQJ霋#Q,Vv |fE̘_m@nJ2Zs )ծiY.ƲbŰpDtz;Fh@Z4BnW4EȊ8,؇J,= V.- bj\xb\seMرk#ZmDtu/Gd _P.�ҳpUqٵ#pjk?oYk/DC^ 4?�llG؎_[c ps8!*BW).cQ1rrqAN1S# QH,q j|<(wp DE='K?rˮaXwnu,p/?,&E&_:W9&k/ʶ D1Q,4Sj,(6n=40j`#%b3d&:6Y%B^+ n X i@nЂUj,ևV' ") WJ. 7@6vqrH)V"%W{%&H-V@ݬG_gBS2lv֘^@gU64~*hY'Jp Qlll>cѡAxzr1(DDN}ӡBTL^5 Dݛ\@ԫdK*yMq~AGb%Rԃ/<>Ջ?W�<ƧyQqQ"l1\mUb%(qoDɤnLq{Cu|Ë)^$B<G=yYq_:b%fO;,K{tvBeʈ Jkl(j6 t=,]s pt[ EdUܐ5P7 #ZX#uPҠ^j>[-PTй6]F@[թFr D!ëĮŧ̀9r򕘗@�]5f/*(fTj sӘߎN?8|y(t0D^;Pr'DsOt}gDŏ"gXCT,k܂x !*"1w *Rm}4FDM{!jl' {T)>7|aƏY~X>ќ&3籉/%+`?>S=Q>ɺ+=<M=VvM77vWMtFX?H?${..]6bn7#@ڌ̰NLP٨C5ZREd- Hi5!*@ b,E݊ PZlUA_ĥGP1.̯<mUPٖ  kp] MQ\7TU5@*4OpD(-eMej΅EpЉ; *+T@p C(U;1%W Ni6Y<5b6 bgDX@k~w"_zފcrt]gb%-#Gj@V&|~.5EM h]lʄMWrKjPԏ>C(PXVGmDB%ʄcm?eVQPEiprz(`LREMj8՘o@VD]GkPׯFtuzDL(CFQʁ%`GӢ Qlll3zM&$ +b1-b Yٯ!$N4|Q,QJuCTAۀy#kAJ@΍Qt-7B-�PӐR�BTQ]=l r<^f@tyȭ˅5hB�a 5>p"4 :b-,[&#~%* er zhV\%CShB0,W6iӠz;BmN, @3!CyS>66хZ7&(66uly5Ya([ iET bN<2 kBd5aN)ZX}:Rcad.XNt֡WK)uzZXB+vkV`]*[z(@VǁFVao4͈L5)S k` Y` bM R8Ֆep6١tQߑҐ 3rjh.�J /ՋTi]& {}CUCwKQ+3tm9gی3|(:y!+2jTQVaBB6m�G4eCz,AF^#l\GJH[_. r1Kf3Q9Z4ȫ7yq6z4lFBVلkP5`D˂l[&ZL.8͜EP{LS@Ң~B@3:{44@3!+l"`Cۈs(f(66Q%đ(kw1Ls&8ZQX,kǿb�6F+Rzxd!إ4Ѡ"R�NU.@qZ3l\F*2WKHhѼȏ*gY&kQn =zVjP5lD"VZ} &x#j7)W-GqPߕHu95์))%JȮU"ݣEM: fY)YJ *Ѵ 6{!X8?RE)EL!xKq~ X]# _Ͽ)/UsIOkWV1`XcQEN65C^gBqk dE:[%8R KS,F z5e4>5V �bJD|:;X]jDh2y& :0^O=hcʋZh#P|)[6tiAI܆heȫ*KAM`J#A=sй2!mvCԱlpCM{8dx:\5&= RjvxSc8z9\b&Dl #3l1hDnDh 4(k!Ts< x?+5d5X&֕&Z,(Z,Cm]+.0erбT 8R䘥(JQ ! l <^9"QJ,`B ECRvV-�ɗ' ZӡN)rs!t(+ׅz+J9(;o+v|@TL4pKQ1d,Z Zui<<,Vpxs"Mm(j멒 kmqΥeVǚ1h{??M,6Zv E2h@NL=YiN%7Itڟ}~Bqiks=MV/BWPR*FG?dǐbM;E^m@Z;puḱ~Lu(h�Qg3mR#ݎ.):W @i7 2GtDe(Q"GIM t2T6)PcX&A"N}nFYnBy]6XP>Y P$CV)JBr/D�.hIs1pF2+rxJ 硤1�bcc%5t8 *6?t(55jhEen;w$-)#QՃ7 ^7m"u~IM,hw:4u՜ M8tФwuFKӋw݅pc{~bH8 0([}zv Y,ִ a_ܰB29d4iPS2HQ M璠s KжX#�J7JP,@NR̒ȀSJ<)TR xR^ mTКSиTlA),52}ϞL�P~*Z4ѱ&+pk/mF05ّ3cE-B Qlll QVY7G9"4N9e+셣5:fnL GhRu(N}o5GD(R=;&\b&K. ⲽḦ,{ ˯HxOwS|ZcbQN6D?FNɑl >3ڗ h`"1 LW rUbmv#HS�MTT7P")"VHєBȪ@�P%Yi`ʜP �u*n l%N+"T|zku"C09Z ֭Rs)cbccc:ut2C%O>Bb]}n bwr�'Qv:dי t.@O?hVfHpEs%:'R*{BU0$ѱ{zl;}݄4Y(Z*J9zKWFJzLԦȪ(Y肫I߅t7 )>�U: n)@JtɑY?GP&JKв@J*RQ\)H&vP#SA|U`im)mz*$pfe§(A*PצDF�95Leµ3S]E_cN&R,d0@&l[%P֚ [CM_�N(666D;jq$uZQȣbhdqR%&2L&5qG-R)fߣ(ԋ/4=S{;cNchkZ_FbXQ3`T )uuٕV*qZNN�)LWE5j !+OD=* r4ZiМgƊPڇ/;?<?w<llG@J�) ʀU9f\TemLh>(jPސgԁɕZ-Έ&],�\5h͛ {ECCCQmch9~)nf Qgy1Ql<k!y Q1Sם>=_s)E:S@ZuM3 .X?ʺH)JF1dXӁ%Z�EUi B"~SyqK5THqw.9<] oTZ E]Q=wCr 6%3Ϟ_?�v|gv~LTiӑ5ܹnIE~# Zt^�OabNRW4RԶik5pv +B[bFC9U9hfbcccb: j4;_N.X9&ko37{^<M(ͳe/p](D-ꚷv1s?%{I>t KvcF8;,k:U5,ц(ȄΌ<d֨eYȍQsF9dr*q%rmsPPpbƽI:x^|6vg/ߞ{:7/݆މ} p+RSGz9AQU*lhPRT 9^{l0:5S[E& X i ZԐM. г<*/JF;bXG|K,e>dDloTU 3_TKp(ZA:5rm.89hYFqs&J4RDs˃GoO_?߳ ?= }F?o^=pvmY : NɩN= F)PߙpMy,8x3P(�^ÈQr@-BZ TN%uH@bP�KQRubAᅬrՏ:U^o0 *9e?(#ei%rAcNSV+GjXV,uXiи3a@JL kp/޵ 鹫H=?={~zm.[.A]B(WR2e 4-)@v fjkˀ-,ͭ~%Y# l5"՜p.T&P[NeX,֑(CA5~eMEEk0 Lo&u:Hk4 �e/KG^ v4d T҈\L ф;bs%~{'MqN[o܊ _=Crx5M{ 2PU!-AK_:BiH7G?-ryڐj^EN Q=rDrУ oCCC ؝bXGL&Wm2REpJy 4tX[ WcQ3vɑҮAˈ = ,1/ s8?5C8ݎkK#xpNlbu k{XH6EyhlπMo" , \WgMl!-JfBkѷr={ (6ۈ  tg+Ѵ[eCCDGi٨_]#CԉᄌO1Y=^'sv81e'A Ҫ4h<w~$%]h|JX(-ZP$�#jBL,ݤljRϔ>G*h4d(|mømei}Kxj]�O#jkqvTh3,H mIEǐ5pzRlVnT]#CMVkXl*dhٚwPu5F ,0 !!j"=Ӹ[DX�Eu:Eii(t2T6Gډbu u8^!*pWTM}ZĻ=S:Ru`'ͧ+w2Jsds f%սdA[вsW.e_*S#e(c[EX"/Ψkqnz+޻?<\ۏⓛ‘0-,)Gg #Y,̈́, XN LjHM0"%C;y~ duP6!Av΀&? B E{lՉFu<!U(5!ΛNȏH)n6C;dDovlEoGfrn~.IC`JڕJR!?*~е L.9~SBZ e`qv갹Ňu.\Doyn[׆? v噸\؋.n +x_=؎P�?(o@Q ,Rɱ`NAzȀu:ʵHIa.7 @�E*s G:(5!!u|A+S~WM-SEȼ�y}h.(olKx4MK8,6 Ḱc6(%EsPwso'DڗҏbB'Mhj+_+~d$sMdS2gFeS~EFrY 8_xr /R=g<g-‹֨NT/_l-=ؿc>3qkLM9vwݻ,'|f:!+_r$p%*+Y0΅# {Xg06uH2́*52K2+4=+(�dŹ\WpH9o!~zJ|x gy=_Soބ CbȕҀi+Pݗ9YOt2ޕڐ9.)}%P{_*v0FM$TG] Qlll Q /xcL9S9u9S9_P# uvފ}6o=G,[v9S%]yxfq1Oa[,riz-Τ'rHvɶ/9ǯ?ⲳZ3n;wZm&sl2)WN6l:'o}Z-nk`.pL]Nls#Fbe?xMj;zF�m?[xFuxWnnlؙ!%rqK 1E -KǿI j%תɎЀi^ :з|.oD*ap�/[7cܾ/\?ݿ>v5||M8p*|z*|1K< }A*W)şy xpe!=Fj%]:x5+` д5% 4,ט^Vfbcccb_/O>dL9"@cR I9owHcb(6!X@z8D:E$h79'W[n]8Sm (QNvɶ/9ձ6}WXXy&k2&󜒁(x}>|1Cch�ts5չ+-EbugMxnP<sw5' WUXѫDn{*r[`�d>B}RL(*O&F2e9 u]n1#jBؚ\x0> iž㧇/Oߌ/y�s=F|6|{6\ Liėé['CYD Š-r4`lWYERB2*T @#iDn +!)!!uE 3r瘘DeE\uMDǨ -1( uMm#;>ٽ<29Q]Fmm:my%sl2i:(+{'i`'C(S3}SC5IO<F"h1Q'D4 }:e~(J: ~SwK3pjaZZ"Gm=+2DG ycgϯZge5>x~|p'o>}|]#[}g`QTxQՓdGEYZ&Gpu*V W&ARN+DR52d94pvj(V!-' 5μ"wW CC(.온s)Jt,!j&B{L+(GN.uE2}z7S8|&dd$J:gy*()MApvuMcg>ϙF&jN"R>g4Y$ړU8!B&¿i)AB/zhTkj5ptuhWa]t Y(<NZ3̀<w(Wò`.^<h绢xV|u~sZ;77{/Ɵ\ܿn NF�(LHqJ Zu]Rx3b+�4%a*[UBV"Ք,<JȎ:V bD`1} Qlll Q ѯ'4)u놛nm`K:쭣cmhLI2c.% A81P2>4'rSm^Y(1MvķіsMM=dM9Mo߾G>D&@kMy.(0E$ (FI&˘(ږhL$[u@T^}#}!l&Ҳ4k]ۃgwl+BY_S #ß,2iL-ji2foGE߁l641W9e㾭 ս;kRV > 3T7iU( aL9 L2a‚к0'?|%M:iぺUpx(9X<QR"H'e?2Q<ꪕl6C5K C%sv݀Z1#)=7λWFh2%= $}|L7|B[PgKM&{SsJ8O pADQ%:w,kOy.�1\^{ÙgHmG&:߾f$#g/D1%m6l CSBÐ 9T*gɓ"JԠ:aR2aa9F$8J<j."tfgө@-V fr-z,QLO-@ToMǂr -JiEXU E "CF6b%ugZ8op UZT-Pߗ+!!uAuGY Q;'U\`#+=_!o(fsV PZ)pDe;S`vAvu& I|>TdpaS*,XZu-eXΚjJhfB>~<y )`:x׮9PU#X_5*T"V&V:N1`W C Z5rQکC۰z=PX Q,luh9l}& QK)SQߗY UMA1:ҡPBYB:*#{t/"IkcN/־yԥΣKCb>2ZmEi�þB u!:̈X2PJE@-G81 xe^0ԦB^#EU46%ʢ-(;Fa)Lפb^@9eH*ݔ];;P(QjyGQmWAogHo*" EtI/i*EU@D)ґkB{ͦ7Z{p͒m!&}}v̙sfggggμƄ(Q4!KeXsiѪ ֺsХ'_=^Vxee<Ҽc@3L 6\>_D~o*HJTGVC:/auN jݺUYxQ|M]-_5С֋x΋h׵['GuG5{B.kcWo5TջFתGuѴS4-{E.hv=|4D(@zhײ *QWZCUKv%|:FN=aAǡuJ/ VUGD NC`7:֨u_DWkQ4DjbpZF5h\ @ǗiyKUТ`x]�NMl]|4>y FAA/Z>.z]5Ѹ+h |<>6j]^F1f6#:oA(l@;m ~o۷FɑʅGFےڤ*S uhXl,ӒVTeQd2$D4Mק׻A6/!o^b׺Khe{F_ &VE!� jЦg]t֔oB:ImtmXh0j5t_[C5ѧYMtyYs԰>z:ޫ]}BѩVY6M#ۣۈ1>.F}Q2*R_P}?jjՏ^E۞к+xw=Ty.:MhWj 0`\G4HEQe�"""V LIDղ,\x{"99:Gjߏzf Ǡ<Y*j%LFa+N"D4M=zg+26ޛoj@UoUFK N&|U #'WGCkI&TEawB- S&fֲ65Y@zUѷEM}{.Q^{ ]T\u>lX=4r$}!s5�'0y a |իx{` 2 jnX5A ЮW;۳ m(*%�e˓ '>yyjYbd(cG6F7m+)Ie$J�AE4] rx[M|Y+в27WZh͏^>.j`W5ɗu:xb]eV{_}~:|4z4>c= ^!oiKL oS4pJ5t::Zw)ӈI HNMǰaC'C56Du1bYѢCmtջG:EVh54 {6!DQU:!;ysӖ-*#Y殦?i^[fR`dr2NcbOsUN"Q?IeJQ4MeѾ:J*-*aZߡ.&By Qÿm0d1i,]GN"0( Qq ;]ѿY VUto\ ެ!4@51zf-^mɀ1~ħ D\L,}D*~X.z ~ }G7z3^4bR} ]fφI tH(BTБ#jݎvT.BIS>m3_ZZNy{wSwGLh.gq!iA?۽k&U#5]='°_/$ ːuel0mڨ]//?% 4"q:k;o_t_ʹ^nkcY]iPּ@[ZjU5sNR iDFiۏB67�q'Sط.~#5hT|}M �Ͼ}o hϛaԗGQT7ZFJJnFsK녦.r:|wDDF$ QA?%iQp tXNi#Qͫ^Zh%<EY =?Lyf DLy tnBbr:b4X *Q DFF&RRӡqڷAf50@.j֢kPUKMswm:pDaA8s1 _bwi! DTp۲ S1_@Q/c11i4BN(&D5kQ5khiJKbw SL"*:-ڼm7(FhikFj UѤgU^'EO̅eaD%i dee#11zDGt7! p23h`|q|N |ؤ67oDfu5ݦ_'lt߄~0",4BsC"x bbc FHXtiHL�Nc'Nb}Щw#*F}\ӱ6^jYEQTلU;Av ϢKֻ! 0|?e6|sPHfV]3Qf H4M jػ:Zc{bG|T;8ddU`p f䞇N�}B9D`i׺L XǐN1]̛;ǏYNjАG"*:5,I\bbOS!>!!8;aO 0~� ]nuO(lB}MKLz~_VMl|dYݼu:ME/<M*wh  h<hpVFiD | *Ͼށ B.>e U)*HӮ]pTTdhTTT ñvN8g6l܊Eso`nJO2ֻg!86{>8~ IEtaZrϞS1CRrIg#U$*5=:CBp lFm{N^9&No(*e>;u9y@` zo]RiDu008t1�&9'eBMGD鐒8} H4hÆM둞ͱ=x<b8p°p, ;~msasN)S8yym6m٥ b4XY3Rpt�b)KRE%$#<JS>A8Avá#'0~:>2! QƁ۾cᡦyK=' [? 5y(ip~/AĩӪ\QMHJNW`AU$.{Y Ð`@_~SpDi@&�3bnE/X Ԗk �COP Aas+Wo>!IEƤkaZzxCwgV]"N?Gz;Ao`]QE~2|u2[l9/j4M4]B G#1/ @*Q%!5-[Ɨ82oETW?͡: lw1dž8yZxx x)Q?~<Fl>QI0`"2*Zj0d3 I pq tڲ`\JQ8щ?9cl۪(J=Dٻ֧|/iix-#�wBllDjM'&g((< !L % *er]ػSA dLD$"*LlKulH@hP0o!!))i uTx:}6�O(y*;bA_XɩYط5w}A|>uMn(*E4MtQk Et^Ed3j0h`"37@ 7;y /DFF#<,JNdD4 xB5 U, >~i!!k%XF#;(m:N$mgO~jX Wzf.R2 R'}p{}Gz6F|:EQ!iioj4ȹ,D:t5JOV" (y&)[CGNI/Dǩgjd)K4)99]mK* +4LII*ѐ / bW𕮶JJPQ0X 5aՃuR10hb3o@`h|8vq4i$DQEiiy X푨Qf$jȸQQ̭Y=Qu)9!g/.^AUz^*ѐ=OL0hCdF^OP`zQoTdzYoVf0IBAT<ZYb4 O�Bãᯭgʨd"Z+kPX<b֮ۂNit } ?QEhi鴴4?m VCXxBw PQ39}kd$%g 'Dfh!G#`%V>2�I^Qt&]礧Y$n^!Aah"HRȀVl|mE?H+OV3l!ABR&}Cq7V݌_A> |#!(BM4Mu;pP='$.k՗ʗ5K]NR7k]QEhi iBEQ(iiBEQ(iiBEQ(iiBEQ(iiBEQw Dedd4M4MU&DQEii&DQEii&DQEii&DQEii&DQEii&DQE9QǎÆ j*i˸i0ߑz(*M4MtXիWg!#y˪'!b(,dgg4M4]r|9uu|KX$DQU,%'yy hi."U U2غ|%UOBEQQyyy*$N4Mtx}uAW$DQUlŋM4M=D]xѥQ._IԓEQ!iD.$!(BM4M:KmdI( ڵk4M4M*#ǹ ʙm<t]@tL Ξ=-[+˴2SI(A{?]8Uc>z X'α r4Et_/\gJ7/:b4MkN=`rrss]j{̶:6BTJ2-i2-yJ[= QE * wWCT5gV^¼Cw 2͇TK4-8>gߐi<ю@TNNKmٖD|OeՓEQTAڐo}+3M˥9h>^SI]\dUt^KLy Zl<u4,:)zLK:BK=nm`ei;\ޔ8W^VgӒasl5/<5WW`lڵX;׾O}j۪hRmh]agxe{]i{6V^џS)XzIS,]iKPiLH^Y܅&-Zb{%]K'!(BԈ xyW\,81?8X`ޫ؍ J�Zl$.aY/w ʟhM˷Ό]|qۚΉ[*_p9mmo.5-�˱afj[iN' η"c?ŞX7o0iGk$DMn޼Xℨ_,1zJq5|T&iI3.mk R2o\&QEyKgTƼn]Qҭm[<g l0eYyvIb(uu>49i}N=%}F&23P}V?ǫ_P3]VFBvi>|ZTAnFhCJ7n܀>;`5-Jg!*;;a[ˆ/Mqf ʑm{QQcU><&$umOmپT5nn*]>i\E= QEDO㋝o._FH!rpq=:f ?|jtuSP,} ^4˴9ZGK �gioNg.C}s1Cuid،�|8eN'@%2, vVش/mw:ݢ_\YqGW~gI)yk]בWܪcor}t2\eo_.R˜ݞ=rt;'=O *::f(ko{2mL7sӴ,&QEZ]<DRkׯO{uE`PY-[. DY.H>;4 V%q`m'(THee^S=yZH=оЕbh.ULw,K@TA UX**|ۡe_/םOq(I(ʥ%!%7V 2a.ì6w+.)(uK"uEgz&JG,ϔBCG+X{Xe=Zmtn5/;?^h<WO%y;Lg3Ql4]V`BT\f X(k^{lOb.vA#X MӾ4ϿGDDL<Wqd2<W2_$DQRRQKQmg.#u[/ĸmJ71/0u]Q}mѦdڼKu95Ÿ !]$$w;kSqe^>ɧq^"[^(4D]~MCF祏b ~)J/ճp[~bCr R,V>ڹZ'T9 Q酶Ew {6l'\H^Y2J+W83$DQUl%i-m !mN!(\eݷF{0`0<ɴɴ)m$DQEiRR@TZZKm}A^*Դeke4Y&yJ[= QEhiA3R!JMMuA3ےQ.]"?2o2TMK,<( A4MM8*{ۑkJJKmdI(E4Mer}MNNvAW$DQEiiB!EQ!i'D%%% +z(*6((h%DD|%QOBEQQ6lիWy("(2GGGk||KX$DQU,ヽ{… QEQTBTBBK۷k䑼*gIԓEQT@ O im˵]H= QE D4M4MW("D4M4M("D4M4M("D4M4M("D4M4M("D4M4M(n(J4MfBEQwQũ3gΔ#zPEvK(QPvEF(ŋ EQ/Rk(QP"EF(E(EEQ!'aco)*+(ʾN!$4EQ!VcǚKׯ_ǒ+wʧIG ;GQQ?hRZEQ!2G=b5bKlQl9 DQ!(UIl,OC"8~~Ro1yfg 7{:utl[+xr؍Ĥ$ۦ(Bm8r' D[aQ(B Xaf8y V]6^延uDƪeVV6uEQT `uQ\z5(6.\P'霜uwv/_V'qp5}pN775') xbî&G󅅇C #69+Z˼ <~*Mnx5}HTer= BEQ#e ({%wIN)iډ֑zG>ڽ²6.Ny"PE*DINϞ;{6Qȑq/^4ݸy]]wy!eَ(*7 )g�DYJ"F~8O #nv3K5kd%˜FQv%�Q-]VMiQ!v9qm܎�9h9Q"DQU (g!w*ߴ3(9!h{v%. ]Kذ+Z-s"Dپ8qmDSH!rQ\9QT%] N#Kr䙨@YlJ0U~WΝY=###SI>eZvCQ(.@^v D5 En#GƛԳU=R((K`#DQuWAԝV]Nxz63p߸Qm߼kH%]F Uyvş 9[we$m;wd>ʲ"DYOw'æ-[O,>Z/(n([#8rͶ7:H׮F#DQE* 7_(׊O2ž�9#BEQ(6( ;ȱ㸘ITJ I(ŋ EQ/Rk(*:Z T!#s_g QEx1(ED(ŋ EaGQk(QP"EF(ŋ EQ/Rk(6Dɉ;w,((X~@4M4Me5{oܸqdll%E.]޽{DQEQEQGҾ[~}Ν;!DQT͛ .^?ii.GUDEQw.ϤP$C4M4]~-[ DQTHPGii|͋EQE 6B4M4}X A=܃5kbǎ+u3뗴كʕ+O?d7ڵcz*x \v͔&ԩ:u4M4Mt9z=etV\.a@s=۷#77C ȑ#M^^^ަ#F`̙!BM4M4]%лwo֓9sgŽޫҮ\ѣG'TiI3_g…xCq ?0.^W-?h֬Yx0{l5/`0X'[f̘J*V~%w#DIdii..4D-$zaw;Du))))SM6HJJRnٲ%NoN:)>}:6mj;7o|믫:wCK.j~׮]h֬:*X֭鐓^zaر(iie ,#DRxxi^8UTɷNZZi>//OEIHm۶ݻѢE .ht{j駟Fbb"y5߭[7,Zjlzꈊ2KtRVw#Dɳf4M4MtvADEQE\.p/_6˴^[e� 1E6l W}^VV*T�4jHɺX"Μ9cN'@u+K7OcwOBM4M4Mbw> RD)<w$e=BEGG,Dd` &ǫ;U'jժ(X4M4Mt,!,a8|D L<5p@C2ŋԘ1cuj2DHʼ{!jܹ~%J& Q4M 6>0Osy|q[$ih9d/>O/ڪ#N~W4Ms*oCa+J{2qt>6,DFSO=II[5oܸqd)BOl]t%yg|Am۶ݕ%+MwB:h6l4.hfcz|:_ܖLww\yi!#1r8壠(k^;}j_4]DחR!80, Ep)SΐQn7Fd�Č7܌7̗:_t eI)|ezNn.v>fͣDRLQNھrޟPqOu7.7|A$eQG,}^˫?RK#'! 26NY%!(%=EDžK٘\L~JeȆ1q~褩xHL=YgΨeq|yeZҌ9N .ߖa/'cfw}L,ת[u|W8"F ] ?:xDD|6ڃc&.'& 9-]_Uk1ZȾH9CTϰm#.Y_{KV!!^矖iI+QEi=.cc{j$ڄhD1 k7.;| T7"$"JDusr IZYez^ed; Ο׶k*knD^,-`c/3;[mLn(TF֭,u5vCJz> uW)u נ7( IwD@TAOzf7#,:\~oYfo_4D*OHTd=k8FR�Q-owP5cbWnجƼF2Kvhf.UͲl0w3rV皳x9%ver4x+rbTzf߯κ;I|ڪ1@_-Ҷ  7uv~m{Ӏaa8~޾i:t6_R.|nEQ(1Jb }F(7B4%cXWHݕٛ h횿r{n4o})嶍#Y"dIp۶Ku.qlߤ;!*9-/ =/l>}w W4]Z�URP\UKug*EQ�dD˿H9 XkK)�Q}Q3g$Nk=s]Q"v䔷 dq=/+h<}>=sϞͷt<pX'FWі ;weMQJD+~:tK}ߖQL'5/ϒI#V2ߒu둪3O֛d%FM<'|}a9}Z}%ѸW4]PWE}.|bnEQ(4$d/9iߠרqҠ*V`j85_͞!}>:#zn\ϼ1b\VмFKrjZfHX'~ߴM 0p,~1Ӫ^]z04E36.6$`܌j 9{x2GGe~/ S[Bj_tqR *)6>d'DQT)(yƀo A.&]׌2$d:o8|Y2g'2.+h<drtcCzwḂ)mUwceO2Y%F {PR'㲢W4M(E4]6iBEuyiiEQ(iiكVZᡇSO= ;;rxO?_vmO<%ԩ::wM4M4]M[oaݪcFF vڕjz}vw}#G潼TMi#F̙3IC(ii$DWBBALϙ3>,^&=O>LK: . /a7Fhh|ᇑpzn}I4k,<={tYn0 ɈD3f@JTt_~6,uYiiUmۆf͚:v숔Sڔ)SЦM$%%)lSNͷNN|L>M6͛7W6|kAzᡦ;wCK.j~׮]lY'[kݺ5t:rrrЫW/;E4M4M(R```!2B$.%SJ|뤥}i&"mVuAlѢcIYѽ{w5O#11<֭-ZdNWzuDEEUn(^I4M4MotPǎsj=K|t%Ӓf*[Y �"H 6Tr \zYYYbFT+XbE9sjlOW2$D4M4Mӄr,www'#,H$玤[Q;vPI*::fY%%#N0A͏?^ͷoީ:UVME8:ii˷ Q>#""P/23Q-'O.4D 8P !ŋ+�3fݲ^Zm[HI@,,D͝;WO .Q2Hii QTAtߓōɴy>g!Jw5jzt(Dk޸qRR'g|JdҥK(o޼y٨|PkJ!JD4M4Mۄ(*B Mӎ{ժU4M4]L(BMʃ((Eӄ(6(6d)!Q4MbbCx(Eӄ(6(%cEQ(&D@Q<.){("DGbцVްa<==BƱcTZOBԝio)KG1TyӾ~ %DQ J�j׮]Gtt4]JZ^zm 0$-Wϒ <k.ױd )wҐul!)c"DcfђXz !JDI*&&ʢKܹs*RcebnW - _efC ;=6Q!EQ%QPʅ Rd]R\e )ƕ+z2ˋ'Nⴟ""To޼YƪǞ;6lެ>wkD,ӵmݾKWe˱c7nbC8rXGFbMX֯GhX8{NAcxMn),[jxޗھsmΥYYS�BED]xGʛw+m\]⮧d,|9z[8r!QӜ|hG r /Qr,+w׸y>AuLIMUhEQ WQDzcϡ#ǐq-emS�&7|{۾^$*]29r=q!J@⩧v{JAʕ㧟~v1Oڵk4Y^NթCtB+m\]⮧3([ (@ك(>{tJjiv1u/k r8p;g: }aR(isԼ4pUvF0<:9r !M-QkUڅ?ωϟw̟_<!JS˖-e;}tjժTCs=۷22n#G4{yyr{{{F3g_L%J.R:nSɢWH9P R1)o՝nAv1u n=g1tgȤۋ1}x'$ؐ-qmoxHcȑcȑq;X DeCsyBALϙ3>,[| F'|RYͻo: . /z7F،zᇑ`va'^Hҳf<ٳg`0X'[哃qƌTntGE*%7N\i{u'x 4uU<eRua;pP5}M@$J+")D bcڵ(6dK֬s!x9 QCύ(v "D9 =ڵkWhر#RRRLiSLA6m]t:uju:u@G_"aM6P|믫Ν;cСҥᷛ5kfN' ֺukt:@^0vXBT9CJۃ(guPkw118{,l,Ӓ&$Oiga0r< J3F3Qj!.`hWϝ;o{k*|ʲn"D9 GZx!1Q vBs99o(yRZ@%!ojBeH]%Q*U['-^"M$QmbhѢcIYѽ{w5O#Q;y5߭[7,Zjlzꈊ2d"Do(ʟߞܴi%l2u8nqX Um2rN^}zڌonK~Jۃ(gu!}ڴm"P2-iIiSYFTvvwQi0oܨ>ȼqm?2ඝ;|2BLgfeErfGEQLl6m٪E<hߡQF w 9r>7:HBF#D9 c:mڴ|Qg!r['mLKZAJ3J�($$AjذjHûO>VדTP7jHɺXb޲N'@u+w}j|('HS8Y$@puA3ے׻;ҲLzǮjRKǞ$@,>BT e)G"Q@<wdF;vPI*::fY%%fL0A͏?^ͷoީ:UVMEvD}*lm>FdA@d@ K TT)t2'O.F@ճ|'N/ȲoK,Q]U@9 QrwA#ې ),Ҥcd &$umO5ik \.\i= QW:r8.j%iGITJ ICQ%]d;y&R_~egZ&O\h8p!B!/Vѩ1c-ին%!.25 QsU}(Dɤ{ !*CQB|r] Z.�rJHɛ7oVq TJXcm۶ I9%2`L;z(VX"M9& ]tIҥKKQ oDT C?QGKy{u~Yj9?+qY5S4FdZҌ%cm{ܘd޸LXx\RTi?@2R:jP"yΕuڰa֭Fh ̏o8A+ËGi}B4Gi%]$$-7nܸ|~4q@ Ȗ4 Qt޼y(yזkJ(!JFYHD(s_KTX(9 矑Z_8J`0`!44DpԖ0b~Sy٦=rd;~ƪz}my$MI+X۞Dlnך?AZ>i\i= QWV}GQ,JL2 F ȧqDR%R%dr٦@5r$J<lԧHNIQ$NKOLj1c(9cUڷ_.R˜ݞ=rt;=Q1-4#DI^{ۓomiZeD/)#DQK!(!w礌KTI1#=FKQF_,h{/(mN5'Ly1t|ym0UH f|?3_w>vh uu)s*z(%cEQ;(O޷%=H|*e\~)-@B?2B b"<f̟.^*-%]E7nR DzS>L NC̞+X {6Vsg?Ǵ1 ,,Ɓ%$uٶtpzS拲(qI#DQ! J޷%wD Dd\.%///*K0__U_zVJڃ(y|t>OORQ@J2|LK%@ZX_${'۰QlCF�XG:Q ;, #$4MӴ&DQT A�]8˨{2CBTQ( ]oֻaa&xiIiS)΍i2eBE-H9Q%ҕQlkG/QMM[ViIe4ՓE4M(E*fC%û ʙmsm2D~d!?d4Y&yJS= Q4M4!QV�tQێ.))).=mKJ:ڪ'!i&DQ!U,KrrKm\]'!ˆE4M(BM"D9p4Nֵ ti89.yҥӶ%#4ݸ3`9XW`)[vWi'DQT AU$KRRKm\]gYDi P<<ؙƢXVTP�Cju~!gqZw|!"唚7o{ǩu_V\?z=ծ]>>>yyO<d,SD\Q.=ruw#D-knide [Ck|y7Dr*=N^PM?w+0ud_ߎfv?GSYH?w s5RiWX�x7Opa2_`?ArP+W믿^& / b7w}#G%RnoooSڈ#V 6(pJD 9::ZxI*x)oN5Djx%"z-W7hǥ. &mJB_cAz_mOK7Ӳ%3Ii<-9t[Ή+Nf.:q|)_Dϴ.!OGTTALϙ3>,^v=O>LK: . /z7Fhh|ᇑpzׯYfٳռriT'[員g̘J*V~Ԉ`,Q{… $RQ?r\#7BذuHrw= Q/84Yk^jkykq~zBqXd]/#9O &\wI7)rӮxO"W6A#nP$JrP Y;!}2e ڴicz6e˖:uju:u@GchڴnbgePӝ;wСCѥK5k.4kjlO@ut F{ꅱc,WݍF#M˱ DŽWOBT/.~ҥ8I&Ds$tfN�}3mG ^oy]_}[t7%)11_zd|7Qv$]0$Re!gMũRJuLyyy*dMEj۶-vލ-Z(p1F5͟?ݻwWO?zNgQݺuâEVW6%/!i{!J GGy*%D1ELՎy^F*{hiyYkXv"Ht>K H]sݩ"G$DYQ&MYg,e˦y4[g @!!!RÆ UcDO>VB F4Y700+Vę3gV~O-OBMӄח9&/ O E QD%\$Dv˜j3b_SLt1%д3˴L4a?Yc繏sy1xYz3Q !O ra!RD(yHc5Dn[VV0a5?~x5߾}{dVZ5EQޑtB,#ɈzF(R{{BϪnYlSٸM6hǍkGHid.<bi♫2'e}yW>J'h8G[Ǯ aOhB@՝D,_{&JeɅ*A xb3fݲ^Zm[HI@www/4D͝;W/""B@'Q2HiDʲIPCOs_4M Q%�Q}O7'(y@{ԨQxꩧTW:"ItK7.߻,%QH=)K.Yyg|Am۶h&D[rT2zZ_h QEiBm򌊌<%k@4M4!JDqnnBM4M(63' ғ�?߹@DH{}fDD?à ETx D!FK CӦ[7QJxN beT9Z=ռ%i[-wCG*<U;*V;:T۾]L"#Ȩ(DDE L0;CveOn*/iQ)e iQ7775lA8|mۚ7=N~rf:T>{8;:!i&DQDKym[uAր({`/h<Y7c< ] 0hũMcTK:]`h0ң.T*^oMf-ZY?f_;6cص>Z`H2h@B^=/6oiΗZ䷾LQ4M4!("QgrIRl Qላ@Dh>5j@UqpNDhA EtxJ|xhx!,4N'*V; ^W}O#aΠй ԯcz ǰk<G+o=G+'^xyDR|q׵eh+]b"t>P#Q4M4!u Jh#PH0~G|'Pb"S D\Z0mZ * k,?*Tģ{ 5@zY)$Djܻw/<"A?Vn(s2$'""*Ehi Π;3YD"=ـ$DG V@)4T ψ0 4XA C[А1ZE<H<(>y T"B}_°w6G5zP?_]&M8&tD(BM4Mh GE!I$bDRiO}M Di܂@SH`zqxX4 _y{`h~j: QQawF+�kf+zLs'{i؊D>d7w6~Y<+|Cc(BM4M[(y9ߔszڞn8iNۙQo&֬vCzr/^pDEFg쳱?yRDEȔt Q4 HI4J BpV$"1oXQw<ATC|<tq ѫS{_}\5ʻzg4 *,XVZ(BMv-~JzA2wMM$jǎZ*b"‘CBlR D?`J J"P҅/�ֻafTRڲ0DDDgB'D;{@ZR ӀJ"afLܖ/7_FHIÐubJ]vbPb޸3c_YuƤ5Ittu]_$pvC/<흇?Xp tk(D&LDʕtBDjp$4n|(@T$*8Pu}>*=<4T qyBUxX8"##@E,V=};"=%ɉHHH@b^Pk ?۽ ]X\ATtzb!H7o@UƑ� y-]Ǣ89Ӻ;OhQXu* ˴gKCD%Akyñ|/>s?Os k|G0w ]qig?۱LS�/1p:̋1r}D;wD˖-3R2PCiQ1E;_~K3w԰,jC9ME".cwɝܼX~"tfEnȱd|ֶȺp7kN{'篫vn{:mv/6'!..9~>߃.0NWo;s-M'L\r (9PHQaG3j/J,+hX'g,&(BTهnXbSqo]jl]-w9_EZo#D6#Q+k1A?#< XS׭9哛g/P2/Wc{Eai aN!C(`wb[`#(iIsbAz&.9\Fw3$uyI,wEߵjk*?(*O5rm:XP%;;.^ r78?w=!G.Ӳa~ ^N-8S7m7jˌm . K@@I{v<"fcw#Qq㏛gkGcWt{[t4\ ygirpR֙=fﮢ]9mzj'=<c/in~wՙbyjܑo!rQ7%)1Hnre~6M/4xEc1fO@~3߈@Mr?%zސ}Lѝ@pVyf!':ٳ\tF 8Z޽PQoM]EKKIjGNz.h屶a9cH]I_e_hR|DQE;]uwC4Z*Q㼜_m@ RhulE䆱D(v޼8XǟM&mM4I$MGIk2AEq((CEY EA(޸ Q/=}pw ZٔLP|-Ec-7Glh~gkc>q}~)+*uF+rdB4dWWk)4>*@jS|~RU7\Z2D=E#48\N@yJ_7;"Dbb5鉢TmF)'ʴ(j{4J91%V =X=HК~6ES �4XPȅQa-DHl%0DCm~Xi>MGQG*vF6`ӗ$uCۏ 3V}~go�*h#!RO_ GYĝ+VB 緸Qe߈C2ĕYЮr}.M*:hcEZD=Mr8_6Rj%B DPBTq$"yV[ X6Hm $/`}5K%S~ 9QϳsLYX,V^p>"wIAOc m(z-2:ԫUhH}OEҒF . Uۡ%z4הjIS(666'+T#/�RX, |,V@T\\z_lQ]] gczEjEw70?LzXQvgcc^ jNPe,nWnEخ^];BʢpSVi"űM5REry,7z )ZXŵEf!lt|1т !bX J|^ "_ HQV^Z�;հTVS%DVAT\v'jjVQ5P)pE`OGbb"S�CbXMy jC>^v)nt( ۰QzjI,U&Kp_%鑊Or)P՞jR7{,#S(EgZqWa,|thhh01DX,DXDDP.%(JV< "JĽkDQ8y"hW7JMա~e"Sy%84J%ObkPA *Az_)!bX,(@j*"R Py+{طe!@ǭM8} �G,ƙC;)spr_Ve(r*DRzl *$!6O�VFxg`ccbX,DϚ( һD^(yU2Kž -i#]phbڕ23q$3W_lM sjm؁HsCjkXk(7MxMj!f QJ5Ag1DX,!UEP+ݕU@u2&O@Ki @"~SӼ=KP—u"[sqRCPD8 k޼V%DwB8upy ,k_mD)1ckK'k:'?a?0uTTVV>ϕ!bX Qlll(*Dӝ(Z.xqN, ±}8s$yg|p|~>c{}pt}QY)=RTV Ix8. @Q5? ST]"]Qk%mg˫ݟ+Ev^ßg2D1DX/9QI'!�Zi\ ĩW#~O:w*j�_R)DU:5n& }7vWK.o|}}~SUR/_W{ΣG/RN"׿rcG}_:::HKKkx{{}Ǐŵ^077Ǎ7|;⭷j3ky5; ໇PqA9-06fa=0m>YkI=MG*py!"W} QllO ~PrXRTzz<Ir @\-71<xS2A.U)󤬫ܭ2Z&㶀em(AxHjѢE?/YDnS翪 r@ѣGk6b˖-Fk׮a̙r{ 9'|"ϣܹ]vAOOUE9?~'''=zwEHH<ʪkKMܞ8q $Pk zfzxCa,yd1D1Dib+!Do+A{*O}0D5e'N4RM<Xjjнr9/p7VhL?jPqXޢr)jnhYV P H+bq8d9B=X,pZ\*zꁔu<Qm[nIyTVA'm˗/mR*,,(h_vv&p?STTgE~~~BPcCy:ES m_tIn6QM=3e4<jW籡d?|⻘._@kq!n?Ī=eye^웲ݾ=܄ъ&m!{Jޓk4Qe=] Am̢p+ݦW0D5fYYY~z9zKÇ?E/;Â2///9¯DQoҤI7oP'@TȚKu8TɂT Nb8$F,cPY$t%J,ĶX^(Z|JH}"*OWwE�UJXVu"Y] !!*ME*a`h[z|ڦоBTS^}CT!@+hQO&O6*FZZZ~'aF Ek ?yϲ!ju üzot/:4 JI??Xo88W QVCT^=L*A9Ÿp ieh{Vby T_®$]o3o=5]10P,.)!#`Z,}7ݓJ>kGNP.]p&ߓ:- WF<x .\W^yE\~:`LMxxxO;v80D=~~E#PAyQ5PsIQhTIS؎E IzPveJ "QZ EpRZj�0yȫujP#?p΋.a~nQ(Hzʓ Q4(AUHJE>ݞ}u</-ƌw>\:Gyݹs 'wh_bb7oZ\1<yڔ'!Nɼfk:FnFU:^|;9ªl[^db;_ol|vX$!=eTOW%@߄D\a|z St =bG`jf͚{O)mJ\k(3uIpqqs|Ј}nݚ|O555)lԺvd>p@XZZbРAr;))I&7?1MMMBeccc1D<BcDtP(q,J/%K PrI8BS&οpf5"9<0n(,M q+vm/˙]~8z OFr+yP|)#9 Q򛂰ذf:RRN�Ib)@"E6CTKϙ36'򑔜(ʕR<48(%eeeXCJJ m-4 t A`K>+ 6V]ݻwS=)a7nO Wnʔ)Y63kn |<Qԉ3w:s£ht_6 Qzl/ɼJ4}ԺvhD;ސ/=Yw~*)\Ou=Q4 Ni)DQٳgkɋCa@n߾}[z3"ʎ`Ϟ=kG r_tldE#JHѰa~h#kKJJ׊!#h*'X*(uZ^^ ]a sgcmdL&nR?4ہ4ΎC2}8:3rLoY/֧O:Sܤ7 Tp!2�  U*MQ, kqR`U#oq!ov@|7x7'==E>B9rJ1sy@?:%Uϣ*z93k~ JRFmHbO# <I|?ly}5!U>_o),DҨs:*L?4VR-)P2bN}�:uփDCg+5f4 Oرc+ѵǏŠF?SSGJ$#\(6JZh"H_&bSp,6,7N,z�A^f_ }sct `2Lc P6`mibXL0 >v7þh9O@[3 KZ"'3y*Iu |lώߎJ?m{^!j[uA 頰# ioN SS>IF9QX(xF^MyDkᆃ2rHʺ!! PDQmX=_cT,ºw.U=)큨OTk 2Jl{䅢"M SN4*NkgRGdNx(W؁� yؽe>"MEԺiظ ͥ)pVNDb+qt?>@?1H C ~0 Z�cSXb*ĺ"Y(.Bb)yYvU$Ȩ"S8yogccFy%JHtZ)7*)UɖnڡEaS0, Xĝ-V )/ێԚvTTa|RU"a=<QG*eiմQ9#G QurZhBu/M$J)ʃh֭['_JQH mGDD(>߹sdy(<!J"QrYjoAoĮs<|Mb™`d^ ?FIQn}O?C_1Ұ'Dy{b0X apw1"o3MDx <D|Lu@r +Tj a} QϓYF o_Y!Q Cԋ'(? @1Dz yyhRoGJu>ZW k-DQqYBJG^$nQhC= -3ġm(]QTN>h2R(p> TZ-`jT^f(֮E Hu|3lN XW9z t{ O@T|'_>E~Z f fsa4#̞abox/ƚ)>a@M|s$O$x8UT�C@ynUp8Cc2jLH_-X,C牢bBT9rF p,7B%Ǻ!3K|]h&v 7>C㳏0c8} <?@�2gVXlXNSb�a]e/ *8DQ(9S\B3Cԋ;Ke9j >B,bbc{. JF\ ;عӼ0~ޖ8sMqBfLXYD"n6'r8�}!Oa0WL!m? s<F ƶ: ;J 13+`r=vJN�\EnWmP6~_%mw&Dt4P+믿Ν;-[?sa顼G_X,bbc{"Ux1B5 iطcV;LFXeѽ"A*6|&օ21NH^kv93S� Ѻps6"K8bIX/^b]ꍑõh?nF` Y!Z@mq ]37 j[NTkh�? P^Cy2DQ/M_@aaa2x*wDKss!bX,(6Qs"pX0~صG,ŪvX9V: &˓oB'cs$Ǹbؒe溍8kR<3K'P='UWMx {dZ%=_V?Pt4ƈ'os$k8[c΅⽼p2<SGWn(*~RXX(iQ֐CCHs#K/ \OإK+uU<ErJ92l[`)** _}&"x*$jYxxx7;#ZItou2ʓ+_ߩspႜ_9410Y[>?CbX QllO r#q ?X-e<K?YSc amv4 {`P�)*CLE6Xg jjhFk#j,^áf< kWN*Y!ѯp2N;vѸVXd "QВ: Q12*BU"Uѵ2F#PRimρ>?xפMu8I(b,ʶO4 @{> ѣGσ*p*זbX,CS ۈkphŚ ;+-]l#Sm '@.m-a8x]}dT:'/C|m 0a\n&8s|W 1},#f 5+sBlN0me^c`9Zcm=j,K'j <xPl2~&dt\K\cEٳg7 IM}^%{KveSl Yɯ Q,b1D=Ch>Hq {xK;\m0;`=m�.{Dm0g8 |gu4 úXVV;ul% rÑsn5ΞXHXh7[Ӽwbq/S^fX∊X uC@ԭ(ڜ(ZRT}#***j5x ET&VmE^ :M\[ZZ*!*<<\Nn 4Gg}&=L-æ<J'D@*eF'>X3DX,T 7jk\_(˙l ?]8q `%  52&ӥIuz�dg! D߽ϯAR^ғn:b\a7y6q`9T{Ar7PQq4R\OիS\\ MMMYŎ]`B<$7743R2O K 3gN4)7A _׮]!Oϧ~  u4DQnH3&e疗}J謟cV7mr͵(b1D 7rn8R<L@Ycu[#5 #&| p 𙀀1m, m d/WS/xBo3pSkpXlv7 πl,񱂥E?XfGιu1H$.$/yU%d?b{R[(#Y,(66(Y�9 E VY[!) Bʪ}0H[x>Z( י#<#5m.3->8{b ˛:y0C/M;b),Xo5k%`32p [{&%uN:Mw@XO8q6Ƈ^twls皮[u{)Z} QllODop쀠27*bfbs,]4 g&wiF06C`k9�tag=� 1}"% ,1a-ySAK'cy+ hi(7lK/+]^7]9Q6]\gѸN|) Ql/<D\Q ;d,k!](sߞ{nf]Dl*>&Yr pUO>DVZxqsŐќ6TY)9MFiN~u& QW '`S3b"\f`n_u1cX@Q1sHYf&YӆaU8P4^V#/f̈́XJ`,gpiKm<PegN`׶E\ Vp3E&W_T$Zi2X!k?M<G, [||$wCSƝWVIåٲ-6盅Pd%׿{u ݐ@fFtrJ6F@=X>MLCUGUUƏ^^^rRh}&M¼ytDEV{Ni؜4Ȱؖ2b.a:Zap IhR)Zl Es\Mh KK+&[3BPM@z'$źa2- 7qp LxOxsLQuJQʼn,InĬ!y$+wk$?&Ʈʓuqʝ?Xo88W Q&=QL6 '/ߖmg^G&_I"$$g߈|C ;|U6v:wυؐQ^뉢SB*_|6(Z_hK/}Tv#R^s`` >#9Q'r&ߓJ/^([sd>>>rK.5?F?Oһ5vXY!J.nDRLqdZN[KPd6ntߗXva􀏷0%{ʒё.5 ,ŵVش >s-0ryc*G$y">sQ#0+#r3Lb 8Pq+ϗ)>+K:9CQS".0>=߬' Q#rk\Z|wkl[݃z1rH(/zC~!~7"(Gzz]*6@6T=V٦sG̕mV1Z(ywYʕ+f͚---Hihhť5t>tsnݚ|O5557o>,2aiiA$ѣQj*\YY ccc9CGLh"۔8/lX넵+쑚)"aF._Hz=q!cl,G[C/D XZ].^WOJQ󹞦X; {$ϑ)*>rư؞#^0ZUQvCTC׷ԛ;NԞz-9!XxNᓂ( (b!X{1NSDRUӲ%x#*^B%r* іs_-TshCT PΝkWgrΞ=[M?SF9shL45fEEJJ z)E6N�Zߖ.] ###N\|6l/_gj%%%Fja ]MĵDFg"NYq@ YaX7n,L1i|? 3 {C83{BDE`;,Yh #)|&"7;{|:BgwD,k!HɃz}`�1'O&h3ÉCKJx"7w|̙/H::: Q QV-@Rr{lW#!=QPX75m'B{GMC=񅨼Fvi\ڒ眨AI~Y| ߽{vi_K;�&U<H|\=dcǎIX$ki2RM`R42(CgUt)R@�8\ExFd y q 2B1{HR~T,^h9̤'jXӄKX"hdE͖ZA�b 6ac=]f;a!Ck@{9@[T{J D5m`bzUG(:Ƚ١Q?'*CIOԊC[ڨ:S0q}>ve='vJq˚ (GFֈס6D`‰hsRAJuCurNo{bK<Q(;@d=Bee5=7 SNێr><׿Uz^tk J P^/!$^zMѲBqn'`TN鰷P'lIBr'gcU#fs<0yf2>l\,{9/|\d1{1"- ^c0lpOL11KՂ1l/mBEq'Q9Ny4PBSE=W;(|/5YFX/ǃqgՠFީh>MmTur)<R߉k/݃{•:'(tJy)E|z/Q7bJ^Em\ѵ@JHsk5[sGERxm˖-2g-\gٹNNA $ QIԔ)Suצ#""܁]d|IKF Q(Eơ(cIeEޖps6C#hܱXiU+&cj{,oA'j7؞>/)gjx3z#& 0Er,Ìi#{c0M2v^&HU~䉢<BAy#RGB{X:Trbuj4u DѨ8WѺjx_k!rBlll{ɐ&"wB4O QPRٺsN;TOFr>+D)%ʋcHK*-Ft44b�|Ǿiuޞc튕K'!-E8{"CTL][}pX0Z*s2JV۰n:|X{Mn(݀\Uh(;C_ + g}(Rw(D@jNT޽^hQ)c'KN7WbX QllD] ( P$J64y{ɉu-rLL4ӕF+2I1n؞%''bk�~g&tdvm[58:硲$Jbq8F::W{%7J5@yȲe:hPB;pww/̍!妔| (OH�b؞ *ۀM5qqryXcX 6yl-cx=9$u7 B,3qga -Iؚ%݋qU�QyQ4vlFjGIƢʋ4mὋrHѹϛWɓ㏹Q2DX,BTʆW@yBW:" Ӧ 3= bp-L!`7i f hZ.Fa ;wr%7 T#Cq1+9P^S"{waZ'\A\L5HըXR@EK튢&O,sh%9l Q,b1D=%DQTiMܱ�_刍k¤7,hp0 0s0kc(m g!5mʚO$8ZLUo Xˤw5eJa*A�EI<@8d8yBl Q,bu:D9rj<>{|^Ӆ%6TDDeٵ,`j|NF0{p8O5d208lX ˞GpZ`V^UBQLIIQa(TU++$*RؚX.֩<'_8w"X)�EВ}fvχ :~ pȡ=a2L3FM #q/NZ50�Eɐjޥ [_jUeaJ(ⅺ|a~_!>Dj(uuu/"!j7JՂH:9*i 8 3Gb>FY U-7eUHTr|'wMӵҸZRBU' LT(q<4dی!D5bZ *!!~Nдƛ8oIBDPY&d TہtF M"x~57RST\'BDU@T=HMST]\P|"=))-X'QdvSaU=2UOd{CquRR'R ݣ{EQjPBOׅDTꓡ|E59R^(ţ%*zr=v<q<S1D1DXO!sPó,G cۋQ ־M1j(ǫ=z(6ђ&{T.7 Q,ӄ(66acֆ<޻w;wD߾}=F1117h.wsFJJ n޼)Ə===(!!iCTCYx`` >#9ڥK>}ǩSliiz .믿.;![[[~HNZӆѼ}p}~lOĨmk-n}#z7X,(66~;#_>t200ŋq-9Rڭ[9s&tuuq)(:FLnY)wqqiU hՕ<[}'Ν;ᅥέoqqq2ܕ!bbccj(Ç%L<!rV}6~_'|g2D1 #oᅬ_1bn6DF1t~駭jêן9sll5E"hc9رcpq(!!=v%曝Q9N!~Wwebk={ӆݨ!ך6lleׯ_ٳ;vHڵkW3DX Qll Q-4 m@u&{y:ZʓRmCMyZ҆UuD=IRmM}?,""p&߇!bbccjČdϝ;'s;(=E!Dyyy߿Bs޽{3D1|!*++ôidjR͉ekך6LxJNTuQ~~peL4ќGyNsN #_5vL:"##W_9Eh$:aJm(2GTaoٲe Qto~#/s#d5B]044m |[҆|'LP'Ĕ3_y|ᇲ,yEEEmlnY2D=HCزP6B_sabccbkN<?3|RVXa4cD\]~6-ԂE1f2CCԏڨ CSSSLBT|bƿtC?Qf&~:F1W_Gsr]C23kgS5uQSgbcczmɒ%S)ATC::hA* O9GR M|Y#Q: aH\'Q&?Z"gj}5bb5E'N{h&We)؞GbU YIA[O]{iL;KwG¹]o!oy.w{BKWGkݡWkB=?,,lOґuڧ|CVÌGCu244~Kչ޻L̑.:gϝk �ϟ|ѺaBk9ܨȍ܀ >"ı G&ڎDF:OlGoXd bdGb\r1>7Ώpdo8/^/[w(Jz2 7'c_P>L{c ll Qlllll QYYx(3gG:zZ AK铧NIH8 s:RڛҬ Sb8xz8^)9c 0uH 3g0mc}aΜ=+5LS}mpi >K|1|Iq>0 CHc-׹޻su (@0�Ǩk i FMqՑ { x02ĮaH^a[jc664ul"]{Ga�$DRz!. Ruu,A64z"ooFҵ5Kk"E~}w2 #g ӗ%@Z�Q́TK# ?vPg0HzVYY{QwJ.ɑ.D#,ƣ<{2:}w-+W�rI#eo@y|6k:9zv^K~z}+Li+D#.,W& P=4۽'b![E@ BƆO@Zwl飍mb" j 5`ОCU_=z [w$t!(6wǞ➭pp89[!US9ݻa~_k}$Mꡆt-Wg>vǾ5!rҹ2%\i|'m4 A؞D5RDkn1Q_"o'Ѳ,d Ow |_ev#/S��+FƣKsKomo!sfG)۴ $5\UxU7 y|QVT綾^BfB"zj"Nb@ h٬b@]l%[ 6; I/f3; qG㤓=Y13R취nݐح�n!gspzN;٠ ,\gb�Sy{mI4]C!'.V~@JcLQ}_J7npEylo堁brLׅƍW'ѣG:u*|M9>(666666BT}j-@ufN:nd(I({^a�UCEI:J[ Q7 %)k7(.~k-JHJ-D54yzrQwl :Y}DJO{!{GZ/ OIݾEFOl_ :BFiI84l\^07Ŗ~$<B־Qi= 6D@uq@QxJR|t^جTһ)ܯ[w݃b`}lb#KgCM 9m4M٢EdE6UFJJ0+M0:KyyyRR!=TOVKLLۻ=ri(rk(oiu^,s($Fh3}]Q!|GQtn@e~YU Q [; 7Lӧؼ D3yN-(^5'²޻|Sg83kz U׃rz`{>Z4^n]!=Cha^7Svd^ѿ/N:#c6r 3$$yzФ5Vls". @;=Esk-Mttpt�9=XO@_~׿o߾:^ |x׿MzF_UU~=ᅦ?^7}-91_:::HKKkYм@yjConnM2Dfu>% CNGжqrPu7RUP]g(r C틂HxS<,Um q䙃MUK߲NGmu>ZW k\.\'%25Dկ\[ZwnS^Hdmm$ !uuA͢.6v}7Gm㌛6kV}=>&81m v X}P�ӳgɣ(NC.,Y)8>E10F[ izD@ }CDa vl=z0M زeQFڵk9s&oIK߯YthVދ&m9{3F'|"Ν;صkW/R}Lm)"0S*I*VZZ*C؞"Du&bn>{AmI! NE'5q=W3{PWM6| `R{k . AW {j {OYX"^A$RAM $u*i8@@v=dNN>!=r8N898/$hȠjOTԐ*7O i!=bk؍84~ κL!ӑ?z62Ρ80v4pX&{GvLL@庑}wr'?I9(/;;W?o5WDdK۴%(UTTTQOS"??gLgcv13v}yTuzO(ĉGD*Ҫ<llOˊ>zWJbb"?Z1U}D$:QA襅$\O..F]>5.#ĝ"sPU\=SO˼&79}4OD=ee^=k@#k'/%3&!7(iښ7vv ֯wm.Tx4*m.*iq!Q84kV$-~ qLM8g8v anK~8=�;;'>Qo苎BZH%f KPhm+p}M}}-9gF*+?S$$$4"yCc PR5D5lYYY~zݤpÇY1ʑΝ;ѷo_~0l=L mwvv$'''GQ?f_9s� p`82wgp)y٧ >sV DOLD&5^H4-<O{tJ1h�v\]͌"k�J~DRB D<jN[t4 N=;�WPg;Dm^<WzzfuxanRw온'QqO{ޯs>{{-9@ÇSCƌr?""BzR<D(w#P] G}$)vOnqj+x뭷ۛ!Ѡ iRywd;)dRmcMD봯Ǜk[nctNGa{ _UATׯXezTTy,H}{'!tR:? 4xUN(5w)2,o�}R4@l?o9GԾtL!YCM�H.,I@Ys}L&,Gw' ilvT?-ɨطW`3Ď2ơjv+`>>Cddd$#Fz H3gNmN )9Q}-90p@ >ԉ%C�ؘQu>SS:|||?Νk4UgКѽ8k,Y:Jn\gC,t-S,C6ŦjjjjN /n=jiiA GP$ xsmߢ$xEyN_|!s>|X{|R1DXO+/1 Ե굒 E!}]K"JANPQpx83=c }L=$<*;Lf== RFą^9ppd& j*�[Q Rkr-I(CɑO/oFSޡ! >G�Pui3WI]@2#U#G49+**<Q^rshXN9e+EyaƏ;L?:(gE۷o˿}KS! uWٳ Qlu[Ia2bĈ:Q{vؙ3gdjS=N^o OF2%}ɵwo$o0DXO$'ۍ! [ODuSXޥTm 5 [L0-?f�6nE0 Kࠥ9R4u@EE$ G EO2�CP Py, 33Q;QhԘ<Xϊ=EKa=(fgCT{SjZaƌڴzY=QQmCԮTX{7׆=*=U4D\llQS5<EX Qj] D\ͤ4/T{k"]K]N»@ ¶}ae.jWOu(! X6p`pepX�X=s.v kdNTg,qr% 7D�8Nvߺ;`l/,Du޽Nxo/DQgF(D(Tۓ';Ւ0yÓdA6BTSnJaۊGsXg S"pBJ_]$FIK ʞ= ool:jo݃a(@QޞCqsr`!8)$)9`HE(j7y}q556#KwbM l﯏a@$jBVt4w^Xr#G7vvSP.߿C!*KDݛ3GCD9KyRr锜(ZWi6ԫW/;͵a?#<P(*EmS;@ŨU5cƌF,1DXO�nG`#MHvA^_P%idpnH"𓦥=C MN"Jz=a(edy.81y<N:#gr|pp tmMY@j~o9!(N _o}#˒4Gնz6/v S0ȨH'ioa jdJ1e"掂([XXjMN ES/Д2I=)M0!Tz𽦎7׆e*P۷זJ} .Q rrrXQra5L +EPGP\w!YΗЕKjHꅣpy]5'f;#&Ԑa:gf!}y!oE�i8> LyQchdq;+9.7OP�/iv 1@�cp-?^D(}!y'Ollqb= tWRpFMb4 q%vS"{l\^pdy�$Qik8f?',q&cq89,bUFkATdsGႛ{`ȡc4 #];[OAs"2d3;Ǿr=ٳgё!U\|9oؔ)S1D1DXD]ٿ9 [G Y{i#Fzd8U˚Ġ(j= C\\腴>D@.L1�[ayF {sr1~!k'2LK]{H1[`A7z( LGVb\=qU?D;w ,,L<ATc,t*:+Z3!!CԳm4/| ñ`ccbc@2v5WX"RGWERG6R!EW:OA C,>ns^0NG=(b ZY`AH }{I87Ǧ#c)΋55Pk�']Ytb^o3#c�zk<gpF~P)~&Kϣ3A^z%̥䒼+u%۲e_rrXEi *M:H<kJnyu^+G4S@FتMKWk>E7 =7ݦ9֗_~)'%kXprCTs!텇llOQJH~KӄB䅊0KG(ۑQ8ͽ]�M{D#lrvĎEGCg,:{h{{v+ qwwwwWC bH{^h))5Iȉ$gg>g3fY34')ruA8;W�Y&VX±6vY%5Pcj ."IZei:2p`l; ";;(ԙnj8%w>@B4t3;gBm6yoM&a=XSMv΄ .YDB!-ا-[B|eeec*eVibxvv>hvebX,CCu jq 4tPabj7wzed90USpn-(rbjpbKD{9Q==:uO3pxd6--kj%`pjk+Xcsp0͙&Xڨ65yK{R QemCdQW6S2@=2GiUK$'X)//o<FK+\e}GFm[nW2" T{y;tME־?)_(b1D1DX 5'K 8n5DBWU6?<;boH*VѢ(WoD &k] \lYmnvUNX#tIvb%`kvN X K*FPFU�e&WP)"ƙ3g$DQ_2C|R`yꩧ$::_~e(\aaa\e'eX@Ab,RtOJqF %J|k2DX,!!źb&dQήZCSQkg=Ga֔VZs0JsCXHKuQe'`J+-c#PnlP*W4g,X)b_XvD`{x &aKL$*i)Du,C~j( ;Q8)A�Y.uT&**J+ <! v@*w)AJajzn]]HOмwۢDP.z F)z/ߤ8{@;* >X,bu ; k^Dn6N.D6JZhj #TIw2y%'aXfF} l,5GTj3cl _9'}3 k]%DU�՟�*o0/[HXg!uon Q,bCʜ2U{:9Y&Dހ(vXfe#aGj2AyJftDWK�)ָԱ(?@d0EHu!؝XZN(^MB*Éy8>{gwPmc%!R�Sx5D[SUma%zX$@|,Cb@ &O9K^M'wts2t=x%@ Zl`EZ(ñp8&BW:Xjd( [#j|_{GИXr5U@ol `lŽ8|?Ni3r0džaoJ O2B_%}R+PR\o*ձJ\DK q%X,(b=u�vACAC3D=EaDU:J5Q?f$Δ~`Tb'm$Ziֺ:`G|ֻ5jL1~j}<^:,}Pel Dƞ808{ғph8|=6{yJK+u\�r],Rh+M3DXjmA깷v՝ UUU\?Y=NJUUO<KӧOZGll^K˰cM}v4Ǜz6j:c.?y4dAM*o?t0 1}V6fC޽7ׅƜy[o +mŒ%O[r/*3uL,. UIK^b>TP',73Zw79ish�V HXi'ai5ֹ˼2~Xf/#suJk v +sP-{Rc7=c#M.ٕKQki%F]?ikb:h`>V,4;ڨruATKѷieZf\BX7Ӥ"M… 2 WKDi]E/ ܹs8~8n?D+Wmظ gΞhݷO[%Xv-h/tV]8'7W&P:Qtie:'l;z4d;9zL  n]uCUHCKZjHņ@b[DbB5$�$(Uh P-U P±-2XETXu6ycc/;802E$-Mgaj6;$a *L-R2*[kT[c%tȝFQɓ<l̟<y2|M<rͯ]vu83<3x1|p~YַEwݻTE͖hZ'#W^ׯqiĉuD)[D!2Q9(5 Q^,[j@=ͬOer~Ϟv泥5#{#GJ ZGC}Q%%(7*'7j`v LXkkF@ܨ վXnZksl * VxH7_vDbZK }hb-+O;-85GǏ,jscA>8V!;qK֎>8*DQզ|{000Sd"~X-7-ЙuuСCaddj&wg6Ӻڧ!RRR[ )\]]CTK[[iY9fΞ#BQ^+DV :F*eE.qKnͮa!AO; KʎMYq<'7Gcz!xUXYa='Ckjb[Lv% tPmf2d}Zf w+La�*SC( Z;kl:7Qިud%hegOǏ7}иzlvsF֨ læPw|r(42D"+Ԟ&nyoi@Zh~^[ly`Tz!^"5ֽV) 8(n6^?#ٹ7LǎOH*,.i3^{E潶8|jtE"($ݲm <:Q(VUooTrVX[.. +lP*�I& hlz/ؘKtʼn,PUfFXnh -VDRFҚCyN2yl &t``PbW\$S3#5+LֺZ;QidE.&&&Ըwy|6uQ'7v~X-ԩSꫯKkE?пV۳DQ>S)ZCԜy7C�EsZm9'ƵtK-)FG!j[]Ʋ͎ӾoU! meK?#7/oAaݿEso@j7WlFҷ܂P(P*IΘ�IHl Z/7F,Ks$xYb *Q*8 撛YEֺ;c-e$bUȅx}ıĪͰ5;we&yoy]yAVGcvvt_$`5�RY:ޜ(wI!wW *,((ltSB7η|;w5ku .7u#>_-f�dbHD4^eaݿE햨iJ!Qݩؓ,@)5v6 Es6zas;6bK'bkDv%`% X�i�!oqxlB 'T_ Oej+͍1 P)E褱8<qNoXde&8x-CwY=/_}vKD 6k*G155!)){?,%77>,u"]`s +EۊG̝) i,݀buMZu#@ꈀ#/#{ m ΘP)؟%P[ [Eo7,V돲 V}\:w'l ǎP@'x9U^%UFҵ\Etqhx3Fsg`+C/57ơ[(4z2D#%%%i((XJfff>dk܀ <c\ YJPaa/4`uӔ>? O秔 ț-&&FQ-55UZ^u[` (ulRlE c\'j[D ӓ+! 183G'hz].vZ{+Tcmý+l^lQ2M5HbLΡRX[D=$~Ti>X$RQWTpŝF'jǎx`q]cbFH?;k6$HHW`g89s"N‘уP3Pkk*geZ;+y*OWB j<)&U2,"Pej F O iZL*rF ŎpEa0uP}Q" P@T}~nY Q=GmرcBDD),k,CC@5p`6.#HSKAT ևc{bv�>rR)vLJT\Ժ REj=ݰ ]PUvrjSnQ55 ;5,(5xbAvE` JA��Q}PW^yrCTرckIˬO8X\X,(랂 z{:ϙ(R@Vy 5vXaeԱXO΃:]- QX%&Xfn"MQde<3,2GևcWzsaGR 6b]? }հ1 u Ŷp,73EĶD9 $$rCbX Q,֝?-؝3fBl;zqlϬ?oԊJ{;NŹ[5;'{Ee7}rj|W̖ 8ZZUKG�S#5\ZolϜ3tp8ji^b1DX,b9RM[bE{="8w,(bZ(qĩ~`X, DX[X,CbX,CbX,Cb1DX,b1DX Q,b1DX Q,CÇall2k:ź{bdu?#eo]]]/Qg̘s!VnX Q,CTWէO$%%)!!AJ[bKZv->֭[_GCTw~ɑK?~=Fb1DuFq…~Ieɓo'D޽k׮_|xg/bn/!C8zhkx衇 8PZd_z%,ZHK:WUUO?i g5>h?&N~ Q܈X,dmmT?^Zѣ_~u8>N:%pj*<eti333@90}tܸg5}QPP I#^^^n+<sr?ƍk׮u Ϟ"0]]]?C7b,(!:y,S|+?u8W^ػwo~}}=?fZ`ttt߬;v:J + O<X,SǏlj'f͛7xxxxGsceoowww(nX Q,CTgDKtNϭwDS¥Ka5ܹsaddԬ>mߺuh& /uDOr; S<S8sL>SdbFb1DuB48s}7h@;cӧOG)Ա*N\T-M"ۦ C7b Q͓sSVȻQ\QY<Dѳ@ KTbbb3?t>+#G`jjڭElNQFM===e0(r~ϕ+W$DQhv%g-%pNNN<<<c-3/?n(L!Q"ET:(eP"QX4(R[d`8!r[*DEn)Ɉ⁡7Fdp2Q|#Q~xaȎŜ dEz"/- SPAHq6[/>G aY4D8p�.:tji@E,33[|kO?4^xdddJȒ裏P]]}|Q4:NQV\_<붉Qyy<`Bd}PXxFu7 ,Po<'0-(L F!(N BQFעlJ,_1]GqɁȧ SVbldI^Ȏpwب|;FyX"D ƈ29^D^^رo6,s9c>"wFi�F�*L DQj GeǛS\L!⇁2`k= Bվ@@bN3R {}1 0ˡKK,CE"7uRX,!1Vρ(>rԐ >Q@QL&!呅kX8Ck¡)HGH;LO2E6az"9ivc�#5 ?C4b;v\(<!|||fX,C7b{ͳ(-; UDD�R KS AV "Z9nl VΊS| N67 cl;6ġx;R>0?p DXa-lzKZ<"X,bb<D v4Q* h_a*jMv]{agpDTQ^351?#|>07Q<Di3QC&ޟbB塯'>H3_{̈e!-ZHN};|R(bX;Q5(U%*%Jq\a< VL.ھD*?OVr s¸> RCŋb z |Q=a 􅷞:,| O2Y~FvRǛh/ B5ޗ7xCݻ;yX,bbzD@Aj�' p D(XBՍSb[ذ*9ñn~ ʆ`{`*´P/"\8Rɱ1m"A |Ce)Wت^pU~ xrV {vM�ED)rBP!CbX Q,}Q0;c05ىVٱ."%*aTQR }(BHĮ<'TX TYRa~21/o"L?#Aʣ_1}̋.oaKH4滈MOQڈttǛlsh�e~:&L_2p|q-;DhZۊ.1uT|_"48q<dUOvV~WׯGB1Y,Y#K=U{abX,!ź jhEH ,izN2@n9Y`z ic&&Z`N;J2QT?l)_7Kpn&Gb_v̱l ̌$Wc_DU�"Eƛq";/-^1eD|է�g<E 2|m; QdsN8 ]2aaar;ZY Zv+ $M7m$_W G ?r?++kIk~>N2-իW/y/^Dmm-;iKV[bX,Cu@THL58* 9F?Lh!# t=đA_ɦ8(Y*Ӟؓkn8ZcˢuM jgxbׇ(a`�rgU1RO0z1!X�T�!yD齀0izG9/_VZ,T\H\O[vϝ;+W4ZDz.'xck<yRor;-#X.sО: Du/ Q,b1DX DOvPϑ8X,g̈ sS1G@(S b(l_2WYK`<_c3  Nñx+ƪHuꋑ_8]۲p`?Tbߘc41D�V} % p%#qpM&왏Ucn%ۨ uI i&2w'Zu#7*D-rT[@TG2DX,bu!ޟbLH?YC!8\#-�(eO1o`epJǻׯK<sƾ9{rqxq0xbbJ3;an ;a^#uĪXe#B- t Gr$/'㗯 ^6+:ɦ|tɓy:mu~e@Q"5n4h,wwuEJr|gs!--w;Eo+K/$hŋgu+*//4ӧOwlg{DUVVBSSO>a///|܈z D 2CH88R3[+p,K; X`v.j`[(bf=>űqfvwy"ak;*rF~& ?C]1%qOD~R0+@#̑牥S.8WNɝy8w Sy`N?+FF]] <qGRyAw sqY\pAh#Ak?|prظq(і()SW֤t;+D:B,%[[[̜9;-DEE:M=555044dbHihhHzQ[.V7E;un3F_!ektVǜtslZo73p:_W'`x+O!ƹ03F<?Ϗ|V'a/jm1- @`~ 5ꆩ.r??)sc}0? (/̏@YX1>"v`'L򑆨ҥrt`H=n̿zTE=ztn׾7/SOd``Kv <(@?qRWWG-[~g]NZ5Qݥϩu:UTTnQf)l,Q{]vu8:r Çsj&r5>2[oa@U4JIIk|Oz硶u=eUUUOe>m4X햮-{ATK9R1VOuZұSqz�|*UΑu@aFz}$wHxmሲ1f{E_C<l1ݥjR,<Uܑ+ b1\ܟPS\0Z*pP$;S";9-[ԓ!̙3xsss=zTv4i_~ΧH4 p)Ⱥ1ȝ݊:-5j(hiiȑ#2X3"##i:$ÛO333Y:z'y ̑՞?qС͌-Z+{C &]nX= qX>K2qz0TM/pŽ6 s13,T̍gdcJ+ H҅f_DX[_1 W  sp 3% ޴탼@<Nc0%15YmpK}jbN/zz!8995~^rK%nhΊBNv4ݻqcV3Ez_}Ui)zzh.}Ac}f-rˈ]IsHǏf"eݣ /( hm&M4ǂ1VO!3R#9^eA؛]- KF# lfs A.-�iF'fEzarrb})'Rb"c3̍@z<ȣ_&5H@̉D^t#kX?[p)X00-끆( OLrA"Fows+tK.sR*z*x3D%ZrTǨ^)M-Z[nd &7禋XO?�@1Uj PheW 1݀iA" $BUp,s-Pma`kXi v(HvxaT$]F:brt9PV㌬0WDؘ`=?VHh0A\+1y䭧OHq2A1\oY4DԤIIJC )Dr i4OJ!I6DPӖ%ڻ^5ZKZ/!*//rUq#ƺ[5=?Hz/#C鍺hX?g.6%ڼ -,” KO=0-³!X91j^ꆬPWLpǘ@'$ٛ`B fy`j7 j1>'�C|&dA(L }9>)mZ'&bJ&z?S!\(<Er͕.FMݒے7+8155'));?f9 x):i\\'E`@{Fw ;;|Ҝ(ڜjz 򚊢bR߉DQjMvMY$`s+{AMH0-0nX=Fy潐lx`gXcbwM&anRԠ/PlQ~3Zo`䠭 G~mpGC>̐l K/1Y6@ld1Wly28\h2\;]o-#Б]^;??eKv}_=f̘!;o"ŒKF4OQ(bw?1.li\h+++A!Gh.|t(Q4g{ף~liz. ZҷrJXJ۫>?(ݕYG@u ɍ^qAZH5LWFi}1>Ì0K )v}!4F�/ka/lDY!@�V(O!/;G7PZ0S탡6ȋ lHcl0c"'zZ"Ͻteds)bTkz)-uDرC..bX|܈zD fj!3\ ߒ)L$>Hr4E%{$S$8YWq6! bk@g<Arm(|Qs/W͏c8[ <@Q^&:J 8 0S+>wE�{d!np RަtyR璖/_.L>]U,F"S Uv.UB#4Bɩ hdg- P,@[8p@ڐ7}ftW_}1Dݻ"*rS(iZ:""bFճ jFa|& Z wV8? A1᤯^ rGn| B09z $hEa 0A /](Q9Q^鍁ֈP0iA7ԀFS@+_wrM j}d_vqr !~r !тs4 ;gp&*/^5vgM0a|%KH($>n Q򕕕V־֎Nvv>(.tۺ/{W<AO9,bF# jaj(Θ5Efts8h!SP"R 0W@Y/mX{S qh?'̏3/G-Jn( 1MG'vG'兡V) Et+Λ%A,?1:D]zqnEP%Ѽ77oXE6ʬ4dR'Mz 999J۶ s*B w-}1DX,!b6*L 2W̊ �㣯 ?CMEqC,K0sDZ`j;bZX_o(7S�DW39cza3F:`J;&9cf�)+LwpwdGy5+!ª`P(oFi٧zJB)--m/[D1 ]6Q:ut[lYవ}eP'YR8{SQQ(e7CbX,m2]1o1>2p78N9僂DB5X&0r tȊ5"4!Y%o rB&5X=<1fԴPk@C.;5YZ({,:Qt$MTT׿* <! @5.@Jajz.-Ma,Ҽ Ց7Q47Hw@[~oqPBgkA5}) ^=abX,CDc]l'=- wCn@LD ΋h/r|i b51ֺ<eXbZ f+8b8!_lTx?GL.<hk!T3\2b94};2DX,!bu ]las Ux!}j%  `5h~Sar"3]1 T??xiJّ r�D@ P3]L p"8A]Q,Q r28\EaAF C!bX,(C)a O{8kN5{Jo $A9-0?[��#}iY#L tC3]1%Ip `m̊H{ޘ/l%tLJ+T*H^h ]"\~ZbbX,!ź�=rvpS*<uՑ/9&7X(s8_ pBt˦!1ANf `fs1+AY!;CZ(HY2\,1/ 5`z;fzNs 7E|ud a Q,(bX;Q Ǩ�$8YAOj*3=C�TtSMs| d*(W@h?ij^Ev fGz\1+C@M(Pw s[Z*Os  Vj}!)j-AWe1DX,b=5;1<hhGs!!i%!(%H򆧡T)E Ā? m.gv\j^/uh"x9Qᮧ>WWr A$$Pq.L>CJ%w{sCԽQXO?xyX=YO/^oˬ{A􇦦&|I }穪YEЍЃN_N>͍@T">_\<(5Lj@s} *N EAbt/C3F73]9yMO.(à˹T28 솑vP wqMZ\wF)a5ɊTκГ(Gt Dv'Oƛo)iA]vu8և3<#6>|8? QYYY+SӦMAV\RYSS#EB.A튟<R۷Һ^~( ą 0D܈z DNA9,j 35"9ǜ(O40G͝3E!5`g"]Q˗'�*?G4I�.q[I[UZ(2\�,1Xuӝ-`P79bd(sss=zT.Kx~: :uJ&]]]~}ӧlM*zܴ]ڀ3=z\wtzɺS"Vu;wojl/GATKу?1VPdYL{ @r@-žEV;#|Q,", ९?ZD@Ezt, `W"TK_ H}oc #k ~΍򇟡&b&K0+L E% ӟ^za޽1Du DQC|3gH>T`dwOHH<灎:ՕzuTRR"]TgT9Ri]o/B=CmLǍ^(L Ü@L{6r hS}xja�VTr aO hb\aB z"A0pk'cb "f#�_S=Z4QV9&f]|; QO4pХKyczo5GyX=ZG*Q)5=vر.[;m۶Iki]]]6lnzׯ_oc!JaZ~p#ƺ7!*EcQx&@)H,OsZ? ,Qy2p/[qEI+}=B!L@@gK̍@g � n 3]9c,u� Zc(GD.E(zFg;!7QwŃ ;%z###nkT%^RuuZeEiel/B駟~BZZZ337b{JFJ*�(=%i($5c|kg :V4 O1M ! S:RQfHtD-d!vX"N̉C1, ŵ]0 3#%A O@8X`bCQJKZ|SSn}ޒY~ycsxPu<)s{F^W^ƍۭmL09'@΍^hQ 5 RðFxUOdh{3r<'30P 9#p?c]:Ybț91ޘnr@,_|i))IN-%zEi =w4033[7!R{+%C-C}|<ۢ);'I)cϞ= Q\/YKF Zk/G@e@_ 8q<'1֝(Χ(JQJ(50 8�b0L @w[ް -bn ʎlFH)N )?!9Q>OnXR3hI&1z]ՀYow؁~+%CTڅF})&&FQfG׉Aֽ2CK0YYY:T߹^zYE| *??}q2j?@TʈDizC"kTVTZ܎ q&g7ny=0-w�ODٚb8`8b)!(!0Vm �K mJ?`BPUjpiQZZZJAKz;YzD--⌨F2֐ Ri c`R;y;b32<0#|0^u:&Hx Y) ѵ b09\גQ=Ǝ+'ҠO3w]Cԃ&T`qdςu@Tl%,#ZSSREbJ:(aT O` I@HE)0{K v¢_%s)"`J A%r$j�/J�W0Tn,(T`qdςգ!OBɀSYF4Z(D-#Ƚ DPWSvfE ':�1'.H 5.#~.솹1!&6@RT�H"$8QFJ68KA\X,(b1DX.C-ږjEDT& l` "U:@-�e*5RuM @) �["SHP,@(%RP|]BZ-L2\+v@5^] b1DX,!burssK/ ? )NSHq7@*ӣ )H4JRűȒsD6I☀(Rqj(&UTC�1(DY$hc~l0zE؅bbX,!źcEr4CW_�ñbpTeòCl`,4UaDql7TC|(#UD>mžظe(ecrqJUуt@T~![BI|ES1o rbX,Cu!Dik͑Rd !bX,(BbX,(b1DX,!b1DX Q,bulrSjM\q?1DX=J~G2Xw[wYKaHu?x'/ }2۷o\'W^3:QTUU;�q#ƺ#csĩt[kn6u/:?<?СCpww/c!AEEȨ1xבsppph!ĉSC'N Q9k̟<y2|M9Zڻwoڵ/_?y>|8CllldR&HZYY:SOgϞp§~*̴iKgݓ.\u\!'vx\BTk'N:8qb.277ѣG/ ==].;dԩS2[ Cz-8qBiG}+Wŋ8<:HnRi$\Xs%Z`ܸqvZKJJп}xJIIu\]]?2DqʼnCTOoq_ş {mܯgb5O<!駟ku;5Euz-m6Y=#pvvnl핺2Dqt 3L<x?ӋRLf�u VɅiҥK Q,Q_|~vAt.;Zn*-U>,{=9źS"?6TWWKmv\Μ9ӸOY:Qt{~ }Ƶk׶]`C[(>]>I!e-}Fp=!CT7BA+D# Qlb'5e~AEѶ3uiSVV^zt ['mܸsUTTdۤӧ;Qʕ+H-),,aÆnMtM6'eE�?=W\so<5?O�'n>Krv+D%%%5j&GLјOCid<| 2љ:H.PG#+uDP}۳gj5jx Y5Q8s''f|Mv!+dΎ|5ϬsKy6m_ugkLl">@]eХH4H{ct_BT{_tMϣƞ)"effv+DQ+]^xddd";;Yy"P'oL͕S(}ź]>8C~dE$>%LP(55UZ?ťs%CQYnWk)LYn@)lz?/ QmȒ߮q FMm:at_[gرo6,ՍR Q};SwG{o߾ۚ8)( p"R@ST t`hT ^~Z.}ZѠիW]tQ/]Ԥl瀋ACTEVǎ"""KaX;Qԁ3A~^[E ũMիWp"Bq1 PdF۶-ͽc=o߁oNڵzjJ_u ֈc2Wgw=V²eKby�: PkHm DRAyڃ?3D=;v<E|>>>YX,6B_GSZVߣ1Dqw!�z#D\v DWxYzP_~=/nܰV¶mu8cؼi]6b]۲֭gǪkQk֬Z-صs'v܍_~:|[ԏW}K]w~æ#3e1�.v]�eu.]ÍROb_qE?rKwF"-~|?_?c Q,bu(XCW)Kk9z2]-L Qڃk~$yl|^<?Ɔao8rnيSCk6nX`k\v]Z/رrը(-æMq K@ԯ7,][YrrߜMӰVeg~{U|ϐ{:DM=]vWդpz;7 +Nw1LzX,DdH41QrAfyM�#Gojj<xSPUIMGisZC p:9m߄8"ؿ_c;|0CS"^Z?;%8wG߷֯Qw)ah۾6lc'$$[w֣VN*_n->7XṢ́j/`g!\tIWiѸ\Np]AVwxgʘ??J LKHiXt_ZSvw\%OPC!J5<UEi%"U�QQeTwW m7W7撄,>?u!bX@ԹsnJpRNgjRMӼ<zzm{eQO-ũuX3i:X(55a!}Xa(mm@eylڈ5kW0qz=zL]r%([P?p?9FXf V֠|bm ~~COaڜI*DPb1 ʶ׋oPueDVMiXl& D"LoL[ElWLRsb|MZ^n{F7!cVN5U2A˝kdx׹ޛ_;Nu`jz5&:B޵ZImߕV.Eޱml'vdE1syg5gΜ93Ҿw:0vۗl޻Җ"fNJP) 3D UHfPVj'R9e/sF{￯JN˶.uPByQ/W$JHe(4O<{UDQwaӎ}1$1:1zU(4]XY17z>x�-`>7WH݂}Af#H]:V^ö[Yv>_WHЭ�;t-]swqW:uF/i.S25 3}g*|M=Vʯ{DeIs_/>=٬2e/_t\.M6:tNɄmzS:9JT$kvmzJfRC+ã'Yl.SDk{D UH }-)eJf{既GEUUY R\D5ii/%q嗬Xid}Q;v}N(&NN^LG~z7|a0#{cJu[ٰs zw+cL Jkc̫H&ACԓ~ :o7bl..cۼYlXF)]}WN%[;K<oA]~]ɑ\K&JSR22 _GKA wEuN^r/ kΏ0Cs6.Uޖ*C?P* :=Rpp<Eꎝ[BA^U&*Ulօ咉A(Q~FT,?qℚQR^ T_BP.J T[DI\NN?k!iByVj{nhʴ053;BۓwPbfX5a|qݹ;P0q8n׉ɏÐ~؍S7~*ctWe[&%:{{'�Nșt^=t'p{[CuW"Qo ɇrenRJ3Q3xRjK_RJZPxo_F9.$)(Zo율ﶺ"Z]2'JAD) F|]4KE[권QDž̳Ϫ EJZ{^{+^k箴H$SHaa{x]3>FHɴɃٲ}I6'ldPt.x4;۟&7Ō=Qcew]HZۘͤy1t؛InRb288i,Yr2c.DNʂi2Lۉ9WVP+ +MRr2JT\ᜨ]gg+ EW#Qm9q:Ii-գ(bqna E.:"*^ܯK m|-EAՖ/RZ؉y/+6UV~ELrNl)RJj$ꉃ;iEE$zu.Q~=FD̤Q^|MnܝY#'DFGq|{%`ޅu{2"g -ku?JKI M`b ?!x!>iX(?/tܞi=XlnaaX$F2~NeUZun͵)˼"SJ[Pї}WRP+?"ז:` 2%MBaqʱ~yUՖ^wSsS2JVi9=*?-}k vUƟ[PYBRIJDD H|,*H[/*o^XbR̭]-Jwy帥HlJ%k֮@ =.eޚ&xa"QW,Q&H?~A7?q7r0A;xGu#id'CY2y8N$N m8%Ss8u7dxF&`"Fh&GŘ{?9:0?12zK^;<֝ʘL05YITbq^vC)~D g%e˕cK7_|k%*`d΂ TKR)D^bJO2|K>jk-(D?0>5`HN4 Z_e8VLMÐv?zzrf$(y<+o|L_qTF2pff%bIOSn2^2FѻYe kqLh4l{/i"a� iM9B$JB$JAD{ッą2Q][J"RKHT˶ZO?UQ7vP+-ۻRR3JSO=n9 TYkD$.u B9F$P`*`ͽb:t ?3g':N{ue-Wz>rL7msqN8/B>Sо$}fbn',u97;oꫯ-&5>=Yi_NI&JB$JAD?~|(2ee% ]O;ᆱfN5F KgP|M|-p)sJrHHpii}Mn9Od򕓝a"` %&#Ukh'nϜўHR+K1lL>1g�f  JDf1L}Mc?.x(9V o zǏYY2oHMEDID B[%ȑ#WsR6mεޣ.'Q5K[/@)ҖkD$VNhwud海>”KhLyd*ׅmQFSG}mӁESx)IYmGDcn;lց"2 1}z0#| N"xzM\tFC9D%2bcDdWU!}(H  Pz/@WJ6J(Kչ{f:z(_~Hu3$jYe)k)HCQL?R-|K6I>5eUB._"rL͢נLԟoeӌ?a[x{[gbz3 bc<2#[{nEWPP$%Xǒ%zRn%BRMI7%$>mݚxgW{c_*_-A6H;+ (uo6ZbbTY%mA`L dѬ9<ܱ=%W'2&|VGu-9̟;;7]dnd$ {chGdS` DjX4ߦO,z̎g1 =q쐾D]wYMoe/l{˟\&c/+)]$J2Q poq!%.Q~!>_(yIeqP6 'JoLm34mNk@$z܇8!b#x|3H'nVv#!"r}7s=qC0}ٳ:Sܛ%iq8t +֬r^tѱ9s5͉Rj-lZ{) ?Qyc<iI称n@/N]UvE$ew.y9>[>LJ_HJ9VYY|Gj??y~e.|%o{J;qZQ*2W }vrTDY$JA.#QGܠo(?׫^zI*甽E#x/{ (E<v7k!33)LƧ0ua(VALAta2 )a.䈹Թ0tHL�n:vn2w܃۞CI~,}GOUC7ufQ0n3=c--Tk]W(bZe۸eo*/}pmc_t.ִ}NhjO٢1ΗyVX<R0i\U*tW$||svZ~7}xm |5?*~|"Q HT+~U9CyFK}&-::iy(ǾcǾd]SCGИixқzJ31=a#ә!mfoө0z}r{X-'Dmd }{}4lAic֑Mw4aFw@ve'}X-u>aLyi/-U3PN8)J2il 1PPd%mJa{jJɰ(s:K3(dz~vnq˝oKI3=b)% (e\ͮ(CWϗrM>O[/!uvNI~r;u˼l@qT;2qx_vME<$xh$JKIé^MrwAʌ^]79]<!!ganZUm>dGQ[(Ne| Y=yw4WxШPqSU~?s$J]OR4 +=[D)Ye\#_3e}= -l^.tJFJy&%d[gDDJj]nD e$Y<N:/�J"0"QG? 8q{/'?SG~C?!4c#cc ~ܮ2~T_:5 ̥}C0tdz, CZ1=waDwElQ,1fMOt;SEӎЍg a֣:LF&c k8s$KdlL&9~f<.%(TTskWɇGOՌ2/tEZc_ RF)swoj.o΁7Jgk>dWAҖfkօ(DA%!!q$JY/QW^bCۨJ9j sO;Y)pތڏwJGF=ؗiwL ҅;vqQaF8N!ntlG C/<xSngUq};eAۏq)az'{F67YOAD$$5:u4ϿY<NjM3s>D1l<܋#GfПq͸Љw3t0038[sg1XJf(#gEl\LO"8i!E>$ {e/]6ƛ}ľ1lܽ3&26d g1&<4=NVAKHĵ%%_j4r ۞y6! 2cH֝'fs1ph/iGAx`P"G!]/{ҷB]1YDLp#:15;Ӗt&4T6AͰYQۘ}wLvl,ޕy~:y5-q.!!% [K e3Q%eɆ ӆ%g2aQw=aSfƸcܨ~җT=1W?= 2f;1/fQU)hݽwelD܇+Svc6ƋQ Y'Is6 CF0-x|xV瓐ADAjRgX2K>ՅZ87wwCx^N"M>tMKp&LͰyLͼQfj9Hk'63s<zN.Nz sv:;xvc_#ɷ%^#|qSSPD.HH  %B%4zHu?3! ܉.SOؼjG0m<{NbРI 5Ƨ3cRW&. ;`&S6:x't:3wFG0< Ux ܍NB}x]�֎XoH|x;aSQ WC3i,3hRߏ%u]\B$J$JAk%w^籰wN})<`QtGf.Dsh ;ӿW??a}֧+}F<@#; YЏ'xX& B bn͞JXjW +*+ȷX1kb6|'ӎ;a^Q/D̜Hi^q]$5jy޹?uF66WZ'|v씺gSEDAA$JUz z~]1sxƅ.aҠ1. gؾ<{<3.|EߎEO|#Su'<h$bВ#xwXޜ9ƦM,it8_vw|cc߰N=vd?@LL[y938j ɡͫO7DzT݋HHW#_|T7U[DD H |%wfބ ^KA Ȥ%LEܟf2sO EQnV7vzѽ8`(oL͑:#GYް^];w3qA>[/zew ˚ 6VװMđݘ;gϣޠoiua}X?yo?*{C$J$JAD,QN>d9u&5ar:ĞKG=>G1%0G&bA;ָ;Sr�6M੩(<??3q$+Ll[ͫ+oX-򸹷_=]mGCB|=)YU]1 4-|O8s5wu-!~ʐ1EDAA$JwES|׿i cADL_̖][)(ڙ-8%3 /FO#-v$J̩<}HXғ™(++Wи%L^=}Ǧk)h#I5%[MɎ70׶i(ErQU%((AA3:s8|]6/>Cq ˗[I{219z:vgdή?c<慅g4z `ZD*CgcN~ǟ<q!OC z x5: ST!>- KOY8Xͳ_*{^WR/)Lʼ}UrNԛA(ANKԙ3D N>㣿8|n`< BmAn CggcgZ!3qGe {Oټu+O?,?G=#;vq N:yѻ D)+)+))e=ז^WR}~yvu=q(AAps٧Kԙ2'8Ax-^xEڂy`I{n o֑(+̻{ qRO KNkb=,Qf*fm$ }[%qmƢ7"/"Q  %~3ʌjv/0Oॷ_fr 2׀;9pM8 ;nM~ӯ0<@<6,m䉓}rZt,Q >VZ.|oD H 3TJUV}oo7̄)C)zVIYDo=S]H  D wp8_Kyi'~DEx~j7;]wc&UC$DAA$JM$>ˊ̕eNRU9 WM;0h$EغYn?S (AA#Q ˗/!}-ĉczb+}YJ&$6#h(W^?+Pׁe˖A(A1i{>u)%+ŹϿy(Y/5t ,]wE| (AA#Q>F#O>&qRRRu s.D~U1s"E$DAA$JnDH񛻺sC2O2P"Q  %ߚDIHDD "Q DIHD "Q DIHD H DIHD H I #% D %"Q H "Q % "Q %"Q  %"Q % "Qo+QgΜ:tҡcǎ}(AA&Q3|WaϱgO%v?c3j^]̓yoe=ٹ_,O<<O</-`]5liz|́;_ڟCg̸"RH  D (%uPj->yyRifVmȾg9_ާnjv<rf}x떒seӑfАe[VɊ6(e~?V'8<ϦZ]Ϟ Xm$8r_ D H RlvnDk[ʮO٣5q~y梌۵_IpWi _2.sz:LLJ8Mf7Zff3[o&j9YjھZ_ +Jy谚Z}ZuNmp 1Ν;oKA$JADH2|U-|%<TRhIVz936ba7[zp%Kʒ٘21KN)m:qQ)0'5Guk/cΝdgTzRhpSWȊ;*%2V91,-(AA#QSy)__Md{JH4<t<Z2irؼ}qo^GVkXKGE`O$9./Qi䤤(c@ ¥ÑJ yiܾ}>M^S헳w2&k0Uv~yZ]IDZ9Q^KKgW{DAA$JnD.#sy-F I$"۫#(O48‹}Y<s$P*:w\4DR"զe˔Q00U<@|Yqc1jXc'va,]UL_J]I,+HfUY:%BېOۇ֑痼+?gu_|Kfo[?>|zgG?O>Q˔sJԩS7ʐ"Q  %J6WM}921CHӎXǘ$J+ %,qdRf'>oz<VY~} L fd`rjY#̺P 2aM$-e:d(14PnjHAQeE)~J<NJWn-!Yb񨪪H`qjKoSObuuuSSSJkaرj;|<jH  D wFdqR!^8lxLY8yԼZj(3x)]&eMXs1i4rtcҒ]HFF�y@|y!3usVc} k=Ys= #>dBMXtQcĈ5<9rVe9l?ݻ9q׿n5t-u*˹{^ڵkOSNE˼uGϞ=[nE�L9Q^IZ_Bmȑ#}O)?w,X@͐D H |q^@WTLBq })ڴه/N 1vLNöe.!D*-|z&#nU9k.$>'#}N,rég_. SR>T/vMnxwy%YN xEGR?~_3gJ;_'==]- W(Bu$ruj"60䯈M[i.:կ8y$7tSCnHrNs]QZ<tPiw֬Y|>>KHH;vL]^fѢE"Q  %߾DٱջVRok-Z6 T8'߆ٜʏ#7�Yzr44k:: -4d).:Lr T2XRnoξr* .qLi6\zkݘ(o,"i-u6]Dy<OC NfwQ~&Q"BJ++WNKo[^Рp8΋υY%k׮Eٲל:uADA.ɴiڽmζu=j$1DLT~ [Y6W8."׶Ĝ8L%x˳qyW9q`g`/$ӓF65|g_fe"I+Dw4=h$[6_kٸ?~$gϞj}e^BsW^eʱ"( ǏFD,Sd{,LdӮ3fZoVS=zTrn]Ӗ\JvڥfnV?۷b_sA(AA(Q/'iܶju(4lȝ%ɣJҲBGeO' 9<y458@sO" ,/n"m#VL.k8wіbͪ)YH+(+D96āgVDoD[|oKRo|˕vme~[ּp?_>hР&kҟ<_,VVREU} oD "Q \DޱN2H* ՚B5eYɚU9Hy‘hr1yq[h,يgq(T y۰ΘMlne,!P$%'%]!ơ "RJFʔœWW85Vlil)S.*Wr^f h4D)s眨˕Y٢&UtUVef/߿E״?-ݻ"2J58iҤuRcD "Q \7XȲ-(O y8kZgSmKM)goRŀAo tNFSq)F-x5FƒW1[̞Oy&r,r!97MN$e5hYHrSc]R1'Zܷγ j`a|Prʋʕc\Ya|W9h^l{qu+S-;ws5Y!vg) M4ke?OE'ZE}DvRO"88?|۷CW$JAD[{ˋ4H|"\sՈ^EeS6[2)q|WY"$ {I+z썤i)m $72t:⴫)#C]AQx,46i5Uy|Ƀ/;*]*OM][7RDA(AHP@k1!f@9IR<{ gK˒IVQ["Y͢jӚ0,BIzT2BVCkF뗨BsTtniٸ. e}T5l^M3QM]H5oL (A$JADJTRI, #H':v<qF(Xm]m΀f"ЉٗѐU'R@|i5^:IDS^6R1IO#ۖ$"5 U5D9=[{Ɇ M+l,wn]nL&H % "Qpc%ju$%jq`kyÚVjX(\iba7lE.RXY0e )8mUX}ؽ%ؼX\jJFs(R‚a$/SKV0Mhu&՛ Tp+XF&jW[i %D H XZ٤EDwUZoۘAVyYI1 `*3{08).Đ_KX(#ɥWp᭴#(:,en|9pz)SXCQGr"qi$BogESAӶnNJY$JAD;,Q?8ekD9BYh"K UbbIUBf+l:W.i1KI )#%RRckK4;m1IˢSԌ2+Ԡ/&-r)I!K/^-G/1\;gQy eě})_>Qˬ^wD|SB uBjkkLNDAA$JnD{Y6߂2輠s2\DLqR hVnLa^;)vd2u HOIR瓠".̲&x̋㋌eM:LKiZ$T5%ׇ”8R KIBA(K~ #Ez>U}I5eRy[.={HJJ'3p1 /% "Qp$(B͌((O0DUESM2CKF b(C9h2fc.نPrݩ$_bDK0EPɮeq,i ڬe#=k.Ye:6ڟIRdN <}*Ry[`eaL×wC${U|**{]X>v/>(yѵ 7no󑙙o+ߨE&}lrk{edd_nI755UK雒ʧV/L߾}Oy߫}W_};S$JADIfõ00=~Zě#ȯLD 2{Y44B3"I^BvNYaQXEN)sRjcKpls؋,-M'CZ.[,[7lo2,Vnb8y:I$懑IJiZ&J9Vd+^ӧٶm{zlDkZ//{Ce?5_\󄇇{gصk|.áwݺu"Q׮]{> iW^_tؑիWD H 8ZgVXb,8tw4kדZIbQ \)3ʲmb5 JuDgfP7*̔IdMX,F RyZU2 Y" cy&3qZ57mF<a)3phYJ5uMߪD<yV3P?s?rekYYfJ5cdMRY%Z֧Ur-?/wY$/%QJ~G%J[o؈D "Q \DRII|ex\n6i$)dp/0l5RyŐDPÒ2{U5̋ɵ#[?%=n˲1Y1Fc%fITbVmPP-zgdm2k)vfR7Lp8\˺?U)?ʕ+ϟҥK(% enO~ٲ_ʢ }"9lRR|dgR2IJ{ٳj)W^WjaÆF$JA$KYòƺ J֠H`^NwyRVK+'˗2 ;/Kؒ{,z W(^#o27fc-Ȧ(Lَ)#M/Kܵ9XsW+)L\r{t/ɦ|]!k<T^`ŦeW:_M(DEE2<OHY!==~Z Յ>|?d5Wu$JK27J#e~Ssy3l0U:[7:GMG~ee¶ȱH  %KT~\X< QLZ)dB Ɍ^4$FPwXtRBԛI6Yjb.iZM$mz8#<7)QWU+Kn_沝r5T4ư,e >W;XEӮJlߘo+% D pEUMM3\0BvnXIiS321i-5xhpPւٛ=/@"ӂcbsyl{ʝvw򄓃Qƀ4 s<iDܕ,faEC-+-oĚ&ۭÑ:z .&²*^arJ�(**D(AA+QlM%q$ĩx+3s Nbu.sT%V`qqxbcK`a۟rSIJ3uFj7Y|Ū=v2MIdh[04l<`cS%4Vgj+2 eQce.r ҥ$)7O>%%D H Xڸ)~90!LzYSckb`'!BjC.e&r ]?EёJ.4}$Ϊ D$è&.} Vs5Z<E3Iʎ!͓A6 [;Y㥸և&:3MkDʬӰSOnD6Y{H % "Qpc%fViS8(O!F'4zt: : r)N./5m^ I~JXٓ̂g+lw zk,$. 8\Z y6͔p.KSW[U.r73(X^ou*pW/mD}w "Q  %%j٦ ,X0)Sx,/g#"7M6ӖT'( we.ؼ2c #ӗGfrƌ( 8y0k1V-ѐ/x*X*MbX̂@<K)Kgjl<Oso㮹K "Q"Q H _+QbQUge¢"xIh$z. T6]fUHO58W" ɆXT<9x~OZo Ypd%],m!A_<y)x܉f'[n"e`\H"m >LFМ큫.;mYX}5KTk׷<x_>3m>įkuo8(AADy2)<k*qx.fbV5DˡMq<l}o<j0eF$4%bD`Ca`reW"Cy8x=$he㮱ebrļD=CbjTz-̅Tf&f 1co*{@ѣ瓓:t(GQcРA"Q"Q  %eZc#Y&,*&Hk&(݌DGv]a<~q4ܐC' T//,əbY&c-'՛"M $܅Z 3-`%+bnb�vWN<$d`6SɄdlә!,< cFH??q~ 珟{9((AAD=19ELIWOjTrR#)j0R=I T"lՒQN^2O(tG&kh21VXeeqER ՘JIWX:ma,5dٙ"mh} ɴ?eH_3ǎA(A.KcmI<2Tc',ETn&Tb)m4^KiS.Eh8y$jլ6/dc,E5$xЗiKCcLId^4%T$S" \VlMƠ#İKu $zrqZȭ̡_,Q(٣f(DD H IT*Rт"Q&3Aa9dXքmV6`7z&awb6;36, '2= //WGJ$[헨PT$bZ|Z\ז@f!9g:Iuڰ/uSd"PG @ʯYK<&e>믿ΨQD%%%]4'j"Q"Q  %eͅ4lQhPT#0dOA(w rek Tm07H+%} ax MqxI2MX33\D kƔ@t ųl;l7XL~qMVK8䖙5رWgQ%JYIOYQOH)+*Q@~_qM7jя~$EAA$J~zvTQrHlRt}.52Sg D^} :+s)Dr /ēlh`b/ƛD6t%gvR; *u s8 qwwwbH!@8 WbHqh)4@p/h ] !}w@r {{f3o5kmVnżuYX,6ۧ oSxgaٮq\U㐔_x(  "OUVoیE;Vbbҗơ`,.H[1)s4w.!020U"9r2QITbDR"r0;<Oʔ\n^DaѼH,H Gnj2J2Zɽn<'!0 (J㱨 "uqۻ kP^˗/aaa OEA$QJ[7a՞Xk9R"nt$@ԉ(Y1iR=Btq]s7KX31+[4"'vFLx R"3>H$*:,E30?= `8gf!>�SQ:I%H^д|;055E(,[ؽ;6| 9_```,(  "OH}@K;Wb,ݜ1|bLe[ґh%`$&Cʲt<e#$-s(̟p$MICzd>򳲑ŤBnbc0p&gLY(] 1$k0)+oQ;bJ,Ū Wl/2NPlL& " HHJfcEY lis&6M9ҟdsNǘbDcI(۟e^s' ia$oLAvq"DJB.R󑞘sdatl9X4QaXm&'"gy&bbQ԰HrlG Ūp T,ޜѯ%AEA$Qa$jܹS&?YX=+W`\,_+`BZɘZ2 !, FbrA"8ٚ1Xu36هM;b}qlE]K"1mn("Jƾ\ZAWgŤPN򱭼 [ش5DB+`kIDAIA|z 8ѳj1N6O-KQ4 Ec9YsFr3aN�Ba $.qϩS8p8R $oB {%c0xtc"香h6[3gP~e=}V7 AEA$QA$A͛7cHqa @$QAAE^$$  "$ H ( H$  H$ H $ H$  H$ H $ H$$  "$ H ( H$  H⣐5k:l-,,PZZJIAADć(;K+W]!ץdǮ =C|.ݡ= ]L1F𐖁Y>03 "p(k#%Cb51o< eMQ6 X5a vA1%OBfp}<|P]ʕ?@NNS/%AEA$Q$U` . } ߕoBwvP$ʨ�셄$$0# ègoX_%YL6T4Unif( -,l{}丙" s|-J'z`U;VqgEc=1og T=z.uOq=aڵkIDAIA|bM{14{B[O(t .= *\ 'P=a',A r𑕁$/J^pIbp8Fh(a,`&揰G)uQFb Kdz" :IX!5igy(uDvP8{D>CMX|,--ג " (0W_Ỽ<L]a)'M=ѭ78Eaa#$ 3!! R( Y>0)`& ӽ{ VD ꈵ7Af!a&( 7)[!{ pBF?k#߇C+f{9CGQuD?$n޹~- (  "#Q",MOz \H`."#QrRe.$ nյ`d᧦Ez\)w4_r^ko>:| {􁝰$h XO 1PIV"SU$sc*Œum侖(:K oDԿ@Us$  HITnT$ DI449qQOa'P]zER Z!@YC�,ŤOV^Gq ċ>b.^pD`%* !I8,9:aF:X}؝aؘۗnWǵ/ީD}͟oKll,<==I $ Z5&0D8'?pvwAhru9 ф F]N:(*_SM"3mjUBbp 83! #N)^F%e!I'l=D9$K NVX拽9:+]qYN (E;]/} ̄GqF 6 ׿ЧO1_/^`ڵ+u)S:$  H⣐(+e)*NT BP "P'4V諠*W TB,1HIJ<a, ƀ.u’'>8IAkudM f|sINĠˉ~1nZ}%d1nX>i}1ʞ_quվ@ms^UY%5iy2g ==ڢ UUU5 ΍ /aϋ;$  H⣐( 9Xa>_!Rĉ5F]BD]{ݞ 7-Ajֆњ``]V( eN ᣬ`S=NT୨ .}d9$K Fa'$0}#LA Rak$kk[ j^y?Ր޽{a"#77Cy֪Xϟ?GNN fee;)t߰ƍ[=k߅UѣGo yj=766r(  "Bt06kzΪO`[&=t/NJH(MFMb ey$`&h"PC0@- F�{;A %ƽ4zpP'TkҪR%M$뚢[`!N/_;o@JPN߿%KLPY}o:6 ?~<?D3,%%cc`׮]ͪHӫW/^4ڂPݻwqݻ|ӽ.'" (($ʅ*p~ّDW&P"pDG@f"@9L4E&i!R1:0TGul oY9L5CnkuўX:VFKxya6 ~HE I)#TA 68_yy8rW>+Qׯ_租<yOo\ oL\ش{}߆un޼l[Vyb]O_zf;/W˗=~ѣG!""cǎ5ctgGDAIA|e/jpKb;HI!D !- ?h`:`2Fk`2'NvHqD>|g_;,~vHr@9"l0؄)B!Va۬1n ,gLQBX=bӳpb0-DU׾앏 oMXm˚ޱ Q__O}gVbMIKKca۷olǎ@jVSEA$QYH*U*-w5n[CmZPd%!)�/N$$᫤8+cTU@:`v_ GL1sC5fy#ٻ6g"n`JwlJq؝ߖ-<lE qtF<7}ٜϐ(IIfUm+++n%\WWr$&&닊.'j|r XFDAIA|娤eUxp`UeL0]5fw8pB'+QTS&cu0X~*( ¼aN(hAN*#2!y,)]9FF8[GںR: Ƈbˌ؞} p˜<?P|kLJ>ϐ3f4wj'ggÃVbl}&hz>|xyiiiÙ3gZfΜ9m>I ( ދDYȡ?'Q<sqX si^C F("HSeOZ`k wSx[#˃ܑHpFxb ~Ev +-ÖQՉ3m񣧜@D㤫7?cqttĦMz)_9bÚ4흯#̪JkÇz,8QM[_2z4iD%""D$  H⣐(Q  Ö(aIICV>𐒁Yp]o)ݘ'c:8i@uU5t;C ǂ13D�{$@)h&(< }P:f %%P Ö⹸R~x\|S>&Q5\jr+}NO( $ NIOACT{%a& ("g IKK#@~Jb||okNf|''!L ?S͐alz+M OCmO8e9;nGx篪O@9j)?ۏI(  "+QRrVU<!+ ^B0)I dӵ$`'*SaDZ" z0E f;c 'UMA4p37D7łQgn`++dܡ#v. ?~ں`=m+cuJ($  HJ*l$ S_))cIIVP)a R5DId᫤Z0ec<"98jɏCXEc픡؛^( >8 �JTܭBMsÈ'O^&e%xTU5q׮? "H $ >D9)CF^2�M5ɔ8{ b4)a,Bi-Zh#VcOx,])a2=�cۿiF#PykO8yzEsz Ś=d rܾ[+?j($QAIAZѺp~pM%*ET1\]{T)SNS4Smzb_NNơ(Dzq^X2n+ï;6wPINX_X'}wW?S5HT'\xܫe3[l+8;;zk`ʕqtT嫵mm>IAAD!ZQQADX)#PScT1JS%-iEJr2phuf}jHw7B9'O'WƖ� E;l=\=/ ۋfee)iz\7c1[ʊz^ꟾ>'7g|%asT>xT*Q"ܱ[T=~rɓ'9 Ub~.!ދ$  "S寣{qIjYXn'11KHb*&kc:'QAʊ(K=LGn?rCsX,X;7 kcGA҆x_WkEUէ:1STTq/xqeM_6{)qwo=_.Cӧ/Ol@YȤ {dl7HJJ6$�?l[ өgϞoTEawOOO\v?222-no߻wo,_111֭ot1[/Zq9~PUUet[;ގ|$QAIAM)+FT_F CU`/" Aa*c"'NVHt0D>|Ք0LCeMe'=, ?'N,e1X"?,6'J4d<v݂a=񟪞ݗ׼P1ba=ܾZc;8˵N'&0a_jgϚgܹ 4633r5v…�G}|>++foݺmmm8[:}7nKavvv㴰$a 64Vhe盚bQVV557>֎$QAIAU%ڪ@cL*%PCuLC! 0FHt18LkX]!{íka<_'lOčG>=u5�gZ6,l ԣG/{ ^Xe Tee=n^y bիWCQQCu|__Hؖ-YXJJlllߑ*Ç{` ,^k&~mMlMXwxۛOEAD$*PSٛ P1ɳ#ט' i_eYLgY VCe0L)V [C9"m EH DN>ΉR?pn=U%XPL`TY3?vԽ5WQy)VuZ؅Ç!++Wb^͛7[oǏq^(VaVZu؛p}L:0&y7onu*HmITKYE$JU?7X~'" Hxk!(16!ZdN8`AX2KF"g5Fj*f!-1JG3\.'3!qLrrh=CY$,M |p)T>{ _s<I>!+~'L8=wk9C%3T>|)jHKK#55YpњL4'o\~ ^*TM=v /hƌQlؖ.^l~TUUbF{>}cȤ{^?/@mi~Kw$  "Sj"drD&✍9af:յ(_Iؚ)jm6.Sl`u={c@W p܉<gsn{ cNj=<Ǹ{_;7۸~8ݻo?.nMn5>~A~$QAIAar2C)0T[ z#2O%8|&DyDeltoK5PXK#F y3\e1@Wۖ-+wҁ8x Ja]رm'?p9W-pE_;7aU$QIAAD8W ĺ#s-}0H =s&n4Oؖ]i|=_In / Q"e#ƚhC ,e076Ϝýq ܼqg^ą Wrr9y,NǎgG96‘!=w'Ϝ{#"H $ >Dr@VM q>Hr6BQ+͛9s9cg^2: ufyXb QI`"|ո`+Wo �}Cٲow~GUP[`?a/>žiyߕK:x9?U]CDAIA|@Ls1Ŋi~( t�01#1o&a6` 1T l0RG}E0XYlؾf,8.�!1q\:{5Oqu|r֭YNʕỵX;ֲغq/|uy'RX:_ (3xTt"!#" HxKdiI&jJF"'P>2@CZ[Wzԅ"L4߆x ɮri VL&pT@Qز|5\wp~ׯW;t6_nxO^ )p"f޷H:u<//7n@mm- ((  "O] ɾ(ˊ¦4- VQ;m |TONjpnz:"l`%,Xgc7G)8@&5Il51ըţ{x)*xToY7OL_Dp믿ϯ_o0~~9ž7u.ٳBj{+QnΜ9+`l`ۓ'O6.kuVhjj튋IH ( jM&2P0fV%D^_#o�LuB|?g 7ԃ,e`%!G 1 QD6- KQ TCˏ/5ࢇh}a'_1F7 "qnlv>,/kwp^ \7c 5k8bŚD?|^" ѰkXZZ"&&ի.]>a<@PPڕlο?eellk5ƼbM ^r#F "" H$5dgQ(1'8\=kr8y҂2z@OXr K!ahu.P*�o`Gӝ Q4f�~*=#y V ӽᯥ ;q1 RG5"m1P[ XC,2G6nj\g,*oQqAusNDasGGGL<...4&mذ.%%ӧO7n*;l/&|M߯>|۞Dud[n5NWWWw%**l\z/y!" HD{X#Ӭ 0Kƅ=鰒f/aM&# =uw>z)vFXkGqa&ʟ 3t7Fp櫭 +D"BX~(͹3$ ù{pa^T=光U*>{;;b&CUUU֭߿7c!!!(BBTs65ZD5rXYY XLړlQ!;r_ѣdeey$"" H$5ؽ?zaJ<Z!NL\\ٷ+?PZJpnoAXȩ^2 3G'㇒tK܉iV<p2ujz̏Yȝ<%c1 1^1c8dUɱشbv؇bس/_EK.Dhn^?ކcM,Xq{<##uuuq…:<?4i,Yaݺu|%Y mx=mm&}g@ú7ol}uttZ\effBUUϯs[5ݿ^KGEADѩJ8;F!X1]m୩; qx#R:p= )1qv9׏ǵkqdU!҇iSqΔCYa:֧M ۦX:=CP21u%sdhLҍ_Qqj߲9#++ ]ti"%%flvOEEE?3;_QQn߾Wl}zj>$&h*Fo]KX̙3͖yJIAAE$Q삐B$BP(O-$Q%D BP(( P( BDIBP( $ H( BP($QAEP( B!"@Q( *)J_[,($'~=n9BP(`abi3⹴Z3h]Y ,1-|;$ŋ$QITg!P(Jg; lEV I3? wa#v}._gaZt njK1M: E%sISĩ۷ [gYXٯ\l{vұvp>?o . Br8:^4u^~:bancLJ=gg_oǶ0jX[Zg7۟Μ \{gδynfU#sKXcMi)2srvtmZ=_9o{K/X־w7ot>9w D5~rtWnEED~^A!R9~ 3m3:h|l~N:ŗ邃BP>B.:/[|&yM3ޑ'NC'!`<.HOgIֶ|M% o./]C |znshK.,`ao,QmK{Ǒa#pq3CǶgܰ}g= 3[(rv?;KJmN<l’:u.4( 3̮ݻf|Б .}qp4+[/8}U4#쵚OgI|eM%Un|սAimCVm}o"Q||}D/C_fգwc뾾}ge`DE[%Pha: i86}ڰ%m颃BP> L\ڻn9]vq=u6b7]ޙsD 7(#ut{]9]7o Tfo"QmK{wi;JA|I&W/kM y8Zky#=U:sNbM֮[FL,IgUiV=ys۞W|=,kϞwEKq0yyJT[JTytOA|z3b/JD6#dD~(]tP(_w\ RRߓ2"ϩlD 9ΜXGIEv7l7o|]IOݯa7m}vXGiؑϭ}i82_'m)&A(ZkGED<k=ܬ1kϛ9Xw__X4l B KT[)&>w4i.bٺSb^X(&M19qב+ϐ(VAa=5W2o[7oZɺ<P{f&'KY!0Y~W߿!~?N'v$QIBP(?pvήo}jF&gLi?{ƤH$BP(w<ze57iE|!"( BPy=1kN5%*Y  IA$Q BP($QADQ( BPH$BP( BED8q PR( BD{( BP(_# aU=R����IENDB`������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/soundcloud-browser-2017-08.png������������������������������������������0000664�0001750�0001750�00000740233�14035600052�021570� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��e�����{i���sBIT|d���tEXtSoftware�gnome-screenshot>�� �IDATxw6Q&H" b{'Dc{D%Fӌ<DccEPTD"2l/wwYP0_psϜ;3;{Xjtl6ˇ+mEQEQEQEQEQx<bԘqL8ۍi+WH]O<jkatt]?UEQEQEQEQEB2m8oRX |rXMױ,ǖ<uVEQEQEQEQEiE|[C8a[kd3&Q YEQEQEQEQEQ&A:r X40>h .fC]EEQEQEQEQEQHٌ˥;wlCh)XEQEQEQEQEQϊe;D"5ei{x2E:,A4\!".KQEQEQEQEQmaH)Th4 ˘YQ!A,c.땻Xi7 >˲"b xd2YTYIM}e)HJd6yAC]%EƖҖ%54$'ÁbLQEQEQ`*zIR:œ4H ecח"h:pQ#Aβ$?@0UJidDEo󹔥(#)5@a}f[%qǠ.%Hb/r'L$iՑ1m!p^P<?OV؎};IY"7'pF R޻ewW+1۲s1EQEQEQXi)<w?ĎZ9~P|c=Tݮ,Ɯg#d2a9l3Y`g^Vwdlh-tv@uz]/EjM&^We!ղC*^G6c p\ \@H7UIdmnOhx404DN7u[SF6y!3qj1[z/^=Dpa{=QHGZB) AlYWSM*Ƒ� ܆NgbWױb_mtqlAد &"}93lᕿSNqCjֿp~m m]\9j=Htx)ukHn7Kd,K])?-g;89 ON&0- IArqp$2:I\qI˹di sk~gc((|H);OJ)6mT(0W]m 0RJgfmr,BuN…>#m>f_x!<ύcW:~Ym#�.Az}_aըCb"z,Ro>/L ITov?Knzz+<#YN Qy/uhG]{j`uCJGL.RS=<}Ӎ]:}g4jb1'sYSVî/<ʿ܂'ΑuQ] G_s.[Hȣ&ݱ5Vܭgw.~_aȇ[s$"Tmʷ_ŷ6_"xШ{5\uZotj^I&|6?|&%$#*}؉j&q:o[\9jSְsx臓p;yURd~USC8>ε(l؁AL8"d!,:sMG]]ǟW}:InxNq|x4D1Pn꨽l[1EQEQEQꓲ3ѕHQNHْIa!WvL |z�~ޏeMeC6VmѷOojkk:-ks3k̜euG"]$v PHŨxqsl%kض@u:`aFM,M&Ƕ۠$B4$ԈL2Y4>҂ kx}y~p(Y~-ed][HKAܘ�5qd8D 0&mH2ݤ3Y24ߋ)\lfS>~:8 U%73I2FO\ ѨerM]$ix]7Xfw,uCsdm~7a6 }94D!!i;.c]m:lZ~P)IIIcChAa0@ iƗͦ}&B( | Iat-MV8~pl;`G䍛q_NjOyew D**$ՐfDFgX!}g ˯g"--\"p,(ۏ)G,"9)-|ׇ]sJfSaa_~m!|~ΝD?GLB(`_@4 hm,@0()s<jwU~Y]s358MAq!�2笣y x$t*g?@ Rc|Xٷ C*!wiU,]\G<l.#C4OL {Q9lnj{[yoadc~DзtDȤX(l]Ǒ5n3ˠŖ[k,Ϡ4χ5-N'1VG(( ϔdL+a'bk[7}CC3X@Åer\%|d8NkCYy9vSOJ? 3|;*;~9 ԰[u؞| /ǿ5-*o_ C)- Lb7kx|{fJ |Vx'X'ɧ.Kѧpɓ;c˻➇?֤gqI9Cf++_}A v#ڛ=x3<}Ӎ<+EhU!?שu0Wpޔ M궭%MeV-<'U{[H 6٭|ֿK+vɟU.S}y1]%$Mv'u'+v'C>"BEy"{99O={>aSj8ㇸIG~tjLO>xұ_e5O+ iw[rd~^q|>V/zG ` 55YM?NfV>|9{~-p$^ƙgNt89OӸuY3 Cuo<̀qŔlϠ;FSI,W>i0i.|DLK6p)4':^)eCmv/򡍈`9S.?YFɴZދs7u2&b9 /'.U?BS/^2ۿ֤ wΘU_x5o]у7<>pcjl%-^Fĉ:I:)xL78JhowTv '^x*3qmjR"yʕĬF]]yGN5{@qs/sP2b.d=\# Nx ]|2H$.r!TUe(hlw5$Hv2ܪ]׸q_{J9Q*WC/$떤u?55b_^NJ((\,* '04cs^c-~:mC}8u]ò즲-a~ݺ'C VY9YV$$%sY]6"2ҋ3tpLE`EYHRR[Ei|jWϪtSϼ ƇLHz㐊?8{"KsWK~v<ܷw'W쌟#&`pT`άXB>~O݀cupm&aumnIx�V2%&K]n-;؇Hܤ&:xXV'}7vCL}4cBdS:E4Y±m_DxkzFM`h;k4eĨ!vJvAelJn W' 3/'%nk?Jn:?nlR AL; ÍD}v"^h(Ne ۼ'uӸ2Iiͅ 7-L`:z WΚ >Lۄxn|8;ٗ3ϰ\Vٰ6cKʶ!Iֲ7f6.+6ڽԥsv=0@5˯:>mlNzU&[;:뛃ZbnVcP-6$Rf}e<>V NBP.@ du/琖جiA穀1r(KхW/m _&YݸO3lΧո@4KNCb`%7$iy8"'aPP^L<+c&?μ2W/FҐ w9EQEQEQ=)%^@JiLla,_Շ?%02;ʏpI}e i6m;GoeY@ӌضZ޶n{<?kO`ɗs 1~/̒OjC-Z0⻮ϫ4z8c_ʌöo\K8`+$˶#ź'nOW:y:"PcSvԼ[ydCsgR181Kiwnowm'e}?Dž <kzh+ȭg`H[}XIa$q|ģ3iaH~ϮMN7ǣcP(Yxma7l]t'Ǎ]͟W/=c۾2Qk7fBFY|#~7X Ҥ#dw5waepL8sr?X[[N39%x7H%Fi~9"{} 6za{ < qG+'c׮; T&MQ RR"q~ ; JS"yKGx(G∖3 zwNtP3bכoh{'pc";{8hB}LhEl@aR�{3kB.*eAOiP8(ux- Gz ilv"gqNdF3!FϽLk1h#csP~Qt< qZȲ *d+m(�&C6bM?ܒmnhl.oKkF\nMqc<44̔,-,5~opSvL+_Ŀ":=(5&;{FQEQEQÂt1SVA4k'VW=ǎϣkӿ͘@ZhZ !d!_5{VE#%.˂m5ϔm_Vw%;|g3gqSFolk1Lf$-}1 ehy%\r(J}ZsTzy$bZޅb DZ[r`B_Y-+* ,Rsp-Yd/[ӭde vq{&))O*#wr3j1[3Mmg+\79R?U@z[UT0+rI}5FڿnDX.EL8GQӐY7'T!%Æ;gCǼپ-w,1tF߰F察MH "đNxrxTk۹o€1)aeн͉}׺@ ѐ Ǯʶִѻ1%S{ jWT!SiCQȧ j ˶BWsʥK|My -邺hV|lI4M( �Ib{ 9Ϲcz!Ky;  t֨@@\#غSRn*{q ]�ɔD7mdt,t$&jz^#?iD3sd99Ya?k*:1y]׵͹m((|t| 6-ƻSS>M ~৓0B8i�-kؘ5WSٚ.FjkjX,靖H]n^Nj䙇BL*=O9RS \:pz3 *"L,*cMO:5)hN<I) K{7^Xƶiv{Ĕz Ìc 8hhZÅtp88�…%mNei)0oCg֚6J?l>N&)~IuRC3iuQ\lX;tCEƐ nB<6:0KkHD8I.]h{[,-֮B4' ZWh qb@y<D36ع?&)n"IৗW<BZţieoXF6VC1飁mG&N K/ /2p`BnјhLwM$O+vr'?!NX5注OG15Z{ǖ#RHD<Aꅬ;"FON16۟yIФy e@ؗlq')ڴMwJR@^@r7iOI LuIкާn[>4ˑǑ}l.$) \zR6is{"GB((|5$e;Ρ].ٌ+А 2oJ?&v`% 7e euېن .l=U ș<툮SխVh{X"#3ll?~hGTצp�]wIdqk 쎥�;l#Jpv3/nчާ~m [iR A*Ro-BhM ".g(klrԸhaǨI(cd?e{Ktu.  2K9C|l5"rY Y}|MۭQ b!pkxajm/IQN~ofsJsщtg/o/W#E$?ؘ=̘֫VqsK{6%NJ/ 4#ÀIKZLwlpB|xX�7'5'PQ$wǒ F̽[�wKHdYp v $B6'+:*ە^?|?:_?13.ݖ&nlg^̹|o|!& D[o2z0Flq~PcJFcKJ_�YRiТxu\dҫ[@JB!h#IwbEН6i7%(W&S+w e)s1SlHΘI5T"к&㛩41=Nm.mUTUl-bFa[5h3H{;6lv!rAT[|ZQEQEQÜt>S2XT;^v 3I#FeRciB'l)v/.tkj2)jk#N˚zԜDr-&�]:.HV..gT�ӯ,^MX7;D[qR2tnmۢeͷe<Pدωp<^g?} S}gĉY.AE5.] HL|W^&$M)>~{YN}Oo澓b<t׆9+,wHD9ҎB 7gA/�� �IDAT3J?ͯ.E�V 4e.:^qVn뗅}QNF),x}֥,(!k٤m_l5N-'`i}[ FЇ NuIfL0;׳Ov.ۨry[١ {l$kv 8>Z9%tE£\σ' \.>n-R7+wlg\N \qlR+tgw*cDŽl1',7vdn5&iwO5xξ!>Ep^ jlcˑ[̒5!Ys,a$@`/E[:H҅Gq:MGN2S2#Ԋ]%y4[d"F12g\߫t~BBwM['1›I-HAs-_;fo淋zAoc{){ѱZ<9hbEj"gEߩ((( �wEI,jhxĤx<n/(xlXɐф !pƍx=.˪W㲺;;xﭵ8ӻ(,]|b1~M^\E(,AO?z+p..;!1Fd5l\I7ڇ~˭UscR"dUƣ;xᣇoݧs1 - 22DvU3a4$/hn-+X`DBE_~'^߇.?G8cp2In͖0-l tan9 /E1^_ ݂JG[Zے@KImͯK|�;^}-&xM>zm 1H-/[9QR쇍=D9\ŬgV x:^ט37yȎ FPr:m#Dr >-Iv6~8ʖ!|woXM= Cd^1pcWg&,[‚7֡ "XmF(Zt^cS_pgz 1DJ Õb׶zпHK_ v 웂}AktEC;,/0-_ϐY={ei߇Ϩ4~,CIljNSA{<XB O{lq 39}6Y vuޒxEDɣ}s1 )'OfO-~ e2eDGXc*0Dn +=/}'#(:K<1&힌hEQEQEQ%)%IM*1 [),10?ݼAU&]A"./wfLlGҷo<dL醲2,۷oG\Lqa&XeMy~($+{w_`?.AAMVHX@4z4|H i;¶ ( HC4OMJA#;m]x5=v$S l3�Bk[DX.L)( JLwh̤y@hփF ~/=J~H-nri}X%o{helJTGf:nJ]I(ih&A@'̒ɤ񏼐~2ޱwi$kc+qa%jty^R$. v:ԯAwCc<I'ئ#.( ;{)|]mkcbXMq'5"IyЛ.b8i6b熀׍N\|{L4>5L#`f3k=HXnDPd>ѮjlڱuBva;2}Ix4 {vQ;wlfoF]zF#Kz2z2l +;_c/ڤ1a oΤΩV?A/6r t}AbѦʺ{Gp,~߭zi9wc((|8=.�efN2Փf$$bRccҴL?.wYV&k |^4Mql4Xd2\)IxEܐt/g{hD/9)px4k9X 9d|yebKxڤK Ivvy{eOF+((|8t]in<N zt];*sfHV%;,ueTv]}Cb'3h],{mϏYRcE"ը~~R181C0xX%{mBW}(((1sƴn͔UEQEQEQEQEQ~͔UEQEQEQEQEQC"s<\QEQEQEQEQE9$R͔UEQEQEQEQEϔUIYEQEQEQEQEQυ0C]EQEQEQEQEQ/M0R̡8ZZ(((((i*ͦtMJ*TEQEQEQEQj=+(((( 89 X9Qrd2lڴ_z+>lZPVQEQEQEQEQ =L7w.'H*)9~=oJJX`A{*)(((((_�')8uu.$I^~M}~>f!]x((((ʡ59掻UB &;}IYiSMŊ(ؤi p(((|y X.?Pzw_Ԕ_SREp؊=q u/ iIgȘ6 MCwy ]hY,Yq$R4Mh~!_((g5d^ZSV9(+K:Ŵl)R 4 DžKSILu 2 _xQ`e&mHBC7 \n^~~ IEcl<A|_W3b8te? RYL�\>#1I2d-ۑMpy== #L"Atplz1pݸ)=i:gu&)чƉ1$WX$모|iyb `9_=cFUP^CDng*~ObEQEQE9,5en'+1Si܃2q� xE:^Ǯ핬_%KV5.\ۖ1\ЏrXȍܺuQ-,!O+3&1zP^kؾa oϯk)czοg|`KG7`K/>~?1-#8[O}a{}& HW9~0e!l>Z=6Ō1@JceHDkڱ%rgߋ'qA}ΒQs W`·Y[>v؞#d՜ۅ@"",IK832+�-LKA #~)((rh5֔U'Ǔb?g & Zn((eHA)CFO?pאEж=dc]>o]Mf u_^)C'2t±xnFhK/<~sZsP N >U4m&Uc[`Y&mƍm7=Ƨ~VHQZї^)BtpQoE2h v-_,n|/=VHv&PPʠR<>Gxv3s0  NB֭ɿ=+Hڠy($ bi BVaI;T/@G|thK隴M2YuRm((lk*Jy]g !C䓅<9-Vo&aE4qQcUZrd/+X,]]ތ^Gs2Gpx\CI߃DtyCq=o+ "4'ɹ_j]} nG?ƟWDC;e:3'|8t8ŝ,#p}nhCE4cO 2.yz^@Ä %hX|#<zoS;: ) F1i a䕇%X A__xo32Ȟw)ٳQHdXV?dEQEQTRV9�nFMD�g"|?Yn~7Q{3n9a%]GJh|h˅ι&cIM,iX OYb̒Θkg:@:.;!11-5 /w ;M$BǗbFփt5M7ii;mۃFsLҙ,Y¶ctH'I{?qUj*:ŷ^ho/8UV6KIl}[[]޲uM4lvv:F]"A[(<o}Oo=3Dl[֯iɹi8Lg1-sbmT+ mDjG: `�[/21WзotjcѤlJI;KfYp.W\q#F v>z]T~k?hQga[iqMЫPiwf՘->$" ٱꚖɴX2H$Mh膎AwO~}t'G}3! 8Iן5ܺ�4NN =CLƈguyvKt^X$q+h0AG^t#WOĢY\QEQaGߛD_ Bk3IA9g*bpE_ʋ $ºꋋX5x&c'epRz*.㥧cC&a7z0IG8ŒGط5 ol$ڜ L>o8qC)p;kv%<B>Iywpf7m.f\9o ѧ!WNiQ׍Am^<?.5%9c:vB5+O۰mq=>%֕;h5fyhLʊ6=?/˔#>/} h{woፇ免f7s/x!eu_Y/_Q,7{-Dbe| Av7׼ˋ~Pdycp05RuỼޭ}W»Ʌ-߲qwzܯzvAxp6�m pƓ݋_ :o?yjG_ЍXU,yc1WP|ڰkk�?q-?#g] F?[ng72$W5 &C[7OhK݋bO@f@S΃f5m^0{}x^᷼pLI 9ɌW_3UdÚ,|MVWeiΈ oxXaw~ݑ|DUIvT\=Zt'?|kѧ`^Ec;x{HYָPEQetK2I4b"1Od\5^stpm s~6Ǹۼ Q<`3b)'qϻQmuͱ㇠Kc[ 2긾2gn%Oli�/ꋷEqb(76Ĵ ~\vt .!חᨹ<m2\u`(WcR*u!L;LY]PHլ %&p0 X-x gF"C=M˶vOWW/xMnmeFVh|IG>G +FáOeמ:}C3:gK[i8>f+pB㏟ͻ-xEؤ 2-wЦzr鄽MY*iyؘd gqBlmս$<k8a>.b{gl2]?Vx{qߒl2Fe>PdoȶYi$;<k}E:BJL,|/lݍC_9Sx8d{nIU[JʼsEnzj3:1}&{5U?vpE.GI`o1{=ǿ- "0?޺ p#EFYUekM&;)~5.&add!V:cYH?3(ezЗ=^)dX]NAI`4߽'=O,$6 AY�d?G<m!ygej#7X<o>M}w-Ec9;0~cKnyk+[cp嬾d=Sƪ8WAv>%X/Ggp%ͼ#<f"Aޠc8s9|_1u7'dvۖoѶ<p3SC">\.9{4EX2ykU%{6ޢ{79B/zp!,]}=dg1dZw{qJIkjsFn[j=m[eO>ٝm2/]lgo_ǚ+ 1ft?Xu=9B㏷`l럿Gnc(􈩜3Pܟ.;e?ys4wW.#{ _m`#s9cl/|z.>6P_\خ'ةZ>M On1|s史ꑿ\X&Gb3`Nfdl'eHX' H8+?o16ܻ۲Oxfꌼ|i8>[Q,@wH9fv7~u�ZsNgΖM,XqI.,xl2!Bqy|n/K/+$Ah?y2{~D#r}3IM4v h2w�}aYGq3ٍ  (^-ڽm{kBoooݕBqw! "7;3&!|gdg{tf9=8*b_ F́U^ ).\`l#YX@ndiC`(AƚPU?,Y)GaO$4h;ɝHJ n˷b.r4EE5 ᑁ|QϹ1[m9–S2O^(%eUQfb]j:!U/Ճs >ԥSɽr�c K_%BZ%pˀd{ԺX5%03:WvȤPѩ;%:evuN&&: 3br!p5퓀P5/Tz҄ n۶3k<m~J= ص{o,$p&僟=hٙy wd,_nA r%/Rv-C)6o[GOQΑ| ؔ^Ed]b яs(VUrb)b1}wBQz<ii|0C+q�g^Tg9t:ۼ½=-]%E=(˿G7 ;<?/VguF M䉻@%{,g>r+#!ɟLq/hVyreliٹJ)Brj{0jD=J̜)o?oўf HJMs]l9qće|>>?: j!驾rQet4F O-{YQG-1,5h\x=CxߏKK޼)AJa~h�� �IDAT}4$YokfVё({=5I~~! D@H$MZugko{N]ANӘP$;W*cUKup`A-9_yoѴ>afpa|?�6 #yDomF Jyma ~f0p WX;U.ة|H^TI!gP`Vaj㬬!Ę& ԰faeW‹~=*>̆_g1kY >$%?4~{眪!,QkVE #LVH}ȸL+on˲L߉WQ8=9JyDc?H_s 5`qkJ^~v)Ԇ-ilR7 oG3:OCk [c\4 7.&yXt[!C~dbӖ0mkA73_tA x~/&>.6'O8](h.n Lړ1]yع3pF3iKg#L疞H^H5S>p6r"K>cm]%~vVi�$`ɞ4(gʮ].]y?_åmըanFwZ,KLo $$R%9A߻,bվ#~ΡGL223/vnWs2l$AxKN>o"{*f~? Y2!"d/ɀ Cߦ/qqyMz$Ypի" (8HGcɊT-Ѱw_b$Y4[ؑ9Mh�9D1Fct4e(.7%TS8ҷȫk\Cu ?p_'$a/_~z<_4.= w%o04I&8uo5iזPIpK]p94FJ!߻m$cH,-N݇>͖0e^zp;dZ'>AxH]36ga,3L!hŅ f̗xp|3df.|[Z?i~曹h41rObO[(ln43K`}blh^ p ̖@-F$[VLDD`Q` Ąׁ^էύP$iرWxjvBisqp?wkŋL߰:?]:c׶g*ea!&q0ncq3f\Mݛ 2rl vG% PΕhԩ'|.M}u+鬟ߤk=5ՅZU5C TNnYΰ~0Zn\i$@ ab7u#|;ԘO=Vm]<Kd4BUCW6L} &7WJڝa oP Ill gˇi�"# E%L%Y[6rJ Pc{1?",!Fά,Fq6wIk $ru*CFj/Dؙ>]c܀sxE@ȉ=H 9u&[޹υQTdߙFNI>>#T@+Ql7 5Jme FߗcuD8&ƍŸ1L*ʶjق[o6[x?y'-7Oa~La&ǓOU֬S^sv1W<I5ʺ,1q0~]ҸXy>x0yw]ױ#(05E 3_<ؔHzͰ>h׬{gD�̀A.HV0�:j˳Ѿea}y]55e$2* R˗TIUO"4BpPaZbXUgu@.\a<=k N[GNbJ擇VIs.#V o{LZ&Rr:wJ]\Mr˜FMHa,d a)'%J!˄ cGH1~x*ySI^@=Z6 F>ecll&w)R {LJ4B.8/bNNkۼ:r Yj_dJ4f>gZ1Y|K׫"]S'MXJxB \9$mZłE9n0tƵjur%qtj8-XfEl>7ҵ˝eA"d^A5MaaC.BصL{~&~xrJS 툛[+ӠjwÇ;�39s\׿/Z"bߝM 0Aڮo.D.__Bێ0wp$OٻvWOnx}ץ+XTD`qT4|iYr!<ɬ-;c[|.w_1b#Op {2ٵl{+܀5Iu(ê'6[&eu _T#k`cGC 5JHjSrTz2 ޘPK~h6N&6w񺳕*Zh\<<谻\+ <>YcL4SCX2I楺`DP)g&êȻ9gJ@EMzl64.j =I~4 mf|ʧ�G/=zl' 9]$ `8.̀o5иR׃ 2J\` Z>750 t҅|\N94oMDD.={> n]پsAAAI� -ۈih$D [ӱc{O5WObIMҡ#HDQa!'O`ɸ1H:|T"## %-$ƌfujՒ 6mʘ#8r8!A4i܈AHH0Gkf-4lԀpV]W۟|ʖĉ-7OA5ʆ3yx ,Wswm>'Ҽy3} lYsZ-uÇһWOfϛϦM[ &['Y-Ďرms}Մ?eMz?.6UI"(xq0<&�I'^-XmZ$Af.6A2d)HbG֔[LskF3ZV.VfU~+h%>+(@B6%./y?' d)W&UT`-ފ\%B7j^vrqϻUH՝])lݖȉ1K⅜$lO\3?M&T_ɋd(àC "I *W2V/[ǐ]GO=Cm<~{/:o^0+R6lK-?<1|M�5|0ԪF%LIVOfr;nxƵju#YŻd3j8Ƿà0p2d/?2ssι͗I/K겟Ye,vݿ~#EX3#h{$ͪKSP=8N\^ d?cVEEUO>=V'{Z%ښpN_9il2f`$Lqr=𓮖{]iѩis [8&71Rro9\`͒x4aŒY5+5^U? 6fd>#I !wvk4t:r0!!ev/� Gm:.8̶|X*<GnFb&;79m[ANRKzC5m#oy]MNS%O jtva6nc' bh\�g%U~Ed 0`m\iH70k$rUXnX$Z'[Hał+ LҊd c~7ӂa#`x@bZ8Ykttttt`0Ȍ5"VYOaawqIOA^ dggEbm<y8ܩN"(¸1{{ϿpՓHO?hd)z" L.y?'iX4q)ϧycbͥiMKN?z ڴnc/'88ZhFFHIImX֮HHOOZPqA Ջ[ҭ[Ze IJ$I_tލYs(wIx?HC |m=^yt0 00.6{ d .@aK{oMs|LHU_^=&K1�BE|)� @~묶\!}x 8[QE<?o/BNjeC#}&\O}j?}7:$;}1/B+#<.1Wl獆9V\E֣L܀8B%u2֔U oy<~w_]/[@:{ H6�aMxmk7~ˬاsyx4,'G?k\7 ~ugA @]Ktj//=$յP|G`ݿkt<#e3}t?<ӫk(+#ӈ88g5!agOmRZF:L}*NؑQ=a}cWdF_7ޱ;kwkSQYlf^X3 g˜Dn֞—I7VZ`iDt$+t: 1PՕBݹ2"iN.@Ia a8Cbֳ9n8] '6Å 2Oa˼{hy0(ku;"8$�%;͙&Ha4h`™>5|1"b]:Z(HUɴ >_a)`"2s3X^j Ʌ *P�r ^ۛR#OP)8;_RjlZO"l;Y#)3'7ްN ؘtrs8$IL0g);l06kʄx9y*dGcǓڥ3̙3L ڵm`r**ib+F` =;vt( Yp1nf͛!I2RXT`!?x֮](=bA N>MnnWС#h{ Mv5hPɕ6ҹqmiZeuhu㤫i` G.F IKZ�e:u EB%e,JٌlTZ`hֆfZ EMr΢CXZH8P|mΦ,DhN;6!@Av /8W Y-( ud< :.ZvGQ܁_CNX$3v V\\XJL4ZchK3y Z~ŴQ3YsiodhYa.e=JDE<KE'1*9ۧ{'y XulQ'4 O.f$T2m.t lVOOiSyat.+m\S'پd:W.mrwbCZOO5_%|Ոpp)ٜffȲ'{v6tjd`K+</kǾ5s}"L!1gst 0f@o\k7YdzKelzv",Q|lЪ9jLu:u000\nr6a{6kl� ۍ +ybQyulR ʈ&\c^(.?U:Zk)�<nwY[A=z}}ֽ62] 8+tI`=~wJϘEӮO0h@k~%!$CA# yՍԋSxYF򥺄qd6#CU8Ή_ⱫH6 |E_'NUd5͸qپHpC*:+6UU_bT5Brr AUUvك@fV6;vh0s-(ۜ[''v\X,N-XLV-YrNIX~v56ےe4_¢"}cv;lW`4ͣe+Wxmc08u:wt:+fsp8]_Ͳ˭v˅\2<6Xǥ<jJ/n.N?fݰJfceiy8 &Ńa!a\?ˠI$= $Qj42 CH<n tzߕ>LU bl.vWxܸST\NNOYUt=v@LB^gr:GLUӹכxmmWg5B;\j/Kї.LB}>:J=vI% #!= qHj;w*z9ouzV 8w^ԃI{P4@(`OG==J;׆"MEt= RGjX),P4nJ8*[OQ,F֝ԭ+BV!va/.y!4Zvf/M<.p6*r62c!h1m!PDq\,W]v.p}q\m+YHz4Ϋ] -ji$8%>BҾ+IHU.Ha8d-Y{ٳc+Ӝ6XՆ)ilXb0C[E3ޣ_T}DCS*=;ٕ!7lLcc?+ c4Gڠ9M g桖TUv>ex()+<x6z[s KUl]OǍ 4x#*L<GX;{mf'yh6&F)B1!0LeLF[Ν9s_W#a; U<Ahx(Fdf fCs: <y/Wck?Qmu 7b �[C~[ؒV-rصV/'}/ZŃ)8q)?!v(..}{1| {pPhRXd3dUY)onڶUUѣZ5gt؎^=xUB׏~z ImExX(nzQ!Iݘx EE uGJTd8C `ȠL4M%j&v}0$]JR.I $՚HNnM%ǥ<jJԱvHN^^$__XwL'2&>!F SA6L{d dc8P(/DaB\4fN~ ف1|{" ;IKVsD)#I;D`) QP@N~XFrzjײ`[Ny*֡`+( ЅbiHM *Wױ`GaKw^Elgq!9yVlZ:%u`-4>}Ftg lHǑ쭝0KlOSlߑ"$wCQAy܆@,~ZҞjkoηj:=5( [R"lu^muQv_Q\\XN.DpYϺt̝IćHgv봨C5'\u({Ó<s}w. h3[0hl_<HWR�BHAQ~N#Q rSU$iDPM?>B+68 h;oI+sybR4.ut%Xm({P4:}O^. 2_mƟ Ga6̈́{TheWL�| �� �IDATW@N^j “O< zq؍2NsqV ׊NܷcumW5h԰;;]؝NukLrc>Cﺛ^:HQueY(,,Z\Lq`,Ɉ"+Ţt˟Nkw`LNN#!#J=î=h%!14jwb(yթ +2�^<R7sR[XwS&=h Kid:Њ=(.Slwb;Qoq,c;;]زX!E~9j'ٷ�)z&Na BYW mfܴyWL{?`:?YY2!]3$Frr QLk'L8.\^v:d$\pI¨_rJ!I$dKMC"welj%y~\7u SA;]D̓KÐx_d+/ҧO<z3_~1�? J`۵eάڥ c`4ȼ$Sǎ4lа̌+(, [$w:u� 9b|/!%.S{u/>{B3O?ɀ4a<p_:w|AXh(]s5}O?±lI]^|}Cwe7Ҡ~je׮Ν4iÆ԰їy!`m<k.Vk1'V9si.);: FW 뾝 ["�n{b�UDoj}n9Nv/^7%2^|[v 9@#J73acϘ|?SE~xu*&g̻MVv]#8o\I+əkXg눁4m2j&ѬG NUYqjOLjNkOǗ󬳚Ԥ#]"e@퍯j-^kBD`'1-Ax9i;uq'{<NB>޿Zٟ2}brشt;Hy<^ut(W$:&HZS([e4+Ǘ}ˬQx{0T-gAgS]5 79WO'tD"вX5{ =r𭼴d?y\皛ŭu{P0b1|,}9{JXֵ I07jMl: b~I[.~eb_x&'nbWz^ai $$KP¶ek3ߜ vfŊXfGIJΤ)0G6K\{\x9vwDtzFˤ/X$FacO%{Pcbɇ?>ldbƷfhkC;VAb1# \q8EiD@=:%fYzӅ=3FGGOw9lr7xdOjJ`=bkϵKøİd$4gY彭HaA瓕kGɖy <0vh90w)4-q-VK_T5gu#h)J܂NRӲkp!0uM ?n@w8"ׯJ]^qڷEtBV-܅Չ!)vWC 6 ,fժDGXb)QdeesՓ7o!'N`ێ]d}?7M$~5; >l@ߪJ_ bT{R^^n^=~V<6 !g_r24K[@&)Z #э?8~MijK l){#3qcFa2v~i6o嶩7ӺuˋI{O?s<Drz:]QB]|r1{zе]KG7^+ygOs"i/mhˁ%sHߋ0Ԉ($3%mkWzNC5sÐHܒzPnֳ擛 kNgŇp F\ՓN-lBs)Tl$>x> -S/Ԍypu:#p7y�J @:f|`;+oXa5oTMGbX|GZ6 '(y]؋=əS'ٝ^,,1 N&S'bUXl2& : ɀ$a P> (1ȦZrec4U|WK\]+X7; !6Qoz0 oz57]Z7""ᶞ%^֯XS ěqti^� H=BRt^r<-H+_tmӜ m'ּS^6?ۍ�E5)}$kk2v 7y2ȋjDD j6+gH;~;w/ËR~M[ɂ<A۫0hl.*eΉ|f Hpu;h] BYEFQv<յl1r{$\>̊Od>47`W�OW]M& $ùt~ ǒc87yح8|iq7o5b5GB[W_h{X(9=f QHVZ}9etJTG!fg&gh~ggpI['?r ͖KՅձ +b!4HVݘp:JB ;8ȏ~1$vxm08{a�b[OdpUDf&f,\ȦV7> }hvͨ.&T{g*#ķ)لMdT\#{Wo=n6`;sEŠ, 8/>beiиM2\-IrRs8B%ko:XMʹiWg=`;4$vT+<N[sЩ8:::::5|'7eM<7EI&9AAa!Ճn/>2˯&Elܲ I@|姸.]O̮VV*׷Y9 2z9Fn];w}&Ÿ֩-degɧh2qyV,?i~uJ?+ްA<ݺ[W,,$M)\5/7<i<'V}gp8Yp1+W|eƏ?Y5'U0\ngGr<Rv:rMxׯim<v)E**P<yU}חf]M.'ӉWHb&=[K,x]~Ϻ59O~ww V W6>{ˋj߼LGGGGGןѺs˚,4j�kQ7t'O;-dƏ3I=Κ9s<=z.;连ץ3ص�I0 ʆ+xZ◶ L8A滯?믿e-<ۙ>c0W$22[3iX{,[Ur"% 6q ^y`п*;4Φ$m.U3ߡf?g8zM:![9p ]s5}`ÜDy}u)a̙7b_]Jgdd2wBvW2u͓T\ us~u!ՃC̘M3]yGGG.ȄFE)ĎkBEbW,#Zvز77#gҮluac :nsTH16x7߬<YF#ogQJ6s瓙}�\˝wǑc߷7<~f̳ϓˤ iԨo/ A*E'OSiۚb4!ΦDNһWOfsvے<\?e* 4y?Ro$I ^y9ZlN#,4YejWr3*k{^v[lƷ?zE<RǂE`ѯ~HXUA׺et/UJOW>z]!ꡨ"an|~E r7,`)E!7e#31F#?e|<W!1964}̥ɸtu.5s5Doo+(k@*>ְ7::::::?bڳO*ﻸ=&R5IRRذq3˖3~X"p1,/zyф`2{nT믾g!ϾodYMHJ:a4oތI D �twJi"44qxػwoX7V yѹbQUiꎡ+|XG+B{n�-%pX{q>_ۯ> $IBeLF#b6vy@q:]R1x<djL(4,/i&4!X%Uw{<hj @T�v ,c0|\M@% Y6"EU$`1q{<H@Ue48].�q?$mο=�UG".`C#?ή  8 !DH2y_u%E4zdIbt؞3 <~QnقC#!ѭk-nr=:IF <͛*BhoKtڙA1 3P();x@5jLmGf͈mӚ $4q<}h13bP:ogճ;cF!8atЁIa2ki6Ns3 Y#\OY?dmEͧ<:ή ,~kusI4d@t(,K;Dc;}ZhB},!c0 )l~~>WVznP5Ɉ(H  !$<< !F3jBC%z<ԏ*X TIqq1aa @ YP<^EEͷ q/(ՐQTc l!OWm 2Ӊ[2bD@u9q塣o $I ˨l|J$ e2Bd TMJBF9RgyU;'c4\ R@%$$ 4 F3 K,e J2Sbe !$$�A+9.(\*!=1]؟۠PLF:H'Nڄ,B {cd+??ΥB_V(3jBëeJ+(;'hi^EH@S+JyUߤ@D֣(@,m$M W"J]VѴ ZblUsEJ Z%[UnHo+<z(31 yXU !+XiU؍4 -O MB_ofB ȉH;q[SɄJ |z&'0LGGGGGGGGGGGGGGf(*W%kW*gEM>+>SV炑�I3Ğ9 @>#޽‰"Ιs%ߜaKxT?lL�M~~~~~N}ԉތI_n#s1<<}kVK@  NÃW!X.UVTUl DX憬(á $و%( cN^Ex#l 79hQDʀ[MkG`4h@qq{U4$`C-$s5k4r(V&E=MGGGGGGGG_#Ri+9'G]•CSSOiHR?%ſ'Ӷ ysY*r%yWFp3~圃8MY%;N}c 6 4eYh�ƞ<˽,n!PnzZ]/!VȠnۄPH<O~؍-Xݤ^;sII@"iѶp[1DmWJ c <ΫwƵy 4nV`;_,N%r}<8^L/'Ⓩa>#CQM)Ni|v _|>|:$K?8)|:WCӶ$ym)g+F ~}ά~l%|19OƦɲJNԚዥ>#4\aӸX*r+D8RvmKBkۛ۷_%}X.g=|G 3?{VpΙxΦrh2*ɤɱ7{gWQ94B Ы (Ht""k7t"EzH $!@ғMپ{9gf~̹wwM;M=efΜ><sz ,XIf}N~· oDm,4p8p8x' sl"3xcLba?ǰį/|WQᕗ[PM3>#h//HM<N:]4Qe=0E Qo1-)ڂ8M G]CyzKCDh0!]EĶT A�DKdxp8p8Ekee:!+}!)o$^m<sV4 HaD M  S _ڇ;:,~|Np|C}Dn` x nbbm#٦#$r$HAqup8p`m@0A:DnЍݫ;O_B$E6R_x>::c5:,*|S$nWXΓ{T P%wkfq[zGm!@bIPm4a1&G_yt#an9& :Anu8p8QyW t~},VLqb"jI5;ӿ_'X $T 3!T bZۂ!)ivÜ(xDZٞfK7c..[݉ KU| 0;/  |rozU(jZp<n?8Ű:kwEyhev~yB550=̺Yh[ɉǝyGk]5a(:- ,[DYp8p8[A-&yXD*M^k`ChEZSrŀ6=:^rlŕZvTcu1$lkϱ_M f`P21o[&&J5+:wOU;׊,=p,^!S d y$YqL+}ǥgZ1_s̮48xDUpG/m"<}Lկȵ7r}Gn9=t y3N}.iD> LLv}EC\p8p8" ɗ)"h=Δ]`H7B  wZ_@UKƔ_~1?HڮɩX@i�� �IDAT֗gn`LhUQ~!( !բ|ۜ:-0Da3]v K~xrp8p0akau Eݞ3`ɓfe4,_j*b0N2Ngpӟ%;[('1`ݴx3b0%<9^�B_-eB_�}̾8{%<Lx3س8n~ls8p8ñ0&+J ·_ҷ,FHT'/f6,,Vj{%ٯ@!J7f5+= :c5`AJ(huj(je]qV0@aE[Q1WZ!$8'sJ0s@rl-T* ]̃? n6p8pl=D(a _A޺f#qb$T$/BGXl"~V~QֺTUھFW A%");j+TuY("f]K+:HTSSm?Qh*vu[6w7YX to˔ul4{X3 Yn>p8pl}#C>Fx_qĊJA" (:)%1R!xbOܮ&#Lܲ kVa9ZckY|D~V6E"Җ]B+L@j@lL"Jtۍ<B"$ED%:CEN wR D=u"u8p8p8%T|yKܱ)\3H!1BY·T&^b1Ɗhj(+Vj4LujȩVFYVi+ʖRcBk_$"IRJ"+PݮVF[[6aqRM o8T&\;K+jRDtljK9v[gücHp8p8N;|||R/%OJOHQ6VXiVhBe_J/AkVFie)PZǚX)QJFkc{Rh1JuQ cZ*Nܸd5&ƨTd^$ qUkP%%T;Od'be̞7+ZwJs!V޲37N$6+Y0qd/vcSp8p8xp&@$'|O)R HQN75l|2rZ b5hcPkkC҄1DP(V"ULkJ" P8քQD*"#cTbZ*P*G(#TR1c+ q"T*>Cl?n<t @iŪkK{kSȲU'!b~Af}d*8FB) A Sc o}t-bp8p8c'OzH T!R}iز3Q mܪ$"xH�c$F[WilH6B6ֆXi"2PRR cC!T#M!R+TJ10BM) #M!a Qq#bqdYK%tCw-gtm_~"<`jju A RLa{.qdwⲟE($+k0u /BdBaBbs-$HOs=9CJ˔u8p8p8eldtI2^bVڣ $B%.r)�^-yUfLTc0$"/nSe Z$�UXYmY- P0KW("J"Dcw ^dUHoK@<ı!SVEh+_9䑞bx Hc;-&2JR׌Կ쏎-Yep8p8Da'I UT} ^f LDW`5~V6fkM\};pxW !YiF .[ (E|d\+E}aL)0;nO98}'⒭\ ֶ5dS%#fu\|o1�!@>1TM "(uuwC:d^x/~en9ep8p8w a۸d[īJO`T8eg #$(mg=)*"e B <A VZlMXOhn[:ɟE[Kmh@  ۗ#l)# �g#Ę�m +M4PyYhs2eG,jd"qyp3d#mpQBza(~]#~&'%Q_qW;&AT@Rx ~:O5vLة gtlVp8p8d20m Z~S'pjO3(ĩj 6HYPֽZ<+aбB) 'nZ]�;F5H)*v\q 1ƈJ2e19/sYk_t&˽<7^Ø{%/< bb폗I#^UWSWA>0QD%`n#hh J~jzSלSp8p8xPFJqDS_F<RXaSkCDP4xRMY׬RZ;B%Ž18jHaݱ'A`#D5 ufaHtY*d(tTD/,0ڛo/T*@u "34uؑM YJ%UYd&:Aʽ1q2#FQH@ v:Qp8p8xbAcu"xJR@x֑tݪH+Di+A2DF눮u !6S b- :#|[MAiE( %4Q i)d Vpր69h[4LuIPEx5'#&\^}mu5LM9UU RR;j;(b­(V#$WJ<)ɭoCuw`0+T_Tl6E>Ztՠi,~m ?4x }9p8piH^R+K$Iq/bM/iJQ/=o`l4ߓd} @ ͎5!ma,clѭ| c ElL_Z5RdU)Jh%C&%H0&)a H1b{t~%�đh$y!,$iN!e3wMa .Y·)}LB9]cO:-BZZV:A {{O%¾Va dQ jҍ͠G.5bptƷѾn&L܁#8|hku)[$?]E}c U\ Q(cm݄a61uT7O Fדub-A"oNHimp1ZcDn!"ϒp8p8,Mi(c(EjYZA$V`#ڀ'Vi! c? iJb bAkЂ|1h+X!4}ŘHT2Fi_yϳ hB1s6O_Iϧ49RKfx3& Qfj Zc+|?c2̾|"V,:|Hi?M\9@w#I锏̦I7= 7P?Hi}?۹8x'([׷8fۚr`ɒ&bDx1>{qίc~ ?(Mn/>t9`Jw߽>{69k録F|G0Рtjk ruHOOM5&CxKHg]kaɷ`<p8Л+]i)UteR)L RJS:)e�J*0W h+Pz q2$[u xIL $Hi4eE<aϊBi {)Y])]2`MH!FH/[ZhCh<i"L`AaI*Ax'P]U_}t &濲-S}>JQZ7v“l"aBss0TLMQ�oVjkjjK_HSSSep{>n*WOYp;Nľ˓O=|11}>}k+#=O\;j(@&sgc2 d;Og`Q>_<>~jFkŔXAol=/ i4EZ1 M{XSbLs`G)ѹHcH'>Kv*v:b2 [MSc i |w7]H5Vo�"d?|zWD|1wo)CLU uChm)v[$ U ܩpuWLJg/݃{/TH[K"мT.r/^5<kp8p8rŐbiM#QIOKD'"+`AD <44B͈E'X߷nUOz1�lxDhy F)d5I.,i7[mE5 =d)<afA>HJ9s9xp̘g^]zz2k3ׇxt ^%j Ta m H'N{ HIb S9 g^_ C}7t dɓy)<;\c9츝)={UJ~pu:XɭkaMNW$Xngw9A7N}-)"gV\t)\#;|Au '#W_gU]Gfݹ"^1Ԥ >2m|9 f{8rjR;[x;Em4 |]Ar\{t r{9Nz r,WE)u0_1xj[Ɇkc%+7s9z㘏h:tӿ}?jz<J}x7ucV\x9jx>\�s[3p8pTH<k3A+AX'Ie4J2,Z B"׫1>6V'Za*1cpA6v$^R L RV4F!NF2(c0*lѭ$d!OgS"RV ՚#sOd%Z <n&0}waSg@G1ZIvmSL{:  F$QTn[1SvC=`>v#;N̿~ 1cyjر9bK(%6&A.X T0t<u-<i0b>vSvU_rRcҺWx[g69s gfn5lHQUí>#&Q'seNҽ0FAi8"ֆԍiJ {Xfh]O]EfI)jinlpe,xeS*27/cS>ť':0(rmtFH547dLDoG-< o6y?{[ɧq'C^OwA$hZWd>t!+\b36jT,ؾ 4u g$WF25Q0oᵖʃ 1>v!~ʕ̅9:;sCLU0j_  %jDKEϪG찑s�SG1_si.(6_cqdiVOMb֥>;(Df Dy:;zɅ4#p]1;x-iWZ]BO;{am0-cp8pl9/)b5Jk'h ȓBoB hʪ$fX=AbhUDX6- H 1RDK|! |)48ń(y<&Z2m4}mۤRڂbFk>p8x{qTLð.4a2R>{Fapլ!=)}vn"4m=]9r|xlVm"d8Alm5~O*96a}=+V�PPOOw�uuuxk>̮}tuhÓʕlcy 0Elqկ\#j{kr.Ι˵ȹ|<b>K_~CmmK }BlqC 8񓝈`{>S9zm Oa\x䛷GU鲻YMKOéK):^y-م<K_߳ a΀ZÌ/8 =Uŀq y KqdmI=A(8+ȨN^y&~{*h3KuŜ7zatDo 2}tGN,r{yţ9wonߐ׬(s⏯d9q3o֣[q_*3}0 c;OV__k2Q!GO~k/~|Ό$*T^>|-OrUcN㥶pM}9+}k)_{RT[ 3ps]6Y=u3oBzjd:i 7_[5+fpUw0!QyϘ+[1^{N搉ΗoaF~1śwzmEՁ|s҃dzp8p8im+cb lӐJR!/ȦA@:dADE6O, a li= Vͥ5!)|OTi^cl)8֮ HSIIٓ-1lm8O1a\kk0O3g1y{d|/cĉy|_t +W'JQd3H5|/5 dSΥԗd&,oS?NYv~4K s6..k/HSf͜g0V;#wCϣ?|zf<(HJD9wߑ'7Δ#2Ljӧ ;xW3́ iwQ{νP iyw!0:5:ֱrB7zZ+j>zKzL}Jigy_|km~#>glm`q\Z I l^ |7sHh{*l^?HPegnN6 qds.ᗏ& Jzܴ=O_:k~#O,ش2+Wy}߿{n|ѵuXN฽Es sWNf7s}OqǗspMܻr[Nw?}+|O|4:W3Woee2�� �IDATq, zM 5 د~\5<O}�߽N 4WNvC8v$z,Ǚm+jD]2ycc2w(JXʮ81MEsp8p85i"ecr%GbkHŚ݅mj0!KSU@M:&E}10&W#e ~I>B( KSD0H)=Yq%c-Mk8^ l,(Ż-rP$)u5U564n;ƌ  |"fѧ+2aq=i߸-<l7nSFi]}ލc<;~WR-:E2vT^d]uG'Gv>~taܸ�좾~[C-YFعj-aJt$B[wU: YbYn筪{3O?~(ݝ=ZjHW{}IQ) 0!}eK;+wSb3ޣs~S0 0܆.cVe_B!UC_Ow!"^cƾ`4a#E7^N]S=M7V]qf8S{`r<} Sm:|z ;~<n_c*ײ}STǾNus17\6[ƺ>ú}/SkK覫Q;S/k F\1d2#ϥ@~Ģ-\^p�fr?_a] we`ܛsအ֧vZw93[{5^nf?1ߞm,=\)w!kNi;@I={A?=olLބMTmwM? gp8p8[N}MVI`?o j Ql!-!\)&*Tѐ6l{^ZbCO.7"�JI*M:Hk'! |%qAaFTLx$6灰yV:Cx() D5f vc7o|e/d OWgI8hR"Wt3;NڎsN$H&,k׭gmo^̚U<3VMKRG7OViیBŪ`DMп昣�`LdsVZNdѝ+YQf/'ŚeDȲ֠ xK?/Px=k.G>҂4Qmf7-޻?g3fyߜ&;ZO~Cfa{P,!!-dJ } 0=}{kO-׭<kjt \tqgT>7F?" fyps%Opuw!tbAy? @Cҳz6wsW.?l/FΜN83okgAQ콟O㷳3"[;V%m ӭJ&4>&U�7^cgNᮟpily7.^@SVYYF:Цk]NM5ȖKzs}: 3 3G8t{Ȁ^\[rt.迟K56Rչv=D; Ǵ~1} ԋb!9v8p8ǖN4q@heGkC4Z @ؘ> [UBS]4q)" RJ01bLz U)EU&@> <1h)` ҷV H+T {}+(&<R`q QƎ]+ <ϓbëcX0bebFk`ۢ"wAfe:XM==vۋG/hXcO=#9E˚5!(lb�EJtQ"L!MxB{o8S @cS#_4Vi O>4z �NdA-K8Orn˭ܿy?˯_eQ[qHLe^ìgOvq ? Zƽ3W)=퍲IAs*o ZiTT8C뼿нB"VD@L7 /dC=.E|\9 Ro']ʊʽT79g%kY^=|�v^zVNof?Ӧo>Kw]\˚M͡*+ R)THWA Iirn vX={36K-k'\Ϟ/Q<nB+E)_CS&BYF7Ő8FCXD=oZ9/vwWN9w'Rq1O~~t}eSxFHoosk".Qhl$[$b 4}s ɑF(@l6<G&οM/¸?YIP�BŦ&2=ڳi<+RRc=~O(BRο`3c\ǘBw2eޣ㉶pp8ñsVRV[ERGKk6=<RV82-m cxO:%R(G" FEEkTg`8S_4!4*R)LFR 5RL^BH)+C&I>2�cDBk¶hY )jMm(u"ݹYO>W^BHcCĪU =F47Ҳ5kV xۙLo<)ȝFU9+4>y$˗qۍYà �rohkor]Ks0&L؞>^|qΛm@-\5lwd9n>^[GȂ>_g8Ѭ\sRFL[|b6oA#xHUhȌޛSe 'lzɯfUD?|<^DIf|A5M?RS=?vwamKHnoeMmQ;2O_։nm[6ai؝SߕWѪSO3W_kezV74zG5HH%aqgqL|f/,p&M`Aa yy`>|ꘑbc^N?z<b>UM}f‡%/9ӏ( Fz2G J|j{)C1>qnHE gNmg'm7%/0[Oم(Oʐe<NܑLTQx-U(,~cc\)ƳWp8p F8Q*/: aAJjhMEQFiHbB!Bzց+L Y fҘFvܶ]'`3{`-dByMHYOJ#fRUi2fX=o`z gxC- UJqL) u"zdmn]6M֗d2zSiT}"V_Ŭ9ze!>Xc+ ٗt qIGBsCž=wŋKQTN^9 a#V.xcn*E?h{1{?�Kʻ>~<{. kOJ //|o}GTı߹:"׹%`ڭ3XOd Twt aƞvӎB=Bie:HӂTfHdO&ڧ`dj!Lx Y<? KA�| ߸XeD@Nr{1< yo38m{-e>x9oT ^ų̍Z_ډmøn5_~ˇozҁ%0ǧ}]NkK=7Gt7ɼ|hTS/WC/bȬ^h{k-ߣR>^|xG}4zLo'Y~ՏlsύrҩWSZ`=O+w_õOnPƳ9yTY -}?(+%m-_xiR2EZ�bNN8t2@P@iwp;dj=2o}2cơqI,͌isn> ][0p8O0F#$ųR\UAkJQZ!yI,c3)$F<i,#Xת xHO$\<WO9[ն`e#uc0Tڏ" c<VJ@&ɤ$'QJ6I䦊#^xy}Q D}dlGOȢmDQ _ vJ]]c]'ԣ戃bܶըFj pZHֵ竟?(ʵtk֬%M>!-˖df/ctű|-j/Xb*{:JaD:_CdS>p8p8; 3 !}+b@ iX9@ C&؂&"HE!*II'}1[4Ø>0aVe@H(B)MX"54硔+0B6V+VKd…|7գi6xY*)J|/SUfͪqLȼdj ȴDTGH5q#9G߾#sϧѽ5TVBXQ{L9`?Z^^;՗\_JNףܙx#Ӥfp8p8cb0!V&D92 /AH[@Z[W iS#Z!YI(mFmS SH m]Xc Z+3k:0jDFŐ|DJ "hV]GOo'Hȅ17g:z^L@uC*grw؇`xLÇ߷'ۏŮ^bssFg^Cu&jeWWu*D*֣hTWGVIŖ7\+h"<Wyop8p8މ̈́t:My)߁jeY@$_PRZkqOJO"d9 1Fʲ*u1vk>@HA:# !Jcd|M}cc-:װ>Lw*J%!d&adR&A@mlPᱵOm'ġ[QAD@R$T@J<qk܄$;s{LNϷ;9q]ͭ(e#8@(譮bEHNku+~셼?HьI |>siǸgrK}q IRp )WlxР27!SB�Lzyyyy;r|VZJ34i* c(DORA%1 @<,}'vv@8f%\:R;B�V<tx`j( W#�H)RF:PBf�_;O zG*3.V4HӞeK1e]\ij8|skl0 KqaN.w0S]TJ nҗ8L[=رNǰڏy_+yyyy/~m/3*!IJE+M6%W:eI %gL4mP#t Z"PHY[]cP] `ei�iYS%^˶{>`:WbKTq^%b1ʃ[c B B <s`7ˋ <q GOrIʢDg$K 5DڧSI{prߑ#<Ty;xog<p/xxO##"Ate0l}6 >IY<<<<{HNfX^SkN-ms "9J'7lss"N.Q6cjc`q�,3% +(-ɋ,7h+$y+ Z)*q8Xs )eHӌ$ e )%CC1Vh Ŕ˜k [uyS`8,Ͽ/2~'NdEQq91ë^Ɛ9TIS7u$VimP%: `smw*x }3z^k.NY?xyyy= %g40$YIhԒ^?NYi%Ơ( V I?!3 V(LjN5%8b3\ A@#! 50sf09`R$ Z h-,(, Y^&vRFZAj( LqշOxxݏ<s9Ǐ3K[~g8_&9235“ѣ\<jY?޹jNqs! BfCQzIDl-ji~3b]|=_󓲞yyyy8&ԛ1A%RJR 0yI$jݜF 8GNJVYA?Ib[Gkӂ@Ih- PJhs(* $R c)BbAŬCX"/I̠4e 8K�!s@?p,< bXn h4<WrՓgWYzEHc'~,˨W5TbMG[6ZiVC V!Ó/~裔[W�6Z,{0~e=<<<<qK * Mau ,Š(rZ=Ě``ps9jfIHJAZ% 􃿱/Ô_OhV0 JY%DQ@H%ҡ C'Ez'J8(%^k΃$Qv,)o\ջYh c]qU4ũ z >57ORWV�ýNr=;gqwL[Y1>1#,.-#wNJe( t{//<<<zO;/%ScujDiJuX7\IeZJ 5`jF@ !am=ah9~F= gN21jĄ!HӜ<+ШLLB<7Es`#NJ * j0Ikݠv~M_M :9IQ P %AC EQt;m{y_RKl%y3(Q0_1αWr8g|FYF.y>B g37; YQ2+:&+aїټ3Y<<<Ǟ%Y4*!zJIXpQ)`<KLiG48dKa-NR̭'X=Vjeõ :Z5#Dh%( q7 89G)@)JY25$cS)HsqZ﹃]pwήNQQ @pN||ygle#Irzcad _+~q.z Bws'Z4=xIY9z6AkGmyyyyc-- 7#"ZgN(Xkqv0j,8AR pRZKH9Do$4H[WQZIP&c ANjd3f( Z�� �IDAT/Mk,A"F)$P$YIR,EJgiWJ`;`i9u0'N^JcHPi݂C䜝}.g֪oEJAZ<G0eszN:G%N#0<<<<_V:)RTcMCJ)(K k ƈA V `B*`M Z#d_JB�@c(uЁ_(i %^^RAh!+KrΚjrdbNe^Fi�1+YPJXPU>}͗) =Dr۝w}v.R%Vh ]wx >y?!ԆharF]cCL#Zg<Hq8v:[:sGes!TF>NV<<<<S9E;}88KS#:J”`! In(JkZ (-$%iaEiJĔzcf!,w3rlGRp] <m41~"wX*[ǚ95̡6[GkN/p`v-[)2'YnglF UJssuV EP`'11Fsέ8~n vm/ LKǎ}xFY�#<NY; <<<<{)ea‘R4(%@fj JI"23sHI:EcP  fd%֊~QҨLEL7#.wC&z|;z =")Xk_Xg11sct V,'%68C]}FȂ-$NW8/{I._;rsENШ(spѓ$A=Tי(2C$6S{\u?Y~o_|Hs׾JM.8y`o{Vȋ Д<x<<<<{$+ B0JT€-0' @b-(9aK3X>%pZpX EiQBP"h%93͈W8pby DAu*ZO a̮&)Ǘ:YW*#ҒZ@+)3sj9x:vTSO9!${}n9z.@󲗾?"�:2tһ"][b}a_#w >QNΝbhLv3[) 6kؤeLɿ5Q}yzyyy=@Rq"P˱֒%JjҴ 5�9AiPmNmZ \Ci%5XAZJVSjFJ;-6\e=QQJ"1W1Q $`rdKNb,(`*&V5* n\ ]Da[x:GG?!f_Reɧ>E[=o]|zNzBٷO囟Acuy<"^361I*9#G)?;XeXs6tL<<<<1%DHt0njX`�%JJikqCFbXꦃ%Y%nV YRӊZX" !B|;aЌ5k%% Y$ZRQ -@ l;nVHiYNfJ{9㵀fEsl(U*:%z.Ea1BHgnZO}>^=>bmb>y,Ξbfzgr_|3n\jK.cH}nطkKCY!�k_;;e<<<VFI r;X@B'>NR҈BJcf`tSCZX1d$_aH-F+PnFP4݌DXG5Phqְ=JSJahBP nTpTB&9Jލ+3fm\3-1WXe|oÝ7]A(M9̖Q.8+-;1kKIa%Ic;Dkq_Ͻ(B( VWL$'֚ [NY߉!Y_gA .=?7ߐ*Im3o mgcK7]̙c|Zyyyyw$뜚oS69QyX𭲇,t,E:^Y2R-ݴp)eYT�+ PJTeligEAR%puVlS,7 EJHj 뽔84.SHJCF!iaiIV:L#YIoID5ZTcM Bt[ t.'h͟'Q+zc̀X,NebI-ĵ*)55]O0R23K_Y` !Yޢu<Ńs/rm251T@֚8atlɩ j-ck5rruD>}((#W 9Vt׵ݟkF?ah4-Z yf!}FB^gsLEw#<<<<qƦm:?2vß[<`#dO1ܢ$4A$9Kr@+AY* Ҋ"kX&#fL( H#8mT C/+i'9Y^0ֈ) C^h$X naXf+!;OT€cMvNٻ}(iQ$!/,ԍX35:sy·?>.{4c4* RPW6ZҨYZ]ejbc 6:msٓؾen/OqSMR)o-ܵ?Ji#:.^v ]~)_tgiVV8DbMIݡ4+чޣDWi}üg/;~ѩOx]ɯ00e̮缊elmi}ʭ7qǯg΢yLޡyyyyGev嗞h-M=,cӣGj˒3$4rZ,憡j@lYL6P pX2R0`!(@iE5R$YI3In"ȌC 8jA�alpEuhC5=RK1VPD+Q ,,-v \zŕܳse©Yܲ> &=T+Ԅ*Oڃ-^r!r|m\x}]qY񌫮e?4+x?9v2:6ŁoIcl?s;ZXZP̮%_j, 66XXX:4 Hh}\½d7 pp-b<}1G<bb7_S0 羆'g'^ΧM#)"e/a<<<N+h{x/='e?YơZ٘8bg(c%k݂N"iVB2SIlƌcj$ JJ*P)9Za5E GVXf('Rd"SkTL4sVLInq))iVCRcfD e73WSLe{gnE(S_χ?%fg?uس'<<몫g>;R>_ '< /xsq$M;5ͷG> 8@kuWXkpqΕ@O #<|;-_%vg'o>ϭޕp3#'»/<ڎ}op8139`YoS~t8$[/||j1<<<Gw.ײg{A,#RP $:̮]1RYe()CSpԤ: ԂnVb[Ь(gEj%&TYiT"w�k +J C+-YeLV# H#!$Xb LUډUN,w1Pt$Pb,i(e~}^^] $S[ٱ}+D`[pc3F 3$*^ʁC \sXՇ$L { Ha;DA2=5z'>/\rEancط_曙$`;+%A֊(x5 Gh 1Lc-p|Susp>6;qþ,&KMP60 }<<<wYe zf# .!҆u*ݼ#"֒f\JBPX(EI/+Wb[XBa-kyHVP C5ƛ50ZXeeiXeXnV%,zzM ZQ"_2V(I$Ia*R7G(U) tzESW,:uǘ~.#EcΎ'_ITX+ ;menq Qh/-76ULP4c^r4 mo~3zSxK_LY?y>q=v7/o d%q (3J"pXѕl1+?aFko}01'b;f!yyyyxfGǸߓl .-o=R<YƗ>s~/w[f0j#),A'�hD iN#BьC'3!:Xl' ׻64+BVZcJQZXS 4,1%`Q94X#bw_gG hI;)8g rq $#Vī^c<ҋIK񛿅RD-gGLrja։S z ,xv{y}_jx͋\ q8`r| =yQ9B `OOU �-~t;J٤K`DD|Œ7I<΁CR$F+,:CHCY<<<_%h^~5OBY@(<-|xgZyjCV*kݔZ%djA/+p$sT#KYā$BEP hujZUPJcɌ#/K"dIKA( uFnQO5nN/f\pN6:)w\&^A %@q|h5BIPTHaUN;v9 [ S:qS+4&e [ΰ{6v}q}Q'']Jf 0J3$?w򶷽$M QJ!ݼFwmqr=LкmJhW. 9'Y©xム~7o‡G�5`Y?w'AUǘ[;yyyy䎏‡RY^0#gr$Wal4Cu;t5k GzL !ZIziI/ɑRa%qH'/hgjD5Ԍ!AZF#+-,:GyiiT43C5:iu-1HEBiZ݌ZYh:f$yIe(":~iwF` JvlfqqFːZ\eӢRE\IitTj F'f:nu~7k~xoQ w <Bؿ?{~(6C,}$(">p~UV n(g?3O/eW>c-;׳ GQ.xkxf87:d=<<<{D6`ii˫3uo=<Y){qŹgwin(JC-�u䥣䅡(Kf ,BHҢdbr0S:1B@73P@Jv#J݄bfJ5(C:Z'A+I E-sd=Ü?=Y"lԂR'C=vNN*{Z FGºN Cd$*ÓSMp%-Tahü?~-/]w_0/|kxՏ' d;!$$ -%J=<޿ }Kx֎ Gsy{z β'x1/z_%-c|yGyyy}4Պ@U͹o=|d$7<Yiػu5V;DZhI5z%) Kn yHz_J㜀 l2QrSN^ IaFF.Cqș5tvʒKXDZaLP-Ey2TH~ E%پ%z1<B+M/MPA-3\r6.9,n'ysǫ~'5__j~C_{wU)[ #DZڇNCzQNO~?xGfO~c{<<<<&-nx[-|,Cѥ5['Np|M"BjHQ CڹoKV)BR I.p֒c,;SN ZOlQE*d%kݔF HBF^15TAA$#ScѣvSAqygsqH<XEA1:~Ygf|ut[-YcrjoVpD,.qgk`r> ݺ0q |>NV<<<<[+J 8TH i1Ĭ1H*~Fn 񡘆HHrJ'))€TZ5` 5--Ifar�-oG!݌-#5qTCp,Yne$ETf0 8(Z ֻ9Ոe|d[9sR:[8q$FH2HSmS~=gɵn7X:x7۶[I^eb4|k/)6! ;v3)A<); <<<<<qb'i1H"ZB`db8!JcKA i@%8cm(8G^ q@?-H4XҒPKFk!pxN‘uܰwBeQ R@ jĶyi ˡ6VWdjbc<%?DkEQiDO&r۽|(2;z?P&˼=G>`dj~_8qУ~FQA((a D~;-qyyyy([n'PG?/1F;G(B+@2T .RHeIY:aHݜh!IA?/ϰ"Bh-BZ/~aYXED iaJH ØtkJG7 dHI\Ql rN.]҅9&v젛di[$>J4y]S,rqNL?:LMs1غť>}&d_c|f;8 p8@6'e=<<<<qC 0J AF TJ $α-Z(5rJ[j%( J@;Ɉ1~JYI- LeƇdyJ'%-Kj&/KN&(�� �IDAT3C1qT#I5 Aֺ)`H, dlh;~U<˹去ؾ\oz\^csɄ+ǷdѠ6WygsγN,x+^sqgsc:R jz I/AY<<<bG% "К̔Df^S :E[gZ `M@Ќ4qZ"(JKr[)))JQؒH)Հ4/]n,/A-X)j;%- :e&kkI(NQJ2GΘ-[]^dz|2Ow14z<(`obbtu kFhhE6- {CNm_t9kH0"Zh 9w:|&yyyyh%9^0lt:!0ցuLQPҚz ,3iZBh Bkٓ Nv$,:+*IfJh0}KpT ,njEiH X#4Z Jsv>s5eRU>q%8.3[oEvlۂs0$-95sK?=fE!%3eOj9!@O|/<<<< iѨEkőM%PJ f%u' %)-Y'ln0kf% X2cYOs9ǚD!dEAh%E# %`P%eiJa8D�RJz0 R}z+c|qMJt}efWrnNZq~V!~S_ezޣrL^il媫fjxZAi,sw􋾼V<<<<+y+E~R8 �q9X h刔b`M36҂^B$@Y 8ֺ)4Q B+p5&/ ډd8g2$+KV)EYT"9>$ cSġbDjYB 1=p=[uĩyڋ,.nJU_«_| ,S=Bx�LI\pM7׿ZY 11!ڶ:h!)YY}yyyyyɓx[,B@QUjK PZ91THz0լpj֒8,54JYX QZ?H!!&J Ҋ^`C)%yV`bŇzkaX-5 ︅<#+ Y9Ԫ}QBlxOCCc/uoZ3y8gv BQzsc ;`m389sÏi<8yyyy=/s/}1qBXk@%iQE@!K1ZbƐY|Oa [BcJk1&o d)J5`. 0$HcńY;>g.\zH#!NBU@ ( "* XaÎT`C# i. $ m33sߛEpsud6k ⦹daʵrb*fmʃ@M4=0[dedzz¬:\ܼAUI>N 7IfQ5 l!'-˗恬=={xBE45-FӡOb4GA;hb5e0b`c~|M׼Y+X,7׌ B!B!R'&ÃzAjFj̀ɢnz=h`Zq2etm5l\]]U BɌբ&2 G1ZpsABJV.361\txHF4Lf3F˪Ѻ\VFjV\ Bрl:U! jh0ᑸA3d'E̔,gp8<0;='N\IY .$Lٶl):g�c[npEZAsp^ΟM]Xn+cuؠ+jlݮt2B!B!jf͚ѳGw"pu5\;L?5k߻2yїp!B!B+/>~/{K_Q\EdNYEB!B!2/\Li׈+!B!B!yJjJ)+B!B!D B!B!BDB!B!BQ$(+B!B!HB!B!BQ$(+B!B!H B!B!bVh{EEQ,0 QMRSؽgdggMNNVk!B!BFUxEQPUUUQOOO`0URS Da(lǑG " �__J*:.B!B!ػ^}Ux?f Z,4MC42pNˋQ<2RV*΁۷/zz[S%J@V!B!`*o|+>>>DDDj*UHQ9JÆ J'I!B!Ġl.(z7jD⅋x{{FT!tzN>MPPW:9B!B!V2Off&:2RV* f٩ B!B!DҪ`lqb6tX-בUHUuX,\]]E^B!B!WZ5euyAYU?IebVWWJr[yaPpP)mm۟a15AWTU\2fHF6hvdqlv!H8tz!j)<u#=U05!B!Dͷ`j~Cwq!77KŮwɫmرsN\\\*|M[Km/pďLMPz.`Ť ȞjiSV~[sjZͧ y4n+9e̻`.y]-ᏳVo*+N;ϮܙO{RʚB!Vq6 :+hZQłf֎=p�IIIDGG3xPR FᅬԾRRR.1fXݽ^999f<<<ʴݕNwMiz.Ǜ?eGj] &eLԙ[a پobvϡYW٢Q$(%%sEQoTu?v6u "`;5UܴE||<"~v Ff&n*I_?-!4j8_YqwqGg6i*}ļms-ŀ׹ (\tʾWJQ=eCtkaYB!Bt@GcNY ۼVAZ7RÌ{A>h6)O]΂ ?~|Zr%͚5'<"H&NDvv6�?Z/za>5sfo_jK ʟ/6mׯ͛0GHHH߅ }HBZA7ș3gxW%''<9J7@nݹa?y$>|'NK, 'w2o{.Vg~\S\]bgB* v�XfwNkZ{m-ώ1Ly,J?1+{Xr4Z� gfƿq5͔!&s^̔\߅AMp3`FQ56s [ ׭fs\ʚB!V() `t*/@yy_,Ƶ6ܧ֌MJJϏ,at/f'iڴu= 0iD6l?رci޼o_}5ݺu%**pQmt7m_|+qy@@�/gΜ=r_~?̲e˸5믿ꫯ{:<tsGEY39inH#05H/N.aCBlV__|)¸>[lɂFσ˶-v9e˧ڽz8-nf\ [s:z}ᑅF%q`|iXu~{S돹+<8i4st[gnJ[x9FIL:q+%?eK6[)|q̛>#6nqEo'9?MQD$f3sv`>b4w<ʗțƄlsf;?Dz"9?Z.bzJ(auΣ~)3Gټm ?\=~uabi'MY]< ֱ4X~6 F),͍:73QsH%Sx=D^vs/tSplKpWvyYr̈[LTC}GMal drT>߱} 4j9Oh2X)GYB!B',+  HXNDsrRDgFnذXp=zгgO{)X5>(Cٻo/;vtzۙoCHIHHyiʑ#G/cǎ/J-xroڶmEA7<**/l , ..___-[ƸqxXtڵc:Jw޽Jt9HQ}zlLXIP4}ꌠs/mS9='7i:\c ީ?n%mQc6WӯpxS|j CcW*p  ,{=Lq+/l;Cxp\LYMBD][eRF(#P�x .o߳Pd4[i,K2aB\J@G`nX߂k�x<-bid\j+n0eþ WvŘw>|uvb s\Σ=v ְ68q$\ xAG.-,A�`<8tvoƛT]d\5KS�M.L[E9)7Mf`:zZCKoȇޝxehΔ˙-4} \8> ZnR>^ z2.a l˱ y6nX[{<_?]a.DS425!B!z9?ofeD։ 1$/uKu*uX~=+f{I=*ݶmb�Ѳe0~< ht㺞=Yh[޽zq$&&2~CKoF<N'GҥKy'瞻ƨ`vރm.a^]WJKAY{AY]ۍUpPڶgw:9Χ` /TݓY'JzstDGݼPKض8o,s&qoz(@:f??ƍ1� ]hzz ?z&Qrd8mb�Z٨CEbl@_󂀑f71߂ރkGvz3Gh`Mob,`P 7]B8xt7ͺ.fYC#6)d#7r3SX)%Pyw- >=ڽF`Zp7cq?-y4v-1sP ǿc^ ry~WZtGOwͫX, GSXg7ڲ%l_9+WV?!J7~t[=0S ܿ쳤h4 (߳2ǧ eM!B!Q͌ɜs&&K-rflΝyz4={dԩ}/}ZkGʾtҹR' ,X09s믿oO?xB6k%]}޿M&:)ǔd2W5::*O=ų=GPPիj!'o^[WWG\Ɣ0�NT0uRt96fʢG9KΤǤ5WѾw" zcSI14'H,8JB�m[,lj.}aX<˶Q u hcMa1clS\ )Ү!-:4=;Fֶ'y-+n`dY8o}0'yp A^X ox9A&sfE2Wy˂7܆mUkq;9nEpj Ç$XS<3z%%o)?:{ $9ʉ]@j܉v"SN/nVZP61>-9Zn5pt9NeM!B!f rٲH_ SQϧ1KJBWΝ6u*h+VlSLPDlewg?v,'OۂߗA>}pwwg <�ذq� 6???֯/tۿ?4GOKŗ_:Lߏ?@-hXҪU+†8L7@dD-_NNNm+5]ѥkQ꽅q~D4`_wy8{tfAEAǶg&1a.Z21s'U f5غo[DIs?\IPлWNlظ z5!S͂=z]|*9REXέ{>g޹lMIW;߬y4&  ^]2jT]|HR E j$gkxxh٘,}ΜJ^%S`.FCN(\_ӄC~)<}AޖvUtXjӹ`͛H XKJ-Jo;!3W w섿.6KqCisf/~.qщ.CYB!Bml#UfZsN^f�E0t4}AYfNFFSң{RQxHPI#G^ǏGh٢gO4M#"<EQ1<ԏGgN�2d0|-;O/O-ZL޽qwwj-h,z?*SN ٹk'C M6�tЁ3^#)) ʧ~gy:_z V4qS^ q0ݻucܹӵ|% Xs�nu^|#<{H�JfI_@/_Гsqnei B^H3ի4&ԸLhTSϳ/�;!!˔ZU898o}%VqНM?49fX}BG<;S״ى&9?(ۋ,+H=ۦ8Ź  W9s+z?}[?~ig|ӧQ:Daש8rB;m4ƅd4WvmvsRGmhx@guSx#CFsW\s }?oQ)e48_քB!Zp{iLgþ(ğ|Y�;ubSO݉lAl9XFe?S~:?xxxȄ 0<̚5iO?Ncaw?�OO{TϟOvvZٳqu,^>/O�� �IDATӒ%XVtWb5kʔ)>">}w{Hzj =h9sb1 8h?>~CCC4qbػw>͛?˩tteqsp+.N>YqMI ZMK[ H"Ҙ9@ mJ?.fSR 1i}�<ӌn:`' ePWyi|,=I=r4VRiGbI]t $]UƁ.S4{JxV`8u-_aYܓ4Q-GgG-[AqCLWyBD6Ľ11CQ;9^h[8MàG,Xڕ^_0"JgΣb}M੡[Ҷ/u 7Ƕmw3Cʠz qh<mtiǑhwN?.ܭ$Z)4UAÔ3xX8puk{ W@!Lyۿ^Vx9m lM[Ɵḡcα94}{eST !B!D pKˉ�EQ֠,؂e6-DeIjtP`Р 4ɄbESyT^x9\\\lI&Lx &)) ///U5xx{L,:Ϗl,  UUIMI.&K6_R/4K^ť \2mTMZv[Q{Y~ziii}]Nimz}P0Hc?H<Ӄn`vf+m1[fLڅy�ɻH46'MEQ8q~1[]J֏lw:H3|YޕEDH4Dݒ(h3tSXkWAUut!WOeʡ(SubOjF*Y8N7Wa\z<;Щˏ k>1JPȽL]@_r+'pnnKf"Ǣe MoP$ΜGJ^(e.!c0ҰR^4>Ϸ_`DrU/|=:0,Q{{ik&&ݞy9΄%:cY /(N8Y_Oy0> "FdΣ<-ϷO}IXT<`Ŧ]uj"& ތ \,˖PքB!jl{u[]UPѬVVkޱJ~QIMIîBG<<Xx1}-2Y c ,S"Vi!�]2_ҼݾW0^?=y<ʷ"Q8&B!nA&UEQPUUձz:vh_dga2U`0`X5<@�]s22NZmeԱY,?DZ"ytSK9=e#m~ta3Ǎø>GQ%5!B!4)77i{仛UH4 f) B_g@ omA%,9Y"4p0c@/]- &Z{bXbTρ! >aA-,yQrYB!Bq +hfY_d!hܸ1AAA !B!B `϶w(N#33Ӭz@jkӓ*%F!B!B\ 1xJSquuEQΓ Bf%88m۶ӨQ#\]]dĬB!B!(4FU)4;A^0VUT iU, QV+zj ŅJV!B!h^>bYV+LBBgΜ!$$:uydNY!(.dds|"/^$-- MӰZE)B!B!+}uBHH]<<<tjPPaK+dB!B!\FzzRҜ-D/XVVNB!B!Dr�@%l+B!B!B!B!Bj$AY!B!B!FB!B!Bj?N<B1W:B!B!oӾӕN׼~){QTS#B!B!f+�!j{*rE|Tk9WHv^Ֆ[[Y\MwMɇBSVkiW: 9WHv^Ֆ[[Y\MwMɇB q-\"eKAzV[omgq5%5%B!� qMn\"eKAzV[omgq5%5%B!ldNY!XU=f( cLNs%-!j5[m%Ք|ה|!QEF qMN\"eKAzV[omgq5%5%B!2M6lw�4 }:ٷ>n2V&;OΕ*Rl֖|WS]S!ƩHLx31`xlz&IfȴێN:UOKc/ֵ߱?cDMfr+QUl Q;H]j-,仦C!Mlܓw7"cV |>cGf:]&6I4W--.`i4/s޵t$̛r"JW]e˅_SLZ֯ξ?0gqk=u[~^ݛW:AզG!DrMe{+Ɔֳdڴ ɷkѱ}$NɫocҐ<Jҳrpxޓ2l`zco1W0gB͹[;Vh>?kxM=rp:ʐ5ex]W*\dOѥB;X["jk>"욹v)k ۛQitU^<K~E{=r�Ii(NlReO! y+q&MB1DGGitk/'͚9._GFwZfNZ?O%v\[^A&DJ)M=[+/cEgN( ZvCb( #ƫ PԩF@/"bpnt,jeK;Sv~iT3DKf;ud-Y4ՅKZ`ݛx3OkbH-3y{T%Os%raY8p:,F&Aǽ*~}3X=|=O_j˜Tz>| əh kԖoCʾwU0Uc 4ٛ'hJ BP<@QЬb'{emC٪'Mho$wo&o+!Durݰ^GHZ6!~}PUH}ſflض頬pS|3)tiNw^zgɏA÷~<(ww D3̔Osb6W(1OR||G$7xv ,Z͞3Y"55m;lںwwm"gRxe2{oF"OU( hZ)JnP놯5Yt>ߜA.ul?RO�Wr+-"xrc^ΐjSz*ʡC_~8j 掩T(GR.٩sR.42ְ5wv (w\{۽Vd ܀;zFVvQ{9wp|{ȋ2vT(OdOz6z4yyUȹ[_ٶ="/Ri&RB3ml<Y;̦_syen SKhYNJ"IA qPL^tϲC7G⩥qndk`;TeO!(c;gxkfE/:-0IIU1s GP%?DZ';_>:Ezv:ˈ0&}tΌf|8*UKeŔ:⧥_\~3_%Lo а*p B]Tv-͗/ߗ1"L7S*Ϻ4j6#5c\I?6$`ίxlTϺ4~;F_Gxh9 G=ʰy�z!3ZqX = ?_r61l Zp㸣cPZe/w& (z{:Uhr+ZҾ'~ğcE&/NoMgD[[T:ldb.a-=b4#@Kfw(gSTkz[;^J;b-F՗^-zŏK@uݗ\hl]/1Thm3I'߿Y:]V:>n^'0NOeoBz`sfbw9QJr`^etX(vZSDu'I?.f3;R=ҰIc|y+Ffbv6qSU.)]7IJͅ?oR2]hsqΨQ9rs;,jiϼˆ. ke-V[GIMhz@!3+v?C{{c= u¥}YV pcpά[Ŗ}Hŗ.3~7szc* !Dq`5pu5`0Pu*JcN`0`p5w#5- 9郫!C<8gp@H>6}/:AxxP *BY G-v<My}> =c6tkߊ20}Խ#ה"S- }h(#f!.[H._sCH1ݠ7#CA`#^%4oiz&PTQ(b?-wr6h=ђDsw}%#_yv/[ᒾ-`L* ʖ\).Ftk2&?7ƆY9 |}&3_dH# _ S8byio1ɉ]q$q`"̘FoXגAiǕySR;Yl -u kYE0C fٚօ^gֳV?1shf e` <O?C!fQԺ;ky₭Ku(ZuMEU-t?~L܎['%}w2S}(~Yc36q?WƝf+[;`TIeV;ҒEC.jNCqbgd1o>|8r$\/>潐&9"<TJˊB\eGs\Fl6Y5PjfNLJch^N1fw_~嵱_<x2/?֋8Éwo{[Y_J oW9/Xcsupg_m6w(^ad4$(+&eXk,Riv*C=T- ]#VjA| 9b@է.H[K:kH3ڶjmC؏ٲ#!~(Y[ zw4oޠp/#'ϕaX0[2I>s c)enfɯhrGh\l1xQ~\r3ixC[ۢ OwiVp mF-->.#/Ҏ+#:Q\.4R6a'-yO eFOBVmLG??XyJ:jK!,-w2,/yаEkFE#{Y|=rޔ Q*u]K9T pT�Ky}y]:* *ؖWuud`lGELtӼm6miG1xY̍,__{يdPXy' GO'\ ^XQXUӒ G85^e/}%1b99;X3"-{}I۲YI5lUyeeE!]ZGxN}Bؾ3#^zF:G%.. !hXThzpn_":ZP M۲pF=S <p,.i}q*xy8+աق2G8ynj)ufĴ̜۲* <p3њ%QT<CT4> /b4~q\?G^7,s4O`g{bp"p8˛ؖ WŋVQ� ҘY!uh6 H{Z++J BKbݨ'λ֛~1 | >NƝR5+Y񛥮 o^n}�ݛXY7xԺnVT_wy&#ߘBeGvw$*ږ~KO*ESv?/4rsd/jӵL^rta,o/-ʀ,pqM冁w4YQD;RB;tIyﳮu(iVҁb X:Jxz#{!ĵaP1ǵԱn7ѳg X+V&Sfeq @rtkG7N^@ؐhCSwHK'>g^Zt R\N Q԰DwvM-+ĵLV_YLYӸ:zb)o1M pIgCS C#5vŀo ny`I^3�hÉzv\'Թ2 Fqcmş:+XuFnIυmVuĒihk53M[7<K:SR(O=PŕaeӑcdR$fI'nI-+2jX7M$ 5Ew| XFR7]Vc>|8& J�u+vmnPU*ҿ!MEHt~ŕ>G#^YK~Ιm*=Ȭ0(S$ګ!mHc]ȁL@/ja㑍 +/<Mh ջԃ絅4n׌�8͎_-Cyp͑<:Eqp7'q━7wnd4|s9>.9HPX:mBpI{k(rG͟W3ќx3,7AXqh�K[bp̌ WN>񧰴/N+c� jH 9N`族bqi@GwܪA v<!7R߭=GBQ'ͪ9w\qEU@Yu|Bu5eRk]< w4:)kI#t2�AE_<GF_itGBTRk =rr5#\X+VEU-\?b3,+Rt,o/oGU (Hl>shz\]u(f1(Fڡ]Xr1?j%CW}r"aP{|ʽ<\V\|rDQT2sML>MBIB.[8~>[q\U,h1KHX-2;n&o|? Ұ{+v%4z$O?qwŔinxѨO�WKčرol>_!~QQcn�� �IDATӻ q*GS: mc3KSƇ'LY+' oR俁GBn,^b4vI漾)ՙ{340/vkvɯ49S<;0t`,}.qCNu ށaCyj[q'8e1s6#sg_AW.o6@y{G9{[ʎګs-+P.ُ֯.4a&>w[tғ(nu. [c@Z2'5˥HjVj]wk=;7KӺx&c,o=rF}NZ)oǫPelDЊ_WI9Okj"#4/h@W[9*1]?[WTCi9߾ A۠k4Т[/voX;iд-=1c4ZjZ|~;_c3mP`<lN'>5zg+=[Vd�WjPlٵMX� A=k/!|UrCiӈo]F3~n`TڎJt#z$8ζ (qYڌ%m-xd G®oRC+e5r2=N{"-Hâsǟ~4#wfϓcэkl"(HVp>3j3<z(h+[yUQzaޟsx ,_B&{=Q#Y×Ccƣ^ =6^'o>k۞uu6KOeؘ.cetߠǸ>b8f'?#K9ne-QkK UIueL˅:mgAe Đ6B+�#l:Iu?MF-o6#˩ݖq3fx"wLNwдrԣny/mߕ{Njg #s\%W`t_WINJؿsT k/̘ͳ!Q10nRb,C�%bh-UƝWWi>|I=_$co)HGi5 ~4}%` Kv:չ|3h"X/Nä "gK2K,//ch/P!6VIw+#'$$,&v=;s Q,_ Mл*9Nı#E8^QQP(�*rY'6JllW>tl�2};s_+|J\(h./z<gV]DtM jtٺH+sɥe)VN,x2h䳞_bsp|ImL/祵ַM[׋sxq=r̾O(smret;\z.W^2 :舺lQZ)14- :+%`%� @&\łb:nRo*^~MyֲeE!R:ιz~Xﺃ3O^YB<;#Ɗ|^zǥnJ_ʩMo % v>ͺ<<"窬9FpMdթ,5t~]:X˅8ǷhaIt:ݥmSJ?gBTJήS{n/~B$g>PP(1-([ Q_x8  X@B*lEt>[z<۔3!zUZP &6] !:Z6o`ɪÜM/;2;ίjΕf\ertO!*jb[ "W@MwMɇBJ !57Fq/E?UsPaXUqՔ-;t w9!*HjPvU\j']jJkJ>BHPVkٵջR\(檿B*Rv\ߪ']-n5%5%B!{{z!PB I Q@TDl?Q("(Ri{ �!!$ -!<;g̙9{fv�j  Е}K 9~csR(Q!b@Ps7BWB-@Ҿ7K=sF@ <pGJP\%[Yfg~nz( v Ŏ^_|fiZ#!t%(.Dn,{3?7Jozf4kkV.rBի @ @ ZE, L@ @ kq@ @ @ \ADPV @ @  "(+@ @ W@ @ + 铘UڒDغ@  8H1;y",&㵂нAÛrxE  R|"rP~A�Ɗ1Y9)2]U »5G0A l]  )]6K\VXf㵂c{6&.g将G|won(7B\d<3G&Lgt*jF=q_ڵo Ea ߃p7D}HǙ`a3D~3U˓T1^Gu_=. L'Lw>B<QE:oY .r`|m_$;Rc}/ͧ%JH_"N(<u9fC=y5,O)WC�f~~ԡ3qHtL}ƟBmX} 1k,Ci,b=NJ-(ʁuVy$[]mw_Q<6`7pPryL}t]f͗ςgXE6@uYOـs\Z\HHU&ț^'k榋J U!b5[IsUO٣6GW2'P1wOK/㹩!o a#pD<Vd) eMŝQc?9x^ϏT3a\#󛷸o/DMi>yuHux|8;}uR;op#q U pkJ>u<M8_..C"kBe/\Q]n{NM6斪WB @Hwq'o>wJʁ+< U#ծ# ҡP!z%%'YcO(*Rt9h*\$Ga'_vI%`6dYB  (9m N, xu0}'?-9QM1ދdOWt↰u V,=G^3е{np=׾X.G-H wܷ3ð.ޅvͶ%T>Bz$_Q\!EEN9+d rtU-z`y җqZ Hzp;$g`De0wVF93P<wzXİO\s!AY;l-14!r*g^7*>?㵿torBc8y*ϩ=I1>>5crr}=@|`#ڴFg."2pJYd/b( 5EP*>Rnv(u&!150zо5{gF�.<ڮooݒz+[PWLŹxQڗ:$l񥠨G%Bu992 ql+2i/+\rC(QJG`�>f {wMqtWC&MJ^ צ9 -rwHH5nEg#nn&(OBh!ˇrW )p3-elcnP 9:IBY&KNx>{;V\@YBj4G3;w.]]h{b by&#<19DB;w?]˧0l.Ҁvr3h:u@d'�7ʼ^Ye_wѐ}r&^r>M'Q3"T<hgta!o479k2�`n}t5e(r5.F"5sV͐}ן`zݢ [4;_\ rd6ԔOƾnWy3t2 8co -h w T>r#툾byd2PM6k3 g@9cjLcšFZd<ցJc6m@MWCQq;r1qm4%lD w3y#u#Jcs?qѽ]91^LAhQ(y*&pHͷ+JGɴ^o燻mhZZ*E^TsuasKGP)b%$+݃lm�@Bn,:98CK;W\ǷoeJvP3Ql}Nry?جrptMx|H50ʚXW&#o>..SOAA#|َڅN>Ni+cHDy0uΞz<IΊL?}ޛC<mW} }b&8f7I(NPjxjUYg ^=b"wX c\ ~2l<]77QGp,NJpB5~ Sbr醞ɠXT] {1_y~5˳ A2yֆv̉h !p/;;(W$]k5pUA*{_&$s/85#g6kYAr Jɭh QN]H$(;}ö^&WpS8U@{v8Gȉ=0?4 Yzs ǺgO1\=Skuzvbjm1c Jvrecޞ2XpB;F^: SZRb&Kh1t1<яu{uNFt#_c;!k ^CоrawOQ!"W|'3<;5׿?a[z :a,^|(@CnB c/[-l8lw ¹܌}#Եo-eOqCɫLMalgb}7!OBȱ=\$=RxeZ";v<r.姟˯CE>'04Γ&ch;)„ ׿Huo5(;ajBټEmEEA7^;F#KR)4WÐYl9t2V_ry5c#_�2=7YеAh(+6\=/`?)AA_ [ :kE@2ȤmE<oK ʒmJϭW:"׿mE?3>'gGΞچz)Y 1zT7QՈK޿lLXbPvRh9j֭GEJ_1tJ#v> {;MvV|׷wf=Gbnֱj$=H<VI ׿.c 'sc}y}L�.΁Lr$},ܷT͌AMrW)&?N�qCV8}<g`oFT[<,v5o1S#PWMVlF׃ˤYQ6LaOȝ",j@Qƶpvn�Z Կ }5y^y8a eq/[|@ /3C-9F;,!q4׿\I++qQ +s$bQ>- pWjV^ m-ΝC^P%gzbj]u�sW@wE~CHm[O -8J E >."4Uq7SWDcVmB݅$xWh XD>)[.+*vKߎk_nي2K;wzc_u22e{vX():t5˜X 2/;Q/ 2vNlC163E34ؿgb[, `3~t )DSx�<n4Ҏ$lmpta]?$)\ b:g*x$ywG~}$`0H+` ՎL:awt|0@$"#^IS3p+B'`K&ǭhZ|W2YcFT<LP;<_!w'|<%K/*:\ Zv<?`Q,1g2T؎ };ХGqJyE/9N@,N l_9k` WZpG,ϊ j L=-#<`nGМNpmT?{A@׾ TЮ: ǀ緥z٣(iyv Qq ^6RE?'>Wdx!4 T T8NS\}ʗ(8r8~`8( *\xFe{ԑwƍR{8z-ag돪$V76l!lˀ}S^eY43jI[1_&Ub,ZɁ؇rS8b!myMGnxd$,q ib1}9ݔ_b,=_vgㄥrd΢A< <S~up<gmuy\"*!%tX0 ~t9W\wҭE z=1md $-Mg@:l,9Gu: yuEgޛnm5]Ͷ݁G0 eG]X$q5Йp' JR2SH!^𣏼ʔB,:4:kR+ѷiM\gt${cO+,}&7ε<X+kq5Йp'^ݴS;3c_u*QɈ{"=wQGP6_uΜD2r  hVԳ6(^px΋h2ul{�=.zKNke+ѯ<.֋- # ?s[މKjNxwլX,>2aJeh!%ոS0~:z#%qM{7ؖ|XdgdϮ!%kt5?Р&C[.)r;! 3DH/*xy;Q<_. cyŒܶاO!3 ٲ-渂r#fW ,={.Z}dAA뱀v$ZN1+wl]>P9N_8.(Ӽmg ?>Uڎfǜ(U]Y@U+rmE҅:MKSµ3c[{ h{Ve,d=؉'a+GjM**EVYZf{)c<N5ģ|{sE+4UVT<S9!ϱ ً<3~㐁Uvz51L-PzըV7;-F;W>l) yIYZE0В_*G]XuNK6M.Tw{F\|.\0hٸ7D{98+7Fg߀HcOl}6C2<�� �IDATncţ9祖') Z p󘻔B.Ǵmhhv> ν%><0Ɲcˮq^8[nx^;;w_Z6?c?Oi`;[K -�V!$?˒yup z} ePmSPE\FAa>b-g<8'jH !;qڃCcUd=G~i䗿m @5Sa3ϩt*PD+5FѭRO?5^JR͎38N'OdONECBrP=c݄:gʙz,ܧ+–,ysK/�͎zdYCwВ/HHj6ZG9RLY r,1џe) c\!룠eBӝU |R>Б\9!T#^/Q r(LІj>b͂4k AW"ӳkVuz: 6SαD5{1r`;ًN9US8_:ABAHDs75UލYq,'ûcaoVfB (Glupt[tnѫ.]X/`N܄hZ&egS# UCA݄:Zq5.cZC:;ҠVi8];JUCa_3`q{c'̏04V6XUP7cc <OCqtGW2$\"Uf:ɜBZ׃Gp>Pf/DZQڴB0 i  AY5-GB*$%kv俰'hoaZ7HGqEKȣ+J�&T NLOǾꔾdAI*EF?EQ_{@=Y=kh{PO,/> sWZX'DB;pIZJa;>ޒk& k�?ϕ6bm.O=Q!c\-H&nlwu3h(Ea>cXrFuġbM$鰧bA; D}GbY3pYSxXz@<s\hgRBc3øD> o(fޏꆮRyH>@Ds3d)1ȯ\G?]Ht+9OGL]gܳVP3T(n_6g^ ~tbWՋ[;W<XM1M­v(J'v J)UjԼLYT=m/j:βW|pޒw_Z,]t/zua[9&f<]OwяLt` 6~eәv߻|>% ().,jK¾ ZT3=`y^yI@r.ǹp1ZTcM"yQ߆a?b@>M\c6?ntd*�({P`*C8R{kpOhؾyԁ\ẢN\ 0(hdeΤ)$9}=݅(+֝?GspHt[,y8L/cbCM=&E+ h./ ǪÄym*`Erlu("y$j]17 Ý@ s  <mO>Ä:PT(X5ke@~(&F\Bap+R\iBG4CbAWJnv j0;0}!l~t=n{݉{g(\FtA|XʡK,׿ Ce ^Tw0a=%l{\{KxBXjyXmϭmecZW[ʡTM2Ax9uXɎ{2x⯟˯7'Q6dCui`?d\㽏aic ]a0ı1 J(#Zt1vvl?MDF\zQ>kGt)^E` ٿ@$6ZJض+%;$J1%alq:"lUO\9 -P6S} )}sʶXJ2&WFj m0:+lu/1ȟ\ͧQ šskD0o߉mw1ZW)~l8E\oP\3iY=cէ\ IRj{hZsF:sPhӻ _@ڢᅮʹQ]TLcղز! ?@UKH&&ιhW%ClJ[׼f4gIo, ׮ET]ql>u2wb<"$-^y<y6\v�}y߰͌iBF vS(=k<2guo۾!w/=@SRLb rgPm>|qV0@hV űA9g1=ʏq%m~?$vY}<?i](QCl!cj2gR7JjqX]F!i9O/zq:VS=MH07X沠k!7K$s~,x듘>M+(kT٧Z>u4zpֹ?qh"WFWތ/='kjw[ N[/,]滺:$Ɇ!=PK iywv+V+!OwŎu ؿHSz@} ۱> !@}R6ʢq8Gp!t͍f=Ǵ_pn}KşKHQQWCMqR{)LL [th9)(I?  OzQOz$W A*c hɿc]3nuIH] -m7#^S _92r {`~gp&VsZ$4TE=+_�41}t\pW,~Sz,ȗwa>nWXy G щbU O(>b'%M l hV af)Ɋ T8kױn: ?>F^OxywswU#`WF2H @!iS<3:CwƜS?O)VZ=?$I]9g)Y=Ծ}hf jL׳YC6OܓZt uI;'<K_4~]'ĝc&nڒi^RR|6mBPg4kkV.%_\rLϏŰ%ryL}'`:Y37]mi7 @p)RILƜ9WC@O)Nv&P)r PT϶`&30ɌLΜCc.[09!?g쳸f¢JRC :Jir6P|lτF3xg<).ȣ¸WWL6)ߠ}yf E~9_(tzĥ'Ͽ2X&N)*y*M t<hFtMdYu͑-@ (r @ >@(MݱYhU͂ݩ7thP!HzLh8PJ.\3b1*%gNu_Q\SlDq3@غ@ ;eoL$L@Aٝ>!g8zO+Tj5|?Tp:@]]pZBe@ @ SRqsKOc5"u/Ć@ @ @pA@ @ @ {W@ @ @ ,:@ "@ @ ^*;e@ @  "@ @ @pAY@ @ @ @ @ @ \ADPV Aw|5oJqj{c/v}榸_peQf׼o ՖE \hYkN҅qc!|CKpܤ~ 7㜹C7U"C;ֹS1&3YGZU\%'Q+8+:ooԧf'u*&eq)v;.F 6͞ʼmá@ kؙf-`k3'tѯwa_1uͤwqWⴗ>~Dvqߠ8\A1?j_mAquKiMbbcȎu8 ]{F6Lj|%Bo9o݊!25r_X:b޴;/Le1$ܨ}SѶ˿+PB*p9y5ރcɸv T\>1clkF+D9ʹ3szvHC&D<5⎮11�9m9F}9. ,IĦqԉ;�g6~Š?sO1 \o~͊]'pKШ3Oq:@ew茘 2hl;o :Rͻ R?˵8~Yt-ʷSвLLcd(M<oWo/Ϥqp3GꈩҜ.ϾMJxۺ}y]c{ޛ?v2{k_3?j0oqyS.M_*:eJ1M#р{<үz4e˩/RZ Gܨ)ʩJ-9`Ս,Qޝ BDxoNp{]U_ZaxY4 MzR}LkTқzt{ʛNL:P#M%'9Ʊ% "eCik+5z26D/HB]P1>dyTG} Fckz"*pq-"]Ֆ#hTN,?h"3dڒy[.ЧrmɈƳԜ<ǃ5+MIfӲ9L|i|jB%]LQ2wgd6D(V2Sⷩ|:h_гb$B2yF6}9ӷ`Уѧfygd }R63{ˇz  uypYO_śjՖp-ש-1bxkfbvbh(яz7W-՟uxձ4aca'2ՊU.Ow5>�9bE{oO6[�9?J h.QJԈ*W9q}9hQ1bE%+Ճl3N;Gb9[QZP`}S-k _.Ø9)9z:^Q%; *=xD*62Sظp6c_O~v5i/im>LHxC Az@2{tЃ_nOj%.27ɐ#tu :"(+KEIN"0*1+u$&S% )5ֻt9\), >VK$ .#[DTv+H='uIxX_h_ Gpչz}KT#ϑ;Vt<*ɠqx&\tJpyYܥ+dN~~<M5߈ϓ)q[)} ð_rco*k7 on@J&9>ig1s")6h(w% eݱNs TR($M~v #*_n-&2q,)7*]Kx$5zo7'g|Cv QQ _6bfLxrԬ]3_տ 6vo*[:YRP_>ڱg]*:ݻWO[Uq5ҭsE.Y$mg{#J!mºG?;`,Y6 4~hg_=Պ> |{D3E=/ \/|#zùhBk7{+(%[(Y*K.4<Q}{3t>Rն]MMB$ <g`ǩݢ<|K¸g48yS_N굧txU2Я'an=C6TLF2 *=SoR UOGn 1$4hHC[d c}[|"/U]YWX8mn*W78*UO b$R^%,5떽 e|8?\-^!m|8]8w3P`}S鎦T./SyuLΐE +Oy]4]qbM~oˍr'U>M0lh Fcwd}sdb~Œ&K)<uxtڠ)3{srGtr|!)m[?6WB  S;WqsX48Es=oވ2!BY^k$1:@ᎢZcIw Mhv2ӡb+'XEEUs+咄,˹lO Ṛݷ6r 3dq"ջ7UE>S8eRI!֋Y<koע6JbEpovi 8`4xp¾ @V-[6sLoX%&û#nl.`]e4oHg2k[O7z~ewJ>З[I? a4zy74Lty|E; FaD=d{Wf_/�:*?w##a-. aS<Ɛ)#blV1HA_&ؕO D8>MFl;4i^ﳁ'~[p۩dZztM,Υ�ڱ}xy{p},3i,_>Jh1,_+_l L_rNo>{7RoЯx1ir賎qR P}ݰ(GXƸJϟ'_L8\62:@No\]A[PA5+f"#.y]T5?9 E"ҵL~Iĉ"z_rR+#纕x8*&;sP_y Sӡd=Hs1*H}-zMO�c} 嫧Xk;t  $obM%�2x­u߇bKw>z.J8MG@x|#Ncm\O{GQ/0~`yѭ4ne_{ wUQ^eLGA> kRxaF Bm\!}  ͩ+r&gNL$2Mдan�ynAݻ Ԭua0)]A9ʞ* k_<vႡ!/On%e6z}˛$xVT$c|R\ C81x4nxtVU"=y^J;=+{ja:(4'!乡h_nҰ#Y&^"+ɬ\sR-[RUd`oGTuCjWUصM]B+AT.nvհm~ʪt/s)pH澺v$C�� �IDAT מPҪI +eLy{~j^RoNhFsBժL֚޾;Xl@̻o] ]yMM3z\*K?\̲)T܅cL; }%a(b"dʶiGI3ٰ_YK?vjC"t_~;ƲhҨ>SݱEOiYZUZ6m#^l &=xk&u 9ы仟w1fQQVCrH1Q9: ߞ^1KC>^׊|Ϊ2ڞcQ;|::KPp Uhx%G�e`9H&!\rG$S&,0?}\6>㮄%=Rr~u۹ q"/}:%Q `676v|?V㙯 l s'8rYS37oH\g6+fO 6:t,:r*[4`ns_A]]D*%$\cJf3m̮)[V CPAYg^u2S'�Е(IH6Dt}cB"K Lң}y0E&/?O:mNSAB`;$֯{uf/FlcPJ:G8a=z)^fB^c?P!x%b5^$߬^+$@f[RDs75UލYq,'H:8yO:#[tT8Gx#akF&:OT6<$ɥx_K5%ҥԨW\) p,.j. LA2/RPdoN %Rf`w GӌTJ(lX*mSçI8VV#kavD<F_K+}v|K$$NѠ4 c,57&.NV$qB}Zѫ.]X/#v#^ȄR0jyޔ,�0x:^#}3x/i3o |C$wgĨq<}ϧ�ub#zkXO!YV RRxZƦ/Ì<;Ǵ?c+v"~Jyl۞,:>7Y[{+%47Ni42nAY539{ =๙'ؚ7լӓs9;S5}!VѲG= o/޸wG.1<vL_2[<ZMbECl͏y%X*@ j.') 'g"6&}b<u:$8a;PzHkW4+'~ ~,&0AeX*Ԉ/0Y<q<|5S%4URH)Ԩl%IMC 8Xj}ms{<h7h;u0yWoI4%,濴.4XT=44)6zy }D)siв@S5/r?m?Ďg3(񺯦iWC3x8o{W!p_NnUAt}9:C9pH?q 󊨤%$h)A A*ԬWnC݋鍂ڱ'3:n%\=T<9*MxGU5$$)>bDl?Wƾ8iZ+壑oVfGt7]U(yϓLЛʲF2zS^| ̔S̱ʑ,%TץQl lF=G{q)pL?S+ ~P @_·u5Fѣ,2]l^3>%_ta%NXLl}V4SįR_Wic"|@ήѳ{{p%l�sgSh+wWFKy30oqk9 KWZkfե[0m{y@!Y4<_]B}boF @rF,, j ֞.C M-CVМN=i/qݺc}( eX-}( ShJtun{ *B f'u*&eB5LqGJU)i@I#yia8m,1}7V`(e#qa{W*e+_3l^{J qc*6MG-o%,lHթgOSd$f[MC.N*r$rH>Mx_E_Yj̟ h<Mbh5=>V=gucrqw5^�?ϽY2$Y2Dg"E]ZJkKQlU͠JI%ͽ I0zy399suCSO6޸ڼ s֙E06 m(YEȅdR$_1p$<Dtf-/g$=%:NqD<} xRzv D4```O<VXam#}}Xr(cה㗲gqBwoXe\+Vb VI'/,ka ty%çc&՗Xֻ=}y RU s[{(/jQ4Z|J-_}|[1&89ۼgYI//W~Κqκ>9: 5ʃL~9! kd*z 鍐8t&Ձ STOv歍0st2)S2>na!Ʀx(jdx_JW)۶"r~rn ;7qW.HKWw<J+e"0n er>J&ys.輩1$?ʯg΀&IDR\&YJ#,Kљsܙ2zDZ ;I+S+mLܩit#v1>oSIΖiW]!3_'Tū^cjx٠߿͛Ė-OfOqjGD<*%QJHbew>P.;e)V+jo[G*9Q %r_!M[,Mk8+E٢(ƃ>0 ;E 1<7%5DCJ-꺗KkْcqKخf2a4rbYQU`Pݗ/̫Ӯ 6*iJ3bjMD鱯9#r'|}}No//W]b8] *gq"M3ٻf.cJ~S9�u(x:6୊ \Uz:!YԤeÕ ]?)=hiJt.>+rT+_syg,ЊZPfEeW^eS.C|d"Ctx;ΛPn? �C9UF.a`U3$d"+T ^LfHh88ӮRŴ,"_PSFq.[дT! 呆w8rE:<%ְN:ʈIvP̣HBG"xci(eHaVjM6P_Wlg{x$rKbfU-.K~Y}U w+H?^1>*@&!wsI+& >4y!?@6m'dc; eQ?]%s)eo$oQS aݸ%q(h@rx}./<BqۑnOkK\d]o&%,bX%㶳E3mte"D2ߖzT)ɗ2{c\[TsM7SOv植ϋ-65(Y ٱl7}f;OP+U%s)mC&'{sg&4޳Ixw@r:c]^n}(ʍ viܜ})3YjO!ms-G-z-̶~~GO…NBR("mPV+K@{%Kr~΃{mG|~M?r- ۨ~_h|I*UwEX(G.y %+[>l }'f~9DCw!%>KXm 7GVʮ$ VX&? * bG=zҳg) Y̩ϢG!K'Nʬ]U累l\J(ph?_Yf2&0-p+1>_`"Z hqigЫA*9NޑN/m@{8=f!c:Sy\TR탩SF ` K1f S< gpӵΗt#j|9.x Fl=ڟچpy8%]QBz9W*ϞS<x ?$,N-&ɏ�k˜e(+,lŹ [˧hș?1٣z tKNf)V:hXV*oYHLu@q=\#irM[_4$Sled/j�rK&ݗ݌ASh6UNɍٷc) -Yzt)@ Wd! ;WoʷÐpzo=LOUQ[ŊỉHVbM~U wNe:B#(_;Fщ* q8qOu'ٴo3M NgnR%a0˼m|L:IK詿NF9WC5TU~dYS=-n;sJ<5 62ә<Mq-Ks{iƍyJSP?2V$,l)^>淢Uq9]1MNb/>\elޑ H~|{wfF~}u>dOy]=dYrsK勘[?$bP6ú2V1wit,Ru[+{c{v)v_VEN6~X?zX+&_^b}Gi)|y*MwR.2l~|(]O5kgƙUSYv IVXe*s;{hx-9Ahd 󢔪z]r /f#\~3'3v{}f)lT.;ÂFLݓf;٫=m`Zǒޏā}PZצu(u6y{$ oAA~h= umLlh a<+ۚέQDžB&JP(Jƶ�% |<v Ad5;e:3‘ JHR iwjd41)B?FrhMJq4DE@}mkObd mbqd4Z)]ƿ?Z\篠qkKقVgJ[ats'H*B~ȵ']=WJ% XO!MTwm7 MaR/wBk2pe~z3-D5 ;'V_RLB{w+¤`f8`?d2qAA{Ƕs! OK8aPo+f eGM~ZM0%(`X?kfNM M |,} <CBFTOr`,hS0#Q4:̭mщZ'׎o^c^/>RCH¯~9W\|H,25W7w8k\|3Xح2v_r$0M bnc>/oF?73Rpi#(WҞfH[AAxo _M 2'|= ۨc5:|[ET3VX룛 VS_4HJr d%+?SV+EB3}>)4V c*o^6or&pFSWXUp?X,-P1'u<:TWyxrŻ1Q$As W,)B>Qfԟ2./2nFG3 7>iPuؾ9  M2sX܈&m1)&! o[i;APe{iFQКXd $KJ!%Iou괴eD|SV6.S^V\^i[c$L B\,2 SA ̮b5Td4wVhnaunͷS`Zz\,#R4-@-h~=?,'cݔn&aNq\AAAABvE0x9�~90b@VbV+)>0@8(V|ؒ{ߎ @9>qNӊA4(|}p T uKFA|\^NS|ҵ p彷 G܌p,aXXy /'$!cה㗲gqBwoXAAAA7پdvm/fH F#_ϥ}KT5࿸d*wj{D8m*[syT � cSc#r*o6+YhJneQ<MYwh}SVE*MwE3ٻf.cJ~D̫Ӯe1o8 e ,r=uUЗ޳3NjCcv5(6&X    leKxҸ7^e)H)ReS򔑐eJPAנXy8NY�E|>Fy$MLq%ʠ�Qs(ڴQ׆d3j|9.x Fl=~2ۧ3c xM&1 Y<FC*`G.] c:6eX3t;UK1 lʼy&b^.#{Q@"    GLe9g5j5ZhA)k@MPBABA,<bl{N{5=Xbtt=  |m_'RawG    {!WcJ?-¹I]n>Ss? ?S1"Jcg 'g\6xɄ߼Ɲ[!x6fb@VAAAA^JCMf җk6?F�m հֳ؛WcįYyKAaz|=/{YAAAAAp|}      A˥]Xm4z_AA?[ƂEY^' AYAD_!TGJ/ACN"INx]woBljv\A=_wl/ru|&<,\/W˛"  9S6k2GW=|ld*}Ú1%k6lmUin,񚸝aUyF^Dzś9|.J 9Y5}4&O:[s{X5=''bIʍXz&pS6dGbB=ӼI*)68Yz'בo ԉB/Om/f2N3 vcޔʬ8>{[װy_\EŒ"ܴ=8pf?악$ ԟj] \>`םX\h{bnޤ#d|=ͥ"tr}gkӪS;A)WOIc1._�� �IDATLc,L.5n[˖R38xUnN16ߴgyu@Hruv~<9i?thfŪn >-mA槬>.d/ 'VnuR Jӥ>{}:+A"'g}Ŕ_CWS8{UQǮww蒰X*ذ6c!Eb[pU'UeaTUiQ'=C4Xo}hoܭ'k}|9c,#GcwHRL Y9_~߂KL:Y ? ayl>z׊yϨfyTIwm<8Ghk*Nl򱌪 ?vr#mpkP3]& ē2*}U߯ eC2A_ԕoO?}!qm諾9K׻AxC]z2*Qf ıuM7<ć]B́=yB6#rf?ʦ?I{ ׂmT ZL |C[DL5mYϨ^gzLڸ(-D+,p{ֳ$^a͐,jNm#9ƦN JcLZXXXBi仾4>XizpÛ1e.O#;49UNas �wJHՏ\.zߴzP{w8)C;X:i]}(ƿL㴀LiL>h;c�H~7]ϲx-q!n f┍f>.*Ŵroøo$v3v2Nv>/ߤM# 3gj{<tbBvl~$v3suϥrB GF)-f{|Ɲ]&.Һ_ml�1�~8 P#a¨w|Y,0;ً']H*ԉP<kZ;1.Z=\m]Nl_Ų /~yCvEaU3?>[80gqOJZ6uoǟ3|usx:SMȆ!bur O6.Yɨ֬֌"6pi%F Xy˿yC[dSԕoO["~̇>_G_57qiQ9EX9=+tV2AýI(̋Rg U#@,;$+,2p=#B3Wx)ӎkw7:5":K/֠ ,{-N~4kؿ1E[r3]ӠK/vNw˻@O5kO .=2k'bbwf*6*yhB T1CEvǙFKX=5 Ra'DʌfH$qk<f>DHXxiKLa甴SR,v1r&dԱ}F2w'wU0q-{Gʎ-ph=G霮̫f+f39(RUdf"L4dVFCv^®?hByӫnz,YĶytr3@?=Wmo3.kE8s6_xQ.jkHE0p$VWZNR�-w.PXV^"ꕮ/6۠ xbt2Z.O"d׋2Qgq?-RU3κh|]ɱXy=!Akm Z5v!~N^G4xweȀ&g1xcV+ VIq|,U k HUD.גib62:>|rl qū8_/!4핌SP"/v}K|CeL1\|wT|�: ?|1za! c>lFa#[<?-_J5 �%px=wLWJUH蜿u<I_о O;ih/G_/[ytUgk^j==:{V5y˿,Ξ(8ۏs-B`4ُ.m:7uƟ+x]_!?y:co@c+|i()T܋BP3<16l"=Fʤ d$Grht&=lΏ?vx&7q\T#>./bPV>&r<7l �dX`Vˆvmұ5?er-5x %uXO!MTwm7 MaR/wB!?.Ԟa+a%ǒ\tW'TPs4nm)Q)EgTO9 w4$Pe_bgbxV̡c꺯RL6&zO%-0 $L AAduGКޕ1zi<&֞Ĭ>hmw2q!L ffOI,eX;+Л1em!:< *c%<KNFN`oT%zjDz0γgr:ZZ ZP(oW5zétiV`n$<J[^3jqqJu&]f9V9z5F!݀lNQS';T%?r4]~_.Ҵmk֜ƾd <}坐(ӹs`iqVtOs<(ڕC|1IoK`F!j|֕ #Ǣy3Xŝ3D*\ob /> A9)$>џ ͽloȦY]D-+=&&KtG&?Ɵo`QX8c_wn5Rzy2:>mEBXÐJ^7)?mcdկ@ASBŋ3."'đ1/{b%0pU3+^OpF2CcIz樷�IDEƣ(LIs̼zEmk5h糬{qen7&X:ksGllZitǟzueוY$rnF6J{0Vg6O}!5~(X`ČZ2�0"t>qSy}7WͿ4Ġ |Lx4>5F㪎/.ORP]ô̏mQM_AaW?*S-oWu)!WIc^{N p"' KQ;žE>1fd@:hԈcԭz5lη3ѴvFJaf>:{7F:1i.taZ9Q,4<sk|[t#!vO+`Ԑ(d42FG-Qү=͐(wV3'ɆMWk1A|-Zxks2Mz` ?a?jAOhVz#˶[XH˝.%KP@,Zמr7΢U75|q ٤KfǦ9u髴^MUѩ P})cOp5зs{٫Y2DEb\6}7s�~rLo32'ƞxSr=kWۉWiXԛ ~3y_TS@9w<Գuuisưs]=uo7tZLYF+H k*}=F^k 59?@g ̬W[M(ZFn&/\LW�VgoIޥ_?#[6*HBZ9EA YID?$O}j%,bFR/a)~J22ȑGSPy!Ȥկ]O9™lt=C \>|o=2%|Qc[jП"1ǗŌ9Z^{7'x8]{;mr=}>5TCÕ#Cy>7?IFue>וYّNm브Җ-B},j!}!N|7HT==3mkȟvY�r|$տ(oJҼQXU Nu}괩閉>3;Ҥu29`P=]0~tsyxrŻ1Q$ŧ%*ԩl# o݆"s5+{2hg@р,֙O}cE e|�3i%sG-BT42h]j%{lԿ9/'&uӑKiƖUh߼(_mM88Rf~ zx7c#օ4(:el3O< leoi>3ցi@r4_2)PY5MO UVF&[L:dG& xY~X}.]2?6}aІם<߇.5<hc86XiU ԯ{ :+�rWw۽w{Q<Aqc>Td4W4ahS 2F;@2n>%N&ˁPtKL J}ƌ!X ,6neoV̶PhLsR +}ê-ߤQzfb$,V X * A<ډ_{n}exs5ߗ[ܔۧٵjÏ3?MWC[*Gueyh2�Ru&D9L“=szZU9u241!ƭtUL}v #0xd̗'z;oC6'&:7?u礛rvn'?+uyHK~Vre~[O?,o,UztgNucIl�9>9L<>./Q _0ӹc8P%hP:̏mHxzEK?1JyVkロ*cs25J;fVY (ߖhw`,_~JJ^n3yeg>=G!SelV|ȝ^]cdL B\,iRR4Y*F |7vnʜl4T}eR=UI-l`m cfU&iN Wߤ\6үSR{(M::vo#ɴ%J .T@NJ"I&y" C|GGdulaH>i|:3yH ֚;e?kR&~3PF m;_⺯(3 's GN"\ߙ,]w1c=*^$p xI04ڋ~iH TvNͯ,h2[Je -tU R; [SP R[&68u)Yۭ0w[w}mBvuv/:AaW} =s`3@G&uP-v6OcВL'$;.bT󢋧""Z:;} <m(Y?8:̎kTV_WnH')1:7]0Z pv ;bx(hN;Y:;SxDL|W1mA&z<~N[֤97Wxag\Y- _|Vu,#K8eעE0PgYƟԕYd둾nX~ȋI3]w"^ᩉxzd/ON(OIz%./^ <2-٭[5{BP'|XǶL>Q|ҵ p&o�hP* %H^'&1\姜8zaHFA|\+csrq`hbHV|ؒ{ߎ @9>x- ߽GBv)cה㗲gqBwoX (=p3™tiVeo` `~1{?-_0j `X;-W2t%=$ ,BUQWWkWOqih j).uK^蛦Ww<J+e"0n /}ɽ/|ikx9!or<!r,n+&?v!-;g0ޗoUʶml#9GuW <d^lAD4`` =ۄk=?Fpw{/,r9cIJlm)PVM$ gÍ.f/^H)s$Q^fՊhʵ{v_|~܊1兵">xA؃prXty%çc  aY{(+׬fX+f�CX4:GEv˿Ky7;\^s*- }禨+B]J<U̯G>S;u}N!!~LN/f,Ql ͛;9>7LUsWK\_ĝ?wnğb~ݻByE(|[&\pf={åQq,U܏k*o6+YhJ)63yk4p)�{ g"([toǬ:xgƛA1a'ֱ!5()co ުUiP!rD8B ֽp6UH}bIPSFq.[дT! 呆Hڇ'yZC1"j# l⍥a&ؘW]b8] *gq"MkW'u[Cp;>+sjTc߅xP�Ɋ_qUsjz\J$e.>D%�cCtl/+ R+/_ŬʚlL@@i{ ^e۷-oS_q۷9U:韦/kܜ})3Yjэy-3QP:_Uv˖$1CcܻLRySrנde*gDzq<ATab̵xX:"܂C9UF.a`U3$d"+T ^LfHh88ӮRŴcr,${6 QN3wzwoow:Eɮ(džr̵Erv7�6!:'uGэ.Z$-ܷK2tA2l)gB)hRqb*v|hަ dK\c:n9ѷE=,//*Ns aؿg‹4&G$p^:ɞpŤÇa�9Ӿ߾߱dX-,秨勮`ǒ2hewXϷ(ߩDuv'Xȝ~P`fYa?5HBi^'{KT~vi$kBc3;bؼvnו: :_5Fz+ѪRB-C,E~H:7*gLqkvU,࿾97}P:jR|9Š |7@Ӯ۹Ϧ\b2G)#D0{|%)hDvOdVQiKLQ˄'D%QA=<}lUxv4,6!KԘ9Yk6 iF/b$ȖSB̧#=2H >Ӯx( 5#alb#.QtKNf)V:i/xDqDLe�� �IDAT/g)25 Ic:Sy\TR탩kO"|nMĻwe7jpx)zԺϣu<cHL)Pu+)7CW#ϋW3yc$IJK4g7S:]G҆LXl?:@3C\a|%L&s94- iЏ/~ΌWȯ7QL&$t[ְjn |:nt{$e `x/ȰOgT6Ƶ,;amF7u+jrqfN XZbVFߊd`#gVң?{sL(u�-d_+,lŹ [˧hzh#5?trwNe:B#(_;Fщ*f |421Yҵ*MGkgASh9 fb,~06/(/w#'7~gߎj0,gNLс }]5)\\9$\)z CWWegU>9żUd%7^3{B.ҿI$E/e~0?x7Hd=1>_`"Z hqigP5lsg"ʷUW'H_CJ|6dFoF,]I*z&}!"~L1nnǮ6�k]]wm<7G|�`N}Us_)ɲ>$oɁ}PZצu(u6y{$|wYK,fAG>AAA}SVJ&]g\eb3hAAAwHU61(+6iw׬w=ԗJo   -W} !    dU܅,    AYAAAAAH     EbPVAAAA-     oAAAAAxĠ     [$eAAAAA"1(+ck~]   CcևÊx\< 112%9lboH<''9u)>w)WX޽ m''qAZs_j}" 1\=vMx>.7v$b﴾|ڤ.h6hԩ0AYAs?27$p{/L!vRkn,&LKmL-X&m3pnf4<Gg &CiEdĝJ:|[Bgg,PIʜɬlĜ{Eq$[O$plRKԢVZi@P #ߣ;?RӶ^ٜ~%Y3O&37>E:ת4jށbGHt.jB;_t>}9/-ON-cX Gp}ЉFȆM|۽5RɧRNhـ:i<xZII$!lߋ6 ؠ%XƉ0y\idRtZt%>75YtYz-u:% ?}86u+q#s?2MkN3?s)χZoh8X&;b?m8[$ay=j{}/bwc/ξMoh~,ӎ7p ?Οհ˷?fkp[aߌ|!/s}=!,Pk(3MX:tV îs! 撚Lܓ'$h8l-kqSne^µ`Ӽ_-T<'ĜY1l3I]}025ZcHqoøo$v3v2Nvίt'Gfx鳄P[3_-,4 D]tsiN\{WӼ1[ fIB\)[%%|!Λw|$D(5xvk-`֞?c.i ̰eaT;, E_<ǜ$v|_:7|߲(*}Gu} gð,I)<? qw9}6vC9Ou,,E|N_ &Е.䏤l"+aP'G d㒕hi(н٦=-D+,p{ֳslPcŊ$V. ›j'{ ?||g| �[7G#1�~6aZ+ʧ |^ZKDyQ/c4x^&<;Z6N@m5HY#թ9 P^3z&!D b ^JwX;:7E*5ۼ?EtwYtkѐ:i0{HM1lLOP7>-}CHN?n,J@͚ԬH]l@&*" pÊ]<mq* 1ѩW%S.2m V|y\}sdڕ$nNMS;:2`ݿiw̤^n>+r ~JMXF3`�֏3]Ĕex-pES.FNAԫ]A?]#^W0}reXMJ[o]|#96 =7Q6ulصҲa [_uD2Fg^e";PT)||+RAiA9yJl]PeMu`;}[ҠjKάWm؀GYk z&;︪ϽFDܣYV#-2Gj\ș93j^p0ds�r._/<|9ySyҰn։ <(2ż)y,bGDծ1#kҰ@hLړ(6-IԮߖ!&"lp 6+p.zK0׬L`x  wf62h]蹻kfxtn *3>AUR%믲Wo:GבnGs5[ɠ꽎4WF1U/OTЋ^ОQ87d\Y.:8?1]yT #,_58"jL _O"i?}wcADDu=mP\uzU3;F2?�<i+/ء>cŤ2Ԗlo#蟦'~p/T]CW<fJC.@P2wj.%d/J2ie-ncS >dMxH<m,7RpS2ZbɓĨ9[$QC #G1VOVE-; nNjma)|̜n>ۿˮ96eD]ˣc #jm9x]O ritXG[>o;26fYQ'6g Y:NYu_!Ö=vL w ᶼM]Ω~cBWG.#Ȁ;f5[}@-@{+czo~΂جtL Ivbe83 xQ˅18"`\u7�b~2޾LnSO~O #>raG ]rQˤC#W{F'42Ȇh\RON#ؤ_c̛J>}V3IUY`IpDUF0 s]0F$EvoM0?`\wɢ ֢N_ R˃^shV־ N/G?i0*9qsG~,:yi 'Q{G麚훏Ӧs˗dŠ 3>@:[ԣs%°ɾLSH8~]zM_LU>+489>ޞX�d.]A_j]£ֶW!ΰ`A"rJQ̚l7cB*X]9kJ#.6jTØ^raPI93ݨjԻp í.^Gnxb԰plu9arAס{h$ Jd-2%*7*$&Ev|L<JWSjPo#y0jJ;.X1!o ;M?dzp”5߾6DqcA$e +%<c#!o9W.pv>iZ;";Y2П; Tx1)BrOsz|"p=<.g=yBDp5uhOΔgIۇTAǯ_c ]i5ߦ*HijA$^93F]cZZ:% *92z4oXKz` G;Mgx:z ŚQ\>%CdwzM\iܗͲ*㍟39n> >\oߓĪF;fSLouIEVǑ"ʍ>>=U"kR-@B8/Vpr]1*%zL9:vә'|g!t$)A߬^sf�?4+8[ІhfG5�- fd8~J SAD%ljK>zڗeqM fYF/H*j9�cz22t&I3 ɉzJQL"w/zϣKХ'}A[`my[_&}I{Y>зW1*j?=9wQS楡$0:u g댡tF~czEw"Fm%Q/T]5wXّ`VIk{d;P+\/W\Wh%-j]rqX6U_DZI/yh?h5=*Й"<Ĩ^C?8^tp~ְ$׎0ըS+Uሠ4wg4$ϡtl2Iw-2퇂~ kBȾQ>j[<cϯL>6!#Mwtv?iyt/3BIE6Ԫb́H mu?q9,-iVq\继9~8wz(\ t�*bp#r>d_̄/wJ˭+Yw_C䀍V>4m!ɱ.h^b:vQrV< a~^ٿm[02<ZĄ!4`$oX\<2.话l5,)\ {k )̃De8ե[;/YSضKjAt&&e-BңΟٛ_MTܰ2p"+XB@*L 'پeTaͼ ߿0:.^'s}N*3M b$ jی䃣o3~BUE>LGd2c:{\ض52Lfc]_ga'̮؜9蜺0a]?Ŕtgu2u߽2,4U4=WoƵ82dW`@?ܼy|9 s�-fpfFW* #c[zz /&ϡ_�X#H8}l~W2SmKϧ/{=z,2:bW u73Qei1;2<hֶ>'of׽FD֪OѐUz0iXǶBeG9U:E ^HuiR[ӱnc)I\uD;mX1ֽbOMCgJjk<k<VA$e+Ν`P'fʸtbc =v>zSl= JNUg9WdUd4fȞ]o@ݗbsɲrJTiԁ.S[=qM ]FY/mbh />d-`Avݨ~͸ŕt[;[HJ$9;Q 3W-+nJVˬ�YF rӆdnj}LcL{'Бbu$58uY] Y$-&RXG^EV)v!ѪLE6eHWJX(;0y.vKhwyPQ9apricu' iLeO2O.}2þ_XΰO Ti^*AL_rZc1# 3f8OȐA5:_PBΛgɦ,R1Iw`+.Rc< q܏q rto#Ug *%#2uM#I !f7kXR]H9v=WbN2mC$d >n87k&g3iW9vV̒-]u> Ϙ [*UB>y]E2'9PE}>ɟ1QT4ylF[QQmҗ| h m. ;D)v5Eix!k\N,)S1�w.^J9+L$YnrB{/c&pAWWv?~!-WdlkEYn==ǰטpԸը*nw6 ;x)Ǐ^= D Y<\ 9dF2ʉ&Q^T66䤬_WV ܽzc4xFE,-cT[sPj7ɴ>^5?U!t*TPqXt~0GN%Xjukjɡ|-+lJr,ımlܙ2& 3' AÔ|0&/h w0(K?ܢ5wx5r>@2,X u&7%=g'T}PY\ż1y^$$2G(Uݴ8pӺ8cMHJ'Y<;F ?%nxOlntiU\_Sne &>hEdz1ic +![lr״#MMa%,y9V_ 1[d%纙}?�گ4۶v"+sV@V&f1Lʧ-fѽϠj&Ů1s!v ).R+ExƱI^/;&euJq$kSHjsaOV 28]ѾmBidRBE湵L^OP`|AMmYaكսPݥftQn[ɷ{h8* 5AlYs%k3 Oe5^iKч>Th4<- .Rө.�Hhl5D2ʓz YxW@XᎎGog<r|,MNVOɡ]^Ȑ5L՗O4NtR'DHG3Gvz�:R w|jSJ-'6q{GNđ8xpwli1~ OM6 Ftk.cWs1$^䮟XԆ(jlܙ<& 3'r%36n7a>X{bjY#jOVH ΗkUjxcG kjO2u~LGsТJj:ϋ>9$C:s{V@)';z!#! O9M1 R =w4xt<ySYD{òr%<T>o+6ъ`JNaH�� �IDATl7ɾE+T>:"QHݣJ#sbzr?/yQEiNC.E)'c[7c|is�U3b&{l_#AʕOӾrRʮJtyA;ڧe}c} ^f'^ù_U9Sel1ΎGv/*-}ظj&W,kAsGFѾ=l Y| S0vۖ^jJZh1cA? T$e-bvۮއs7YW@ YxWLEB#ܸ˘W>qY+2rc" lZ ¼InՅV}ΎiiЪqJņy͸Tv3(^#DdIP)LSPO/InΩ= NIX9fnT8&5>>rBr h:9 iHJRo`&MfLԶθנY,Iw97ɐlqTޣߥ!WLu s" ɮUIxYSXt$G"{T[9>: #1=MaVX *~XZJ2isru|>d nhRƄgV|PPV8{xd[* 4nti2wFd. 1's9lJkθKsS9t5W4!Lu%eDt.v$(w)I3|j2 ad<m(W&fCe Ƙyr@J6zДMF̛7rJ2.֟ɋ=د;5mT6Ii3f8'ZކƼE QJgra)Q/1]}|l)K 9e'gעR53ygH_̐78aE1[HrJr{#R^yrׄ7/W-\ϯksjĘ-ch_iڻ'c:}?�5zWQ̾lrPtTL]t ;OM] 㱬%J,? %S'o7_i$<诲iy=|dK>%!w @ ;6үb@ (\Jͳ! AasmO˴쳨Ňڶ@ 8@<#@PA|wI{K =j?+&.xvS9?l=Td >! 4-Z<@ T"bF|@ 0@ @ H2@ @ @P@ @ @  ")+@ @ %H @ @ A "@ @ @P@ @ @  ")+@ @ %H @ @ A "@Pȉ-2-@ <KSNrtg 9[+蟶,@P1zo}//={81` _ϪP}g ޾I.S9~=qx_9ۧυ<<df<y/%=@_EIENl8S:3፫rA`sFH잝NSqK:=nN/D?MC81` _OgPS-J6̕ ~WjJX&nERWp={حH׃Dz>ץyh: y#XW՛FޙFm)BwnjP˅p̷=s#|a+eĦw!vG ?EH[GeJ ~UP ,IIsCAL~+AoֽߍYGϫqT"@Px7vG9,ΞcziVh,>kf\N³z+ڏ,AK~^_%Ɲx{PgUZ-wHה?oM], 'X>} Z>4cȧ( .w3L?l변l)zIیgOFʬ0~8r'eパ?p6 &_ttΔM=_dZ8Ն8j<v))gAF<i&aB?}PB@rKo|>5\˚,Th=v,k*c=I dV7IJ ھ6+ ^N|1 .r 1*>ϠO<v3/܌N@ɷs=&8zyQ5f.QfR@i׹ʅFgP)Imw �$+Ug']eOXz'e<=nC֗I=,s1\|o~ؽdc?;j,ѦB` :V'#z+ǧzOV}<g7Չzzck~\~Z[<Ʊz bW:&dT6$%= (.1*ɏk$=qSˬm zSRHQy5v |%Sٓ7r;FN4'TN9#F 1rhnsbϬ-ʴؕĐdӆc9~ߡwH�eJ%0ODRV xIzZ=UB7g])SC&ZXn:4jٖf , ]Ɛ-  ͮ&k:pWlvȪ3qL^s[ z|"i`h虽0F.4T^Tmևc3 }wH[D�:.,K%�\Μ4.:Y,= zTID+~Y[CH1eک1e<.hM?^vR7+m/o&ѬzkxblAItuKл 9f. ~˹2kѦ`zq^a�FxS朩RϷvsN5xޤ֤_Q}yWFe)@GXVϕ6T.W PGJg Şf/50׻z>/'p`To?[񤫜=3`\Ȣ+e_ퟌ}u 1 Rݥq܈|7F<.5ˈ\R.gD񜼞{^:mq@yng?6zY@m_3k=G~J w�<߈ўGi%t P3o懽=́CxX>2;y<p[&AcajR x󺶸/|>5@x/U++kg\nq= &9?^~/7ģnoƷ_Q/ '&+z63u/G_BQ N-yc, {_z߾ϰKxdkŵ'uW] Y^+`c2(-'p,X'nbQLfD37T6}{SmJQ~Siz7f�aͷ ?؆7N:gQLn)he\oaO/>0]αFQMYIY"{qRBd]C p;6`Hބ׍V[2s. ;5 L%VjN<Iӈ5JLzF[F,|IֶhԐ]gztG90c'Pfl:y�e*69I:sG0sv7<{1jX8۰e�PS8ƶA*Ivbe83 xBChu=YS=zg;,ʣ-p\ {_zQR_8V/Ͷx429(I^M28t!jxޫ9=ųryF0eΙ4/_!Ö=vL w ᶼM]Ml߭<Rz+ϒ"#G0zD?*$sqٵ#ԦHkyT\R>[w72zD86ضp6ҰO_pGoLgwU= t !݆е%w^ˢùZĔ("9l£ֶW!ΰ`A`zM_L19qǒZa<ħKqf94ʖTlQ j9�i&S rJ)hpr|PWLU2.ƠW6(q=T΂]5٦oƄU 'J BĠ^@GFt474yzDw_R1yɃm v =GB�ɞj={`Xn9›UkceJS]r4|V@+/Š]0@ *l^~5aW-݄:L~sާ*j$,=B0'Yq?mWτ*)cȸ5=3U^}^}_j13+gO+(\mlwd^]TԦifaB$w+PŤ\ˁ>:gZè&jvD_| jth3q?V,am`ݬףyì'pS8i: סvu!~<{;SN% l[FZYDq\u�X?@cu['^JdM#HHv o GO$ dݞ"*(>uq'ӷjj5kI먖43P!dRI 4mDjd^t<'@ $ehB^Vn:NܢC]CsC SkRb(i. z|bWOIm__c0A0E[APZ?K9iܠb|=[}۽EyAw\db2V^!Ԍ ǒpc="_iAr*ă;z8= RP;wԬ|.&s 񥏻OHk}6*g\Hߋ%@Lw"Fm%Q/T]jB2QO޹ÎVBUͼІ@;-WoLVkT2*= (gAvrm>:2&13TؗƊw;3OkW3Z�zoq4:پh=PS!?ȶATU5b)W>n弯d;f]f ~B뎺R<ƽY%)Lyy+'P^67=Xo|!eɺ, ϗ1F+ lqX} P}`]){P)>i#z:y|\OeO4Y[U˸W?K@uW!QNŹ^)hͤcәYHj"h`ގ<!sNp,.$ڿ+;$IhCYI>#_mҖud\l*mh 9֥Y KLNx9[.Ԫ~ZXxlۺ#& iZo^a;ٕ㳆eC̤{&X&5Lܽ;;vi{ozѸI0y.= g?.~>zr:?YyF4gS1gΥ.>)M_k SOY2/p9Ù0[ʺbd(H$(~n ЮȹxBOj"m,hClZ]7rW/Cbp]Z1L<~g�`io"l]A;iznn_R}>}ټߒ-bU}~NڳzL&OqHk3mH1J]%cY^^ZZd'/y`z(myQX]ՆG^?@_Ķ?Q_CLlqXQza)J/[wbJ/NDRV xNr Vɑ }M`N7.:cS)48uY] 9\AUz0iX\4ؗqFSV;z/ ÁY&|W:�^bݖi7q%uocu~o ێerC?]7_㕣rξBJsǧ+UuJt>wꑌ lZߖ9f+ BzLᛖ;T/S(9PE}>ɟ1QT4yP̑edɁ}MI#Cc1Kk`Ιzg_ Ϙ,1(jD$)k\0y] 23u+ei%zt9Ȓä +^IBh?ږ(ԒN{j\,A⊋X-B.}e\YMY*bP5"=9x-?H}ֶI z3wēsd_A{$>2^_\!4IV *ٹ4{P (܂îouBbǾʆd]&##hu rAǟgΓ'vy/H٫:UE <h+}{?,6{%b*0$``, 3ymEn{!|7%LC6qXQ5Z!ux=B̥RL k\N,)S1�w.^J).L$YnrB{/SD.[hުɦ߾}q2S*W&/ '^:]^ۚWHh!9)9L[ن ׷gO|V-x,[bckLy?ƭF Tܸ~m*x,I{S-,0Bq-bnޮ4u9Ͷn ~٢N$c<QIKYp" ta*0w䟳 .ekLgINy*Pi9q8ٗnp5!* $ L23 wz$dsa'S,[]D{ZU*96LT^]"~uY0A/RuNM>ҥ,]Kg3&#vl~.2V/{9kN>''sb x]\{ϊ6X;îeSgz$[am_K J8N JAڛ_XS0O A~R,1SFS2s]v#V4 .*nc/Xz;&euJq$kSHjS9q0N4ܾp!oL_rzX֤֤q5OeH|XSU|+-qL':NGj/*ٲrJքgbyjP~6Q1[},'"ۄddڴO&(ՖKO�T < oY;Hɱ-9,{о_ixchJhUh҇frŲ&4|jCe|fՇf}ÚZgn\\?o@N \9 o|׊(]}\;zJ؝?$uG/dX={$dbw~A)?fC#v�t{'P\I[I,Z+MUW,RpGS?q>dC}Nm_βh2 U ~(ږg##韽{2v2o}Vr|5tDҞfǰ\ )Oۊ xiؾG10 +?1xCJ%ފpeF}96%)'c[7c|'I;}ШSH5Uǜq �� �IDAT+$lsYw}XKt2Dk^?dٰwk4 -MmN\KSS5; b|ul/Ѐ.UdȚ|KT'{Vixl 뽢l8;Jɞ~k3M$S}&WL?S0sOIA~R\abf%{?c ql")+<hT LOv>|2O�B!<�*5sHhןz%T99a:>G7oZ)Z,ʸ{&%MOX;F&Պ1rVwb.#7&iٝe0{=r0ҭݨqM4^asnē!VGKGĩnՅV}Ύi!R9ѪqJņy͸Tv3(^#_3l]#*wÊw \ƿu;Wj4q1 oOgӷ,-cW'v'#AQ;ܨY0X{ l2F,bKfү[4]}YD6NzEWbE>Ә弐2vm<ZeUVTvfhdF.Dm댻 JiYx3/#]ŭRM:}џ^ ?+)=cCwYɶ<0z P&hgx>awwDVN^~ݩi ̋<FZb8Ǎh4f _4Ssa)Q/1]}|l̛SV"ӸLp=�zn_&CHyקr)EBJfv cI"(d_7f,ʏY{Gjt}'m3cWTEJukSxFHB+Gnch^6ϔ^I UY똹?6 yS!vګ_߁iq$ v)SY =CĄh,;Ccԩ޷毴~  Ō*͞ O@ 3TviǯP}M TQ1~;e@`"\Jͳ!Vx~@ @ (u<qXɷ+).;7%iA|wI{K =j;@ @ yÞB"c*=R/̀|@ @  ү$7,@ @  DRV @ @ J@ @ D$e@ @ IY@ @ @ (ADRV @ @ J@ @ D$e@ @ IY@ kx&| ]qGNrx Dzۏd)2^uDNnowY$Ǽ8e i"Ja;f+YIi)J1޾I.c2Otħql$pvND'QCYNl8S̕Cs*&x,Q5KNsAnҺ77r7b{"+$/fq=X)%1Ei3&bM2W]*cOKeJ]hOD|q/6~/قʖ*P#E&=_d{AeicYҼkqAE,mcX~7f>*G٫^Zܖ},YXM`D#vL%k<?š XƭX)qq̪ 㷎ֲhFC,xspo꺩=ڴ tj+4ho૏&sY,xn]a9,~j\*% z,L1.%=QWy)odڸToLsFNjA, k_Jf&ud[q{&>vfOmIͪww?RCS\dEq@SٙoVGҲ<] <\$_O ײ9;*Mg܎Ev͛|e "t)8\/ & 8Wb[T*_%7Г@fN|~#t߾>`#1B/G)AB3dn6;^Z�nJSJ0;Ő&i$ĜcϏC ?N@yz&xnSRHQy5v |3'*{<-f3:AOo,bb| Ok Z_> IW2dn_3@p6uݒ9n6_2͒t.RғTr6*ym*F c{2y|dgpƋ!,}ǘ̞ڍ�뒿:iBF-)_&IY'ynj.^ VY\LH̍4\<CJRT02qŇ򉿰tK'ftQ!s믻~xd<=\4?AI}_.Hr,;[ZIJg|7&ƭr#:Ԩ/#@ϭ_'0r>Ǧrj> }S`ݟ(mR:v Zق|d<B1$2)>7o |krwyIN|x_d/]~1Ua/[D&wzK}"i`h虿7*46,�WԸzWY}L{k<‘/hZ[}Arz9[gL<hw%g%|rsmK$l2yT8?Ph>v&844kRw;ŦmxMw/'|+tu ԊNүsNNNѓΟ1G7Z3?}犵h0ޙkͪ[’4^O3s֙Ľ3y}=n%q0TrʅX+ V1C[:sP˅,zR>21\.Hы]Έ9y=+*u  :`l*91$\ $3OrPɠ˱|5){on<y][<T6p۾f.{Z+g}O,ۼE�]س}:GϤۦZ\ڥ'ڭ y;"%ῑX繭oZaDZJfLJ6Μ2@#mJAdqPA΋*ռ&v7_NmLt7Ԧczs=30^z"sENХoȤݻvl>Ǔl e\.vj@&=ә@[K՜8y5 |kdSSzwd@흌]> =o=7?gAl<zȳK87Ȱt^\8Jf_-+O#ؤ_c̛J>}V3IUY*TnAmpsRtn LK`tA +?b{rX&b,ɞ^h(rw"A2lj 1{W`n ԕXrwzOpj&4gS%$74l rָًQ±؆,;2Kg!e9f*G`FF;UH<x^ )Sˁ9WkoS^ER4r`_;S9`ֶhԐ,?}\v!)#'Z m:&MwqU�?.ȞDQALL-3̑e9SsLMi?+5͑s{ʒT˽ (~s39wʌpwၹK1dra|QA~PN2o8,*>)CbÈr1'rd; �&ޭeMs)O>8Nɐ2OnK>1_P\՝}QŠ Y  mwE3P)\ubW5_Ox$#TILwFl-4W#@OtSXQLu|;*#͇ fIgOs؏_-Zzq^('^y:N:綱h[ԡ\�SW;,\LzzqŶ/J?]zn2 VQOdByLlaN.<}nLnF?C??/L{A%G, kGg`$U)/9e<kҤfHijxf\YcR6jeAr xTyiqBXܱ 7Nb՟ݩ‡oȔxR%ɟ̆:FL"}nΧk[�a_1v{D-[V!x'N{(|j''q7ɔHX<g1 �J5{+P^u&~5\l<F~Th�fz݊M\wp xt]lH;yfV]9ɤ\mR9u2'kfUU# /S]fu<Su\{l'dÖ;リ('̺l+|s|O>yL8g3s0Lh}BM'}rCN$\~zԨU*)9Kpm_y}˅P/,;R<r $HT %2*$}lEG 9PWŹk=:{X�L<yTλ>uhV? ZT#?ǀ,T[ lG?\g ۇWm]3;d_Wªb;n+o~@E#퀩Uiה:SMV|҅Jsܪ佁'ݛjc2߱ UF!9,:N0 F)Dxom畇rz88偉t$ 0Gw/z}gB]/,P!}bڗ:#47crB#.Uz1 ]Ң�8t .VR-;=sS {E=!1> (+jmpf{k'ijf+B^4ΕcN[ciw9p՗FR TYMn|vghCXJsg#.X[$iZdֵxPs7o3\&.Q{{sd eJE$r_dJ% nb5jIUգy 6T}7uc[:F֪6g¦EWBtZ8+,( _"ˬ=񴁓 H<qXjM[iKHg?ޣ5i2^ᲮMZ &}<&=5j}zǥ<>Mf|ވ2n!j *(y:t7G˕7iۮM0T/q%5[lv|T8?EMzcG|E<Nms)\{\TC/YQ5ف\KeZbX˶וiX;#/Y3<4e#YJ1{gؤ# m nq?ӝzo5+c/t#̫MAjqG̍lK̵lZCocoOwDU}fny)_ Ͼ86mm~2\S[+ڿvG >o<G"x$WRIt;2]7R~]4)|) [kI2uþ 2kU,pӠ4NܹoFjx4ZI)$%`LݨaKg  BE HN"Eͳ48csKLo篋[R1&Qt< ;j?ex@L?g(K|XB%3XޯLry-A�rGj׫ܕQJ1>=uS70-VQIDZ4$h9)eqbrXTVN53IAˬݲ>ŞoF.Z֠g \?܌+wgҐ8*s\}ĕ:7g5n?Yb-IH2+C <[0z˧ǩԬpq)e!+KUTKnzddzZbN۶ҵnV [ ȞCWގI z3G/2H4vzq!~w12 9|Lf. z_^;Rϑ~U uMzCBs-/TE$C}RaڮgjT1+Ҿ >Z)S-qT錇C;p%tqu,r"#,iG1nؿ\W9hT3,fr^x>Jq2�⬐*+W nr IydSwLcs/?6R2)`jn مvkF]i*d+RI)H$do2:Mdxx~TC(y.*f67�ogܭ<9} /D%M*Ka(�#?|9yj{D ~)۠1ص~'èW՚j g7v$!1 \ ߥKڣq'y{醗FS6c|1sv1%U-jm;NNYMfBJX W='zK5-}',"oEno />f)\LY//Wwb~o $} D{Kb^n<qԗ7Mˑ× �P`!{?H?SO;xZY@yޡ -/s5rO'x.wc^1rz[&CFYZ^g;^ Kwv>RP>ٗ KDP(HWyĘVfU韑le}09h[M<Ƨit_rٜBk Mk%[-9߼5']Ȏ휼rj՟bQ~@\CΚX2;O2$楦JFJ( ?gj4~JB)ɤh#_،Q SIA0غ|^*bcx_Y77ŪqL~$ĉh|HI8 l<c6D:''$':,N/WcՇWpJ0v\wK#U]7ab! M[ (:Yak-#MCo=CGlbYn]*2|%N5=)u _J2 #+SN8᳉o&fE=leI�mWb,Jzu(zK}/ߏ(낅:ӗ1!+Sv<ߘGXds5:ŭ8n7rï+wdMp&ĘTe2xG{,{} c w9ꎉdP-Kd5.P GHJYxW@*灊8SsX\β#eh<- hŮm%}N[emɈ9͟+q˱AzΟq˯}Ӹ~RNB9>[S>>zB.Cؤs}2~fI^IrzU[y?ĤR\?Қ&&,SRMN;k,%CQU< w .s=BXaT39wU߰y|}0\z\{CgW0kC;̵֡9{@u쿬9E=CWbhZ8)ylGîB�� �IDAT-ʇzqS$-7y r)O`_z]RIIEΝ�r|0~P#S&&Abeqe\67cܻ9 k ϝsYC>oXfLjߓ2V`iL&�,Fe՚쌓Tc266ZAcAŠ|>-rKL{w ) [3#gҧӳY䎄Ygh,$;̫Ӭ-p~!:웺kjQ:CglRi̲] 6QVsvMg9bі{̩S"CG4X5]]hdq܀ {_zI SfS;Pt,`ɦ]+NK4r2̜y$CH"S+˚Oӣz@/.x&OfĢ,,lqNS,++Wp5C!Bgt*--_CR* ׏nJnebdohW~؃ږ2P^t3\ Mi4f 6Ө)tw&U=y ib3v|XR)KW9-_lu1I*Lm >ftċADY}v-gf]ZϘ!sE{XLE>b#Ϙ6LXT3jt<0g?{ǵ7h@v lR~L+k5S^�WzL㵸Ǒ9.I!A(;mVhFpDJ.AuB?<ݽ{AAw B^ɻȇelwC �_ŝ 57od'֘rиk hA̕2y6$`TrbR) } $YنYm1F, JTbm3>Nb,nuҧ,*99~7?*  `*5r1H@x}    W/    EYAAAAAH,     @bQVAAAA     /XAAAAAxĢ      $eAAAAA^ (+IIٴ^CEAA^GR*-fKb:(9TqԱD-_8uv.;M"%E]I(_~̫\\  αwL>@q0(%qrJ~;=.M~vf7UbRץ}vU\ȅ9z+Ϲ׉LX+Mu@bQV^{)\?Kqi Iʭ3GY*hgwo<! 6$iKuloU^6|Rg4M =S_lGĺ1#at_+/36)Mn䡺yFwǙ6gټ,'`-Vm›PcXi4hF̊c)2{ժ M&7C5eQ;j8󝠔1u1R;A5/fĻmi֤9zf) e$4j7;b5|N"T"5yC&3[jژG#y2*ZiKN ݙVMмv ۓ3MߚƑ?)mfXZrUNCMQ(LLu^ŭ0u]S͐svz~Mh_/]_ӴI>1лN?.ѱUS5lHh~9_O'hg Ylywv]Xp.uVLO']$ DCZҴy[z wD=,2nO, |4_=h:=J@*\JbdBnҘ#80W KΎ9x}s4y磏Jl8zzF:=Q5&2OuRjCťU㙶τCüէ.e_ՙ_.ŵ1*9VEWj_PRq}RR*"!984INH$B~U /s|L;[{Odb@, |}"vPctc.*FrOA-^blyvbG6zO77{n_cF93{j7|4d#THVOc|0'ƀ F:'=ϿcmSz|>vrR_d%FVx:b49�e)2W(Mzƭ#v1LХQHSH$?zD: @)rmκ̺DXd˝vÆ5v^X݋r!)K`QWz 4S:$~V,jWV}ZRy=lcDZԨkkʏ}0Y7ԕqbxdyitzRکS{=kW2Y@+g}k`|棳N?GE$xtfXRIV1KdDΡW=uo78qWZ{m0_ jn:|T>}K3K|L &0" ^-y;x8PXS~ *1t)%ƀeCkb=<09ĚK=ɞE̡YCt" MmN͜ƠX2.,Z瑩c!ݘy30k:SĢǼ$}</[i.nmĎX\ڍKUQ]L| Gh Js'W WΓ 9`Wh#jNrZ4j՞|x.cPBW?00'0Ylqzgt`&ĽD5Vp 4jmʍ*Mc'-28ra"ijl@%_`B`}ەmyխsnNOڕ.0{yOW[37H%eک'X#^Jlq-| $hƬ̍=)ohSJ3ok *̑BHن':ц&_}IZO֧ٓN--Y MTx5Ġ5{ЬeM=,*jEx=~Nn9 [q3HK@PrnwtΑ??vx+A! &?B1/q_Zތٻcd:;OA~4v02T~z(00u=OVA빐M{2B=] 8_+w*W=6A4~tʵhmU׳t/;0k%mF|Mh,7o캫<ïk1o_S sk">X/S0zQ"g-O>!~H2xWk V楴E\|x9&OF6a8䒪=.K:GҭrWN x?˒8΢.ʪoX7urqdDM"b:/rPr|<"7bm;wk92D.❧v/ NeNO?t!%rfc$4o2Ú:!W'r?`>=ʫ:-L~ؿtK8D#*P .# }cI9s' 54=O?s 5 d3g}=TNѩl'MǯQ/ nCE:Qz Wξ>:c@=RrdZÏ`Ί~_OɪAKw ASyKA}P!}&:1-}cWW(c 괾e(+L=9KI?ٵ)˜LfApP\-6ؗ1$2lhaϜ!I/2MWi >dG8>-dfd hZP1NDx9vZkX[lHN;vD.p3_d`,T-ey�0\q.u͍LC;<0wACP8Ʊj䀒 PtXVIRIfKV~__OUNl<nS]lw?M> >ȄàA]nwq#%^ʈrm'rjR{6n4%a5;7mt/?k&!>{g59sjʋlXeqt;ȸǶ:fF^U/lzu:mc ʷC\pQЪ+[~ITb#ީfYkK5j Փxɐ1(D]YYc)M�ħ}NKY=¾q"yu]w[q0T牌̷ȟ3S~`B` , yV''vI[ƮfpEOy&P'Ɠ J~Hb6V^dPd:r-TW#�]q ׺PL"iѱbqNugQCST'Ŏc}:ұhݚPSdra|QA~PN2o8,5\:5nT;) w:Pqy YO;W b9J.ΐe`&(9q/-dT7ƨe4z >lEҥ=򳖗5Vry ^R㬜'#=(9� öpW#d[[T9n5,X8^/vwFs3ɣ = ;ʂ&TӜy&Mp7x8CursgA1Msʧu9z1#7}b׀:MUuw>uZz_=.:(+Sk/kR _!rx֤I͐LC@} QƤl�ʂ:6. u&iPFRL!9XBT mbԡYoUL%:b:Q=SԢONv<g'SN_ ϧgWVǞB9eF<�L<3)זiB, %Cèg|Lh}BM'}rCN$\*e+ʮlI66Ep e۾IkX�5:_ҋ/o8Vͦ_!]]ț>^Ѵmڵ^g1lRn:gOL[GmnjADt fیt͉Z}&}�-K`*'$={p$Vٝ\HڿM1!|vLIO'U\OUe hԅH<0#aSܹ2RHS>tcVFQwmкW}_8 C];Tc䝐*Ϥs㙹0hL:9kB+CG]W+SIw+~܇u=@ kH:=ÿIB-IkZY)z]׫-xd:>8\ r[d$<#+KɱS8ӹK 2u3F'kbU}RgʱɊO0_i[7cZ<Tѻ\Ǽeh=#>r�7 ȩfѿqYpv5O!«&HQ톳Gq\w/7+.uk$`͆[~U|UߣS;r(ʅP/,ɻ*@ٮA式d/)1=`߭^_)yܡ||NθHGhO5q8qeɦTW 2K=9YRG L Ƅ`2k#BhAݲr]L=q9NWk댁9ǥa~Ep xt]lH;yfV]9ɤ\mR9u2GMbQ]sbǀ𔮴)]y-vI>hpФǪ|W[D9zG=.Y, FZ["ܢ.Ze[YMa!/zJձ}xS'1iw9p՗PI&92#ʸ|x:Mf假 O@JE$r_dJ%  \d֞xɣӚE@{#Jm׎AN24`˃hS˛$h-0܍o6"ۛݾ<yoog GZ]hھ.'ofϣF{s#<ڎ?a!s۟1nnOGbǶ-L 6_0aP;1 _ʿ H[%_AawnƓ):v'ߏ?Oq{OJq ;K6nm^}�VSil2p+$  3tC?bnd[beӲ  ?xE̷9Ǘ-I^ /gζ]k7yqiƕ3iH}>_my)ՀңƾA#WNWy±F"3)ˇֳdg 1Ky(_[PjIs=Ki<J^5MB[~�`3|XLe>˾߬5Cӱ^6z9#ëJE6>g`mҔH}t{!^Ǹ {T|KV :}̺6k*/;tu??ۗY]i6;Qep~- QO>#s\H!$s1zmu9Է.s-Ӗ "Iշr1Śjz©(砋3\&.Q{{sd k)I�GIkUGOaӢ+!qT:-kYT?ᗐCO>"u@}?|+SxXǪkNZ\#?Wǖ22Xהs%]`YSg qΕ<3TS1XE^SQV9D$dZ;E8*s\GghH9:ƎZEfO?'$B<?'otZ'v2kp]dVnYobݷx#-k3/(dTɳ!dŅ?| |Ԙy20a۴^̞u/4rTnԅʍ:ux>v 2uNS~];760}Mj]Ɛdwg̰q|6qU:5)dp�С7b{\OA((cIH wǽe-I/3w#LkT'>tmw"6r'ulȒ1[Z'mem\,\P50_ucL{NTnT p̩&ND* &2SisGyo1։ps/|\uE pN{Y"qJN&HcbcD\R 9?jDYGQ/'r#}7PˮۇWQvLb3 -<MS㤍n@~f2uYг|)jC^ۋ̊-RfniG{لf~9# IBYp]0vo@W$1jjXǹɲmo<Va\ؕCAW&ƘFL>t-c}k1pQ;R^%殌T=GA!iQHHJ% OqSS:|Plu"[UKG#F}q~xe 8+dĂCd&8tcgrAyOc)eK؛Tf4~{qXc石%*Q:dz˪ʼ٫ 5} ۱PAJrJ2+oжȾedX�� �IDATsюض8QORN8RSt%KXhjͥ۸9̪?#x]U3©zuiܹ[{RY*x[f[=3S8պ}G͐INSs3d.[p}d5JKW9 \L0Fpgb݅Bed"+OɰjPAAAP䙽 :ir-foTދ"`̝oF|2b휃$Hoo{sqH9x O O/Tf/ X]/Z[PgX?RI飧HqNĘPFf7O!d](q "{?M5K9=P~xxs|:5v $,ܿC!Di;}25ߤ9vlΟ sr/>f)\LY//Ww;{ޞWm#?|9y,61.Z~I_^q+O9xNW<:cE^r6hL@!vɡ0UZ0ͺIhL~N}R$WZ}b8b׉b1'-80NYAxMe޺m 歩<*Gvl+$U=}ć5#veI9w:e*IKM)=:/sl&H'D(ɱI #+/uR\ߢ^{vˇrbmxIUR|`+YEI,1&Ui#o(~? 8N_C24Mh۾WMfQu'VnJkl=rd+{+Z{g,ڳm'{9Epou:5g\*Z U˱ 圐\XMyic\aVu7G̭P`n׬GD4R@PuzFQ징d(,L �愽?6'FӠީ ܰ{,2k2gu-eG-IL*UJN3l_1.iX黔tǎz]l%x$okT, M͙O}d^nKaW4$vO3!u,![N9G1 e 5w=[!kf\_?‡Sfc@kCՎ]6CL�d[}*t 4$>uӷNKI9{$V nsfF6D2kTmA[S>>$Al?^iE+ގYҲ}f/fj;ޫa؞ZH~5o~[ʸs?Wc3}(5Gi7.lcꃫ[(~ׅsbܖ�t]o,ޣR:2ڷ#n>lDVj&M$G^ \;oLߣ]u,unj:G׷3h(]+GYTIp=މqLv \ɂ# ~Ջe]uȀG}:Lm.'H|X77ŪqL~$ĉǠ-E88]X_VF+`~2lvY҈fU0MX@Bzj+acB7*Q@Eȧpu [kqf5ozHGLܿ>OP_eYX 71+ޱV"dž3G/xnYj)AGv4_ʇzqS$1xT˕<!N~itSC=h=2cs<ԂuE]v )1s eL^G AT-bb#~O"X38b,P:N1C0sr4@{ުzI SfS;?}FEG4X5]]heῩt�R"$Bwh1Ep8um` V@&T5nWklRq7> lq >t7lm8C9 #ޞcGj49_14,axV쩤"ND�s}>Z?w(͑)IND̾.Cͥʪk W%!"՚s-H]SSRxt/$6n`bw3tY3f\m.+/ 7p7eוښ_ui- \[>i. 5O|"in/% iVzu-]Zÿz3i:`&4g oN3M #W$İMW63rv7ǼCpwXו-(qFt5NO 1LJ14|3C_GLΘü"6uxo@:RI~uVr;.#k|C2Զ!%oPjd]t3\Li4f 6Bc]O#a{� NƶΣ>*=FçiӁ3ޑFKIAGәj%0vu*3{<;NEYy(=S~dos"YT6;iq-TbB3IB)ޛ,ۅ,ܰkPlej;#Si:Uk&3NSeoLA.ӔIΡ8k~/]Г;f"AmiVϖf_/`,S wɻ=7u=3Ԣu5'.Q'L22eX8XcU݂_X+㢏3e$Usfjm9foy G$%L}}?bx${;AA$$ߡIo[#鯢Sɻȇel=)$@SVAS1Wn&ԂQ_AAܿYx:[c~c[A Q8Qzb*YنY-bQVAЏ&['}ҫrwYF  +BJ%^~vqiH {<iP<8Qb4d�WP/b ^_     haU     @bQVAAAA     /XAAAAAxĢ      $eAAAAA^ (+    EYAAAAAH, BJr >Wd<})3k/6 1JJܖE,~>AJ?1^W}W(Ģ ݿKN!sl/?FEJv<FED.[9qB*m)Ϳt]+t`()b˩Gb(nbjcehfcI6t|$]_l^/�A(i)\?o +4:s vT-ui4 5M̱vbpmux!I\ȵ9u #,<ٙ[]VYuucFrBZ?;.%36#z}J#jL6q)J02ƙr5iսmsUsx-΁sP8ښKm'B䓛(&qD!_ĸm%Oaۨ&&60xA@wۦFIN+N zL欏Z)Z>4t3c=%x|>G-gaDȝ]|dN7Ų9mrR?grB?7#ߋ>~yݟHO~\Hdw7{u5k˵ b!zcWr(W]Z9l^bQV^w׸z>)Wb^mAinw/9Fjɪ5FF;3bnwmJNNKZ<ȉ-;u*wϱgJF;hUU*&36ZJKذ_"#r]~?l&F8k.e${~!꫆##Rx R-;2~JQc!նevU;~&F,O_QD-/eZ1 ۍ ߳CM=cw(:7.c\Kp/L97e؏UHyzD??2nyܞk>)"x΂u MnǙ|3"ّ}bcr-xb!/sPr/ڍG}kX6bQV^si7.qWFu25c�aP;(1rRFUpԢQ4KƳ(pBsFDNGǹXyU廟~r=LJH"7{iە#d5uz:0Q]=Nt MܷRfJ[>*./E�/gn4ٱU&Ls!ާeײlʍ*Mc'-28ra"ijl=Ci@zw}y+qF8T\|@=m1ܩ\Jv\:>ip3eP>]c'GI.Muiߢ檯`{%,hH^Ɔx:? 1. לyDn<X 5?{E6p7){HH@ - D&RDQP)(Ho/E:ۧ( tPN; dK .eg̙s9ٙI>^1=^ t`&=?NWk]]_tAN),ykwP} s:g0o=+d}^F5~Rq UcckM_pMb ؊ ow'5r%Clt &Nin?ǔt6Y?T] -STFuK@f>?g 5߫P5e.Tip]F )~ũڟU%ì,i5!dlgE'_仟zX>cw)m]rBⵑh[({}y:UsC7<>N~wS-|꙱Mk}5Q}6T󤃮g!+& Q^7|{%~�ev'nS|Z?Q/m^|ᙶA1hp>TG<8wWs'&�N,''jYub vJ@&#scL9{%  rbR[On_qX}Tdri ZZdBkX8f�wEhbL.ʠח1!~vy&=^?Q W[9@W1n 3{gPV$+k,% @AJ156J/nc|Ξ(nFk7 \˩- Y1z<ͦH!*ѰP>lEҥXC,NqvH"mmj x)?8H'>.'e2Z>^5$' o݌^c-yͫaj oda\@#/UDg^.n˼c\2.էhqdZ.b3[,OꨋmM:x ;3l@-IdػsƁn=1$X4~wqBNgGvz#Py�s ,9Lp ĩ141zx{fٱѲeulSm,Ĝ=cjVҳ:aNu2k]njPyꦡl6םki6V Gn;4MnetߠsN)SIEӽPI WĠվ\SKgB"9GF3syd@~#Nmװ(NKv#& Q*x#Վc�2yoGBl%=륽۩K*_g? ˇJ5_1)+)&8h;^$1+"9/shR+4gDs,L\`H hRpQgh2^*P^ɮ׀ga֭Ky\X ݪިY.3ʅM73}=:fhA 6ٿj)'z|դ>O*si2SIssBK׺ ʷ6wX3HǓo2uJa9q'y-wY7i78َ!Nmi hdIaGOE<c Zmhj&$mlj 8-?DŽ5pXlBzB<2ؤ`(>ZCwTSs7ݢđʷgJdOWJQwݵnL/MuPyRFBo&n Ƙ`*fcטٜ. Cr4 ]} |E8RYӺVzɹFUua_+ǂIB, %jP%|Ue˧7c 52(l/' G:gBMWyYhe[2q|/~JR($-ws"x\uKiQzU:nZoI܍;$!Br h‰C"x>99l׉ӆıZ|q|Ssپ>a&9]vCN$\kwKG (|!Uc0CwI_#piMHs]),Ղ50WJձ' ynEr.ޞgy 6V{�Iп\LU4pk4u]ؾIWj(4fSߗ9e; KktПF@&wf?9}ɒfh2,F?O8re=%Iv÷Q><JM,9_ѱ|3!;`m$<cWxSxƸ%*p:q 9f+"^wRrI2WR3Չfs5KX4N?$+<růFg]ѲMStiCL2q2�9vvfp!2:_79$YQ5eX0|.2{Xw4z4 `eED,[%X+dUP I[8,7}t}_~)-u;'ͥw�[Z"J٢վ99D92.b`|_(Obn:U{pI;j˳RWĤ G8U~_ VJN`iGln] ON]55fW] Ȳz*{*7Hs,̼0FQz\B0 Ƥ!MSآv#$%#O_I3ZKTTsͥr]`怗oO*W Z;&m{ܙŝ8,gUsg/D*G* t&|,ϸt] 2搜DL~KV44rFqL_uQڦ_U Ԇel1Թ46ʮ^%=h42HG,̈́>71u}{4֥e/IؖAq-BagHl\&O.4&TDr#+Gʁ[lɩB}r-/bnٝz4Qq]#�~_: ۰LYׅHVXazr ]'(I99t֣Z>R9:ߧcŤUܮw5`qnvލ銉ױ"X~'~7#pѲ&푖zYcӢ %Zڼ5N "&W2�cʕI%:+W ΣhM1pmn6d~) 9KٓB5PJ%rw<v<*g 6T[�� �IDAT?|M8u<wızu|i܊ER>@2Ee ))yۥυR#9S d'Tȸ9I!\VW_ >ݧ8NsBvdZiI~n9çoT/ (G:*'&fHTﶴj؉7\ 9%Nʍd\~L nQH]uѵM}⿴rؕ7n"ʚXs+3$a3~1 m3d^ZǶ̳, P8Q13GO㜈1%ju,WTeXl˖-cٲt 0¦Oi>�M?bBXOt)-1V8+ϱb>ԡmiYAnV"9G&&~~g!WLha^37.}q?EF Bꥳ퓮e%*|E)+Q.-;zK8HʑpBc]<EZ'q9g\(sL<)$6u}IQ9yM:^خD:&;4'{z >$"@݃ Gɪ)πu#VуPWT3IÓ_.n`Ҧ*VRnsjJNδ qCi媥�7*V0gլ "8㪼Q]įseȫ C3X0!޾xVnǻ?6Dū19˺tg?kEO"+ ks;VZKĝk>4ogCNܩSXi2H_?9ҌЁ qW�v.HTKK9k*tRr \ǫ&4PT97F!fP %r77[yV<QL٦.nʂq;|uE6=>>bX"!{}& m]c3|P+uxb&U1J{jѧ1VY۹G,h<5 ͝Cl=38\C6 DҺ쥠kl3|hm|sz4Mjl?IN`\uH+ +O2W}5ؙJ(t)JN?KѰr)V9 S?ˑX469Q^Iʍ;18{_WΛ*Y^rD"9Gnesd]ȬQx\Mnrx+YH;QCvq ߮ďk&8͜ミAL[$ mSBǠѾ-Ť 'e  :5Iʗ68q)2$E\!xTk:E F71r&$#3=֜/浣y`\1Of<l̐EXzn易=)V Xe.#V%#YP(;<56eq;> LmqFrtÒ 5 SG*N!|*Bq)p~?ًK?!Z5a[2Raiz0SeE1zCJ ʹTf @H4ޕ}S61s]m~urM)qr&Fq Qѩ{v f]',a@%yp65ճ|'k*)ʹk@Tn*33dd0Vt|ҟg$ԦvxbD]h.bW&|<ޯ�xL:DwǑx8ś&1lqJs[|9MJx'^Adctׇn߷&ue[ <qP#>쥠sl݈ɴ{wF11}&[;I&QRMrC{Al޽#?̳G뵽['0M]<$=$sCyvΡ̵CiZymEFGNf$:"ٱT{cQg&X9KsKI!AxA G7[=    +|F [<]YJĝPdYF^GAAAA ҤG\e6듚3m/1![Ĥ 01)+   KE}&~ _>V$&e (oI    $X=w=^!bHAAAA IYAAAAA2$&eAAAAAʐAAAAA(CbRVJPAAAA(&IAAAA 'fAAAAAʐ&    PdyWA&CK2駫 Z.'s~bq1<GrgVp?R} ]*髬AAϋ6>8~_:GVAu吅)zBvr9y??:~IYAxݽM7)YYګ' I-D.Ѩddx6xNl]ö^Ĺ,AC!'z~;[6ɡĩ_Vxa+v+vAφ/"~s.&$_7gYӹ{\~h`_iY?an\ӯxU36h@^˹M1V|ل h2/V'iyW@Җ#{H.5R\'G0 N2MC~1ۓ4sv //\1.ަW޴ x8TviU sCb(i?˘8etVF.?Vc0uedh@22ޓӮkyyqIæ;3+2]h?c2Ůdnl6>e8'Ӭ;4C<niw#?sj Mk>y:但L̏{4q)4 Z҃ WLb[9p*|ZA;* P+MPm[6tg^Ŋ>OB~xMsaEbe|jާ@&|oLc5N@亙tkI&䣁iVفWp;jw :;eΓD')NDOZáLcT{f_GjҘШ.g|9j{%6gGr?Rg\ >6\Z3ޠɄi쌗sFFOe.(X{>"yIYAK軤\~v։"õ"܍C?)Ljٻd'Dkqe6. 8'›Q(6WFyV Vjݑ{x`E/BRs=_oF#F=WVbu-JeS%4$'$ہqSNJa5cpi7 ϠBT&r2$}-$rB}u w/s|Vo&0[/Rc'fO錟>kIMG{&o:8y 3D9t~eOW_t(0-gD;~6<?k~d[|?`\Kq][Gwo�o}L}xR.gīrF1l]j|OdJb;yhm'].%sx`&/g™M(TKgѣbTW: ?SSIUx1zm<sꭰ9/,rGdU?i8}&u?{c~ NDߡ;oU|=<IYAKqۙW._;=.έTTA]ٞr/:;Oܓ~eٶhs۽Nx:#1.'wm8_T'eDz$|Q Ic|w _w?]DR58VjHD$;*6p [ttVnTi>?i^~ȹ- Yi/go%6ݏI=Lίe0 z'Z=9<WI!r6:4x}JD’gv' ݧ0[EXp1Vƶ|MZOڎjwk4{> \+bz(('n=кqO[E8$+ Ej&鶈j=DrNFhwCgt`&=?N+0Z~؟^]s,}2zJ{2ݜ+ejy&yǦ411csp !?-_w;�ĝv?L j;jӰ4]؟/eq  {?[,bq 퐹o"&m$\,#T^ˆ0P86z,$+w*W פo>\C :y?ũ1"P钕?8~[OqI6 3|q6w41YYj7-\iv Fm 8'AZYL+N}z ,?mĬw|^m̀ꮉ`-tJS4?N:](C:EӉ7feNThrR">S:/5۰Dߴa]7B^dfW9LLG3gUpUͯ3YY5�%곍jSEucmHd3?f!<tMgZ2 P$nS|Zv8L9qh"_҅t/0޺Q=h~+ɒEkua%sENyT/9pGIА`46~I,Lyjf5<w<n MQ7rgDO$sjfV)Zn۹]Lkn@j?PcĤ 0I<yăs9~51=+2n $~2zagqjȲ'%gΞ%F $Ăw\GK H[k7׭X/id^dCXC#YO1yoRlfvnF[F ,&;ft{߃]olәQ|P\G%`ds`ngOdryP.}@p u88'dd1)eFo17C Py�s ,9LpE!?⡃\̰(''aG_6?;ϼ4\:y#`dU#~-;9M\y֓VӰu3]Jxdb3x65 ZO{} 1g�֦K:<̖,=rf紥}*-8`#J49+[t/8u7f3;FoqYwc-n :S["O  ;J)5%պ(GUh?_]\sIrjʗC0 DŽ.,\aߖ}6F3,-qZ~NN W%%t{\slh@R…y˒SIEә*eJpJ :ln6Wb"Mi3&f5OC*=洌]/n^io'8#ٗ 2Ipݨ"mWBKhI䎄m|֚h)]1#KdЊz UX1+/bD{ƙB'-K``L={ g8u#B&Yn`G{gi_AoW̽Q|DDޗj1EkV�\<ڷ#!^5V' Վc}RNEքZő~Tv x@|y<dαr!vynh7%l|D#N�J*uW0spDJvr OkWU|QRs۫'V QGs b%&IsJp`$r _> ,<kѤVhfQשYzQ%ФDs*e<LH+;vY{q&iZ~ wk؄xRe_dCxpN9sT!l[ 5‚1&5ao6B+.8MBW$P֦oʁ><{'\ OSfo;1TCaj {hop=QwJXh I綬kug9kT^m+o}ζU^ԫ1ݬEGkPOC;{=oFl1v[{"Rإ_` mbT\`Pҵ' a֮Krwnj׹gC*sx='٧m!'b[ﲄoQ(ě}Yx $ȖTAՊH~?f^5 3PZ!aqs[?~J"슺} x>8 f蹤 Uz0êQQvNmi hdIaGOEma%NŌGC܁ycA˱m-,x%EǒҫUֱw/Ln! ^!z4ŷd,wi|,q5F)-$đ |᧥*݈ԟ_Ϣ_4aιd:5t<R`Y&>L3B·whEhzRnE\:cdbz+߭z[zSc5$:ِv8Zaz:jQ}N53@W{}yǍϑ7Jc{">a&9]vCN$\f@ǚ֣zN9]Pp{8׭RGI9||}8*B^OL+` cPrώgģڕO/*{O||h?)-_Mk1nQ:c ԨmRwfn S^QqΓoecTQԜĐ.I/Y"T8[${~KxjA^+S?q>y(V$ |ч$5,Qلӹo̹7[�-𺓒 HRAd^W[Ƿ':=f-Ḵ3+INΡ,\'o#Y,3MP2q1Ś{idd@3H$+ ̵t/N}+DDٹ>Rt? 9k4ՖxɠɴRoL?ZAa kǧN9R`&Q;L@}<Rm ~LN' cTľD]#[ByQtús[i5ǜG #Y{♧œ4ĝN:x\@5x1v"羭s[FUgFX#()ˇ7t|)cF(u􇹖8-.;jbLc#FpEIsj�ƖHAv59n' Vܥɨ xfʞ_PXˤ>#w�c\r=\ә@])?9hҹa/kgdtW 3s PŢ3==wKп\LJ%Z Yr4;zݿNFͳs2*=j`#2uG9�9i4<ޅg(u8Mk�1;|/;vԬgؒu8kڷ~vQW4G%9ޮ1ƤX9N1:Hx,/Ur(YKP޼dcόEINE$&eɲIzoB3q5^< ,:>ܺ3# }0B΄ow~#ΣBS�� �IDATH)B?k'y=IFA+W=#O_I3叿QsBÁKWIÃ-tsi42H QYFh0h$$&5G`P}k23j>O̰?aU+F7]x<tcҐ&ةoqlQPp'Ȳd܆dta$){\?a\6VSnֱX[WqKi?%*"箩BQB,A:h_َҲWLZFc]+9sZՂ0֎IFDc,dqgDN9K|#o wǵ>=a= INP-RLI8;o#[rJYO^,;)ظL\iMh_ii,#&`x7;[|߭|C[ڐ.*T84ߠ#Lz,o|+{C¢P8^sWtGAAoS7u3S&GR*ѩv#j]}yFԎPk4t,$%+ߨwx3-k-o^AȞ=D{6YŜ:G1{خ1i9VsNPgߋw@ Ж1P(rQ<?P=~講س./+%kJh`-\�)W'\M,|/:I6q$_N>sQِy_G9013Erx GGVN�$T)ɤxA-|t!H/dz~"SRlW岺2ohE�_|qxzRPKϙSQ3JI9o /<'@w??fx?~Z~pF2.x? ry_J{; |,ïcg&Ϲ@H֔ϟIѷ]K ~Un'>ZF9HB͝^ :~d1tSzT,\@k+J*\Zgb'zf#ϙ!qKQ۴IDXʞ$.nE97I-njжx6HIU %as>~曐2ϲ{°B2g9V,ۇ:--+('ax(WeXl˖͠k6\əI)Z}8'bL Zihӻtc>W*?t_a*Oy㳞zϡ:w<v<*gF \^kL`avmԫjMHd;ؘל;YW{FM:s -RȝC׌ l~COaQtӢ[4;ώ;|58 G)$uk3h'gMkӤe^XLbrgN]EGU<LKy?XhGSA (Ѳ#~\!):1N=sθ"AQ$]xR2SIm:ZiHIJs4&'tKijC8�HULJAed_PAjz|ʾ^! ? *}b ܎w l3W?+ckrd޼Yќ3?s!/{= ZVR7qQ-`DC}c˹+YqĂƣr&J 3OG60oM'YD2fydT65% _U2Q44N&tg] f_Jx0j~Gp 4 bhxNyDx@yM.}z².;#Zѓv<Ȋr _9֣j9c̥8d@lL^[ 䤛:vOJ\*Mev䳄XĠ:HG;j!j["!vXL@'NNhyx2vo' 5ޡ: WgLZc/Ԕ#A9)sNa 9.H3B6]mq20v.HTKK9 XjfMڄG21Wq'gy7>4W -Oa鄗e5ؙJ(t tƶ3ݏ,^U>o@WQm?-Cڤs} \zJex?u.A[emȈ97ЌJw/v|Φ5B1òu1�w&_sCUY?u$T՛-+6!od޺ڮdW'|ݾ33;Ca?FaH+I,N3S=MѪ'[q hđ~TQ9wf]pƱW印^v]Ks=a^w 5 {<Lxd-Ts7?XGTP_1M!#',tSbRV2y\W.~+_tiX[C\#: u$K*)ʹS@T Rf2i2Nʆތ1s&`ӧ6zΝˏ-)|!Z5a[2Rai$�Kj}:&sYn;$+`l I<2h\Y]K& {wBQy,9Ф{WMu;#,mO  50z3{=&63=#&fm#OIau {we3|Bhm6냯1TFenJy.`tZ!Tǃ7៽h=)V Xe.#V%#YP(Wr *?YXy7$Kej8e?{71V$s+TOo;#ʌqX֥M)' ;eU_]$\p>H F71r&$#3=֜/浣y`9=xwɈ3Yig4ɷ:MK{Z֌= \+'71u0Be툻_0zNrޭ#ƵũKYW8o: KkI&4qMh7b2/1|O ۏaHxx331 N255ߎj/Ku{zMb Flk@^?O;A^"ޟȩ$\?ƍ{N+縆*8!=c*vTy,<!2 31g"_ުgyYhuYuճ叽x}Guaaњak4ԩ7 _-;ښrH~0T=P۪ kgpQ[yޏh0m'gAd:Rp:[<L?%uW>X\Z`q#4nΆh*}[u/M .Q=b$p痒,/Aٹj} �uVʜ}pl<& wmowBIǃ  B^-d~o|vJ b'ﳡd6~QC?r[r~5cT)+RpsE4ɗ5  P b Mzĥ_f>9#ze&Jw_î~?B υQ1)+%LRJCPTba܎KCVXO'Hs{{+F  S䷉ϨUxu6j?KĨx} ܯ/eIH AAAAm$PO    BAĤ     B     eHL     !1)+    PĤ     B     eHL     !1)+P\X-ˤ.;r*/aK`YD qhJ Oe ID~z<Ч8.AAW@$8_[t%ranF%>('ql9=uZq/?r*SWmg۪ 4q\Հ&+wlBdm4WIߣdRgws9busRyi4[Wr:w]1JAA -GR]jKN*QgaAn-l#3= iЉ{ť~R兗5E !b,k޼;|T<lqE]PՓ\Z3ޠɄi쌗sFFOe.(-־Rc6u/e-#0261pCl6<_ '16Q9bQ>^>&v!BYƘ2L3^7/_f~ߣK 6NxԢED/~/Ǔ8TviU '2z24 beIi׵<T]al'4kK~eŴ8,V g P+MP+@NOGѧ ߂2Ű<xcq$ ,^r7%NcNi\79q-א|47 ܞhUNΎEsY$IJ*Sp(XQ6͙ˆ}m{F/~ e楽AO׸}+Tw=VupwOL<u vC#:yOw3uȤtLJsDMĨyDquM~ G-'SSÐ!,bG *.gvĪ?`)Lh8}&u?{gY'8]#E|=27TUi׶2??uJyN0/Sl)l/ΦH}F:1<' e97(n|!x.YEk Yٸ7b4s%&n4 ؿT^5 [aZwX'o2ZCrB"Y714>_V39.ORr^>o:9s+n^-b+F|?`\;:mw6C Jh(H޻AQiҥJ A)RU&P H/!$Is8̽sٙg̤8_}FGi.:c:uKʁ߄b_Ef̄$KEqM?B|N|ؓl^oZvV[*wg̊jܓ8r1CwzմR 'b? |>ulR 6_G|:;Q_51]>giL]NNm-7cr6�r B*L 鷯q/[z$ ,aMC-I(Gi ͥuXuњqi�o+:_UDOKXdaVwz_cW>GW/`SJ*{gaό1*ӛ1ɘעa)0JţByeqq4V_uǜy 4z? ~K?ei!@*E_�X?&#+E]CЧz]W`7y'cp$"~#l\+>l~fT;,;Nt| GaĐZ  g"vIgpno)lp$,u!$<& mS;ìRBa;,stdV݇It0w aoFIʾ4Z Cu,zLB\XU{:1c^p[&GbDd O RNesԙj 0i.8MS)vhG'|rAA9w5.n%X/_l_oԢȚL GjӠ.{-cbO64.^!c mi6VNby냜ĩ53Yq T{& e0NX~r~Lxo<C1%R6MSaS9-݈>'"%>}= ^Y4v^`K*_Cƴ5aq2b^xy#wA'˃нr1׈Qbdr?9~/Ma/*?`>^m'-V{1ty)b`s4WC0�j8$qi&A@S!P[ɿqo=n=Q�Cpl]Τ|Q;xۑiTsd`*'! )7J.􍤼gCd<C6;dLP` K/aidmjrqV,#{noSTͅJ66|5gS=É1U! 9d4vI}MHv-k=@2KFhk!Mx<:=3C"+W4 qw/ dL=ke@@mrÜM>gv�6u@3{HHX e<_/`j6 ^(W`]wtkl̴H% g0Ώ\ '6U/ Q>>[JU1uA bN#'偁Y*T*%'E$ oGCSs,wz1vd8 c̈́X5?xµD&sA (g}OLHDrG2a&m l_V|[QA,a^(#a4\6JgI;z-|@8}F.nA!u<=ê+"2]zy_8T/}H21XDsf\B1U{#tX=Ň ЗsqnZucXdZ9c_ƍ gl+˨ȷtl:~v㿼R`n[+ +Xˏ^WЫ ^ǞS72]s#t< ߶c^ !> Zw:֪ʓK mWHM ? ;87yRIO&b8}h񗵗GrZ icf_+㥛ʍ뱨B~ e|~7 PJX!(k?_%)'"9"y#4]=/Y4P]+Lfh\UR=*64$\ž";0=~7ų@98Ž F‘},/j;)ؼ=62e3b\:5ON]UQy_e ^2M#w}Z{z\txMUlI6m}LC ygT:+dRhyQaocQQo8ec|kR oFtl<t3|\:*TMeSBj>~O:D::[> Z8_z)%Ē=iT6_j#&vVgPךX/%#14 f!Q;p,fxıbT*%3ũrN}OF߃,e$%?v{}+>*Ti$޿[8g62(͸x}s;<T˓]SfPG?K]GjC>Gۜz ^'~g $(W'Եniy&)JCC)dY!w'߳*%S1KcXt؈�eB)~V s,$œC9+v>Hø<=M㚆\<tgЩ,P_ԪlmWk�� �IDAT}ddrc?A2UnA(%Ijxwk ƸnAӚ*^<m?ą3xU| L{ VUy=iC%##(* z-HIW̨^뿋h)oN\jxڨ"eN.&*q=-y]h6?9Jlơ", "nMTɫJxS6Ol l\lTd5M@3P}aTIUm'zhݦ MPC$}{0ud#̟{KƼ-\f!b)<TR'T'+ѱ0F߬9\|6ðL޶⊱D%\XPLNDzN}uЇ٣aLVr,'r|./bNgMzJFOy)0r{^S[MmWqQZbN$I2!p1)2;rv1,h°<5+6 ~,YCSק $ÿgXGY@|`AȤ="&ˉ7-_10vÿ4ro l5�cc4@Ksf?A$ҵՑg)] `*fw?V #מFNFJE$gfY$$s""6\ ,rחLh8r+Hh8X롯YOKtDɟFOm%&X*(şRTd¸d1 F' FZmdd~ TnBgmd3N`ވz>Y2ReŸ)./5L5A!BK 传`>!N6uys[6*BJ2rQeJK<60F7(\W�MAָzx*[5;͛V,p2Rq q~XTm^LK]~1JG[E1ڨ4UKśJB\sFeR@NDK:B/_-z(V/'ܣ4K)exV8X7~%k}qBC =meDžw8pؙAyv4-'lIg,b S13QshVXJIgO@\e+zI;ɒ?} c;9W2z,^6(F9̃2ss="Eaٙ|@s BvAxSeFT&(c~# ҤɊ&E ݸ˜9y/ChFǯ?:x-)G6sL}J/${ɝ ?ܿW.*4gB9?K셧^*o`8Yx{[]RccI~:A|Dž#|1T7h3 z)3r˛7.彾片?χZ_�l+UE[OH8fw MM,9UIJRꡯ)jO?L!%t �ɢ][qjrB00GNM!Lʩ00#$e Υ=fI IMSӭFR l䅗o(Cj܏L^pDYsf\Rr2֬p=ZDKXZwH{M-m]S_aeG \|EIB" _zZVZŪUXj=1k<|>; ^#f=vd~y)LU*U8SߪH2] s/Qz.vZYiYI P* )+Ѳ ~o57_Nr2Ti:>E|K f,4PHڜÇpC{B0Ud{!ƹק{'/nw&hO ,=KmT&Jğ=ћ4G|[RCmrL|dR.uM g sGvp|&2OjVk z]5#?8n#{}^"$tyߝ/m;xj4:n_í7f:D%(`£K\z`k} TOw/; U_G6LA&'Gq f+qYlyێdi-G|*6GN ~vNj:?}+.䵴>ZX9βr/hCߪ.9̑S~M(aC r''GsyLTGqg3P%YπF8V [#&R:qw.r!6k;faIh 5qqƅL<#:112'3x%cx1*~YW3MuE32xɿ3jCpnoX: <PoE/qBP^=`O>}_֞Gr%LDڵI C[\Wb'eb:ɏ8G|1+[׮=08ҮSU,tqK pj' ԽtӴߎp\Ŏe nYaMcj\f I܎8ޟr~PNCA([.olXаKs,xR]/\aso *e[3_wh&YeĢEoX˙!,�SkG4{ d F/إ:of/ BaM=92ss7P˺T3yX}&e/Oi2aS2J=K\;Ӧ`Lm. ɽ藌2|\k%,3|ju~V8{f,a΅[ddO@4 Ϯ|=:y1fW29m _GsٸݪU7WܾʸHܲwɒ TРsma[P7{&PM^ʛS2Θl?L=|;q3k,K#5 f(l0`T|[70@N!%]Aru!31w^�ֲ1…r!ݞyK1Liafmd3(7+ӥѓgw=,1rB6n`+1L+'o5I V;Gf+o#t9.ŸP-z #33Onې 0qƻjs>[ԁQI[ox.˷Mg ͱAS-f[k;%Eq3ʣ?طc9Jtٓ)SS ͏D\ #qȷ.0>.gj\~4Qɺ8˞(a=eja[æ3yu4# G2?5:NdtzHL/ $Y+}BP> !zٻ^C7bf@j]_p Ɖ?/AAAA(72^dNhnxDa~oW ٙֈ}E@VAAAx# TPI7<(ѲN 57   o&Atp_w1^*}ܛi$   /AAAAA(C"(+    PDPVAAAA     BAYAAAAA2$     eHeAAAAAʐ     !AxQ8N7P}+XZXQfxT/-$6%Wԗ_ج�.Yβn   ? =I%}ҼZI\9zSQ)Edcs 9Xٿ#3fR2nOڪ Ҹjn@/k6!acl&;r=CZuxߞGY1m!W#ϴQ(mMV!&ulG+Ez=cB8k#{.<z-HsAA. Z*9LjԴ^a4"!S U]5qr:7I�+go5 U?]) vu#7proV5{ܾťqM=T(qX} 뒭c?g vf ʰ;34Mn,։*z2a#2U iabOtى�k#==ֹZVۢTR7-3?f˜(�dN-dW{6}1~Y//WԱGb;8{=ULhXV`y>Zǀ&o8c]c Auh}[X*霘!3/lWڴї6:_L'y*3Pj颯(%ON$|*>ƅS|ܙ 9y. f.Z4tyUR^kvq2 nɀacWؿl!%:Y Juh3czִ.z]r&-<j-Ե_qWAxTs`A/&7cHG +qJ&LG*_i~uG !m:i?' yus辚W.m/M)bǼsu9-G%tcx?{3b?_ xߙp>w`^̹4;m]|3wdЯB0 )IxvbXHwC[70|-Q,fWXdN/a{4i/3 K}"M!~#ImƳ7gj"tڕ0񓆘=7 ] + ?XԉɟbL'1&v1] SzR6$DܑbL#1Ƕodg [@ *6^ÊM*aYw㫺hZI:dwjLVQ/]*6~"zxƬ/=#+3KyK?$1qM?B|N|ؓl^oZvV[N|ؤm> tv.l%>}L_K.($ICij2 A o_^ HjYcYR[ /([aQ.K릱5g-Z1$ZmG {Wd9z+VV~X=Tݓ<8[}fg5sn8No^DǸ'c^փ;Ħ@`FţByeqq4V_uǜy 4z? ~K?ei!@*E_�X?&#+E]CЧz]W`7y'c$"~#l\+>l~fT;,;Nt| GaĐZ  g"nqܑL ̝iZ6 r2vq,>-_ 'q6fDRFڏn 8sqga$n2J=Slh,C[bT$A4T$NɊܼH 3Y-EylMnf8x8+pމ$@]U2r·JռU׽|Tb;:FDDt*4:�4 nykaVbl_8װm9' >L"]K0- 2={v!hKӰa|r0<XL}MSaS9-݈>'"%>}= JYW�AA9w5.nXw%/`!cZ8�[/< Y/q~FT>O{ c¯ D0h>`�pHҀMl9փ&x:uԚXsM;'ǽ Dx9w9e?S~|i#뺀Ռ@}iih;0A F㜾@Gwxtwbw/:T'RifXi29xkExDZAb(4ż>_o[T/blmkS{l#a#/c\BnKь% >5!!U,.?I|ꮅ,7LlD\AnSYL{,�1Uz s H7}BBm�ZT1/[#!a`m|D@b,xY^uXTnNѭ1",4;?vs)B?~emr|^|)ƒL\FfIRFe F|DPXlR["=̘t�n3'ߌ?1WOU7 L nV yls0V8Zw`ݺS8NUwP(EP(HEֵr_L} xXΌ6(4]nocꬃtŜFNh?z\oǹ㆜ʝsgЋ#0Tq~gk&|ŪE2"SW?BS|�3yzϱ/Fayx eT[Xp6SlѺsHt#;pϰ* ھS^)k7H˄XG+UK_> ^ǞS7_ $ R`U~!eOS=/ AB|* G�prPI%=w?ϽbY\޼| i-AYRگAY9p*I9ɩ<CԦIyҦj\u7`bO5{PFs exT Wi'ټ*m/Ys=ɴը/)پ.=VuۏpdˋN16o" m\�/%N|Gӡxdajv6U|wkWB }uȝ;ījc,4}+<<nSU0(vM[`e1LW{IE{B.v{?;(N#'=빠RFOŦ͗j?>78[a\yNIWuIL؋]SfP_{r֗+ЯJnA3;m8;=s7Otl<tCg2M&>W)՗U;fcZY=}/GlopM#IM8/qCϩ !rQ' pt" .c>k{/0ftAdns+z%g.ӣ;\JZW9}AQ2’M|ASI+M4? ڍGJ¬f @I#^6*7+ GP/]*-ba#ZNj6#qy {5 x&AϠkz̆p ;c7_dE_q or,B)IUkM'sC\Kwŧ0ƥv tPil+%.ǫӠJs\L/IS* E!W釦kA*NGfF^]DKs2W@TQ,sWu)v0Q}iDB>Qb0?dds1ePɫJh~}H6Ol l\lTd5AQ@3PB1QdR` vɃj(.r5Քj!~\]#8g?LfdSW<64.m/dҬ{nm; dɠ;.SP>sھ=:O)LpRMXn3Lt,m~Gȟӛޣu64jnqM8/qC2u 'a�� �IDAT$"󚃲-D$= bii�"Cũ+>Sdc<?sys:m5?`aXkbob ?銫 ϟI@I=<ϰ:fy{'(,'"\ ~Q|TۿR=~֢SxA7 J׶2VG JVv)2Y46ݽgZY*\^{uN8)9y )g%JF@ 1Z$YFLh8rIh8X롯YOKtDɟFOm%&X*(t6k2,zOuG&H@lt9`IF&WY~> ʻ:c2;T -(_|C*%JI mu%_`H/?%,Ʒ,2$Wa}M^yZ0) ?z"bo +Qϔ-sBCJ%$!I:3ٵ}?̦7ũ75T Y%NU.TbۦE $mtP̗vn(VŨ+k\=<LwUanY#fxV8Xjd`5>UvH簭ЁVXJIgO@\e9|<ߏi'Y2gtal'Gj\T(a)\E`b-A,M ^nDe:X{a/27�+MhRtЍ̙=fd{Ө[ْrd#ۮ>ԧ}2H7k\~̹#|U3i}s~ OTN \q(p{[]RccI~:A|Dž#|1T7h3 z)3r˛7T^VCO/�vJ2^ ?q?2yqe@a<})qJ |EuJԿӲsǑ F2awI%ݯrʘܗRJ3i(#f2lunKКU6WߑV/b]I n9a޳rfQ.ɜ[4kYS/X餦)A[^h\VeG \|FKO!'vd~ywOs&V**�W3vFz6 Fr#�Wm@!^lߋ*oN^%^5 ?bLj PUMA(RV5enI?k7go~j5(ҥ~@|C.XE-.'FlZӨg@#isV  tTAXTf\a"ߙ >17. ƶS P`n* GozУ:{oJя]0ʉ&2Q H&΍a['np0'zjWg"xfׅY3Cn>1H!v~:Jg'<L2Oy(Ҧ7F*Ϯ+u>ZxcIT2ߛ ֟)<ĥV ']4cKBux|rVh]恒%ӷx|q"3L!9󘧳LKֿ n>S>/ YĺWa}MmjƎ{ On="[KLZξ4K|2/iLrx`k1౬a`)%^v ldTjƹFq3"3n##!p2g\0#"I uO?+V?{3Uc"z&SX]CXc\<U&)D >"'Cݲ Ka{=_C }_֞Gr%LDڵIҮSU,tqK pj' Խ4q`ՏDtcW:][`j8bDzh,[װ15zV.݌KƾӴ\Ax# ybA.;3N^8Tn-e[3_wh&YeĢEoX˙!,�SkG4{ d F/إ:of/AaM=92ss7P˺T3yX}&e/Oi2aS2J=K\;Ӧ`Lm. =񗌫2|\k%,3|juyF8{f,a΅[ddO@4]zt/b̮dr16Ż5 qU{S^oa ?XKO-eY95hA .d)@GғSU6L$>9̦JX"ӭDUD_cS2oĨ-̘sx,`Qƽ%&>u,W%4Kr-#܂&ZCdMt<^ r1*iʸHܲwɒ T8S@8x(Ju Ϳط?-%FffhƷ÷!i`jw|-C.) Z:`zvc? mMmp tiʛNEq3Ryv,'6Y#>5{2e`wj(py<S3æJ!5ߌD՗_rq9 "]Bar�ObVC\N5l:C�yE7NV~hj?9IS o"I | BHGhnP"''25bWQ/Lf8 DX_|k;tFL}ϐzP41AAqG" 5,>*?u!;1;Gˡ9w2Oi8]ƵJvkehb  x| Bщ/>MɛtÃ-tݑPrN,4b/f˾܋OGַſDsٗq.      U1     !DPVAAAA     BAYAAAAA2$     eHeAAAAAʐ     !AAAAA(C"(+Pd"v/eD"*+'1}ǍcVi\ݷ{USg9~uE{RAYAs$;M"'r-j/| b.TP9Xٿ#M[ ~ ][5Qiv^dNуJ^dc+^`SN̮H\T )/x)}jyZ7<Z=]�A^Tnsz]i%4iDECN4stZO&{D :ZTfާ%ZETF?7gƄW꡴ޙPwC^%Ər2jx?&a[9t6Z[S#hoފiˌ2=6Vbꊫ):/uPL}rn>8է[κI:bA3&SE~/.Axi~֓83L7F:BN�V%rn\l;d]iXp$^gc񳚼}wb:oc`cQ6oe]L}k<[2`Xo2nB8KtfivPaS=s9]pm-<jOȤ8r221A~ˏٶ`![\%N6ã{ ڇzͼq_\J K'4ؓNջ]^ .Tڏ9AW1mg2)Ϣ}x)oj;5SA6ѹ] nr#:q԰*恲Titxd_9MT$&S? LNbL$bG ĸ׳7R )*GȷCN9tr)u @~|ٟMySz~/ 18gi1N *zbSf"ڼ,2ѫFzKIS#~9ݙ5yc;Unʶmj~0Qs }H&$0"B$p̈́s;*ycS<,ZU]tPc<cVPs|đļ/1j~VkX 7Se/̸~!V'>vI6/[ͷS-Y;-vR 'b? |>ulR 6_G|:;?En{ ˦^@YS2I-aDBj:mYc®ּ5uWm@ְߎ9Kc2tpuno\U9-G%tcx?{3b?_ xߙQ ^GHS%{kɏK~%V6 I0<_Sq"\R<]\DPVp鷯q/[z$ @_zibp2(:3~U" !E[ 㳕X[ 8oM4aٽ3\}$&.4 *c':>#M0bHs�9' >L"]sy�(\ٗF+t]U7u!$<& mS;ì=3_dI%g֙.Ngy)o\M^Og!65ԷmO8[}fgzoA扩t{+�U7/"c\1wEb̯ڕ|TڵGsg %EoaSZXHثHNu(jlmYEF_F�Vfmuu*e�BXY$n;¥YC=gV'>?՜?"PP`>TEP^[A{:s T}^ʽVU`\NԚ8d*=2Y}[,cyJ 'q6fD*pOSaS9-݈>'"%>}= ~]{Yi1$"Sѵaס| 4uVS~I`7ϏNzxawMv;à4P!K6X 0s^l?HӽXJ wȘVc&8;N_+֡_ ukʶI8w<ѭ' sh͹˙tv6(q18vG`uI@fJ]w\Ue߽ - {)" "5͙+WjV#}U9r*=q l.PA Vy{?ryγγ1]VM1lR H_p;ej9x<m=CmV7' X2%~2qoL=ڭ:6q=lMa`*lg~usN N~3]QLT{/'rȖǹ1|+ʮ}s9i a8❰1͓Y$bw/fM7|(6 OLO9ƝPG kS.@zswJ@g倛w Ƈ՝3iy'gLghLebQVܥA^y>87<8ή1e5 «Di1숳 H(BI5n*N9C R |ֵ7c#|Y@RX٠QAzZRVjtXǜ^?p&|R>9*63g$&3/J)'s˳+c{sY# �~G3/JX462~n; bZo,➵;J4f}SOr9t)WD,(V?]\kbl__ aU##OV>AW=**t-̐53Dmᣱ[0#[siJx6t< Gݔ?}(7: A:9 ]OvSA O,^ʹr!jIVz/2Q'L>cT)B4X+cx=Bʇc4g R"ş hs_R"niy7X-3dׇ's3|=Ai{.aՒl+=&AtdhJ8I x^>87了P[wuvCgMeOv-d9ei؟s5r>Zx�mVGqK*tyꊣF)*Sɾ18}OMh0,[|鶐].&&JjΎ-/#UJ[Mbuk% y}qgXTbPzpSɖ1V gOs"%s[x4}g9r;viT _h OďxӨGZi<Rr"hptxkURZ&qr ~_+l5F)ۂ,� ;vB ض8̴n=cz6~{>`L :.-€EqDvr(eUJޛ[0Ao rҗ~Cew05?=q(ҧnF\MRFn!욍̍G˘G?RҲ!|;atģ,;0+O3 XKW!<};F(#&).q%W)"k3TDu{V~.VYcB9'B߈2|L\LŮ׃ofz:$nc8NXp?4UiP#=oJ&sTO/ .8ɤHŗ'oN.K劙rDra�X:P< ǯ¶HdG CAIBvAxyN^(u8q:xgfPz`Ȱ:VP~hBOhBDd+[MkQYuJeyjTX.^%P&PǹC_;E ʆذYjϾg;>WUESZH/&2 [l*O<{*qw+c3`ƋgƠ?X* v583!X„V;+RV5'hHɣ1N&1SGϡ 0kLw(%n-u^ʡ?q1}5~T3+ '(ov~@桄<>NߥxO'sԎAZ,6:պ-\~=Jlҧ+srXڞ#Jd{xSY'b@_0)ǖ.kR(2@{`6tLk�^ЏSϠoԭ`=W l \2'a1*2T\ж}Eӹu6F|Fƌ)k<ݪ0دx39%m^CZcX_p\jMUqX}%<H VMm3wӇ}gWXc{s=ɾ*y]{~y}Fv/&y_141:1g `Lx.y<LV$_Ƙz]-I#YGE2rH9\J+z ˼uGgf)`VןG?'EYAQhp/לv^'.e)ԄQR)rX. FHuq.}5ǼGӶ(TzE~!>p2. ghshsƩHTcբMCk`dp7Gcg4lt;3:oҼE ꇹb (P!5�� �IDAT m;g*V>~j> gN?63Ÿ7uT([~tj{ ޔyN] *ԭaܾCk+9pۋ:u3myiD@ώep=VB4)`?Rjz;4 gb4ue׆ \;Ud]sc'˶M8DždG">,+2͡D%C@JT Xp)Mp)u b:JgxeWQa:fՇC}E-ϲED# <� p1&_7$xr=eË8pP6mV>aO@ bt&JaP+LnA^(gbw2g]G:b~ 58fV"A4wӽV-.oŪ Oޱ?qaK<HP])"3Xc~gY6DgDwNͦC ԹJƮguckoxExa1YV_e`NN{o*n/kۯFoN-%8Ac:8F3N8M4tSq "c0G xtgJr\`Og7>qt3 X)KRwٗsU_)_ y:Ƶ8.*]+?&R8{Ume I )6;3~@]\,59lmb�BI/!k5|9 ?⳾ (dbvaZf~-G1j8)Ҹv_ƞoƉDUkXPv{JnCcI.M5=~t}jeAHI|$NTiT =o=e]9րox?,դ GNI 2z;du뻂;$Tehwk#s7 \ OBhtV`}6OMn'5,J꥘97Вjr8T]P:Ss%Q(21O_ TJЙw5ztΩR[dCV&((?-fd?Rkp#? WWخ'R4.x:iP:xX-Op8K89t`n# |YJ t»̝ӕⅶRtBM|se k煒V}k7i?U򶠪fsTL  DlBYUQTGeHdw&Lƒ$*:>_]#4tξER/q~8+}ڞLQy_E7H  #7?gݯ.sqR `mXPUGiwv= ack $I5G=oLKCPaalbFӿȊq4`/+@ٽe \N8 M�] <2$Zzc<8gorD{?&/N, 4hZ!_,!8ƝJQ?&d_rKҼٽ(BfBcII9HV =v>s{u Ŧb ]`۶۪u/Өp-_n|Hez.) lXaaaϑm7|۶;7}YQS`x~x;XɃkX5PV:EF D8*еaz30eFK[D#N}%}�cN} |PQ.!kNH@U?wfACR3 2<I.jJ'$h'V9%/E&m1]{}:wJPʸj9})YnX!eq;E?.a…,\ %Ǻ~T 5YR.bc~:I%<ׯ賏ʸwoǐץB}_qْj [�f*F q OtuOrӭPcꉻ,Cњ%p6%iߏ<sKٟC73+ȶl}G&olQy}U▯>COXv9H$& @T:rd>2jwP`mAJJ$I_@s'<7>KU ?UOFl; 8x_Vĝ/}+ R#(ʄ+ޱ/P<Lt{>YuUJLƹq$iI_1rH ќ>~ G}*^]z,w~rQL@X>{H|lqMJN#:NY*/Jذl2Vg~H, Ms Gt tF鋱H!8Zfe:-KOW3zMeDfx_nsri] +{o^JɿU(E\v Y_6,5u6|z>}u:1|iٍ}Ɉ#[U{ƪ@W`lZNY J7!bTV%ޫ9Ȕq#׆qdRU#Ono) n_-N-]:whEKj kAu4(=3lġX"4 4QE%?n O5Y&Dt*1 $bwEI6r.+ۡ@]c=՟M&jtl_seT6&%_FI%`>B2.X$瞎W8SyT}CŇm;9Ŕ 0ٷovJ]Ăl E'v"*u:V4&<{/w >J〟]l@eKL@z΅kH]Ag�^Z/󾡌EsBSw1QK)T s Ǽƥ;E]HT%h2530y*plO.C7P{ꌦ+\3Y7fؐxmح(>[oQ7딻޽ݧ;V&kc׳D>LVV1ΗDXr WUF{o2n3G2sY8} I)hd5!m?k |U!S@R"Ic6O.CMzcCfdC{w&A_G(qX%-աNYp�ϱSOpxy<1bFrc[GG,XˈkQXXCɰF ݆F!N}Ʌ]K2T#a{}3ge|1!3f2,4qdX(0U&;jD߱l�Ҭ\)vu3%~_YIWZ< OSӴ5`W4Ki8&aw?q;.I19 %u?\2rlQqK?peoZb봦vi5Ɏ"3m jˢ,UUHӄ*smTß{=U' 9\^H9U#O?loENM^**ALbl欛yZ|#h8l:7p}ʢy*sf̸ZA"l=7. / VHT)(2y1ju<Z-NfbqA <k'2t~*"+ZU^a̠Ť)lp-Qv_kw)Lc_FJ&֬YtTFv`T.vi3|mOη+F3(|9'aS7q3SI_@wd`I푛~ޝ8,i*Co"-"AQѤkJUjӾaO;_ct׏~JDrj�VQ<mG3U5|s{N ;mK*t#Axq]7[P0m񱢩9?}l?g1|i" [tI\iM-?}|O.s:ٙ3K&)4Yw(jޠQFM$1E*aVyw>0Y,_9 \KGmJœLw&A?>6ٗYQPL$Ig%عm|G7 KΏ{\/ޅ#  _1 ^*;eA҈|E:7dUB#   fscϜumi-*YE3^$cEYAA EW4 SF   HĜ˪mQ܎MA8R&+{P �    rwAAAAAB$eAAAAA XAAAAA(DbQVAAAAEYAAAAAB$eAAAAA XAAAAA(DbQVAAAAEYAAAA8{*WIDm[w/^^?I, @<  ωMz!WI ܴGc^[9~x' !/c~)gץ8uΏ'J)vԩӐf Y%q^MK<&3ISkws1#3Nhs߮ M`&9ukx\/2V67{7Le.4=(,w%|]tiGu ȶ-n NJE]h؍ec󪨟=6[ʚr.:t"xWA.TSuׁlE}(ξќ$HRmCQ_JWAh*$y81n. g{]1e-Od*=>MN]4gυ86~Y5I`jNl ;_*ORBN2xh�jg \ 9uCFYQmz/2 9{CĿc6J~q mw �R84&z$-,qt/M:wEh0ZN꣩f+%w f V"^~^}G/ZkRUGNeF_1~Ze̶Qkk5o{iٔC[Ӽ%%ӿ,dKAUZQގ44k}Q<)^Mۍj\IO9۳sLkR- J:/}E֌&(``<oEcωN&QÂ4+9k=~EE|D8Omd5Z̙NJUZxtd~MT:6F3R+< B>h9to{zڧn^3x s>Į˸t9$vWr.IRޥ(<Mg܍Ery~yҙQ"QH><xolWB-�%%Q7u!nGduq'w{V/cX ;&{^ݘ9#VCϰd`~LM]N`L KϽّcVȘN/\ⓕ8R{;70;q]Cs}W؎1%=۝(i~b7YU^)/rKʣ(YΈќi_,Ju`ǵx6Qrc /R. II݋|hC 0dlk1nHJ$>x@>,D~>θĚ9[уk#hv$ާ-AL݋Xi/6:g?r2U3:j'qki:6e7jN~)ꎟ=̎[ Oȥd>5VYH=Ŋo7[`+-bxgLi{AB6J~vGgޓ_43i*]aènU~՟Pu͙ΗC397eda|1\mJN;|,_@QblZPp(2XNMx^d?X+ɓ;NL�:q5 Kyk;nxtt،eLx in<`U q>?Ldq р._& L^1.@bQVR_V%*}ڱ1b}< N1/RZ2<=NYT:P.5qo:hyQ"uzs$}23 GOf\Oґw&M+­Hѫ)IӞxFW?8w/{4~CzB3Q� QaCphh*Q#̒;]q]wp�"<n.`n@r '(ʋf3`V7' X2%~2GF{_֜ĻT՛^+ŞDˋOV|.uWBej7iI.dE(UzQ00wU1O$mV<ePjk6[{HCV)49e\9ʉGtB֠q1XƵ`*X͜a4}Q"a8❰1MV {1nvGHx9i{SḺAxEprNDَ&Ig>ʭ;ߘ<r n}FSK?fۖvFD\[ƭx m-d'<"KR ?b~2Ҩ@wI. pQ[":}JēFcya7CO_䮾6*͍]ob15G u[96N72Z>Y9s3 tzGzs>�Q%Hxsw(_q T;_ ?l9µG*\Jr_eT]&e),Ų_:~N2*jOG*Wbƒݜ'!dJҙ \5d|L!G'~ mP* (Dr/>@K\b;~P&N @OLE)U,{ikhϛ1nw;u L|/<s<h<9eAM@<ܛʜ8nȼ>teͧ:r36ewo䩍)bQVUyp G<zyDhg,F^%OmdGmUDZFJڨtSqbTJC/_OcKG@7J)'s˳+c{sY<j,N g'ѽ>cT)B4X+cx=o v iVaq-9q-|^ lkS�(ۥ 7bW-&qEY>loM?Ձ~9 #kjo-G W*{ȍ/�k4z2&xqH<:lШ =- C-͠Gס{rBRD(V?]\kpOϝ26CU0L#=q(ҧnF\MRFn!욍̍G>22Hyp}q&V9oLG5Ɇ 3R{$cKmc\O'{Ftihi#zB tvQ ]}9Zxp J\lJ/_<_JT#ikTc`4H2?URZ&qr ~62U>F냜LU|sXc\ι}𱟞 =|4v fd[s)_1)31Jۓpq|i$c|<~G3/JXNZOٍuAL[ܳvϪs&2Wϥx8mt␝">cj2P` oA*/ҹ4l<E:hxxpgգnʟ>MQנDJa1SAσ34f''1MI�� �IDAT[nOlAKW0.G/Rl�<VT7QEbf̚`fuE6`EYAWhpw`2mQb[z"0zLEQggGbE5&!�}M.D(S._+?X9.K劙Dr43?X* v58uaҍ\ӝ�*+<GM&/]1e�]$v2}ffiL=w|l47 .oPQ_ž7Wza~ދhj9+(&-ˮdV7]rc&b*vE|\狹M̢|U^xn43N6=[ػӼj dH]NۺӟqSla7=u"ۭb&4kф%s, #| S:{ \w&uj<v|+w`cL=߮@Ǒ,a.ؼaƑi]k$BLI r2Uחfa\SƏ-sn8ߧRq COL3Чl.+sr<J'lfﵥ/eL=0VöWXCv)gSWQ~%ě)i%j 2/TA̻˕LDƥX.^%P&PǹC_;y>SXJźͷ(y_t ȼoHu.[:P< Y/?$^td١$!Oe*Փ2il$ədrX@䔯ڢeClXs,WuVg3՝IWsh*)Z-7.Ᏸo5݌K>gSvsx7/!+_K k> L'<8ɤH6 EYAQhp/לv^'.e+ԄQR)rX.{Rnl e_1/p2. g7q!ّ:E9td{1^'ڣSyԬ)IqR.\O <ы1c>eu@MNJhfd]Jw귬Ƃ6-^x]^|TȏDѹ[C?CeIzӶ^BBW-?G̏xI3EΌPnRxϜj]9h;mfqo6<Kx|\O׭$'P;١qBV^|zghƉi2n*.B#, -tc:8 å?w4i틡Bn9Jɜw7r!^(_)!xWiJsz}}>aO2P;+fLgTӗy5&R&591Wq oMZvi`۪ѝg~i�P$+us/5QLԗ'E.'= f>OC(k| \K\M/BDo:<?aҒΕgw\MhA0W,pdT86#9~7`k+J}SwA)XwVy31BJeθAL%3<o|ŀ>_@klPGb|Z-i-w-c8u {Zih zWPm)bQV,JQe_V~| .`8޺ot=ޯSRBFSRrޱk^tK5HJ`H& 2v-2qp=u:+(R4I™Zд8Nj٪_{H >l%.\a_ۏ2e SsW]8oҬs.Q)Qö΀F=gN<O<Y;'7ܜ_(c9uAaNRKJnOms |5"]_)?'cPP'mHHo:Re Mõt [HL T[E+ j&n PYNCf7ijkI"4M?.4.sz`MHB"룪*W<*x=iy@O75}\psrի ϧ2hkT� (R,(łH~TDel77WP$;Wv&XLׯRԑg !ÔfǍח9])^`sRIBRSk7G=[)bs1sC]VQ6[̏W(f|Z |:T8j+q4(ZsDJ#'$Ao2K]WisK24 B돔Ε5e�u_}B)l 5Zrm/\ S&͢!T"k>Q×#>: bQ^YĢ [JtƩ?껗+00H17Iy]zޡ8!%^yhஇ:&N8;7H KYT>AZWЖ/9sK F)P3&}2(8. )mvx@\|8!W|W߄3ohgw2fCZs|\~VPڠic_#+VཐlCHI^>~3ɦgtІE]o:۸С* )`o͚V0.Nc&3DΟfm=F}\[G 3?dNR.[LSZ<ŕ{u!Rev Una6H$& @T.(d=kk RR"I^*=^)C)dXXfgy/:QXwRM9S~ČG 8r f~# *Nϫ\T<]İtK]}1 d!o񔵿B'1c>t5wfYn_>X%qz"଩_HE.qBcIIf/ MۂuQf‘@-+><۪lA? Vz|6\w(׵n+R,V9EFNDHJ3~(Cf `ŷikf v;ű ?gՠj?k6^9%]i>ތJn綠UT 6^y񪇭 $)ܰ)5L9y2 ޽<ssVDh(qtId$WzL)=Z$gRh^ӑǏfWNl4c{"X݃%50olnjW�D[ò}:?nEY3T V {1v(C^Ylep*$Vyg]O}pu]N^OSIt+p?VĕÛ 93mR{vdw#sw$%Ds1<{wmdTBmG:y Zʌ)޺*Ws,JGCpVɏ|Kb.H 79sX΁j&'|0Em!6'71ɝPf~hNqAQnG=ޓPe<TCD=FΥe;yk \ӿ/u2t6hSHJF_5!m?k |U!i= $%$3rPJٓ'ק{3{~f k">RuPQFMi_G'68[)Pٻ{ cL^D6\y6ۓ T+Ld@֏[xx -4.[Ct �;!:#}Svⓘ`gVD]Jaĸ7^v1yCkሩtAr߉Cli 3lH < (_}u:1|iٍ}Ɉ#[U+{>*_Cѱ}I>^2ϕ=hSی\%$JEP ^ BQqJv!6Q,},/"Yh@ak"I1qA#w2罿U իy|r6fx-MW&D,ʊߠ{U_ށ y*6R>e|>~̼ Hw.oGfu ʜC瓾{xo 㳪ͧ?nÿIIiDLhRƗbQV<HtVF:e Ҫ+>Nq?Iyy >+d;|#x:Nd T6Ep (O}F3)ֳnih o,X$.'0l(57R7GeKh~֔) `[*y^#w.a8ՎxUvM^q`AJtf._҄סZ-# =[|::bZF_WJ5b64 q2c-_SN|ןЦ[=~Q]H4+j5^2.cY='nǥU<":}:[A֢0\c̽Xe_H?)Znce $%&NY�[ T#[ 4($HG*Cn8_˰W+ށ=x4:xd)i5i0ñxUG[?%Hhdw)kGXf7cQ9فQ=PN˜9Jj y,=r3_x"%'ole>1 :,Ѕqw Ho71%r\ҥԢ ۭxێfpjZRyi5Ɏ"3m jsT^ԳT)(2y1ju<Z-Nƾv5cYR0F8V~~^Uku+t %ak^88d2yk`js*4q(kӤA>1W|=n*e珠~Q1sqNz:}T#zl7fDB_m5V2clnH B]7J+3QK$IO;mr/σhFW#AAAAu%nAAAAA(DbQVAAAAEYAAAAAB$eAAAAA XAAAAA(DbQVAAAAEYAAAAAB$eAAAAA XAAAAA(DbQVAAAAEYAAAAAB$eA^6)3_{iH~ :P0 >k7.,ɥ4yA :ڶ6_|e*e? mIc ݳcrDOĦUl=-Hq۰ͧE00CA1T_sn3O<@k<kN^vU3Xg,6j9A"c׮7" [|PNCZ\G\Auu%%pr2yej/Kĵ{I6\/d&M݂1O롇b!34Ŀc6J~q mLȚ8dPD mɤX55'&} k?Ȍܷ+=h;mzRKX0w5{N]'6M/AM)^f.k Ep@-3#OeATzns&>5;c2ߗrj^v02=jᡔw^A]3*0jT[PԗUh-8<ΓMI$6I *Kl DiZDa6GGcU<h5kV@-s,xScɰv#J+z}Ԟ"J@65:+X9oj%4k}Q<)^Mۍj3[zDNלOs⩿w\UϽp7D@QEHDͽ5-K+GZf̽sΙ#GeTPYǽW D{ޯ^ss3se`x[5L $m_,f} Ž|d:-¡ T:ڜS%d g31sXA c ^>^'2Of)S2e.?ZJ)񽘔]uEǐz5jN*M䔿aiHy4uXs'V . I'arG N5 c wn23\L_`8hߘANjL$㬱-} uIC$̚onv۟u,4'T|'2/)\Y$RFL<o+nIIL"l;vtcp|݂~O>SMW[*ĘHm\/"ɌM#Dڹe F0dC@-mMVAV.;mMIfuğ'(Pik>MyZlv-dALm?`MϟrїW -uMkp=US3`;6f>I"YH0䀔F܋ѣhrkr.zq5?J|v| أ];Ӕ _ 5搿fcB(h?YbBϙ1 ?G%dKɝl5WH'Js; O0W/(9 N"!.L1G^#g9]vGR|"q_;_q9N޷:-{MW�W0}nC3uwx|PȆX1la3xPq}S+},S1s-O27)PR)p ɻ rGTQ: 0" Z.յJo[GGlZĹ_"ظw1u(M~�tGϧ& \r0�7[Ȣ^es󐽟"tDF~̟p6& S[w*)]cb'=X8)3}q^-5: ~\>u*m eo~_w Rx)gفkܾDZ}>>~Sπ)f&4yUo8 ^X+2k/*U{¡& q�X2E)c'xYM$SnGP\C1渔k@>DsHđ=:=柼1i/OW;NmtS3c~I_,W^2yoC+vDG`viFn2q̭?شM'MX�ܓ{ ?Bn~=!: ((Ė=Xfe Dך 4bG5#4;LzSNN"'|py3|(Ct Lj\wDZ|+6Ҏi'zp<}FքE|QϞ}p?؝�|m#ذsQOI]ǧ1)DZd'%.yGt牙(R~mS~F>=ƶddIuo ǩT~[ &$o> 6½,l|vOը4慍r=*Acwc cc7.foǸdS@Nথs|JwJd<E6u^ '"V(مLp2$2s T`js5 Zq1vQMbB"2϶ko/nd_f#X7w#">5`B_g\2#`x&JPFF 'zL�� �IDAT7@^.jS!g7gq8,E;/cN 8kJϡ-p3!6ϙ t~qd*i =kf |ŝ` 4bFVOCocZ++bB;cLHGĠ=5.S`azb6,ol=AYfMٶeG]nYoayՆ6m.{髻, ]4#:u>8KU7G\#fM+`ƲVH}ӿ㧻5if)yݧ.<o^H95C)=\wİ5ptD5rGOF ";b4'ɐ.H7`4{U$[cC2|o?W9�w,+*Ѥ~I_~`hLŵ;=u/lg۱L|֦ @ݦ-ۣĞ=+>j.e+x;'&7KXԵK}jͷVXZLuHiϓ,.Nucu,ϣ5HLP');ˉ$Cx2! AB|*roM@}GU5\'͘yCd}1- QY:F9P3/4 ʪ!]1j))Y5~%'o 埔5ʍ'ޕo{a*V;2uj+xex62i=*b S[wL:l"W}c?TP{h5c#-dNȟ;.ԣ4v7tlTsrPFnѠW|\ކȽbRV^+f8"$k'_&)GcW+YjfaTG}KSIcRUJ:5KxWXiab28Һ+?Pװ5*v y I`zh5^‘y.m/i<7SզI+U8nG'˸ү&PbKdͣ7hGVyW*ay o&u)bMj=b̴lꍛ^x3ꖵˍAC ƚ/Q<.cdy31B%#GGdM0*Z## vT><EA߰i2ؽH~#.ܶ/�}uL˜r{x#yw{VfG fp'1tt' [g+M/ȖH82FG k/)e A&쎺}5x?tUꆅ<0@Xh BcNSꔒCղ<<'ΐص'\?-96 $$drGj|:f'%3=hl+Do҄WkkVh5|;jv>aZ׊hUGdKF 'AFxҕh~]Xe.HdgͷLs\cjs {{AYrn˶1,52wǶO*7;q}y)H{?̎NL$QQ<ϣCYmCbڋ8ɘޕQd٧\%zUvj(UOҭ~w|tϔ_hض *Xnb뎯ߓxtL;ڟ/S\yhueʭhؓG>$ݍ;fvŸyeRŇYe{E97׍L[8ž?˭ьa?rհ3'ۧ8DPHR*U(QբS+>^ǩ5l6\MdmQI$K`մLfvɬ'Rp�e6^xD$UD37"";up&ٺ`d6T )g@YxP5GLh8uqnvn>q{+ lueߺ4;-{ QؙVhI5;WKpWv� /`mEyƟQú_~x>-@YQ7gh덷6,J_p2ad8򰯨9k k[̜] Id8:ZՇH<u4V E"+9+G7d|)ez{_L Kzb0qZH񻘿<7G@%}4#D 1._̀!o$#Um}דq�(v,g3::jQYFj|޹{i?kf` ln1ɸ|7oTԲ=o*c- |^_oo^,lW@߆s9Ֆ*5"#wzMXp }g>86/]<ƫrE.rx~Ґ]JؽcW,{V6rRgfŤ \Q2[J9Y4.e}LXy{4zI$%`JVq&˦ : K+KHI&U$ IfCSY5aj) 0~6$d+=r5Yo}ʗqQ$spJ@&CNL>ŃX̉ SA:ObnP0#HLw%d!'G{ _Z'vef}5-G3sPg%I>hФu}?SKOҷmmQc:<Uw R]힖DZڰ,;?cA{?l>cFoj=k]?gab%I*j}׬ 9ꂶT SQiDa{,Z}3坸|`Lal(X,h+q$;H_GrPJK1e p7Ju:6iP5wtA GYq<>S'(a)2C{2ym< Ent|zOw M2(케e.5*WԔoO_{zu뾄ҙϠ0d:_7zN>E9%)T{xhaYANWj* Fry޸Gjp[m׵_' ) wd9AmݫAȓykQ_\2PrZ0iI1,"'wPyؑ}OBJ*Y#d ܎c Av2,,H)A叟y*WoPJ`2s搚Z ^Uy5(_2.ө+Sz^(jcM/\U<q +w[>~-]ҚB%8:HWYdJC[w""m#Mw])ֵ[Mm\%ꓑ~e/iɏ8odrI{POlIM?9g^7kXk ju}02HɜZ}ɥh<L]SAJ'5Mf(0_c% F_lO,[Kttbh( FU22rϱ_g;A6 w K6g!=9kNJe#S`⎛y/=jk}/̷i OujFh*F݉({˥><5! 8/@s cL,ͤs*k{R$0j곰mא)"*"gЮxo5bFzȩW JT=*AcB(N}|ZnNYAxMeEE-Vs9#O?;wpUTV@Pit@kG| gHN#Y{iRJ2oBOv v~]R )2thÀuc֬ռI 9[ăڳ!9TPۡgKJi<r+CYA>~f5؎O�D%yzf:&'V+jS«`iϜ똸!jA8[ANo[ ɍU<0q׿.txߗkG'UQf> ޲ oRO.!wv�-^ĕТi#NGrLxF#YT.ӻ^VT1*KmƗݶ}u eڨ0'V\Erk) /]>e1T|ϟڹB{w9j\Ȑ=}']ΨִFc;uf)9'O`aݽOdPSue946LR96xX,HLTrkWJ[k|\+v(/OQ+sXX�-Ukw"V*mt&''}Vq3"C"-7r~o\x_^c�C6H>Lp,|a2.!W1XDxڛ{?V'ʹ *㩮|Hصt=Q΍ȼrp6t|_5( i'Y2WLZMgeo̽>?0uy"> .do;j&@KnC)T4k'Qmps/~P}Au]:1 %1WgQOG%h0X/:tjg?}7^UN4W%p{E<ZA;4ɰZuJZo !xHKpU_zCHMeB�k=zJ d)KP4&-`^CnMz<VL Qѹʉ4>i+ud8f˰-*w%MgLe�VTc&YNa/_P=fl?$=tۇ.!WKIpLs2U)*vEc:IKa1 mȰE9XWƞC;U9ɒYRG~B=+ 탳N{?:ЮSKn[1eoh?9( yF2:޴S!"3^=<ד{5uWC]?0 iQ#zQG7 L-u"rSۆ8g0\ v؞ւ !tՙ ދ秿_ձיʃ+}"bUy֕t&6#'q 9b| ~\3!fQRY ÙeGF2v C[5p 1OIZ&VY�<5HR7~*0u??J |d_ 23 h0j7V8/RIs<֌&7؈=k~i>Nކ֡̚NbV]2\ʗAa rN<s.*[ L_ w-պgljcS}S,2$.ڻ*o A&.У%XøAzLaBn\udXP<Ճ\!G(ǖ2I6A `_Yg>Kȑ  jC>T kR PB۶ngu?I"~MWSVAAxTٳ:S܈ADPs/EBVƿG1)+  po {t}. %F}2wӑxWǧ>iWn h/" ^_     K\AAAAA(FbRVAAAAIYAAAAAb$&eAAAAAAAAAA(FbRVAAAAIYAAAAAb$&eAAAAAA(JR2.`Q:qY2:u!sx|<9/;/< ECJYk) p /;/  bRVc$9)GCʊȩ_qExRĥ{8BWʍq>6ՍՒǜ ,=O<D+@J|<MlJ زmg eAAeg@-#NGœd/0MQ!SNW.~ٷw3}c&a)c-pL3~=;\L@Q9l!mF'tedAfjUвs{ZR4{Y@EAR"g7-姭8s3 WkObZX+9v7zUѠ>P\gp";vM(#}5%#3>fħfvA.= /ÆUȣ&+Ygni75٠yQ#7%ΥKS-褰}XKʟ1J͚*A>nP Bn Mg/0\8NlcZa~c9ٌ5b14TP} [Axݥ]Zt Wl_D1HNNV)79rT OͅgXWo]0=څn#?Misl7_.HIL"ǯlARe_wi]dLAv:JdEdyPZC&/4ac5&q`<F-c悏 VXؘ+6@3fE"5<�H&ѫ-VFbL$6fdF̦ >e6X@5H0 oL{ '5&qؾl}5 cc8eᕠwܐ}Yg l6 C76Pߒi+֢**'Y Gga?r\R9ar,{cF܋ѣh坷]5�Eٷ  1)+Vz81Y4Pcq"P9{yoB#qTs2OT _rHUKd�*,I%� `No'A;z:]AsU'̆u5 tcDg b )>y߳5nO"]^[q_;_q9N޷:-{M -SdE΃.aHb 8 Śק:Ǧuh:o:ąkP*ֿyc{oNzx [q6}XkP"|ŊmIHujs՜I 4Ĺ_"ظw1u(M~(Ʋoi̋kę}bm|_<>)5յJo[ͼ;Gzn~̟p6& S[w*)]_b'=X8_�P'qY�eaSBF1#}+VT9-G~q|^\6%F NA8WʝıY,&)#dfwdnoEE~F;YMSRmwG"Gd(̗7c|N`hN̵<;_ˠ @ʹBNQ30n[ZƟ2npyq33\ߋ*HoT9׿wML{Y۞HIOP� <@[UA(Ĥ Vxp0ǯ%N"-dXM@XzR+wBiv8Z�9X*0s5sĚ�RqS8;ljZˑ.7��dܧ JVȑa䆜�(kҥSmJ=,=hg2sK&3yw(הC[bgBm̟3 nA\J֩v!X89O! K/Jj.oܑc^<vtP _ζc6Mi3zcקsẈSUj.e+dwqUCg1:ܗC|;i(&++bB;cLHG(QXM�� �IDAT5snV=4|_bS;vsXo6 CӇg[w7u/{V6d1*(=12M'ښm@ZB轶2r6y99(#h+>.oCr^~I㥼C.9uN X)L'O\3ѓCCȼ΅7͉z=z2+,3^V4/xVN Sֱh1)z]Xx7mb} MӠ/(P[xr Ow9s(k.|,7Li"<K@d*>I.)D:V\} PbIYAxT:|$͟R c]7kT͛,l/yi?iLJUJ)PFs9MFy&\/9xQOڼϕ~iR/n*ij7#icj*Y$ܾK8FjNh5iG2<k^"S枕Y=P503?C!n"o‘y.m?hه~$eUi]+b2SI~4icRZbקJ#^%Idr{d$>' C^i6JSAPK2#5>A3I!1v5?_Ty]=N9sOFZoYJ|5cMg5To܌›Q]n=4Pw[ő(YS>4JB޺U=#(kLvs[PV^W&ʍ=yTuA dAF3|`րQ۾q6QbQRqm|,fDv (wR7,I\`43 =4N)9T-#| ]h}Eo_e{5ѫUaׅ7w{`9Wㆂ~_w۔{%<W9y>x�gIif r3�,9XI{e[Qmz f~_@* |bRV^72%nUZKdƙhVKq-W 8s"*~m~ r)2t? ʀZv~LfㅗNHDBIp}3o"BfGUZ~3B<=Ur=Rd6Xdg$[ǯlȃ::iD@Y{~js3 9-~3`8 ftd诉UQkgUX+I3WoCSsgf0m3؃iCbDVr,Wn`ɼRiխ \Jjh٧';5<sߥ[tlZh}%`GÁ̯ӍGvs6&Y{_1n`C\ ]YtYúsỴqe� =SZ͑\N?-3ۚl|n# T7 Yk_@,{V. Wfήs$ J2K-CR$ n(1X,2*Av 3 J=s  gh :(J]% ,O_$o݉ Vŷf5>gsd53g0qHˇQ B'&e5eZ2N`R Bq)O}fy~99AQatnd|LL@RK3͛hkW\-togd)_ECXV<H̆gӧdںa2_"p7Ju:6iG]&c AX+p%a:D @G ,N(케e.zpt 6Lܾm{e % II ?fΦƌ/iKI c>fNoО aX>~s򝇁0yb'[6n`gkYr43A{|h]-<ۦu,([3UhjL{ܟpfTbL䐓*X*) Ԩ4i0͇Qk0VK !;'ĻHW:kOW_08Ta`}%J;`y9y m7g0uXͷ'6J\M {O [AO\|U-Ee |qU@kIO &+3O.r!=w4)2O>)Z&dQCjJjl?w"e}p1!+s}"WTy{8>-?~\B)|+yLrr+J+Sre*0kE>[0]9{ ynD9*Ea`HSѫf֩I餦 c:7^9}Z0jW3d7?|iO|_Bu3Z5ӹP)qmAq@L /ܪW IWc x_1rj],GetKd4Gir#㟿O9F?E%R9Ly'tmYF_`p}%R߿µ$ K;?>5u B)K.{=Y"[AG)+H%jN ggN_Jrjj^4OyE #O f,ٽ4Ez DtnDF-ce-YgkCr#VQC8�`o+#^/C=?JWlǧY�vLTYM]:a|kփj^X$uۜacJyd_ןN(W79i1رr3ny3X)X3XUl7> IdߢU\ z-"AyçRr4OFIJ|4ST�O9` e6u/׎[yO«|@eެd;2|gYAD|U{ +G+:&nH$Z>VzVpBruLlRGrLxF#YTLeϰKv_5q6$*2p~ڦڬRE=;F.dpmkdH.PgTkZ#CMr?Omjxc͕D ܝXxWBN]䞊8f:&'V+j$xU,VIqj-Pb/lh<B汔M gSѴ2o9[Sk;Up`=ioJfYX(&l /oAJ>1)+l8PCS&mlժ^'p?Uy!<ai| BKOrrbbf4!?UiBiT�;fkkR뎌̕s%S%錩 O?$iL[ &#m \wn ʟlߴdfvu> kCbmlXѮJf Cpi>@n`9[Qd)t7Mo;'70 7Ei낧GuCCI~?1>Sl3ś0re 2RT4FڢW <c2vEF1T@<ɖbǝt0=0nc%$NX}u% ۉd,q)[#?^b1'1ta6Uyk 4q1JO~ @e�HGm:�3L,ܸ6¡Ty(#9>c,0ar0կ=_Ҵ *x!ɔYR6v[ 7^&96~`[ -ن`9U䃉Yۈ4ֳo ' / R7~*0u??J-k +¾UAx]$IzMg_Yg>Kȑ    AAAAAAAAAA(FbRVAAAAIYAAAAAb$&eAAAAAAAAAA(FbRVAAAAIYAAAAAb$&eAAAAAAAAAA(FbRVAAAAIYAAAAAb$&e? =I;    «eg@-#NGœd/0MQ!SNW.Е96NVkD|;ݸ;BTYxՠIۮE7X9&Nޤ|v:1?djL8f|N {(V҃U>Mm}XKʷFVM`M{syrMJncp KWj)?nXt־u0 :VEh+?/6e4DVelvUf Ĩ͵ܽ=?J/%bHi;XjY#nCCţMQ^߷Ph~qݾ`Y,GŧSW8b{$>k'okA)>bQNYYgYw8av;Cn[lыy .'[goBjѤ4j-S~+N#m웘kl)c@Ui.'xZ;BKS$z N5Q.hJȌG4`b+jЬKOƒ퟽CoBثDJ즥gnƓcJ`V|i{B@6c-pL3~=;\L�5YLP*JVȩ3דpҜGnJϲaLdGһ긿ʾ_M3Y7(/ q bIMp,[5YCb't|_ oOea( Ó)ˆ8pQ~us1Ę%?iu73Oek?&r+<=$я]95.^5Xn#bqQZ5/eܨݫ>y]Zt Wc@Ritx$'/9VjRkN#[~*bJɑС,HN U eF glb7rd J&ÿ,V|CEUd3S51/9/s]r�{dd�qʬɝ7ב<:0<+e8`*}`+WP,�/?E1I N\]5#ʙ(e{W'ttuݶc#4μ?&>uѺ?EIĖ&[Iiiɽ=Vy#V5O͟]_2c5;K5{;1-pcyi_L}c~ 91V`b3Ŝ~C 5Z^̝ؐ' ʩl;vtcp|݂_ZcJ<x@:WrTј N\Pcu B.I1$zeتHL"̈tܒ8Cd ! Sږ&+ +cڝ6& k~GYpߍw)-qSdVAY}BމM8_oc2f.`l% bj+n} ìT4Grÿ,g=\O\a`d)9YrIYf%hoEJ;awh| Ń [1,*>M[v@g(]941nb2G N5 c wn23n2Ʌ.<xa1yiFĤ oFr'[;?nD<4>X\H+FAWԠ^e3v[}1 ']`ǝDޡނ~O*aZ6?N"#)+\a}ܘf2@MH} U\bFXykʓ*k(si'ݷg6ϡ)=|<FZugx^+#I<TóGul~*[w^>E^m7<[&Ov!/bhElD N{I^rw˾Ħl;wcԺ_ٸ+&s*Ɏ7n5wP&Z7 cl. δ#Cm 6ӗȬzϚ4h֒bX/g`Y!1-J$%7ɿt[;țx߳Ѯx#)> wk)HxRbܱAHujs՜I'_4gkc(WU;?CC0ag#Q7FʧW`xV|/o9M%nr \S27ϱi),N5�'q~>ԅ zB uPQ뻉-{RvQʪs63ZްFbC%Nu~;pp4N]̤ӛ3пs\/8?<7\oXxx0̳KnQg._fŘ#ŘC'1(1Gg,Rw|ϽɍȖ-! g(REREh֯jQvGVډdͽw%" =+y9 >d">坘b`lʰǍ3 `tbޱ;=9lVHs/prW._Zjiq2nXXבNrdVX$RS@y]â~7>ցe~ђݺQ>{v#UȼD"!˾Ec<;f*ׯ܁rTv!sjc`w"GsOը*T?:oFxD>w9W3Ɔ=;q'Yi\ZGP>2Ҵf2e*8h֞6_%-[cP%>&>Uu_[[N+S}K<n`E]){ʜ=qS<M.yvCzqբ|JfIPZGkǴ|5{LM\l2I5HyM+O`r ˉC[d]@ Ul=C jgr=1okE㰝<Fنuj/^L\#ȟӗ'ꨋ\WA` 5FqJ% 2I`T&Iܺ5Os)_2빡iWgθȉ8ui� ᗸcGyצ/J=Uo"lnd�5Ńkr)GOeёhY'1cĘ:(Σ(hlhcPSǍbRV(&8&]Nܾ̽uGO#)wnp-U:PfU\e/VJ2$720.@Jy QZL̽lr{j<GeD½{ĨrT0'j8U1GٸC9O@m._K! �\y|?"We33i߸e5of`)ep{/.cʸXt ]t > :t Chu:MǞOrj eSy Ӗr"͙u|܊Q(e|, 1}bY<ݮnlҒHLLKEkNci{:t4ݷR4r[|Y64a\=ޯþxed|]Z3|dlOMG|=c-ތ8.`]ۣ#Wcr'^W 9nC,v~5"=k8TU<K�+;va>VkUdmBj\,~4].mJh[47s�ͳvn@Đ 屉V3|ӭOM̱y;lAO!ԱHg]VFܓ$ *YE\OP:H@"41k�� �IDATC2'%wAԎ^΀Cw xGחt=cC#b[0w,|Kk<d\់ؗoD!9g"GY|mĘC9Ę5s5cn.B8 R0$ M#3ŹJ+:m8*ģfsT\i*T\<oaAʃ\xt>,Xx5At+o QY`JTK\zBMaRf^>jE{yaQj_q<}[2ؕIC9r ,1;Gُ~d.o֥ѴW[l΃{KϏPo�jOJyf&ߚUPFXVoi)n)26d�g1qM4OWѿCR ۑu*ΤӋ4+6|y?Y3k&JzYsC]_#fdALd= u{t/h0 vʉ۳ɽWr87ʼ".E޼XfKj >:K$&PZbjS.m\l&m50o>jiIqaBvƕ>fFX#ō6t|-cFDzah!} ,bf)s"iX y~:#&g mX Qu}&LK3�PXZ"Kh%l|I$?Od>hW?\"gaB@d}ַH1Y"FO$dzxNI -x+$}er@ OtdĘ1c^1G[>jQǿ~q7S`YYCf8zcfόXx{Cwg򰷰S=`lUR%!3;<Ty:)`;q UaIC]W·%r/7c#c  0D - ppZ \iB3*T#3*կ.*ML_zcV05i=l,_|ň2*98h)N8ٙ]pذJ X8e+)G1s"b[tOͳP[frS1`]N̡ _Q/宻2kWRicVH`Zv|'=C;R1SW%M^Z^0$vnY9v)]wqIFm<s2U`�)5T J=?4$RSP`DB"ƔkӅڛf|#˘ L00]qb@>Yϛ/GŠ@ocCmyLo c%́~LK"gv Q�<7!Sj4s6Fܣ'bk;Y<1J©cCz0umW<!QnEsS>} KAW_,W0+rm|LfVhWDocs<!җ٧ Tj/-获\G<T4X&DKv) i\lĘC9Ę#+{e[G!:rqx| q~/N2PEqV[ &=D7Lpc ʇO?dfxŷb(F#(z'Nxǃ#6<9gB)KWr4ٝfGJ[5q*SFس'.Q:Uu@fUφEljoTE>Trޖ�r0nWMeМTJ3(_  X(2ֻ])3?`- 5EuzlɰtrPAAA`o۲ cއt’KYo1#Xs}fMNWacjxSx].`]Ĥ M9xd5v+'%p~R'id?]Yx{ۡ7g߻'rUx@J$1 LJ!d†ӻډw\ 33SD )ddN3^C- d #+9,C嚐a,!E ȝ<X gJP܋JgpV,;j[Z+ˊuKtx1H@|vd}VZ. Y/,_e˖l cx Ǵ]S_=J;ܻMPEs1sd9)_+CcqZ۞XJYAxC߿N-<͛$TJ/1 WX";\K2ɦX䗱g8E)3X6Th8/~͊qhXH.oGS)|\)oFԫ[V"Q m:r\4}R's<͠t)!sgsޒ*/Mha\k+֢^,I&rF Jq<jB1 H _ɬn[8}@W["PGrd^\+VژKj?LNPl9:W \nh^cυ]owlï?^ ;L*_LQ3B˳X63kC�Wd)D bzMv!N c ;2uG/bp-Kd>0ӮRgI t,6TF}6^]U$brێԡ&<�Dn#*PY }?'ǣCgY057D ,I]BF~V4c";Mͨ:$79$g-0YG g1V)/ (*JNrd{Wn%ʹo*@zeׅ)ܹ~=+K\̬)[!>YW*i!g0k�8*nf`}kdH$G(`ol#FNj |Pu[ϡq+lRsx[o[R[38N їoR4NxfR2pA/Alkl97cor%뗯e1c<Ę !%?Շ 2(_mhl6.BsSĤ <IaffTV>ny$ay gKSD{ ы?B[V׌T+u+lpNTh�uHkԜKfJ: 8y pBiFCh{l({r-ɸI(wI>"nWSX4-#:dwwͺL?ѿ0gGa.j">=e]D(4/Y|%b+);ٰa1Y;҉1}Z;sr]i7BLQ.!U49g~[ClcSTi\B>7] .rۮ.CͥUl;ɫIcV*Mxi$Xgɱ|?x#2c3)Ԍ/絣Y 1ՁI3XdOl ^A>iul' YWȝW ffȔ$H< qrFF\ rcLq  1N:cHyCNJNɍ?سgTظW{Hus@y+-ap%R:z'n=\:֌\[>d=CyPF�˰6u0+.C_*khsWlNӌv k\YD#P_-/rیar6?3b!1G9G1'rܺee95O|بA"m4=7nL&Iky $Vy>?yMmY {$    T%AAAAA7AAAAA(BbRVAAAAIYAAAAA"$&eAAAAAAAAAA(BbRVAAAAIYAAAAA"$&eAAAAAAAAAA(BbRVAAAAIYAA^ )k{0uTJ@,v lDhN,-ޜ< 'чwCx鿝Fb %pa*B]q߱ݗ 2.WK:N>FFJ%2xk,l,x=O= d])C!JLu P"$qavI~)\6s%"d̰w/Oӣ.e>J(âDWߙ9f1+͏0 jζ1&:(^>BIV 'f~Ɣ#IR 6Nxפy,j}^N'|?T%ޕժ'}[-k'72(53l=3SBۉdЍ1{q))_5?HhYs |ȡ1}1S|ERN?b-IJ-,9H0iegM_ƴցz~Ⱥϻً#xoB,}W͡Iq[طsłD9lo> ڎH=͏ݿdI'.O+H%s]bҌf{i&qi2~~wc0s¯v>#3KJzzs5%k'>1FSE?3/G;?9J�?̥X׿;io%Q8v_L i'>cVRo\~#զuVݡ@T?;}x%d)W5*>Q"ڇJpF|[$݌aX'"cs smR.밯Zw䋞n+U'bm:1v`Cl&Kg#z7Frb.EZŖ3iPCUE^ئ:i ٲSV;V$9&dӉ� y.gROOnJ|5nXtz]ZYRz:¾PYj*?zSB'\*ٿD&vRYiN&e_ _4NnW"ձd% JlX(58ƣ\IWۑjݻ})b͡.{y-==/h&t'r"s!k%L2ʷ?ʅڅ߅b%=bۘYY˞3nD ? O[Έ15Hr| 9$ qԋi15:e7wb|?Ɏ_,f}ŤSvLv4KgѽEczA1*<J`/Sb/H!bĤ R^R bk8`g@X41 ${lKP͔\;~>6ے-pb oTBFM o3dVnTT)xA4:yjljIEnJ&3_3,*qt:͝x#cX ΚUN0'X(F3@±<Gj<Bhg껼Ĩ9v6ZD5hwrH,?rIV±B(Zxqh/'~=6%Ly~z)YW8rk\frK[;u5Y4Z pdəSYő&q|?Ԃy|Doh?-/OUWf``V|Tnu+wnAn<ӱ;gcWZR/R<ahӟ?J֓F'3=Q:�e$yԷ}'IuR|;ϏZ6&q!/fLsg2Ql?; ݢDlt,ye;;0kVJ\'<%>& k)h;Ȣʖ pk?gmҝYu67tlʱ>M_%U?Bg AF\N:8+Ci[mgzPN޾x;"LޅS45/xfhan N~_1V<k$]}eʶCz>8:篤,&_enՏ|8>utt m~'W:fGE)y090W׹0W=TS·.b? {5Nn45~魋qc gOgه|ģr8玖38N Q>d1)+oṱfK>9l2\;seӜZ vFDZFiʛ+0q2RXQFJ\4xU+4b}qUkUVP={L\.יNԄUbԗP~[Fu-)'79̓hl4&ǶB3z kv`~pgnpn0Fms8U"!)LYT(>j3 ZtR2&OuLvl:ˁt./ͦ?jm˼Qc\2I;=5,{[<qtw Ng{%u3RȤi13a9gm2rd;#qqnwaJ ٗ#nUL?j䀒/HEVS#HOKCBU_3tSj~<D[͢3-{Eɍ<3#Er=NA&{LҼ ;D|(ogdjSFY, ޓН#ٿ4Gۍ2+k,eѩi`8dn_ c֮_R P^cXKLJ߳(&5h>}vDk[)v֤_ԉnGl؉A&�ȝ=qS< z/okE{y:iRr"ɘbc܌V$[7P%tϾU~ͭ}ۙ}/f ʑhQ�$!w79NvʕHc?ږ/lt֏|O9ч><G'*}TC_�Rf=<pȡu+rԥ3dgl2(ϰjJIDg._1.v*]`X<.1ݵڷ+IHEZ>NU7  N׈ȶHJ<FGMުY5kijƿ<XƤL�Uʀ:)xTTi ˝x9^n-Myf&|*ΤfټRpsDzo6= E5UcKDɘRyn8#mZhOSZ4G7OOgʥYq6|@ٮK߇YW"~ְO˩b,O|fbɜ0ghn,k7' hG똹� 80 !6n9T-z"qݼ˽qIT Ne?Kd' wLlv}[ L=Rz[%LH>rEK UcQT(ӓ}p+r"͙Vu|1NQ<�JۍVnNx'P/fUtO*yz7)H Es|7dG;sݢc!K>7>]L/kāx\uV&*GW܇nu=+W4.nۍ'TkL5lJqلԸX%^uS>ʐ l>X0.W^˒k]Z3|=NLkѤ9-[7^9пu<66#aSӻUʜ~ Zܸ|[QBIG$ Tj8=WGŶ`҄�� �IDAT*X8d+ o511-ƵGJ롃,8CMSnղoz'wsCxI%Z6?oN>np'UٕrL!(~\8E]&d+طO2T9l\%} uuk``<,U厩;:k]S'ڇBn 7*zÿzlYV%5Ӥ'OT_|`<8Ox='!2:C>' Cg2ih#.!5½<)&,&xQSbK?3;3lGs&}+}aF"=!md/Znje1BɣX.DfJ%4饩aؠEyM,32+wmBlv#s39:t2T8=Fmu88QKPcgg7(gf>]kq{jݚ&Ao3ߺ6Mj2cD9Ȏ4Jyf&ʚaZħ!\j U8eW ^ԋ^zBixAz7/{K_�ZtUu@jZbP>}}<3BgKWOD'xBakMmq%üTv2⪥܏'AǤlA(m#fd˝i~]L'vƸ6̂ݹr�dr8΄p1ҷ*f!2wQ+nf% ~:&ϥw�(,-%)f? VDbx1TDaN3GնɚH~rt7}*EϮ\Ӆ�}3ђ|Cn/}6_uEwޕ:vEu~ZkYx.s-ɚ*ߺ5vĔ}ЗVS<.mDaa~hڇ2q2k<+xh,PGolQ bO 7 n&w[bcH̝)Wb" EoEpwP|J^lu ?5ϺFn9 rT v;&9=({cF&z@ Ey[6$9>Tal팱e cQeW#qc(f*jǶM=p-kì!u3tʬN},C?fYyC٤}cMLuX"dĐz$$Iq=z0FHӶ Y:z7nGTV(eh>KkVaQ3DZmߝNSƳUJ�:U`�)5T J=ϯDjr  L2HHs7srmP{,xĝt)搘@"ogpu.%Ƭʱ-;Fвk[Mڑ¼*!m}K8e(WD ZϖtHJ“'$ʭ(un*!042҈{S{\lKww>D=f[Re:7W{hAwKs< SMb07_LD%łI1p#;" ?ƷdouYؽl<D2~txC%=־9W5ӈ糮Uj*ƺftՅi\u1O9d~^DP4C] 4@mY_Lex]uAҤGhIurAiŤ o7r"j6^K-EfUφElҟ@x}ؒaO  ^CNR I*06A(o]ᆪ"hIM}vx1@2r,s_Š\TiV9mZrS*w)?Ol y2S\BZw,[8' )1ȼFkqʞ=g8queW3'+P.NFne>@znfKfqLdWS62,r}[ JkZ528?VIZ)+r8 M[TqŐrV ~Eo`I4v͙!rUx@J$1 LJ!d†ӻډw\ 33SD 8z>*W[A9v}O),Y35wjXDDk}_222Ȟ+GYmiQa,!E Y/,_e˖l cx Ǵ >K _ȩg2-D&VOl ((a+/V%K9Wחw]}s~](K>ՅiCbJ>J<ꊩ|CN>RVP!9v ; Oũ}{p& UaWDŽ+]y._%ILdSit3Z>Kva-O%b�@J ٜKS7.:<͠)w E-)! RAءl:oF!/<Y_ռ<64Ǫ^AȲ.]:g/'jz`8I˛Yͨs-ώbϸӮ \}/5I~ˬѩ֏;i]X?(E6uq-`yd~tmUu\å1Hfؘr:(RT+T l^=S̩;!X~:Y X5 V}hoJU,<fB1 zYգev{к iO1B#=^^&U�|ES2Ѹ<†!T[QZF̹MKL&c;%ڣ3%2$b,&8NJ&%ҹبSyylgTzMwU5kنNg 2 v$p\5A'rVQ< 20557=<jg02LM!)$vD_[tj7bZzG|h{.&oï?^ ;L*g%~Ry\@QVr#ػr+Q-x+PH$G(`ol#EH֔Z̫$Nxf>ؕad儇 76p߯ |Ssz9.>Pu[ϡq+lRsx[o[R[";[?~וKtǃ׮y|=y7lHeG]׆Y7w3|XX]?s.mS5. *}dZbmв])8rY 8�>Rq3q8FR$іk5Lv$ <o *`^z4e HDOf[!j%[Ṵvprxg{qX|7h}2zx<bFCh{l(QBIzŖ6N.XȁkAn#nt!eN~târ#%alei'ʿq=TxJ/fŌY2qEfWRi*X̱w+OI16)S?T,ݾ1kP#=~|T7sF>#]fcj|4-�,W4UVʑG8^帷Ds#uL)L3ǂMSXGU9Mܐz1%LZs2E*uM㮺@eSX9vöj[/rGndZMƒ:5Ҧ6\lac_~FdfX;S>_kG�[=Wq~g}~y@:0iKlⷙM7+w'-+d0ͺR@TOm2L̐)ILf?#R<'\W~`܈wqh|ClcSTi\B>7]K{yI'%'3Q *Ll\ލ?9@eAe~,,|i7j 3%AM®d[`B蝌oR^G#e#wf[� M_cn/*za;}>%̻9_׵Ad| #MzDp̵ꮋ¢;uCaģ昪ocO5Y h)8֙S$Iz-dԪ '-aAM}_~Fի_' B&ч&�ߵMLzx 5q  BH#]Rd\1u 8AOẩwt32<pF~[q|]CJL  =vO8? f" B}nR2QYcRLS^L] 6P AAAAC,AAAAAAAAAA(BbRVAAAAIYAAAAA"$&eAAAAAAAAAA(BbRVAAAAIYAAAAA"$&eAQGsb8&oFove8Ž/N7/fo7ݐg w^'%ry,{uq BnRaۯ_Z_z}HIE W(꽘1)+)i-2K{c$R ?7sANO|𚒒s$Qɢ [)Z7'c0Wy \VrQUc[D~R,gf'DP)omW<})!}|q+rE/>$?cߗ-OmqR1w0(祅ySq1lS"ĝSIۙW&aHSrKDҍ=,YCf~53pH 8xzYOu6ə择kK$/=y-+‰1b`d5i޵K/(6~хY畚~3(צlwcI7.MFz1f 3.~Ӯ[ L:ǓԳ!e|^i+/')ᓹ`+gj騌L0Ud8ίɜ'`K|:7 ]~I7q4=M3nX)rOIy6]4S|BZɠhdV>?3/G;?(|r,`KҖeƐa_6|yGKgƃekDK6xxO|L]cnbp癜]"R>>SR>g݌8fST7ÖZ d LXaQX ㋣_}Yz|i%%%4\tɷIh;`PT4Is${FGK7=񵕓y іXGϣu~VZ4޼ 3iPCUE^ئ:iɫ*BnGKT{1@>Н@c@fc I0~67׺ {45K>1i=(ԓ 5qdt`ت}xCW18MyݔHJLN&}*v/r| 9$ e-A-$|çe9t>c1kgLܝcF#5[ba}YbjtnG~L{g+|fck*WKcQ)P@֟ӒGYp>SPGl5 #0``wٳ`&ߍ`Tk°Hz~D5Z]Kv_!/lJ~8ї.Qk3Žsq-K{J57ဝ%J S@n^!NǶDu mxo4}}V~S2b8:<ˏxR J{Т zw+wR{.~9ȥd]ӺVeNō=h@A_ :3kh1EK.[V}Q-GxNʒ(4 MeNWP:K-`#\7+jQ?z6@E|83srVɘF7`#߷0!/-2+7*VyנO }VsZ�5vO`DĤ"rRү^V"y6Im=i2ژ.[F~L՗*jGc`Psr>URYh㹴QG,NX~͕3f'y4|]//5үaqd@L(Sw3RA&<꾘#y+r}q,شN~[J'IOϟ_1ٮоi+jh kmrGBi‹C{9v8 !-)gJvIG'{yj3_ִB&ppLo~xԆ~}Ga܉7¾?,OZK(婽^sJ>+>GXD&Niy�JۭO}suȒ#GȢ } 'o_3Ee[֟Ǭ|a-̀j.\d uR+x˿<]rgK~X$]}z[`]8K]Xip|˖cC!\=ȈK׉Tbqge4~(m[�z}L*)_ka8wC*!1u;Rχ8/4XWrjZ>݌9+gP޽Uu&a /WߝM]ǗYpl&=>Q<m!}2*9<K1_0o8Tq?{}7L4nu ~>Bs41$3˝}R91#^j_>@"~7S餡uԐq+ȸ%FM~z}E˽MPty~3Ⳟ#J'8= ˬܝ!+ $גm0$2JS\ˆ2TZQ1l*wM3{p7w\3rh0h.l]Ċ1]6yOw72iA:}ŌFn?}fٮ"0³Xƴ@ 3{gsy0o6uq Tsm\Ytp}ʵǹm߅kb+%fySr} ]wQTm=!$R-AzT7x? "bGQP "*.EK$$!ݝHlIH>u-N9sΜ)g=ޗ~gpB{'GTKif 3 wv- ampC cܻ7慨v,9:L`*M LH9 H;Ɇpw}*6J]X0Ūin 馛|/w[?d\ӎ(A*,znrxGǷvf#?lVIܷM/mq|9?\]WܽٻfW*ٱP&C]+>ڷ+61oyk+<߬ onU)=оy`{e!޾M{7/כ o]mKeKlF*sx|p|MG5[�b__?z', E̾"qx#tD]5O֡Xvpav;\Q=ؽ3~4Frwa>,$lr4=cg" 9L Isbn䯶 `9/XpYkWyg~jebZM =hF %$lA߲ w sKdz ]H,L%ƥL*Nnz|߷S]u/wϪ<ұ-g6黛 31:];9ۅ;ڝ{{ˎ 4wAek2k+17h|M&yb;;\E<vrھպ:n8?]ՑhGgz%v [-f϶]X9Su jxn[W�� �IDAT#qAQ^t)Y# |2#{0GRY�tGݻS>-h2$=]A?ƞ*͓::\GxY6c_2˯N=v|vgdEl;[sYs-ѩu wX3Zŝݦ'~vGD:$Xص1~%emDߋ`/lt^ǼΓ7+M#=>nŷ&/s/j.>po\O{fC/!z<3mź.yͦܟL3A=l4s,$fHo'9ſ5mcl8r,d1]j* '}|]7i`W>7͇<95$@0ke:=j8g矋t˯+\ߪ\<qpݤ=%w..d<l}uOx1e;97"JyalV;~-o0.SԌ㴼lt%{÷,lۃG{?=oW zQ'Oȳb$ׯ1zPtnXTO.ӅЕ ;w MbxtR'y}]�#f\}:Arʱ^<\Wp}7ngu&WM<U!ݼrSҠjtZOW02a&d;ղïNZM)w鼪3t!+*+Wm*!tc<6 g !&[w8~X̾q_5kbƼR=ʽ ή٧YgzpQϮœVp[h`ݾ/}M!Q1<9_mG8gH~&,ض#D`Gxnq=5W'$(+ąF%(4ƺ~&5曟.=sE-|m)Y$t+Y ?ҩ~q&O>7{v%&OSynĸqU<AJn칞G2+sރc/(q\:fBӨոlbOAI6vlsS íQw}7&:sƶD~F%? c1& ,0P+<YȐٯ2*ŝc!z Wf+etqSne=Vcߣ[;/?h*C˸:ю,չ9wƄ3D?~?Fՠ,)q3vʭ`ԣ8XJRu{EEy\JBu 1y;9u ^-+~1O.Yg=ϛˬ~9 '׽Co"n+NZ ?5Ln~<7 ǂ8yp3߼=͹m<7k.W` JBpߕ><6d mjS {asuۘ׫p\WB{л;Q8lNȐq$?1NL."DR߲4Ѭ5vATz|}5{xk7Ev0RCkZ9ҩt /#\w{qIO_[+'CԩmlK{|[ \[;gջ'wU;ݸ "6T *ha�ZD" %*͛:n8qggzd<n]zzT^;Zr陲?O3>^{WwMCSLl{{V0GaTdv.u^f9+I~h*,HO1ͬor~#J.'v$+_^}44Mqo{1=Ow^܇Y͓p.9̓,ߝJ!1T^`{[؂pV8rff=4pqV~,Mھzwj{=8Ռ ݛ6h,8|Iu]s}s<V8=xBb{Jõ 9\@{o C52sJi>޹Qa}U@QP7yr#IϤ70_t+g8eKtFH_tD/W^)3kw9L1_43bĞ;Xʹ_z|?RѲu#ZDr/d/Boť7Q_/r>U=OkwFzyPVchݾ�&Q6*q\5W6,p#ۍl>6) z:V5ͭ{P\o*]K]tem=6.N}ɍ{Q C~qR)O7.D|G~Na67;7 vWunq=>U^ϡg'!gph1EX*`9g_XN1M>e?iX`J˭u<'[7Z 9~t]|_bGqsXxg"V~/9(>@1¶tga#ѱZ_-h֨bvT,Ykchl۲&ЅPbghm0AyhX`:}rzUB{Z5:ۘ(=r{M=Ubhv S>|t1; <˒ޝcWF mNJRЌ!#ރ_$Hh;Χ쫿W,̀;Ƿ?ӧ'{>:Z8/6\*\7jqBf}0zBͲYs_ӕk8glsĶ!1zA0{n`)�]TG:Dرy;eXo%;;S)=c)$R=dK32h*o ..;o=}=^c}R̘m+Q!JKՌ?[ ߛ>]?%U^P:uDD"v 뀋0˿A潬Z<iy�ZZyPѮ^=E-58N<9_ܩ/wݯ`h=|V67/Kܩ;{B5ntT]_SV TTil5BwMkuFj9v3՚ڢ;Į Bug{?a֧9֎F+G]GjFleBj;R⭀ YL{ӜЋ2Xd{ݚoq_Շ&Qf0&>sAvC՛~ӯ NC~,zg>Q"0Or|wQyc/lI;<bf[(e5- I1gߕnG 䙓8q\ߎSVS}8lᖩܼa.^s :FWx?}2e6v(k9*Nf́ǍU^eMw|<C�7P'_S]o_W^+.⸮|*v{9+_5:7ǧٽlc&/?ww G`Ȥ%OvFhNr4Ouύ*>?zd>?70Qԁ~N]0-zWѫ#W70+v"Wnчhz'ذt 9M4@|r6{:e9z&&r(5|CkPƴO>1cBj(~`Si�Bji+Wxtɚdw4 NpIȪWo(ӧ^AEhvRI``^rJqOu]@.|CHU6^Jē.A5S??彯tnCKYN#0 ."O5Iny|q\� _|4Ey xPwNz=sn|ګwOw 4~z;go@@4~z;gS 3?Η:9 qA2i c!$5u4KNFFp{5Ʌfm/Y%"9VC`B ~7>'-|Bi3&pcZ#rz}ʂ9(Dw'_�@ A~ >|}"i{t]M{Cb7oyX|iZZ_Q[oK~gym͓l\&\Y(;IȝˢOg"3zPu㒦e4]#r^K{} iC_2}R iB{]\6Qu<i}:|K`hc7 �q˼&|'>0DԩN54#Srnjywf!/7N1m.|eSBqݳ3sQz^ym Ó'eY)s{Ƿzg~H[|N)<]w+YkqTnֻfo.[ჸܾ`_Xͭ/1/mm$>tosynT@l4Y%3|bşܯt<5E:9?F/�F?1 :_嵏<obCg_R@Ρ,_!DzJG<sRz]DQ;L {3<{9>h,ZXG.'sߏ|"NYiBnb`O ѭgx>4ͣʉ#G)MiĹAku[­;iRuۯ eΌvsٶre) >>9WT;0.</]p;k⺾\�:GFcTz4.:>/<)ԥ^kRf^[{CH=(g. .vy}gC!DP9?e[^!z.B zOZf/aGĿzrB޸1V)=HOY!B`9O?$D1]!Bj)*%ϲ!<qe Ȟg$(+BQ ,ҩOMB!Z,GXw@Gq Qö!qB!B!2,B!B!uA_ˉ'/@Uk⼧ '::ΎB!B!ǎd2ےPz}}g-w6.Xfl/':*$B!B!D4l^^%%&:vN'#+ H@@@}gK!B!B5gZz:M4pLJ6mڐ~d}gE!B!BjiP=e  CӴΊ4M;/}> !B!B!AuIUUMz z=<�N!B!B$*B!B!ueˇ8'k{~3m"4Sa>yW-ьZ_߾+Smx뻃~[TmBmji|n4 .([s"8䞄Oоp \Wy)<c:Z'ȟrܙ./-?bs2VK,mw;Wj;sZV,c A-jOc|RB!g;F}= 阬eJS-[Sׯ_,jw|q7 >UpkqǛ=q.[r%ρ 8봼<j:&Lq^7[nwky̦Mڥ9Y;r\2B!B!D` Ԫ#@HS8}C^U _ZVϊ+HMM%11TΝ˔)S%&&xNlݺX8'hYYB!B! L dP݇|ŤYjK&#چF<{bb"3;w.$''hoh$//BZ[9 q;io/c !B!BqkpA)(Lw}u㏓ʢE޽{3~x&Lh&%%(`ʔ)9( >Ü8q( >$&&b43gV;aƍR8q"#F.ٳ{ =ZǍǔ)SeX~=3f̰1b?u~<ocݺu;2'%%UX !Bb6WUN(..G`!lXJ8{ e <Xtմ lNF3Ps^jwҥKIMMeɒ%,Y#GZ{FZnάYD]hׯg,X0w\nZa,X{ ȢE*_~=ƍcɒ% 0e˖Y󛞞ԩSINNfɒ%?UVr y?gn#G2b�,X_K{T!BkzKӣ( ,sk!B U)'/Cn_>t`jbP-a J_P>=fuТ8ͷ'?ltt4FtϹ$''s}YXc=F`` :ٲeL>ګ6)){tR;$غu+ׯhƏ}ٲe kyػw/+WdĈMtt4IIIִ\G@!B!BΫ?-T4L*X Zw80?ʻeӫL/;uqtfyO֘  @JJJi+C4Ktt4K..o4IMME4HHH ::>tLY !B!By CPeckQjcQpV\'00ӧνk5//Э||Ww8z8+KJJbر|%+B!B!ĿSǫRE-{/U"lm׀o+j۝zzj >Ç3m4-[ÉaդY(׵kW�Ҭa{:Zyeٰacǎ4@F#{><پqEz !B!BySb]jYW{-Z5yiF#)))xb&MDtt4wqWZŋ1FÇ0|IOOgڴi޳gZt͛Ǿ}XkC#==ŋy>|8O6:ByYF^B!B!B\(ΫkhEgeC ˦۾L �s}4i�1a/1Y-[ŋL>MӈGe޼y3&M̙3~taOYG/!!I&ꫯzjkǑfX>i^Æ k׮NB!B!3%LNpmٚBϞ=/PZ %3>k)~e->\F#zu Is~LZ??a^]!7QgddYݑ@bbbahwTFukˉ'=]퍏,X$b!%%]:^B!B!#WOY_4BQ:as%jhcQcZwC @%#}QC#Q;DmSB��IDAT~ftzI/[E/s݃v\ η֖(nY]kKz !B!BY)۽{FdffҨQƿba۶mSV!B!B\OY! |)~Y տlc3 ADu+w}O!B!Ҡ:UUtрY,z}}gF̝ P+n>|h_~ώ|nOQ{/_yW?ԫSjU!B!BA CXXX}gcu1(_}gj30[}&6dԴGڏkhs<|9O^>Lvxgiz1풐vekPJpN { Wu C_i˾B!B!Ŀܹ2t۵]XLF6.111:u \Y d"##ƍ;+bܹ<S֭Oǯ(FdPi=jI>'ذn7&e/ҊLM|3kOuB!B!D >_e?g^ˆ\VtTO yF>LF`hPYtJzʞ;f|222 ((TkǬFQG{"–4hpQv[Y&q/qp !mظ5Ck!Qh B!B!8ڴiS/i?8l$N8AaaykСC `ߟƑ :_?zڲ(R6Oѹ8̑"'[ZT"N砺4d!B!B\P ,4ΆubڴG#m%8h-PL$UBEG8=`@Aсl �>1mlC 4B!B!ν={2g\Ls4mAY!-3 W[dO+X=WÝ+\؈A} &4S$NW]T Zr$F]yB!B!WfI}M<5߭qPV?m#OBxj- ;?z5NꉈoJfM^-d/_.ݵD [S8 b$3m[~OEe8|Q^%*!@W iȀB!B!z"22922^z8]%L<J:AنB?/`9UEO=7hC76j>ŦKXayfDD_:b?OqT`bIB!B!8OIPVaC#g+<N&}{#e�!B!BZ&AY!DElxG{`bwB!B!D.S!ٱMtYGBdW!B!BZ!AY!B!B!C΀B!B!BHPV!B!B!eB!B!IPV!B!B!eB!B!IPV!B!B!eB!B!<YXUU4M**(q6gy4Z)<B!B!BsQLTQtyu9sM6CqI %%%X, ^0Qmv.X,ւt:E!00BCq{Q\\LΙ\2331h֝QҴGmG!B!BQrΜa떭degSTT4&Z-( @b[ !! QrT*¯Ɓk <X]r\y,KY/VBN> ">@i?pHLL Yˣk =MHhXG!B!BQE᷍s}܎;~Jqq1ѢE _mOo~ZlI@@� ߚe-% PރUQ ED6 88a S4kAU k ɐvPIyB!B!/77}qL< [2͔Ç9r$͛WXJPvѨQ#  iPl0HLL$tNʢuʶ[;ce*)!B!B!j(MGDDDbzB|Kp9J-*,S!([PPHVVZfMEQ4ME!""4z=]֠7PO\\,F<B!B!BڦNPPPc1ˇ=(b>%և^ re EF˔g/`6> AbAoK)B!B!hH,v]"nze,Xo 'p+PfL XT*w+ef m}�'/SX ^i4Za`Jc5}zf3x|[EYM{,B!B!h8,kYɴPߙ|3޺լߛV೮§oLѽ$&,8R5l][fyTU@͠:# [^DrOfY&a ZJ7~_RRd" |///L&kd*}Yk6YnYNƠ/kG!B!a۹^YMv߇GҠSѯ|l1,ՓޞDOzjmьl`&,'?MO; ڛkuz Qg޴F:OB-qZb�1<b)ދ^t;NW:TiOv8v ۿE!/rLuNY \cf͞MII S~*t:,WUUbbnK/\vv6( 7pe<B!B! QѾ/xiFr+ƁBhOe1eV�FoNodqo+@^V~3rǨh b/0SӨtN]0u݆q8Y,S%([-y4v:q$>>>QE<1�S _9}b6WNkl a"{$4 nر/HAA�fvtUUպl�̜96[;={>}:?à3Y!B!BFE'I^?m) -t%*y?H(BI°{:UiG-k?m&I{]u={ aoʣX"(=̵ɑg{IjF |'Q;>9U>ΖMˆ|ssʗHXva̓iT9-_|vr<OGXxB48o8q%1{]ŭw -{Ԭqė$pb3νmQ;vߺi[9`w;^>LvxgiQi37c%!(Z;X̧S9G.++氾_ԝVKa]:;ij/kYylUףi;b8LQq@i ahFΐ{Pd+0tYgCU d,,[@-( :1e<hpٺ*B!B!Db9o=&dFl- dWFgǿ;YeC2sx|:_}+u%,I6{{h+9>-BaQtyenLiC.~kv/@KAs[&BEMl@39(+bBk&p}+obWq!Vf ^aaxM.u';O7)-߁=QupU[g 0.4'|Vy;7m) nDV@Ih/%<|ce@ (撳/~Wa'M{v<vu9̀-{;vK/YÇ # 0O?_!@$- Y,i�ԓ9)B!B!Drw,w�s{Tt~~>6и]?yVXN!W'}GZGٙEX=+hy8j-ݸ5]:�oYž)3Q!(EX�a=k`k >CFf ~11mg}ѼR\S+Haͺ4Yyi}Slr|wgyak#dd4~{!)2դ18ܞ+֙5ͺ't v쾯>wӎnZ.KAddfdRlƭT\ƃi=eIԕʁ;wV`6o|a>3f3/2%'WY(=K+|x.B!B!DCl/3}2f&W盙5fЊ:Kb_g \y3K^~#=2x z PQ:)U)_9TJ`A77,]x /, _Bq1xx YN[rK*˨'p$mb d|òo`ozc6&`7 ;2 QvgЩK, w% (}N9协Kp)ND=(t:ӗuJ#M$1 'PG鰡C۬njѣ-[ճT)[i;n\!-_B!B!h4R~eS}.n6n~cO/'mL!</7~)gs Mټ5-Ēgb{)]QtjR;5|-7>PRRR)2~{ImӸw`@Rr:%iM0yj] ie8�F㔅sȿIጫ:>ǝSPt`6e9M[C7؋eFw?&޻:]f,Za[B҇~ND4E+/̳.T bh:t(0ke5�̅ V۞酅gϞ*٧yвeKTUeϞ=�=B!B!h{gL^x~&/|+3.!ALSy/eƸXN-yVgQaA-薴pqSbIhQq"#(<Mͬ}_0ݴu*w?n(nIo>HerDmWs|sYh~7 "e^zۃraV U'{ʩfq""On,l<Y�%r±.]�X›rf%rD9'Z1QUo41!og!v{^{hNTƨeLG믿'>"77>KZZ�n3`�/8B!B!htLQAd_m܊ ŧSH m*+Ռq-"rI=|ͧ^ ua<0qd|-^tk0-oӕn /|Eʏԟe/Z%W8hDWo@Ͽ%=v$7([?96i'q5fHh'9AD"&i }&[e"=W+b7oؗ1x|:_5Yq(-ntOk�-nU}i9ڟgDFSNa٦ms@5X9Jq+Q8,h3'?? v5\z`#"PU z}et i׎4 l ;;lm1�*]yB!B!jyvp }`-c+_1^d9¦U\L-:pEdG,]fi~6ş7=ͪvF!<)@|TH[M,GI=XLqg̜Ͳ^SzyWꪇ-yt~D9>k>gyG# `-#|6 g@;o尘()Q ړ׃:s;uL4.awxS3z`"ww8e2tEUU˞tr9wZY'L*1R%L5 XT\oFӦM C{4m3b &Q,q6nYȲʦ͛IN`?Ro6ٴy {BS;֑3<79҉esϺ=uV!B!BQ ~g䅘nW} SZ._;cxa`4z xF5q3̝ʄ9L^$$y~\á$� k~_혨=aX"==.츼. =<Qs .R5AҗlvJwjqI >>h4(̣e/raYgB!B!դ{v[ P|k?a:xTqH{ >#{{a#i+&+r%1nj:|=đo?5Ӏl9D)TB =tGr'.:Q'9 :c\sgI)f 6w}n (JݕG!B!BTVDMpSEh>!'sCcZPsK4)A46,|ϏOn/F^|I >{{ϯ1Qg4M׷ zMh4ҤIQܚ8qVq(Ju:z=&??։ ecVeX8|-[bXT4Y@jeGEl+V<B!B!Bڥ7ؿ?99gj-&i%%%H֭K;U^YRRRdBUKVe1NWW崜t/]KCaٵkNt:7dݘͦ<uw;?v^^uV!B!B!DTjDmPULII 4iV^ JP`=z&j(,,DopT@U-X,ɓ$&0P___6iwkMƑmw) #B!B!]HB|<GCݍkaa!Gpp0&SIu* _�L DFFOgdb) ,jVơC.ayV^N#,4&1DG֓ʟtf4ٳw/yyySPPHqqqǃDmG!B!BQlcd>vLt]CYOGpP0 `0`6 e&VړTQte=HW3oxvD+uuB!B!B.Ob6AZvj_ݎB!B!B'3B!B!IPV!B!B!3����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/tagedit.png�������������������������������������������������������������0000664�0001750�0001750�00000141700�14035600052�016527� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����������sBIT|d���tEXtSoftware�gnome-screenshot>��RIDATx|e?ֵ|_ڻe翲?YQD]l,G)>"+E4VUi"ENBzO'$$'0\ΙFz]3}瞙\5:IzzVZK. sY˄Fh4F5AA_bŊ8B!B9}@y,4۳^QQ!4Fh44ډ'|ӎ4xVFh4r }͚5kҥh4Fhe˖- `/geh4Fh-Ϡ!4Fh4:;Fh4ch4Fh4Z 3 vFh45Gh4Fhf4Fh4Zk5554Fh4;Fk x1'hc?坎ceeih6+ثi4سo?ordfTnc{dr(E/#Mz4֌F[_d0)OƉ''0|y55Ƶ@[Nk:m[[6`*5؂ȲџG{Sy0xȵrk^F!v6 㘮#1F9Nw#)0i UUU4nL/5!ly2i!e{>z\:a=zئ~ yCe{5O0wMþ]᧔M߱eR/ R]2ģ}bq1d t7fL),DOYG:Y&_y{l{o\2b/q-hSȱu{a= vƛ>5C@oڱKSe?(7x'2eWpD>|0~Gj~ (/ir/iyJyKNm>-2>QҲl+c?)gcY.EK_R3eĤe_u xfO&= -;OK`cZBJHEEGm/7Zn-Pb⤴mFk.Ds}ߕwkC5uӧhbՄb5]Hͨ9ꆋy辨X5~Ƚ~&1TxeU6`= =VK+{m$/5@*]뀑.H°~9핗+Tˌ_Kk(2Fu7\4+!qOxǴnFۛ6`㚰u8KZؖ WS ]L-[ڟ޴Tфi>Z./qy vx_4Tx捎Cwl{9)ZG׋ˀƩyQ.e%}t}}T*̇'5XWTTh4Z1_H-Z[{1¥+K"{ȸYZ(Hv3Q'vioo}ǥ-z@z !% Pq yTo)э鱜,r&eWpʂ{>0i;Fʓ,O=~е̇ȋG>L;잷x*aQT;tgik7Lt _\ۦ{lھQXMDKzVHcd]ϪU뱜3rA(mFk9MK(* :2:3i hbn*m9_y&aHw ZN׏қ;.Mk`I[ϻ;Hnh6j2mʧAhm(i4 "%V.dk(&yi42F5/[pefr<h43 vFkbC;9:0Ik(;:/q<h4ZK쥥4FkBHoVFNQh4FhA;NFh4ŒFh4Fk ph4Fhf4Fh4Zk%%%4Fh4;Fh4nh4Fh-܂oh#GbFhanNF}׮]{nٳgݻWYpp0Fh4O4;!M(qHhhh4FY2hhh vBPb HhFh4Cfv`' ;.4\x'4Fh�� -ANH vŗ,))Fh4ͧizZQܯ(7NH{i-9!!A]4Fh�� -aIk( 1eiu"ܿ'{X[mh4FkZ۹kr|$%̇i^vh{}=wy{.t2wi4Fky>},e  Ш݊=9%EVJ~LG(밶a?+7N4Q5ejo v"O`Orv씣GJxdOv vb=&&Չook`d?%՜_ɪV{f̚-;OaDtN{)m,$þlJ5,-U5.юe+#mP;nNۤH5{=dͺujj y~ r 4^5TW.#mP[fGCu׏[k/5SM_G>!|8Lur5ڰ\~^//G|1>o,[6oq{+7OVZQ52{\}Y_Α-~`>Ÿ'ؼ/l-׹zXnb<ʅ{X.jY=!Nm8uWu~5Ha;w.̮9*x5Ei/]+**{;VI|Ȩ(%#%Ƭ c'|"7mV)ȏ?2nڈT߷C8e;CU[?Y#o{u?5i 6i?\)ۙz`|J@?4H/_0ڴN8UWqvu @㡡ajxނx} v:3/_Rö;8^B>aZWHіVw= lz9+eklne^mQƷn.r19#7n#: obJ}Fzy.O>ֽdzj́7{;,y}pi:̟zr?,TӴ1$>\_hm^_^AL׮Qb|N`ij�xjJ:31'M[uY|n8s d[A_HW5\kmJ;>[h!VE,QKG(۸`7|`?_/W:uRb\̑tz=/z~%}'>֧h i%۷P6E\O {OدUbU|tjag^{06^1/wȹϹ6R[g0;!)1M$OSU߻y[e4;΃?ڰq;s(`( krJIathX;f }V  v:Rg׆.)R:{vb4kq+eklnu\L!&|6ɝm)qڵ^ex%1zZRk�9z*7lPNb^gi! /=rC,+M=OB`7`_q;]_M>r؛R[@7u?`o.?L۱sK8� �x9VuV؂>)!{[_;nس^b`<|Rק|z=tO+l몇 6Q4P/p=~e7J[A/1;ʁM7%):Cz>T v|(i,qO۾c,a^O +>mάlMK>٭#!Ӛ =@ HG3tqh!/vHش6aO>Qb+\zmAvյuCNgu vBZ`%OM#A{c|9o_.Wp !%5ƺh۾? 섴B]񣇝Fha{poǯ`4Fh4Z13Si4Z=Fh4;FNh4‹F`h4FNC?\t4: ځݢ=**JTњ9Zs1F5A3@;@C@K .1.5R^󫬌izAQ_A T$c{qٶT^YAQҊ2i4ֶT{{d_g)m&l[t/>R&ϓK^sb˩(iEB! 2v!8M/P19 Iɯe?4Y["_aӌe7&8ny7ۿmg_HT ?ɒ"²2e?99]ٽלt9~"B!YZy0mN/\y6ˬaX^,+E^VlY/ KB,Tږ`7ڿmowȋsefPT~O?R,0 Zs7EUALN! fp iT Wd{~&Gu^|1y?68߇]Ӭ vηm_=?G>~Yϲ<]G[ELN! a74ti$>%k}oH Š%PE2;!B([V 6ofcؗ]/ڑbCLN! vˆSA`_naG/*KwIz@9rQSaϮH"}aǰ>~{Jwx!8S3B!þ*D~4]#PAn 34Y LqG.𴣧9;DcXמh6cU}zΤ%Fʎf6%84 vB!PK}㿨( !BRlMLmsqTq v;!B([}Pʏ?R`QB!F`'B`Z`4FڇQhTEv;]#mBw vBH/: v!6J!PS 6J`'PS  vB`'QB;_s$~@`o! 'NK.2rH5McҥK9kzK-OǏ=q14̿]!~ ṽ}rK/$~u:ٸq<N7xC xU!~k el)9݂}?hqL_* vBϗ{Wax…O<lڴI˕H߿'M${<44T߰0˔)SU!!!rw*۷o_&UN~Νep8L&L^HAw~|Bt]T8 !)hHK1]nݶcm8oB;vT\Ý:u<E]di6M*9~/sϕӧqLJmmL8Qnf۷TTTnwޑɓ'+v=?s@ˉu<^jYn*綾^*7p޽c٩SʕW^4U^.^mH'߯w%K^ٶ;Q<,eװ?vrJ$.\,]BE-Xs=Q8\s!do'M"q/E{ZjZ/1U+Ƽ!HC| ڵkG\zHr={ʻ+ ۂڵ򗔔H>}dС~[SS#]v*05`Ȑ/28PJKKeѢEr6~}y,ۭ[79t2 ?v :{á;z}4My�|KՔd5/X?<2򔗂aR믒r'8=?*&n`uڳ4`kTjZOMKSnG7##~gzx0|Yg\6O6bΜ9/au]{Rr�Zn;馛nwŊ*]Gvʕ"ثTNe-'G/g%))InVۄ4v;0[{gf$fSÉ6_,KTVVBwيj"ڦK8`|\3?,[D4`OJnmشΡ5ξڪ xk!! v;w*O}@j_%/bW/ 0D@_wwzد ZNc=a| xǍP :>6K4E囓b~/XV;+eoJ^ǟ7lT/ 6|ʆ/;il=En\{v$ح/_\y=O?>Do4`ذajgu/sww+ isZ&rG=a׋vؐ%صJaopO_q{z\|| .S;ilf/&hvlj7ofO'%P[ׄڰ2 !Hϛ7ϰlx㍲OXJ~c9t`/3gTi-\)3@Х7+3f̨`k""k}r"}{v ;=^SŃEȅg{r GKk6eş6zɀm젫%)AWr2Z{ȾPu14`Ow=^̀ڪtT|cLC=BH;xi0#FxL'"ر,_uV+ٳU87;>pET7v? vR\з9a^zcTΆ vπ<>E>=?i{¯pOzCȋjOKϐUȢo(CoNnn Ç7=\ïÙն=_P +MiȵGiGmY 5xAz6J!섂݉HEeJ}o>6NBN`'섂%<t V}aBN`'PS QB`'bQB;!bPB;!섰B() iFh4Z6 vBa'B= vB!PB $5-E'J,9òڤ'Bi͂ĉ2|pK9RMظq<Ny7 B_W袋Γ;ʪU e:mOu~ 5E| U:}aᑺǎ=;)!Қ{,e^p{~Νep8L&L ]t\$+eΜ9'"={lX-ж{Bbz2)+/28KKY"5ߖ%mAR=oT/X [9 v۽i&8;uwr ,ॗ^/4c 3Pjkkeĉr7+߾}½NjjK.R @QQ{{V<Fx ٲe{|ΝңGzSNU/"AkiVǏ˘1coT ~>Ǫ_*e4\BnR|Pun۶mr=yXFBNq8Z֭['&MRedcC^{ JCgT y-S2m槆ĭ[Ķe#5.~:Ć6JBN niQV^PPP-_@tN<-\pWf3)=1}tڵH>}dС:t;vHUU8N<x/2Ho9viiiu&R[.~*?dddC 1,S}U? /(cnn2xǎ /1<6 "[oT-Z$^x*6~}y,kT m{A(Ay)q({IKgJ-./xmj섂 v3TTgu_O m! ƗGC?-;;c;S8G2 >Pn]ІaÆyGϭjv;cO[<ʋ}ˋe㕕r={XSOJ Ǒnڃ`VQjW̬tɀeIzFY-QAU sNI޼Q~MMmra2T/FG+K}bw}WE>"׃ !HaP7n<# }S !ax2ՈTxk}Fc䰯]V.ⱞ%øZ-;կoV~k~tt_ver{Phܬڃ`9)Q/.)rY 9Rk$E?Ip. #1QM c"9QJhG~ZEaݻw?1?! @s!`^_ }ws$z~;Z.|Cn֏=מ5k{1 ןWszح Tnzc vzlhk=6-UW*\e\%֏&/w{ThQ(YVwa[Ҏ;mFļk~*#Do\\JeX`zd9s\`1!!AzѸfRT/u+)72r?2h^cXU1+g}rQnv_ϱ5 o=<;V*/zX دz t_ͨHtL%'saGB~RX0M$h5,REHS@pCXVBa6!>H1まrJ瞫rIz S"Q UMˆ[hns9G`Yp:ǬO>{=w 0kVvЏ?Xc}>ǪCsYb²epǷ�Q== vq pGi;Cv-%7%Kg&|,c6,REfv3Ҁ<P;;!줉nmcKQc ҤDalX^.IQVE1"2YlY-͢H/E9~NY_;!섂{DdX]?L$5uTHNr;$EGN v,_,f1o"1Af9F-%<Es瞲;C"4~'*JN;`g=!Q'س3$"; [)Y r0'[Γ#BMB#>>^?"`'% Yt̚>ErJvJزҥ _NTUUJuukOj) i1HЍ|J!Җ{\|TyA~TKm~hG7@Hy=>R%PBڀ`w8Jh`lDDnD !BN{3 vB!P‹B!PB!BN! vB(؛KIjZ$O$XreIyE9O"!Қ;p>|Aȑ#u>ПÜG eiN6nܨ k7xC x~ 5ET맂?Jpu#u9z'BiM}rJVV2 /\,Y"=PiS ٖ]Ν;իpHYYL0At+8]YY!eRV^*eNq!Ej-;Kۂz<^@'&B!EwQ6mpN<A7x8pQ{MMrUW)0闝:u#K/T $G Fez'd˖-;wJ=,V&N(7|>W***<;c gqe?aj\}ղn:4i* 7 ww]\+X%!ֳsl*<˖) IHSSCH-b۲YhonsZҋ;i= J?Y=\[oiTpes=c E]$EEEB%$_>=3Fu&%;vDz!e?~|nr19~s=fi?ӧOW+^Z#C?/yyy(h" e^uɓ'_HHq1Jk^uDJv;^RwDK~A -A[G XO+5k(gGFF曍.51b<ì|B(gy>묳aaa*r$''gC~~RR|#/7_|Æ ;SE4~M7y]nWÈ,x#=кЎt^)DE+(+zfVd2$=#UR j; sNI޼Q~MMmzKuW^*2@Ϟ==V#Tm۶;O]Z^K~>˼yՆcN m~aDs h0! v3;RfpcDݴ𰭮vc˱vZ뮻TZW//0`y@7Px uqGN{IzqI ^(EG tw̑Z&)IwIXɍjzСرCt(R~<ڶ~>^j4z&~iP~yiF{O}gΝ_}{p}V&rx1la7SYf)σqbگE=ސ6.c܂^ue[RBBnWv@55h۶~={OENLSiVS3Ϩ+C<᧟~ZK/$7oVBZ`G8J/1VŦFQ@&GX{m syP#Sotqv|\`i?3gTܿpȇQ_{5?2A#أc"�/9;wϗzib%ITtD Hum#D }~Ztt o@Nv<҆uxcqg(z诬Te֫O4;.bu# pх7= oXQp0`( �?!|IKA^ y^swcGh/>ݨ+WTa[p�#>I�w^3$o)Qb}I\׻zV]o2Q'!4phxaƯu|E|-cذaeh]B@bR6\7f秞zJL5�=awD !LDnbR[/1p)MYN։Rae);0&!^0333{f,B/+q^k.!F8zѧMa+mnqF*_:N� p&i'L````o&V{y8S7IMa]/Ui;).Iaё6Kkx97`7P-[Lm)-KvÎ^W'V۰6g"ۈwd`\X} v v v fu=;#I"P)O θ*s<)) G6`'B(۰`'aJUKˬS$7ad-+] tHUUTWW>!aB`'y{\|TyA~TKm~hG7B`'QD-df{%:&J !B( `o&N! vBxQB! vB!PB( !BN{s 2IMKKN6)(I$BZ`GÇW^Fo ?O_1'G ǿ5&G}T{5\#oJ`WHM**\bHD\#B!Hϟ?_^R 6m A<i$j?aaai)Sz޹sgYz8)++ &H.]x%P+ veeWIYy9YZ"2,ql yz9xU} !P;ʦMԩSǏ˘1coT/=V&N(7|W***|nfUW]s=WO<xPRSSW^r饗E]$={"w|Eʂeg̘!_q>jYnz@nٽ{DzSN+R4h\.^ X%!ֳsl*<˖) IHSSCH-b۲Yh`'><MBnICj*\~J$"e֬Y*^ѧ~*?ddd?p2d{v׮]#C݇zH�w}W 6#<;t ;v쐪*q:ޯ_?ÛYY?/yyy~yRZZ*- /PW<֭:tHǏsxi<yуW".>F rͫpH.vGK\=Sbnp/ȗ}%7hTh= 9噆;!E 3<#gu)Hddv 7nMN9p{y7tΙ3G^~e5|JNN\wujw*,ʂu n{eIIIr뭷& t^ ظh%vQJ XfgJʞ$a{]m+Av)ɛ7ʯM^oF-_(:^jT}?)}{>p�a6pX-W\q{,HT7wyR]]s?_(e_M_"r2^2&z/$nfe\8uaԓqƹ=`GeRl/#RB;Hm$$,dD5K24YVZ "kt<GRRR >s/fު`7&rnMnn`zO? 6L?eFA#_}|堛,`{1î#] (`W]YFrsX?TcVHnٔE"MVը!m瞓UV?,O=ǼLݕ}ٲeeڽY7Ш4! yl߯<_ZR 77@3gmcWBBJm1aLl /_ܽ k֬QmJ}>%AnEwYرc_{5U<,o s)5c"�/9;wϗzib%ITtD @[f&+=k} {G=lrJy:kx_Ofު`7&r <Hs1rJ⃇ QFy<X6f? ͞=[y /vZmWv)s9K}˄"ۻ4`rwQ G/8߿sH(5(-qpgHޮ%RƓb}wd"OE4AWVV)I vp]w)Ӯ<tHHH曆ʬ[fD !X [/1p)MYN։Rae);^#"ÛME4!MA D ;i~X{1پ}fj"JB( ;iau3uRC"9r(9)ر|mԛYt+H|AiGܹs)I vDYFh}vk?,[4!PSQ'س3$"; [)Y r0'[Γ|xDh vBKB( `L'd2kM*)bJ|q:RUU)㄄Z vB3TZBN{@JKHMMbvtI B( `D}!: v[>JtLNB!P7`'B;!( !BN;!B( !B`o\.$5-E'J,9òڤ'Bi͂}8 .#G<__xrŋ- ??_^{5w7GyD֯_o( ъoKAk裏k7ސ^9mTHM**\bHcDI%BZ`?{r .tOMMnA{%<SF]e$;w,W!eee2aҥ 6* veeWIYy9YZ"2,ql yz9xZQ2B!;vM61ܩS'8_~Y+_^^73nÎaM7$w<h Pm/\uU0i8r- cZ||ĉoVQ}JEE<D[N&M$^zzYڽ{DzSN+R4h5/^9mT'ĪcS)0YLɴeHzFGnۖRgԸD{K9ڣG^~2nܸ@"f@#V".9BZ`袋=^XX.n 1cƨnJ9&e{=IOOPn /fSB^fKUa֭*zرj"۶ms/$w>}tUE,ӧ :pRYh<=mW[e_d0<~xűO<Yz+ �ּg8bw%3%v |[rJ.FN(}7|S^~e%a/|ז6xA5۞ƒ%K䡇5GHKck= :,8!85nRVMwߕ뮻N.byW$//;r5*++f yrr{^[oU #ꀛw_Wyr:hv] Ã=o~Y}e9'i=6.Z vG]y3%&gDIX^W[IvJKH45E/x6mǵ1ӫW/5={oFi`Ե?Ö6x{cA=HxENH fv4 ܜX{<TWW1i�P?"x9 /D>~h <C_6{IzqI ^(EG tw̑Z&)IwIXɍjzCӢAZJߖ;t ;v쐪*q:*ԯ_?2! ?l~j+T+߿|IBifox{+xH83Z`7k9D@;P8}X v}0î&mLF;2R%w׷b9WK<fݮrXK:D[ @W4DW_}}>g[h,/T* "W섴p3rV0?z'o#FPyW\q߿E QFy#Wp[L>sL i һwz t_džv kyō9''Gy-v{tL%'saGB~RX0M$h6+BoˑBj&@buh􊐆v&B[g7P{}aA t{pإX~BN`{ذa"AP{?!qM P37lؠn(Æ8G*>@m^brf!0K \Z୘={nYvm v<w+WTs=W}pOڞ`!yHO咿%ֳz8mv|oo˘:AD} 4zEHC7NIM5h:v|=( i i=2*^blR(˥`4)ʊSwD]""ÛM#wW BI~\fzT/of+B2pR-[L9A)Yf"ޘEmB( ;{3Ȱ~KřIj zJ!Op9wH XY B=D!w/1Ss9GR~Y@FenX'111Fjo"ށFPD|!PS7`ITfJyqƭP9-III]IxDh vB!v/Ô�?!.YӧHnVN [V鐪Jr-}BI-;!BN{Xt _. юn !BN{3 vD}!: v[>JtL!B!PBLB!`'B;!B`'PB!y`䄂]LRR$y$<,M+y !,чտFOh . HXkveQNKK;%}㣏>k7xC )-q 5ET맂?Jpu#u9z'BiM}rJVV2 /\V?^⸸Xƌ#;v`?IΝed„ ҥKt vK$$Ʃ )(R)-sDe5W۲ı-H͓ xbb[ YC!yӦMq w:tG?_ /W]u2 cǕU/ݨ(d̙jV&N(7|W***Mc۶mr=y'7tK QZ֭['&MK/Tnٽ{DzSN+R4h5p\NnX%!ֳsl*<˖) IHSSCH-b۲Yhol[D#??_^{5uGGכ@#ǁD}믿!_~7'&ؑRTT/,,T7_@BAjeJnݺInn2xǎ^O?\222 2zWڵkO.]vUקO:tM([oT-Z$^x <=~}y,cK Ǐ]TL<Y cԃ_;%RⴋQ,"xϔؽ[$&*\ e_n */]7H'* ]v_WK]Jj$|MyU9a/|<'~g1䵞gue!To6Mͻ[$99ٽlbbznMM/RZwwʁkntSg|ْcpF<ѻOOOgK`Dl\RgfK,3M3R%ej н ;wf쩮Ky$ٳ,e5ޗ~5(޴i(؉8[ (r l3 $= vv`}z?!*)M9�'e1i G27NtBektS^xAovMhFǨz:%V9)Q/.)rY 9Rk$E?Ip. #1QRoCcө"RX(HL?Iۮţ`'$"ؽ# y vH8! voX.88Amt #aap6 /<fzgqy?6lPel,?F E;>ݒ`r vxՕeJožsGJy ݻ]y%}믿u $j61Dߎ}] _,Y"Ǿ?ٿ{ygҞyLs낂䡇 o/rFÎQT{ffv\!ѧ>>vxBB=9ީ=ăC#զ>ݗx޽sa}>n( nHǁ9VTd:Hb=_jݖ$QEGFF, HT Q3(;iDm{1K]sxG}P;~څgS;n8Æ S7؈#Ny#l_~Q/xx"a"?V8ܨf̘sO>D#!>T~˖-Sx}c v-70`�pV\=\G߿w><`7C wZ"%Jo<)֗KzXϪM&2vxqhD̢fV=S pZaG}vo̙<! v|P76Qc ҤDalX^.IQV8"2v5k֨UDj (?;6xM D33 EaUhc_Xd0B{G8ѧB( ;/,#"a//g&)*m^?ErP!),:rRcfoG_x9 2rMl=HGhSHċ$;"Ǿ0dۏŋU&]QBN(Iku=;#I"P)O θ*s<))KE m6N!PS{'d2kM*)bJ|q:RUU)UOHX>`'B( `o+.A^#55R[e! $!B( `o&p(Ѿ/4Dgn ٧^RݣB! fB`';!B( `'B;!B!P7`/+/ԴIޟ(I>hrDB!5 v<|pk7#GzFgqC1*f֖9oy\sRPPVKd@jT>OTG&;&r(O*!Қ)gee)… ;v(Fá죏>RΝ;իU=Ʉ K.lM& veeWIYy9YZ"2,ql yz9&MK !4`޴i{Ý:ur_pJ|ji }J^K/.Hz)EEEǏ1cȍ7ި<_|{^mmL8Qnf۷TTTo۶M9䦛nxU>l eݺu2i$UnAvԩS+T $G `X%!ֳsl*<˖) IHSSCH-b۲Yho "4E~o|{$BN`X B%^5^|E;v8N9=zYdǎRUU=x`ׯ{~*?ddd?{2d{ӥk׮*"y}C#eժURSS#z˰|T/"- /PE<֭:tHǏsx<yу{\|W,]b{"1Q_/wKnV6x``o~oBH 3<S!$>묳Rk^ ˃ay@v$ yr8Q. xgϞ-999g08&''Ǔ[o{ħR7`VQjW̬tɀeIzFY-QA^d箝y53fk3Pmo;**J:9s{޼yԽѶ|^]ƊE} i۷SBN`7Ëu};5F<`}{eax@^.L2)?f3ǰLF97NyZ &1';<%E.+b{b1Gjm(' %a!{$7&괉 L{=^m~z+dڵplJSO"+fU/ v\xZ섐"r!"i e!y6BfÆ ;X]aǰ/'M&c܂^ueum휫RBBnWv}/PCgggH /kS+++,X7z!/ؿ)섐fuzܸ ׬Y|&!q}aW !ox߯ һwo_~Y=<1t_ݻhF~ko qc;{S H%KNÎ 67amIqmòrY}7$fU/ v< ) !]!1l0w?#FxpSO=%_|~ZzBs9*79e!zr�O@>( ^#l2m<0[ %ص<UiCcʕ*=r)&% ۵DJXxR/.UכLdT v_ؾ a\兟6mZ@x5o`7E)Z`3D\섐.Iý0t ȨzKir0NG/ Ӥ(+Ny!@""ÛM#'k!6m9~CPB#{A(f佥=<Pg'!P 뇽TrxICyIk%<fi( 闃O>Ē`=h0w vYTwOף^ dey+ ! :$AIevlgJJ9rpԥG6`'5TV!  Yt̚>ErJvJزҥ _NTUUJuukOj) ! vB(؛GJKHMMwYvtI! vB(؛I;%J YBiWcGB`';!B( EGN! vB( !BN`'B;!%$5-E'J,9òڤ'Bi͂}8>\#!oȑ]p8_K/T.r7n\@oO>gkFx )((`+`o4HcTGI.A_Xxnc"GB!Iϟ?_^R /+ {饗믿HW:w,WV/=eee2aҥ [1{^+++LK)q9Hͷegc[Tϛ' vwҽH,q}f,p:*}ٖp ;ʦMԩ{.SDn G?=55Uzꥼ]tS<7twyJNp?~\ƌ#7x|y2qDUo߾RQQaX^,\}ղn:4i* 7 wXvԩrW r x`o4b Xα,[d2$=#MO #[mf)߳Gj\ x Lkאsfn aa!6gXCXn =+E333gQ0Y2yYY΅w]1$0۷Y=9 o޼Y9PzK-@!+m 򚝫V-Ѡ⸰P^c~~c:Ȏ;JN <X / 6Mmx/~<㒑fȐ!yӧO]GjXށJii,ZH.BUmX[nr!e?~ܓ'O=zPS7q1y)q({IKgJ-./xmj]@{:f@j*lgS [-YQF>HMZaɒ%Cr fe1; e۬/'xB9jPs>ub +ucV@I쨬ck= :,k&[+rga8FD|xeen;q1SoT^ݮkjjN~dxRRz~�t*` F#6.ZvQJ XfgJʞ$a{]3Av)ɛ7ʯ"Vm&s'mf1̟1cqj~_$̓M5;.3o<Y)ske]',(UW]%ӦM HؘEIr4`wnwg~Y]S } fe1:fמY&Aףپa4;G8 buɻn̎Ǭ6aXHG>S7GFFQC;qƋ}uu@c[0`=Z-80%aGy ш9)Q/.)rY 9Rk$E?Ip. #1QY $Zet-" ^< 3E0矗<4+?Q$Pd\uX4ScU@ĪBӟd֬Ycn_E)e5Z@m}(/(cǎUѣGiVzc0+sL@m ۆ5ivYv):Xݾնjv<f \:ל9soL4 /Y,䫟vqZ vþ<zю!`o4+H]i\%֏&/w7Fk)hѵOٳ%''p9hYD 󳳳 WO?l S d\uX߳C8U%<NxtsGCD"ǰe̬GoT;u fe1;FubI`uhV۰s}MZmy֍|^nmxH;iu!\#4bMeٲeO1oO?{|)>@8$?Ɱ[̙3+.^wtݻww{?07;M�Eoa`oLc"�/9;wϗzib%ITtD @%0 Vmf1@fǀR?)tfe&ح'+:V7 "�>o~}έtxv"XiVzԗÔ`Vsa!Y&}G}[mΩ5iܹS_} v1+o v\ vĈ7ŋ˵^BvHM oGVN'sQyR IF =StwJc v-0`lʕ*s4`o 4(-qpgHޮ%RƓb}wd"Z`C i x}]( <Vmf1_ $gt}`Ku~ˬn9Oj=|[u@7f7p^Aڎso}fa׋M}]F׋YYE uI`u16ofפ6|r>/ a5xjU4 !-#%.I?ˉ:\ 6L8yNjmDdx#=sуjAfk;F69C9M*6ThW\a`tnc'-YeDPlFPPJffy6E!Ɛy+Ӌ13\ՉY&پhV۰m]f=Q/ˬfYy v vB="2Rqnº_vS$'9\¢#';mqh=̝;c>a>JQE"b@F@{ tFeVDCErFl]ᆱh/1ff-J,<.;}S룶z7h E䩧/XO?> ZFc 0$0۷Y=۬ Sk󠣧+Xm=ƨV ;;`ovQ'س3$"; [)Y r0'[ΓbxDh vB!=k vB(aJUKˬS$7ad-+] tHUUTWW"aB`'y{\|TyA~TKm~hG7e`1! vBHGBCt춐}(!B( `o&N! vBxQB! vB!PB( !B~z0]/($5-E'J,9òڤ'Bi͂ݬ;1<|pV'#GZk?O/c3 ̿Uς NiӦVR?y7WW+RSJ~* X/,<R7מ:$BH+fvrJVV2 /\'M${<44T',,=m2eʔV%G!=?x;wիWᐲ20at҅WW+ qB+ʤTJ˜,-gC|[v8IyRz<c[XǭN׬Y#_}= HZkof;vTc wm6\uUrq5_ȹ+ӧOW㘎Z8q| ߷o_po+55Uz%^z\tEҳgO)**:\b妛n;O|AItK}{l +B2_S; 6Ȼ?+UAꫯu֩"lnݻw{,;uT+A? .2o=>!V rJ8ϲeJ-C3Ԑ=uضl={GAp.KA?Lyg}aL_hf [xwr4Z])믫ƍli,5$1y?o|U?󷌯�{rʵ^+/~BP5.<CVۿon#a]*/>Dt>}dСtAv!UUUt:g_~` /x`[}{_~EzᷞPFh_IIIد+8PJKKeѢEqa}lnСC0<~xž'OxIK5Y"%Nb/)rLݻEb% _ܠRm1JV=QmXaocjԨQJ>#5͛%Kg'YkZJ>z3 X0o/D쥗^t=YkHc>ff>kQ8,{?ay_ ] v4�}9:,3g:�o/999ruש޽{ N9p{=4xO =??=^YY)-ot'^*-[fXO=9SO6N_WjqMNNv'%%ɭs0xө[`V7hG]y3%&gDIX^W;HvJF'=i۶mr=h ~9DƌgQ=rF'̟1cN8 JdO5 ~͎L<ap"`9DJM1 !{G#G{=rXݿ灾}C]vG~ذJ[o@C hQ{u꿡ڗ`b z?۝b111fyccc/vNUW#22R!l5HC}r^|EUY?wqSPPx#޲e) V"0 KǜPRT|D BW}m$8xܘfT2j/[>O$F?d"OK^^{Z=+Q3;<WF_29OohU޶&͎υcǪs�/ѣ4=?+RIٿsƬ͇f}L?էސ^fڋw}C盵/4J5kV!F"< ʑzzou!9O?Æ S>{d<1' DCx@=Lu]ʴ~^ m cؗ]/&PF;2R%w휫RBBnW yS yxzgϞ"tFvm~1<a~vv1E̢fS/8@0ۯq 'C_{kf�!t =_4߿? kꫯ}~7O+m!2_ fŻ꿡/GĄv;Q̎Ǭ=>F~XYAM,yf̜9Siᆃ0IBBJ@_@#a z߸dz{1پ}{nhyJ P(4/񖯿Q?9@�᭓9SGD*^r2gv$/ٿ nKf쁴YoÉ_$}t{{F'ƌAQB}kv\u1k 6nv x&!Xiz_|l4S(o"ķbx6ۿY}Zi /yΟ1k/eV o־AtT|fcP�xO[`7˭ q+#Fx<Ԭܠׄj@} ޠAC.;<:}ڵp^s9G3aY z?}ios 쁔)z0`Goʕ*T{DI%5(-qPgHޮ%RƓb}wd"Z`Ǎi x}]#(;>V~k@[{G|/H5`˞@kt\fu[_{ؽd_O3Ѯf6tzacmESn{o �#:4@0;f0Ϭ:߬}!?1jpz3[zI]4AKi_]ۏ` [&,' czr)0M)B7 GUƎ;>`xÎvȓ&H`GU 궾s=f�AcC,THETCHHCёD%s12?,h{/o|6(oc9W<C F}OB -))[` 뇽TrxICyIk[`Mh̝;c>Xa>J!PD %_( $Rf$%&YWcQ ľ[c/1fǐzCA6olj}4:͇߬ 5O<|k!2ΟW_֨:߬}i5o7ԧz5/\cx4jv֧`o VQ'س3$"; [)Y r0'[Γ`xDh vB!=k vB(aJUKˬS$7ad-+] tHUUTW{Oj) ! vB(؛GJKHMMwYvtIZ~H! QD-df{%:&J}I! vB(؛IB!^tB`'B! vB!P|i+LRR$y$<,M+y !,ͺkhwcXoh6[O7*}ݍ"ҥ[cƻvh !cnM/8w2{k7xC (}p 5ET맂?Jpu#u>\mB!H[e O>,_Isu,SLiz`\/Jܚ{Νe/d„ %T'UVVHyEJiS%,sHqqoǶ 7O,㉉Z}5k_b?%O-i?R'߮WSS#\uU0irf^~ͦ;~/sϕӧqL9%\n&9TeHMM^zɥ^*]tS,<s/-[?ox1xbĉK.ZER}p {neN*W^y?h Myy\p>OUb=;ǦR` γliː45?5d$n"-|qvcosSaev=ayf }Ѽz[ly?=6{rʵ^+/võ;|pu_Euȑjm?z-HHH{<33SyU>1j@ջ<f3+[8^ueܸqt0j9)Of!!y1c3Fu&a;vl@~衇 H}]7l <^x%z+**SN:t;vHUU8Nׯ_@}78eQ}X9^,3p@)--Ew}ˢ: Ǐ]gңG v_u׼g8bw%3%v |[rJ…ش.OȦMS�t=5fYj|ᇖg S38Xϟ?_^Rᅺk׬|fy²cǎ2j(%la}fXdzyl{f4zo/D=쥗^XםY;f!!Ee{oob[o hsQ!''G:5޻wou跗?!: .^}UFާOzѾ9f1naD /$z~k'>==q(+zfVd2$=#UR ٹk$o(!m۶=ܣ<{H#oQ'rḞSg<f)Hwr)Y}hDEE{̙3O:8ݴilDgl>R f_D mWwj|bg>h^,^8pJ;3^cGo/2u׀y-]_FS/FZu曕Ǿo߾e6cאB>sV]]0oqq/Xъ8TohX鬳 .Z>i/\ q Ճ^z ߈9)Q/.)rY 9Rk$E?Ip. #1Q%$bԦ/"kO?TqP!Cx,g|幧m3Ti ~[X~\qvZ՛lu`t1R=fBbS JpX-}1kDϋ/86lwjZ}%}l{`>4p2Wz1z#Z[}I8tP׷|fvfV<ڭ`M y5oO? Æ S>EOϷZ@# nkmVVx*a_vhأ`!c܂^ueuwUbhR)Y!{+oD]<gVQ$n6Q3`>MFE۬Dۧە@{3x_0z߷ڢ`uG}i'/=SRP=aXl1+sADIsaXBH:M@* <gƎ޾k*R+"g}h^bNGp.N23ǘ35Ц{!^?InNAicv#}.>3aJ5ikx<TGHS?jykv+7UrfcV7K#(\~$? boc"�/9;wϗzib%ITtD @ڄ{ ^dh"\uHtAZQl[Ϭ>D@>}Eۚ`߹s4@=z;xZ=1POm;53}n1")))~ge{ z?D+%穕h^b@e�j;m-=Ƭ!υ%r+ހQAP= D8l_GC*~q\h"!w!sygO?jykvxDޫ;wF9f1_P匡 8\R <S(CK^Z"%Jo<)֗KzXϪM&2e v%T zR#;Ht:B0TwZ)Y}q�rFzjK Duk6_έA>w^P[u6*z@5f/Y{SFoh^cT<3ƚ_cڙY\hvBoɂ=2*^blR(˥`4)ʊSwD,""[`7.!)>`@xH\EȎvHtH# GྰղR><x`_Bj+81EL惠 .)h[|lԛY̶﫽r@ !Jy>?ciV@!fk-/8e˖)>2Wzwcq\86#TVicoH1f̬| y.P v F!"2Rqnº_vS$'9\¢#';mq,%D%#7s zݕQdW $:e$%FbfQ-+3 D4.ON:BXuזz"fz~!(wIZ#F8qmW}rSO=0|S?{h-^x7]h;=FחѼ@- ùw4j cڙY\`'BxD`H2;TS63nd%l9|8OJJB& ! ;!n”�?!.YӧHnVN [V鐪J7 '$,|RB!P7`J /ϑj >#BNi(Q}_h΂O>!B;!$ !BN/: vB!PBN! vB;!B( `o.^V^&i)?Q` }&<B;!CHM**\bHcDI%B( `o8B+ʤTJ˜,-gC|[v8IyR`OLl碽S?NNxBNił=>!V rJ8ϲeJ-C3Ԑ=uضl={%)Znښ`o-ǰqFyGw\s5oHAA333gK.D1pm>\^FY돷."O[']t!A;!FǨUw8KiX%E.){HLT˾ݒU.k%IgѹsgYz8)++ &(Qꏎ;ʨQ>HM˽+YYY0PwmfժUZ._C"O?  vB(؍VQjW̬tɀeIzFY-QAWd箝y,sƌrgĉoVþ}JEE:SN+R.R4hCz꥖WgϞRTT/Wǎ+BywzW]uڟ0͓nI;<y%BQZ'GzW˺udҤIj[7p޽۴-Nry{oyӦMq w|o~9tPˇv5p@y6m#BN1';<%E.+b{b1Gjm(' %a!{$7&Y ^ӦO.]vUB>}СC=֭0 ?ާ`СرCt_~j?3C =Z~iU.X-oח|fxPU}aNh" q+ҖPg 6ydwŋ/(cǎU 6 Ӭn/7Bbeuƍs\!0x~a>$`'PF;2R%w׷b9WK<fݮئN9p{INNv'%%ɭj(N5 @ӽg;l25|-HJJ{=v}|xeeו>v{f:k CT#==rhֿm3tQ:|={[-ڕ!/]cC vB(؍Td:Hb=_jݖ$Q*ؽa2կS]]ǰ>*5ЋxqC~l,JyZ'Vh6PgM)}/8?#~ׇ7yqL㽽#UgmP;\O=c|HBN�wHVVZ"%Jo<)֗KzXϪM&2y7H0ZGð?o2N-F x@BBB7tO7m1g0,x5nlt�"4q5V; np=;!P8[/1p)MYN։Rae);UϜ9Syn һwoukc9(׬Y<HGD~-<۷owOC|'|26 tFu<p'|s5`o ukmZQsrB(#/\`l{֨ ((Hz!cV>oƌpyq=s=|HBNau3uRC"9r(9)ر|i%f*w}]cGW 0#CMq 9眣ձ]}bȥ~5wO>DmvC|:A1zZ9smt9XrsU=ߝ﫜iiiSO_ /5kwذa~GqJ?Fy_C7 <%F3x!  v##{vFD}'١RAq+%+!TdyRRRlD~C<cD||`C�!PBn0%OȪe)USŖ.t:R 'D+?Rk 2Dzt3:# vB(A\|TyA~TKm~hG7-Z3s9HAh1ŗ7*os!PBڜ`w8Jh`lDD?+"B;!$ !BN/: vB!PBN! vB;!B( `o.^V^&i)?Q` }&<B;!CHM**\bHcDI%B( `o8B+ʤTJ˜,-gC|[v8IyR`OLl%cTWB;;!P'*AcS)0YLɴeHzFGnۖRgԸD;]-{7?µ4|pK9RMSyGOW_uE!C() iۂ=.>F=05Y"%Nb/)rLݻEb% _ܠRp!]+9N ˽+YYY0Pw-K,zȴ^WZ%~!2-c㢕`wڕG=3+]2`i*){VKTpٹk$o(61c;38CM'7߬<t} uN*W^y\z2h 9˹ T1K-/]Ϟ=H_5;&W\q:o555*?+'͛'7twyJt@aN:WꫯuɤIԶnٽ{siTFEEu]'3glqcǎi&8;u:pxrzСC| v vBڶ`9)Q/.)rY 9Rk$E?Ip. #1Q&ysO>}tUy`ӧ :cnݺ8 Ǐ):t ;v쐪*q:2x`ׯ>̽/"=zPãG~Z ֽ{w%_xlJN0@aN?p@)--EɅ^w}ΥQΫ]~zZvm^V;^6/E矛+^bG;;!m_F;2R%w׷b9WK<fݮrNBegg{L;M@y$''Ǔ[o$ @:G}ٲej[nz؟J9+}Z'v5~;KҨ f~rJDDD_VgnS�gu$,,L bV߿BNNH1JY AKmob=4ے$*:Y fe_=aVҥK}/ wqlBU@k_nEubfΥQΫŋG}tZqzg>Rf/4>,.!5(- ۵DJXxR/.UכLdT vo >bޓadLG[>o< !!!oyͶ=} 3<7`7*yrrmɴiZ`g|_[l'88BNNHQc ҤDalX^.IQV#|~Z;>$D3Bh1!!Azrʵ\i ;65k)0{?<c}vQFy?m1{0&#9=\v2WNjb[`zIikPPJ!v##"a//g&)*m^?ErP!),:rRc&:{lC}o$H0`G~7nTsQخ>mJk9�>'mXnc@aT'ӎs6`7*y x!뮻yi6j ǵ6l01b)VBNiu=;#I"P)O θ*s<))KEm6X"!#?z1">>^?7y! v vBڍ`SZXfM" [%;%\lYRP/NC*\}RN;賟!C(O.zAw|:;!PBt+.A^#55R[e! d{Z/%s99HAofcZR+/;!PB^O%,m!4+1QOm!BN{3 vB!P‹B!PB!BN! vB(؛KIjZ$O$XreIyE9O"!BNRSJ~* X/,<R71GyR ! vB(؛C'$Ʃ?N2)+/28KKY"5ߖ%mAR=oT/X [`+vD;!U X%!ֳsl*<˖) IHSSCH-b۲Yhx8}eh8u]pqFyGw\s5oHAA{_].Reܸq>|\r%^F鉋ݻ˅^(^{,^=oҥK9z-Kzwo~>$`'݈׼g8bw%3%v |[rJ…m8mܹ^Z 20aoJ^z%ϟ/{dee)Bݵ*7p|O<(?x ٴi{RGMr~r}BNqJ;Jʣ.4IH=%*8HBJRRܵS7o_]B9Dό3믗38CM'7߬<} uN*W^yJ4HrbW^j.Hz)EEEJacǎW\[MMjJv yM7ݤ>$x/?~\ƌ#7x~>%]w̜9ӰlnZ \TӀh;vT[Ý:urC嗖R6p@6m_/-! vbN vxԋK\V(B)*>"+ľc6IQOKBHnLT^ӦO.]vUD>}СC=֭:tHǏS0tAv!UUUt:eү_?5ß}{_~y=z<Ӫ\0Xݮ/Q /fS/W W}\222T}2}_^]ִ\-nZ`1N< ^XX}/V,ь2@D#|?#ǁWDOYfU#;WB`'ݗ`r vxՕeJožsGJy ݻ]y۽sdRdgg{L;qxկOJJ[oՒ*--Uix-[oIIIqYݮ/Q?ނݻrmZc{"9""9k u-Ad(===^W_}}xWv?3m`rc/HA{AL:C$22R0_жky|HBN1JY AKmob=4ے$*:Y B`+XuևH^2q+ =>ٮQUo=2+ E__ۃ�裏,P7-}}Yrjn+Q=Îzx̽ٹsw6,#ru?"f=PBn&%!yHO咿%ֳzj^ 3R${0ÎS"&<xx%ͼfm Q娛gVoÎxᑋlP7-Ev9s(aÎtxo|rE 7-^aG" DM`' ȨzKir0NG/ Ӥ(+Nyn ?="G]ݻ:țr1<vXۄr͚5#| Ox�o6j(<'|26(ENwwx3+ <a<98F(M4ɴ\-nZ`G\[999*_Îtd#% =SQQ/1QR|7RuBk {77z{  v#""a//g&)*m^?ErP!),:rRc&zKٳU.;=>4xh跉>!D9%Z]}bH~5wO>DmvCBh!5l[fe91xˌ!RjDK-ԍ-_rsUb*"~Ot<s=v lĈP^u ?:U^zoїx!B^𧻓YG4�B( `7 <Ngg$IDwR*)RB`N>'%%u) &K7x04F6t !PB=L jb5}&lpeKAA8j|pyBIm;v {x+ Y7BN{SiTyA~TKm>! dK >roFolcior5GB;;!F;%J YBiWcԇB`';!B( EGN! vB( !BN`'B;!%$5-E'J,9òڤ'B`'t)RX?QRKCxѣ<B;!!'UVVHyEJiS%,sHqqoǶ 7O,㉉\g]B;!'*AcS)0YLɴeHzFGnۖRgԸD;E+Cs96.\r#Gi̔gyF-0."|!\zr˸q<qFyGw\s5oHAA`;mG^f`qqqҽ{w kŋ[ G;!%04Y"%Nb/)rLݻEb% _ܠRp!{? vsϟ/{dee)Bkcǎ2j(%,a}UVɇ~7_V"K/_߹sgYzvYYL0Atby}%KC=Sa 7 ?z|PBZ`VQjW̬tɀeIzFY-QAWd箝yz681c38CM'7߬<} uN*W^y 4Hr|^zٳ)�5;&W\q:o555*?+U ϛ7On&9Dt#F_eVǏ˘1coT/g9뮓3gͨ_ ugLM Mԩ/%d5JKK4r!e]ڠD?wr[Y vm/ [C;!U"JPHA #MR=,?/yyyiӧO]*o&E>}dСtMǏߡCٱcTUUK~< geѣ=z<Ӫ\0nח`f) 3.ˬ,~<㒑sȐ!ceeڵeTfjR/B_|QƎ ^h%Lźu >4p?ɓ'ۭ/vqBOYfӭLx/HKOVHBNi==6-UW*ιJM^*1+$tvm7ml1;T? x֯OJJ[oT(�x;+u�e-")))?%㕕r[{חYYn6}lNGDDX>gFov]ejJ<Lw>묳.Kkɫ꾇+rg<0D:-Ra 1^eT/<];iCz \jBNiU=:&R 9#!?}|Mo&v[DEG4`,0%,_:q #ėPH^l{pw(/ dނݪ"ؽˬ,8}}yo/'ȳտRw) Îʮa4oZϞ2n+7Q>|G,˨Y[D>=[ C;!vM;JK$++Cv-%7%Kg&ռgb؟Qx#_|xx yͶ]Q7[Ϭ,~=77WyMfտRw) 4/,Vrر`ϙ3G T`mza1j8Ɓ6on$oV?PBZ` [&,' czr)0M*!<Hnj һwouSPc9þ ۚ5k)0{=l߾= |s؟|ɀ3+ <a<98FI&Y:gFov] ejJQ/1By뚇?>E_ ""E =Sŵ琛o<;޳6.)-؟>l!섐V!#"a//g&)*m^?ErP!),:rRc&ؑ[;{l n ,>`�6g4D9眣ձ]}bȡrz<y}O>Q۰x�f2+ )D#ǃ^f|mywu:VsfTf/Zΰa1SO=%_|2_=Ǵ߇W'+WT{JRD)o!W} x:^�?#*{xD`H2;TS63nd%l9|8OJJR#BM7oq?l"% vB(laJUKˬS$7ad-+] tHUUTWOjۉ`G{=@<~lBN{SiTyA~TKm~hG7A0j5_ i$HxUwMq,|�؜u\BN{#p(Ѿ/4Dgn ٧^R&B! fB`';!B( `'B;!B!PSB!PB!BN! vB( !BN`'B;!B;;!B`'PB! vB!PB( !BN;;!BNN;!B( !B`'B! vB!PBNN!PSBN! vB;!B( `'B;k vB!PBNN!P;PBN! vB;!B( `'B;;!B`'Bv`'B! vB!PBN! v vB( !BN;;!B@N;!B( !B`'B!PB! v vB!ځ vB!PB( !BN;!B() `'B;!B`'B! vB!PBN! v vB( !BN;;!B( `'B;!B!PB! vB!PBNN! vB( !BN`'B;!B``'B!PSB! vB!PB( !BN;!B() iAFh4Z0 vBZ`'B`'B!PSB! vB!PB( !BN;!B;!B`'B!PB!BN! vB( !B( `'B;!B`'B! vB!PBN!BNHyyy}vvٹsDB!섐͛7KiiN ~C<Рc?B!PyqqrqS6}ڰ.O>m"v?;N-?=,o޻<B;! ؑR]]m>2-;>df `b,)ѣ-BA{K! vBڭ`zVVV&&~?̜5t<TVV ~'}NҧJzF{>D/KO)0gzMljHaJ),,RY6o_yHn2i49vT3rh'Nؾ^f2tN:ːXES*BsY|JTLL5گv~5%rW3ϩ}~׶̎۬.""W_S5kyS  vBھ`G^?BZ&]t}/?BuC>&yKUU_H^m|wzwqM?V+~\܏׸ǧD}b0 [c-ʡϛ/oZ{^mW$"2JjjjKiO?X)ӤBV]^~6kkY+Ug -]͕2"eBS;?^$ !P;ra(9zA0G&ֻ>! IjY+0v{<x]h6箁tz={JfV{/yȈQ0޿f[0T8c ޷ϯo3#3ӽMmÞCx:ΓCz㛀,keF }+)17KD ._!B;!Gkx1T6pn.:u"%feqy.9)>ᡅhF]Q@?yo6'NXǨ^6~kuߺ1d@kvNf7)TT/^!P;ayv:=Eb㥠@-`*]ê84lx}Y[6+q7mbMcxؽ?oب<ᵵ귾"<e뫫NO{/v_2ۿY]jh`Ӟ!P&{NN2xC=DCuV-vml'Kf ^R*ݪ`y"YeU/Ƒ2a$!v }ɬϻ~3wRCьf}'OG?ߨvkk[f7KhACaOMB( i=%` Ug@ӴZT{9oguj&!q; ]ij@Z}eJ} 2ß|6Imj" '8Dwz\KFsvT/gϙqeV>Rg[ '! vBڴ`G?C/ 0Ma9&?C/O?+B( `o`߾}DDD(/:>(~ \xxT @jzAo0o$+B( `o`G?Hhh˪Ue*Mi>z!KB`']AAA*/)2 B( !% !B( `'B;!B!PB!BN! vB( !B( `'B;!B!PB!BN! vB( !B( `'B;!B!PB!BN! vB( !B( `'B;!B!섴!?Zyh%7yo%q#ܼy=zDnQF7KM6ᐊ ZuLNCzmku}z섴j56:| 5B7y65ɺ>? vBZ`촦5vsy|4;_^KsMO$+++i`|(Q v;;!켉@7GNH n>.e?M\i)KsJ섂PĤxIH8wedKk^MoL:U>'M)ʚ݆.Kë%1'[4QS $)-sޣ ߻K쒼?Qrrl{cRr;!-R!qV.{OsSӚb_o,``'qJWVVHYyg.^,`A F7IFfp]=o9Wn`9Ȩpϧ``'evt6x.KDB5}2+B7d~cYKgrۜyǟVK^a vBzr ArX/gCJv)IaJcǎe\}bECQUUU=fZHrϗyKCvW]D wjEE~F/e?Ҵ*"Me!_iV,!C7d~cYKn/as~2 vBz SQ/Y/*.#E&q񱒘ْ1NJ$k5 ɪLO Ks.^a^̧JNNu)Y* ھC\ DNiRoBS?Eޞ2nٛ1[~xE/4尮F/_-ZE2zy1>NcO<)sMiP\@f4˧e~CY_~잽0r|ٰi8Nu1s)Sr~j"�p/mdk91pק#aY(Ikht85^$EB)t|?(9JvMJzxɌ/NlC3s_Xw]zfEG%y?$׬Uo+KBʆOά/k֭Su9seڵR\\ܬ9 vB(qNJ岙3eHe7!/*ۚlN'G؏d]pZWyK7ɲٔaӴxhr0:$o 7ߚ{_cNqUgwb%%eJv8.ٺU[H}ەn|R5/4LQrb6Jnqm�Q_oTyhUK*5)iB**TR@ԇc68%"iIb/xo2޷g6^&vP o0^3c~<sps=>#+ۻ,Zso˗F5MW$YY.pz ($ZNFCƳ0}f)m25s_g#YW8ežcv;>D?13[}0$nmwZ踔;,'&MxnXjjdjz.H2ze}ua*gPqμyRc;'\|RO>/6Ԇ׼{L|,w cn&owTU ߽?dBp&ԕ=9Y,љ͕<O~74rIg>?,r%4f7 Γa<zuQ-ߣoKҤ:Q2OLNiuGgzJմD76 yfvvEG;NܴLݷ{L;Rd;Nw 1 33;]b0|&{yƩzgg;#C>KMlNkadhNUZWMekNb*rN3((h™|T&ʅ_E^TX~#-nc>l~[뻭w/55 9wO~K:aky`_o0 u4(sR"ӪܘyXnF`BS+iVro^,/^*l!x.2 ƴ`D76kiĨ0 Vݐ/#;'^yYnSK{ۉ96hvߞn-ŋ2}\˥~`\}nUcKZP ;!IqI)ꈑR`?%9_έcd6# FZ_Z.#?ׂL<,c{ztuw@ÙPWJqq2UYx*S';[&dR YX_nF菎~ҽ-wtソv-UmVݱ@߁NEjW]<2#O$ey</jgHWZCvn8va޶*]:pȀ%l6}u[rsLW/rN3(m'9|yy#kG?â=:iua]c;bbO!|Oq9ˠ<t]urc38[ TRm:w~m<�jbbRJJ˶$ Mk }o}s^S3whjo'/spN|PR%Ks&wg˖,vk 1lč'Y؛t:MiCI/>M#`d,Vݯݘjn㪰ヒD9Ga'v&3( KߑkoIBt_yO뷏ax~tBd{u?lL hd7HSD ]mEQf-c"`wZ@a'"jw1q$[,*%hY'KfBvn83q$qG(18Y2-ƽ6<\iAƴKnơ2q',Y/ͰOpsvB(!ɾߖTu>.yMOtttL<=Z&P!�ƐX: ;tJHd\:Ғ牴&鸆&`[T}wt*ѣGޮ}vt]d4ժ%O:%DDO/oGui;]" ;P1~/V'."3RgX֞RV(OyynU7lאy4(oeQ)aGBJ7%>e|Qb3ȩ/i;]" ;P-ciyicG^g:QHa~ʔN[V, ).1駘≱>=3SM+S npɼCy7vD*v ;.XRb*V)BB)*.oaQrs}P!<`YIa;Od ;PؙvNS S !vcVJvBag(vB([v iń?(P)PؿXXX1>>΄1Cke`e!<^#sLr_lGa'd{L&O~cB[ckCee.PY>;l52$ΖvBv"κ.`SHw!,7Y6넝B!NB!vB(vB!P B!NB!NB!NB!vB(vB!P B!NB!NB!ď3 0 0 ;Ju 'Q͏����IENDB`����������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/images/tagrename.png�����������������������������������������������������������0000664�0001750�0001750�00000200644�14035600052�017054� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����!���Jb7���sBIT|d���tEXtSoftware�gnome-screenshot>�6IDATx}t]ŹuHeB(!!ɃP)Lm1l`{/r{U.[jV>~+ifΜN"))̘&N!�$I$I$I$РM z̝;)S@   !�MЦۡQUR!I$I$I$amm@N<yb0T,C$I$I$IFQgΜ'NX]]-$I$I$I$-4iz֣4I$I$I$MV`*$I$I$IBR$I$I$I+X+++I$I$I$I2jHJ$I$I$IF` I$I$I$ɨ!+I$I$I$݂$I$I$I$$IFkkk 555 7�a8+iό3s8u-:mN!l)ZZfDyoCYoS$H]=$I4Ǐ'I >{rN_ij;8viYtSyRT\8rUg~W {z}Fgoc;+['%yھ?XG ݆9iI>dʩA̭ݼMq XQw4*/˘i3]C'}]et~U,[uאe$IIJdq歲|>jlaܶ{gcQJqxs }y$/@+(, 4Wmj<L�fi#}zִ+<ޭn٦|ҫYllz9ZZ.Ҁhyǜ;e<i,--  zieVϦ^ô+xʤYG_<-Nvc;V/tǫQ*禬ۥ٩\kv328fKJOwV͠aS1^|E.]fN;4Y9*n/ծxynjϭ?絼9}]d Iݡg}b>V q,lz1$ɨ6>-3KU>i}WB ܧݮ=b|[2b498f@&N_$'C8Ł4ǻ#3n:uh:JmYn4Kj_jF ykA ó,_!>dԔQ+<Xv~WA᎚czK%&YQцN699FZQ pO_{;mP86m̴c'_Ph[{ޟ=vŷޗy˕P6o*oZVemYKUq0 Dxg0yX N,l ㆴ"=/졕@o9{ʑY>U#kzw>Z(@92l]!I2h%X;Qty$c~ã`%I2ji&zcVބ$ifu.'7W5 $$ʃm_EWYVib"fjʨŇF6Z56nߩ/daѧ2x$9hDVh] WPGCðK=r4\eksԵPkN 4SR옗sjfGxN6*cvpbxxJEvklձ\ٰm8~Xutl{퐟8_* rryyemYwJYGWz]*o\1-p-o^ckd׾JģL^rdnTPX,zB{)#^1{I|yoCmӿvyWH^끴 %RӝVC$M[fǴ!�Q!ܬEKՋ,P] 4 a`"mRk߳QÔ!| h@V$ N >)` <̞C2 1+.X|5}#W,ivԳqyg֧_!+oR魞#f"eg]=рGc:K#@9WveN{۾"/9N wv׼-/&d:)Ni6-ׯ\0Ǵpޅz|#~rdnf^@|^ʈwL^5:vNyC+$IFja Vmx1Q$(>dXUh/[AmǭYg&X{[ygkaQ^j׈_z#%1Pd8C=3$nl6mm͙ljHh' w}ߪ!NklH7<tV[vvkϣ^ld;8868l*emkP+ڳ;~y-o%j(Qc|'av,I[M23 Vx>nVܖ? IѐJ :VC>:`---%I*jWmؤ<Άy`'v8iZ Eb0{'sC_ΗhBtӫM"WaʰiYxI 199xs=$nl&m:hBYx<-338ax0_ρy|6oj"')%1͞`NZG6{]q<[2R-ŗӚ[#Vݦٲ\Űa3i mҞuw|+b*:#ێŊuc>ʑY>xҮx}Ǵwۯ)aHnVܖw!V7 ihWc~ã`%I2jrzxL<8m@z@,[aY^lC|wl.7r<;j(Y}ҳ_MFAӴQ*!|X s?{ٶ{ ^NUo洹 ]MR"6vv4gœo6l:  9ٳ){_VM Bj촙Njσ!?́ٸmDTYwfrm:z8s=,Z_I9|[#|R'xiZ~$i"ky7+snˌջIѐJ V< ~؂H$'qh hs@/'ZvijQƞճhӁ_}ƴq0D_6vnҦ q_hţaž5{6ck<{99NjFM~6 W ưGZi-nuc>ʑU>ҩxy4Rʜ2c;Dd4$I'VWVMKh&?O '`-H$]֒$I?{5 ŃŰbM m RTA[$IZ$I2 auD >zi$uZPTL[$I$IB$II%)XI$I$I$EEE$I$I$I$5`%I$I$I$[$I$I$IdԐ$I$I$InZPP@$I$I$IQC V$I$I$I2k~~>I$I$I$IF u̘1$I!>|i$I$IfPQw+VUVիe͚5$I$I$٬v1h'SD Vk׮ˆ dƍ$I$I$,0hLJ ,XBܼylݺ$I$I$5.Fd Vh`/mdǎsN$I$IlD{bN`%Aھ}zAwM$I$I͚h}vrD!C Z=Ix9#{%I$I$fI.FdWUFRDd]^}$I$Idּ_+APH$I$,Z#.XxX˔i12lH8e޳*`mg>V$ٜt͊V$W-$EuO R.[.qf7 `mX}� Gz Odg1= 3d׮]i<621oUzK/ظfzR6:kGGN2UhӨd (otjDkӵ{9{( 𽉨[~xP#}=>Q^DX$uwT2k V)f ;`e~Oϸu .RzScx3fڦk22`H~e̸rժfk{U9A:.Z'C -y7:L78xU] v~]̮]و7!er߃MMs*ykV^mrCN}|};o+[m r+7wɞU:yX9{\yֿߡ6/ȤSef9o˕W׀@xɒB9ϙ7:|(O# x=k1S<#T==dƖIR*8I헖RLΙ;OA�5C0kٰa-Yì;o:6-tM9-AC{a5kʸ ec!FN6-PO5,,ZdZ . ~}=(qfNSgSh86+1,XOcv~]l"L 4t| u#[>_{ąF=yw=ϛ?_ms}i&NƎ:Ϝ)ϵ}Y Vc]]x:- JaK-pq\A齬Vuv>P? iELUvmxRG[6o&I3!ǥR32/*5c>۷}|C+.5005~XpzܗX}i˞veK~\iGլ щ=^MW[p?yvH͜fK^خ9_͛eW}biᠡ'P/jTQp]i ~4M7oS"=MZlF 4'j3\o'couno$<VA;ot[~k@yҏ 1ClL5Ĥd#4|hy JFf& A}Zպi=nxZ%]Qư&8-+Vlvidt`x\:mѥ@ָy3/�֮m < ZaSϵ[9bOnŢqM"au'.ǵzܼqtPYŅ:a6mk׮SxVv'r NlLV `mqbXViY Oj7{ݛKcG`QZ3 g\Q='E?"{V{ Ul۶ݳ@5I[8}Ͽ:蹦`b/D݈QUnӆn<dfxH$)X huܹ9f+zC3}^[͛>3fR2sj`ㇽ4ʞ~+f s[SU9`=uPFw$7nTC"Xjeaa V7i`u'l8w<U~ Vq+3f:-ܥ'O4{l [ ǵX |H C۸Sqc&<-7`%aŇ %1*ڢZc*8Z?xUmc>z85 bk({H_h$i+\_tnlfU)XOypǟ |V<&ϾV-Ebl28\&mn0i<̳j`yPz|Weʾ}k/5 i6mzXۥ~p@1 u[V0ƳcǏUW;ڲ~3I V \6j+7JҞ$I$IRAZİUu(ʀ=I$I`%A46V-0n1Y=I$I`%$I$I$#/XI#R$I$Id $I)XI$I$I$)XI$I$I$I V$I$I`%f#X)ZI .&ݐ I -V`ǡl;Z䟷cb/D$I2#ݐ I M.Fؕ`m-RZ^#G˫e|uL/B40V c Tȯg6:TT)oMɰ۬,I+Z9גCQ)8Z$I)H+$h`#ɇ˥El͉oO͐Jy}rzjk%WǧIѱjm= I^"KG`՛`%  5q:++M 4K*VNy$uyS\K"sl0.4~x(wIj),l^cfIW'XҘTYtTF&LJ$<Еjq{m<n:VБy*}O;q3›[kBJAADB�m /. مHX*WgJe2ckm(❴1_6*nM/}53L&n8vdύ8`yCdJȠ$P. Agu,tzvq!c{J\=?{{7{*|^ǰ=EAAX+vMԛ`}j)`@UT!<5Od5wf/\XFۇ^ 6LR^E}Ϗ8]N/sX̡ޘRW%3\3Tɠm;�(X  ֆx! Sw$ bLkvϏ[1/Vx!w.;2԰X Np:xX₧uLc3:` >7{NӔeV w`%  F&Xz1n7 GַsX̵DXx'}}ԯq V5yj5~K lYRPVEJAAUbpV v+d!+r<vӲ_2>MV&M;/oqk@\='ׄ7`C`:*KtCtaax}_L~S:Rq;gگ`ukʓ?|U/1m۟sZOJAA,XቊR8X5ԗ`*0agj^unl^rLOCR.RBH[wDjj-XHH[nlV l4hs4Vt;)݊R'vtb]@),-~ՂX+AAA4RJ:b s+iM/C  5j9s[ZIUOAAAIu bx0V]H V  `%I V  `%I2Md^$I$I2|mcâ$و+*%!!$I$Iɰ!GUTT… ma ,B)--%=vV VlD=Sɒ'G!I$Il2DX\\Zv0𘛛kkc VlѣGI$I$9~xծmsk$`-++SVH$I$vNC$)X$I$Tk4) V 41cnOצ%?)XI$I$ h W =G.= u-X[8mKj9_<3KvdIEuV=Ed u!p*S*)t%)yRJi$I$INA):}&p|?z'gR֥`#ɇ˥El ߖ^&]b$yrh,U$RJ#"R=5C + .fjk%WǧIѱj剅_"KG`nkeee?A lԗ-^6|cy%*J Hִ3fħe{ר_'Z?coll,k5q%H}l>fy}IRVQ1?.а/TCǥøS> 2v]W*{( >'[y);K5)%0/9^-e2rukAl㘙GՉ%*=V4&U$U&LJ$<Еjq{m<n:VБy*}O;q3›[|ijuƍ6NF\}OZ+}fir؀n OdzP{{IQocEkeOatL;!ZRBV*9``>s:tND$hH/~lcxc ]q도are{F:dY_,3YP)IesjQ2[6qـwf G\{!Ȟq< wɔVAI2gG,]GX"XBe{jBWol%aS aok׮ҹso4:>k}*N>RFOS6-o)+kAAA2\71CLY.;-296 ZcwD"IJV7"S|L<V-&]Sk.J:MHSެ"&XzJl<dU}ObH2fvq ŜS} k'p=ᭅ׭ 6LR tpe]\_19O3_XMg-Av�D`rśnI,YѸ޽{r%Ȍ3>?_.rYlY>!W]uwysIQQQ<|o߾/Jo۷Oz!u9#ZR=Vt .<\4x>c/:KJ2du?P 7|c>3nذAt"\?7Wqs<V"=Hn˭_~/.H]ߡCU浗r.^.>vR6.^z 0@[nEvQ't7.uYn䗛n>C 7$&ʊ-ɲi_lVu2gu=8w|?jKLL,(,>_W GZF! y :!=#CyZ8s#GIV }p/77WgeeQa}/&SweDl~1HgZ Z{<uGԋ%3jA@ lۉ9\p=y iutjw*�-LEj<gÝq�[h93v/"d{SbޱcǂATC>[^y 7oKTSO믿<+w}Ijjq ?tRz /`N3k{M[95/R2e8 mڴ1O?lkYIǎUwߕ{U˖-%===ϣA>N:t#6j"eV@lûEd-7n7jo'ؕK-YfɅ^(ӧO9HrrjtMNloN]"Yn/睞.Clho Ӎ7۲W*Xm1# Ub%;SsYQNX/]yX'M9?}欠`׭ NSx9;񒐘6!!QƎpZ\va,|76m٢7m,ͺKcsW ,`G uGŇԼI?=f%3au$_/6NqmI+kpkmq/6!mvU5I:biݺuHaq3 ߻wopehW_}ڵ+ωSJ#*=x2Sxv׺M[95$@ݻ^&e_?Uy3ܹS>ү^I (^Dr.~*v]Dx}_!K;"&?ĖNT9%rn~=ud] V3'pQbu!/aFbdU/\_&,ت氦?˓#G_9t̘) 9(''=ZCP7mYs͜='pli.2{<=ut[\ ;~Xn`#0vוa!+r<Hݲ_2>MV&"^6d9qe^?_P̃uk# *KtCtaax}_L~S:RU>{Nq ^qXy} ufi'`EG^KVWW;ѸџGG?Cuy Cek J0;TԴ!m*Na;g|.?ib+6oެ<M\p\s52o<mZ#^&xvmz`~njH'R54;I跍e6^ʍ[{>rBb&ⷳNYiq9gfv?]祜:۩9=guKpe6vE2s-B14 s^Ë,YSFX-goޣI܈/dvOʫW ).(~9q]EEŪ� TƸQ!laR8?Vh}rֺX%6L+WmVCN?IaHE^qHUMe i+b[?֍ÊUrQ՟ ma'Ec$V v^kuMmGc1V bUMMbOc8XU׎5J}�0 yt:m9hf/BCm %>sQM^x0k68Gͭif?cv/ңEDzmF֗=l~yܸK8y6cU.0+cH)ߜ3NHHyg$#M?L`ܺR9^w+VȊVv9 FˡC9;vzYn}Sz!1eu2eډy>< L)̭-7bSboٓGS0 ?̝ÐG}4x>{GqUcs۰Jbbi]x <F/4xa~z19cfCD0ZόB.h YC~n^y]1\`[_9nKqcp)Ǫ\PB"S9gfiu[nFD*;=c}$ j^rC) Iy$ PΞ%,޽e'c7lӦIfV2kܐygՇƆ@}߰qk4q0V_`v!AQ9J~E<E4r0WStjѸm׮F9|š;wj'?Q=W;oNR} ڪ9?a7c,x}5ώUKN2klbj,6 S>U4`zk$moNY85Re);=#I66`8aDZ^ՃKHuR4nS`Ŝ]GCłHƎ={\UXNadgTcuak gRF1"c8+c[څZSScK ۲eu hHg۪%ɼ'I`} VxV0 kS%+I6sJ$I$X+J!YU_]R^e9$$)XI$I$Hbd}V.QRd$I$IMhdgg7(C6wR$+I$IdXȭ!IJJ$I$I$IJ$I$xkfff$)XAAMhddd4()X)X@S?="%XO.A$kzzz1!!Aaa077ƾk�mɗ9Z^-S7cndw1*W,OMavo] E dv@[`!9 ;vȢEѣAkZZZp2{lֲk-X@.Ob//.GK)<3Lz͖G%II2nّQ֤[S2$B)Z:>MUK9Yp !^u/X=S$I$I h[Rlս= ǥS4l>fy}IR^UK� JCǥø4pF> 2v]W*P vi\HFɓkdPCxЕwJjO~2k{U+b\Ε; ἶҘTYtT]WVQ#kCKd!.?,+Jh=TT6[5TG`%  G @O1<Z�M)뺀'a[k'mva [+3G%˲b2IgPĶ^\:?pTv xl#=,&7  =~N+.1Ҫr E}ύ8r 8mx?<LI:|ܷ")X  Z}O 4lZ{l;:ŷ`}j)`@Uxkċ]>3gǗʶSC!sP{~{ <XzO[tᡬ+{`^kM /vn#V AAH+҄ GdO1߂DA@p@muRKE{Z„k}tO鼶yR3jjaW+3(+1j<`%  F"Xah=^YS/ևx CCݤ ӌcJNᙥǫVV<68Y든~ԋ=SVWu*WFΕK\eAAш+[%8.X ӆ9z Gbuv:a&!+rհ^~4`Y1_H-&<Lޘ2Ic{b8U.(R4cX RL^l` 'V vr`[ DP?Տ;sڧ`%  @ 93J /_}VJKX1v:'4|<{1oZ:&<`/J0[YvpwU #-ueOĉ_ō`0°W[wG`$I$IdcgD+ټg!A-i :++IJAPAP$+A+AAJAA$IRAPA$IZuVAA+IR։`AZ9mLhJ A+IRnxmA+5BAJa P7ֽ2eZ 1R&N"eJބWsӜw�<!G(VVUc8kpmiٹk:6h0=nXJi&~4#&LÆ ~/`%I ֆ{U˖KEElܼYݷ5,Az3#3SO!! kkk@J&%5Ujjjx5ذqIuu߯ίZ洰v\=~d~/`?Y)X~N2U@#Nc Kޜ9{L>w}bjuH ^?xI^pb2Ώ0˕X{AD Nے/5rZnW̮ݝu̓C} Ǻu)X8VY#;2ʤԨlfeQY]+UXLV ^ #` 7:O11z߰Qm #nj}'a~yUWAQ)XHri32E}bsNC7 ± Vm$.OJ3Lz͖G%[D l 'NRQ `uQΝ@LU“9|YSpׄq'ӂz^5q:++BytPTcRم*l?3?=qe),V6#X[IїS\KC_ Ŀ&騔Y|TrK2<4buwzց*kV6B~M{D) {=*>'[FSC~;-#ڑT<8?wGz#UQ(Xw>(ǒ89~jԠw  ܓ;֧KbcuXVUU)jKDZƎE:V]` fzaD`F͂]E2|UnXE9.,;XS2y6 jAx&n8`xeʓ Q,Xfl-O+.1Ҫ"vOp"M%|<]g1]ьLٔRzZ4GW֨}7b{zHGZQF`%fLճ[PAPכ /]&%'fϝ<mùH%Ayp]k{ADT ZQ7'Pzcr a$+<+ͩjƓfUb|<PQ0.MU5_6"m<\b&[ѪA4y ~g<Nӂl¨%v"jlpr[kܯysиRMC<mGPց`% VAQ$X<2a Vx/!t0df1a 9vA@U+j!ԁZ8<)]ͻD4ŻYt]a7xpwe OoՉ%ƒj-ia當2 }xd``%`%`/XZ!Ņ5y5Ģ<؇Ս`6 ׵ cq)x든~!MNτyN6w|֔ Y1|' vъ!AAkîV v+r7xa^3yc~Lx>'#XUaa`+deBI<J!XI?n5NV[F 3= T3O;sO<wDyn5sX)X (X (X.@ FpFJ_b>&~G 9Vv Q O(g˧sCKjjO\BsA1dj` *<ߚc.`V FX~/TVUURRAPAPd&<Xتo    ZeT!A+A+B16RѮ#Xј"I$I$H V   [l$)X  $I V  ,+IRAA+IR6=YT3gΔ_WMyK~Ds~\E49Gu$ kmmry']tQF? ݻW~Klll~jYv5ϗ?ӟT~ȨQbM .@Zl))))u;wPyy53<S.Ry$''[nkeS:NO[I>}oz² z X'ں.[1岾 V$\<Xn0=lذW<Qa[f76x0;vȅ^<GdyV6c}ޓujO-̙#JbΝfwy̘1C Dw.wuթ `7x#NZ 7}x2yF/XoF9~w /X1~*[1V1)PnS=oA+:KnVٽ{w|MMC*mӦ:1{lܳg.ri߾r_msZ8~GTz [V9sTJ<zRÎ8 cӋ`  WYYY*}j?>>^wfo_k >l_y֞> 0 XcT%\ޗ/B=_.+W .R_}U .?ϩNM�/\\\<p_+K!Tt .<wkWڮ~_WUU%\q*6}xҿeVbSv[o%ƍ h| zXe]&{-X|N6gׁ_~YK~k.䜟]>xyأC*-%_JkhyLݜ酚^DBhfecRY]+UXLQ+*}>%X[j%D^,Sn-((~Z|M8�~wPN.ޏ>H*_}~4lJff"N]vum;T?ɲeرcRTT$;vmۆEձpEթS'>NC k1,5&&F}T_ ê y:}O B ȇD9G_r- ?p64ZhAuj�lԫ)u#]NؘNݼ^pl$Xu},b lۦO h.4swuGtMы`F̚5+,;vurCP1EM}N@Gq/.GK)qfN]aݙY&=f#$((lU/G&X:/++g} k<q�ơ. ^cc/#sa ׭0OaqjՇvNbƋ]\?jC}}= .tfK߾}m;�<z&4X'=!=eGeh;'%%Q9?<p_]s;TXt {> VNϮ~_QV3ṩVcN~h0wbC~_ʦM<G?+?v+XhL2E>ԩS=O൮pm۳kuVVp{՛`hؗTJEu:.ƥI$Ry-$KY Z8]� /uAYt-Ij-we\;ru(xlxZBzXjw 3asF`(u�Ǐ}~\k Vؼya<G]ߩ}YcӋ..⣆x&4 - ziѻ!z<<5}lەcoT`(~!5/yfU}Tt {] VN]`W?\~myW?a<tR5lY,Zȓ`y}׵n!Vav#X~^{e} ֏v=unO4=e5SCNlCxVj%Ҏ>뒏*.(z<lUl(S,e_u#=L~@̉>$X,&I9rF8txȵ@ ǯ?b.l2jMlJ)(jw C{1<kGV-8o+jCb̀*`A x:S z+5@0quvi0-O'l+<u�|ĶU/Zy ` :Qo5zA*v,Na;f4x�cV?诃5:q*/yn3;=zV5ViuW^a[[4o5iW८pcxÊr޲)kjCyR3DL>5@pR&fTcR o9*Sa{y'䠝64ԐxOl)\b{8�XZۧ&ڵ+d1{'MzѵR1~!sXsz<"b[aXlV ƂШ 8p@x:`HV#/|jYZqhbx|;'s:CzO4t*hs3Ϩxѐg85X[nNyf<µVeӮ)l/Bg+agު?~sX>V7郗'N6Y৞ziL ,`ͨ60)f /W6n6v/u{`%=F>7pAB<V|yX1丕n-+tB鼓`uţ'<6=Y( ?;^c XpXs0O0O0Kňa-X@bNާ~*?O,XHH[Ia2nlVPK?�ҀU+a?Ot⣇2FS\z[ ڱfiAGlaHV?yƞ�V="G= Wj@}@A?\s-beJm~!q;CSjk*v,Na;f4x<@X]T[;2;<w>|?8<tJ?T!h+/7>A|ӎXB+M८pcu_sXpYxCÊX=^>lyXC) `%QSH4N4'0Dt۶mLgUcKh߇ V,zdJʄ%ް0PœK(:dE"WƧ7Qʻܞ7pVVlx޾ʛ [s++aA/1"a)h{`% (X}Vj̖5f/r5@V.W WbA+O+O 9پ+ m\*X5W#]x^0`WQp>,IJ%0 C]^z饐1  ߇& X[ORAADc-[(X)XI V  `%)XI V  `%I V V  $I V  `%I V V  $)X  $I 3gTԟI,4}3oY.k "ޣzF VlV}]9sΓ.]c.\(wuuYr饗ʋ/(Gq]YY?޽{6ꫯk^3|,?O75**?.Vy>g e˖ kw'{rzᅬwy晪|$''S[nkeyN/-i+?iէ|uXTXvСCO;`䷜Y][e+:9UrY+Iu.X,7pj6lX=ܣ>XGUkNZh>5ko[ٸqcW?C:رc\x ;'''?ӟ'FfpٳPk(y2c e޽oD}C)!XV[&O7(!WHt_{֭`mJ1I V?/mݦ7o s9'bA+T[oUv<_SS#=zJy۴i#q /={,?v񖗗Kϗ/XkۊwY] bǴc<Ju*=>yzꥆqMj:߯T~||:&͞믿^+Wⵌg+'}nfg{+g?61so?K.Q_|}ʕ!=袋W_}U***,FsOv...sڜ|W7|c)$ʱ1NaۅgxM|+v*+P~wCنWK_fṩˬm7ޗzKƍ<6o<-aj]v۷`cg?Sf*"^~e/ax=u8՛^{7СJk�mɗ9Z^-S7ck^&[xeVI9a @/0Zf$x X;iᘡXYY*Mյ*OM8m C_if͚%"֨mժzܳgO締@~iy7m@wiC9 x?#�C?OT7k׮?322,Oe˖ɱcǤH:v(m۶ cӋ`SNʳ 8P} \3bfLL!xXr7>-vsg3`+!VﶙO}�Ç䛶%Z  ?p<hzi:jee9=wn݂iJH8cc:v^x±`{}gʳ.믿n>M,o̫sHu]tM70/uܹj xX|ٯ`2,~nZW8EHkI>\.mF(bO)AҘT-oG%s#Ȋ%.YXV&(J,:ɾ悵217[d##ⴁ+j^�?яLݶm}۾}{ )O k<J�挡. ^cc/#sa>th@ <n?3z1cӬتbO<F�Pw}jGU)3ҷo_�7φ^` p?qk7|6# [ﶙO}l 3lx\!?þH14cc:v^x±{a,}|qcxn2?iTa>D9s?k*//eӦM#;v[CLpix:u'i3՛^ '{L>ݶ=[<.]ge7XptKY Z8$X!$U̲Y|Trmp(Z?t\:K ocBu?:7꽒ޣ-N�txp+0v]UI92zmJxwZFȵ#W; =n= Iʫj)Nú|rU_EBCe BX~D~5sǏxq=_c^<轴͛|9 >NȚ 7^<vq5xLhA [h93b1ҢwCy6y`iḵS>]C�UA!ɻmf/SǶ[ϣ& _HKڜ,;rlLSn R8r*wv]6/?sy=_j|ҥKհigh"O]׺Xf"ڍ`mϽ+Ǐch~者<pG~ʦH/`Ӌ'<>čG԰P -oO/gPwon`M+.1ҪJӜZ(u CNx bCt3x#-X*X*rMQcJ()+}}$5lCam?kg=~enԚ<ٔRJqsX,`^xy1zh5?b6  S:y+NqRí c>o|x!0-OKaW+xV0,(;+jS~ Ͱmg3f'` :QoIsrXڮ)l/Bc81+kf:Y3SЩ{N6sau}P0n+x19\{7ëKnoǧyqL[܏mzX=m+y˾<kخ=%,88C\1<zN^sRڏM z0p`U!>5@py IvHuͩߘc͝'+=s[m:ǸkC=5CE) $X1n` Q0qc"?@=8&MzѵR1~!sXsz<"b[a`lV ƂШ 8p@x:k)>}/~b&~p=o\}4q=hqv䁙=&]nd{#0sP`vH VZ Vths3Ϩx!X0aB?r9=7ӎklmW{axM[s03 o՟w[?S9H~OzCtSOy=納o& G^fԇ`u~?h᯶xMƮRW]BÊF/!~bn+pTlWĕ6DUb( zmSHߘyj~86F]:;;ޓuwQ  g-R¡! ?B�8y1 h^UO'?e h+a[?LƍÊjx�@y�x:=H4jJLLTܹ3(ڱfiAGlaHV?y`fOI94`_ch07ץ`uo`V{~Z�a<cNm vPMskk*v,Na;f4x-VVbdn?u(|gn҇'N6;䧞`<mE^fԇ`u~?0mˈ+Vv_۸i՛^ 7h?bΥqf_+E*_'o~1+}Ö!|#%Xώm3^b1iViFߠD("ѐhUcKhԈ V,JdJ0>/ vkn!sX58$XJ¨�[ 8kZp0p`kw,. (>I#Pvl c83qxv/RFГ^bER'A3 Շ`l)PCMi& !*B]`pT"m`lrJ0+4Bjj' ;WQpȮq`7f<>¢Iӄ4ObA aoe?U[%ϏŚ+3kqWU-Ò̗p0 uy饗B  / ֛M@OV>++AAܰe V   (XI V   (XI  `%I   (XI  h>`%I V  `%I%?!iw#˅Yx\DSٖ`%I V/xmmry']tQ4̟?_˙g)^z<sS/ٽuU^s5̝;W?OS;o޼}HСC3%\7̍ᾏDa֭VDŽ#$%<n}OZ}7|s[ .:ti,X`Y3klE=¶ +I$X,7p(b{ذawy̘1C Dw.wuW׮]+^{u뚵`ݱc\x2g)..VB;wl2{zK rYb{mB> ouS:C֧ML< oQCq&+2$mݦzP~e8G{ $W^yuYr뭷ݻ-m555ңGꪫǸM6RZZjƗ_~YK/]v!Czz%կ3P :w,_|"qL_-]tꫯJEEus9G|A˫3{<2`c{L٫:mc>[c+8'fυ0^ٳg/rYrH4\&#+E}7X 7eWN³zc 믿^#O몪?+Bw٦ZV*v>u󽰫Б7nܸ1i߾g+Vsˤw޾w&~̶LitA?₵EӶKiy-11Sc۬,I+Z9XT)j6ukj%JV%H iQ<.hQvg6W,OMn2Uh3rCeآE ߕ|V$55U^j;ql gϞrw+oqAA<oZƁ .LEl+dx@? ^]܃YYYOLO,[L;&EEEұcGi۶mcGOҥK/o[5DcHmN$))SxNyb~4>|̸Gl> ٨W+++= ح[`+!Tvt Md4x} Qu|zz⋦}gʳlۦO hn4Owu;%o&$XQ9f ;`e[2(B#.XHri32E}bs,|^LZ!4):V-=fKIYKkZJ"k aDDXª+$((ȂH,qaY.iqɻ"Y2 #30 SM=]]3L9uގշoUߪnzg_vG?~} 8QޛF-fѢDG.e㏛ /'xq#iN}/F�U\˗OȻ偩0O61#vNXl"j�w<.\'N%,[l=Ǐ9t0^@l !F< o+{=#GWq^x�~_Q6mieb'͛7M]Zsu#hpBjٲ:V{uZT>Aq)Θ1#͠r9zy~ʞꔇqI&#,QFFPxqڷo;%v ?zLˬ\ҵ?뛰1F4}=\v yl,v|ӿ5V\H1(m.:.F"]l|2݈MA\})T&RBr J}.^;te q_\ o\]sA߅;pn<z[=(?;#}-&Qxy"gVX@vݠ;I NyAfȎܢ&R=& OJɑVcFH18n$qïxbsӡd*?Sdxs3Q7~)<F.(Z*+:cFA]AGQVFz-D%۾n=2 0DOPG;{dwUu**o?IWbI)r8|ie藰ZìLl͛7kV!Ch {iGg;}ٗ'G&>n@] BOM(L/ D/ч$ @T6pZ[Q|Zw~xתTR3H<v2TxA *'xc%RɊlYE{m>v,&폸Km`'yN8m?C$;�ҍ9Ny` ۋm96dLv_SJ�#rJ3‹cʫĶӨ$Qbѩ>SV|@E<^et;XHӪTe,au~f`vOR^'VwTg]tt2<3౱61G|&bbtG ONjv^~e 㕰b(h%vN'h/y2SQ}l?H!Gj׿EhuSvv"uWq2Qi57ZkUD1!~xnKVSĴ:Rϥsk y"fZ8:XO"5XL.An?N<)jxw ک`<`l#E0!ѣb ; & bEǎX$U~v|qU6lX= 40>իԷsΉ}C >,8$!t갏0F$9Տ2_ `x,Z[&խnGFի83ZVwTg]ttVľ![n-:#l:yJ V/˅<2T.i/tϩ^r!vN'h/y2Xt ?2+ =ﱂC)Ę~L"Np!n\__ILUr+!`u0ےϒ"&So  *y,~!2 3R,25xoUy+ޟxl?HB`y''?ބF2䁕x6꫎?vؑ8LŊ=g'1Vö<mF^Yc`+nϝ;X> `5F5:Hr]񣫌.s1"i 4Xk~eKX{dd>3wPGd޸VwTg]ttV5V={v%Kg<b|0 4tPcw7:^M0:e۫]^bxh!vN'h/y2(bXq݀嗴;aᲈkzVx}x%p g#FxLӃ퓰"q>t2۫Έ_au+ÊZIUr=U&b]+#(guC@WY,^b*CW]?EJJ0gYp`9v7bXEDezVri"߄uיXA+bZs𒪦QyB?C *vL 0Rk 녻Zk!ʮ/# ?lJ1ؖcY?#6;Ű20n0 # ++DiHX o NargO<X%,a'++~7aӦya`,$/L� o!z3>?SE{~yy}_*r!4"zjjwbM 4m3 +I `0ʢSL Ĉ/Ng(V`0 FNƁr .>-b[r/LX2 `0LX9=SbzHV& `0 VNab`0 `ʄ'& `0 VN81ae0 `0ү?˄'& `0 VN2a͌7 FfKl^Ef1'|GLX9qʁ5%% DO?4,X>qj2@)eaLF!= uɓ'3eôqFQ?C=oߞ]=D<xʗ/E]S #,VZ=K̛7/M69',Pߛ^}ˌvr) ܹs^ϋ秹w У"YqQʕ3egN:j*u떐uт`3oo߾3#kF*X 6KfyZJJNN8^vmO+GOXwM/H{aš+UJVS!AGSk֬pMtt4 t krD>@dd$=ct)q>Ӈ-*q,4vX*]&wЁ޽k?s hт *D ͛STTy>!!z!Cɓ'k寺_NwܡyN:By=3'&&R"EDݑ+V֮]K&L,YvpIg{) b`xmۦkWmʩ-?Y52)7;uVTJ KJJÇvϝ2e|ǎ^-& nr;ӦM^^tjoO-2mذuaj%Jӧn�N:g? suuF8T~ny]t'k׮ZT0U@ݻ CNXoܤНɴ|Mq8qy]q 8ә6.@I)wd~oH:u_Dϫ9Eޣy76™<fS !7nZ ߟ q_޽W={0L?QlP~}|H1"(:uTW$ԵmۖgPm߾ݻGoߦ^zQΝ#G2h2䯺_aECotǏo^RƍhLL -X/3eo.5dGQlF#Yc0r*`aW1pkWmʩ[}ӕANQ+XBt/^H:uYY :]3:~N6mj-{W̰Udº~z18f͚kU.?zKX5kF:ꖇ]@.\/lҋnK tmJ(!'v¯ߧ_ ۟mf?c<-&7'Lenc^;=_iHj9;LW_g9vj1+:-'brarxIT.OtRlJXq5<qO<񄹿w^1[ ~bwO?v2eĉi+[kxYL1�b,1t0h�Ϸʤ~;!Stt90K,I͛7κxTZYǏ-CV1Sa0RpBjٲo/Xfc6*Ͳ祽Pɠk<3f̠K.^>N3;rAX5?U%.\ҭ&MRn:jԨg*gΜIŋ})Z{?zKX^jQ| [e˖om<._\K7 B+Wg}Vkz<}=s~R D>H'yl,~=iי�7s[j?6SxcN;op4݊K 8&?o{8:.)L_vGQl|2݈MA\z쌸ZL@3ϬޟN1=MfZz<QB~_5@uʅSb0FX5}]AÔQLKA)"0N/-O6p^Fla@Ƒ@q/.!Ld_uFz-dS_|QֈcYֆ7| LkWmʩ[}ӕANQ 0uZ2`�2KX $)-[iXbZgȐ!Z鸗>~ԧS5.-^nyX듗2ZF~U%< ZnP?%ǼvAq.q\&g{/ 2i':|1>\pN$x#6pK[Q|Zw~A/ @LUxXq_Sɧq|ت˴4XRGd<SΉa *=ӟD 4><^G4 mn=a OWmhnn dG^Xᣏ>R¶[ybӁYƏ{+VdT孲F,W;Yxll,:DL]> vV|ĽT锡Jn;=ڽ<7/HJX1mi:KXU훝NTzU'oSgd[+W443V]_c+^t񰢞({< ϧlsG1M-AÓ*?{g]vyDsZĹk57ܔź(v9:a^BVŠ^xI ]n<z4swx:�_gM +ܽ>~_ Y >eO? ܰaÂj��_`aGRV輬^ZL3ÔZ[cj@x U<#::B+X Dg@˲c[ei׮xot0)`~{yɩ[e3h+.]ttVľap[n-:#+:yJ V/զM2TmGCU^@/$պH ,L{jt"^O+;v4FU~,3 VV U'6stdDhdg H>E"<OǏb*f3z~up{9C?{L8P# <XCEXϞ=+/<bj h2Vö- pA W_}5`a(ܹsO\k]҂MUWo'YE8,a5Vh8+E|I'83#'dg̘1`튼fT孲H] F]EU|qx6c僁C ۉw7:^CatP%Uyda5<Zu^7;yh{wؑΝ;bŊu*U@Vx: gx kB1vaX߄yΐaJA<1ˢK}^WK@VmaS<fOހ [?[#SD:rf]ed02_rŠŋT/V ^f�u#HXj/_ŠU1v̺S"XXax?7D^]S #=lQSus4 YyY9vÊm9w۩eqVx 1LXYX:7Ä`0 Va]q o,:p+ߺ`5܋7(A_ܨȩ*_XJ^ > gfUG<guiEiD3AŹ;I` J0V'bMr?MGo񰜘2NCf͚&`0LXӍr m7rb`0 `LX3{”1 +V& `0 &LX3Ehu)&LX2 `02aĉ +`0 'NLX `0 &81ae0 `0�rĄ`0 `ʉ'&Y=H +\/ "3ɘzG&8@šB ~ ,H|8&k1VN)OfeƍTV-ʓ'=sԾ}{v,R3kTr]W~d}ժUK6#TysKs|ӦMo=s6V0z է@o +'NҝΝ;^{5:H؞?~49ڛUGCԩCV[nQll,=֭˽}#r߾}3}GQ%gF֌U6lHK.J*pvڞ&GOXwM/H{aš+V_#hj͚53Ι3J*Ey5jбc<cRҥCt]_ԧO*ZH1U =䄗XbvZ0a*TJ,Iv vҤIϊ={ǼܹCO=,xmۦm3TvG^خɓ';3gP-ĵ ͛STTs+}uknJ*U ٤$>|8 SLqZ-SNzi矧{̓nUXiѢE 6Pnݴ=X͵D4}t߄խMv҉=è./K.4qD}t5X듗~[Fݻ CNXoܤНɴ|Mq8ޜ0z2b)^2}Oڝ^@"R\JHNS? W2f4&Eޣy7Iͼp&uLX"0Ѹqhe#3+g}f6ڬY32Y:u*իWOx~m۶ԯ_?_˗E'sĈϫztbbbh?~ի_rkH=j(|4>7> m3TvpȑM1lPm߾ݻGoܹUM]t[0+VNŋSN׍7NxÅ?cW ]~2TtiӦtʕC>aAUVSNiS"Eh͚5AyX~연]Eup¦-K/'/e֟ѵ*}`򇜰e5 ~:|y^$ly~ˉu&V.U"V\2~?Gr/DdK8 -fѢDG.1ca}͆O<ak / xKX^jQ|}Lk9}XN=i4L2t s#we˖|^߼yԓus?`2,,{ F… e˖l~Xmש }8ɩ[A׾=Θ1.]z]r=fvpk~2KX/\[U;4iDuQF<{U=sL*^8۷Op[oG~ [Q-[Fo|r-X듗2p >V\ڟMX&+}xVe!KU wn(Imğ=WS|Tp H1Е)}q/0n۞(eKWĻ߈MA\ G 9p~[DŚZ I)L꘰ J5n`@@q~<bocǼ{Ƕs7|{ F*;hgH)A(rVgg7ueеn%0uZǏh_*/<l"Mc=͛7kV!CKGv$ adDwߥŋ-k}R^Oݴ➐VLmCBA6LX?<UdU=wu3gL':|1>\pN$x1&c-Ķ}{-j9;oFhݑa,R@Oƻ,.ˤ kPUj !#/( #zXu:TsmaI+1 Z V/(Nk\�Jv8o'*o�#* :BgntX|@f<*0SS*h^ڎ"+aE�i:KXUmNTzU'ooi\xq?Z3:‹>w&Mf<bACT m?cN q:x"f2`A:y3R䕼z;-Bf|~L=f :guAVL Z 7}ģ =y&uLX"rw[%uH!ɓbI޽�? 6yx.QjժO? H߰a<w3Af嘐vډE1 F^o3m uW hWSiϝ;'y;9Uy rЕAGWlEbОaz|:#+:yJ V/զM2TmGNU^@/$պH , aUv:QQVN;v4Kȭ?c+.A bA&fZ yLI/$ C o[ SV,rTǤ kP#H#N#d0`$XF]_}U_ 9�DX֩,nCIXU05X^O>)⭰ҟ`0@vƌf Vr=]q[% 2;wn.5ɩ-?#v%ttU.j<{K,yL{"0v`pС"ntȇ蔡Jn;=ڵwjxᡵJd;Aaǎiܹ*V[7^En[E(ȟ1քœ@`v CaUyXG )@XeYm'LZ1ŘI`+#cQ`020EСC,g6UV)K#;gBNXؑ*QzM?]كsᙝ'cUoİb%njX"Uv.A#VlBaj5(#cX2ae`0 aWrŁh1 b!@t{(ѾK/ O#9y왰b-J0i җ\Ɋy ^nYc4kW,G:uRetˉ +V6 `0LX5+2 `0`ʄV`0  +'&2 `0LX9qbʄ`0 'NLX `0 &81ae`0 9`ʉV`0  +'Nz___? ##=Hmnu7'|GLX9qʁ5%% DO?4,X>qLƑ#GA?~*^8}A,CY +5nݺE~!*Ty9rc^jJs7n2ɓ{9j߾=]v{| O<xʗ/TrݙUW~d}ժUKzr͛Mz~AF1W{zVN8;a;w.kty=|3gdɒxb/|=}nZ=4}WΖ>*ԩSVZ%Hwll,=֭ˬ |C}EAX3RWʇwlذ!-]4*UPrrrڵk{jǙ>zº{nz饗DڳgV&`Ą5_#hj͚5}ә3g`߿O}EmS5 -Z P)***9sPR(o޼TF :vy>!!z!s'OFp¢ `^ӧOMXqرcXbvZ0ax? :ڵ+I&ѳ>+S wܡzYm۶M[}tbLݻ혎ʹʩ-?!257uVTh.ȃuIII4|pa)Sʇv^-نMn'=b{ڴic=Mtk?O-2mذuaj%JӧKI'~wܭoaϩPtB'NG׮]yэ>y雹#B_ݻw򇜰ʰ;85}s&ݽOocd/./| 5t,%&ͻId D1VhܸqC4`pcZ( JŠׯO/_ ޽#F( *޽{tmիu9f͚QDD08⹑sCMXO(7Y�?϶`SA_yҌ~[G2&&,X pC'~ʕ5 ۣFC#ظqcf ~bb:uTWmR~<1iSl v>[btcPNl7n, Ǯd~Te|ӦMʕ+A|1‚VJN"ׯ"EК5k2_VW[wu}C_ؖɥX듗2pG1PD_O</?zz'U7ahh+ޜ0j1;':r)b"?~'}lðWLu1N@2eĉ>Fʖ-6 Fk^jQ|}<PvSwmڴ\r+c-4:[8qM>Qkw?~xέ԰0f ,\Zl[>0Bxc:6**dеkn3fХK\+WN>\]9?U%.\ҭM4~ݺuԨQ#^Ulc6ֹطo_ ѳ_ַJXP˖-~y\|nK#B_+WtϦa=c<Xicĕ{!'{VmDJHNSW i<v^Uy5 mO]I^fo򗳴[L&�tt\^w%DpGn n*&a 8oJ+Ǜ1U JLo1;l:v %aE $S=~x1�cckc C&>tnmXiy7y0>p :~Ut`א0sjtlUNU~l v.b$xq}^9ƭmZ .Cպ@۲e6,6oެEXAp `lGVsNII}W5b�SYQ^tcO^k_d8aKx@?8m&{.$<2IrA/ʼnߟNOЪ_v ч N?0'>uG]x]hL9G̥53Ԅկ@ 1U:{\a֬YF)9 "c*VLc0z 4vT[}49'Wi'*o 6bȠ+t1�ME�|ȬU%;^xtP%Ohw_ 0^ +(x;JN^O@ } 3V]xX4ۇ)Ιgɣ,a@]a#\cۉoû뇰3oi*_!S,0<:D1VbJ06�^O?4 NpÆ S6l^ZL ;w1~V=tz`ؒ%Kt4yJ* 18y򤐯w޾:rvzrl 3aM8^o [pQjժ/;f3T孲e2te[8g*MEzaU'O)bX!E>x00S*hiuϩ rҳ_`aZ~:uF;sVtь/}3~D(k.AaM Hg=E"ᘆLL>`}^B_xh>ybցQc*rȋ.b i&NF 1wb5G&@NBNG&!СCZB *@F'x8a5V!h0O š1 ;cƌ" 1\j6:vfɩ[eёF :�V5V={vy 8iX. :TݍN~bq2TmGOjjxᡵ*;yhwؑΝ;bŊuo֏e 㯣 a؇7UpyVLv75" <lyXeҊ)Lsaeߍ`xXάR FvGd8aGn5 KE<&{a}/JO;o8Q\ōz,@Ě':h)!~<la S1?:,✈V& nh `0=aXWӀŠP O+bGgmEXhdqGuq]xZKuƬbGƣ ^W X4Ex|IbM񰜘2a0 ȶ5#RR(); +V`0 F6aN,Ä +V`0 VN[ˉ +`0 'NLX `0 &81ae0 `0rĉ +`0 LX9qb`0 `0aĉVF/+3 ~ "3ɘzG&8@šB ~ ,H|8&k*Pֳ7nH+V'|ʖ-K .1u^sEŋ>'7cjբ<ys=G۷k׮qipA*_|Ϻ߮JNڍԕYep_jf*/|pn޼yioڴɱ>gNצw F7Tˌvr) ܹs^ϋ;b 0`9r)BW;wPxx8}G<msMbb"ф ��V5ԩCV[nQll,=֭,i:ٷoLQTə5#u|xdž ҥK<aR %'']'ɄݻwK/$Ҟ={2ara}<ZfM|0͙3O>ThQc;v pŊk BWP!*Y$ڵr*UK5jԠcǎ^uVT1'NMgΜ-Zwy}nݺI&y~_xwҥwCt݀<MF?<=cd~g={RBBN18SO1Kbdvn۶M3|=z0ɓ'; ʩ-?'+C(^DÇ^xA<wʔ)V«%$][$쫟vB>׿ZhylÆ bD4}t߄խoL Xs*?<Tb.]]^{韹:߽}t]r*ysBF&IXeK|@G.Q׿Ed 7L{ݡ_O7ed=ɪC67n Q˥KϣSP~}|H1"C ,S^ʕ+V 5k֌"""QLjLk1g/RN|yXe3Ϙ*T۷ӽ{:w} F]rE ~_SNz |tt4mۖpH7:z$l56_ȏFqٰ̒E[Uȑ#oðNDBeGrcte]jǍ'<*Aϋ^W?!|TjU:ua]~Uf͚<^~ڤPVҫ-ջ .\er駽RnPE?<^HEf$fWjlFEa3kpfM:~^(zӛ>f `'p<yR빈)eʔ'NQCln޼id>{AzG峽3f̰%~ +:bZFB􌎇ӧO|υ \[zrzbƈ/W3oٲXmשV;bS+C(W[]\9G|r ,[釰W05iDuQF<{U=sLþ}mSiBEXK-ջXl2z}˗^{)vYVrJl!Wn%R%la|sbqMr[q"aǂ!?;CK%}bdYaM}wawW1.#qI7pKL_VU"5sIG {Ɂ8KS]Ztu$QizדaT6bd ocǜ ~0s p`d#&OÊQj1c4J^T8Ȁ\_y/{˭XBx|MfJLLөΆ:}*;bS+C(W[m}oe9~xs2Y۲e6,6oެEXAp SoWv$ azNI~]Zx,#?2ZFa ?=Y;r؞ `3>_{80 p9SPunKqbz+HS1`y|}dej6,7'LȺm,S;I&U< tuwyUi='~yJG1ɥ_kzՓÊ;bX?<AXaT1g�#{8{ ʀ]즗 1(=(Cx(~uNjM.xN߲ <2iAQV03^o͎ɩ[e솮 nZdê3cp/<U:ei �ꐪ_~Y$x%wVU =$N^OȀ3j3V]]ֱ^XI;ONJw7_ԿՑbD&kv_t~TkoX<YF&U q`wQDžFlbM?aEtZxޓ8'Y"]J0F\j�J0b,~1CezVrH ViP~ k֭baJxIUӨc,(r!t2Ν:=1XR} jp~QjժR5be-ҴkNȁ%!>cXXz;CmZo͎ɩ[e솮 n)E +cX/W6mP%l<t^Hu ڱ`o6)ө32߉rcǎf\x韹:‹>9 LoŴYx@TfLG4tX+!aMHJ)$Qǯqϒba#etN&U{4k~J&Gj FƑt4A kIvցQctZ@K +F_ꫀ)${6Wö<$+F Zٳ}%Kya*T$Lu ~!ܹs+>)tw3F}AĖ W_ '&jx4\g`Q1ĩaD#΍x�3cpv[%͎ɩ[e솮 nZ_C1vxwE>XA Urf##!֪+ªM(tEھ;v9sN/3vYVx: gE\K_~E/ƉC؇'͋`6noRΈ_WaAҋtj<_v G*ݛBiIV% _YF? 0ET-rf]]ed0sW"+_7wu{- _qݼf7b[z,>yC䉿H=_]gbqI4vhbq!~K% y䯺_aE7k1Yy9$*݋ŞOU}&F|7F`09A.UxL:0 bYV ف'419"ӘuW#DsIRD'IC,(:얿~g :#<1-U#{B4ԕP&Ā`o"02 qSN3] e:`0 `df8p +'"cV`0  +L�,",e}0ae0 `0rĄ +`0  +VN2 `0LX9qĄ`0 q$ #}?L& `0 3ae0>de09.za_VIƜ;2ae0r aMIIAO?M O>D3p9/#at~zѓO>)~7lQ۸q#UXQYlYZpajtjբ<ys=G۷k׮`dR<xʗ/vIFϯ}H]UUV-]ۆP͛7/M69'[1W2& # ܹs^ϋ_uO֭[" 2D#GP"Ehݺu#+Fst >(G:uЪUDѣnݺ0FJΌ `;6lؐ.] k*U(999xڵ=L&޽^z%Ä +}+'FP `f͚SO=%Nf͚pl̙ԪU�6g*U͛jԨAǎs;ԧO*ZH1ycǎbŊڵki„ TP!*Y$ڵ˼ҥK tݻyEGG3<CQQQDAQV~k'MD>8߳gOJHHp|gwra0 xmrУGq/ɓę3gE PUNUn:9AnunJ*U ypV.))N/x)S\C{l#Nr;ӦM{1OUӢEc խ[7m+Vs-QM>7aukǝtG~ȗNŭPtB'NG׮]yэ>yKSt{/޽ + + l4nܸ!h-[#F۷7oذaW\t)_f͚QDD0I<eQ~}|HF`ʟ??ܯ\yԩS^z bڶm[ׯ_Ǐooqi.ŵxH=j(HY`02`aW1j4rHVΉHTPoN6ܹU]t@Ċ+DŋԩS'ƍ'<Ǯd~#n|ӦMʕ+A|+fXPժUԩSZ՘EfO鸗v ?zKXu,N疇] .l 2k}Rn][ ?V#lxl?>FAlMXF0A իW8ʗ/V2ʔ)C'N01J8Wy7o4e#ZsisqЁ #.1*dɒ4 Ǐx-F8a02!c/.Xש }8ɩ[Anxdg̘a;)_W\9G|r``ךvD^pAK* 4iDz4jI51{xo>%sJ:~연Y-ջXl2z}˗kZ[?EVrJ,V#VFqr +yW/>' Ǜضdg0 H 8_kщM/(F>ǮAt{'7ȄT8yaP ;{D*/b1% �UNUު츮 vӭ-bI)r8|%f 0 vDܖ-[Ĵigyf- >s:ێճBXu,^ש3VxbsSYW^tcO^kV}@^ÄȁU #L +MbX#?Ȭ>'xiKիW -vV\0U`d.`졲AV/(Nk\�J,_㼝X8:2 exf ccזcL2kaUɇAJ ONӣ{+zE2WŠdx,aUv:iu aZ~:uFrJ1Fj /߭?˄ƄAUjxX@hU ÇE< Z@I>5X% � FX% rF~:@X4y<yR,&p4 Fx7護 r<ǮAlРm9v]vB&tF<ǰ2XY~m!L֩#1a T�[eʠ+M}C 3LoϷnZtGEj<a|r jӦVӣ]*]/jF q;EXNN;v4K_ʭc+.A~& F$A8p?rY_JwyGD�:ܹs_c̯aňW_}eô޽{+a[tyBb^}Հ$2p_X}Sh`]Ħ`?Ⲱ"`02@vƌlba'`/V -F=5ɩ-?#v%ttV5V={vy+g<b|0Yr"O,S*hF##+�1<V]VU;n:y ر#;w~_xKStl}௣ ?V#VFhAQ+-0EСC,g6UV)K##)LX & ߈1LX `0ae`0aeši 7V.0ń`0 V& V& `0l0ae02 `0LX V`0  + +`0  +``0 `0ae02ae0 `~1V +`0 `0a?G #kT\/ "3ɘzG& F$)))4h z駩`'cnݺE~!*Ty9r;>|}]*P�͛^uZbE\mܸjժEy{ڷoO׮]`p<xʗ/E]S'?7#uGVY>WZtm{B[>87o޼47mX3kӻnPߛ^}ˌv2t'sΥ^{Ο?/ϟo裏uւt!_z~gYfѕ+W(>>vM͛7ϖN:j*AccciTn] FlA߾}3}GQ%gF֌U6lHK.J*pvڞ&GOXѷz饗DڳgV& F!vb�k֬i.\X<�Ho SLQ9sPRFt1O>ThQcnJ*U"p#_9=ر\X1Zv-M0AxK,Iv vҤI|Ϟ=)!!1;wSO=n۶m6ҥKY0:twaz!}<y#8s hB\/8rS[~NWW]ivj+%%%^ϵaV^%r~2tI؞6m=cyҭ߿?-Z<a֭(QON:g?KgT~ny]t'k׮ZT}/UHݻ 29pFƍ +*)R""" Afu0I3:ק˗//#z)0/^N:i5PZ`ϟzeW\9Z)Ge/Gƍ"39LLLԶ9SNz0Զm[ׯyaM2Pm߾ݻGoܹU_]tV7NxÅ?cW ]~2TtiӦbR0!|TjU:ua]~h׬Y9Wvyѳ_g<Tb4k-K/'/eҵ*}`3ae0r a}͆O<ak׎?mӦ ʕsۍ6Ǯ^jQ|2eЉ'}-[(3ҥKF57o4u,,b}O<qEf0r0.\H-[es0>f a�jNGINUު_ ٭ V+Wcf'\.*C… ZUVI&ԯ[5j䉤3gΤŋӾ}mS۽=%n}-ջXl2z}˗kZ[HVrJ,V#VTL!NjiY^ab ` aDӲ)^ }lb5P\ Lcsiqnɾ߿_ÞAʩ[ՕA>wm%h_*/<l"Mc=͛7kV!Ch~}<َD{!^Iz:c\x./'/eൌM> /a`@ªa't/(3�cP$,ضE&`0r&0kZ�:6_t zApm"~vrvʠ+t1�]bVׁyXUa#J UrTT"+aŴQx,aUv:Q9VNo)fY8fKzX![Eg2٘"m`LF#iNK,Si%ȑ#bZ,ˇD\C駟Q`nذayb C`tB0%�<'OMP 1ؖc:0C1 F^ok``W`=JZ2#LIɾ^ZL=wP4ɩ-?'+0؊7=V[[a"1^䃗 :eK;<t^Hu1 X'ªjt"^O@|'Bϊ;q~t*UHVx]LXHX1:p@1j4xi!_|hԱ-#:=bw^aiD>o¢Ci&{6Wö< D $F1 !{F]j-0O> Xψb09 ;cƌms:&.ÅxW_}5`A {J0'2wb\kS[~NWW]EUgϞpޭÀСCE{')C^1/ZtݷӉJϏz-?w>ǎ;߹s'UXѷnTe /_GA~& F$ `)ց>3k*%CLX & & `0LX V6 `0b`0ae`0 Ȓ8p�V +`0 `0ae0 `02LX2 `02 & `0 V +V`0 F3ae02 `0LX ֌B`0rc[B7P/29;Jwd`@ b$;РA駟 '|"P.T g( kG7RZ(O<sQڵkq0YgxGQVϯH]UUV-];-7o^6mrO~ӵ]cM>eF;LX FyX ܹs^ϋ?R/ kzb;ԩSVZEnݢX=z4խ[?# m߾}3}GQ%gF֌U6lHK.J*pvڞ&GOXwM/H{aʄ9_#]f͐=k7g*U͛jԨAǎ3ymy4vX*]wЁ޽kOHH=zPBhѢ4ydmŠx<Ŋk҄ D%K]v\;i$zg={ pzꩧ`0۶m}^gΜ-Zk (@͛7(G9Uydueеnm֭[RJ]A"%%%^ϝ2e|hՒN&[6m4z[a߿?-Z<a֭(QO޿#qM'~GϩPtB'NG׮]yэ>wEݻw3ae0 lTnܸ!&͚5aP1-`O:ի'<Զm[ׯy~ȑT~}˗/ Š^LL -XOz2+Wp<$l56_ Rƍ`0`a7CJޮPm߾ݻGoܹUI]tmGHŊ+DŋԩS'ƍ'<B|Y@OMkڴ)]r%AW^y Z*:uJ_)Bk֬o1`zgԽ#FG~ [PӅ 6m\zэ>y)PE +5 qaO;azG atӧOŨe҉'}!7o4>Qk?~\4R̰08, R˖-}ه`핛GIN/-?/A%-uΘ1.]z]r=fv 6ov-ݪ+ФIA׭[G5DR3gRi߾})(SL'vG~ [+auC.V,[~msqZ'/ewѵ*}\S + yAn$rïLG7퇰zǶyo`d`*/1% �UNUު줮 c$xq}^9E^r4`�2ۦY@Ss[lӦ^͛+ΐ!C^.Gv$ aN:+}]ZxL,/'/eൌM> /a`0aMaA4F|/vWMXa*VLc0A>m?!X{%oZPbqT햟-֕AGW�:DL]> vV|{)Cܪ6kyx%U/HJX1mi:KXU=;JN^OȀ4W\i8fzX}[E{2ae0r aE*^�5 O@$Å'O> 0]`GRVhРA@\Nam9N]vBVt0 `d `ի+ymb*s焷8o'*ol :R-[jW1Oa"\mڴ*Cܪ6kyzT6b A.O0O? wnذa:QQVSgd wgEǎ͸j?Qc+.A~& F$n1$�FX(F0ma(V3Vj={Iy68&D W_ X +#b E,a5V3a |I.3f!X{%o?A&r-VEy;9UydueѕmYdx6c+C1vxwE>XF Ur4Zt+\S;yر#;wRŊ}FUug`@š,͊`0~:t*e`dV kDB>LX `0ae`0aeg0 ``02 `0LX & `0 V`0 ``0ae`0 ``02 `0LX &LX `09_̄``0 `0ae0LX:2V,ezd Qz#V#V#92VN) cz7 IXe}խ[N<! .LM4ϧ27nZjQ<y瞣ӵkh1lqA*_|wu#:3RW~d}ժUK׶'Tyڛy9i&䷞'ye`wozo0ae0aB*2@ll,7*WLTT <x QVuSZnݺ%gbPG߾}3}GQ%gF|`;6lؐ.] k*U(999xڵ=LX=aݽ{7K"ٳ +V _U\9:}؎{\"O:%ߧ>}PѢEE6�>xƎKK Rݻ3gP-PBT@j޼ lG<d<yVUtʛ7藍hzgdOLL"EP=N6yQӌ'(~+Fk׮ &)Y$ڵ+I&ѳ>+SP>O=--۶mv= ۪֮**o}]tY7{uVTJ^DÇ^xA<wʔ);vLxd6GjlciѢE 6Pnݴ=X͵D4}tmw҉=!_؞3gCK5ju>sC.vҥ M8Q|]v 8E7j_UmwEݻw3ae0;aݻ7͝;WlϞ=[?(Y_>]|Y$xFa:u*իWOLok۶-<_Bھ};ݻwn߾MzΝ;G)d2d_u!=n:Ǐ7oq aY'ަMRdD=A$|}كkBQlEÏcFl6tavEV}V9Uy{Vʠͺ3L_bt_x:ud{f.tgt=*[mAW^yRRRıUBº~z18f͚kmÏf͚QDDmUz+Pc 2k}RnmPE +5 +a>;РA.S 8q¼#me˖u_i2@!FF VtWݯz'ı"voNLwODtLL̋w=1/F]}E�P6mAvZXuԢB jb}ߜ[I]Xd]sSC~Ki&*m楍t¨_;uR]]z_ǣ׵ѣam~| ޴p 6Hz6}_z} ~ƭ~:٥KJqqzzGp"?sm` }m?Sҥj^lۿdgg{{{c _w`uڇ+[l;kx}M9p­=RRR<}%kOe)]C9/_6iu[m尡|co~/LL1Z/kߺ%\m{k7m۶uܟCGis(6ַ z}uW{ڴiÛniЉumt۷! i+_i/>%XBԫZ}hk{m4#tYjjlG/W`Հ3cƌ8pBEΑ>SDs>ֆ|^ խ[7IJJ KWxiדsE mnC`X~k`ԩ }I^4�5&{xBo۠&ݿnǤؿqtkHfD ?|Tos7N>m X*>~밡+a۾[?mK-؄{O:>SĆۏp=n/t[sW4)VXQֱ nĭcg^ϟ׌򗿼Zfm^=Y+@`}wyG18ŋ}T2k֬zc'_~A t0:1#G䩧 ./۷o7%Mz O~ﶽS_F:U{e B[V3y9XN| ~}ΐ!CqXP0t(aCW췝۾[?mct~cVڎXpўRêaR?<xsVp6gnH :OC^kvSӫgB 6,8:o /.i X~roÇCziNcN#]2aGB踧71կ~e꺡XPE+%in;Y5V~H_ljhbX(D+gXNXK$:>H'ۿ[36Nge ;s̉umopO[i.jٗ8~}n]_$0_B͜9Ӽw[O{%ur?Э1i4ϱJ{6v{o&n|XPFF-gff?ux7{ПX0E|𠣝 zw}G=W%p?$VGtRX�  C3-_ �@`@`���bV ���XX���+@`%�� ���X+���b+@`����no`P( BPB` ���<H���� V+���@`�������� V��� ���X+����+@`�������� ���V�V��� X���+�+���@`�������� hZZZ*钘h4)++D��� q;vHMMu=]CM?��@`!ruvktLO*u(&Nb=Hõ5��X4z`MHH˗/*.]/sl*2t8aV��@`pnw_\ |&%%kki67duҥgoiA^ۮ Au,m7.WwaQL6ݬעm{?MΞ=\;%wnu ;[<=Dl-{{scө^v=Bs yi34 r{{C{]?(<>3Cɉ'nv|}"v;u zJH(0fNʕ+ͷL=m}bu���xP?̙3빚Yb ~n,#ƌSRSs^f2[޶#ǎ7J^zM}4XsJ]] -\zz6jZ֟*K7IMK7\fϝ΍YOz_lMfno H[m__ds;1~rZyvVjumO^Gӄ)pfNBEaey1��V UUUJE 4x K2p=},ٷ?'ݟ,/^4[5VPHaש΍YOzʒ^6a]?iLמke`Kŭhmd멬t:z.��V Tt`?=7o4=UϽ0B22cF~h`u_u, ;Gƌ5ZZؾ/ξ/;z:qH@unz:N{w5\^28V^j=4.9}%:-m]oדKs.��V ;~JI |F3U/uՌe`okmXz;R>gˎuk_ Ro[="@g>s<^|;^Ƽ8Aֽ?jxs_{\õ5!Ub ={m_͜΅<�� <PW),,D߁UMCi_`&=qRΘUo[ TxP:NТ22SFko0uYxDz6s +]{scө^7m W%ڷmyXu<K: :n޶^^O~ΥӹxưjvzX?��@`EX@zfaԀcl-fKW-XxL=L#[Y]uKgƋtW[=B+\c$J^ܘtW(-\}ޟrOss⒰L mVԙYpu'?v;impKs�U,z.k1�� L`aS VtINNnc�� ִ46RuEz999ɓV���+F :RJJdee]E1Q���V;˃u?.ߵkWU��� X���+�+���@`��������  ���V ���XX���+@`�������� ��� U`---tILL4TtyZZq"���@`иU;_^^PGi|p� M5##C*++r5עΖ]I{^ }$=UiE8(&AN1D;&cV4��V> re_ҥKq%HUu\rErVMx>h_f#ߛ<˺c3p{��V>݅ |sIRR뾛i+"~ȶ cpf| ?Hv:K卅Li8eeҾS+l51IE+IHJ6q]^˛CÏRs^Ҵekyf09qdp> :>6$$^72˴m}LW +*qVTTf:-b_둲cOŭzV=zILxUkי<cŀC=wy>WEE2ytE21~={uuoܸaݥgo/^"qj#u:Hqm"'R;o:y�@`pP?̙3LgQqkȲ?6aJ|0 )#ǎ7AO^zM:<;ٳ/0w4ug>sr?Մ^rZyvVtSo{ \Y˗S&[S[~dmۃBMRM`P={<ρթ׭aFKqIԜEoS}kPxlR[y?hd:Ey>߾~I1b89UZjy+eK"S }mVPn~^o��XܶZUUTk@|kwi.N^zAXYYcH?'ݟni3g(?}GM1+=M[ C{wV=feY/c0Q^4܏iks[{,7nbOݵ#hTok2A:V9sW{V@Wzmj/b$Nm־^+5[}Bo:y�@`pk9!K`>czxHn޼RlJ/K,<~\?7<6O?}6;ۄ>9Cܪi˥rϛKA5%v~<nz1Xk2ІΩt\=vL^3ִu,{굮(uV }.vp ǼWkmq;pupz�@`pRRR;R5vOUNvJ{15 hO;K'Mq|zjV5 fQ_4u*u B/_1 NJoKsڷw{}߾n~OKxrj#/ 6N Nn4Q��V�-*q'gH{:̌k92 |V yָEmcg;vKmHWQ>i/Ƃj@^bepyͦך<z_/ɴt"! r)sCxȒSnVo\i J4k]t!nMڴO3IsIx$Nm־nn{m܎7\�� 5?Ak)**XIt\~֌J'O-̰z b^zaКغW/͍6s\ݏ%t` :5ۮ޶_Yhs]\s>A/2=ez9ު".]#bo`u:W:#[o5Np謹۩GөmﶍS}µ񆫃��V�%j@hr+^AA$''ߑ7'+��@` iiimƥ .rrr$##�� h(HVV߿ߵz~ lAV���+@`:˃u?.ߵk ����x+���@`@`�������� ���VJ`�������  ���V ���XX���+@`���@`ZZZ*钘h4)++D��� q;vHMMu=]mÇ<z_&om ���!ruvktL}WVUWgK\Ҥeky~HٽwPd_c.sX��}X˾ʥKQ˛Kޑjr|0񎇝;+X��}Xu .*Ν$}7kVjk/E :b<!ytCnP :u6q իW#A`Y}.!!1bgaQL6ݬۢm{?MΞ=\V=zI$Ov:V/vShe֮3Ԟ{d;:u)8(w.I6eCiҹg/I1�� ۟P?̙3d7$b ؄)RQQv==rxbuxo4|sPL0h6˰QDjjˢNozV /^mbD<y"^ݶcgI\ץr=w�� _UUR^^ <wֲ]+No˓OX]f_ɓǰjDK>}[ӾXeB- ul w>*?[=7oӧ ���5vs*:CjW]}FDn޼Aˢ:.]~ y1yaXi!xmq_~XV/ wzw-幏x\&O:t ~7+�� XOO)))XZsI?{ê=g7nsauzXVXhGKX!w}f -��� _qqRXX(7qX{u%.3Z-:1/w`5V|媈uЉxH!LUZFT)3}8S]n SݎinU`yR^4:Y͜e,Љ4e���V;RTT)jH^q4�;d3{Kg륫,4+]hu]i=LzyK3[/ߡ]=3S3z۱:ۭ^ <1' ֬5w~ٟ^N���Vju-^AA$''ߑw?��@`&f\�\]]r]/''G222��� h(HVV߿ߵz~YY���V�XКj.D*|׮]w,���V �������� V����V ���X+��� V��� ���X+���@`@`��������_kiiKbbOҤ���+ >w!555trN=&�� RYY)ׯ_k׮]OtweU|uu*MZG{Nbѧ)~Dٗ%OzZE+D_7l[D.w[{�� /_U.]$^7^\TUW˕+W$oe܄}Pһ�S9MJێ%-#Sjk/IqI+���xnw_ܹsfmښ)؋ұ[yi!m ҮSgip\z1 }QtKl- &'N .иͷ}.m}y Y}Y(sޘMTK3y wNAO{—\%{V;IH&OnڷE21~={m>^7nܐUkIu\ys%Nu8-bI-eǼa���+pV ~ʙ3g<֡#FoJQqk?6aJTTTF i#ǎ+*L+Vq xJiY <+׬g.8hC-GǼnJc:حM4>zz6j顭9/c?hd:Ey;#m*!)YF'JK3^-^X.$5-ݴwYy̞;7 ��@`ZUUTΝ@]Z^~%b?VVVOqNOǍZ榭wݧѾ?C}j.h2u6qm`ѧoĞ`tEӓtܶqO(^iS:u)7oq ��JK�X` ?3{ vgLٰ]͛7CZ-mK n?C/g\َ2n$m=3z\~c˜R\~hss䶍h~<nzW['ڛ�� z`aSJJJ|Vu֌XcVV/T f-n2/mcXnO1=O?\ԘmTp^4,9 {331��X{<*oYYpgM'Y23ӢƿêcNw[Qo .[2._~폷<ꜹf /mO陻C~̘ђS<?AOg)Ku{LyݶqOAҦM:V2u,:L9|k`е;o�� 5?Ak)**X54L %bt2{cPYy z1 : 5Kޮ %k`Չr~{PwUY;:w`]=3T ^I_{8iBݞm{h/CDzj[8Ȅx:+SXg I���=XwXTChnnk $99? ���+ִ46RuEz999A`���@VD)%%EdE&!�� XXКj.D*|׮]w,���V �������� V����V ���X+��� V��� ���X+���@`@`��������_kiiKbbOҤ���+ >w!555tmjmAD;��+@`-##C*++r5עQ5Xy�  re_ҥK:V��@`QV… ʹs$)))&@v xz4mZ:%)?.qㆬZN-:ȫcr$W\o%;u1Eoc<| &'N<x'9{lqYn۱TWq<ѧ?WTMIEE_P`{9f}ұ[V=zI;7EE2ytih^&Owllz[=6N���5Urָ̙.$5-r=w^pYBR3NN 9ٲ%Oȱt= =F?RZVf5k#nEe ǿ@Mz,N?5eeG&lݶ=xA z9f} SaW^^-%%fEo)sP̗ zl{QߩnmVp[}BEN���5WY`ԽlܼEOe{%UUuŊ[>=xݟ[y+M[^%N^9YUs/_~z,NϿ7+Kzwe~K3e_{:f}^i﬽ŋMacS=ޭm=pupj?��@`1Tt`/ZիW=i2x؏Mc:F?,h~h`FuK>RoOKys >Nϯkxd.7=U^jmvz_tvGƌ5i]k_c[@?VpDN���5UO)))X;+=e] {]iP,^zX#*>|X^ymNêƼ8Aֽ?jxs_{\scР'Q>s55fnhz[=mﶍS}1vѴS��+@`A`-..U %11u߫֬GyyKf2!O{^݃˒6m2cB 'eYVCoV*^!Fos<O޴YZ N~_z=pǠc5Rб22K]w[ۻ3n8G'㲋��Xkk~CRTT)P Ӫg: jѱڳuUDǢftla~IzϧX'7fu! \:&R%=Qu}Y{~Qqcw KgꪗL=Le:.WmG,ߩnmVpۻmT`Ig%o;�� j (Hrr}3,:9����@`MKKl3.Ug�Xt#u;ϤX[T���X܁(HVV߿ߵz~x5찛n��@`pZSSSHEڵ��� +���@`@`�������� ���VJ`�������  ���V ���XX���+@`���@`�������� V���4lIII1(mCX+���bVw)W\1@Ooh%V���D=/_:JKMMiO+@`��@>i`4hh X��9B`���縋/RbT����1w…F)H_Uhw7+@`��@ ?ǝ?Q_JN'zX+���b9NgE).)YӔ_Rk'?i,XlM At<f7+@`��@ ?ǝ={6&Eꅋƍf\a=rU+9Ҳ|߶ ?ȮTYv-˗fHNZgw~z6f!V���sܙ3gbRܼyS`?Ck̔;ʇfF:$6 5Z,~KN>-.Ȩq/ƬY����1W]]b֤ka9>v|סd7ibʷ=&G}V8Є#GȔnO֏IUU zܹsZ~?qjA?NM(#{2Zm},As{ɻˤSҪ]Lk!V���ܥU0@R_$W/9صd=d:v~$^<z[ #yˑ<}<%{̬j1_f ~FRwj.y!rݕȰP˦͜%/ V���ܭ1e[>[<~l=˷�{'do۶9اcΝ;رc2乧oOii̞3Wtmˤ䧟~ .3 ?\!wn%n$L ;aJ$mdn_cܖ:ez[cuZ����1WQQ}sIƍ&y6,_<6i"[$kzo$9Ώ?(e?rELOːÃeesGzj){YhNN<)'N01]ִU6]u X��p֕k1OK~e[ n ݟ|"0nzM=k ϕ:zKѶfZi?uLYr,[\kJa-,*W+:~+@`��mMyE'm/&jk~~WǓfffJ^^ ~f-1fZRR"'N s/.oߩ|fq&j-ؽ[?ה={oHHG40F0yJ̎?ϿV ���q1(7[_LOjYYڵkeN,Xg߲(燙`mӡi&>ҼAT ܣ)zzL ((=5˘+@`��]Xg̚&W\5kXllzZ LO>zjs G{akkk;_ }̍\'`K{ZBmDnkT ��.W^^2%~qڣzêRC?ތa}~1{X+���b9N/ݍE?I-[*%,yϓ_yE4]&O&cƿ(C ~O >Ksǎ  �� tXo9 ƌ0^  �� t"$Jl  ��J`@`��?RbS����1JM!V���HJJIQQEGۓ X��O>D?.(' �� U{%7X+���p"V��� X ���� ���V�V��� X���+�+���@`��������  ���V ���wBP( BP(?9+fv6I����IENDB`��������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/index.rst����������������������������������������������������������������������0000664�0001750�0001750�00000002647�14035600052�015002� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. title:: A Music Library / Editor / Player .. image:: images/paned.png :align: right :scale: 50 % **Quod Libet** is a `GTK+ <https://www.gtk.org/>`__-based **audio player** written in `Python <https://www.python.org/>`__, using the `Mutagen <https://github.com/quodlibet/mutagen>`__ tagging library. It's designed around the idea that you know how to organize your music better than we do. It lets you make playlists based on :ref:`regular expressions <Searching>` (don't worry, regular searches work too). It lets you display and edit any tags you want in the file, for all the file formats it supports. Unlike some, Quod Libet will scale to libraries with tens of thousands of songs. It also supports most of the :ref:`features <Features>` you'd expect from a modern media player: Unicode support, advanced tag editing, Replay Gain, podcasts & Internet radio, album art support and all major audio formats - see the :ref:`screenshots <Screenshots>`. **Ex Falso** is a program that uses the same **tag editing** back-end as Quod Libet, but isn't connected to an audio player. If you're perfectly happy with your favorite player and just want something that can handle tagging, Ex Falso is for you. .. toctree:: :maxdepth: 1 :titlesonly: :hidden: screenshots changelog downloads features bugs_repo guide/index packaging translation/index development/index license contact �����������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/license.rst��������������������������������������������������������������������0000664�0001750�0001750�00000001031�14035600052�015277� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _license: License & Contributors ====================== License ------- Quod Libet and all associated modules are free software distributed entirely under the terms of the `GNU GPL version 2 or later <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>`__. Alternate licensing terms such as MIT, BSD or LGPL may be available for certain files or modules; see the files for details. Authors ^^^^^^^ .. contributors:: authors Translators ^^^^^^^^^^^ .. contributors:: translators Artists ^^^^^^^ .. contributors:: artists �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/packaging.rst������������������������������������������������������������������0000644�0001750�0001750�00000007013�14455205526�015622� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _PackagingGuide: Packaging Guide =============== This page is directed at distributions, packagers and developers. Please :ref:`contact us <Contact>` if there is anything unclear / out of date / missing. For license & copyright information see :ref:`license` Existing Packaging ------------------ The following distributions package Quod Libet: * Arch Linux: https://www.archlinux.org/packages/extra/any/quodlibet/ * Debian: https://packages.debian.org/source/sid/quodlibet * Fedora: https://admin.fedoraproject.org/pkgdb/package/rpms/quodlibet/ The Ubuntu PPA / unstable repo builds are automated by the following scripts: https://github.com/quodlibet/ppa-scripts .. _Dependencies: Mandatory Runtime Dependencies ------------------------------ The following software is needed to start Ex Falso or Quod Libet. * **Python** (>= 3.8) * **PyGObject** including **cairo support** (>= 3.18) * **pycairo** (>= 1.8) * **mutagen** (>= 1.34) * **GTK+** (>= 3.18) * **libsoup** (>= 3.0) * On OS X only: **PyObjC** * **feedparser** For icons a complete **icon theme** is needed, preferably with symbolic icons. For example **adwaita-icon-theme**. For playback support in Quod Libet one of the following two is needed: GStreamer ^^^^^^^^^ Required: * **GStreamer** (>= 1.8) + **typelibs** * **GStreamer Plugins Base**: Vorbis, Alsa, ... Optional but recommended: * **GStreamer Plugins Good**: Pulseaudio, FLAC, Jack, ... * **GStreamer Plugins Ugly**: MP3 (mad), ... * **GStreamer Plugins Bad**: MP3 (mpg123), MP4, Opus, ... * **GStreamer libav/ffmpeg**: WMA, ... Xine ^^^^ * **xine-lib** 1.1 or 1.2 (the shared library, no Python bindings) Optional Runtime Dependencies ----------------------------- **dbus-python**: * Enables the DBus interface * Multimedia key support under GNOME **libkeybinder-3.0** + **typelib**: * Multimedia key support under non Gnome setups **libgtksourceview-3** + **typelib**: * Undo/Redo support for multiline text fields **libmodplug1**: * For MOD support Plugin Dependencies ------------------- All plugin dependencies are optional and will only prevent the corresponding plugin from loading. **notification-daemon** (or any other implementation of the dbus spec): * For the notification plugin **GStreamer Plugins Good**: * For the replaygain plugin **GStreamer Plugins Bad**: * For the acoustid plugin **rygel**: * The uPnP media server **webkit2gtk** (== 4.0) + **typelibs**: * For the Lyrics Window plugin **libappindicator-gtk3** + **typelibs**: * For the Tray Icon plugin under Ubuntu Unity and KDE Plasma Python libraries ^^^^^^^^^^^^^^^^ These can be installed with pip (as well as OS-level packages in some places). **dbus-python**: * "Browse Folders" * Screensaver plugins * uPnP server * Gnome search provider * gajim status updater * MPRIS * ... **paho-mqtt** * For the MQTT plugin **musicbrainzngs** (>= 0.6): * For the Musicbrainz plugin **soco** (>0.27): * For the Sonos plugins **pypresence**: * For the Discord plugin Build Dependencies ------------------ * **Python** >= 3.8 (stdlib only) * **gettext** >= 0.19.8 for translations. * (optional) **sphinx** >= 1.3 For user documentation ``setup.py build_sphinx`` can be used to create the HTML user guide and put it in the build directory in the ``sphinx`` subdirectory. This is not part of the default build process and requires **sphinx**. Testing Dependencies -------------------- * The build dependencies * **pytest** * **flake8** * **polib** ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656314886.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/requirements.txt���������������������������������������������������������������0000664�0001750�0001750�00000000053�14256256006�016425� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sphinx>=5.0,<6.0 sphinx-rtd-theme>=1.0,<2.0�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/screenshots.rst����������������������������������������������������������������0000664�0001750�0001750�00000002131�14035600052�016217� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Screenshots: Screenshots =========== .. figure:: images/paned.png The paned browser, providing a customizable hierarchy of filters for finding your music .. figure:: images/album-list-2017-08.png The album browser, giving a visual anchor for a large library .. figure:: images/covergrid-plus-waveform-2017-08.png The cover grid browser, giving an even more visual anchor for libraries .. figure:: images/soundcloud-browser-2017-08.png The Soundcloud browser. .. figure:: images/queue_2browsers.png Quod Libet's queue in action, and its handling of multiple browser windows .. figure:: images/tagedit.png The powerful and feature-rich tag editor interface, shared by Quod Libet and Ex Falso, that gives you the freedom to tag your music how you see fit .. figure:: images/tagrename.png Quod Libet and Ex Falso also share a powerful file-renaming system .. figure:: images/exfalso.png Ex Falso, the standalone tagging application .. figure:: images/plugins.png Quod Libet and Ex Falso are highly extensible through many included plugins ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9609354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014404� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692733856.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/default.rst�������������������������������������������������������������0000644�0001750�0001750�00000002373�14471210640�016567� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - Quod Libet 4.5.0 - `quodlibet-4.5.0.tar.gz <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0.tar.gz>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0.tar.gz.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0.tar.gz.sig>`__ * - Quod Libet 4.4.0 - `quodlibet-4.4.0.tar.gz <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0.tar.gz>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0.tar.gz.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0.tar.gz.sig>`__ * - Quod Libet 4.3.0 - `quodlibet-4.3.0.tar.gz <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0.tar.gz>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0.tar.gz.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0.tar.gz.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/osx_exfalso.rst���������������������������������������������������������0000664�0001750�0001750�00000002271�14231604332�017473� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - Ex Falso 4.4.0 - `ExFalso-4.4.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/ExFalso-4.4.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/ExFalso-4.4.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/ExFalso-4.4.0.dmg.sig>`__ * - Ex Falso 4.3.0 - `ExFalso-4.3.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/ExFalso-4.3.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/ExFalso-4.3.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/ExFalso-4.3.0.dmg.sig>`__ * - Ex Falso 4.2.1 - `ExFalso-4.2.1.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/ExFalso-4.2.1.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/ExFalso-4.2.1.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/ExFalso-4.2.1.dmg.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/osx_quodlibet.rst�������������������������������������������������������0000664�0001750�0001750�00000002327�14231604332�020024� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - Quod Libet 4.4.0 - `QuodLibet-4.4.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/QuodLibet-4.4.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/QuodLibet-4.4.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/QuodLibet-4.4.0.dmg.sig>`__ * - Quod Libet 4.3.0 - `QuodLibet-4.3.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/QuodLibet-4.3.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/QuodLibet-4.3.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/QuodLibet-4.3.0.dmg.sig>`__ * - Quod Libet 4.2.1 - `QuodLibet-4.2.1.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/QuodLibet-4.2.1.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/QuodLibet-4.2.1.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/QuodLibet-4.2.1.dmg.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/windows.rst�������������������������������������������������������������0000664�0001750�0001750�00000002517�14244626671�016654� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - Quod Libet 4.5.0 - `quodlibet-4.5.0-installer.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-installer.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-installer.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-installer.exe.sig>`__ * - Quod Libet 4.4.0 - `quodlibet-4.4.0-installer.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-installer.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-installer.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-installer.exe.sig>`__ * - Quod Libet 4.3.0 - `quodlibet-4.3.0-installer.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-installer.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-installer.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-installer.exe.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/tables/windows_portable.rst����������������������������������������������������0000664�0001750�0001750�00000002544�14244626671�020544� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - Quod Libet 4.5.0 (portable) - `quodlibet-4.5.0-portable.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-portable.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-portable.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.5.0/quodlibet-4.5.0-portable.exe.sig>`__ * - Quod Libet 4.4.0 (portable) - `quodlibet-4.4.0-portable.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-portable.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-portable.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.4.0/quodlibet-4.4.0-portable.exe.sig>`__ * - Quod Libet 4.3.0 (portable) - `quodlibet-4.3.0-portable.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-portable.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-portable.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.3.0/quodlibet-4.3.0-portable.exe.sig>`__ ������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9609354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/translation/�������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015470� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/translation/faq.rst������������������������������������������������������������0000664�0001750�0001750�00000010564�14035600052�016775� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������FAQ === What do these things in strings mean? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ``This is %s``, ``an %(foobat)s example``, ``for {translators}, {0}``: see `String Formatting`_ What does ``msgctxt`` in the .po files mean? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ It stands for message context and (optionally) allows for different translations of the same translatable text appearing in different contexts. For example the word "Search" could be a title of a window or the label of a button. The former meaning "a search" and the latter "to search". Why are some strings not translatable? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In case of strings like "Apply" and "Ok" that show up on buttons, these come from GTK and are not part of QL. But there is a chance that we have forgotten to mark a string translatable, so please contact us. If anything else is not translatable you can start QL with the following variable set:: QUODLIBET_TEST_TRANS=xx ./quodlibet.py which will append and prepend "xx" to all translatable strings. What does `titlecase?` mean? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There's a special string `titlecase?` which should be translated as anything if your language does not use `title casing <https://en.wikipedia.org/wiki/Letter_case>`_ (eg *This Is Title Casing*) for labels. If it is left untranslated, title-casing will be used. String Formatting ^^^^^^^^^^^^^^^^^ Some strings include replacement tokens like ``%s`` or ``{foobar}``. These mark places where text gets replaces at runtime, so they should be carried over to the translation without changing their content. Some examples showing the strings to translate and the resulting strings where the tokens have been replaced: * ``Hello %s`` -> ``Hello Lou`` * ``The number %d`` -> ``The number 42`` * ``Hello %(name)s`` -> ``Hello Lou`` * ``Hello {name}`` -> ``Hello Lou`` * ``Hello {0}`` -> ``Hello Lou`` * ``Hello {0.name}`` -> ``Hello Lou`` * ``Hello {}`` -> ``Hello Lou`` In the case of ``Hello %(name)s``, a possible German translation and text displayed to the user would be ``Hallo %(name)s`` and ``Hallo Lou``. Plural-Forms ^^^^^^^^^^^^ The first thing you need is a Plural-Forms line for your language. The GNU gettext manual has a chapter on plural forms with examples for many languages. This should go after the "Content-Transfer-Encoding" line. The Plural-Forms line tells gettext how many plural forms there are in the language and how to use them. For example: :: msgid "artist" msgid_plural "artists" msgstr[0] "artist" msgstr[1] "artists" The English plural expression, "n != 1" means to use msgstr[0] if the count is 1, otherwise use msgstr[1]. If your language has 3 plural forms, you'll need msgstr[0], msgstr[1], and msgstr[2], and so on. Sometimes (usually, even) the English strings will be the same. For example, ``%d selected`` doesn't change whether it stands for *1 selected* or *99 selected*. If it does in your language, you should translate them differently. There are further difficulties for the many languages that have gender agreement and an unspecified noun in the phrase, but these are often translated with brackets (eg in French: *1 sélectionné(e)*, *99 sélectionné(e)s* perhaps) Fuzzy translations ^^^^^^^^^^^^^^^^^^ A translation marked *fuzzy* is (usually) one that has been matched to a similar previous translation, often by `gettext` itself. Note that fuzzy translations are not treated as accurate translations so will not be used. Common reasons for strings being marked as fuzzy include: * A contributor corrects a typo in the source (English) text * A developer changes the `Mnemonic Label <https://developer.gnome.org/gtk3/stable/GtkLabel.html#id-1.3.8.2.10.5>`_ - This is the underscore you see in many translation strings. * The English has changed, but not much * sometimes it *just happens*... For example:: #: ../quodlibet/browsers/albums.py:425 #, fuzzy msgid "Sort _by:" msgstr "Ordina per data" Here, in the Italian `.po` file, you can see this message has been matched, presumably used from a "Sort by date" translation previously entered. This explains why this string was missing in the Italian build. As a translator please make sure there are no translations left marked as fuzzy. In `poedit`, you can click the cloud (!) icon, or in a text editor you should simply remove the `fuzzy` string above the `msgid`. ��������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/translation/howto_manual.rst���������������������������������������������������0000664�0001750�0001750�00000003525�14231604507�020731� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������How-to (Legacy Manual Process) ============================== .. warning:: The new preferred method to translate is via `Weblate <https://hosted.weblate.org/engage/quodlibet>`__. The process described here still works and is supported in case you for some reason prefer it. Translation Software -------------------- To translate, you'll want to have gettext and git installed:: apt-get install gettext git For translating itself you need a PO editor like `Poedit <https://poedit.net/>`_:: apt-get install poedit Translation Process ------------------- Get the QL code:: $ git clone https://github.com/quodlibet/quodlibet.git $ cd quodlibet You can find the translation file for your chosen language in:: ./po/<lang>.po In case there's not already a translation for your language, create one:: $ ./setup.py create_po --lang=<mylang> Update translations so all new strings that were added since the last translation update get included:: $ ./setup.py update_po --lang=<mylang> Now start translating... :: $ poedit ./po/<lang>.po Test the translation by generating MO files and running Quod Libet and Ex Falso. build_mo will create a 'build' directory including the processed translations and if 'build' is present QL/EF will use these translations instead of the global ones. :: $ ./setup.py build_mo --lang=<mylang> $ ./quodlibet.py $ ./exfalso.py If your active system language is not the one you are translating, you can run them like:: $ LANGUAGE=<mylang> ./quodlibet.py Finally run our unit tests to make sure the translation will not cause programming errors. If it says something else, there's a problem with the translation. :: $ ./setup.py test --to-run PO.<mylang> And as a last step create a pull request with your changes: https://github.com/quodlibet/quodlibet/pulls���������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/docs/translation/index.rst����������������������������������������������������������0000664�0001750�0001750�00000002752�14231604332�017340� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Translation Guide ================= If you're fluent in a language other than English, and have some spare time, you can help us translate Quod Libet. Translation is a continuous process on an active projects like this - as developers add new features or modify existing text used, new translations will be needed. Of course, there might be mistakes in the English, too! Please let us know if you find them. Getting Started --------------- We use `Weblate <https://weblate.org>`__ for translations which means you need to: * Create an account on https://hosted.weblate.org * Visit https://hosted.weblate.org/engage/quodlibet and start translating * Any translation changes on Weblate will automatically be merged back into our code base after some time * Similarly any code changes that result in changed or new source strings will periodically be pushed to Weblate so you can start translating them. If you have any questions regarding the process see https://docs.weblate.org for Weblate related information, our :any:`FAQ <faq>`, or ask us on :any:`Discord <Contact>`. Although not recommended, you can also translate without Weblate on your local computer, see :any:`howto_manual` for more information. Current Translation Status -------------------------- .. image:: https://hosted.weblate.org/widgets/quodlibet/-/quodlibet/multi-auto.svg :alt: Translation status :target: https://hosted.weblate.org/engage/quodlibet/ .. toctree:: :titlesonly: :hidden: faq howto_manual ����������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/exfalso.py��������������������������������������������������������������������������0000775�0001750�0001750�00000000625�14035600052�014221� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env python3 # Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from quodlibet.exfalso import main if __name__ == "__main__": sys.exit(main()) �����������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9609354 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�013314� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/__init__.py�������������������������������������������������������������������0000664�0001750�0001750�00000017337�14231604332�015441� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Joe Wreschnig # 2012-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """distutils extensions for GTK+/GObject/Unix This module contains a Distribution subclass (GDistribution) which implements build and install commands for operations related to Python GTK+ and GObject support. This includes installation of man pages and gettext support. Also supports setuptools but needs to be imported after setuptools (which does some monkey patching) """ import sys from distutils.core import setup from .shortcuts import build_shortcuts, install_shortcuts from .man import install_man from .po import build_mo, install_mo, po_stats, update_po, \ create_po, create_pot, build_po from .icons import install_icons from .search_provider import install_search_provider from .dbus_services import build_dbus_services, install_dbus_services from .appdata import build_appdata, install_appdata from .coverage import coverage_cmd from .docs import build_sphinx from .scripts import build_scripts from .tests import quality_cmd, distcheck_cmd, test_cmd from .clean import clean from .bash_completions import install_bash_completions from .zsh_completions import install_zsh_completions from .util import get_dist_class, Distribution distutils_build = get_dist_class("build") class build(distutils_build): """Override the default build with new subcommands.""" sub_commands = distutils_build.sub_commands + [ ("build_mo", lambda self: self.distribution.has_po()), ("build_po", lambda self: self.distribution.has_po()), ("build_shortcuts", lambda self: self.distribution.has_shortcuts()), ("build_dbus_services", lambda self: self.distribution.has_dbus_services()), ("build_appdata", lambda self: self.distribution.has_appdata()), ] distutils_install = get_dist_class("install") class install(distutils_install): """Override the default install with new subcommands.""" user_options = distutils_install.user_options + [ ("mandir=", None, "destination directory for man pages. " "Defaults to $PREFIX/share/man"), ] sub_commands = distutils_install.sub_commands + [ ("install_shortcuts", lambda self: self.distribution.has_shortcuts()), ("install_man", lambda self: self.distribution.has_man_pages()), ("install_mo", lambda self: self.distribution.has_po()), ("install_icons", lambda self: self.distribution.need_icon_install()), ("install_search_provider", lambda self: self.distribution.need_search_provider()), ("install_dbus_services", lambda self: self.distribution.has_dbus_services()), ("install_appdata", lambda self: self.distribution.has_appdata()), ("install_bash_completions", lambda self: self.distribution.has_bash_completions()), ("install_zsh_completions", lambda self: self.distribution.has_zsh_completions()), ] def initialize_options(self): distutils_install.initialize_options(self) self.mandir = None is_osx = (sys.platform == "darwin") class GDistribution(Distribution): """A Distribution with support for GTK+-related options The GDistribution class adds a number of commads and parameters related to GTK+ and GObject Python programs and libraries. Parameters (to distutils.core.setup): po_directory -- directory where .po files are contained po_package -- package name for translation files shortcuts -- list of .desktop files to build/install dbus_services -- list of .service files to build/install man_pages -- list of man pages to install appdata -- list of appdata files to install Using the translation features requires gettext. Example: from distutils.core import setup from gdist import GDistribution setup(distclass=GDistribution, ...) """ shortcuts = [] appdata = [] dbus_services = [] po_directory = None man_pages = [] po_package = None search_provider = None coverage_options = {} bash_completions = [] zsh_completions = [] def __init__(self, *args, **kwargs): Distribution.__init__(self, *args, **kwargs) self.cmdclass.setdefault("build_po", build_po) self.cmdclass.setdefault("build_mo", build_mo) self.cmdclass.setdefault("build_shortcuts", build_shortcuts) self.cmdclass.setdefault("build_dbus_services", build_dbus_services) self.cmdclass.setdefault("build_appdata", build_appdata) self.cmdclass.setdefault("build_scripts", build_scripts) self.cmdclass.setdefault("install_icons", install_icons) self.cmdclass.setdefault("install_shortcuts", install_shortcuts) self.cmdclass.setdefault("install_dbus_services", install_dbus_services) self.cmdclass.setdefault("install_man", install_man) self.cmdclass.setdefault("install_mo", install_mo) self.cmdclass.setdefault("install_search_provider", install_search_provider) self.cmdclass.setdefault("install_appdata", install_appdata) self.cmdclass.setdefault( "install_bash_completions", install_bash_completions) self.cmdclass.setdefault( "install_zsh_completions", install_zsh_completions) self.cmdclass.setdefault("build", build) self.cmdclass.setdefault("install", install) self.cmdclass.setdefault("po_stats", po_stats) self.cmdclass.setdefault("update_po", update_po) self.cmdclass.setdefault("create_po", create_po) self.cmdclass.setdefault("create_pot", create_pot) self.cmdclass.setdefault("coverage", coverage_cmd) self.cmdclass.setdefault("build_sphinx", build_sphinx) self.cmdclass.setdefault("quality", quality_cmd) self.cmdclass.setdefault("distcheck", distcheck_cmd) self.cmdclass.setdefault("test", test_cmd) self.cmdclass.setdefault("quality", quality_cmd) self.cmdclass.setdefault("clean", clean) def has_po(self): return bool(self.po_directory) def has_shortcuts(self): return not is_osx and bool(self.shortcuts) def has_appdata(self): return not is_osx and bool(self.appdata) def has_man_pages(self): return bool(self.man_pages) def has_dbus_services(self): return not is_osx and bool(self.dbus_services) def has_bash_completions(self): return bool(self.bash_completions) def has_zsh_completions(self): return bool(self.zsh_completions) def need_icon_install(self): return not is_osx def need_search_provider(self): return not is_osx __all__ = ["GDistribution", "setup"] �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/appdata.py��������������������������������������������������������������������0000664�0001750�0001750�00000007670�14035600052�015310� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ AppData Specification: https://www.freedesktop.org/software/appstream/docs/ """ import os from distutils.dep_util import newer from .util import Command from .gettextutil import merge_file class build_appdata(Command): """Build .appdata.xml files Move .appdata.xml files to the appropriate location in the build tree. If there is a .appdata.xml.in file, process it with gettext. """ description = "build .appdata.xml files" user_options = [] def initialize_options(self): self.build_base = None self.appdata = None self.po_build_dir = None def finalize_options(self): self.appdata = self.distribution.appdata self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'build_po', ('po_build_dir', 'po_build_dir')) def run(self): self.run_command("build_po") basepath = os.path.join(self.build_base, 'share', 'appdata') self.mkpath(basepath) for appdata in self.appdata: if os.path.exists(appdata + ".in"): fullpath = os.path.join(basepath, os.path.basename(appdata)) if newer(appdata + ".in", fullpath): merge_file(self.po_build_dir, "xml", appdata + ".in", fullpath) else: self.copy_file(appdata, os.path.join(basepath, appdata)) class install_appdata(Command): """Install .appdata.xml files Install any .appdata.xml files from the build tree to their final location, under $prefix/share/appdata. """ description = "install .appdata.xml files" user_options = [] def initialize_options(self): self.install_dir = None self.skip_build = None self.appdata = None self.build_base = None self.outfiles = [] def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'install', ('install_data', 'install_dir'), ('skip_build', 'skip_build')) self.set_undefined_options( 'build_appdata', ('appdata', 'appdata')) def get_outputs(self): return self.outfiles def run(self): if not self.skip_build: self.run_command('build_appdata') basepath = os.path.join(self.install_dir, 'share', 'appdata') srcpath = os.path.join(self.build_base, 'share', 'appdata') out = self.mkpath(basepath) self.outfiles.extend(out or []) for appdata in self.appdata: appdata = os.path.basename(appdata) fullsrc = os.path.join(srcpath, appdata) fullpath = os.path.join(basepath, appdata) (out, _) = self.copy_file(fullsrc, fullpath) self.outfiles.append(out) __all__ = ["build_appdata", "install_appdata"] ������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/bash_completions.py�����������������������������������������������������������0000664�0001750�0001750�00000004055�14035600052�017221� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019 Arnaud Rebillout # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from .util import Command class install_bash_completions(Command): user_options = [] def initialize_options(self): self.install_dir = None self.bash_completions = [] self.outfiles = [] def finalize_options(self): self.set_undefined_options('install', ('install_data', 'install_dir')) self.bash_completions = self.distribution.bash_completions def get_outputs(self): return self.outfiles def run(self): # note that the basepath can also be obtained with pkgconfig: # $ pkg-config bash-completion --variable=completionsdir basepath = os.path.join( self.install_dir, 'share', 'bash-completion', 'completions') out = self.mkpath(basepath) self.outfiles.extend(out or []) for src, dest in self.bash_completions: (out, _) = self.copy_file(src, os.path.join(basepath, dest)) self.outfiles.append(out) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/clean.py����������������������������������������������������������������������0000664�0001750�0001750�00000006503�14035600052�014752� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Joe Wreschnig # 2012,2013,2015, 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """clean up output of 'build' commands""" import os import shutil from .util import get_dist_class distutils_clean = get_dist_class("clean") class clean(distutils_clean): """clean up output of 'build' commands GDistribution commands generate files that the normal distutils clean command doesn't. This removes them. """ description = "clean up output of 'build' commands" def initialize_options(self): distutils_clean.initialize_options(self) self.shortcuts = None self.po_package = None self.po_directory = None def finalize_options(self): distutils_clean.finalize_options(self) self.shortcuts = self.distribution.shortcuts self.po_package = self.distribution.po_package self.po_directory = self.distribution.po_directory def run(self): distutils_clean.run(self) if not self.all: return # gettext byproducts if self.po_directory and self.po_package: pot = os.path.join(self.po_directory, self.po_package + ".pot") try: os.unlink(pot) except OSError: pass # Python byproducts def should_remove(filename): if (filename.lower()[-4:] in [".pyc", ".pyo"] or filename.endswith("~") or (filename.startswith("#") and filename.endswith("#"))): return True else: return False for pathname, dirs, files in os.walk("."): for filename in filter(should_remove, files): try: os.unlink(os.path.join(pathname, filename)) except EnvironmentError as err: print(str(err)) # setup.py byproducts for base in ["coverage", "build", "dist"]: if os.path.isdir(base): shutil.rmtree(base) # docs for entry in os.listdir("docs"): path = os.path.join("docs", entry) if entry.startswith("_") and os.path.isdir(path): shutil.rmtree(path) try: os.remove("MANIFEST") except EnvironmentError: pass __all__ = ["clean"] ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/coverage.py�������������������������������������������������������������������0000664�0001750�0001750�00000005764�14035600052�015473� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import absolute_import import os import sys from urllib.request import pathname2url from .util import Command class coverage_cmd(Command): description = "generate test coverage data" user_options = [ ("to-run=", None, "list of tests to run (default all)"), ] def initialize_options(self): self.to_run = [] def finalize_options(self): self.options = self.distribution.coverage_options self.packages = self.distribution.packages include = set([p.split(".", 1)[0] + "*" for p in self.packages]) self.options.setdefault("include", include) self.options.setdefault("directory", "coverage") def run(self): # Wipe existing modules, to make sure coverage data is properly # generated for them. for key in sys.modules.keys(): for package in self.packages: if key == package or key.startswith(package + "."): del sys.modules[key] break try: from coverage import coverage, CoverageException except ImportError: print("Missing 'coverage' module. See " "https://pypi.python.org/pypi/coverage or try " "`apt-get install python-coverage`") return cov = coverage() cov.start() cmd = self.reinitialize_command("test") cmd.to_run = self.to_run[:] cmd.ensure_finalized() cmd.run() cov.stop() try: cov.html_report(**self.options) except CoverageException as e: # this fails in case js libs are missing, but the html is still # there, so don't fail completely print(e) dest = os.path.abspath(self.options["directory"]) index = os.path.join(dest, "index.html") index_url = pathname2url(index) print("Coverage summary: file://%s" % index_url) ������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/dbus_services.py��������������������������������������������������������������0000664�0001750�0001750�00000007764�14035600052�016542� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from .util import Command class build_dbus_services(Command): """Build .service files""" description = "build .service files" user_options = [] def initialize_options(self): self.build_base = None self.dbus_services = None def finalize_options(self): self.dbus_services = self.distribution.dbus_services self.set_undefined_options('build', ('build_base', 'build_base')) def run(self): basepath = os.path.join(self.build_base, 'share', 'dbus-1', 'services') self.mkpath(basepath) for service in self.dbus_services: in_variant = service + ".in" target_path = os.path.join(basepath, os.path.basename(service)) if os.path.exists(in_variant): # the exec line needs the install path, so we can't really # do anything here besides renaming self.copy_file(in_variant, target_path) else: self.copy_file(service, target_path) def _replace(path, pattern, subst): with open(path, "rb") as hi: data = hi.read() with open(path, "wb") as ho: ho.write(data.replace(pattern, subst)) class install_dbus_services(Command): """Install .service files""" description = "install .service files" user_options = [] def initialize_options(self): self.install_dir = None self.exec_prefix = None self.skip_build = None self.dbus_services = None self.build_base = None self.outfiles = [] def finalize_options(self): self.set_undefined_options( 'build', ('build_base', 'build_base')) self.set_undefined_options( 'install', ('install_data', 'install_dir'), ('exec_prefix', 'exec_prefix'), ('skip_build', 'skip_build')) self.set_undefined_options( 'build_dbus_services', ('dbus_services', 'dbus_services')) def get_outputs(self): return self.outfiles def run(self): if not self.skip_build: self.run_command('build_dbus_services') basepath = os.path.join( self.install_dir, 'share', 'dbus-1', 'services') out = self.mkpath(basepath) self.outfiles.extend(out or []) srcpath = os.path.join(self.build_base, 'share', 'dbus-1', 'services') for service in self.dbus_services: service_name = os.path.basename(service) fullsrc = os.path.join(srcpath, service_name) fullpath = os.path.join(basepath, service_name) (out, _) = self.copy_file(fullsrc, fullpath) self.outfiles.append(out) prefix = self.exec_prefix or "" if not isinstance(prefix, bytes): prefix = prefix.encode("utf-8") _replace(fullpath, b"@PREFIX@", prefix) __all__ = ["build_dbus_services", "install_dbus_services"] ������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/docs.py�����������������������������������������������������������������������0000664�0001750�0001750�00000003644�14231604332�014626� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import sys from .util import Command class build_sphinx(Command): description = "build sphinx documentation" user_options = [ ("build-dir=", "d", "build directory"), ("all", "a", "build all docs, not just the user guide"), ] def initialize_options(self): self.build_dir = None self.all = False def finalize_options(self): self.build_dir = self.build_dir or "build" self.all = bool(self.all) def run(self): DOCS_ROOT = "docs" GUIDE_ROOT = os.path.join(DOCS_ROOT, "guide") TARGET = os.path.join(self.build_dir, "sphinx") srcdir = GUIDE_ROOT if not self.all else DOCS_ROOT self.spawn([sys.executable, "-m", "sphinx", "-j", "auto", "-b", "html", "-c", DOCS_ROOT, "-n", "-E", srcdir, TARGET]) ��������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/gettextutil.py����������������������������������������������������������������0000664�0001750�0001750�00000031766�14231604332�016266� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015-2017 Christoph Reiter # 2019-21 Nick Boultbee # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import subprocess import contextlib import fnmatch import tempfile import shutil import functools import warnings from pathlib import Path from typing import List, Optional, Tuple, Iterable, Dict QL_SRC_DIR = "quodlibet" XGETTEXT_CONFIG: Dict[str, Tuple[str, List[str]]] = { "*.py": ("Python", [ "", "_", "N_", "C_:1c,2", "NC_:1c,2", "Q_", "pgettext:1c,2", "npgettext:1c,2,3", "numeric_phrase:1,2", "dgettext:2", "ngettext:1,2", "dngettext:2,3", ]), "*.appdata.xml": ("", []), "*.desktop": ("Desktop", [ "", "Name", "GenericName", "Comment", "Keywords"]), } """Dict of pattern -> (language, [keywords])""" class GettextError(Exception): pass class GettextWarning(Warning): pass def _read_potfiles(src_root: Path, potfiles: Path) -> List[Path]: """Returns a list of paths for a POTFILES.in file""" paths = [] with open(potfiles, "r", encoding="utf-8") as h: for line in h: line = line.strip() if not line or line.startswith("#"): continue paths.append((src_root / line).resolve()) return paths def _write_potfiles(src_root: Path, potfiles: Path, paths: Iterable[Path]): assert src_root.is_absolute() with open(potfiles, "w", encoding="utf-8") as h: for path in paths: assert path.is_absolute() path = path.relative_to(src_root) h.write(str(path) + "\n") def _src_root(po_dir: Path) -> Path: assert isinstance(po_dir, Path) return po_dir.parent.resolve() def get_pot_dependencies(po_dir: Path) -> List[Path]: """Returns a list of paths that are used as input for the .pot file""" src_root = _src_root(po_dir) potfiles_path = po_dir / "POTFILES.in" return _read_potfiles(src_root, potfiles_path) def _get_pattern(path: Path) -> Optional[str]: for pattern in XGETTEXT_CONFIG: match_part = path.name if match_part.endswith(".in"): match_part = match_part.rsplit(".", 1)[0] if fnmatch.fnmatch(match_part, pattern): return pattern return None def _create_pot(potfiles_path: Path, src_root: Path) -> Path: """Create a POT file for the specified POs and source code :returns: the output path """ potfiles = _read_potfiles(src_root, potfiles_path) groups = {} for path in potfiles: pattern = _get_pattern(path) if pattern is not None: groups.setdefault(pattern, []).append(path) else: raise ValueError(f"Unknown filetype: {path!s}") specs = [] for pattern, paths in groups.items(): language, keywords = XGETTEXT_CONFIG[pattern] specs.append((language, keywords, paths)) # no language last, otherwise we get charset errors specs.sort(reverse=True) fd, out_path = tempfile.mkstemp(".pot") out_path = Path(out_path) try: os.close(fd) for language, keywords, paths in specs: args = [] if language: args.append("--language=" + language) for kw in keywords: if kw: args.append("--keyword=" + kw) else: args.append("-k") fd, potfiles_in = tempfile.mkstemp() potfiles_in = Path(potfiles_in) try: os.close(fd) _write_potfiles(src_root, potfiles_in, paths) args = ["xgettext", "--from-code=utf-8", "--add-comments", "--files-from=" + str(potfiles_in), "--directory=" + str(src_root), "--output=" + str(out_path), "--force-po", "--join-existing"] + args p = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) stdout, stderr = p.communicate() if p.returncode != 0: path_strs = ", ".join(str(p) for p in paths) msg = f"Error running `{' '.join(args)}`:\nPaths: {path_strs}...\n" msg += stderr or ("Got error: %d" % p.returncode) raise GettextError(msg) if stderr: warnings.warn(stderr, GettextWarning) finally: potfiles_in.unlink() except Exception: out_path.unlink() raise return out_path @contextlib.contextmanager def create_pot(po_path: Path): """Temporarily creates a .pot file in a temp directory.""" src_root = _src_root(po_path) potfiles_path = po_path / "POTFILES.in" pot_path = _create_pot(potfiles_path, src_root) try: yield pot_path finally: os.unlink(pot_path) def update_linguas(po_path: Path) -> None: """Create a LINGUAS file in po_dir""" linguas = po_path / "LINGUAS" with open(linguas, "w", encoding="utf-8") as h: for l in list_languages(po_path): h.write(l + "\n") def list_languages(po_path: Path) -> List[str]: """Returns a list of available language codes""" po_files = po_path.glob("*.po") return sorted([os.path.basename(str(po)[:-3]) for po in po_files]) def compile_po(po_path: Path, target_file: Path): """Creates an .mo from a .po""" try: subprocess.check_output( ["msgfmt", "-o", str(target_file), str(po_path)], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) def po_stats(po_path: Path): """Returns a string containing translation statistics""" try: return subprocess.check_output( ["msgfmt", "--statistics", str(po_path), "-o", os.devnull], universal_newlines=True, stderr=subprocess.STDOUT).strip() except subprocess.CalledProcessError as e: raise GettextError(e.output) def merge_file(po_dir, file_type, source_file, target_file): """Using a template input create a new file including translations""" if file_type not in ("xml", "desktop"): raise ValueError style = "--" + file_type linguas = os.path.join(po_dir, "LINGUAS") if not os.path.exists(linguas): raise GettextError("{!r} doesn't exist".format(linguas)) try: subprocess.check_output( ["msgfmt", style, "--template", source_file, "-d", po_dir, "-o", target_file], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) def get_po_path(po_path: Path, lang_code: str) -> Path: """The default path to the .po file for a given language code""" return po_path / (lang_code + ".po") def update_po(pot_path: Path, po_path: Path, out_path: Optional[Path] = None) -> None: """Update .po at po_path based on .pot at po_path. If out_path is given will not touch po_path and write to out_path instead. Raises GettextError on error. """ if out_path is None: out_path = po_path try: subprocess.check_output( ["msgmerge", "-o", str(out_path), str(po_path), str(pot_path)], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) def check_po(po_path: Path, ignore_header=False): """Makes sure the .po is well formed Raises GettextError if not """ check_arg = "--check" if not ignore_header else "--check-format" try: subprocess.check_output( ["msgfmt", check_arg, "--check-domain", str(po_path), "-o", os.devnull], stderr=subprocess.STDOUT, universal_newlines=True) except subprocess.CalledProcessError as e: raise GettextError(e.output) def check_pot(pot_path: Path) -> None: """Makes sure that the .pot is well formed Raises GettextError if not """ # msgfmt doesn't like .pot files, but we can create a dummy .po # and test that instead. fd, po_path = tempfile.mkstemp(".po") po_path = Path(po_path) os.close(fd) po_path.unlink() create_po(pot_path, po_path) try: check_po(po_path, ignore_header=True) finally: os.remove(po_path) def create_po(pot_path: Path, po_path: Path) -> None: """Create a new <po_path> file based on <pot_path> :raises GettextError: in case something went wrong or the file already exists. """ if po_path.exists(): raise GettextError(f"{po_path!s} already exists") if not pot_path.exists(): raise GettextError(f"{pot_path!s} missing") try: subprocess.check_output( ["msginit", "--no-translator", "-i", str(pot_path), "-o", str(po_path)], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) if not po_path.exists(): raise GettextError(f"something went wrong; {po_path!s} didn't get created") update_po(pot_path, po_path) def get_missing(po_dir: Path) -> Iterable[str]: """Gets missing strings :returns: a list of file information for translatable strings found in files not listed in POTFILES.in and not skipped in POTFILES.skip. """ src_root = _src_root(po_dir) potfiles_path = po_dir / "POTFILES.in" skip_path = po_dir / "POTFILES.skip" # Generate a set of paths of files which are not marked translatable # and not skipped pot_files = {p.relative_to(src_root) for p in _read_potfiles(src_root, potfiles_path)} skip_files = {p.relative_to(src_root) for p in _read_potfiles(src_root, skip_path)} not_translatable = set() for root, dirs, files in os.walk(src_root): root = Path(root) for dirname in dirs: dirpath = (root / dirname).relative_to(src_root) if dirpath in skip_files or dirname.startswith("."): dirs.remove(dirname) for name in files: path = (root / name).relative_to(src_root) if path not in pot_files and path not in skip_files: not_translatable.add(path) # Filter out any unknown filetypes not_translatable = [p for p in not_translatable if _get_pattern(p) is not None] not_translatable = [src_root / p for p in not_translatable] # Filter out any files not containing translations fd, temp_path = tempfile.mkstemp("POTFILES.in") temp_path = Path(temp_path) try: os.close(fd) _write_potfiles(src_root, temp_path, not_translatable) pot_path = _create_pot(temp_path, src_root) try: infos = set() with open(pot_path, "r", encoding="utf-8") as h: for line in h.readlines(): if not line.startswith("#:"): continue infos.update(line.split()[1:]) return sorted(infos) finally: pot_path.unlink() finally: temp_path.unlink() def _get_xgettext_version() -> Tuple: """:returns: a version tuple e.g. (0, 19, 3) or GettextError""" try: result = subprocess.check_output(["xgettext", "--version"]) except subprocess.CalledProcessError as e: raise GettextError(e) try: return tuple(map(int, result.splitlines()[0].split()[-1].split(b"."))) except (IndexError, ValueError) as e: raise GettextError(e) @functools.lru_cache(None) def check_version() -> None: """Check Gettext version. :raises GettextError: (with message) if required gettext programs are missing """ required_programs = ["xgettext", "msgmerge", "msgfmt"] for prog in required_programs: if shutil.which(prog) is None: raise GettextError("{} missing".format(prog)) if _get_xgettext_version() < (0, 19, 8): raise GettextError("xgettext too old, need 0.19.8+") ����������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/icons.py����������������������������������������������������������������������0000664�0001750�0001750�00000005516�14035600052�015006� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import subprocess from .util import Command def update_icon_cache(*args): args = list(args) try: subprocess.check_call( ['gtk-update-icon-cache-3.0'] + args) except OSError: try: subprocess.check_call( ['gtk-update-icon-cache'] + args) except OSError: return False except subprocess.CalledProcessError: return False except subprocess.CalledProcessError: return False return True class install_icons(Command): """Copy app icons to hicolor/pixmaps and update the global cache""" user_options = [] def initialize_options(self): self.install_dir = None self.outfiles = [] def finalize_options(self): self.set_undefined_options('install', ('install_data', 'install_dir')) def get_outputs(self): return self.outfiles def run(self): # install into hicolor icon theme basepath = os.path.join(self.install_dir, 'share', 'icons', 'hicolor') local = os.path.join("quodlibet", "images", "hicolor") # copy all "apps" images for entry in os.listdir(local): source = os.path.join(local, entry, "apps") dest = os.path.join(basepath, entry, "apps") out = self.mkpath(dest) self.outfiles.extend(out or []) for image in os.listdir(source): if os.path.splitext(image)[-1] in (".png", ".svg"): file_path = os.path.join(source, image) (out, _) = self.copy_file(file_path, dest) self.outfiles.append(out) # this fails during packaging.. so ignore the outcome update_icon_cache(basepath) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/man.py������������������������������������������������������������������������0000664�0001750�0001750�00000005206�14035600052�014442� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007-2008 Joe Wreschnig # 2009,2012-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """install man pages Commands to install Unix man pages. """ import os from .util import Command class install_man(Command): """install man pages Install man pages into $prefix/share/man/manN or into $mandir/manN by using setup.py install --mandir=$mandir """ description = "install man pages" user_options = [] def initialize_options(self): self.man_pages = None self.mandir = None self.install_dir = None self.outfiles = [] def finalize_options(self): self.set_undefined_options( 'install', ('install_data', 'install_dir'), ('mandir', 'mandir'), ) if self.mandir is None: self.mandir = os.path.join(self.install_dir, 'share', 'man') self.man_pages = self.distribution.man_pages for man_page in self.man_pages: if not man_page[-1].isdigit(): raise SystemExit("%r has no section" % man_page) def get_outputs(self): return self.outfiles def run(self): basepath = self.mandir out = self.mkpath(basepath) self.outfiles.extend(out or []) for man_page in self.man_pages: manpath = os.path.join(basepath, "man" + man_page[-1]) out = self.mkpath(manpath) self.outfiles.extend(out or []) fullpath = os.path.join(manpath, os.path.basename(man_page)) (out, _) = self.copy_file(man_page, fullpath) self.outfiles.append(out) __all__ = ["install_man"] ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/po.py�������������������������������������������������������������������������0000664�0001750�0001750�00000023052�14231604332�014307� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Joe Wreschnig # 2009-2010,2012-2016 Christoph Reiter # 2021 Nick Boultbee # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """translation support This module contains commands to support building and installing gettext message catalogs. """ import os import shutil from pathlib import Path from tempfile import mkstemp from distutils.errors import DistutilsOptionError from distutils.dep_util import newer_group, newer from typing import Optional from .util import Command from . import gettextutil class po_stats(Command): description = "Show translation statistics" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): po_directory = Path(self.distribution.po_directory) with gettextutil.create_pot(po_directory) as pot_path: res = [] for language in gettextutil.list_languages(po_directory): fd, temp_path = mkstemp(".po") temp_path = Path(temp_path) try: os.close(fd) po_path = gettextutil.get_po_path(po_directory, language) gettextutil.update_po(pot_path, po_path, temp_path) output = gettextutil.po_stats(temp_path) res.append((language, output)) finally: temp_path.unlink() stats = [] for po, r in res: nums = [int(p.split()[0]) for p in r.split(",")] while len(nums) < 3: nums.append(0) trans, fuzzy, untrans = nums stats.append((po, trans, fuzzy, untrans)) stats.sort(key=lambda x: x[1], reverse=True) print("#" * 30) for po, trans, fuzzy, untrans in stats: all_ = float(trans + fuzzy + untrans) / 100 print("%5s: %3d%% (+%2d%% fuzzy)" % (po, trans / all_, fuzzy / all_)) class update_po(Command): description = "update po files" user_options = [ ("lang=", None, "force update <lang>.po"), ] def initialize_options(self): self.lang = None def finalize_options(self): pass def run(self): try: gettextutil.check_version() except gettextutil.GettextError as e: raise SystemExit(e) po_directory = Path(self.distribution.po_directory) langs = gettextutil.list_languages(po_directory) if self.lang is not None: if self.lang not in langs: raise SystemExit(f"Error: {self.lang} not found") else: langs = [self.lang] with gettextutil.create_pot(po_directory) as pot_path: for lang in langs: po_path = gettextutil.get_po_path(po_directory, lang) gettextutil.update_po(pot_path, po_path) class create_po(Command): description = "create a new po file" user_options = [ ("lang=", None, "create <lang>.po"), ] def initialize_options(self): self.lang = None def finalize_options(self): if not self.lang: raise DistutilsOptionError("no --lang= given") def run(self): try: gettextutil.check_version() except gettextutil.GettextError as e: raise SystemExit(e) po_directory = Path(self.distribution.po_directory) po_path = gettextutil.get_po_path(po_directory, self.lang) with gettextutil.create_pot(po_directory) as pot_path: gettextutil.create_po(pot_path, po_path) print(f"Created {po_path.absolute()}") class create_pot(Command): description = "create a new pot file" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): try: gettextutil.check_version() except gettextutil.GettextError as e: raise SystemExit(e) po_package = self.distribution.po_package po_directory = Path(self.distribution.po_directory) with gettextutil.create_pot(po_directory) as pot_path: dest = po_directory / f"{po_package}.pot" shutil.copy(pot_path, dest) strip_pot_date(dest) print(f"Created {dest.absolute()}") def strip_pot_date(path): """strip POT-Creation-Date from po/pot""" done = False lines = [] for line in open(path, "rb"): if not done and line.startswith(b'"POT-Creation-Date:'): done = True continue lines.append(line) with open(path, "wb") as h: h.write(b"".join(lines)) class build_po(Command): description = "update and copy .po files to the build dir" user_options = [] def initialize_options(self): self.build_base: Optional[str] = None self.po_build_dir: Optional[Path] = None def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.po_build_dir = Path(self.build_base) / '_po_build' def run(self): po_directory = Path(self.distribution.po_directory) langs = gettextutil.list_languages(po_directory) pot_deps = gettextutil.get_pot_dependencies(po_directory) to_build = [] for language in langs: po_path = gettextutil.get_po_path(po_directory, language) out_path = gettextutil.get_po_path(self.po_build_dir, language) if newer_group([str(p) for p in pot_deps + [po_path]], str(out_path)): to_build.append((po_path, out_path)) if not to_build: return self.mkpath(str(self.po_build_dir)) with gettextutil.create_pot(po_directory) as pot_path: for po_path, out_path in to_build: gettextutil.update_po(pot_path, po_path, out_path) # strip POT-Creation-Date from po/mo to make build # reproducible strip_pot_date(out_path) gettextutil.update_linguas(self.po_build_dir) class build_mo(Command): """build message catalog files Build message catalog (.mo) files from .po files using gettext. These are placed directly in the build tree. """ description = "build message catalog files" user_options = [ ("lang=", None, "build mo for <lang>"), ] def initialize_options(self): self.build_base: Optional[str] = None self.lang = None self.po_build_dir: Optional[str] = None def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'build_po', ('po_build_dir', 'po_build_dir')) def run(self): self.run_command("build_po") po_package = self.distribution.po_package po_build_path = self.po_build_dir and Path(self.po_build_dir) langs = gettextutil.list_languages(po_build_path) if self.lang is not None: if self.lang not in langs: raise SystemExit("Error: %r not found" % self.lang) else: langs = [self.lang] basepath = Path(self.build_base) / "share" / "locale" for language in langs: fullpath = basepath / language / "LC_MESSAGES" destpath = fullpath / f"{po_package}.mo" self.mkpath(str(fullpath)) po_path = gettextutil.get_po_path(po_build_path, language) if newer(str(po_path), str(destpath)): gettextutil.compile_po(po_path, destpath) class install_mo(Command): """install message catalog files Copy compiled message catalog files into their installation directory, $prefix/share/locale/$lang/LC_MESSAGES/$package.mo. """ description = "install message catalog files" user_options = [] def initialize_options(self): self.skip_build = None self.build_base = None self.install_dir = None self.outfiles = [] def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'install', ('install_data', 'install_dir'), ('skip_build', 'skip_build')) def get_outputs(self): return self.outfiles def run(self): if not self.skip_build: self.run_command('build_mo') src = os.path.join(self.build_base, "share", "locale") dest = os.path.join(self.install_dir, "share", "locale") out = self.copy_tree(src, dest) self.outfiles.extend(out) __all__ = ["build_mo", "install_mo", "po_stats", "update_po"] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/scripts.py��������������������������������������������������������������������0000664�0001750�0001750�00000003241�14035600052�015353� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Joe Wreschnig # 2015-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from .util import get_dist_class du_build_scripts = get_dist_class("build_scripts") class build_scripts(du_build_scripts): description = "copy scripts to build directory" def run(self): du_build_scripts.run(self) # remove ".py" for script in self.scripts: outfile = os.path.join(self.build_dir, os.path.basename(script)) new = os.path.splitext(outfile)[0] try: os.unlink(new) except OSError: pass self.move_file(outfile, new) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/search_provider.py������������������������������������������������������������0000664�0001750�0001750�00000003560�14035600052�017047� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from .util import Command class install_search_provider(Command): user_options = [] def initialize_options(self): self.install_dir = None self.search_provider = None self.outfiles = [] def finalize_options(self): self.set_undefined_options('install', ('install_data', 'install_dir')) self.search_provider = self.distribution.search_provider def get_outputs(self): return self.outfiles def run(self): basepath = os.path.join( self.install_dir, 'share', 'gnome-shell', 'search-providers') out = self.mkpath(basepath) self.outfiles.extend(out or []) (out, _) = self.copy_file(self.search_provider, basepath) self.outfiles.append(out) ������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/shortcuts.py������������������������������������������������������������������0000664�0001750�0001750�00000007656�14035600052�015740� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007-2008 Joe Wreschnig # 2009,2012-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from distutils.dep_util import newer from .util import Command from .gettextutil import merge_file class build_shortcuts(Command): """Build .desktop files Move .desktop files to the appropriate location in the build tree. If there is a .desktop.in file, process it with gettext. """ description = "build .desktop files" user_options = [] def initialize_options(self): self.build_base = None self.shortcuts = None self.po_build_dir = None def finalize_options(self): self.shortcuts = self.distribution.shortcuts self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'build_po', ('po_build_dir', 'po_build_dir')) def run(self): self.run_command("build_po") basepath = os.path.join(self.build_base, 'share', 'applications') self.mkpath(basepath) for shortcut in self.shortcuts: if os.path.exists(shortcut + ".in"): fullpath = os.path.join(basepath, os.path.basename(shortcut)) if newer(shortcut + ".in", fullpath): merge_file(self.po_build_dir, "desktop", shortcut + ".in", fullpath) else: self.copy_file(shortcut, os.path.join(basepath, shortcut)) class install_shortcuts(Command): """Install .desktop files Install any .desktop files from the build tree to their final location, under $prefix/share/applications. """ description = "install .desktop files" user_options = [] def initialize_options(self): self.install_dir = None self.skip_build = None self.shortcuts = None self.build_base = None self.outfiles = [] def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.set_undefined_options( 'install', ('install_data', 'install_dir'), ('skip_build', 'skip_build')) self.set_undefined_options( 'build_shortcuts', ('shortcuts', 'shortcuts')) def get_outputs(self): return self.outfiles def run(self): if not self.skip_build: self.run_command('build_shortcuts') basepath = os.path.join(self.install_dir, 'share', 'applications') srcpath = os.path.join(self.build_base, 'share', 'applications') out = self.mkpath(basepath) self.outfiles.extend(out or []) for shortcut in self.shortcuts: shortcut = os.path.basename(shortcut) fullsrc = os.path.join(srcpath, shortcut) fullpath = os.path.join(basepath, shortcut) (out, _) = self.copy_file(fullsrc, fullpath) self.outfiles.append(out) __all__ = ["build_shortcuts", "install_shortcuts"] ����������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/tests.py����������������������������������������������������������������������0000664�0001750�0001750�00000013023�14231604332�015030� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014-2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import absolute_import import os import sys import subprocess import tarfile import fnmatch from distutils import dir_util from .util import Command, get_dist_class class test_cmd(Command): description = "run automated tests" user_options = [ ("to-run=", None, "list of tests to run (default all)"), ("suite=", None, "test suite (folder) to run (default 'tests')"), ("strict", None, "make glib warnings / errors fatal"), ("all", None, "run all suites"), ("exitfirst", "x", "stop after first failing test"), ("no-network", "n", "skip tests requiring a network connection"), ("no-quality", "n", "skip tests for code quality"), ] def initialize_options(self): self.to_run = [] self.suite = None self.strict = False self.all = False self.exitfirst = False self.no_network = False self.no_quality = False def finalize_options(self): if self.to_run: self.to_run = self.to_run.split(",") self.strict = bool(self.strict) self.all = bool(self.all) self.suite = self.suite and str(self.suite) self.exitfirst = bool(self.exitfirst) self.no_network = bool(self.no_network) self.no_quality = bool(self.no_quality) def run(self): import tests suite = self.suite if self.all: suite = None status = tests.unit(run=self.to_run, suite=suite, strict=self.strict, exitfirst=self.exitfirst, network=(not self.no_network or self.all), quality=(not self.no_quality or self.all)) if status != 0: raise SystemExit(status) class quality_cmd(Command): description = "Run flake8/mypy tests" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): import tests status = tests.unit(suite="quality", quality=True) if status != 0: raise SystemExit(status) sdist = get_dist_class("sdist") class distcheck_cmd(sdist): description = "run tests on a fresh sdist" def _check_manifest(self): assert self.get_archive_files() # make sure MANIFEST.in includes all tracked files if subprocess.call(["git", "status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: # contains the packaged files after run() is finished included_files = self.filelist.files assert included_files process = subprocess.Popen( ["git", "ls-tree", "-r", "HEAD", "--name-only"], stdout=subprocess.PIPE, universal_newlines=True) out, err = process.communicate() assert process.returncode == 0 tracked_files = out.splitlines() ignore_tracked = [ "dev-utils/*", ".github/*", ".ci/*", ".codecov.yml", ".editorconfig", ".git*", ] tracked_files = [ p for p in tracked_files if not any(fnmatch.fnmatch(p, i) for i in ignore_tracked)] diff = set(tracked_files) - set(included_files) assert not diff, ( "Not all tracked files included in tarball, check MANIFEST.in", diff) def _check_dist(self): assert self.get_archive_files() distcheck_dir = os.path.join(self.dist_dir, "distcheck") if os.path.exists(distcheck_dir): dir_util.remove_tree(distcheck_dir) self.mkpath(distcheck_dir) archive = self.get_archive_files()[0] tfile = tarfile.open(archive, "r:gz") tfile.extractall(distcheck_dir) tfile.close() name = self.distribution.get_fullname() extract_dir = os.path.join(distcheck_dir, name) old_pwd = os.getcwd() os.chdir(extract_dir) self.spawn([sys.executable, "setup.py", "test"]) self.spawn([sys.executable, "setup.py", "build"]) self.spawn([sys.executable, "setup.py", "build_sphinx"]) self.spawn([sys.executable, "setup.py", "install", "--root", "../prefix", "--record", "../log.txt"]) os.chdir(old_pwd) def run(self): sdist.run(self) self._check_manifest() self._check_dist() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/util.py�����������������������������������������������������������������������0000664�0001750�0001750�00000002510�14035600052�014637� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from distutils.core import Distribution from distutils.core import Command def get_dist_class(name): # in case of setuptools this returns the extended commands return Distribution({}).get_command_class(name) Distribution, Command, get_dist_class ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/gdist/zsh_completions.py������������������������������������������������������������0000664�0001750�0001750�00000003631�14035600052�017107� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os from .util import Command class install_zsh_completions(Command): user_options = [] def initialize_options(self): self.install_dir = None self.zsh_completions = [] self.outfiles = [] def finalize_options(self): self.set_undefined_options('install', ('install_data', 'install_dir')) self.zsh_completions = self.distribution.zsh_completions def get_outputs(self): return self.outfiles def run(self): basepath = os.path.join( self.install_dir, 'share', 'zsh', 'site-functions') out = self.mkpath(basepath) self.outfiles.extend(out or []) for src, dest in self.zsh_completions: (out, _) = self.copy_file(src, os.path.join(basepath, dest)) self.outfiles.append(out) �������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/operon.py���������������������������������������������������������������������������0000775�0001750�0001750�00000000631�14035600052�014057� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env python3 # Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from quodlibet.operon import main if __name__ == "__main__": sys.exit(main()) �������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.974269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/���������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�012620� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1676832588.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/POTFILES.in����������������������������������������������������������������������0000644�0001750�0001750�00000017056�14374467514�014426� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������data/io.github.quodlibet.ExFalso.appdata.xml.in data/io.github.quodlibet.ExFalso.desktop.in data/io.github.quodlibet.QuodLibet.appdata.xml.in data/io.github.quodlibet.QuodLibet.desktop.in quodlibet/browsers/albums/main.py quodlibet/browsers/albums/prefs.py quodlibet/browsers/_base.py quodlibet/browsers/collection/main.py quodlibet/browsers/collection/models.py quodlibet/browsers/collection/prefs.py quodlibet/browsers/covergrid/main.py quodlibet/browsers/covergrid/models.py quodlibet/browsers/covergrid/prefs.py quodlibet/browsers/filesystem.py quodlibet/browsers/__init__.py quodlibet/browsers/iradio.py quodlibet/browsers/paned/main.py quodlibet/browsers/paned/models.py quodlibet/browsers/paned/prefs.py quodlibet/browsers/playlists/main.py quodlibet/browsers/playlists/menu.py quodlibet/browsers/playlists/prefs.py quodlibet/browsers/playlists/util.py quodlibet/browsers/podcasts.py quodlibet/browsers/tracks.py quodlibet/browsers/soundcloud/library.py quodlibet/browsers/soundcloud/main.py quodlibet/browsers/soundcloud/util.py quodlibet/cli.py quodlibet/errorreport/ui.py quodlibet/exfalso.py quodlibet/ext/covers/artwork_url.py quodlibet/ext/covers/discogs.py quodlibet/ext/covers/lastfm.py quodlibet/ext/covers/musicbrainz.py quodlibet/ext/editing/iconv.py quodlibet/ext/editing/kakasi.py quodlibet/ext/editing/resub.py quodlibet/ext/editing/titlecase.py quodlibet/ext/events/advanced_preferences.py quodlibet/ext/events/animosd/main.py quodlibet/ext/events/animosd/prefs.py quodlibet/ext/events/appinfo.py quodlibet/ext/events/auto_update_tags_in_files.py quodlibet/ext/events/automask.py quodlibet/ext/events/autorating.py quodlibet/ext/events/bansheeimport.py quodlibet/ext/events/clock.py quodlibet/ext/events/discord_status.py quodlibet/ext/events/equalizer.py quodlibet/ext/events/gajim_status.py quodlibet/ext/events/headphonemon.py quodlibet/ext/events/inhibit.py quodlibet/ext/events/iradiolog.py quodlibet/ext/events/jep118.py quodlibet/ext/events/language.py quodlibet/ext/events/mediaserver.py quodlibet/ext/events/mpdserver/__init__.py quodlibet/ext/events/mpris/__init__.py quodlibet/ext/events/mqtt.py quodlibet/ext/events/musicbrainzsync.py quodlibet/ext/events/notify.py quodlibet/ext/events/notify_bookmarks.py quodlibet/ext/events/qlscrobbler.py quodlibet/ext/events/radioadmute.py quodlibet/ext/events/randomalbum.py quodlibet/ext/events/rbimport.py quodlibet/ext/events/screensaver.py quodlibet/ext/events/searchprovider.py quodlibet/ext/events/seekbar.py quodlibet/ext/events/seekpoints.py quodlibet/ext/events/squeezebox_sync.py quodlibet/ext/events/stop_on_pause.py quodlibet/ext/events/synchronize_to_device.py quodlibet/ext/events/synchronizedlyrics.py quodlibet/ext/events/telepathy_status.py quodlibet/ext/events/themeswitcher.py quodlibet/ext/events/thumbrating.py quodlibet/ext/events/toggle_menu.py quodlibet/ext/events/trayicon/appindicator.py quodlibet/ext/events/trayicon/__init__.py quodlibet/ext/events/trayicon/menu.py quodlibet/ext/events/trayicon/prefs.py quodlibet/ext/events/trayicon/systemtray.py quodlibet/ext/events/viewlyrics.py quodlibet/ext/events/visualisations.py quodlibet/ext/events/waveformseekbar.py quodlibet/ext/events/write_cover.py quodlibet/ext/gstreamer/compressor.py quodlibet/ext/gstreamer/crossfeed.py quodlibet/ext/gstreamer/karaoke.py quodlibet/ext/gstreamer/mono.py quodlibet/ext/gstreamer/pitch.py quodlibet/ext/playlist/export_to_folder.py quodlibet/ext/playlist/export_to_sonos.py quodlibet/ext/playlist/export_to_squeezebox.py quodlibet/ext/playlist/remove_duplicates.py quodlibet/ext/playlist/shuffle.py quodlibet/ext/playorder/follow.py quodlibet/ext/playorder/playcounteq.py quodlibet/ext/playorder/queue.py quodlibet/ext/playorder/reverse.py quodlibet/ext/playorder/shufflebygrouping.py quodlibet/ext/playorder/skip_disliked.py quodlibet/ext/playorder/track_repeat.py quodlibet/ext/query/conditional.py quodlibet/ext/query/missing.py quodlibet/ext/query/pythonexpression.py quodlibet/ext/query/savedsearch.py quodlibet/ext/query/unique.py quodlibet/ext/_shared/squeezebox/base.py quodlibet/ext/_shared/squeezebox/server.py quodlibet/ext/_shared/squeezebox/util.py quodlibet/ext/songsmenu/albumart.py quodlibet/ext/songsmenu/ape2id3.py quodlibet/ext/songsmenu/bookmarks.py quodlibet/ext/songsmenu/brainz/__init__.py quodlibet/ext/songsmenu/brainz/widgets.py quodlibet/ext/songsmenu/console.py quodlibet/ext/songsmenu/cover_download.py quodlibet/ext/songsmenu/custom_commands.py quodlibet/ext/songsmenu/duplicates.py quodlibet/ext/songsmenu/editplaycount.py quodlibet/ext/songsmenu/embedded.py quodlibet/ext/songsmenu/exact_rating.py quodlibet/ext/songsmenu/filterall.py quodlibet/ext/songsmenu/filterbrowser.py quodlibet/ext/songsmenu/fingerprint/__init__.py quodlibet/ext/songsmenu/fingerprint/search.py quodlibet/ext/songsmenu/fingerprint/submit.py quodlibet/ext/songsmenu/forcewrite.py quodlibet/ext/songsmenu/html.py quodlibet/ext/songsmenu/ifp.py quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py quodlibet/ext/songsmenu/lastfmsync.py quodlibet/ext/songsmenu/makesorttags.py quodlibet/ext/songsmenu/playlist.py quodlibet/ext/songsmenu/refresh.py quodlibet/ext/songsmenu/replaygain.py quodlibet/ext/songsmenu/splitting.py quodlibet/ext/songsmenu/tapbpm.py quodlibet/ext/songsmenu/website_search.py quodlibet/ext/songsmenu/wikipedia.py quodlibet/formats/_audio.py quodlibet/formats/__init__.py quodlibet/__init__.py quodlibet/library/__init__.py quodlibet/library/album.py quodlibet/library/base.py quodlibet/library/file.py quodlibet/library/playlist.py quodlibet/library/song.py quodlibet/main.py quodlibet/operon/base.py quodlibet/operon/commands.py quodlibet/operon/main.py quodlibet/operon/util.py quodlibet/order/__init__.py quodlibet/order/reorder.py quodlibet/order/repeat.py quodlibet/player/gstbe/player.py quodlibet/player/gstbe/plugins.py quodlibet/player/gstbe/prefs.py quodlibet/player/gstbe/util.py quodlibet/player/__init__.py quodlibet/player/xinebe/player.py quodlibet/plugins/__init__.py quodlibet/ext/events/listenbrainz/__init__.py quodlibet/ext/events/listenbrainz/listenbrainz.py quodlibet/plugins/playlist.py quodlibet/plugins/query.py quodlibet.py quodlibet/qltk/about.py quodlibet/qltk/bookmarks.py quodlibet/qltk/browser.py quodlibet/qltk/cbes.py quodlibet/qltk/chooser.py quodlibet/qltk/controls.py quodlibet/qltk/data_editors.py quodlibet/qltk/delete.py quodlibet/qltk/download.py quodlibet/qltk/edittags.py quodlibet/qltk/_editutils.py quodlibet/qltk/entry.py quodlibet/qltk/exfalsowindow.py quodlibet/qltk/filesel.py quodlibet/qltk/getstring.py quodlibet/qltk/info.py quodlibet/qltk/information.py quodlibet/qltk/lyrics.py quodlibet/qltk/maskedbox.py quodlibet/qltk/matchdialog.py quodlibet/qltk/msg.py quodlibet/qltk/notif.py quodlibet/qltk/playorder.py quodlibet/qltk/pluginwin.py quodlibet/qltk/prefs.py quodlibet/qltk/properties.py quodlibet/qltk/queue.py quodlibet/qltk/quodlibetwindow.py quodlibet/qltk/ratingsmenu.py quodlibet/qltk/renamefiles.py quodlibet/qltk/scanbox.py quodlibet/qltk/searchbar.py quodlibet/qltk/seekbutton.py quodlibet/qltk/shortcuts.py quodlibet/qltk/songlistcolumns.py quodlibet/qltk/songlist.py quodlibet/qltk/songsmenu.py quodlibet/qltk/tagsfrompath.py quodlibet/qltk/textedit.py quodlibet/qltk/tracker.py quodlibet/qltk/tracknumbers.py quodlibet/qltk/unity.py quodlibet/qltk/views.py quodlibet/qltk/wlw.py quodlibet/qltk/x.py quodlibet/update.py quodlibet/util/collection.py quodlibet/util/cover/built_in.py quodlibet/util/cover/manager.py quodlibet/util/dprint.py quodlibet/util/__init__.py quodlibet/util/library.py quodlibet/util/logging.py quodlibet/util/massagers.py quodlibet/util/songwrapper.py quodlibet/util/string/__init__.py quodlibet/util/tags.py ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1626015735.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/POTFILES.skip��������������������������������������������������������������������0000664�0001750�0001750�00000000142�14072603767�014751� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������tests/test_qltk_notif.py tests/test_util.py tests/test_util_i18n.py build dist quodlibet/packages ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/bg.po����������������������������������������������������������������������������0000644�0001750�0001750�00000712130�14436352625�013567� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Bulgarian translation of quodlibet. # Copyright (C) 2005 THE quodlibet'S COPYRIGHT HOLDER # This file is distributed under the same license as the quodlibet package. # Rostislav "zbrox" Raykov <zbrox@i-space.org>, 2005 # msgid "" msgstr "" "Project-Id-Version: quodlibet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2006-07-05 15:56-0500\n" "Last-Translator: Rostislav \"zbrox\" Raykov <zbrox@i-space.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Заглавие" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "човека" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Дата" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Дата" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "оригинален артист" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "_Жанр" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Оценка" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Редактиране на показваното" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Сортиране по дата" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Настройки" #: quodlibet/browsers/albums/main.py:430 #, fuzzy msgid "Album List" msgstr "Списък с албуми" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Спис_ък с албуми" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Всички албуми" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d албум" msgstr[1] "%d албума" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Показване на _обложките" msgstr[1] "Показване на _обложките" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Песните не са в албум" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d песен" msgstr[1] "%d песни" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d диск" msgstr[1] "%d диска" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Всички албуми" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Настройки на списъка с албуми" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Показване на _обложките" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[Опции]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Показване на албум" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Затваряне" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Разглеждане на фонотеката" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d песен" msgstr[1] "%d песни" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Невалиден шаблон" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Колекция от албуми" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Неизвестен %s" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Множество %s стойности" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Потребителски" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "Добавяне" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "_Премахване" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Етикет" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Сливане" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Настройки на списъка с албуми" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Прилагане" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Отказ" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Общ размер:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Общ размер:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Настройки на панели" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Показване на _обложките" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Всички албуми" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "Няма нови станции" #: quodlibet/browsers/filesystem.py:42 #, fuzzy msgid "File System" msgstr "Ф_айлова система" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "Ф_айлова система" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Неуспех при копиране на песните" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Избраните файлове не могат да бъдат копирани към други списъци с песни или " "към опашката." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "Пре_зареждане на фонотеката" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Списъците със станции могат да съдържат само местоположения на станции, не " "други списъци на станции или списъци на песни. Следните местоположения не " "могат да бъдат заредени:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 #, fuzzy msgid "Internet Radio" msgstr "_Радио по Интернет" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Нова станция" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Изтегляне на файлове" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Нова станция" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Въведете местоположението на радиостанция в Интернет:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "оценка" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_Нова станция" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Радио по Интернет" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Нова станция" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Нова станция" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "_Нова станция" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Няма открити станции." #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Няма открити Интернет радиостанции на %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Всички изписани станции са вече във фонотеката Ви." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "_Добавяне към списък" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "Премахване от фонотеката" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d станция" msgstr[1] "%(count)d станции" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 #, fuzzy msgid "Paned Browser" msgstr "_Изглед на панели" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Изглед на панели" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "_Избор на всички" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Неизвестен" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Всички" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Видими колони" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Настройки на панели" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 #, fuzzy msgid "Playlists" msgstr "Сп_исъци с песни" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Сп_исъци с песни" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Премахване от фонотеката" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Нов" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Внасяне" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Неуспех при внасяне на списъка" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet може да внася само списъци с песни с формат M3U или PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Из_триване" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Преименуване" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Неуспех при преименуване на списъка." #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Внасяне на списък с песни" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Внасяне" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_Нов списък с песни" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Нов списък с песни" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Настройки на панели" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Сп_исъци с песни" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Песен" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Нов списък с песни" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Въведете име за новата папка:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Внасяне на списък с песни.\n" "\n" "Добавени са %d/%d песни." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Нова емисия" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Въведете местоположението на аудио емисия:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Добавяне на файл..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "_Опресняване" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Наблюдение на папката за нови песни" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Неуспех при добавяне на емисията" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> не може да бъде добавена. Сървърът може да не е на линия или " "местоположението да не е аудио емисия." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Ограничаване на резултатите" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Разделяне на _множество стойности" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Списък с песни" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Списък с песни" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "_Изглед на панели" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "_Изглед на панели" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Търсене" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "песни" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "местонахождение" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> не е валидно местоположение." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet не е стартиран." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "фонотека и програма за слушане на музика" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[опции]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Показване на изпълняващата се песен и излизане" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Започване на изпълнението незабавно" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Отиване на следващата песен" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Отиване на предишната песен" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Започване на изпълнението" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Паузиране на изпълнението" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Започване на изпълнението" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Увеличаване силата на звука" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Намаляване силата на звука" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Показване статуса на изпълнението" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Скриване на главния прозорец" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Показване на главния прозорец" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Превключване видимостта на главния прозорец" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Фокусиране на програмата" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:113 #, fuzzy msgid "Refresh and rescan library" msgstr "Опресн_яване на фонотеката" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "_Изключване на разглеждането" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Печат на текущия списък с песни" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Показване съдържанието на опашката" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Показване съдържанието на опашката" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet не е стартиран." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Затваряне на Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Прескачане в слушаната в момента песен" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Включване на повтарянето, изключване или превключването му." #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Настройване силата на звука" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Търсене из фонотеката" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "запитване" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Слушане на файл" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "файлово име" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Прескачане в слушаната в момента песен" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Оценка на текущата песен" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Отваряне на нов браузър" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Показване или скриване на опашката" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Филтриране по произволна стойност" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "етикет" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Филтриране по стойност на етикета" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "етикет=стойност" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Поставяне на файл или запитване на опашката" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "файлово име" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 #, fuzzy msgid "Unqueue a file or query" msgstr "Поставяне на файл или запитване на опашката" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "местонахождение" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Невалиден шаблон" #: quodlibet/cli.py:216 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Невалиден аргумент за \"%s\"." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Опитайте %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Показване на _грешки" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "описание" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "редактор на музикални етикети" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "папка" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Редактор на музикални етикети" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "ID в MusicBrainz на песента" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID в MusicBrainz на песента" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[невалидна кодировка]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Заглавие" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Редактор на музикални етикети" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Етикети със регистър на заглавие" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Настройки на панели" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Общ размер:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Редактиране на показваното" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Тежест" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Редактиране на показваното" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "Пре_глед" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Информация" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Поддържани формати: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Само този _жанр" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "папка" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "_Аудио емисии" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Нова станция" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Запазване на оценките и броя на слушания" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "дата на запис" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Показване на _грешки" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Нова станция" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Настройки" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Внасяне на списък с песни" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Внасяне" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Внасяне" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Отказване от промените?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Отказване от промените?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Преслушване" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "шаблон" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "шаблон" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d секунда" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Само този _артист" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Избор" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "Пре_глед" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Лично" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Неуспех при добавяне на песните" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Запазване" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Невалиден шаблон" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Слушане на музика" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "_Радио по Интернет" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Оценка" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "местонахождение" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Скриване на главния прозорец" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "шаблон" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "шаблон" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d песен" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Информация" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "шаблон" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "местонахождение" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "ID в MusicBrainz на албума" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Име:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Заглавие" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 #, fuzzy msgid "Show notifications" msgstr "Няма нови станции" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 #, fuzzy msgid "Song Notifications" msgstr "Няма нови станции" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Няма нови станции" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Други:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Артист" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Файлово име" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Произволен _албум" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "албуми" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Тежест" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Произволен _албум" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Отметки" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Име на отметка" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Име на отметка" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[Опции]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "[невалидна кодировка]" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "дата на запис" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Из_триване" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Текст на песен" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Из_триване" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Текст на песен" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Няма открити станции." #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "шаблон" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Запазване на редактираните стойности..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Артист" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Пре_глед" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Слушане на музика" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Внасяне на списък с песни" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "организация" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Избор на нови станции" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Текст на песен" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Местоположението не е абсолютно" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Шаблона\n" "\t<b>%s</b>\n" "съдържа /, но не започва от главната папка (root folder). За да се избегнат " "зле именувани папки, направете шаблона да започва с / или ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Няма избрани песни." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Няма избрани песни." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Не може да се запази песента" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Текст на песен" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Неуспех при отваряне на файловете" msgstr[1] "Неуспех при отваряне на файловете" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Текст на песен" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Не се изпълнява нищо" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d песен" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "шаблон" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "_Оценка" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Не се изпълнява нищо" #: quodlibet/ext/events/trayicon/__init__.py:52 #, fuzzy msgid "Tray Icon" msgstr "Настройки на иконата за статус" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Сп_исъци с песни" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Преслушване" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "Пре_глед" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "П_роизволен ред" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "П_овтаряне" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Спиране след тази песен" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Отваряне на нов браузър" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Редактиране на _етикети" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Информация" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Сп_исъци с песни" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Колелото на мишката наглася силата на звука;\n" "Shift и колелото на мишката променят песента." #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Колелото на ми_шката" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Показване на подсказка" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Текст на песен" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Няма открит текст за тази песен." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Не може да се запази песента" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Показване на _грешки" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "Няма нови станции" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Файлове" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "Пре_глед" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Само този _артист" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Лично" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Лично" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Само този _жанр" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Само този _артист" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "_Аудио емисии" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Въведете местоположението на аудио емисия:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Внасяне на списък с песни" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Внасяне" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Няма открити станции." #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Файлово име" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Неуспех при внасяне на списъка" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Файлово име" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Внасяне на списък с песни" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Премахване от фонотеката" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Нов списък с песни" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "последно слушана" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "последно слушана" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "_Опашка" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "_Опашка" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "_Опашка" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Никога" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Никога" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "групиране" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Неуспех при копиране на песните" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Само този _жанр" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Невалидни етикети" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Запазени стойности" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Запазени стойности" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Преименуване" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Фонотека" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Скриване на главния прозорец" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Файлово име" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Не може да се запази песента" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Размер" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Търсене:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Търсене" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Редактиране на отметки..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Редактиране на отметки..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Отметки" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "ID в MusicBrainz на албума" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Файлово име" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "Д_иск" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Песен" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Заглавие" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Артист" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "ID в MusicBrainz на албума" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "запитване" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Търсене" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Няма открити приставки." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "местонахождение" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Няма открити приставки." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "Пре_глед" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Преименуване" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "файлово име" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Никога" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Невалидна стойност" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Лично" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Неуспех при копиране на песните" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "_Изключване на разглеждането" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Редактиране на показваното" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Множество %s стойности" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "_Премахване на станция" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Филтриране по стойност на етикета" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer неуспя да зареди избраната песен." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Само този _жанр" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "_Опашка" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Запис" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "ID в MusicBrainz на песента" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "папка" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Нова станция" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Няма открити приставки." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Преместване на %d/%d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Внасяне на списък с песни" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Внасяне на списък с песни" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Няма информация за времетраенето" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Спис_ък с албуми" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Внасяне на списък с песни" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Внасяне" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Само този _жанр" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Д_иск" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Песен" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Артист" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "албуми" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Продължаване" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Файлово име" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "песни" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Показване на _грешки" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Преименуване" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Внасяне на списък с песни" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Пропадна изтриването на <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Опресн_яване на фонотеката" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Опресн_яване на фонотеката" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Песен" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Редактиране на етикетите" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Редактиране на етикетите" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Всички албуми" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "Пре_глед" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Етикет" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Неуспех при добавяне на песните" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Търсене" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "шаблон" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Запазване на редактираните стойности..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Оцветяване на _търсените фрази" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Редактиране на етикетите" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Търсене" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Фонотека" #: quodlibet/library/file.py:156 #, fuzzy msgid "Checking mount points" msgstr "точка на монтиране" #: quodlibet/library/file.py:166 #, fuzzy msgid "Scanning library" msgstr "Запазване на фонотеката" #: quodlibet/library/file.py:230 #, fuzzy, python-format msgid "Scanning %s" msgstr "Проверяване на %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Запазване на фонотеката" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "фонотека и програма за слушане на музика" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Показване на про_граматични етикети" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "описание" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Стойност" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Редактор на музикални етикети" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Няма избрани песни." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 #, fuzzy msgid "Remove tags" msgstr "_Премахване на станция" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 #, fuzzy msgid "Remove all tags" msgstr "_Премахване на станция" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Филтриране по стойност на етикета" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Филтриране по стойност на етикета" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Няма информация за времетраенето" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Неуспех при преименуване на файл." #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "_Премахване на станция" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Файл" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Показване на кратка информация за употреба" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> не е валидно местоположение." #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "непознат" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Подред" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "П_одред" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "Произв_олен" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "Произв_олен" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "последно слушана" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "П_овтаряне" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "П_овтаряне" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Една песен" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Една песен" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%d секунда" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Няма открити станции." #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "Неуспех при създаването на папка" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Име:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "П_риставки" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Начало" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "липсва" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Време" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Име на отметка" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "ММ:СС" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Отметки" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Филтри" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "Н_икога не е слушано" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Топ 40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Нова станция" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Произволен _жанр" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Произволен _артист" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Произволен _албум" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40те песни, които сте слушали най-много (може да са повече от 40, ако някой " "имат равен брой пускания)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Име:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "С_тойност:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Запазени стойности" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Запазване на редактираните стойности..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "Номера на песните" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "Спис_ък с албуми" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Без нагласяне на силата на звука" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "непознат" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "Добавяне" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Редактиране на показваното" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Филтриране по стойност на етикета" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Редактор на музикални етикети" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Файлове" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Изтриване на файлове" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "Преместване в _кошчето" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "Преместване на %d/%d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Неуспех при запазване на фонотеката" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Пропадна изтриването на <b>%s</b>." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Изтриване на %d/%d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Неуспех при изтриването на файл" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Пропадна изтриването на <b>%s</b>." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Разглеждане" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Изтегляне на файлове" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "липсва от %d песен" msgstr[1] "липсва от %d песни" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "различно при %d песен" msgstr[1] "различно при %d песни" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Разделяне на _множество стойности" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Номерът на диска извън етикета за _албум" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "_Версията извън етикета за заглавието" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "_Аранжиментът извън етикета за артист" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Из_пълнителят извън етикета за артист" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Из_пълнителят извън етикета за артист" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "_Версията извън етикета за заглавието" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Добавяне на етикет" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Етикет:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Показване на про_граматични етикети" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Показване на про_граматични етикети" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Никога" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Продължаване" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Редактиране на етикетите" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Показване на _обложките" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Неуспех при добавяне на етикет" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Неуспех при добавяне на песните" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Неуспех при добавяне на <b>%s</b>\n" "\n" "Текущо избраните файлове не поддържат множествени стойности." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Невалиден етикет" msgstr[1] "Невалиден етикет" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Невалиден етикет <b>%s</b>\n" "\n" "Избраните в момента файлове не поддържат редакцията на този етикет." msgstr[1] "" "Невалиден етикет <b>%s</b>\n" "\n" "Избраните в момента файлове не поддържат редакцията на този етикет." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Невалидна стойност" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Невалидна стойност: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Етикетът може да не е точен" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> претърпя промени, докато програмата вървеше. Запазването без " "опресняване на фонотеката може да презапише други промени по песента.\n" "\n" "Да се запази ли въпреки това?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Не може да се запази песента" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Запазването на <b>%s</b> пропадна. Файлът може би е само за четене, повреден " "или нямате права да го променяте." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "О_ще опции..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "П_риставки" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Настройки на Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Папки" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Нова папка" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Избор на всички" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Нова папка" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Въведете име за новата папка:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Неуспех при създаването на папка" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Неуспех при изтриването на папка" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Песни" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Диск %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Песен номер %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Редактиране на показваното" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Няма избрани песни." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Няма песни" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Информация" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Текст на песен" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Продуцирано от %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "артист" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "артисти" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "изпълнители" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Никога" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d път" msgstr[1] "%d пъти" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "добавенa" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "последно слушана" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "Прослушвания" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "пропускания" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "оценка" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "времетраене" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Информация" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[невалидна кодировка]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "размер на файла" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "променян" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d избрана" msgstr[1] "%d избрани" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Песента е неналична" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d песен без албум" msgstr[1] "%d песни без албум" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Избор на дискография" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d песен без артист" msgstr[1] "%d песни без артист" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "албуми" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Общо времетраене:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Общ размер:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Файлове" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Няма открит текст за тази песен." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Отказване от промените?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Етикетите бяха променени, но не бяха запазени. Ще запазите промените или ще " "се откажете от тях?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Никога" #: quodlibet/qltk/msg.py:108 #, fuzzy msgid "File exists" msgstr "Ф_айлова система" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Преименуване на файлове" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet е стартиран" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Сменяне между Слушане и Пауза" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "Р_ед на прослушване" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Редактиране на етикети" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Преименуване" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "запитване" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Общ размер:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Грешки на приставките" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "_Изключване на разглеждането" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Няма открити приставки." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "П_риставки" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Показване на _грешки" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "Д_иск" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "Песен н_омер" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "групиране" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Изпълнител" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Алб_ум" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Файлово име" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Времетраене" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Автоматично прескачане до текущата песен" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Когато слушана песен се смени, автоматично да се селектира нея в списъка с " "песни" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Други:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Редактиране на показваното" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Видими колони" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Заглавието включва _версията" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Заглавието включва _версията" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Името на файла вклю_чва папката" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Настройки" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Видими колони" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Списък на песните" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Видими колони" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Глобален филтър:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Търсене" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Разглеждане" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Когато слушана песен се смени, автоматично да се селектира нея в списъка с " "песни" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 #, fuzzy msgid "Ratings" msgstr "_Оценка" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Спис_ък с албуми" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Паузиране на изпълнението" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "номер" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Без нагласяне на силата на звука" #: quodlibet/qltk/prefs.py:445 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Без нагласяне на силата на звука" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "_Оценка" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Е-поща:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Оценките и броя на слушанията ще бъдат настроени за тази е-поща" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Отказване от промените?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Раз_деляне на:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Раз_деляне на:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Редактиране на етикетите" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Редактиране на етикети" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Нова станция" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "Т_ърсене във фонотеката" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Проверка за промени във фонотеката Ви" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Пре_зареждане на фонотеката" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "" "Презареждане на всички песни от фонотеката ви (това може да отнеме много " "време)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Няма песни" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "Опресн_яване на фонотеката" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Сканиране на пап_ки" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Информация" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Опашка" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "Грешки на приставките" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Премахване на всички песни от опашката" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Р_азглеждане на фонотеката" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Превключване видимостта на главния прозорец" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Паузиране на изпълнението" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Избор на папки" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Неуспех при добавяне на песните" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> използва неподдържан протокол." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "П_рескачане към текущата песен" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Файл" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Песни" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Преглед" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Разглеждане" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Управление" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "Помощ" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Добавяне на папка..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Добавяне на файл..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Добавяне на местоположение" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Редактиране на отметки..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Спиране след тази песен" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Търсене" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Добавяне на местоположение" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Въведете местоположението на аудио файл:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Неуспех при добавяне на местоположението" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> не е валидно местоположение." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Добавяне на музика" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Добавяне на папка..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Слушане на музика" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Добавяне на файл..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Опашка" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "_Премахване на станция" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Оценка" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Заменяне на интервалите с долни черти" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Премахване на _несъвместимите с Windows символи" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Премахване на _диакритичните знаци" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Премахване на н_e-ASCII символите" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Преименуване на файлове" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "Пре_глед" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Файлово име" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "Артист на албума" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "Избор на папки" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Спис_ък с албуми" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Ново име" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Неуспех при преименуване на файл." #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Пропадна преименуването на <b>%s</b> на <b>%s</b>. Възможно е да има вече " "файл с такова име или да нямате привилегиите да създадете нов файл или да " "премахвате стария." #: quodlibet/qltk/renamefiles.py:346 #, fuzzy msgid "Ignore _All Errors" msgstr "Показване на _грешки" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Продължаване" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Местоположението не е абсолютно" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Шаблона\n" "\t<b>%s</b>\n" "съдържа /, но не започва от главната папка (root folder). За да се избегнат " "зле именувани папки, направете шаблона да започва с / или ~/." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "Песните поставени в тези папки ще бъдат добавяни към фонотеката" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Фонотека" msgstr[1] "Фонотека" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Премахване" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Избор на папки" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Избор на папки" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Запазени стойности" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Запазване на редактираните стойности..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "Спиране след тази песен" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Ограничаване:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Тежест" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "запитване" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Показване на оставащото време" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Текст на песен" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Фокусиране на програмата" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Прескачане в слушаната в момента песен" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Неуспех при добавяне на песните" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Неуспех при добавяне на песните" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Само този %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "Спис_ък с албуми" #: quodlibet/qltk/songlist.py:1194 #, fuzzy msgid "_Track Headers" msgstr "Номера на песните" #: quodlibet/qltk/songlist.py:1195 #, fuzzy msgid "_Album Headers" msgstr "Спис_ък с албуми" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "" #: quodlibet/qltk/songlist.py:1198 #, fuzzy msgid "_File Headers" msgstr "_Филтри" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Филтри" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Премахване от фонотеката" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Премахване от фонотеката" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "Премахване от фонотеката" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Оцветяване на _търсените фрази" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Добавяне към _опашката" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "Премахване от фонотеката" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Неуспех при изтриването на файл" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Изтегляне…" msgstr[1] "_Изтегляне…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Търсене" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Изтегляне на файл" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Спис_ък с албуми" msgstr[1] "Спис_ък с албуми" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Изтегляне на файл" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Замяна на _долните черти с интервали" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Етикети със регистър на заглавие" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Разделяне на _множество стойности" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Етикети от местоположението" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Етикетите заменят съществуващите" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Етикетите се добавят към съществуващите" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблонът\n" "\t<b>%s</b>\n" "е невалиден. Възможно е да съдържа същия етикет два пъти или има " "небалансирани скоби (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Шаблонът, който въведохте е невалиден. Уверете се, че сте въвели < и > " "като \\< и \\> и че етикетите са балансирани.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Редактиране на показваното" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Номера на песните" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Запо_чване от:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Общо песни:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Преслушване" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "Пре_глед" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "и още %d..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Запазване на песните, които сте променили." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Преместване на %d/%d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "точка на монтиране" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "местонахождение" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Внасяне на списък с песни" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Списък с песни с името %s, вече съществува." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Показване на _обложките" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Ф_айлова система" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Общ размер:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Показване на кратка информация за употреба" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Показване на версията на запазените права" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Няма информация за времетраенето" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[опции]" #: quodlibet/util/__init__.py:167 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Опцията \"%s\" не е разпозната." #: quodlibet/util/__init__.py:170 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Опцията \"%s\" изисква аргумент." #: quodlibet/util/__init__.py:173 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: \"%s\" не е уникална представка." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Няма информация за времетраенето" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минута" msgstr[1] "%d минути" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d час" msgstr[1] "%d часа" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d ден" msgstr[1] "%d дни" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d година" msgstr[1] "%d години" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "Заглавие" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Датата трябва да бъде въведета във един от следните формати: ГГГГ, ГГГГ-ММ-" "ДД или ГГГГ-ММ-ДД ЧЧ:ММ:СС." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz идентификаторите трябва да са във формата UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Пропадна изтриването на <b>%s</b>." msgstr[1] "Пропадна изтриването на <b>%s</b>." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Неуспех при редактиране на песента" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Запазването на <b>%s</b> пропадна. Файлът може би е само за четене, повреден " "или нямате права да го променяте." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[невалидна кодировка]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "албум" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "аранжимент" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "аранжименти" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "аранжимент" #: quodlibet/util/tags.py:86 msgid "author" msgstr "автор" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "автори" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "файлово име" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "композитор" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "композитори" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "композитор" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "диригент" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "диригенти" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "диригент" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "за контакт" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "авторски права" #: quodlibet/util/tags.py:93 msgid "date" msgstr "дата" #: quodlibet/util/tags.py:94 msgid "description" msgstr "описание" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "жанр" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "жанр" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "изпълнител" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "изпълнител" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "групиране" #: quodlibet/util/tags.py:98 msgid "language" msgstr "език" #: quodlibet/util/tags.py:99 msgid "license" msgstr "лиценз" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "текстописец" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "текстописци" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "текстописец" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "организация" #: quodlibet/util/tags.py:104 msgid "title" msgstr "заглавие" #: quodlibet/util/tags.py:105 msgid "version" msgstr "версия" #: quodlibet/util/tags.py:106 msgid "website" msgstr "интернет сайт" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "Артист на албума" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "диск" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "номер" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "каталожен номер" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "оригинална дата на издаване" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "оригинален албум" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "оригинален артист" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "дата на запис" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID в MusicBrainz на песента" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID в MusicBrainz на песента" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "ID в MusicBrainz на песента" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID в MusicBrainz на артиста" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID в MusicBrainz на песента" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:138 #, fuzzy msgid "MusicBrainz album status" msgstr "ID в MusicBrainz за артиста на албума" #: quodlibet/util/tags.py:139 #, fuzzy msgid "MusicBrainz album type" msgstr "ID в MusicBrainz на албума" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID в MusicBrainz на песента" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 #, fuzzy msgid "track gain" msgstr "номер" #: quodlibet/util/tags.py:144 #, fuzzy msgid "track peak" msgstr "номер" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 #, fuzzy msgid "album gain" msgstr "албум" #: quodlibet/util/tags.py:147 #, fuzzy msgid "album peak" msgstr "албум" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Настройки" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "дискове" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "песни" #: quodlibet/util/tags.py:156 #, fuzzy msgid "last started" msgstr "последно слушана" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "пълно име" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "точка на монтиране" #: quodlibet/util/tags.py:166 msgid "people" msgstr "човека" #: quodlibet/util/tags.py:168 msgid "year" msgstr "година" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "оригинална дата на издаване" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "Отметки" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "формат" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Сп_исъци с песни" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Редактор на музикални етикети" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Редактиране на етикетите в аудио файловете Ви" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Затваряне на Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Слушане на музика" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "За слушане, разглеждане или редактиране на Вашата аудио колекция" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Внасяне на списък с песни" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Неуспех при добавяне на песента" #~ msgid "Invalid tags" #~ msgstr "Невалидни етикети" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Невалидни етикети <b>%s</b>\n" #~ "\n" #~ "Избраните в момента файлове не поддържат редактиране на тези етикети." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d секунда" #, fuzzy #~ msgid "Startup" #~ msgstr "_Внасяне" #, fuzzy #~ msgid "Audio Feeds" #~ msgstr "_Аудио емисии" #~ msgid "_Audio Feeds" #~ msgstr "_Аудио емисии" #, fuzzy #~ msgid "New" #~ msgstr "_Нов" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Търсене на текст на песента..." #, fuzzy #~ msgid "<artist>" #~ msgstr "артист" #, fuzzy #~ msgid "<album>" #~ msgstr "албум" #, fuzzy #~ msgid "<title>" #~ msgstr "заглавие" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Внасяне на списък с песни" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Внасяне на списък с песни" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Информация" #~ msgid "Unsupported file type" #~ msgstr "Неподдържан вид файл" #~ msgid "Unable to add station" #~ msgstr "Неуспех при добавяне на станцията" #, fuzzy #~ msgid "Device Properties" #~ msgstr "Информация" #, fuzzy #~ msgid "Mount point:" #~ msgstr "точка на монтиране" #, fuzzy #~ msgid "Media Devices" #~ msgstr "Аудио устройство: %s" #, fuzzy #~ msgid "_Media Devices" #~ msgstr "Аудио устройство: %s" #, fuzzy #~ msgid "_Eject" #~ msgstr "_Избор" #, fuzzy #~ msgid "_Properties" #~ msgstr "Информация" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Пропадна изтриването на <b>%s</b>." #, fuzzy #~ msgid "Unable to copy song" #~ msgstr "Неуспех при копиране на песните" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> не е валидно местоположение." #, fuzzy #~ msgid "Unable to delete songs" #~ msgstr "Неуспех при добавяне на песните" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Пропадна изтриването на <b>%s</b>." #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> не е валидно местоположение." #, fuzzy #~ msgid "Unable to delete song" #~ msgstr "Неуспех при редактиране на песента" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Пропадна изтриването на <b>%s</b>." #, fuzzy #~ msgid "Unable to eject device" #~ msgstr "Неуспех при изтриването на файл" #~ msgid "Search Library" #~ msgstr "Търсене във фонотеката" #~ msgid "_Search Library" #~ msgstr "Т_ърсене във фонотеката" #~ msgid "Rate the playing song" #~ msgstr "Оценка на текущата песен" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Показване или скриване на главния изглед с песни" #, fuzzy #~ msgid "Unknown Device" #~ msgstr "непознат" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: \"%s\" не е уникална представка." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Невалидна стойност" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Файлово име" #, fuzzy #~ msgid "_Clear" #~ msgstr "Грешки на приставките" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Текст на песен" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Изчистване на търсенето" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Текст на песен" #, fuzzy #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "Преглед и редакция на етикетите на вървящата песен" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Текст на песен" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Няма песни" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Разглеждане" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Неуспех при създаването на папка" #~ msgid "Audio device: %s" #~ msgstr "Аудио устройство: %s" #~ msgid "Downloads" #~ msgstr "Изтегляния" #~ msgid "Size" #~ msgstr "Размер" #~ msgid "_Download" #~ msgstr "Из_тегляне" #, fuzzy #~ msgid "browsers" #~ msgstr "Разглеждане" #~ msgid "Unable to download lyrics." #~ msgstr "Неуспех при изтегляне на текстовете" #~ msgid "Set or toggle the playback order" #~ msgstr "Промяна на реда на изпълнение" #, fuzzy #~ msgid "Combine tags with _multiple values" #~ msgstr "Разделяне на _множество стойности" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Неуспех при запазване на фонотеката" #, fuzzy #~ msgid "Unable to save iPod database" #~ msgstr "Неуспех при запазване на фонотеката" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "номер" #~ msgid "Shuffle" #~ msgstr "В разбъркан ред" #~ msgid "Weighted" #~ msgstr "Претеглен" #~ msgid "_Weighted" #~ msgstr "Пре_теглен" #~ msgid "_One Song" #~ msgstr "_Една песен" #~ msgid "Restart the playlist when finished" #~ msgstr "Започване наново списъка с песни след приключване" #, fuzzy #~ msgid "Disable Browser" #~ msgstr "_Изключване на разглеждането" #~ msgid "_Disable Browser" #~ msgstr "_Изключване на разглеждането" #, fuzzy #~ msgid "Force Write" #~ msgstr "Запис" #~ msgid "Filter on _Genre" #~ msgstr "Само този _жанр" #~ msgid "Filter on _Artist" #~ msgstr "Само този _артист" #~ msgid "Filter on Al_bum" #~ msgstr "Само този _албум" #~ msgid "_Music" #~ msgstr "_Музика" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Отметки" #~ msgid "Song _List" #~ msgstr "Списък с пес_ни" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Колелото на мишката сменя песента;\n" #~ "Shift и колелото на мишката променят силата на звука." #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Спиране след тази песен" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "и още %d..." #~ msgstr[1] "и още %d..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Номерът на диска извън етикета за _албум" #, fuzzy #~ msgid "Timeout" #~ msgstr "Време" #, fuzzy #~ msgid "Select an album" #~ msgstr "_Избор на всички" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Сп_исъци с песни" #~ msgid "Re_fresh Library" #~ msgstr "Опресн_яване на фонотеката" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Премахване на станция" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Невалидна стойност" #, fuzzy #~ msgid "command|filename" #~ msgstr "файлово име" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Търсене" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Употреба: %s %s" #~ msgid "_Download..." #~ msgstr "Из_тегляне..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Нова станция" #, fuzzy #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Пропадна изтриването на <b>%s</b>." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet вече е стартиран." #~ msgid "No song is currently playing." #~ msgstr "В момента не се слуша никаква песен." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Неуспех при писането към %s. Премахва се." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Редактиране на отметки..." #, fuzzy #~ msgid "_New Folder..." #~ msgstr "Нова папка..." #~ msgid "_Add to Playlist" #~ msgstr "_Добавяне към списък" #~ msgid "_Edit Display..." #~ msgstr "_Редактиране на показваното" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d станция" #~ msgid "_Order:" #~ msgstr "Р_ед:" #~ msgid "_Add a Location..." #~ msgstr "_Добавяне на местоположение..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "Номера на песните" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Филтри" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Спис_ък с албуми" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Филтри" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Филтри" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Номера на песните" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Етикет:" #, fuzzy #~ msgid "Warnings" #~ msgstr "_Оценка" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "Артист на албума" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "артисти" #, fuzzy #~ msgid "album (sort)" #~ msgstr "Артист на албума" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "изпълнители" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "изпълнители" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID в MusicBrainz за артиста на албума" #, fuzzy #~ msgid "errors" #~ msgstr "изпълнители" #~ msgid "Permanently delete this file?" #~ msgstr "Изтриване на файла за постоянно?" #~ msgid "Permanently delete these files?" #~ msgstr "Изтриване на файловете за постоянно?" #, fuzzy #~ msgid "Version:" #~ msgstr "версия" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "Грешки на приставките" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s не може да се добави към фонотеката Ви.\n" #~ "\n" #, fuzzy #~ msgid "No eject command found." #~ msgstr "Няма открити станции." #~ msgid "Unable to start web browser" #~ msgstr "Неуспех при стартирането на интернет браузър" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Не може да бъде открит интернет браузърът. Настройте променливата " #~ "$BROWSER или се уверете, че /usr/bin/sensible-browser съществува." #, fuzzy #~ msgid "Library Error" #~ msgstr "Разглеждане на фонотеката" #~ msgid "translator-credits" #~ msgstr "" #~ "Ростислав \"zbrox\" Райков <zbrox@i-space.org>\n" #~ "Проектът за превод на GNOME има нужда от\n" #~ "подкрепа. Научете повече за нас на http://gnome.cult.bg\n" #~ "Докладвайте за грешки на http://gnome.cult.bg/bugs" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Други колони, които да се показват, разделени от интервали" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Продължаване" #~ msgid "Search your library" #~ msgstr "Търсене из фонотеката" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Всички права запазени 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "Това е свободен софтуер; вижте изходния код за условията по копирането. " #~ "Няма НИКАКВА\n" #~ "гаранция; нито дори за ПРОДАВАЕМОСТ или ПРИГОДЕНОСТ ЗА НЯКАКВА ОПРЕДЕЛЕНА " #~ "ЦЕЛ.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Общ размер:" #~ msgid "Quod Libet Plugins" #~ msgstr "Приставки за Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Показва простите търсения в синьо, разширените в зелено и невалидните в " #~ "червено." #~ msgid "Separators for splitting tags" #~ msgstr "Разделители за разделяне на етикети" #~ msgid "Quod Libet Preferences" #~ msgstr "Настройки на Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Не е слушана _днес" #~ msgid "Not Played in a _Week" #~ msgstr "Не е слушана 1 _седмица" #~ msgid "Not Played in a _Month" #~ msgstr "Не е слушана 1 _месец" #~ msgid "B_ottom 40" #~ msgstr "Пос_ледните 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "40те песни, които сте слушали най-малко (може да са повече от 40, ако " #~ "някои имат равен брой пускания)" #~ msgid "gtk-media-next" #~ msgstr "Следваща" #~ msgid "gtk-media-previous" #~ msgstr "Предишна" #, fuzzy #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --refresh-library | --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Дата" #~ msgid "Add" #~ msgstr "Добавяне" #~ msgid "_Stations..." #~ msgstr "_Станции..." #~ msgid "Unable to save library" #~ msgstr "Неуспех при запазване на фонотеката" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Неуспех при изпъление на песента" #~ msgid "Sort by title" #~ msgstr "Сортиране по заглавие" #~ msgid "Sort by artist" #~ msgstr "Сортиране по артист" #~ msgid "Lyrics provided by %s." #~ msgstr "Текстът е предоставен чрез %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Няма открит текст на песента.\n" #~ "\n" #~ "Може да натиснете бутона \"Изтегляне\", за да се потърси текста в " #~ "Интернет. Също така може сами да въведете текста и да натиснете " #~ "\"Запазване\"." #~ msgid "part" #~ msgstr "част" #~ msgid "Opening audio device." #~ msgstr "Отваряне на аудио устройството." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d песни запазени" #~ msgid "MusicBrainz album ID" #~ msgstr "ID в MusicBrainz на албума" #~ msgid "Loaded song library." #~ msgstr "Заредена е фонотеката с песни." #~ msgid "Unable to open audio device" #~ msgstr "Неуспех при отваряне на аудио устройството" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet не може да открие елемента на GStreamer 'filesrc'. Проверете " #~ "инсталацията си на GStreamer." #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "Показване на _обложките" #~ msgid "Unable to retag multiple values" #~ msgstr "Неуспех при презаписването на множество стойности" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Не се поддържа смяната на името на етикет с множествени стойности." #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s не е база данни за песни на Quod Libet" #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Нагласяне на силата на звука за всяка песен (\"Радио\")" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Нагласяне на силата на звука за всеки албум (\"Аудиофил\")" #~ msgid "_Volume Normalization" #~ msgstr "_Нормализиране на звука" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Сканира се фонотеката Ви. Това може да отнеме няколко минути..\n" #~ "\n" #~ "%d презаредени песни\n" #~ "%d премахнати песни" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Сканира се за нови песни и се добавят към фонотеката.\n" #~ "\n" #~ "%d добавени песни" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3U списъците не могат да се зареждат." #~ msgid "This station is already in your library." #~ msgstr "Зареждане, сканиране и запазване на фонотеката Ви" #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "на <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Диск <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Песен номер <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "Фонотеката не може да бъде опреснена, докато Quod Libet върви." #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Зареждане, сканиране и запазване на фонотеката Ви." #~ msgid "Rescan your library and exit" #~ msgstr "Сканиране наново на фонотеката и излизане." #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "Изглежда в момента Quod Libet е пуснат. Ако редактирате песни, които са " #~ "също въф фонотеката на Quod Libet, докато програмата върви, може да се " #~ "наложи да обновите фонотеката или да добавите песните наново.\n" #~ "\n" #~ "Ако Quod Libet не върви или редактирате песни извън фонотеката, може да " #~ "пренебрегнете това предупреждение." #~ msgid "GStreamer status %r != %r" #~ msgstr "Състояние на GStreamer %r != %r" #~ msgid "_Pane %d:" #~ msgstr "Пане_л %d:" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/cs.po����������������������������������������������������������������������������0000644�0001750�0001750�00000745070�14436352625�013615� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Honza Hejzl <honza.hejzl@gmail.com>, 2011. msgid "" msgstr "" "Project-Id-Version: Quod Libet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2022-11-16 22:47+0000\n" "Last-Translator: Karolína Pláničková <karolina.planickova@denikn.cz>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/cs/>\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Generator: Weblate 4.15-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Název" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "lidé" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Hlavičky _Dat" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "původní umělec" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Žánr" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Hodnocení" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Počet přehrání" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Řadit _podle…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Nastavení" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Seznam alb" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Seznam alb" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Všechna alba" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d alba" msgstr[2] "%d alb" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Znovu _načíst přebal" msgstr[1] "Znovu _načíst přebaly" msgstr[2] "Znovu načíst přebaly" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Skladby neobsažené v albu" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d skladba" msgstr[1] "%d skladeb" msgstr[2] "%d skladby" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d disky" msgstr[2] "%d disky" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Příklad alba" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Nastavení seznamu skladeb" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Zobrazovat _přebaly alb" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_Hledání obsahuje osoby" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Možnosti" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Zobrazení alba" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Zavřít" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Prohlížeč sbírky" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d skladba" msgstr[1] "%d skladby" msgstr[2] "%d skladby" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Neplatné zadání" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Sbírka alb" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Sbírka _Alb" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Neznámé %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Více %s hodnot" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Vlastní" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Přidat" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "Odstranit" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Sloučit" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Nastavení sbírky alb" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Použít" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Zrušit" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Mřížka přebalů alb" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Mřížka přebalů alb" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Nastavení mřížky přebalů alb" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Zobrazovat _texty alba" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Zobrazit položku „Všechna alba“" #: quodlibet/browsers/covergrid/prefs.py:75 #, fuzzy msgid "Wide Mode" msgstr "Ši_roký mód" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Zvětšení přebalu alba" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Systém souborů" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Systém souborů" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nelze kopírovat skladby" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Vybrané soubory nelze zkopírovat do jiných seznamů skladeb nebo do fronty." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Přidat do sbírky" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Seznamy stanic mohou obsahovat pouze umístění stanic, nemohou obsahovat " "seznamy stanic nebo plylisty. Následující umístění nelze nahrát:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internetová rádia" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Všechny stanice" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Stahování seznamu stanic" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nová stanice" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Zadejte umístění stanice internetového rádia:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronika" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonská" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indická" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Náboženská" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Sborová" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turecká" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Taneční" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latinskoamerické" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "College rádio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Rozhovory / Zprávy" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasická" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativní" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Zprávy" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Šlágry" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funky" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slovanská" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Řecká" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotická" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Přejete si načíst seznam oblíbených radiostanic?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Načíst stanice" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internetová rádia" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Všechny stanice" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Oblíbené" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Žádná kategorie" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nová stanice…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Aktualizace stanic" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nenalezeny žádné stanice" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Na %s nebyly nalezeny žádné stanice." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Všechny stanice na seznamu jsou už ve sbírce." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Přidat do oblíbených" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Odstranit z oblíbených" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stanice" msgstr[1] "%(count)d stanice" msgstr[2] "%(count)d stanic" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Prohlížeč s panely" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Prohlížeč s panely" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Vybrat _vše" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Neznámé" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Vše" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 #, fuzzy msgid "Wide" msgstr "Ši_roký mód" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Upravit sloupce" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Vzor tagu s volitelným značením, např. <tt>composer</tt> nebo\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Nastavení prohlížeče s panely" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Stejná šířka panelů" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Seznamy skladeb" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Seznamy skladeb" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Odstranit ze seznamu" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nový" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importovat" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Seznam skladeb nelze importovat" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet umí importovat jen seznamy ve formátu M3U a PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Smazat" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Přejmenovat" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Seznam skladeb nelze přejmenovat" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importovat seznam skladeb" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importovat" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nový seznam skladeb…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Co si přejete udělat s touto %d skladbou?" msgstr[1] "Co si přejete udělat s těmito %d skladbami?" msgstr[2] "Co si přejete udělat s těmito %d skladbami?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Potvrdit akci pro seznam skladeb ‚%s‘" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "prázdný" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Příklad seznamu skladeb" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Nastavení prohlížeče seznamu skladeb" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Zobrazení seznamu skladeb" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Jste si jistí, že chcete smazat seznam skladeb ‚%s‘?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Všechny informace o vybraných seznamech skladeb budou smazány a nebude je " "možné obnovit." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Skladba" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nový seznam skladeb" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Zadejte jméno nového seznamu:" #: quodlibet/browsers/playlists/util.py:73 #, fuzzy msgid "_Create" msgstr "_Vytvořit databázi" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importování seznamu skladeb.\n" "\n" "%(current)d/%(total)d skladeb přidáno." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nový zdroj" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Zadejte umístění audio zdroje:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Přidat soubor..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Obnovit" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Hledat ve složce nové skladby" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Nelze přidat zdroj" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s nemůže být přidán. Server může mít problémy, nebo na zadaném místě nemusí " "být platný audio zdroj." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Současná obslužná aplikace nepodporuje URL, prohlížeč audio zdrojů je " "zakázán." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Omezit výsledky" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Rozdělit do více _hodnot" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Seznam skladeb" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Seznam skladeb" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Prohlížeč Soundcloudu" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Hledání" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "skladby" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Přejít na %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Připojeno" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet je nyní připojen, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Odhlásit se z %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Vložit kód…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Přihlásit do %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Autorizace Soundcloudu" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Vložit audorizační kód Soundcloudu:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet neběží (pro spuštění přidejte '--run')" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "hudební sbírka a přehrávač" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[volba]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Vypsat přehrávanou skladbu a skončit." #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Ihned začít přehrávat" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Při startu nezobrazovat žádná okna" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Další skladba" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Skočit na předchozí skladbu nebo začít znovu, pokud je přehrávání na začátku" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Předchozí skladba" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Přehrávat" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pauza" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Prohodit režim přehrávání/pauza" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Přehrávat" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Zesílit hlasitost" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Snížit hlasitost" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Zobrazit stav přehrávače" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Skrýt hlavní okno" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Obnovit hlavní okno" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Přepnout viditelnost hlavního okna" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Zaměřit běžící přehrávač" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Odstranit aktivní fiiltry procházení" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Obnovit a znovu načíst sbírku" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Seznam dostupných prohlížečů" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Zobrazit současný seznam skladeb" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Zobrazit obsah fronty" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Tisk aktivního dotazu" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Start bez zásuvných modulů" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Spustit Quod Libet jestliže už neběží" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Ukončit Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Vyhledávat v přehrávané skladbě" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ HH:] MM: SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Nastavit nebo prohodit mód promíchání" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Prohodit mód promíchání" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Vypnout/zapnout či přepnout opakování" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Prohodit mód opakování" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Nastavit hlasitost" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Procházet sbírku skladeb" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "dotaz" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Přehrát soubor" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "název souboru" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Vyhledávat v přehrávané skladbě" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Nastavit aktuální prohlížeč" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Zastavit přehrávání po skončení skladby" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Otevřít nový prohlížeč" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Zobrazit nebo skrýt frontu" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtr s náhodnou hodnotou" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtr na hodnotu tagu" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=hodnota" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Zařadit do fronty soubor nebo dotaz" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Vyřadit z fronty soubory oddělené čárkou" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "název souboru" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Zobrazit jména souborů z výsledku hledání na standardní výstup" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Vyřadit z fronty soubor nebo dotaz" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "místo" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "vzor" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Neplatný argument pro ‚%s‘." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Zkuste %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Vyskytla se chyba" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Tuto chybu můžete ignorovat, ale pokud aplikace nebude restartována, může " "být nestabilní. Odeslání krátké zprávy o chybě zabere jen chvilku a hodně " "vývojářům pomůže." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Potvrdit hlášení chyby" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorovat chybu" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Podrobnosti o chybě:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Detaily týkající se chyby a vašeho systému budo odeslány službě třetí strany " "(<a href='https://www.sentry.io'>www.sentry.io</a>). Odesílaná data můžete " "zkontrolovat níže." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(volitelné) Prosím, zkuste krátce popsat, co se stalo, když se chyba " "objevila:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Poslat" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Krátký popis…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Data k odeslání:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "editor tagů " #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "složka" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Editor tagů" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL zdroj přebalu alba" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Stažení přebalů alb pomocí odkazu ve značce artwork_url. Funguje s " "prohlížečem Soundcloudu." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Přebaly alb z Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Stahování přebalů alb z Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Přebaly alb z Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Stahují se přebaly z archivu Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Zdroj přebalů MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Stažení přebalů z archivu MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Převést kódování" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Opravuje špatné kódování hodnoty tagu v editoru tagů." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Převést kódování…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji inverze" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Převést kana/kanji na latinku." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "_Japonský text na latinku" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Nelze najít 'Kanji Kana Simple Inventer' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Náhrada regulárním výrazem" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Umožňuje libovolné náhrady regulárními výrazy (s///) při úpravách tagů nebo " "přejmenovávání souborů." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Velikost písmen u názvů" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Velikosti písmen názvů v editoru." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Velikost _písmen v názvech" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Povolit _Všechna velká u tagů" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Běžná velká malá písmena" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Pro velká/malá písmena použít základní pravidla z angličtiny (např. „Dark " "Night of the Soul“)" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Pokročilá nastavení" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Povolit konfiguraci pokročilých nastavení." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Vím, co dělám" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animovaná obrazovka" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Zobrazení informací o skladbě, pokud se tato změní." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Poloha:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Velikost přebalu:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Zobrazení" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Písmo:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Vlevo" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Na střed" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Pravá" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Zarovnat text:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Text" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Text:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Vyplnit:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Barvy" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Stíny" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Obrysy" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "O_blé rohy" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Zpoždění:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efekty" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "U_pravit vzor zobrazení…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Náhled" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informace" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Podporované formáty: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtrovat složku" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "složka" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Audio zdroje" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Vrátit na základní hodnotu" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "‚%s‘ nelze nalézt." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Aktualizovat tagy souborů" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Aktualizovat změné tagy souborů. Ve výsledku budou aktualizována i všechna " "hodnocení a počet přehrání." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Uložit hodnocení a _počet přehrání" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "datum nahrávání" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Chyba během synchronizace" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Aktualizace stanic" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Nastavení" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatické maskování" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Automatické použití mask a umask u disků, které jsou připojeny a odpojeny." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatické hodnocení" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Automatické hodnocení skladeb, které jsou přeskočeny nebo přehrány. Používá " "se ‚urychlený‘ algorytmus z vux od Briana Nelsona." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Import selhal" #: quodlibet/ext/events/bansheeimport.py:118 #, fuzzy, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Import hodnocení a statistik %d skladeb byl úspěšný." msgstr[1] "Import hodnocení a statistik %d skladeb byl úspěšný." msgstr[2] "Import hodnocení a statistik %d skladeb byl úspěšný." #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "Spustit import" #: quodlibet/ext/events/bansheeimport.py:128 #, fuzzy msgid "Imports ratings and song statistics from Banshee." msgstr "Import hodnocení a statistik skladeb z Rhythmboxu." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Spustit import" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Budík" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Probuzení hlasitou hudbou." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Ukolébavka" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Ztlumí a pozastaví přehrávání." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim status" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim status" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Změna statusu pro Gajim podle toho, co se zrovna přehrává." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Zastaveno:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Text statusu" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Text statusu" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Byt" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Živě" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Plný bas i výšky" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klub" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Velká hala" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Párty" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Jemně" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Bohaté hloubky" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Sluchátka" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Soft Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Plné výšky" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Taneční" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Notebook" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Ekvalizér" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Kontrola zvuku ekvalizérem.\n" "Klikněte nebo použijte klávesy pro přizpůsobení úrovní (klik pravým myšidlem " "resetuje dané pásmo)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Současná obslužná aplikace na pozadí nepodporuje ekvalizér." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Základní téma" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "Vybrat _vše" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Resetovat" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Vlastní nastavení" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Smazat vybrané skladby" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Uložit" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "online" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "offline" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "pryč" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "neviditelný" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim status" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Změna statusu pro Gajim podle toho, co se zrovna přehrává." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "Zastaveno" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "vzor" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Vypsat účty, oddělené čárkou, pro změnu statusu. Není-li žádný účet vybrán, " "změní se status pro všechny účty." #: quodlibet/ext/events/gajim_status.py:157 #, fuzzy msgid "Accounts:" msgstr "Účet" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Přidat „[paused]“" #: quodlibet/ext/events/gajim_status.py:164 #, fuzzy msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Je-li zaškrtnuto, ke zprávě statusu bude při zastavení přehrávání přidáno " "‚[paused]‘." #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statusy, pro které bude změněna zpráva." #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Zastavit přehrávání při odpojení sluchátek" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Zastavení přehrávání, pokud jsou odpojena sluchátka, pokud jsou opět " "připojena, přehrávání se znovu spustí." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Potlačit spořič obrazovky" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Přehrává se" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Model:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Potlačit spořič obrazovky" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Potlačit spořič obrazovky" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Log internetových rádií" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Nahrání posledních 10 skladeb hradných v rádiích a jejich uložení do " "kontextového menu vyhledávání." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Uloží soubor Jabber User Tunes do ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Změnit jazyk" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Změnit jazyk uživatelského rozhraní" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Výchozí" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Pro uplatnění změn je třeba aplikaci restartovat" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Mediální Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Zpřístupnění všech alb pro Rygel UPnP Media Server přes MediaServer2 D-Bus " "rozhraní." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD Server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Povolit vzdálenou kontrolu přehrávače Quod Libet klientem MPD. Streaming, " "správa seznamu skladeb ani knihovny nejsou podporovány." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokální _IP adresa:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "H_eslo:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Spojení" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Otestované klienty" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus podpora" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Skrýt hlavní okno při zavření" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Akceptuje QL vzory, např. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT vydavatel" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Zveřejní status zprávy do tématu MQTT." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Hostname zprostředkovatele" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "hostname / IP zprostředkovatele" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Port zprostředkovatele" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Výchozí" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Hostname zprostředkovatele" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Port zprostředkovatele" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Téma" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Vzor pro přehrávání" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Text statusu při začátku přehrávání." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Pozastavený vzor" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Text při zastavení přehrávání." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Text, pokud se nic nepřehrává" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Text, když se nic nepřehrává" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Nastavení MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Text statusu" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Připojeno k zprostředkovateli na %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Nelze se připojit k %(host)s:%(port)d (%(msg)s" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Chyba připojení" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Vyhledávání na MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Povolit nastavení hodnocení skladeb číslem." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Jméno:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Heslo:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Účet" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Oznamovací text" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Název:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Zpět na základní hodnotu" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Tělo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Zobrazit notifikaci" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Zobrazovat notifikace" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Pouze při <i>_ručních</i>změnách skladby" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Pouze při <i>_automatických</i> změnách skladeb" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Při změně <i>_všech</i> skladeb" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Pouze když není _aktivní hlavní okno" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Zobrazit tlačítko „_Další“" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Chyba připojení" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Nelze se připojit k oznamovacímu daemonu." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Oznamování skladeb" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Zobrazení informace při změně skladby." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Další" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Oznamování skladeb" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Pro nastavení QLSCrobbleru otevřete okno Zásuvních modulů. Do té doby " "nebudou informace o skladbách odesílány." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Nelze se připojit ke službě ‚%s‘." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Autentizace selhala: neplatné URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Autentizace selhala: neplatné jméno uživatele ‚%s‘ nebo heslo." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Klient je zakázán, kontaktujte autora." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Vypadá to, že je nastaven špatný systémový čas. Informace o přehrávaných " "skladbách se možná nebudou odesílat, dokud nebude čas nastaven správně." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Zasílání dat přes AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "AudioScrobbler, klient pro Last.fm, Libre.fm a ostatní služby." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Autentizace proběhla úspěšně." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Služba:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Ostatní…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Ověřit účet" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Vzor pro umělce:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Vzor názvu skladeb:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Vyloučit _filtr:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Vzor používaný pro formátování jména umělce při odesílání informací. " "Ponechte prázdné pro výchozí hodnotu." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Vzor používaný k zformátování názvu pro odesílání. Ponechte prázdné pro " "výchozí hodnotu." #: quodlibet/ext/events/qlscrobbler.py:593 #, fuzzy msgid "Songs matching this filter will not be submitted" msgstr "" "Informace o skladbách odpovídajících zadanému filtru nebudou odesílány." #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Offline mód (neodesílat žádné informace)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Odeslání" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Ztlumit reklamy rádií" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Ztlumení výstupu během vysílání reklam v rádiích.\n" "Stanice: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Přehrávání náhodného alba" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Začít přehrávat náhodné album, když přehrávání seznamu skladeb dosáhne " "konce. Je nutné nastavit v prohlížeči možnost filtrování podle alba." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Hodnoceno lépe" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Přehráváno častěji" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Přeskočeno častěji" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Přehráváno nedávno" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Spuštěno nedávno" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Přidáno nedávno" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Delší alba" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "vteřiny před začátkem přehrávání alba" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Rovnováha" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Přehrávat některá alba častěji než jiná" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "raději ne" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "upřednostnit" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Náhodné album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Čekání na začátek %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Import hodnocení a statistik %d skladeb byl úspěšný." #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Import z Rhythmboxu" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Import hodnocení a statistik skladeb z Rhythmboxu." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Zastavení spořiče obrazovky" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Zastavení přehrávání při aktivním spořiči obrazovky (GNOME)." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Pro Quod Libet není instalován žádný vyhledávač přes GNOME Shell." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Poskytovatel prohledávání GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Povolit prohledávání sbírky přes GNOME Shell." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternativní lišta prohledávání" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternativní řádek prohledávání. Je vždy viditelný a zabírá vždy celou šíři " "okna." #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Žádné záložky" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Název záložky" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Název záložky" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Synchronizace se Squeezboxem" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Logitech Squeezebox jako zrcadlo Quod Libet, obojí načítáno ze stejné sbírky." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Chyba při hledání Squeezebox serveru" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Chyba při hledání %s. Zkontrolujte, prosím, nastavení." #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Možnosti" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "kódování" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "datum nahrávání" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Smazat" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Synchronizované texty" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Smazat" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Přeskočeno častěji" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Synchronizované texty" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Cílová složka:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Vzory cesty" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Upravit uložené vzory..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Vzor pro umělce:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Náhled" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Zdroje" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Exportovat metadata" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organizace" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Vybrat nové stanice" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Synchronizované texty" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Uvedená cesta není absolutní" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Vzor\n" "\t%s\n" "obsahuje / , ale nezačíná od kořene (root). Pro vyhnutí se nepojmenovaným " "složkám upravte vzor root tak, aby začínal / nebo ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nejsou vybrány žádné skladby." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nejsou vybrány žádné skladby." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Skladbu nelze uložit" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Synchronizované texty" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Přeskočeno častěji" msgstr[1] "Přeskočeno častěji" msgstr[2] "Přeskočeno častěji" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Nelze otevřít vstupní data" msgstr[1] "Nelze otevřít vstupní data" msgstr[2] "Nelze otevřít vstupní data" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synchronizované texty" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Zobrazení synchronizovaných textů z .lrc souboru s názvem stejným, jako je " "název skladby." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Text:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Pozadí:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Písmo" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Velikost (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Status zprávy pro Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Aktualizace všech účtů založených na messengeru Telepathy (Empathy apod.) " "statusem se zprávou o právě přehrávané skladbě." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Přehrává se:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Text statusu při začátku přehrávání. Je možné použít QL vzory jako např. %s." #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Zastaveno:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Text statusu, když je přehrávání pozastaveno. Je možné použít QL vzory jako " "např. %s." #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Text pro status, pokud není dostupná informace o aktuální skladbě" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Žádná skladba:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Vzory statusu" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Změna tématu" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Změna GTK+ tématu." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Téma:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Základní téma" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Upřednostit tmavou variantu" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Automatické hodnocení" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Prohodit lištu menu" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Prohodit lištu menu stiskem klávesy Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Nepřehrává se" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Ikona v oznamovací oblasti" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Ovládá Quod Libet ze systémové lišty." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Zobrazit %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Přehrávat" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_auza" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Předchozí" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Další" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Promíchat" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Opakovat" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Po této skladbě _zastavit přehrávání" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Otevřít _prohlížeč" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editovat _Tagy" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informace" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Seznamy _skladeb" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Zavřít" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Chování" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Ovládat hlasitost kolečkem myši" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Přechod na další skladbu kolečkem myši" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Kolečko myši" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Zobrazení tipů" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Zobrazit texty" #: quodlibet/ext/events/viewlyrics.py:26 #, fuzzy msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Automatické zobrazení textů pod seznamem skladeb v hlavním okně." #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Ke skladbě nebyly nalezeny žádné texty." #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Žádné aktivní skladby" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Spustit vizualizace" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Spustit externí vizualizace." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Nelze spustit vizualizace s použitím '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Chyba" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Spouštěcí příkaz vizualizéru:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Znovu načíst" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Lišta hledání ve vlnové křivce skladby" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "Lišta hledání v tvarech vlnové křivky přehrávané skladby." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Přepsat barvu popředí." #: quodlibet/ext/events/waveformseekbar.py:678 #, fuzzy msgid "Override hover color:" msgstr "Přepsat barvu popředí." #: quodlibet/ext/events/waveformseekbar.py:682 #, fuzzy msgid "Override remaining color:" msgstr "Přepsat barvu popředí." #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "_Zobrazit notifikaci" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Ukládání obrázků" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Uložení obrázku přebalu do vybraného souboru skladby." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Soubor:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Práh:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Práh dokud je aktivován filtr" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "P_oměr:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Poměr komprese" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Kompresor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Změnit amplitudu všech vzorků nad určitý práh na základě určitého poměru." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Přednastavení:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Přednastavení filtru" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Ořez frekvence:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Low-pass filtr frekvence" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Úroveň _kanálu:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Úroveň kanálu" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Výchozí" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Umístění nejblíže k virtuálnímu reproduktoru (30°, 3 metry)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Podobné směšovači Chu Moye (oblíbené)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Přiblížit CORDA zesilovačům Jana Meiera (malá změna)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Vlastní" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Vlastní nastavení" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Směšování kanálů" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Směšování levého a pravého kanálu způsobem, který napodobuje nastavení " "vhodné pro poslech ve sluchátkách nebo vyrovnává nastavení nejstarších " "stereo nahrávek, kde jsou kanály příliš oddělené." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filtrovat podle _skupiny:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Frekvenční pásmo filtru" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Šíře _filtru:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Šíre frekvence filtru" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Úroveň:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Úroveň efektu" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Odstranění hlavních vokálů." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Sloučení kanálů (mono)" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Sloučí oba kanály sterea do jednoho (mono)." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Hodnotit:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Zpomalení:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Audio zpomalení / rychlost" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Kontrola rychlosti přehrávání streamu." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Exportovat seznam skladeb do složky" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exportovat" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Cílová složka:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Vzor názvu souborů:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Exportovat seznam skladeb zkopírováním do složky." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Seznam skladeb nelze exportovat" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "_Základní vzor názvu souborů:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Exportovat jako seznam skladeb" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Exportovat seznam skladeb zkopírováním do složky." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Chyba při hledání Squeezebox serveru" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Chyba při hledání %s. Zkontrolujte, prosím, nastavení." #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Export pro Squeezbox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dynamický export seznamu skladeb pro Logitech Squeezbox se sdílením " "struktury složek. Sdílí konfiguraci se <a href=\"quodlibet:///prefs/plugins/" "Squeezebox Output\">zásuvným modulem synchronizace Squeezboxu</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Exportovat seznam skladeb do Squeezeboxu" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Jméno seznamu skladeb (přepíše již existující)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exportovat seznam skladeb pro Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Odstranit duplicity ze seznamu skladeb" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Odstraní duplicity ze seznamu skladeb." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Jste si jistí, že chcete odstranit %d duplicitní skladbu?" msgstr[1] "Jste si jistí, že chcete odstranit %d duplicitní skladby?" msgstr[2] "Jste si jistí, že chcete odstranit %d duplicitních skladeb?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplikátní skladby budou ze seznamu skladeb ‚%s‘ odstraněny." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Zamíchat seznam skladeb" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Náhodně zamíchat seznam skladeb." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Zaměřit kurzor" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Přehrávání podle výběru, nebo přehrávání další skladby, pokud je seznam " "výběru dokončen." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Zaměřit kurzor" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Zaměřit kurzor" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Ekvalizér počtu přehrání" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Zamíchat, upřednostnit skladby s menším počtem přehrání." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Upřednostnit málo hrané" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Upřednostnit málo hrané" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Pouze fronta" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Omezení přehrávání skladeb ve frontě. Zvolte pro přehrávání pořadí skladeb " "podle hlavního okna. Dvojklikem se skladba nebude přehrávat, ale zařadí se " "do fronty." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Pouze fronta" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Pouze fronta" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Opačně" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Inverze (převrácení) pořadí přehrávání skladeb" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Opačně" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 #, fuzzy msgid "Waiting to start new group…" msgstr "Čekání na začátek %s" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "_Sloučit" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Nelze kopírovat skladby" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtrovat podle _skupiny:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 #, fuzzy msgid "Delay:" msgstr "_Zpoždění:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 #, fuzzy msgid "Time delay in seconds before starting next group" msgstr "vteřiny před začátkem přehrávání alba" #: quodlibet/ext/playorder/shufflebygrouping.py:184 #, fuzzy msgid "Reset to defaults" msgstr "Vrátit na základní hodnotu" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Opakovat všechny skladby" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Zamíchat skladby, ale opakovat každou z nich podle nastaveného počtu." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Opakovat všechny skladby" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Opakovat všechny skladby" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Počet přehrání pro každou skladbu:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Podmíněný dotaz" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Výběr dotazu hledání založený na podmíněném dotazu. Syntaxe je '@(if: " "condition, then, else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 #, fuzzy msgid "Missing Query" msgstr "Podmíněný dotaz" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Neplatné tagy" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Dotaz v Pythonu" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Výraz tagu" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Použít uložené hledání" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Zahrnout výsledky uloženého hledání jako část jiného dotazu. Syntaxe je " "'@(saved: hledaný výraz)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Uložené hodnoty" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unikátní" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezbox OK. Používá se přehrávač (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Nelze se připojit k %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Hostname:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Uživatel:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Heslo:" #: quodlibet/ext/_shared/squeezebox/base.py:138 #, fuzzy msgid "Library directory the server connects to" msgstr "Složka sbírky, ke které se server připojuje." #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Cesta ke sbírce:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "O_věřit nastavení" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox server" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Ladit" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezbox server na {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "neidentifikován server Squeezbox" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "neindentifikován přehrávač pro Squeezbox: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Vybrat přehrávač pro Squeezbox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Nalezen Squeezbox server.\n" "Vyberte, prosím, přehrávač" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Přizpůsobit obrázek _oknu" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Upravit obrázek po uložení" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Náze_v souboru" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Ukládání selhalo" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Nelze uložit ‚%s‘." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP chyba: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Klient stahování přebalů" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "z %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Rozlišení: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Velikost: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Hledat" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Hledání…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Hotovo" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Stáhnout přebal" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Stahování přebalů alb z různých zdrojů." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Zdroje" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "Z APEv2 na ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Převedení APEv2 tagů na ID3v2 tagy. Po převodu budou původní APEv2 tagy " "smazány." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Přejít na záložku" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Úprava záložek u vybraných souborů." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Upravit záložky..." #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Žádné záložky" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Vyhledávání na MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Přetagovat album na základě vyhledávání v MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Pro „date“ tag pužít pouze rok" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Zapsat „_albumartist“, pokud bude třeba" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Zapsat tagy pro třídění umělců" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Zapsat _standardní tagy MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Uveďte tag \"labelid\"" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Název souboru" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Skladba" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Název" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Umělec" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz vyhledávání" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Dotaz:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "Vyhl_edávání" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Výsledky <i>(přetáhnout a změnit pořadí)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Vložte prosím dotaz." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Objevila se chyba. Zkuste to, prosím, znovu." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Načítání výsledků…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Žádné výsledky nenalezeny." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Konzole Pythonu" #: quodlibet/ext/songsmenu/console.py:42 #, fuzzy msgid "Interactive Python console. Opens a new window." msgstr "Interaktivní konzole pro Python" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 #, fuzzy msgid "Python Console Sidebar" msgstr "Konzole Pythonu" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Jako základ můžete použít následující objekty:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Aktuální pracovní složka:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Spojení" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Stáhnout přebal" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Klasická" #: quodlibet/ext/songsmenu/cover_download.py:160 #, fuzzy msgid "Large" msgstr "Velká hala" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 #, fuzzy msgid "Full HD" msgstr "Bohaté hloubky" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Klient stahování přebalů" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Žádné texty nenalezeny" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "Náhled" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Příkaz" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "jméno" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Jméno příkazu" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "příkaz" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Spustit příkaz v syntaxi shellu" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parametr" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Je-li specifikováno,výskyty parametru v příkazu budou nahrazeny uživatelem " "zadanou hodnotou, např. při použití 'PARAM' budou všechny výskyty '{PARAM}' " "v příkazu nahrazeny hodnotou, na kterou bude uživatel dotázán při spuštění." #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL vzor jako např. <~filename> pro použití k výpočtu hodnoty příkazu. Pro " "seznamy skladeb je možné použít virtuální tagy <~playlistname> a " "<~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unikátní" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Pokud je nastaveno, duplicitní vypočtené hodnoty budou ze vzoru odstraněny." #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "max args" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "Nejvyšší počet argumentů k předání příkazu najednou (jako xargs)." #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Opačně" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Vstupní hodnota" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Hodnota %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Vlastní příkazy" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Spuštění uživatelských příkazů (možno v dávkách) nad skladbami s použitím " "tagů." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Upravit uživatelský příkazy" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Nelze spustit příkaz %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplicitní skupina" msgstr[1] "%d duplicitní skupiny" msgstr[2] "%d duplicitních skupin" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Sbalit / Rozbalit vše" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Duplicitní klíčový výraz je ‚%s‘" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Duplikuje prohlížeč" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Hledání a zobrazení všech podobně otagovaných verzí skladeb." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Akceptuje výrazy QL tagů jako např. <tt>~artist~title</tt> nebo " "<tt>musicbrainz_track_id</tt>." #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Seskupit duplicity podle:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplicitní klíč" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Odstranit _bílé znaky" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Odstranit _diakritiku" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Odstranit interpunkci" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Nezohledňovat _velikost písmen" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Souhlasící možnosti" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Upravit počet přehání" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Editovat ~#playcount a ~#skipcount skladby.\n" "\n" "Je-li vybráno více skladeb, počet bude pouze zvýšen, ne znovu nastaven.\n" "\n" "Je-li nastaven ~#playcount na 0, údaje ~#lastplayed a ~#laststarted budou " "resetovány. V případě, že bude nastaveno 0-play skladby na pozitivní " "hodnotu, neovlivní to délku časů přehrávání." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Počet přehrání" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Přeskočit počet" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Více %s hodnot" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Upravit vložené obrázky" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Odstranit nebo nahradit vložené obrázky." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Odstranit všechny obrázky" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Vložit aktuální obrázek" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Nastavit přesné hodnocení" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Povolit nastavení hodnocení skladeb číslem." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Použijte prosím hodnocení na škále od 0.0 do 1.0." #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Nastavit filtr" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Vytvoření dotazu hledání na základě tagů vybraných skladeb" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrovat složku" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtrovat adresář v novém okně prohlížeče." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Vyhledávání prstokladu pro akustiku" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Vyhledávání metadat skladby podle přiřazených prstokladů." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Potvrdit prstoklady pro akustiku" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Generování prstokladů s použitím chromaprintu a odeslání výsledku na " "acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Chybí API klíč" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Před schválením prstokladů je třeba mít v nastavení zásuvného modulu uveden " "API klíč pro acousticid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Vyžádání API klíče" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _klíč:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Webová služba AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Zařazeno do fronty" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Vyhodnocování" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Vyhledat" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Zapsat" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Vydání" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Zapsat tagy MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Seskupit podle složek" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Režim alba" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "Zapsat tagy a pokusit se redukovat počet různých vydání alba." #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generování prstokladů:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Pordobnosti" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Provést" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Pro pokračování jsou vyžadovány u skladeb některé z tagů: " "<i><b>musicbrainz_trackid</b></i>, nebo <i><b>artist</b></i> / <i><b>title</" "b></i> / <i><b>album</b></i>." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Prstoklady:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Skladby s MusicBrainz ID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Skladby s dostatečnými tagy:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Skladby ke schválení:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Hotovo. %(to-send)d/%(all)d skladby k potvrzení." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Potvrzování prstokladů:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Potvrzování…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "_Aktualizovat tagy souborů" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Aktualizovat změné tagy souborů. Ve výsledku budou aktualizována i všechna " "hodnocení a počet přehrání." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exportovat do HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exportovat seznam vybraných skladeb do HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Poslat do iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Nahrát skladby do zařízení iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Žádné texty nenalezeny" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Přesouvání %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Chyba během synchronizace" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Exportovat metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Exportovat metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Exportovat metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Exportovat metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Informace o čase nejsou dostupné" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Přebaly alb" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Import selhal" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importovat" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrovat složku" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Disk" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Skladba" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Umělec" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "alba" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Pokračovat" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "‚%s‘ nelze nalézt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "‚%s‘ nelze nalézt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Název souboru" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Opakovat všechny skladby" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Aktualizace seznamu grafů." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Není co aktualizovat." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Získávání grafu pro týden z %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronizace dokončena." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Chyba během synchronizace" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Synchronizace s Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Aktualizace statistik sbírky z profilu na Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Uživatel:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Vytvořit tagy pro třídění" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Převod názvu alba a umělce do jmen pro třídění, volně." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Exportovat jako seznam skladeb" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Export skladeb do M3U nebo PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Použít relativní cesty" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Použít absolutní cesty" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Zápis do <b>%s</b> selhal." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Znovu načíst skladby" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Sledování změn a podle potřeby znovunačtení nebo smazání souborů skladeb." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Znovu načíst skladby" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain analyzér" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Skladba" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Průběh" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Je zde <b>%(to-process)s</b> album k aktualizaci (of %(all)s)." msgstr[1] "Jsou zde <b>%(to-process)s</b> alba k aktualizaci (of %(all)s)l." msgstr[2] "Je zde <b>%(to-process)s</b> alb k aktualizaci (of %(all)s)." #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analýza a aktualizace informací metodou <a href=\"%(rg_link)s\">ReplayGain</" "a> (s pomocí GStreameru). Výsledky jsou slučovány podle alba." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "vždy" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "pokud <b>jakékoli</b> RG tagy chybí" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "pokud chybí RG tagy pro <b>album</b>" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Zpracovat alba:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Stávající tagy" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Rozdělit tagy" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Oddělit současně číslo disku od alba a verzi od názvu." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Rozdělit album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Oddělit číslo disku." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/a" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "_Resetovat" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Vyťukat" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Vyťukat tempo pro vybranou skladbu." #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Vyťukat tempo pro vybranou skladbu." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Vyhledávání na webu" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Prohledávání zvolených stránek s použitím jakýchkoli tagů skladeb.\n" "Podporovány jsou vzory, např. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Vyhledat URL vzory" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Upravit URL" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Konfigurovat vyhledávání…" #: quodlibet/ext/songsmenu/wikipedia.py:36 #, fuzzy msgid "Search Tag in Wikipedia" msgstr "Vyhledat album na Wikipedii" #: quodlibet/ext/songsmenu/wikipedia.py:37 #, fuzzy msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "Otevřít okno prohlížeče a zobrazit stránku o albu na Wikipedii." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Hledat na %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Upravit tagy" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Ukládání selhalo" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Sbírka" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Kontrola přípojných bodů" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Načítání sbírky" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Načítání %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Načítání souborů" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Načítání sbírky" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Odstranit aktivní fiiltry procházení" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "hudební sbírka a přehrávač" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Selhalo načítání souboru: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Seznam tagů" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Tisk stručného výpisu" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Sloupce k zobrazení a seřazení ve zkráceném režimu (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Zobrazit také programovací tagy" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Málo parametrů" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Příliš mnoho parametrů" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Popis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Hodnota" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Vypsat všechny společné tagy" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Zkopírovat tagy z jednoho souboru do druhého" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Náhled změn, zatím neprovádět" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Přeskočit tagy, které nemohou být zapsány" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Nelze zkopírovat tag %r do souboru: %r" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Editovat tagy v textovém editoru" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Editace zrušena" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Spuštění editoru '%(editor-name)s' selhalo." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Žáčné změny nenalezeny" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Nastavit tag a přepsat původní hodnoty" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Nelze zkopírovat tag %r do souboru: %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Odstranit tagy" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Hodnota je regulární výraz" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Odstranit všechny tagy" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Nelze kombinovat '--all' s '--regexp'" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Nelze odstranit %r z %r" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Odstranit hodnotu" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Přidat hodnotu" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Nelze nastavit %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Zobrazit informace o souboru" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Nastavit vybraný obrázek jako primární vložený obrázek a odstranit všechny " "ostatní vložené obrázky." #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Načítání souboru %r selhalo" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Upravování obrázků není pro %(file_name)s (%(file_format)s) podporováno." #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Odstranit všechny vložené obrázky" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrahovat z vložené obrázky do %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Cesta ke složce, kam se budou ukládat obrázky (defaultně do pracovního " "adresáře)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Přejmenovat soubory podle tagů" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Vyplnit tagy podle cest k souborům" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Soubor" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Vyplnit čísla skladeb u všech souborů" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Vytisknout tagy podle zadaného vzoru" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Zobrazit informace o pomoci" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' není platné jméno sloupce (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Neznámé" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "V pořadí" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_V pořadí" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Náhodně" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Náhodně" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Přednostně lépe hodnocené" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Přednostně lépe hodnocené" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Opakovat skladbu" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Opakovat skladbu" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Opakovat všechny" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Opakovat všechny" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Jedna skladba" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Jedna skladba" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Načítání do vyrovnávací paměti" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Nelze vytvořit rouru GStreameru" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Pro obsluhu tohoto formátu nebyl nalezen žádný element GStreameru" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Formát média: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Zásuvný modul GStreameru '%(name)s' se nepodařilo inicializovat." #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Roura výstupu GStreameru používaná pro přehrávání. Nechte prázdné pro " "použití výchozí roury. Pokud roura obsahuje sink, bude použit místo " "defaultního." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Výstupní roura:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Délka mezipaměti:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Zakázat přehrávání _bez mezer" #: quodlibet/player/gstbe/prefs.py:71 #, fuzzy msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Zakázání přehrávání bez mezer může s některými verzemi GStreameru předejít " "problémům s přechody mezi skladbami." #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "GStreamer audio sink nenalezen" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Neplatná výstupní roura GStreameru." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Nelze vytvořit audio výstup." #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Zařízení %r nenalezeno. Zkontrolujte nastavení Xine v ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Nelze najít modul '{module}'. Možná bude nutné doinstalovat balík." #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nelze najít element '{element}' GStreameru." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Pro nastavení QLSCrobbleru otevřete okno Zásuvních modulů. Do té doby " "nebudou informace o skladbách odesílány." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Pro nastavení QLSCrobbleru otevřete okno Zásuvních modulů. Do té doby " "nebudou informace o skladbách odesílány." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Odeslání" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Jméno:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" "Informace o skladbách odpovídajících zadanému filtru nebudou odesílány." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Spustit zásuvný modul „%(name)s“ pro %(count)s seznam skladeb?" msgstr[1] "Spustit zásuvný modul „%(name)s“ pro %(count)s seznamy skladeb?" msgstr[2] "Spustit zásuvný modul „%(name)s“ pro %(count)s seznamů skladeb?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Spuarir zásuvný modul" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Začátek" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Čas" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Název záložky" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Záložky" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtry" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "_Nedávno hrané" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Nedávno _Přidané" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Všechny _skladby" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Podle právě přehrávaného žánru(ů)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Podle právě přehrávaného _umělce/ů" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Podle právě přehrávaného al_ba" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Náhodný _Žánr" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Náhodný Umělec" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Náhodné al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 skladeb, které jste poslouchali nejvíc (více než 40 jich může být vybráno " "také)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Jméno:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Hodnota:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Uložené hodnoty" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Upravit uložené hodnoty..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_maticky" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Režim skladby" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Režim alba" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Ztlumit" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain mód" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nový %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(neznámé)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Přidat" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Upravit" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Výraz tagu" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Výraz tagu, např. people:real nebo ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Vložit nový tag" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Výraz tagu" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Soubory:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Vybrané skladby budou odstraněny ze sbírky a smazány z disku." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Vybrané soubory budou smazány z disku." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Smazat %(file_count)d soubor navždy?" msgstr[1] "Smazat %(file_count)d soubory navždy?" msgstr[2] "Smazat %(file_count)d souborů navždy?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Smazat soubory" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Vybrané skladby budou odstraněny ze sbírky a jejich soubory budou odstraněny " "do koše." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Vybrané soubory budou přesunuty do koše." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Přesunout %(file_count)d soubor do koše?" msgstr[1] "Přesunout %(file_count)d soubory do koše?" msgstr[2] "Přesunout %(file_count)d souborů do koše?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Přesunout do koše" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Přesouvání %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Nelze přesunout do koše" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Přesouvání jednoho nebo více souborů do koše selhalo." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Mazání %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Soubory nezle smazat" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Odstraňování jednoho nebo více souborů selhalo." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Prohlížeče" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Stáhnout soubory" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "chybí u %d skladby" msgstr[1] "chybí u %d skladeb" msgstr[2] "chybí u %d skladeb" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "liší se u %d skladby" msgstr[1] "liší se u %d skladeb" msgstr[2] "liší se u %d skladeb" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Rozdělit do _Více položek" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Oddělit disk od _Alba" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Oddělit _Verzi od názvu" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Oddělit aranžmá od Umělce" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Oddělit _Interpreta od umělce" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Oddělit _Interpreta od názvu" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Oddalit _Původního umělce od názvu" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Přidat tag" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Ukázat _" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Používat všechny tagy včetně strojově generovaných, jako jsou např. " "MusicBrainz tegy nebo tagy Úpravy hlasitosti" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Ukázat _" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Obrátit pořadí" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Uložit" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Pokračovat" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Rozdělit tagy" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Kopírovat _obaly alb" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Tag nelze přidat" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Nelze přidat skladby" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Vybrané soubory nepodporují zadávání více položek pro <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Neplatný tag" msgstr[1] "Neplatný tag" msgstr[2] "Neplatný tag" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Neplatný tag %s\n" "\n" "Vybrané soubory nepodporují označení tímto tagem." msgstr[1] "" "Neplatný tag %s\n" "\n" "Vybrané soubory nepodporují označení tímto tagem." msgstr[2] "" "Neplatný tag %s\n" "\n" "Vybrané soubory nepodporují označení tímto tagem." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Neplatná hodnota" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Neplatná hodnota: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tag nemusí být správně" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s se za běhu programu změnily. Uložení bez obnovení sbírky " "(refresh) by mohlo přepsat jiné změny." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Skladbu nelze uložit" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Ukládání%(file-name)s selhalo. Soubor může být jen pro čtení, poškozený, " "nebo nemáte právo ho měnit." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Více možností..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Krok zpět" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Znovu provést změny" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_O Quod Libet" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Zkontrolovat aktualizace…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Zásuvné moduly" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s a %(count)s více" msgstr[1] "%(title)s a %(count)s více" msgstr[2] "%(title)s a %(count)s více" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Nastavení Ex Falsa" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Složky" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nová složka…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Vybrat všechny podsložky" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nová složka" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Jméno nové složky:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Složku nelze vytvořit" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Složku nelze smazat" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Skladby" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "podle %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Skladba %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "Podle právě přehrávaného žánru(ů)" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Upravit zobrazení…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nejsou vybrány žádné skladby." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Žádné skladby." #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informace" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Texty" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Vydáno %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "umělec" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "umělci" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "interpreti" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nikdy" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)dkrát" msgstr[1] "%(n)dkrát" msgstr[2] "%(n)dkrát" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "přidáno" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "naposledy hrané" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "přehrání" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "přeskočení" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "hodnocení" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "cesta" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "délka" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formát" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "kódování" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "velikost souboru" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "naposledy změněno" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Dodatečné" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d vybrána" msgstr[1] "%d vybrány" msgstr[2] "%d vybráno" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Skladba je nedostupná" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d skladba mimo alba" msgstr[1] "%d skladby mimo alba" msgstr[2] "%d skladeb mimo alba" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Vybraná diskografie" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d skladba bez umělce" msgstr[1] "%d skladby bez umělce" msgstr[2] "%d skladeb bez umělce" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "alba" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Celková delka:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Celková velikost" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Soubory" #: quodlibet/qltk/lyrics.py:34 #, fuzzy msgid "_View online" msgstr "online" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Ke skladbě nebyly nalezeny žádné texty." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Jste si jistí, že chcete odstranit všecny skladby?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Vybrané soubory budou odstraněny ze sbírky." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Odkrýt" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Odkrýt" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Zahodit změny v tagu?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tagy byly změněny, ale nebyly uloženy. Přejete si změny uložit, nebo zahodit?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Obrátit" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Soubor existuje" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Nahradit %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Nahradit soubor" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktivní úlohy" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d úlohy běží" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Prohodit mód promíchání" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Prohodit mód opakování" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Události" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Pořadí přehrávání:" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Úpravy" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Přejmenovat" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Dotaz:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Přebaly" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Chyby zásuvného modulu" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Povoleno" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Zakázáno" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Žádná kategorie" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Žádná kategorie" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nebyly nalezeny žádné zásuvné moduly." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Zásuvné moduly" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Ukázat _Chyby" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Skladba" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "_Sloučit" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Umělec" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Název souboru" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Délka" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Rovnou automaticky přehrávat skladbu" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Když se přehrávaná skladba změní, najet na ni v přehledu skladeb" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Ostatní:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Upravit..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Přidat nebo odstranit hlavičky sloupců" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Viditelné položky" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Název obsahuje _verzi" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album obsahuje podnázev _disku" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Umělec obsahuje všechny tvůrce" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Název souboru obsahuje_složku" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Nastavení sloupce" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Upravit sloupce" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "Použít coučasné nastavení pro seznam skladeb, nové sloupce na konec" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Seznam skladeb" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Upravit sloupce" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Celková délka" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globální filtr:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Použít tento dotaz spolu s ostatními" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Vyhledávání" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Prohlížeče" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Potvrdit _hromadné hodnocení" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Zeptat se na souhlas před změnou hodnocení u více skladeb najednou" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Povolit hodnocení _jedním klikem" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Povolit hodnocení kliknutím na kolonku hodnocení v seznamu skladeb" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Hodnocení" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Upřednostnit _vložené grafiky alb" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Upřednostit náhledy přebalů vložené přímo do souborů (pokud lze) před " "ostatními zdroji" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Fixní název souboru obrázku:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Přebaly alb" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Přehrávání" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Nastavení výstupu" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Jestliže není informace o úpravě hlasitosti pro tuto skladbu dostupná, " "upravit hlasitost na tuto hodnotu" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Vyrovnání hlasitosti (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Upravit hlasitost podle této hodnoty pro všechny skladby, pokud nedojde ke " "snížení kvality." #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Předzesílení (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Povolit úpravu hlasitosti" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Úprava hlasitosti" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Výchozí hodnocení:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Stupnice h_odnocení:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Faktor Bayesovského průměru (C) pro sčítaná hodnocení.\n" "0 znamená běžný průměr, vyšší hodnoty pak znamenají, že album s méně " "skladbami bude mít menší, hladší odchylky v hodnocení.\n" "Změna této hodnoty spustí přepočítávání pro všechna alba!" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Hodnota _Bayesovského průměru:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Hodnocení a počet přehrání budou nastaveny pro tuto emailovou adresu" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Automaticky ukládat změny tagů" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Uložit změny tagů bez potvrzení v případě úpravy více tagů najednou" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Seznam oddělovačů pro rozdělování hodnot tagů. Položky jsou odděleny mezerou." #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Rozdělit _v:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Seznam oddělovačů pro rozdělování hodnot tagů. Položky jsou odděleny mezerou." #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Rozdělit _v:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tagy" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Úprava tagů" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Aktualizace nových hodnocení" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Načíst sbírku" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Zkontrolovat změny ve sbírce" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "_Znovu načíst sbírku" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Znovu načíst všechny skladby ve sbírce (může to trvat pár minut)." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Skryté skladby" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Načíst sbírku vždy při _startu" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Pohledávat složky" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s a %(count)d více" msgstr[1] "%(title)s a %(count)d více" msgstr[2] "%(title)s a %(count)d více" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Vlastnosti" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Fronta" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Vyčistit frontu" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Obecné" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Odstranit všechny skladby z fronty" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Model:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d skladba (%(time)s)" msgstr[1] "%(count)d skladby (%(time)s)" msgstr[2] "%(count)d skladeb (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Procházet sbírku" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Přepnout viditelnost fronty" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Chyba přehrávání" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Nastavit složky sbírky?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" "Zatím nemáte nastavenu žádnou hudební sbírku. Přejete si ji nastavit teď?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Ne teď" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Nastavení" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Nelze přidat skladby" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s používá nepodporovaný protokol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Skočit na přehrávanou skladbu" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Soubor" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Skladba" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Zobrazení" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Procházet" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Ovládání" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Pomoc" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Přidat složku..." #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Přidat soubor..." #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Přidat umístění…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Upravit záložky..." #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Stop" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Po této skladbě zastavit přehrávání" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Klávesové zkratky" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Online pomoc" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Hledat pomoc" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Přidat umístění" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Zadejte umístění zvukového souboru:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Umístění nelze přidat" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s není platné umístění." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Přidat hudbu" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Přidat složky" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Hudební soubory" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Přidat soubory" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Jste si jistí, že chcete odstranit všecny skladby?" msgstr[1] "Jste si jistí, že chcete odstranit všecny skladby?" msgstr[2] "Jste si jistí, že chcete odstranit všecny skladby?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Fronta" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Jste si jistí, že chcete změnit hodnocení u všech %d skladeb?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Uložená hodnocení budou odstraněna" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Odstranit hodnocení" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Hodnocení u všech vybraných skladeb bude změněno na ‚%s‘" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Změnit _hodnocení" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Nahradit mezery _podtržítky" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Nahradit znaky nekompatibilní s _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Nahradit _diakritiku" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Nahradit ne-_ASCII znaky" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Použít jen _malá písmena" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Přejmenovat soubory" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Náhled" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Název souboru" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "umělec alba" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Odstranit nepoužívané přebaly a složky" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Přebaly alb" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nový název" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Soubor nelze přejmenovat" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Přejmenovávání <b>%(old-name)s</b> na <b>%(new-name)s</b> selhalo. Cílový " "soubor už možná existuje, nebo nemáte právo soubory vytvářet ani měnit." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorovat _všechny chyby" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stop" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Pokračovat" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Uvedená cesta není absolutní" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Vzor\n" "\t%s\n" "obsahuje / , ale nezačíná od kořene (root). Pro vyhnutí se nepojmenovaným " "složkám upravte vzor root tak, aby začínal / nebo ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Skladby v uvedených složkách budou přidány do sbírky při obnově (refresh)" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Vybrané soubory budou odstraněny ze sbírky." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Odstraňování nezařazené skladby z iPodu" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Cesta ke sbírce:" msgstr[1] "Cesta ke sbírce:" msgstr[2] "Cesta ke sbírce:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "Odstranit" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Vybrané složky" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Vybrané složky" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Uložené hodnoty" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Upravit uložená vyhledávání…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Prohledávání sbírky s použitím čistého textu nebo QL dotazů" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Hledat po _psaní" #: quodlibet/qltk/searchbar.py:148 #, fuzzy msgid "Show search results after the user stops typing" msgstr "Ukázat výsledky hledání až když uživatel přestane psát." #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limit:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Váha" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "dotaz" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Zobrazit zbývající čas" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hlavní okno" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Procházet zpět po 10 vteřinách" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Procházet vpřed po 10 vteřinách" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Zaměřit na vyhledávané" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Resetovat filtry a přejít na přehrávanou skladbu" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Otevřít informační okno k vybraným skladbám." #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Otevřít editor tagů pro vybrané skladby" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Zařadit vybrané skladby do fronty" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Smazat vybrané skladby" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Zobrazit hodnotu řádkového hledání" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Levý klik na hlavičku sloupce" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Přidat sloupec do seznamu sloupců k setřídění" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Struktura složek" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Sbalí prvek nebo vybere prvek rodičovský" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Rozbalí element" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Texty" #: quodlibet/qltk/shortcuts.py:41 #, fuzzy msgid "Undo the last change" msgstr "Znovu provést změnu" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Znovu provést změnu" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Vybrat všechny skladby ve všech panelech." #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtr na %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Všechny _Hlavičky" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Hlavičky _Skladeb" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Hlavičky _Alb" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Hlavičky _Lidí" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Hlavičky _Dat" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Hlavičky _Souborů" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Hlavičky _Produkce" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Upravit hlavičky..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Rozšířit sloupec" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Odstranit ze sbírky" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Odstranit ze sbírky" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Odstranit ze sbírky" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Spustit zásuvný modul \"%(name)s\" pro %(count)d skladbu?" msgstr[1] "Spustit zásuvný modul \"%(name)s\" pro %(count)d skladby?" msgstr[2] "Spustit zásuvný modul \"%(name)s\" pro %(count)d skladeb?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Spustit modul \"%(name)s\" pro %(count)d album?" msgstr[1] "Spustit modul \"%(name)s\" pro %(count)d alba?" msgstr[2] "Spustit modul \"%(name)s\" pro %(count)d alb?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Nastavit zásuvné moduly…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Přidat do _Fronty" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Odstranit ze sbírky" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Soubory nezle smazat" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Stahování…" msgstr[1] "_Stahování…" msgstr[2] "_Stahování…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Ukládání selhalo" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Stáhnout soubor" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Stáhnout přebal" msgstr[1] "Stáhnout přebal" msgstr[2] "Stáhnout přebal" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Stáhnout soubor" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Nahradit _podtržítka mezerami" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Tagy Kapitálkami" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Rozdělit do více _hodnot" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tagy z cesty" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Nahradit existující tagy" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tagy jsou přidány k již existujícím" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Vzor\n" "\t%s\n" "je neplatný. Možná obsahuje duplicitní tag nebo nemá uzavřené závorky " "(< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Zadaný vzor je neplatný. Ujistětě se, že vkládáte < a > jako \\< a " "\\> a že jsou vaše tagy v pořádku.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Upravit zobrazení" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Čísla skladeb" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Začít _od:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Celkem skladeb:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Přehrávat/Pauza" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Předchozí" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "a %d více..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Ukládání změněných skladeb." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d skladeb uloženo\n" "(%(remaining)s zbývá)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s z %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Kontrola aktualizací" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Připojení selhalo" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Používáte aktuální verzi %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Je dostupná nová verze %(new-version)s\n" "\n" "Současná verze je %(old-version)s\n" "\n" "Navštívit <a href='%(url)s'>stránku</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importovat seznam skladeb" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Seznam skladeb musí mít jméno" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Seznam skladeb s názvem %s již existuje." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Vložené přebaly alb" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Používají se přebaly alb vložené přímo do souborů." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Přebal ze systému souborů" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Použití tradičně pojmenovaných souborů obrázků nalezených v adresářích " "uvnitř adresářů alb." #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Mřížka přebalů alb" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Zobrazit stručné info o využití" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Zobrazit verzi a copyright" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Zobrazit informace o souboru" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Využití: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[možnosti]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Volba %r nerozpoznána." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Volba %r vyžaduje parametry." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r není jedinečný prefix." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s vteřina" msgstr[1] "%s vteřiny" msgstr[2] "%s vteřin" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Informace o čase nejsou dostupné" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d vteřina" msgstr[1] "%d vteřiny" msgstr[2] "%d vteřin" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuta" msgstr[1] "%d minuty" msgstr[2] "%d minut" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hodina" msgstr[1] "%d hodiny" msgstr[2] "%d hodin" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d den" msgstr[1] "%d dny" msgstr[2] "%d dnů" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d rok" msgstr[1] "%d roky" msgstr[2] "%d let" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "Všude první velké?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datum musí být vloženo ve formátu 'YYYY', 'YYYY-MM-DD' nebo 'YYYY-MM-DD HH:" "MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Úprava hlasitosti musí být zadána ve formátu 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Nejvyšší hodnoty úpravy hlasitosti musí být zadány ve formátu 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "ID MusicBrainzu musí být ve formátu UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "Status MusicBrainz musí být 'official', 'promotional', nebo 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Jazyk musí být ISO 639-2 trojpísmenný kód" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Ukládání selhalo" msgstr[1] "Ukládání selhalo" msgstr[2] "Ukládání selhalo" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Skladbu nelze upravit" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Ukládání %s selhalo. Soubor může být jen pro čtení, poškozený, nebo nemáte " "právo ho měnit." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Neplatné kódování]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranžmá" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranžmá" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "uspořádání" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autoři" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "příkaz" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "skladatel" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "skladatelé" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "skladatel" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenti" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigent" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "rok" #: quodlibet/util/tags.py:94 msgid "description" msgstr "popis" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "žánr" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "žánry" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "interpret" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "interpret" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "slučování" #: quodlibet/util/tags.py:98 msgid "language" msgstr "jazyk" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licence" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "texty" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "textaři" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "texty" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizace" #: quodlibet/util/tags.py:104 msgid "title" msgstr "název" #: quodlibet/util/tags.py:105 msgid "version" msgstr "verze" #: quodlibet/util/tags.py:106 msgid "website" msgstr "webová stránka" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "umělec alba" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "podnázev disku" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "skladba" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "ID labelu" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "datum původního vydání" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "původní album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "původní umělec" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "datum nahrávání" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "země vydání" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "ID skladby na MusicBrainz" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "ID vydání na MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID vydání na MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "ID umělce na MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "ID umělce vydání na MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "ID TRM na MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Status alba na MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Typ alba na MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "ID skupiny vydání na MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "úprava hlasitosti skladby" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "nejvyšší hodnota u skladby" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "úprava hlasitosti alba" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "nejvyšší hodnota u alba" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "určující hlasitost" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "disky" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "skladby" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "poslední start" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "celé jméno" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "přípojný bod" #: quodlibet/util/tags.py:166 msgid "people" msgstr "lidé" #: quodlibet/util/tags.py:168 msgid "year" msgstr "rok" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "rok původního vydání" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "záložka" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "formát souboru" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "Seznamy skladeb" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "počet kanálů" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "řadit" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "role" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor tagů" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Editovat tagy skladeb" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Ukončit Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Přehrávač hudby" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Poslouchejte, procházejte nebo upravujte svou hudební sbírku" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso je editor tagů s uživatelským rozhraním stejným jako editor tagů v " "Quod Libet. Umožňuje zobrazit a upravovat jakékoli tagy v souboru, a to pro " "všechny podporované formáty." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Podporované formáty souborů jsou Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/" "XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet je program pro správu hudby (audia obecně). Nabízí mnoho způsobů " "zobrazení hudební sbírky stejně jako podporu interenetových rádií a " "audiostreamů. Zároveň je skvěle vybaven pro úpravy metadat a jejich " "prohledávání." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Exportovat seznam skladeb pro Squeezebox" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Nelze přidat <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Neplatné tagy" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Neplatné tagy %s\n" #~ "\n" #~ "Vybrané položky nepodporují vkládání těchto tagů." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Automatické hodnocení skladeb, které jsou přeskočeny nebo přehrány. " #~ "Používá se ‚urychlený‘ algorytmus z vux od Briana Nelsona." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f vteřin" #, fuzzy #~ msgid "Startup" #~ msgstr "Spustit import" #~ msgid "Audio Feeds" #~ msgstr "Audio zdroje" #~ msgid "_Audio Feeds" #~ msgstr "_Audio zdroje" #, fuzzy #~ msgid "New" #~ msgstr "_Nový" #~ msgid "Automatic Library Update" #~ msgstr "Automatické obnovení spírky" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Udržovat sbírku aktuální pomocí inotify. Vyžaduje %s." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Umožňuje kontrolu Quod Libet s použitím MPRIS 1.0/2.0 D-Bus specifikace " #~ "rozhraní." #~ msgid "Searching for lyrics…" #~ msgstr "Hledání textů..." #, fuzzy #~ msgid "broker username" #~ msgstr "Hostname zprostředkovatele" #, fuzzy #~ msgid "broker password" #~ msgstr "port zprostředkovatele" #, fuzzy #~ msgid "<artist>" #~ msgstr "umělec" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "název" #, fuzzy #~ msgid "OK" #~ msgstr "_OK" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Export metadata vybraných skladeb jako soubor .tags." #~ msgid "Import Metadata" #~ msgstr "Importovat metadata" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Import metadat ze souboru .tags pro vybrané skladby." #~ msgid "Migrate Metadata" #~ msgstr "Přenést metadata" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Zkopírovat pro Quod Libet specifická metadata mezi skladbami." #~ msgid "_Copy" #~ msgstr "_Kopírovat" #~ msgid "_Paste" #~ msgstr "_Vložit" #~ msgid "Information to copy/paste" #~ msgstr "Informace ke zkopírování/vložení" #~ msgid "Map tracks by disc and track number" #~ msgstr "Mapovat skladby podle čísla disku a pořadového čísla skladby" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Povolte v případě, že chcete přenést metadata z jednoho alba do druhého " #~ "na základě shody čísel disku a skladeb.\n" #~ "\n" #~ "<b>Pozor:</b> tato volba musí být povolena, když jsou metadata kopírována " #~ "k uložení." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Je zde %d uložená skladba." #~ msgstr[1] "Jsou zde %d uložené skladby." #~ msgstr[2] "Je zde %d uložených skladeb." #~ msgid "Unsupported file type" #~ msgstr "Nepodporovaný formát souboru" #~ msgid "Unable to add station" #~ msgstr "Nelze přidat stanici" #~ msgid "_Wide Mode" #~ msgstr "Ši_roký mód" #~ msgid "Search Library" #~ msgstr "Prohledávat sbírku" #~ msgid "_Search Library" #~ msgstr "_Hledat ve sbírce" #~ msgid "Rate the playing song" #~ msgstr "Ohodnotit přehrávanou skladbu" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Zobrazit nebo skrýt hlavní seznam skladeb (zastaralé)" #~ msgid "Quit Program" #~ msgstr "Zavřít program" #~ msgid "Top of screen" #~ msgstr "Nahoru" #~ msgid "Middle of screen" #~ msgstr "Uprostřed" #~ msgid "Bottom of screen" #~ msgstr "Dolů" #~ msgid "_Clear" #~ msgstr "_Vyčistit" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "Zabraňuje spořiči GNOME v aktivování pokud se přehrává skladba." #~ msgid "_Zoom level:" #~ msgstr "_Úroveň přiblížení:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Hledat přes uvedené URL, jestliže nelze texty dohledat na LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternativní hledání" #, fuzzy #~ msgid "Web Lyrics" #~ msgstr "Zobrazit texty" #, fuzzy #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "Zobrazení okna s textem právě přehrávané skladby." #~ msgid "Skip Songs" #~ msgstr "Přeskočit skladby" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Přehrávání přeskočí skladby s hodnocením stejným nebo nižším, než je " #~ "nastavený práh." #~ msgid "Browse Folders" #~ msgstr "Procházet složky" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Otevření složky umístění skladby ve správci složek." #~ msgid "Unable to open folders" #~ msgstr "Složky nelze otevřít" #~ msgid "No program available to open folders." #~ msgstr "Pro otevírání složek není dostupný žádný program." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Podpora QL vzorů\n" #~ "\vnapř. <tt><~artist~title>></tt>" #~ msgid "Fix MP3 Duration" #~ msgstr "Opravit trvání MP3" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Odstranění TLEN rámců z ID3 tagů, mohou být důvodem špatného údaje o " #~ "trvání skladeb." #~ msgid "Burn CD" #~ msgstr "Vypálit CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Vypálení CD s K3b, Braserem nebo xfburn." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Vyhledat umělce na Wikipedii" #~ msgid "" #~ "Opens a browser window with Wikipedia article on the playing song artist." #~ msgstr "" #~ "Otevřít okno prohlížeče a zobrazit článek o umělci přehrávané skladby na " #~ "Wikipedii." #~ msgid "The single image filename to use if selected" #~ msgstr "Použít jméno obrázku, pokud je vybrán" #~ msgid "The album art image file to use when forced" #~ msgstr "Použít soubor grafiky alba vynuceně" #~ msgid "Stop Once Empty" #~ msgstr "Zastavit, pokud je prázdné" #~ msgid "Vertical Split" #~ msgstr "Vertikální rozdělení" #~ msgid "Device Properties" #~ msgstr "Vlastnosti zařízení" #~ msgid "Device:" #~ msgstr "Zařízení:" #~ msgid "Not mounted" #~ msgstr "Není připojeno" #~ msgid "Mount point:" #~ msgstr "Přípojný bod:" #~ msgid "Media Devices" #~ msgstr "Zařízení s médii" #~ msgid "_Media Devices" #~ msgstr "_Zařízení s médii" #~ msgid "_Eject" #~ msgstr "_Vysunout" #~ msgid "_Properties" #~ msgstr "_Vlastnosti" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s je využito,%(free-size)s je k dispozici" #~ msgid "%s is not connected." #~ msgstr "%s není připojeno." #~ msgid "Copying %(song)s" #~ msgstr "Kopírování %(song)s " #~ msgid "Unable to copy song" #~ msgstr "Skladbu nelze kopírovat" #~ msgid "There is not enough free space for this song." #~ msgstr "Pro tuto skladbu již není dost místa." #~ msgid "%s could not be copied." #~ msgstr "%s nelze zkopírovat." #~ msgid "Unable to delete songs" #~ msgstr "Skladby nelze smazat" #~ msgid "Deleting %(song)s" #~ msgstr "Odstraňování %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s nelze odstranit." #~ msgid "Unable to delete song" #~ msgstr "Skladbu nelze smazat" #~ msgid "Ejecting %s failed." #~ msgstr "Vysunutí %s selhalo." #~ msgid "Unable to eject device" #~ msgstr "Zařízení nelze vysunout" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Nenalezena obslužná aplikace, prohlížeč mediálních zařízení zakázán." #~ msgid "Unknown Device" #~ msgstr "Neznámé zařízení" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Nemohu importovat %s, což je třeba pro podporu zařízení." #~ msgid "%r is not a supported device." #~ msgstr "%r není podporované zařízení." #~ msgid "Initializing device backend." #~ msgstr "Načítání zařízení." #~ msgid "Trying '%s'" #~ msgstr "Zkoušení ‚%s‘" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Nelze se připojit k obslužné aplikaci zařízení." #~ msgid "Device backend initialized." #~ msgstr "Zařízení načteno." #~ msgid "_Filename pattern:" #~ msgstr "_Vzor názvu souborů:" #~ msgid "File Bug Report" #~ msgstr "Soubor zprávy o chybě" #~ msgid "Lyrics:" #~ msgstr "Texty:" #~ msgid "Lyrics Window" #~ msgstr "Okno textů" #~ msgid "_Lyrics" #~ msgstr "_Texty" #~ msgid "" #~ "Use Python expressions in queries. Syntax is '@(python: expression)'. The " #~ "variable 's' is the song being matched." #~ msgstr "" #~ "V dotazech používejte syntaxi z Pythonu. Syntaxe je '@(python: " #~ "expression)', přičemž proměnná 's' je název skladby." #~ msgid "Audio device: %s" #~ msgstr "Zvukové zařízení: %s" #~ msgid "Downloads" #~ msgstr "Stažené" #~ msgid "Size" #~ msgstr "Velikost" #~ msgid "_Download" #~ msgstr "_Stahování" #~ msgid "_Copy to Device" #~ msgstr "_Kopírovat do zařízení" #~ msgid "Save" #~ msgstr "Uložit" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Nelze importovat %s. Prohlížeč zdrojů zakázán." #~ msgid "Audio Backend Failed to Load" #~ msgstr "Načtení obslužné aplikace na pozadí selhalo" #~ msgid "" #~ "Loading the audio backend '%(name)s' failed. Audio playback will be " #~ "disabled." #~ msgstr "" #~ "Načítání obslužných aplikací '%(name)s' na pozadí selhalo. Přehrávání " #~ "audia nebude fungovat." #~ msgid "_Open" #~ msgstr "_Otevřít" #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "V aplikaci Quod Libet došlo k výjimce. Zpráva o ní byla uložena do<b >" #~ "%(dump-path)s</b>, může pomoci závadu odstranit. Prosíme, ohlašte ji na " #~ "%(new-issue-url)s a uvedenou zprávu přiložte, nebo vložte přímo její " #~ "obsah. Soubor se zprávou může obsahovat informace o vás nebo vašem " #~ "systému, jako například seznam naposled hraných skladeb. Pokud je to pro " #~ "vás nepřijatelné, pošlete místo toho <b>%(mini-dump-path)s</b> s popisem, " #~ "co jste právě dělali." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "Quod Libet může být nyní nestabilní. Doporučujeme jej restartovat. Vaše " #~ "sbírka bude uložena." #~ msgid "Disable Browser" #~ msgstr "Zakázat prohlížeč" #~ msgid "_Disable Browser" #~ msgstr "_Zakázat prohlížeč" #~ msgid "Set or toggle the playback order" #~ msgstr "Nastavit nebo přepnout pořadí přehrávání" #~ msgid "Uninitialized iPod" #~ msgstr "Nenačtený iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Chcete vytvořit pro tento iPod prázdnou databázi?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Úprava _Hlasitosti (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "_Kombinovat tagy s více hodnotami" #~ msgid "Capacity:" #~ msgstr "Kapacita:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Saving iPod database…" #~ msgstr "Ukládání iPod databáze…" #~ msgid "Unable to save iPod database" #~ msgstr "Nelze uložit iPod dazabázi" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Nelze najít libgpod, podpora iPodu zakázána." #~ msgid "Controls the tone of your music with an equalizer." #~ msgstr "Kontroluje zabarvení hudby ekvalizérem." #~ msgid "Use header bars" #~ msgstr "Použít hlavičky" #~ msgid "tooltip" #~ msgstr "tooltip" #~ msgid "Event Logging" #~ msgstr "Záznam o události" #~ msgid "Sends song events to the Zeitgeist event logging service." #~ msgstr "Zasílání události skladeb do logovací služby Zeitgeist." #~ msgid "Playback follows your selection." #~ msgstr "Přehrávání následuje výběr." #~ msgid "Track Repeat" #~ msgstr "Opakovat skladbu" #~ msgid "Force Write" #~ msgstr "Vynutit zápis" #~ msgid "Filter on _Genre" #~ msgstr "Filtrovat podle _Žánru" #~ msgid "Filter on _Artist" #~ msgstr "Filtrovat podle _Umělce" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrovat podle alba" #~ msgid "Unable to download lyrics." #~ msgstr "Nelze stáhnout texty skladby." #~ msgid "Shuffle" #~ msgstr "Zamíchat" #~ msgid "Weighted" #~ msgstr "Vyváženo" #~ msgid "_Weighted" #~ msgstr "_Vyváženo" #~ msgid "_One Song" #~ msgstr "_Jedna skladba" #~ msgid "Restart the playlist when finished" #~ msgstr "Začít znovu přehrávat po přehrání seznamu skladeb" #~ msgid "_Music" #~ msgstr "_Hudba" #~ msgid "Add Bookmark" #~ msgstr "Přidat záložku" #~ msgid "Song _List" #~ msgstr "Se_znam skladeb" #~ msgid "Rate the selected songs with 0-4 stars" #~ msgstr "Hodnotit vybrané skladby 0–4 hvězdičkami" #~ msgid "Embed cover" #~ msgstr "Přiložit přebal" #~ msgid "D:" #~ msgstr "D:" #~ msgid "W:" #~ msgstr "W:" #~ msgid "E:" #~ msgstr "E:" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Po této skladbě zastavit přehrávání" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "a %d více..." #~ msgstr[1] "a %d více..." #~ msgstr[2] "a %d více..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Oddělit disk od _Alba" #, fuzzy #~ msgid "Timeout" #~ msgstr "Čas" #, fuzzy #~ msgid "Select an album" #~ msgstr "Vybrat _vše" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s a %(count)d více" #~ msgstr[1] "%(title)s a %(count)d více" #~ msgstr[2] "%(title)s a %(count)d více" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Seznamy skladeb" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Použít v náhledech zaoblené rohy" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Zakulacení rohů u náhledů přebalů. Může to vyžadovat restart přehrávače." #~ msgid "Re_fresh Library" #~ msgstr "Obnovit sbírku" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Odstranění duplicit" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer nemá parametr pro čtení souborů. Zkontrolujte nastavení " #~ "instalace." #~ msgid "Invalid audio backend" #~ msgstr "Neplatná oblužná aplikace" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "Obslužná aplikace %r není nainstalována." #~ msgid "command|filename" #~ msgstr "příkaz | název souboru" #~ msgid "command|tag" #~ msgstr "příkaz | tag" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: %s nelze nalézt." #, fuzzy #~ msgid "heading|Search" #~ msgstr "heading|Vyhledávání" #~ msgid "%d of %d" #~ msgstr "%d z %d" #~ msgid "Usage: %s %s\n" #~ msgstr "Využití: %s %s\n" #~ msgid "_Download..." #~ msgstr "_Stahování ..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nová stanice" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Přepsat <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Chyba výstupu" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Výstupní roura GStreameru nemohla být načtena. Roura je možná neplatná, " #~ "nebo může být zařízení používáno. Zkontrolujte nastavení přehrávače." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet už běží." #~ msgid "No song is currently playing." #~ msgstr "Nyní se nic nepřehrává." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Nelze zapisovat do %s. Odstraňuji." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Upravit záložky..." #~ msgid "_New Folder..." #~ msgstr "_Nová složka..." #~ msgid "_Add to Playlist" #~ msgstr "_Přidat do seznamu skladeb" #~ msgid "_Edit Display..." #~ msgstr "_Upravit zobrazení..." #~ msgid "Output Log" #~ msgstr "Log výstupu" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stanice" #~ msgid "_Add a Location..." #~ msgstr "_Přidat umístění..." #~ msgid "_Output Log" #~ msgstr "_Log z výstupu" #~ msgid "Invalid command %r received." #~ msgstr "Zadán neplatný příkaz %r." #~ msgid "Unknown browser %r." #~ msgstr "Neznámý prohlížeč %r." #~ msgid "Custom _Sort..." #~ msgstr "Vlastní _Třídění..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "Jste si jistí, že chcete změnit hodnocení u všech %d skladeb?" #~ msgstr[1] "Jste si jistí, že chcete změnit hodnocení u všech %d skladeb?" #~ msgstr[2] "Jste si jistí, že chcete změnit hodnocení u všech %d skladeb?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "Jste si jistí, že chcete odstranit %d duplikátní skladbu?" #~ msgstr[1] "Jste si jistí, že chcete odstranit %d duplikátní skladby?" #~ msgstr[2] "Jste si jistí, že chcete odstranit %d duplikátních skladeb?" #~ msgid "Track Headers" #~ msgstr "Hlavičky skladeb" #~ msgid "People Headers" #~ msgstr "Hlavičky lidí" #~ msgid "Album Headers" #~ msgstr "Seznam alb" #~ msgid "Date Headers" #~ msgstr "Hlavičky dat" #~ msgid "File Headers" #~ msgstr "Složky" #~ msgid "Production Headers" #~ msgstr "Hlavičky produkce" #~ msgid "Tag:" #~ msgstr "_Tag:" #~ msgid "Descending" #~ msgstr "Klesání" #~ msgid "Too Many Errors" #~ msgstr "Příliš mnoho chyb." #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Zastavuji přehrávání, protože se vyskytlo %d chyb za sebou." #~ msgid "Warnings" #~ msgstr "Varování" #~ msgid "No log available." #~ msgstr "Není dostupný žádný výstup." #~ msgid "album artist (sort)" #~ msgstr "umělec alba (setříděno)" #~ msgid "artist (sort)" #~ msgstr "umělec (setříděno)" #~ msgid "album (sort)" #~ msgstr "album (setříděno)" #~ msgid "performer (sort)" #~ msgstr "performer (setříděno)" #~ msgid "performers (sort)" #~ msgstr "performeři (setříděno)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID umělce alba na MusicBrainz" #~ msgid "errors" #~ msgstr "chyby" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Načítání přebalu alba \"%s\" selhalo" #~ msgid "Permanently delete this file?" #~ msgstr "Skutečně navždy odstranit soubor?" #~ msgid "Permanently delete these files?" #~ msgstr "Skutečně chce navždy smazat tyto soubory?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s a %(count)d více..." #~ msgstr[1] "%(title)s a %(count)d více..." #~ msgstr[2] "%(title)s a %(count)d více..." #~ msgid "Version:" #~ msgstr "Verze:" #~ msgid "_Cause an Error" #~ msgstr "_Způsobuje chybu" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s by neměly být přídány do sbírky.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Při provádění příkazu %r se vyskytla chyba způsobená %r." #~ msgid "" #~ "Cannot save library contents to %s (it's a directory). Please remove it " #~ "and try again." #~ msgstr "" #~ "Nelze uložit obsah sbírky do %s (je to adresář). Prosím, odstraňte jej a " #~ "zkuste to znovu." #~ msgid "Library Error" #~ msgstr "Prohlížeč sbírky" #~ msgid "_Output device:" #~ msgstr "_Výstupní zařízení:" #~ msgid "translator-credits" #~ msgstr "Honza Hejzl (honza.hejzl@gmail.com)[připomínky velmi vítány!]" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Zobrazení dalších sloupců (oddělených mezerami)" #~ msgid "_Edit and Continue" #~ msgstr "_Upravit a pokračovat" #~ msgid "Search your library" #~ msgstr "Hledat ve sbírce" #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "Toto je volně šiřitelný software; ve zdroji jsou k nahlédnutí podmínky " #~ "kopírování. Použití na vlastní zodpovědnost.\n" #~ msgid "No eject command found." #~ msgstr "Příkaz k vysunutí nenalezen." #~ msgid "Unable to start web browser" #~ msgstr "Nelze spustit prohlížeč webu" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Prohlížeč webu nelze najít. Nastavte prosím svou $BROWSER proměnnou, nebo " #~ "se ujistěte, že existuje /usr/bin/nějaký prohlížeč." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Celková velikost neznámá" #, fuzzy #~ msgid "Not Played To_day" #~ msgstr "Dnes nehrané" #, fuzzy #~ msgid "Not Played in a _Week" #~ msgstr "Nehrané v posledním týdnu" #, fuzzy #~ msgid "Not Played in a _Month" #~ msgstr "Nehrané za poslední měsíc" #, fuzzy #~ msgid "Date" #~ msgstr "Datum" #, fuzzy #~ msgid "Add" #~ msgstr "Přidat" #, fuzzy #~ msgid "Bitrate" #~ msgstr "Bitrate" #, fuzzy #~ msgid "_Stations..." #~ msgstr "_Stanice..." ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/da.po����������������������������������������������������������������������������0000644�0001750�0001750�00000701467�14436352625�013576� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Danish translations for quodlibet # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the quodlibet package. # scootergrisen, 2016-2018. msgid "" msgstr "" "Project-Id-Version: quodlibet 4.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-05-15 16:32+0000\n" "Last-Translator: scootergrisen <scootergrisen@gmail.com>\n" "Language-Team: Danish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/da/>\n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.7-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "personer" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Dato" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Dato-headere" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "original kunstner" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Bedømmelse" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Antal afspilninger" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Sortér _efter…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Præferencer" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumliste" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumliste" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Alle album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Genindlæs album_cover" msgstr[1] "Genindlæs album_covere" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Sange som ikke er i et album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d spor" msgstr[1] "%d spor" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d diske" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Et eksempel-album" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albumliste-præferencer" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Vis album_covere" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Indbygget _søgning inkluderer personer" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Valgmuligheder" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Album-visning" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Luk" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Bibliotek-browser" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d sang" msgstr[1] "%d sange" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Ugyldigt mønster" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumsamling" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Album_samling" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Ukendt %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Flere %s-værdier" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Brugerdefineret" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Tilføj" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Fjern" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Forén" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Albumsamling-præferencer" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Anvend" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Annuller" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Covergitter" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Covergitter" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Covergitter-præferencer" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Vis album_tekst" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Vis \"Alle album\"-post" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Bred-tilstand" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Cover forstørrelse" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Filsystem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Filsystem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Kan ikke kopiere sange" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "De valgte filer kan ikke kopieres til anden sangliste eller køen." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Tilføj til bibliotek" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Stationslister må kun indeholde placeringer af stationer, ikke andre " "stationslister eller spillelister. Følgende placeringer kan ikke indlæses:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet-radio" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Tilføj stationer" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Downloader stationsliste" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Ny station" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Indtast placeringen af en internet-radiostation:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronisk" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hiphop/rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japansk" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indisk" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religiøs" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Charts" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Tyrkisk" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Skoleradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Snak/nyheder" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassisk" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativ" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Nyheder" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Slager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavisk" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Græsk" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotisk" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Vil du indlæse en liste med populære radiostationer?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Indlæs stationer" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internet-radio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Alle stationer" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoritter" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Ingen kategori" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Ny station…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Opdater stationer" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Ingen stationer fundet" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Ingen internet-radiostationer blev fundet hos %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Intet at tilføje" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Alle viste stationer er allerede i dit bibliotek." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Tilføj til favoritter" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Fjern fra favoritter" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" msgstr[1] "%(count)d stationer" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Rude-browser" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Rude-browser" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Vælg _alle" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Ukendt" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Alle" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Lille" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Bred" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Rediger kolonner" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Tag-mønster med valgfri opmærkning. F.eks. <tt>composer</tt> eller\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Præferencer for rude-browser" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Ens rudebredde" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Spilleliste" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Spillelister" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Fjern fra spilleliste" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Ny" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importér" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Kan ikke importere spilleliste" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet kan kun importere spillelister i formaterne M3U og PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Slet" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Omdøb" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Kan ikke omdøbe spilleliste" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importér spilleliste" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importér" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Ny spilleliste…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Hvad vil du gøre med den %d sang?" msgstr[1] "Hvad vil du gøre med de %d sange?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Bekræft handling for spillelisten \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "tom" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Eksempel-spilleliste" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Præferencer for spilleliste-browser" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Spilleliste-visning" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Er du sikker på, at du vil slette spillelisten '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Al information om den valgte spilleliste vil blive slettet og kan ikke " "gendannes." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Spor" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Ny spilleliste" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Indtast et navn til den nye spilleliste:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importerer spilleliste.\n" "\n" "%(current)d/%(total)d sange tilføjet." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nyt feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Indtast placeringen af et lyd-feed:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Tilføj en fil…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Opdater" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Kan ikke tilføje feed" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s kunne ikke tilføjes. Serveren kan være nede eller placeringen er måske " "ikke et lyd-feed." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Den aktuelle lyd-backend understøtter ikke URL'er, lyd-feeds-browser " "deaktiveret." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Begræns resultater" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Opdel i flere _værdier" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Sporliste" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Sporliste" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud-browser" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Søgning" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Mine spor" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Gå til %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Tilsluttet" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet er nu tilsluttet, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Log ud af %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Indtast kode…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Log ind i %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud godkendelse" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Indtast godkendelseskode til Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet kører ikke (tilføj '--run' for at starte den)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "et musikbibliotek og -afspiller" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[valgmulighed]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Vis sangen som afspilles og afslut" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Start afspilning med det samme" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Vis ikke nogen vinduer ved opstart" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Hop til næste sang" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Hop til forrige sang eller genstart hvis nær begyndelsen" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Hop til forrige sang" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Start afspilning" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Sæt afspilning på pause" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Afspil/pause-tilstand til/fra" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Stop afspilning" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Skru op for lydstyrken" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Skru ned for lydstyrken" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Vis afspilningsstatus" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Skjul hovedvindue" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Vis hovedvindue" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Hovedvinduets synlighed til/fra" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Giv fokus til den kørende afspiller" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Fjern aktive browser-filtre" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Opdater og genskan bibliotek" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Vis tilgængelige browsere" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Vis aktuelle spilleliste" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Vis køens indhold" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Vis den aktive tekst-anmodning" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Start uden plugins" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet hvis ikke den kører" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Afslut Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Søg i sangen som afspilles" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Sæt eller bland-tilstand til/fra" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Sæt bland-tilstandstype" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Slå gentag fra, til eller til/fra" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Sæt gentag-tilstandstype" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Sæt lydstyrken" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Søg i dit lydbibliotek" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "anmodning" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Afspil en fil" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "filnavn" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Søg i sangen som afspilles" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Sæt den aktuelle browser" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Stop efter sangen som afspilles" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Åbn en ny browser" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Vis eller skjul køen" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrér efter en tilfældig værdi" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrér efter en tag-værdi" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=værdi" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Sæt en fil eller anmodning i kø" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Kommasepareret filer i kø" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "filnavn" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Send filnavne fra resultater af anmodning til stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Sæt en fil eller anmodning i kø" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "sted" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "mønster" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Ugyldigt argument for '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Prøv %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Der opstod en fejl" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Du kan ignorere denne fejl, men programmet kan være ustabilt indtil det " "genstartes. Indsendelse af fejlrapport vil kun tage nogle få sekunder og kan " "hjælpe os meget." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Indsend fejlrapport" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Genstart" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorer fejl" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Fejldetaljer:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Diverse detaljer om fejlen og dit system vil blive sendt til en tredjeparts " "online-tjeneste (<a href='https://www.sentry.io'>www.sentry.io</a>). Du kan " "gennemgå dataene nedenfor inden de sendes." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(valgfri) Giv venligst en kort beskrivelse af hvad der skete da fejlen " "opstod:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Send" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Kort beskrivelse…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Data som sendes:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "en lyd-tag-editor" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "mappe" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Lyd-metadata-editor" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Grafik URL-cover-kilde" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Downloader covere som der linkes til af artwork_url-tagget. Det virker med " "Soundcloud-browseren." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs-cover-kilde" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Downloader covere fra Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm-cover-kilde" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Downloader covere fra Last.fm's covergrafik-arkiv." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-cover-kilde" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Downloader covere fra MusicBrainz's covergrafik-arkiv." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Konvertér kodninger" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Retter fejlfortolkede kodninger af tag-værdi i tag-editoren." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Konvertér kodning…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji-simpel-omformer" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Konverterer kana/kanji til romaji inden omdøbning." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanisér _japansk tekst" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Kunne ikke finde 'Kanji Kana-simpel-omformer' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Regex-erstatning" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Tillader vilkårlige regex-erstatninger (s///) ved tagging eller omdøbning af " "filer." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Ord Med Stort" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Skriver ord med stort i tag-værdier i tag-editoren." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Skriv _ord med stort i værdi" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Tillad tags som kun har _STORE BOGSTAVER" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Ord med stort som mennesker skriver det" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Bruger almindelige engelsk regler for ord med stort, som i \"Dark Night of " "the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Avancerede præferencer" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Tillad redigering af avancerede konfigurationsindstillinger." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Jeg ved hvad jeg har gang i" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animeret on-screen-visning" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Viser sanginformation på din skærm når den skifter." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Placering:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Coverstørrelse:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Visning" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Skrifttype:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Venstre" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centreret" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Højre" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Juster tekst:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Tekst" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Tekst:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Udfyld:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Farver" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Skygger" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Omrids" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "_Afrundede hjørner" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Forsinkelse:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effekter" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Rediger visningsmønster…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Forhåndsvis" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Programinformation" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Diverse information om programmet og dets miljø." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Understøttede formater" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Konfigurationsmappe" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Cachemappe" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Lyd-backend" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Tilbagefør til standard" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Kunne ikke skrive '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Opdater tags i filer" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Opdater ændrede tags i filer. Dette vil sikre at antal afspilninger og " "bedømmelser er up-to-date." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Gem bedømmelser og _antal afspilninger i tags" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "optagelsesdato" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Fejl i %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Opdater stationer" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Præferencer" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatisk maskering" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Maskerer og afmaskerer automatisk drev når de afmonteres eller monteres." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatisk bedømmelse" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Bedømmer automatisk sange når de afspilles eller springes over. Dette bruger " "'accelerated'-algoritmen fra vux af Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Import fejlede" #: quodlibet/ext/events/bansheeimport.py:118 #, fuzzy, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Importerede bedømmelse og statistik for %d sange" msgstr[1] "Importerede bedømmelse og statistik for %d sange" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "Start import" #: quodlibet/ext/events/bansheeimport.py:128 #, fuzzy msgid "Imports ratings and song statistics from Banshee." msgstr "Importerer bedømmelser og sangstatisk fra Rhythmbox." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Start import" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Vækkeur" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Vækker dig med høj musik." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Godnatsang" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Udtoner og sætter din musik på pause." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim-statusmeddelelse" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim-statusmeddelelse" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Skifter Gajim-statusmeddelelse i henhold til hvad du lytter til i øjeblikket." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Sat på pause:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Statustekst" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Statustekst" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Flad" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Live" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Fuld bas og diskant" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klub" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Stor hal" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Fest" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Blød" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Fuld bas" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Hovedtelefoner" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Blød rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Fuld diskant" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Bærbar" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizer" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Styrer tonen af din musik med en equalizer.\n" "Klik eller brug taster for at tilpasse niveauer (højreklik for at nulstille " "båndet)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Den aktuelle backend understøtter ikke equalizering." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Standardtema" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Vælg …" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Nulstil EQ" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Brugerdefinerede indstillinger" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Slet de valgte sange" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Gem" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "online" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "offline" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "væk" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "usynlig" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim-statusmeddelelse" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" "Skifter Gajim-statusmeddelelse i henhold til hvad du lytter til i øjeblikket." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "sat på pause" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Mønster:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Vis kontoer, afskilt af mellemrum, for skift af statusmeddelelse. Hvis ingen " "er specificeret, skiftes statusmeddelelse for alle kontoer." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Konti:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Tilføj '[sat på pause]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Hvis tilvalgt, tilføjes '[sat på pause]' til statusmeddelelse ved pause" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statusser for hvilken meddelelser der ændres" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Sæt på pause når stik til hovedtelefoner fjernes" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Sætter på pause når stikket til hovedtelefonerne fjernes og afspiller når " "det sættes i igen." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Blokér pauseskærm" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musik afspiller" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Tilstand:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Blokér pauseskærm" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Blokér pauseskærm" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Internetradio-log" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Optager de sidste 10 sange afspillet på radiostationer og viser dem i " "søgegenvejsmenuen." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Outputter en Jabber User Tunes-fil til ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Skift sprog" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Skrift brugerfladens sprog." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Systemets standard" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "En genstartes kræves før eventuelle ændringer træder i kraft" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV-medieserver" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Eksponerer alle album til Rygel UPnP-medieserveren gennem D-Bus-grænsefladen " "til MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD-server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Tillader fjernstyring af Quod Libet ved brug af en MPD-klient. Strømning-, " "spilleliste- og biblioteksstyring understøttes ikke." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokal _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "_Adgangskode:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Forbindelse" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Testede klienter" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus-understøttelse" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Skjul hovedvindue ved luk" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Accepterer QL-mønstre. F.eks. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT-udgiver" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Udgiver statusmeddelelser til et MQTT-emne." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Mægler-værtsnavn" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "mægler-værtsnavn/-IP" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Mægler-port" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Standard" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Mægler-værtsnavn" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Mægler-port" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Emne" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Afspiller-mønster" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Statustekst når en sang er startet." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Sat på pause-mønster" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Tekst når en sang er sat på pause." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Ingen sang-tekst" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Almindelig tekst til når der ikke er nogen sang" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT-konfiguration" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Statustekst" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Tilsluttet mægler hos %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Kunne ikke oprette forbindelse til %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Forbindelsesfejl" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz-opslag" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Tillader at bedømmelsen af sange sættes med et tal." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Brugernavn:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Adgangskode:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Notifikationstekst" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Titel:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Tilbagefør til standardmønster" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Krop:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Vis notifikationer" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Vis notifikationer" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Kun ved <i>_manuelle</i> skift af sange" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Kun ved <i>_automatiske</i> skift af sange" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Ved <i>a_lle</i> skift af sange" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Kun når hovedvinduet ikke har _fokus" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Vis \"_Næste\"-knap" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Forbindelsesfejl" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Kunne ikke oprette forbindelse til notifikationsdæmon." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Sang-notifikationer" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Viser en notifikation når sangen skiftes." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Næste" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Sang-notifikationer" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Besøg venligst Plugins-vinduet for at opsætte QLScrobbler. Indtil da vil " "sange ikke blive indsendt." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Kunne ikke kontakte tjenesten '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Godkendelse fejlede: ugyldig URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Godkendelse fejlede: ugyldigt brugernavn '%s' eller forkert adgangskode." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Klienten er udelukket. Kontakt forfatteren." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "Forkert systemtid. Indsendelser kan fejle indtil det er rettet." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-indsendelse" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler-klient til Last.fm, Libre.fm og andre Audioscrobbler-" "tjenester." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Godkendelse lykkedes." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Tjeneste:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Anden…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Bekræft kontodata" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Kunstner-mønster:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Titel-mønster:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Ekskluderings_filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Mønsteret brugt til at formatere kunstnernavnet til indsendelse. Lad være " "tom for standard." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Mønsteret brugt til at formatere titlen til indsendelse. Lad være tom for " "standard." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Sange som matcher dette filter vil ikke blive indsendt" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Offline-tilstand (indsend ikke noget)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Indsendelse" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Slå lyden fra i radioreklamer" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Slår output fra når radioreklamer afspilles.\n" "Stationer: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Afspilning af tilfældigt album" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Starter et tilfældigt album når din spilleliste når sin slutning. Det kræver " "at din aktive browser understøtter filtrering efter album." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Højere bedømt" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Afspillet oftere" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Sprunget over oftere" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Afspillet mere nyligt" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Startet mere nyligt" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Tilføjet mere nyligt" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Længere album" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekunder før næste album startes" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Vægtninger" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Afspil nogle album mere end andre" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "undgå" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "foretræk" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Tilfældigt album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Venter på at starte %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Importerede bedømmelse og statistik for %d sange" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox-import" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importerer bedømmelser og sangstatisk fra Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pauseskærm sat på pause" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Sætter afspilning på pause når GNOME-pauseskærmen er aktiv." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Der er ikke installeret en søgeudbyder for Quod Libet i GNOME Shell." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME-søgeudbyder" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Tillader GNOME Shell at søge i biblioteket." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternativ søgelinje" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternativ søgelinje som altid er synlig og fylder hele vinduets bredde." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Søgepunktsbogmærker" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Gem søgepunkterne A og/eller B for sporet. Spring til tidspunkt A og stop " "efter tidspunkt B når sporet vises.\n" "Bemærk at ændring af navnene på punkterne nedenfor ikke opdaterer " "bogmærkenavnet, det ændrer kun bogmærkenavnene som pluginet leder efter når " "der tages beslutning om der skal søges." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Bogmærkenavn til punkt A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Bogmærkenavn som der skal søges efter når et spor startes, og hvis det " "findes søger afspilleren til det tidsstempel" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Bogmærkenavn til punkt B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Bogmærkenavn som der skal bruges ved hver afkrydsning under afspilning af et " "spor hvis det findes. Hvis den nuværende placering overstiger tidsstemplet, " "så søg til slutningen af sporet." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox-synkronisering" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Får Logitech Squeezebox til at spejle Quod Libet-output, forudsat at begge " "læser fra et identisk bibliotek." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Fejl ved forsøg på at finde Squeezebox-server" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fejl ved forsøg på at finde %s. Tjek venligst indstillinger" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Valgmuligheder" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "kodning" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "optagelsesdato" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "slet" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Spring over" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Synkroniserede sangtekster" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Sletter" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Lykkedes" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Sprunget over oftere" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Synkroniserede sangtekster" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Destinationsmappe:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Sti-mønstre" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Rediger gemte mønstre…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Kunstner-mønster:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Forhåndsvis" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Kildefil" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Eksportér metadata" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organisation" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Gemmedestination" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Synkroniserede sangtekster" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Stien er ikke absolut" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Mønsteret\n" "\t<b>%s</b>\n" "indeholder / men starter ikke fra roden. Brug rodning for at forhindre " "fejlnavngivne mapper ved at starte dit mønster med / or ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Ingen sang er valgt." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Ingen sang er valgt." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Kan ikke gemme sang" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Fjerner \"{}\"" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Synkroniserede sangtekster" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Sprunget over oftere" msgstr[1] "Sprunget over oftere" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Kunne ikke indlæse filen: %r" msgstr[1] "Kunne ikke indlæse filen: %r" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synkroniserede sangtekster" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Viser synkroniserede sangtekster fra .lrc-fil med samme navn som sporet." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Baggrund:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Skrifttype" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Størrelse (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy-statusmeddelelser" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Opdaterer alle Telepathy-baserede IM-kontoer (som kofigureret i Empathy " "osv.) med en statusmeddelelse baseret på aktuelle sang." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Afspiller:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Statustekst når en sang startes. Accepterer QL-mønstre. F.eks. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Sat på pause:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Statustekst når en sang er sat på pause. Accepterer QL-mønstre. F.eks. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Almindelig tekst til status når der ikke er nogen sang" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Ingen sang:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Statusmønstre" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Tema-skifter" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Skifter det aktive GTK+-tema." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Standardtema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Foretræk version med mørkt tema" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Automatisk bedømmelse" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Menulinje til/fra" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Menulinje til/fra ved tryk på Alt-tasten." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Afspiller ikke" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Bakkeikon" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Styrer Quod Libet fra systembakken." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Vis %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Afspil" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Pause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Forrige" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Næste" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Bland" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Gentag" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Stop _efter denne sang" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Åbn _browser" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Rediger _tags" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Information" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Spillelister" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Afslut" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Adfærd" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Rullehjul justerer lydstyrke" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Rullehjul skifter sang" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Rullehjul" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Værktøjstip-visning" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Vis sangtekster" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Viser automatisk tag eller filbaserede sangtekster i en sidebjælke." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Ingen sangtekster fundet til\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Ingen aktiv sang" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Start visualiseringer" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Start eksterne visualiseringer." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Kunne ikke køre visualiseringer ved brug af '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Fejl" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Visualiserer-eksekverbar:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Genindlæs" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Bølgeform søgelinje" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "En søgelinje som har form af den aktuelle sangs bølgeform." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Tilsidesæt forgrundsfarve:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Tilsidesæt pegefarve:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Tilsidesæt resterende farve:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Vis nuværende placering" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Billede-gemmer" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Gemmer cover-billedet af den aktuelle sang til en fil." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Fil:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Tærskel:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Tærskel indtil filteret aktiveres" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Forhold:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Komprimeringsforhold" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Lydkompressor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Ændrer amplituden for alle datapunkter over en specifik tærskel med et " "bestemt forhold." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Forudindstilling:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filter-forudindstilling" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frekvensklipning:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Frekvens for low-pass filterklipning" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Feed-_niveau:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Feed-niveau" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Standard" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Nærmest til placering af virtuel højttaler (30°, 3 meter)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Nær Chu Moy's crossfeeder (populær)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Nær Jan Meier's CORDA-forstærkere (mindre ændring)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Brugerdefineret" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Brugerdefinerede indstillinger" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mikser den venstre og højre kanal på en måde som simulerer en højttaler " "under brug af hovedtelefoner eller til at justere for tidlige stereo " "optagelser." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filter_bånd:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Frekvensbåndet af filteret" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filter_bredde:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Frekvensbredden af filteret" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Niveau:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Niveauet af effekten" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Fjerner hovedvokaler fra lyd." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono nedmiks" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Nedmikser lydkanaler til mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Hastighed:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Tonehøjde:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Lydtonehøjde/-hastighed" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Styrer tonehøjden af en lydstrøm." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Eksportér spilleliste til mappe" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Eksportér" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Destinationsmappe:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Filnavn-mønster:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Eksporterer en spilleliste ved at kopiere filer til en mappe." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Kan ikke eksportere spilleliste" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Standardfilnavn-mønster:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Eksportér som spilleliste" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Eksporterer en spilleliste ved at kopiere filer til en mappe." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Fejl ved forsøg på at finde Squeezebox-server" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Fejl ved forsøg på at finde %s. Tjek venligst indstillinger" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Eksportér til Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Eksporterer dynamisk en spilleliste til Logitech Squeezebox-spilleliste, " "forudsat at begge deler en mappestruktur. Deler konfiguration med <a href=" "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox-synkronisering-" "plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Eksportér spilleliste til Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Spillelistenavn (vil overskrive eksisterende)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Eksportér til Squeezebox-spilleliste" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Fjern duplikater fra spilleliste" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Fjerner duplikerede indtastninger i en spilleliste." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Er du sikker på, at du vil fjerne %d duplikeret sang?" msgstr[1] "Er du sikker på, at du vil fjerne %d duplikerede sange?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "De duplikerede sange vil blive fjernet fra spillelisten '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Bland spilleliste" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Blander tilfældigt en spilleliste." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Følg markør" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "Afspilning følger dit valg eller den næste sang i listen når opbrugt." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Følg markør" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Følg markør" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Playcount-equalizer" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Bland, foretræk sange med færre samlet afspilninger." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Foretræk færre afspilninger" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Foretræk færre afspilninger" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Sæt kun i kø" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Begrænser afspilning af sange til køen. Vælg denne afspilningsrækkefølge i " "hovedvinduet, så vil dobbeltklik på en sang sætte den i kø i stedet for at " "afspille den." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Sæt kun i kø" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Sæt kun i kø" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Omvend" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Vender om på afspilningsrækkefølgen af sange." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Omvend" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Bland efter gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Blander efter en gruppering af sange defineret af et almindeligt tag i " "stedet for et spor, i stil med blanding af album. Det er nyttigt til " "blanding af flerflyttende klassiske værker så alle flytninger afspilles i " "rækkefølge inden der blandes til det næste stykke." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Bland efter gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Bland efter gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Venter på at starte ny gruppe…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Grupperingstag:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Mærk for at gruppere sange efter" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filtertag:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Gruppering anvendes kun hvis filtertagget er defineret.\n" "En sang med et udefineret filtertagget behandles som\n" "en gruppe som kun består af sig selv. Typisk skal\n" "tagget matche eller delvist matche grupperingstagget." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Forsinkelse:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Tidsforsinkelse i sekunder før næste gruppe startes" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Nulstil til standard" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Gentag hvert spor" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Blander sange, men gentager hvert spor et sat antal gange." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Gentag hvert spor" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Gentag hvert spor" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Antal gange som hver sang skal afspilles:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Betinget anmodning" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Vælger anmodningen som skal matches, baseret på en betingelsesanmodning. " "Syntaksen er '@(if: betingelse, then, else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 #, fuzzy msgid "Missing Query" msgstr "Betinget anmodning" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Ugyldige tags" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python-anmodning" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Tag-udtryk" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Brug Python-udtryk i forespørgsler. Syntaksen er '@(python: udtryk)'. " "Variablen 's' (eller 'a') er sangen/albummet som der matches på. '_ts' er et " "(real-tal) tidsstempel i begyndelsen af forespørgslen. Modulerne 'time' og " "'random' er også tilgængelige, samme gælder klassen 'Random' (==random." "Random)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Inkluder gemte søgninger" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Inkluder resultaterne af en gemt søgning som del af en anden anmodning. " "Syntaksen er '@(saved: søgenavn)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Gemte søgninger" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unik" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Bruger den eneste afspiller (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Kunne ikke oprette forbindelse til %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Værtsnavn:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Brugernavn:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Adgangskode:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Biblioteksmappe som serveren opretter forbindelse til" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Bibliotekssti:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Bekræft indstillinger" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox-server" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Fejlret" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-server hos {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "uidentificeret Squeezebox-server" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "uidentificeret Squeezebox-afspiller: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Vælg Squeezebox-afspiller" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Fandt Squeezebox-server.\n" "Vælg venligst afspilleren" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Tilpas billede til _vindue" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Se '[plugins] cover_filnavne'-konfigurationsindtastning for " "billedfilnavnestrenge" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Rediger billede efter gemning" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Filnavn:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Gemning fejlede" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Kan ikke gemme \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-fejl: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Albumgrafik-downloader" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "fra %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Opløsning: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Størrelse: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Pr. motor 'bedste'-resultatsgrænse" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Søg" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Søger…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Færdig" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Download albumgrafik" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Downloader albumcovere fra diverse websteder." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Kilder" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 til ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Konverterer dine APEv2-tags til ID3v2-tags. Dette vil slette APEv2-taggene " "efter konvertering." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Gå til bogmærke" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Håndtér bogmærker i de valgte filer." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Rediger bogmærker…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Ingen bogmærker" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-opslag" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Gentagger et album baseret på en MusicBrainz-søgning." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Brug kun år til \"date\"-tag" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Skriv \"_albumartist\" når det er nødvendigt" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Skriv sorterings-tags for kunstnernavne" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Skriv _standard-MusicBrainz-tags" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Skriv \"labelid\"-tag" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Filnavn" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Spor" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Titel" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Kunstner" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz-opslag" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Anmodning:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Søg" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Resultater <i>(træk for at ændre rækkefølge)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Indtast venligst en anmodning." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Stødte på fejl. Prøv venligst igen." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Indlæser resultat…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Ingen resultater fundet." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python-konsol" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktiv Python-konsol. Åbner et nyt vindue." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} for {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python-konsol-sidebjælke" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Interaktiv Python-konsol-sidebjælke, som følger de valgte sange i " "hovedvinduet." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Du kan tilgå følgende objekter som standard:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Din aktuelle arbejdsmappe er:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Forbindelse" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Download covergrafik" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Downloader albumcovere i høj kvalitet med cover-plugins." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klassisk" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Stor" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Fuld HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Covergrafik-downloader" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Indlæser %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Intet fundet for albummer:\n" "<i>%(albums)s</i>.\n" "\n" "Udbydere brugt:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Ingen covere fundet" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Størrelse for forhåndsvisning" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Gemmedestination" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Gem som JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Kommando" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "navn" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Navnet på denne kommando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "kommando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Skal-kommando-syntaksen som skal køres" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parameter" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Hvis specificeret, erstattes en parameter som forekommer i kommandoen med en " "værdi som brugeren har givet, ved f.eks. at bruge 'PARAM' spørges der om " "værdien ved alle forekomster af '{PARAM}' i din kommando, når den køre" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL-mønsteret, f.eks. <~filename>, til udregning af en værdi for kommandoen. " "For spillelister understøtter dette også virtuelle tags <~playlistname> og " "<~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unik" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Hvis sat, fjerner dette duplikeret udregnede værdier af mønsteret" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "maks. argumenter" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Højeste antal af argumenter som videregives til kommandoen på samme tid " "(ligesom xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Omvend" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Input-værdi" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Værdi til %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Brugerdefinerede kommandoer" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Kører brugerdefinerede kommandoer (i partier hvis krævet) på sange ved brug " "af deres tags." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Rediger brugerdefinerede kommandoer" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Kan ikke køre brugerdefineret kommando %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplikeret gruppe" msgstr[1] "%d duplikerede grupper" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Sammenfold/udfold alle" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Duplikeret nøgle-udtryk er '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Duplikerer browser" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Finder og viser lignende taggede versioner af sange." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Accepterer QL-tag-udtryk såsom <tt>~artist~title</tt> eller " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Gruppér duplikater efter:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplikér nøgle" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Fjern _blanktegn" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Fjern _diakritiske" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Fjern _tegnsætning" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Der skelnes _ikke mellem store og små bogstaver" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Sammenhørende valgmuligheder" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Rediger playcount" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Rediger en sangs ~#playcount og ~#skipcount.\n" "\n" "Når flere sange vælges, forøges antallet, fremfor at blive sat.\n" "\n" "Når en sangs ~#playcount indstilles til 0, ryddes ~#lastplayed og " "~#laststarted. Men når en sang med 0 afspilninger sættes til et positivt " "afspilningsantal, vil ingen afspilningsantal blive oprettet." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Antal afspilninger" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Antal overspring" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Flere %s-værdier" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Rediger indlejrede billeder" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Fjerner eller erstatter indlejret billeder." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Fjern alle billeder" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Indlejr aktuelle billede" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Sæt præcist bedømmelse" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Tillader at bedømmelsen af sange sættes med et tal." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Giv venligst din ønskede bedømmelse på en skala fra 0.0 til 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrér efter vilkårlig tag" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Opretter en søgeanmodning baseret på tags fra de valgte sange." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrér efter mappe" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtrerer efter mappe i et nyt browservindue." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akustisk fingeraftryk-opslag" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Foretager opslag af sangens metadata gennem akustisk fingeraftryk." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Indsend akustisk fingeraftryk" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Genererer akustiske fingeraftryk ved brug af chromaprint og indsender dem " "til acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API-nøgle mangler" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Du skal specificere en acoustid.org API-nøgle i plugin-præferencerne inden " "du kan indsende fingeraftryk." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Anmod om API-nøgle" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API-_nøgle:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID-webtjeneste" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Sat i kø" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analyserer" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Opslag" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Skriv" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Udgivelse" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Skriv MusicBrainz-tags" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Gruppér efter mappe" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Album-tilstand" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Skriv albumrelaterede tags og prøv at reducere antallet af forskellige " "albumudgivelser" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Genererer fingeraftryk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detaljer" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Indsend" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Sange skal enten have et <i><b>musicbrainz_trackid</b></i>- eller " "<i><b>artist</b></i>/<i><b>title</b></i>/<i><b>album</b></i>-tags for at " "blive indsendt." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Fingeraftryk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Sange med MBID'er:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Sange med tilstrækkelige tags:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Sange som skal indsendes:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Færdig. %(to-send)d/%(all)d sange af indsende." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Indsender fingeraftryk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Indsender…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Opdater tags i filer" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Opdater ændrede tags i filer. Dette vil sikre at antal afspilninger og " "bedømmelser er up-to-date." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Eksportér til HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Eksporterer den valgte sangliste til HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Send til iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Uploader sange til en iRiver iFP-enhed." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Ingen iFP-enhed fundet" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Kan ikke kontakte din iFP-enhed. Tjek at enheden er tændt og tilsluttet, og " "at du har installeret ifp-line (http://ifp-driver.sf.net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Uploader %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Kan ikke uploade <b>%s</b>. Enheden er måske løbet tør for ledig plads, " "eller er slukket." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Fejl under upload" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Eksportér metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Eksportér metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Eksportér metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Eksportér metadata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Ingen information om tid" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Albumgrafik" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Import fejlede" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importér" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrér efter mappe" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Disk" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Spor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Kunstner" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Fortsæt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 #, fuzzy msgid "Nothing to import" msgstr "Intet at tilføje" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Kunne ikke skrive '%s'" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Kunne ikke skrive '%s'" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Filnavne" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Gentag hvert spor" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Opdaterer chartliste." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Allerede up-to-date." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Henter chart for uge af %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synkronisering fuldført." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Fejl under synkronisering" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm-synkronisering" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Opdaterer dit biblioteks statistik fra din Last.fm-profil." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Brugernavn:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Opret sorterings-tags" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Konverterer album- og kunstnernavne til sorteringsnavne, dårligt." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Eksportér som spilleliste" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksporterer sange til en M3U- eller PLS-spilleliste." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Brug relative stier" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Brug absolutte stier" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Skrivning til <b>%s</b> fejlede." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Genskan sange" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Tjekker for filændringer og genindlæser/fjerner sangene hvis det er " "nødvendigt." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Genskan sange" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analysator" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Spor" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Forløb" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Forstærkning" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Spidspunkt" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Der er <b>%(to-process)s</b> album at opdatere (af %(all)s)" msgstr[1] "Der er <b>%(to-process)s</b> album at opdatere (af %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, fuzzy, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyserer og opdaterer ReplayGain-information, ved brug af GStreamer. " "Resultater grupperes efter album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "altid" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "hvis <b>nogen</b> RG-tags mangler" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "hvis <b>album</b> RG-tags mangler" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Behandl album:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Eksisterende tags" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Opdel tags" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Opdeler disknummeret fra albummet og versionen fra titlen samtidigt." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Opdel album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Opdel disknummer." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "utilgængelig" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Nulstil" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Tryk" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Tap BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Tap BPM for den valgt sang." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Websted-søgning" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Søger på dine valg af websteder ved brug af vilkårlige sang-tags.\n" "Understøtter mønstre. F.eks. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Søger i URL-mønstre" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Rediger søge-URL'er" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Konfigurér søgninger…" #: quodlibet/ext/songsmenu/wikipedia.py:36 #, fuzzy msgid "Search Tag in Wikipedia" msgstr "Søg efter album på Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 #, fuzzy msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Åbner et browservindue med Wikipedia-artiklen om komponisten af sangen som " "afspilles." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Søg hos %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Rediger tags" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Gemning fejlede" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliotek" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Tjekker monteringspunkter" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Skanner bibliotek" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Skanner %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Indlæser filer" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Skanner bibliotek" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Fjern aktive browser-filtre" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Musikafspiller og musikbibliotekshåndtering" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Kunne ikke indlæse filen: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Vis tags" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Vis kortfattet output" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Kolonner til at vise og bestemme rækkefølge i kortfattet tilstand (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Vis også programmatiske tags" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Ikke nok argumenter" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "For mange argumenter" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Beskrivelse" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Værdi" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Vis alle almindelige tags" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopiér tags fra en fil til en anden" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Vis ændringer, anvend dem ikke" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Spring over tags som ikke kan skrives" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Kan ikke kopiere tagget %r til filen: %r" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Rediger tags i et tekstredigeringsprogram" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Redigering afbrudt" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Start af tekstredigeringsprogrammet '%(editor-name)s' fejlede." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Ingen ændringer detekteret" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Sæt et tag og fjern eksisterende værdier" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Kan ikke kopiere tagget %r til filen: %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Fjern tags" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Værdi er et regulært udtryk" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Fjern alle tags" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan ikke kombinere '--all' med '--regexp'" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Kan ikke fjerne %r fra %r" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Fjern en tag-værdi" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Tilføj en tag-værdi" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Kan ikke sætte %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Vis filinformation" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Sæt det medfølgende billede som primære indlejret billede og fjern alle " "andre indlejrede billeder" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Kunne ikke indlæse billedfilen: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "Billedredigering understøttes ikke for %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Fejl alle indlejrede billeder" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Udtræk indlejrede billeder til %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Sti til hvor billederne vil blive gemt (standard er arbejdsmappen)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Omdøb filer baseret på tags" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Udfyld tags baseret på filstien" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fil" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Udfyld spornumre for alle filer" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Vis tags baseret på det givne mønster" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Viser hjælpinformation" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' er ikke et gyldigt kolonnenavn (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Ukendt" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "I rækkefølge" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_I rækkefølge" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Tilfældig" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Tilfældig" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Foretræk højere bedømmelse" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Foretræk højere bedømmelse" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Gentag dette spor" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Gentag dette spor" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Gentag alle" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Gentag alle" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Én sang" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Én sang" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Strøm" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Gemmer i buffer" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Kunne ikke oprette GStreamer-pipeline" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Intet GStreamer-element fundet til håndtering af medieformat" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Medieformat: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer-plugin'et '%(name)s' kunne ikke klargøres" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer-output-pipelinen brugt til afspilning. Lad være tom for " "standardpipelinen. I tilfælde af at pipelinen indeholder en sink, vil den " "blive brugt frem for den som er standard." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Output-pipeline:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Bufferens varighed:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Deaktivér afspilning uden _huller" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Deaktivering af afspilning uden huller kan forhindre problemer ved skift af " "spor med nogle versioner af GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Intet GStreamer-lydsink fundet" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Ugyldig GStreamer-output-pipeline" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Kan ikke oprette lyd-output" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Lydenheden %r blev ikke fundet. Tjek dine Xine-indstillinger i ~/.quodlibet/" "config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Kunne ikke finde modulet '{module}'. Måske skal du installere pakken?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Kunne ikke finde GStreamer-element '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Besøg venligst Plugins-vinduet for at opsætte QLScrobbler. Indtil da vil " "sange ikke blive indsendt." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Besøg venligst Plugins-vinduet for at opsætte QLScrobbler. Indtil da vil " "sange ikke blive indsendt." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Indsendelse" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Brugernavn:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Sange som matcher dette filter vil ikke blive indsendt" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Kør plugin'et \"%(name)s\" på %(count)s spilleliste?" msgstr[1] "Kør plugin'et \"%(name)s\" på %(count)s spillelister?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Kør plugin" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Begyndelse" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Utilgængelig" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tidspunkt" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Bogmærkenavn" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Bogmærker" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtrér" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Nyligt _afspillet" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Nyligt _tilføjet" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Alle _sange" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Efter aktuelle _genre(r)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Efter aktuelle _kunstner(e)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Efter aktuelle _album" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Tilfældig _genre" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Tilfældig _kunstner" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Tilfældigt _album" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "De 40 sange som du mest har afspillet (flere end 40 blive valgt hvis nogle " "er ens)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Navn:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Værdi:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Gemte værdier" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Rediger gemte værdier…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "_Automatisk" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Spor-tilstand" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Album-tilstand" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Mute" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain-tilstasnd" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Ny %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(ukendt)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Tilføj" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Rediger…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Tag-udtryk" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tag-udtryk. F.eks. people:real eller ~album~year." #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Indtast nyt tag" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Tag-udtryk" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Filer:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "De valgte sange vil blive fjernet fra biblioteket og deres filer slettet fra " "disken." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "De valgte filer vil blive slettet fra disken." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Slet %(file_count)d fil permanent?" msgstr[1] "Slet %(file_count)d filer permanent?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Slet filer" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "De valgte sange vil blive fjernet fra biblioteket og deres filer flyttet til " "papirkurven." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "De valgte filer vil blive flyttet til papirkurven." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Flyt %(file_count)d fil til papirkurven?" msgstr[1] "Flyt %(file_count)d filer til papirkurven?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Flyt til papirkurv" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Flyttede %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Kan ikke flytte til papirkurv" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Flytning af en eller flere filer til papirkurven fejlede." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Sletter %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Kan ikke slette filer" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Sletning af en eller flere filer fejlede." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Browsere" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Indlæser filer" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "mangler fra %d sang" msgstr[1] "mangler fra %d sange" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "forskellig på tværs af %d sang" msgstr[1] "forskellig på tværs af %d sange" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Opdel i _flere værdier" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Opdel disk ud af _album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Opdel _version ud af titel" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Opdel arrangør ud af _kunstner" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Opdel _performer ud af kunstner" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Opdel _performer ud af titel" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Opdel _original kunstner ud af titel" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Tilføj et tag" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Vis _programmatiske tags" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Tilgå alle tags, inklusiv maskingenereret, f.eks. MusicBrainz- eller Replay " "Gain-tags" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Vis _programmatiske tags" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Tilbagefør" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Gem" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Fortsæt" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Opdel tags" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Kan ikke tilføje tag" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Kan ikke tilføje sange" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "De valgte filer understøtter ikke flere værdier for <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Ugyldigt tag" msgstr[1] "Ugyldigt tag" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Ugyldigt tag <b>%s</b>\n" "\n" "De valgte filer understøtter ikke redigering af dette tag." msgstr[1] "" "Ugyldigt tag <b>%s</b>\n" "\n" "De valgte filer understøtter ikke redigering af dette tag." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Ugyldig værdi" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Ugyldig værdi: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tag er måske ikke korrekt" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s blev ændret mens programmet kørte. Gemning uden genindlæsning " "af dit bibliotek kan overskrive andre ændringer af sangen." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Kan ikke gemme sang" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Gemning af %(file-name)s fejlede. Filen kan være skrivebeskyttet, ødelagt " "eller du har ikke rettigheder til at redigere den." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Flere valgmuligheder…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Fortryd" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Omgør" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Om" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Søg efter opdateringer…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Plugins" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s og %(count)s mere" msgstr[1] "%(title)s og %(count)s mere" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Præferencer for Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mapper" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Ny mappe…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Vælg alle undermapper" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Ny mappe" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Indtast et navn til den nye mappe:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Kan ikke oprette mappe" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Kan ikke slette mappe" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Sange" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "af %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Spor %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "Efter aktuelle _genre(r)" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Rediger visning…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ingen sang er valgt." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Ingen sange" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Information" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Sangtekster" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produceret af %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "kunstner" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "kunstnere" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "performere" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Aldrig" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d gang" msgstr[1] "%(n)d gange" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "tilføjet" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "sidst afspillet" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "afspiller" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "springer over" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "bedømmelse" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "sti" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "længde" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "kodning" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bithastighed" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "filstørrelse" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "ændret" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Yderligere" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valgt" msgstr[1] "%d valgt" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Spor utilgængeligt" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d sang uden album" msgstr[1] "%d sange uden album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Valgt diskografi" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d sang uden kunstner" msgstr[1] "%d sange uden kunstner" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Samlet længde:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Samlet størrelse:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Filer" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Vis online" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Ingen sangtekster fundet til denne sang." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Er du sikker på, at du vil fjerne alle sange?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "De valgte sange vil blive fjernet fra biblioteket." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Fjern fra skjul" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Fjern fra skjul" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Forkast ændringer af tag?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tags er blevet ændret men ikke gemt. Gem disse filer eller tilbagefør og " "forkast ændringer?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Tilbagefør" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Filen findes" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Erstat %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Erstat fil" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktive opgaver" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d opgaver kører" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Bland-tilstand til/fra" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Gentag-tilstand til/fra" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Begivenheder" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Afspilningsrækkefølge" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Redigering" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Omdøb" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Anmodning:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Covere" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Pluginfejl" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Aktiveret" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Deaktiveret" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Ingen kategori" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Ingen kategori" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Ingen plugins fundet." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Plugins" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrér efter plugintilstand/tag" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrér efter plugintype" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrér efter pluginnavn eller -beskrivelse" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Vis _fejl" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Spor" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "_Gruppering" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Kunstner" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Album" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Filnavn" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Længde" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Hop automatisk til sangen som afspilles" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Når sangen som afspilles skiftes, rul den ind i sanglisten" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Andre:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Rediger…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Tilføj eller fjern yderligere kolonne-headere" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Synlige kolonner" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Titel inkluderer _version" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album inkluderer _disk-undertitel" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Kunstner inkluderer alle _personer" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Filnavn inkluderer _mappe" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Kolonne-præferencer" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Rediger kolonner" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Anvend aktuelle konfiguration til sangliste, hvor ved nye kolonner tilføjes " "til slutningen" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Sangliste" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Rediger kolonner" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Samlet varighed" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globalt filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Anvend endvidere denne anmodning udover alle andre" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Søgning" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Browsere" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Bekræft _flere bedømmelser" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Spørg om bekræftelse før ændring af bedømmelse af flere sange på en gang" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Aktivér bedømmelser med ét _klik" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Aktivér bedømmelse ved klik på bedømmelseskolonnen i sanglisten" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Bedømmelser" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Foretræk _indlejret grafik" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Vælg at bruge grafik indlejret i lyden (når det er muligt) frem for andre " "kilder" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Fast billedfilnavn:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumgrafik" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Afspilning" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Output-konfiguration" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Hvis der ikke er nogen Replay Gain-information tilgængelig for en sang, så " "skaleres lydstyrken af denne værdi" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Fall-back forstærkning (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Skalér lydstyrke for alle sange med denne værdi, så længe resultatet ikke " "klippes" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Pre-amp forstærkning (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Aktivér justering af lydstyrke for Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Justering af lydstyrke for Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Standardbedømmelse:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Bedømmelses_skalering:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesian Average factor (C) til indsamlende bedømmelser.\n" "0 betyder et konventionelt gennemsnit, højere værdier betyder at albums med " "få spor vil have mindre ekstrem bedømmelse. Når denne værdi ændres udløser " "det en genudregning af alle albums." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesian gennemsnitlig mængde:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-mail:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Bedømmelser og antal afspilninger gemmes i tags for denne e-mailadresse" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Gem automatisk ændringer af tag" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Gem ændringer til tags uden bekræftelse når flere filer redigeres" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Et sæt af separatorer som skal bruges når tag-værdier opdeles i tag-" "editoren. Listen er mellemrumssepareret." #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "_Opdel ved:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Et sæt af separatorer som skal bruges når tag-værdier opdeles i tag-" "editoren. Listen er mellemrumssepareret." #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "_Opdel ved:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tags" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tag-redigering" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Opdaterer for nye bedømmelser" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Skan bibliotek" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Søg efter ændringer i dit bibliotek" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "_Genbyg bibliotek" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Genindlæs alle sange i dit bibliotek. Dette kan tage lang tid." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Skjulte sange" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "_Skan bibliotek ved start" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Mapper som skal skannes" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s og %(count)d mere" msgstr[1] "%(title)s og %(count)d mere" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Egenskaber" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Kø" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Ryd kø" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Bevar sange i køen efter de er blevet afspillet" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Bevar sange i køen efter de er blevet afspillet" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Bred-tilstand" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Stop ved slutningen" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d sang (%(time)s)" msgstr[1] "%(count)d sange (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Gennemse bibliotek" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Køens synlighed til/fra" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Fejl ved afspilning" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Opsæt biblioteksmapper?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Du har ikke opsat nogen musikbiblioteker. Vil du gøre det nu?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Ikke nu" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Sæt op" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Kan ikke tilføje sange" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s bruger en ikke-understøttet protokol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Hop til sangen som afspilles" # scootergrisen: jeg prøver med "Arkiv" fremfor "Fil/Filer" for at afprøve det lidt #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Arkiv" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Sang" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Visning" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Gennemse" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Betjening" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Hjælp" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Tilføj en mappe…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Tilføj en fil…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Tilføj en placering…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Rediger bogmærker…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Stop" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Stop efter denne sang" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Tastaturgenveje" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Onlinehjælp" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Søgehjælp" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Tilføj en placering" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Indtast placeringen af en lydfil:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Kan ikke tilføje placering" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s er ikke en gyldig placering." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Tilføj musik" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Tilføj mapper" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Musikfiler" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Tilføj filer" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Er du sikker på, at du vil fjerne alle sange?" msgstr[1] "Er du sikker på, at du vil fjerne alle sange?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Kø" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Er du sikker på, at du vil ændre bedømmelsen af alle %d sange?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "De gemte bedømmelser vil blive fjernet" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Fjern bedømmelse" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Bedømmelsen af alle valgte sange vil blive ændret til '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "_Skift bedømmelse" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Erstat mellemrum med _understregningstegn" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Fjern tegn som er inkompatible med _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Fjern _diakritiske tegn" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Fjern ikke-_ACSII-tegn" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Brug kun _små bogstaver" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Omdøb filer" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Forhåndsvis" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Filnavne" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Flyt albumgrafik" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Se '[albumart] filnavne'-konfigurationsindtastning for billedsøgningsstrenge" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Overskriv albumgrafik ved mål" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Fjern tomme mapper" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Albumgrafik" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nyt navn" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Kan ikke omdøbe fil" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Omdøbning af <b>%(old-name)s</b> til <b>%(new-name)s</b> fejlede. Målfilen " "findes muligvis allerede eller du har ikke rettighed til at oprette den nye " "fil eller fjerne den gamle." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorer _alle fejl" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stop" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Fortsæt" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Stien er ikke absolut" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Mønsteret\n" "\t<b>%s</b>\n" "indeholder / men starter ikke fra roden. Brug rodning for at forhindre " "fejlnavngivne mapper ved at starte dit mønster med / or ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Sange i de viste mapper vil blive tilføjet til biblioteket under " "genindlæsning af et bibliotek" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "De valgte sange vil blive fjernet fra biblioteket." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Bibliotekssti:" msgstr[1] "Bibliotekssti:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Fjern" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Vælg mapper" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Vælg mapper" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Gemte søgninger" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Rediger gemte søgninger…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Søg i dit bibliotek ved brug af fri tekst eller QL-anmodninger" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Søg efter _skrivning" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Vis søgeresultater når brugeren stopper med at skrive" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Grænse:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Vægtning" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "anmodning" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Vis resterende tid" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hovedvindue" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Søg baglæns 10 sekunder" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Søg fremad 10 sekunder" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Giv fokus til søgeindtastningen" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Nulstil filtre og hop til sangen som afspilles" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Åbn informationsvinduet for de valgte sange" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Åbn tag-editoren for de valgte sange" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Sæt de valgte sange i kø" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Slet de valgte sange" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Vis den indbyggede søgeindtastning" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Venstreklik på en kolonne-header" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Tilføj kolonnen til listen med kolonner som sorteres efter" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Træ-visning" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Sammenfold elementet eller vælg forælder-elementet" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Udfold elementet" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Tekstindtastninger" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Omgør den sidste ændring" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Omgør den sidste fortryd-ændring" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Vælg alle sange i alle ruder" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrér efter %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Alle _headere" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Spor-headere" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Album-headere" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Personer-headere" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Dato-headere" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Fil-headere" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Produktion-headere" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Brugerdefinerede headere…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Udfold kolonne" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Fjern spor: \"%%(title)s\" fra bibliotek?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Fjern spor: \"%%(title)s\" fra bibliotek?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Fjern fra bibliotek" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Kør plugin'et \"%(name)s\" på %(count)d sang?" msgstr[1] "Kør plugin'et \"%(name)s\" på %(count)d sange?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Kør plugin'et \"%(name)s\" på %(count)d album?" msgstr[1] "Kør plugin'et \"%(name)s\" på %(count)d album?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Konfigurér plugins…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Tilføj til _kø" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "Fjern fra bibliotek…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Kan ikke vise filer" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Fejl ved visning af filer, eller der er ikke noget program til at vise dem." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Vis i filhåndtering" msgstr[1] "_Vis %(total)d filer i filhåndtering" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:443 #, fuzzy msgid "successful" msgstr "Lykkedes" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Gemning fejlede" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Download covergrafik" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Download covergrafik" msgstr[1] "Download covergrafik" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Download covergrafik" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Erstat _understregningstegn med mellemrum" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Foretag title-case af tags" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Opdel i flere _værdier" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tags fra sti" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tags erstatter de eksisterende" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tags tilføjes til de eksisterende" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Mønsteret\n" "\t<b>%s</b>\n" "er ugyldigt. Det indeholder muligvis det samme tag to gange eller det har " "ubalancerede parenteser (</>)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Mønsteret du har indtastet var ugyldigt. Sørg for at du indtaster < og " "> som \\< og \\> og at dine tags er balanceret.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Rediger visning" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Spornumre" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Start _fra:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Samlet spor:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Afspil/pause" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Forrige" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "og %d mere…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Gemmer sangene du ændrede." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d sange gemt\n" "(%(remaining)s tilbage)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s af %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Søger efter opdateringer" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Forbindelsen fejlede" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Du bruger allerede den seneste version %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "En ny version %(new-version)s er tilgængelig\n" "\n" "Du bruger i øjeblikket version %(old-version)s\n" "\n" "Besøg <a href='%(url)s'>webstedet</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importér spilleliste" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Spillelister skal have et navn" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "En spilleliste ved navn %s findes allerede." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Indlejrede albumcovere" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Bruger covere som er indlejrede i lydfiler." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Filsystemets cover" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Bruger billeder med almene navn fundet i mapper med almene mapper sammen med " "sangen." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Covergrafik" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Forespørger albumgrafik-udbydere" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Vis kortfattet forbrugsinformation" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Vis version og ophavsret" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Vis fejlretningsinformation" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Anvendelse: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[valgmulighed]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Valgmuligheden %r genkendes ikke." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Valgmuligheden %r kræver et argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r er ikke et unikt præfiks." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekund" msgstr[1] "%s sekunder" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Ingen information om tid" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minutter" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d time" msgstr[1] "%d timer" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dage" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d år" msgstr[1] "%d år" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "Pølse!" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datoen skal indtastes i formaterne 'YYYY', 'YYYY-MM-DD' eller 'YYYY-MM-DD HH:" "MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain forstærkninger skal indtastes i 'x.yy dB'-format." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain spidspunkter skal indtastes i 'x.yy'-format." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz-ID'er skal være i UUID-format." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-udgivelsesstatus skal være 'official', 'promotional', eller " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Sprog skal være en trecifret ISO 639-2-kode" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Gemning fejlede" msgstr[1] "Gemning fejlede" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Kan ikke redigere sang" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Gemning af <b>%s</b> fejlede. Filen kan være skrivebeskyttet, ødelagt eller " "du har ikke rettigheder til at redigere den." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[ugyldig kodning]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangør" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangører" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arrangement" #: quodlibet/util/tags.py:86 msgid "author" msgstr "forfatter" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "forfattere" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "kommentar" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "komponist" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "komponister" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "komposition" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenter" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigering" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "ophavsret" #: quodlibet/util/tags.py:93 msgid "date" msgstr "dato" #: quodlibet/util/tags.py:94 msgid "description" msgstr "beskrivelse" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "genrer" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "performer" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "optræden" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "gruppering" #: quodlibet/util/tags.py:98 msgid "language" msgstr "sprog" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licens" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "tekstforfatter" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "tekstforfattere" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "sangtekster" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisation" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titel" #: quodlibet/util/tags.py:105 msgid "version" msgstr "version" #: quodlibet/util/tags.py:106 msgid "website" msgstr "websted" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albumkunstner" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "disk-undertitel" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "spor" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "etiket-ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "original udgivelsesdato" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "originalt album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "original kunstner" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "optagelsesdato" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "udgivelsesland" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz optagelse-ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz udgivelsesspor-ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz udgivelse-ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz kunstner-ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz udgivelseskunstner-ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM-ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz albumstatus" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz albumtype" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz udgivelsesgruppe-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "sporets forstærkning" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "sporets spidspunkt" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albummets forstærkning" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albummets spidspunkt" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "reference loudness" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diske" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "spor" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "sidst startet" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "fulde navn" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "monteringspunkt" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personer" #: quodlibet/util/tags.py:168 msgid "year" msgstr "år" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "originalt udgivelsesår" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "bogmærke" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bitdybde" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "filformat" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "spillelister" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "datapunktsfrekvens" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "antal kanaler" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "slags" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "roller" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Lyd-tag-editor" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Rediger tags i dine lydfiler" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Afslut Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musikafspiller" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Lyt til, gennemse eller rediger din lydsamling" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso er en tag-editor med den samme brugerflade til tag-redigering som " "Quod Libet. Den giver dig mulighed for at vise og redigere tags i filen, for " "alle de filformater som den understøtter." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Understøttede filformater inkludere Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, " "MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet er et lydhåndteringsprogram. Det giver adskillige måder at vise " "dit lydbibliotek og understøttelse af internet-radio og lyd-feeds. Det har " "ekstrem fleksibel metadata-tag-redigering og -søgningsformåenheder." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Eksportér til Squeezebox-spilleliste" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Kan ikke tilføje <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Ugyldige tags" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Ugyldigt tags <b>%s</b>\n" #~ "\n" #~ "De valgte filer understøtter ikke redigering af disse tags." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Bedømmer automatisk sange når de afspilles eller springes over. Dette " #~ "bruger 'accelerated'-algoritmen fra vux af Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekunder" #, fuzzy #~ msgid "Startup" #~ msgstr "Start import" #~ msgid "Audio Feeds" #~ msgstr "Lyd-feeds" #~ msgid "_Audio Feeds" #~ msgstr "_Lyd-feeds" #~ msgid "New" #~ msgstr "Ny" #~ msgid "Automatic Library Update" #~ msgstr "Automatisk opdatering af bibliotek" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Holder dit bibliotek up-to-date med inotify. Kræver %s." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Tillader styring af Quod Libet ved brug af D-Bus-" #~ "grænsefladespecifikationen MPRIS 1.0/2.0." #~ msgid "Searching for lyrics…" #~ msgstr "Søger efter sangtekster…" #, fuzzy #~ msgid "broker username" #~ msgstr "Mægler-værtsnavn" #, fuzzy #~ msgid "broker password" #~ msgstr "mægler-port" #~ msgid "<artist>" #~ msgstr "<kunstner>" #~ msgid "<album>" #~ msgstr "<album>" #~ msgid "<title>" #~ msgstr "<titel>" #~ msgid "OK" #~ msgstr "OK" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Eksporterer metadata af valgte sange som en .tags-fil." #~ msgid "Import Metadata" #~ msgstr "Importér metadata" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Importerer metadata til valgte sange from en .tags-fil." #~ msgid "Migrate Metadata" #~ msgstr "Migrér metadata" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Kopierer de quodlibet-specifikke metadata mellem sange." #~ msgid "_Copy" #~ msgstr "_Kopiér" #~ msgid "_Paste" #~ msgstr "_Indsæt" #~ msgid "Information to copy/paste" #~ msgstr "Information til kopiér/indsæt" #~ msgid "Map tracks by disc and track number" #~ msgstr "Kortlæg spor efter disk- og spornummer" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Aktivér dette når du vil migrere metadata fra et album til et andet alt i " #~ "mens disk- og spornumrene passer sammen.\n" #~ "\n" #~ "<b>Bemærk:</b> dette skal være aktiveret når metadata kopieres for at " #~ "sporinformation vil blive gemt." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Der er %d gemte spor." #~ msgstr[1] "Der er %d gemte spor." #~ msgid "Unsupported file type" #~ msgstr "Ikke-understøttet filtype" #~ msgid "Unable to add station" #~ msgstr "Kan ikke tilføje station" #~ msgid "_Wide Mode" #~ msgstr "_Bred-tilstand" #~ msgid "Search Library" #~ msgstr "Søgebibliotek" #~ msgid "_Search Library" #~ msgstr "_Søgebibliotek" #~ msgid "Rate the playing song" #~ msgstr "Bedøm sangen som afspilles" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Vis eller skjul hovedsanglisten (udgået)" #~ msgid "Quit Program" #~ msgstr "Afslut program" #~ msgid "Top of screen" #~ msgstr "Øverst på skærmen" #~ msgid "Middle of screen" #~ msgstr "Midt på skærmen" #~ msgid "Bottom of screen" #~ msgstr "Nederst på skærmen" #~ msgid "_Clear" #~ msgstr "_Ryd" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Forhindrer GNOME-pauseskærmen i at blive aktiveret når en sang afspilles." #~ msgid "No lyrics found" #~ msgstr "Ingen sangtekster fundet" #~ msgid "_Zoom level:" #~ msgstr "_Zoomniveau:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Søg via URL'en ovenfor, hvis sangteksterne ikke kunne findes på " #~ "LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternativ søgning" #~ msgid "Web Lyrics" #~ msgstr "Websangtekster" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "Viser en sidebjælke med onlinesangtekster fra sangen som afspilles." #~ msgid "Skip Songs" #~ msgstr "Spring over sange" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Afspilning springer over sange med en bedømmelse som er det samme som " #~ "eller under den givne tærskel." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Understøtter QL-mønstre.\n" #~ "F.eks. <tt><~artist~title></tt>" #~ msgid "Burn CD" #~ msgstr "Brænd CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Brænder CD'er med K3b, Brasero eller xfburn." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Søg efter kunstner på Wikipedia" #~ msgid "" #~ "Opens a browser window with the Wikipedia article on the playing song's " #~ "artist." #~ msgstr "" #~ "Åbner et browservindue med Wikipedia-artiklen om kunstneren af sangen som " #~ "afspilles." #~ msgid "" #~ "Opens a browser window with the Wikipedia article on the playing song's " #~ "album." #~ msgstr "" #~ "Åbner et browservindue med Wikipedia-artiklen om albummet for sangen som " #~ "afspilles." #~ msgid "Search Composer in Wikipedia" #~ msgstr "Søg efter komponist på Wikipedia" #~ msgid "The single image filename to use if selected" #~ msgstr "Det eneste billedfilnavn der skal bruges hvis valgt" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "" #~ "Albumgrafik-billedefil som skal bruges når tvunget (understøtter " #~ "jokertegn)" #~ msgid "Ignore" #~ msgstr "Ignorer" #~ msgid "Keep Songs" #~ msgstr "Bevar sange" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/de.po����������������������������������������������������������������������������0000644�0001750�0001750�00000772635�14436352625�013607� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# German translation of Quod Libet # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Avoid Injury or Death # Rüdiger Arp <ruediger@gmx.net>, 2011. # Till Berger <till@mellthas.de>, 2017. # msgid "" msgstr "" "Project-Id-Version: Quod Libet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-04-20 20:12+0000\n" "Last-Translator: Martin <martin_kolbe@gmx.net>\n" "Language-Team: German <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/de/>\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.18-dev\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: .\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Mitwirkende" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Hinzugefügt" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Originaldatum" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Bewertung" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "_Wiedergabeanzahl" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Sortieren _nach …" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Einstellungen" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albenliste" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albenliste" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Alle Alben" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d Album" msgstr[1] "%d Alben" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Album-_Cover neu laden" msgstr[1] "Album-_Cover neu laden" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Titel ohne Album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d Titel" msgstr[1] "%d Titel" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d CD" msgstr[1] "%d CDs" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Ein Beispielalbum" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Einstellungen der Albenliste" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Album-_Cover anzeigen" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Die integrierte _Suchfunktion erfasst auch Mitwirkende" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Optionen" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Alben-Anzeige" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "S_chließen" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Bibliothek-Browser" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d Titel" msgstr[1] "%d Titel" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Ungültiges Muster" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albensammlung" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Alben_sammlung" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "%s ist unbekannt" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Mehrere %s-Werte" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Benutzerdefiniert" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Hinzufügen" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Entfernen" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Feld" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Zusammenführen" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Einstellungen der Albensammlung" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Anwenden" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Abbrechen" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Albenraster" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "Alben_raster" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Einstellungen des Albenrasters" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Album-_Text anzeigen" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Eintrag »Alle Alben« anzeigen" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Breitbildmodus" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Cover-Skalierung" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Dateisystem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "Dateis_ystem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Titel konnten nicht kopiert werden" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Die ausgewählten Dateien konnten nicht in die Wiedergabeliste oder " "Warteschlange kopiert werden." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Zur Bibliothek hinzufügen" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Senderlisten dürfen nur Sender-URLs enthalten, nicht jedoch Sender- oder " "Wiedergabelisten. Die folgenden URLs können nicht geladen werden:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet-Radio" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Sender hinzufügen" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Senderliste wird heruntergeladen" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Neuer Sender" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Bitte geben Sie die URL eines Internet-Radiosenders ein:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronisch" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "HipHop/Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japanisch" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indisch" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religion" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Charts" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Türkisch" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Campusradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Talk/Nachrichten" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassik" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Nachrichten" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slawisch" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Griechisch" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Möchten Sie eine Liste beliebter Radiosender laden?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "Sender _laden" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Internet-_Radio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Alle Sender" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoriten" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Keine Kategorie" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Neuer Sender …" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "Sender akt_ualisieren" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Keine Sender gefunden" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Unter %s wurden keine Internet-Radiosender gefunden." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Nichts hinzuzufügen" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Alle aufgelisteten Sender befinden sich bereits in Ihrer Bibliothek." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Zu Favoriten hinzufügen" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Aus Favoriten entfernen" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d Sender" msgstr[1] "%(count)d Sender" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Browser" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Br_owser" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "A_lle auswählen" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Unbekannt" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Alle" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Klein" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Breitbild" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Säulenförmig" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Feldmuster mit optionalem Markup, z.B. <tt>composer</tt> oder\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Einstellungen des Browsers" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Spaltenlayout" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Spalteninhalt" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Gleichmäßige Leistenbreite" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Wiedergabelisten" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Wieder_gabelisten" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Aus der Wiede_rgabeliste entfernen" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Neu" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Importieren …" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Wiedergabeliste konnte nicht importiert werden" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet kann nur Wiedergabelisten in den Formaten M3U/M3U8 und PLS " "importieren." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Löschen" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Umbenennen" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Wiedergabeliste konnte nicht umbenannt werden" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Wiedergabeliste importieren" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importieren" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "Wiedergabeliste a_nlegen …" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Was möchten Sie mit dem %d Titel tun?" msgstr[1] "Was möchten Sie mit den %d Titeln tun?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Aktion für Wiedergabeliste »%s« bestätigen" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "leer" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Beispiel-Wiedergabeliste" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Einstellungen des Wiedergabelisten-Browsers" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Wiedergabelisten-Anzeige" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Sind Sie sicher, dass Sie die Wiedergabeliste »%s« löschen möchten?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Alle Informationen zur ausgewählten Wiedergabeliste werden gelöscht und " "können nicht wiederhergestellt werden." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "»{pl_name}« um {num} Titel erweitern?" msgstr[1] "»{pl_name}« um {num} Titel erweitern?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "Titel _hinzufügen" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Neue Wiedergabeliste" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Geben Sie einen Namen für die neue Wiedergabeliste ein:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "A_nlegen" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Wiedergabeliste wird importiert.\n" "\n" "%(current)d/%(total)d Titel hinzugefügt." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Neuer Feed" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Geben Sie die URL des Podcasts oder Audio-Feeds an:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Podcasts" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Podcasts" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "_Neuer Feed …" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Aktualisieren" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Quelle auf neue Episoden überprüfen" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Neu laden" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "Alle existierenden Episoden entfernen, dann von der Quelle neu laden" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Diesen Podcast und zugehörige Episoden entfernen" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Feed konnte nicht hinzugefügt werden" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s konnte nicht hinzugefügt werden. Möglicherweise ist der Server gerade " "außer Betrieb, oder die angegebene URL enthält keinen Podcast oder Audio-" "Feed." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Das aktuelle Audio-Backend unterstützt keine URLs, Podcast-Browser " "deaktiviert." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Ergebnisse _beschränken" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "Mehrere _Abfragen erlauben" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Titelliste" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Titelliste" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud-Browser" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Suchen" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Eigene Titel" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Zu %s gehen" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Verbunden" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet ist nun verbunden, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Von %s abmelden" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Code eingeben …" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Bei %s anmelden" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud-Autorisierung" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Geben Sie den Soundcloud-Autorisierungs-Code ein:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" "Quod Libet läuft momentan nicht (fügen Sie »--run« an, um es zu starten)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "Musikbibliothek und Musikwiedergabe" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[Option]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Momentan gespielten Titel anzeigen" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Wiedergabe sofort starten" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Keine Fenster beim Programmstart anzeigen" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Nächsten Titel abspielen" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Zum vorherigen Titel oder – falls Titel noch nicht lange läuft – zum " "Titelanfang springen" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Vorherigen Titel abspielen" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Wiedergabe starten" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Wiedergabe pausieren" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Zwischen Wiedergabe/Pause umschalten" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Wiedergabe stoppen" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Lautstärke erhöhen" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Lautstärke senken" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" "Die Bewertung des aktuell wiedergegebenen Titels um einen Stern erhöhen" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" "Die Bewertung des aktuell wiedergegebenen Titels um einen Stern verringern" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Wiedergabestatus anzeigen" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Hauptfenster verbergen" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Hauptfenster anzeigen" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Hauptfenster anzeigen/verbergen" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokus auf laufenden Player setzen" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Aktive Browserfilter entfernen" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Bibliothek aktualisieren und neu einlesen" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Verfügbare Browser auflisten" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Aktuelle Wiedergabeliste anzeigen" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Aktuelle Warteschlange anzeigen" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Den aktuellen Abfragetext anzeigen" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Ohne Plugins starten" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet starten, wenn es nicht läuft" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quod Libet beenden" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Zu einer bestimmten Position im momentan abgespielten Titel gehen" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Zufallsmodus setzen oder umschalten" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Art des Zufallsmodus setzen" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Endlosschleife ein-, aus-, oder zwischen beiden Modi umschalten" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Art des Endlosschleifenmodus setzen" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Lautstärke einstellen" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Audio-Bibliothek durchsuchen" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "Abfrage" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Datei abspielen" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "Dateiname" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Die Bewertung des aktuell wiedergegebenen Titels setzen" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Aktuellen Browser einstellen" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Nach dem momentan gespielten Titel stoppen" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Neuen Browser öffnen" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Warteschlange anzeigen oder verbergen" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Nach zufälligem Wert filtern" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "Feld" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Nach Metadatenfeldwert filtern" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=Wert" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Eine Datei oder eine Abfrage zur Warteschlange hinzufügen" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" "Mehrere Dateien – durch Kommata getrennt – zur Warteschlange hinzufügen" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "Dateiname" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Dateinamen von Abfrageergebnissen auf Standardausgabe ausgeben" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Eine Datei oder eine Abfrage aus Warteschlange entfernen" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Eine Datei oder ein Verzeichnis zur Bibliothek hinzufügen" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "URL" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Muster für --print-*-Befehle festlegen" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "Muster" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argument für »%s« ungültig." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Geben Sie »%s --help« ein." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Ein Fehler ist aufgetreten" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Sie können diesen Fehler ignorieren; allerdings läuft die Anwendung " "möglicherweise nicht mehr stabil, bis sie neugestartet wird. Das Einsenden " "eines Fehlerberichts nimmt nur einen kurzen Moment in Anspruch und hilft uns " "sehr." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Fehlerbericht einsenden" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Neustarten" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Fehler ignorieren" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Fehler-Details:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Verschiedene den Fehler und Ihr System betreffende Details werden an einen " "Fremdservice gesendet (<a href='https://www.sentry.io'>www.sentry.io</a>). " "Sie können die Daten vor dem Senden unten überprüfen." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(Optional) Bitte beschreiben Sie kurz, was passierte, als der Fehler auftrat:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "Ab_senden" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Kurze Beschreibung …" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Daten, die gesendet werden:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "ein Editor für Audio-Metadaten" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "Verzeichnis" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Editor für Audio-Metadaten" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Grafik-URL-Cover-Quelle" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Lädt Cover, die über das Metadatenfeld <tt>artwork_url</tt> verlinkt sind, " "herunter. Funktioniert mit dem Soundcloud- und dem Podcast-Browser." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs-Cover-Quelle" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Lädt Cover von Discogs herunter." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm-Cover-Quelle" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Lädt Cover aus dem Cover-Art-Archiv von Last.fm herunter." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-Cover-Quelle" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Lädt Cover aus dem Cover-Art-Archiv von MusicBrainz herunter." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Kodierung umwandeln" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Behebt fehlinterpretierte Feldwert-Kodierungen im Metadaten-Editor." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Kodierung umwandeln …" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji Simple Inverter" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Wandelt Kana/Kanji nach Rōmaji um vor dem Umbenennen." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "_Japanischen Text romanisieren" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "»Kanji Kana Simple Inverter« (kakasi) wurde nicht gefunden." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Ersetzung mit regulären Ausdrücken" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Erlaubt beliebige Ersetzungen mit regulären Ausdrücken (<tt>s/von/zu/</tt>) " "beim Bearbeiten der Metadaten oder Umbenennen von Dateien." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Title case" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" "Gebräuchliche Groß-/Kleinschreibung von Titeln im Englischen auf Feldwerte " "im Metadaten-Editor anwenden." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Title _case anwenden" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Feldwerte in GROSSBUCHST_ABEN erlauben" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Übliche Groß-/Kleinschreibung von Titeln verwenden" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Gebräuchliche englische Regeln für Groß-/Kleinschreibung von Titeln " "verwenden. Beispiel: “Dark Night of the Soul”" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Erweiterte Einstellungen" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Erweiterte Konfigurationseinstellungen anpassen." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Ich weiß, was ich tue" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animierte On-screen-Anzeige" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Zeigt Titelinformationen auf dem Bildschirm beim Titelwechsel an." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Position:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Covergröße:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Anzeige" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "Schri_ft:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Links" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Zentriert" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Rechts" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "Text_ausrichtung:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Text" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Text:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Füllung:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Farben" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Schatten" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Umrandung" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Abgeru_ndete Ecken" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "Ver_zögerung:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effekte" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Anzeigemuster b_earbeiten …" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Vorschau" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Anwendungsinformationen" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Verschiedene Informationen über die Anwendung und ihre Umgebung." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Unterstützte Formate" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Konfigurationsverzeichnis" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Cacheverzeichnis" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Audio-Backend" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Nach jeder Wiedergabe (Standard)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Die Metadaten werden nach jeder Wiedergabe eines Titels in die Datei " "geschrieben, es sei denn, er wurde übersprungen. Die Anzahl der " "Überspringungen wird nicht gespeichert, wodurch unnötige Schreibvorgänge " "vermieden werden." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Nach jeder Wiedergabe oder Überspringung" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Die Metadaten werden nach jeder Wiedergabe oder Überspringung eines Titels " "in die Datei geschrieben. Diese Einstellung kann hilfreich dazu sein " "sicherzustellen, dass die Bewertungen ungeliebter, und deswegen " "übersprungener Titel in die Dateien geschrieben werden." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Einmalig, nach vollständiger Album-Bewertung" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Nach jeder Wiedergabe oder Überspringung eines Titels wird das Album des " "Titels überprüft; wenn jeder Titel des Albums bewertet wurde und die " "Bewertungen mindestens eines Titels noch nicht in seiner Datei gespeichert " "wurden, dann werden die Metadaten aller Titel des Albums in ihre Dateien " "geschrieben.\n" "\n" "Diese Einstellung vermeidet ständige Schreibvorgänge; wenn ein Album " "allerdings einmal aktualisiert wurde, muss die Aktualisierung der Metadaten " "zukünftig über das Plugin »Metadaten in Dateien aktualisieren« manuell " "vorgenommen werden." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Wenn die Metadaten eines Albums geschrieben werden, wird die " "Wiedergabeanzahl von Titeln ohne bisherige Wiedergabe auf eins gesetzt.\n" "Das kann hilfreich sein, wenn ungeliebte Titel im Spiel sind und später nach " "vollständig angehörten Alben gesucht werden soll (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "»%s« konnte nicht geschrieben werden" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Metadaten in Dateien automatisch aktualisieren" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Geänderte Metadaten in Dateien nach der Wiedergabe aktualisieren. Stellt " "sicher, dass Wiedergabeanzahl und Bewertungen aktuell sind." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Die folgende Einstellung wurde aktiviert, da sie zum Betrieb dieses Plugins " "notwendig ist:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Bewertungen und _Wiedergabeanzahl in Metadaten speichern" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Einstellungen aktualisiert" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Fehler in %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" "Beim Speichern sicherstellen, dass die Wiedergabeanzahl größer null ist" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Aktualisierungsstrategie:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Einstellungen" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatische Maskierung" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Maskiert und demaskiert Laufwerke automatisch, wenn sie aus- oder eingehängt " "werden." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatische Bewertung" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Bewertet Titel automatisch, wenn sie abgespielt oder übersprungen werden. " "Benutzt den »beschleunigten« Algorithmus aus vux (Vacillating Utilitarian " "eXtemporizer) von Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Die angegebene Banshee-Datenbank ist ungültig oder nicht vorhanden" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Import fehlgeschlagen" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Bewertungen und Statistiken für %d Titel erfolgreich importiert" msgstr[1] "Bewertungen und Statistiken für %d Titel erfolgreich importiert" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee-Import" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Bewertungen und Titelstatistiken von Banshee importieren." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Datenbankpfad:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Import starten" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Wecker" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Weckt mit lauter Musik." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Schlaflied" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Blendet die Musik aus und pausiert sie." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord-Statusnachricht" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discord-Statusnachricht" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Aktualisiert Ihre Discord-Statusnachricht entsprechend dem gerade " "abgespielten Titel." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Pausiert" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Statuszeile 1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Statuszeile 2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Flach" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Live" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Voller Bass & volle Höhen" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Club" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Große Halle" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Party" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Weich" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Voller Bass" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Kopfhörer" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Soft Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Volle Höhen" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizer" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Steuert den Klang der Musik mit einem Equalizer.\n" "Klicken oder die Tastatur zum Anpassen der Pegel verwenden (ein Rechtsklick " "setzt das Frequenzband zurück)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Das aktuelle Backend unterstützt keine Equalizer-Funktionalität." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Standardvorgaben" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Auswählen …" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "Equalizer _zurücksetzen" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Benutzerdefinierte Vorgaben" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "Ausgewählte löschen" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Vorgabename zum Speichern:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Speichern" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "online" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "offline" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "zum Chatten bereit" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "abwesend" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "länger abwesend" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "unsichtbar" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim-Statusnachricht" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" "Aktualisiert Ihre Gajim-Statusnachricht entsprechend dem gerade abgespielten " "Titel." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "pausiert" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Muster:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Geben Sie die Konten an, für die die Statusnachricht aktualisiert werden " "soll. Mehrere Konten werden durch Leerzeichen getrennt. Sind keine Konten " "angegeben, wird die Statusnachricht aller Konten aktualisiert." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Konten:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "»[paused]« anfügen" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Wenn gewählt, wird der Statusnachricht »[paused]« angefügt, während die " "Wiedergabe pausiert ist" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Status, für die die Statusnachricht aktualisiert wird" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pause bei Ausstecken der Kopfhörer" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pausiert die Wiedergabe, wenn die Kopfhörer ausgesteckt werden, und setzt " "sie fort, wenn die Kopfhörer wieder eingesteckt werden." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Bildschirmschoner/Bereitschaftsmodus blockieren" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Verhindert entweder, dass der Bildschirmschoner aktiviert wird, oder dass " "der Rechner in den Bereitschaftsmodus versetzt wird, solange ein Titel " "wiedergegeben wird (nur auf dem GNOME-Desktop)." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musik wird wiedergegeben" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Modus:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Bildschirmschoner blockieren" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Bereitschaftsmodus blockieren" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Internet-Radio-Log" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Zeichnet die letzten 10 Titel, die von Internet-Radio-Sendern gespielt " "wurden, auf. Die Titel werden im Titelpositions-Kontextmenü aufgelistet." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Speichert eine Jabber-User-Tunes-Datei in %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Sprache ändern" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Die Sprache der Benutzeroberfläche ändern." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Systemvorgabe" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Ein Neustart ist notwendig, damit Änderungen wirksam werden" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP-AV-Mediaserver" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Stellt alle Alben dem Rygel-UPnP-Mediaserver über das MediaServer2-D-Bus-" "Interface bereit." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Die folgenden Angaben müssen sich in der rygel-Konfigurationsdatei befinden " "(~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD-Server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Erlaubt die Fernsteuerung von Quod Libet über einen MPD-Client. Streaming, " "Wiedergabelisten- und Bibliotheksverwaltung werden nicht unterstützt." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokale _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "P_asswort:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Verbindung" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Getestete Clients" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS-D-Bus-Unterstützung" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Aktiviert Unterstützung für die <a href=\"https://mpris2.readthedocs.io/en/" "latest/\">MPRIS-2-D-Bus-Interface-Spezifikation</a>, sodass Quod Libet auf " "dem Linux-Desktop über Multimedia-Tasten gesteuert werden kann." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Hauptfenster beim Schließen verbergen" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Akzeptiert QL-Muster, z.B. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT-Publisher" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Veröffentlicht Statusnachrichten an ein MQTT-Thema." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Broker-Hostname/IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Vorgabe ist localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Broker-Port" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Vorgabe ist 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Broker-Benutzername" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Broker-Passwort" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Thema" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Muster für Wiedergabe" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" "Statustext für den Fall, dass die Wiedergabe eines Titels gestartet wird." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Muster für Pause" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Statustext für den Fall, dass die Wiedergabe pausiert ist." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Text bei gestoppter Wiedergabe" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Einfacher Text für den Fall, dass aktuell kein Titel abgespielt wird" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT-Konfiguration" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Statustext" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Verbunden mit Broker unter %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Konnte nicht mit %(host)s:%(port)d verbinden (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Verbindungsfehler" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz-Synchronisierung" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synchronisiert die Bewertung eines Titels mit MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Benutzer_name:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Passwort:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Benachrichtigungstext" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Titel:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Standardmuster wiederherstellen" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Inhalt:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Benachrichtigung anzeigen" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Benachrichtigungen anzeigen" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Nur bei <i>_manuellem</i> Wechseln des Titels" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Nur bei <i>_automatischem</i> Wechsel des Titels" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Bei <i>_jedem</i> Wechsel des Titels" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Nur, wenn das Hauptfenster nicht _fokussiert ist" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "»_Nächster«-Knopf anzeigen" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Verbindungsfehler" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Konnte nicht mit dem Benachrichtigungs-Daemon verbinden." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Wiedergabebenachrichtigungen" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" "Eine Benachrichtigung anzeigen, wenn der wiedergegebene Titel wechselt." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Nächster" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Lesezeichenbenachrichtigungen" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Benutzt Benachrichtigungen, um Lesezeichen und Kommentare in Echtzeit " "anzuzeigen. Hervorragend für die Verwendung im Soundcloud-Browser geeignet." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Bitte rufen Sie das Plugin-Fenster auf, um QLScrobbler einzurichten. Solange " "werden keine Titel gesendet." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Konnte den Service »%s« nicht kontaktieren." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Authentifizierung fehlgeschlagen: Ungültige URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Authentifizierung fehlgeschlagen: Ungültiger Benutzername »%s« oder falsches " "Passwort." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Client wurde verboten. Kontaktieren Sie den Autor." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Falsche Systemzeit. Einsendungen schlagen möglicherweise fehl, bis das " "Problem behoben ist." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Audioscrobbler-Einsendung" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler-Client für Last.fm, Libre.fm und andere Audioscrobbler-" "Services." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Authentifizierung erfolgreich." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Service:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Anderer …" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "Kontodaten _verifizieren" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Künstler-Muster:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Titel-Muster:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Ausschluss_filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Das Muster, das zur Formatierung des Künstlernamens für die Einsendung " "verwendet wird. Frei lassen für die Standardeinstellung." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Das Muster, das zur Formatierung des Titels für die Einsendung verwendet " "wird. Frei lassen für die Standardeinstellung." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Titel, die diesem Filter entsprechen, werden nicht eingesendet" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Offlinemodus (nichts einsenden)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Einsendung" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Radio-Werbeanzeigen stummschalten" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Die Tonausgabe stummschalten während Werbeanzeigen im Radio abgespielt " "werden.\n" "Sender: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Zufälliges Album wiedergeben" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Startet die Wiedergabe eines zufälligen Albums, wenn die Wiedergabeliste ihr " "Ende erreicht. Setzt voraus, dass der aktive Browser das Filtern nach Album " "unterstützt." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Höher bewertet" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Häufiger abgespielt" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Häufiger übersprungen" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Kürzlich abgespielt" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Kürzlich angespielt" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Kürzlich hinzugefügt" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Längere Alben" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "Sekunden, bevor das nächste Album gestartet wird" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Gewichte" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Einige Alben häufiger als andere abspielen" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "vermeiden" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "bevorzugen" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Zufälliges Album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Warte bis zum Start von %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Bewertungen und Statistiken für %d Titel erfolgreich importiert" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox-Import" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Bewertungen und Titelstatistiken von Rhythmbox importieren." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Bildschirmschoner-Pause" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pausiert die Wiedergabe während der GNOME-Bildschirmschoner aktiv ist." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Kein GNOME-Shell-Suchprovider für Quod Libet installiert." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME-Suchprovider" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Erlaubt es GNOME Shell, die Bibliothek zu durchsuchen." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternative Titelpositionsleiste" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternative Titelpositionsleiste, die immer sichtbar ist und die ganze " "Fensterbreite nutzt." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Titelpositions-Lesezeichen" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Titelpositionen A und/oder B für Titel speichern. Zu Position A springen und " "bei Position B stoppen, wenn der Titel wiedergegeben wird.\n" "\n" "ℹ Beachten Sie, dass das Ändern der Bezeichnungen der Positionen unten nicht " "die tatsächlichen Lesezeichennamen ändert; die Bezeichnungen legen nur fest, " "nach welchen Lesezeichennamen das Plugin schaut, um zu entscheiden, ob " "gesprungen werden soll." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Lesezeichenname für Position A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Lesezeichenname, nach dem gesucht werden soll, wenn die Wiedergabe eines " "Titels gestartet wird. Wenn dieser gefunden wird, springt der Player zu " "dieser Position" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Lesezeichenname für Position B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Lesezeichenname, der verwendet werden soll, um zu jedem Zeitpunkt während " "der Wiedergabe eines Titels zu prüfen, ob er existiert. Überschreitet die " "aktuelle Position den Zeitstempel, springt der Player zum Ende des Titels." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox-Synchronisierung" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Sorgt dafür, dass Logitech Squeezebox die Ausgabe von Quod Libet spiegelt. " "Dafür müssen beide von derselben Bibliothek lesen." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Teilt die Konfiguration mit dem <a href=\"%(plugin_link)s\">Squeezebox-" "Export-Plugin</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Fehler beim Finden des Squeezebox-Servers" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fehler beim Finden von %s. Bitte überprüfen Sie die Einstellungen" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Beim Pausieren stoppen" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Dieses Plugin ändert die Pause-Funktion zu Stop/Wiedergabe/Titelposition " "ändern.\n" "\n" "Dieses Verhalten ist nützlich, wenn Quod Libet das Audiogerät nicht wechseln " "kann, wenn ein neues zum System hinzugefügt wird (Bluetooth-Lautsprecher, " "USB-DAC etc.).\n" "\n" "Sorgt dafür, dass die Titelposition in der aktuellen Quelle beibehalten " "wird, solange die Option »Nur Quellen, die Anpassen der Titelposition " "erlauben« nicht ausgewählt ist. Andernfalls wird die Wiedergabe angehalten " "und muss von vorne beginnen." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Nur Quellen, die Anpassen der Titelposition erlauben" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Pluginoptionen" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Kopieren steht aus" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Löschen steht aus" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "Löschen" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Überspringen" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLIKAT" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Synchronisiere" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Lösche" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Erfolg" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "FEHLSCHLAG" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Existierende Datei ausgelassen" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Kann den Dateinamen eines Titels nicht setzen." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Zu Gerät synchronisieren" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchronisiert alle Titel, die auf die ausgewählten Suchläufe zutreffen, mit " "dem angegebenen Ordner." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Die folgenden gespeicherten Suchläufe synchronisieren:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Der absolute Pfad zum Exportverzeichnis" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Alle im Zielordner existierenden Dateien, die nicht in den gewählten " "Suchläufen enthalten sind, werden gelöscht." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "Für Geräte, die mit MTP eingebunden sind, exportieren Sie in einen lokalen " "Zielordner, und transferieren Sie ihn dann mit rsync auf das Gerät. Oder " "nutzen Sie adb-sync, was deutlich schneller ist, wenn Sie viele Dateien zu " "einem Android-Gerät synchronisieren." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Zielpfad:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Muster für Dateipfade" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Gespeicherte Muster bearbeiten …" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Die Struktur der exportierten Dateinamen, basierend auf den Metadaten" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Exportmuster:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Vorschau anhalten" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Quelldatei" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Exportpfad" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Doppelte Exportpfade erkannt! Die Exportpfade können oben vor Start der " "Synchronisierung geändert werden." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Im Zielordner existierende Dateien werden gelöscht (mit Ausnahme von Dateien " "mit dem Namen »cover.jpg«)!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Synchronisierung starten" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Synchronisierung anhalten" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" "Noch keine gespeicherten Suchläufe vorhanden. Erstellen Sie welche und " "kommen Sie wieder!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Zielpfad wählen" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Exportpfad wurde von [{old_path}] zu [{new_path}] geändert für Datei " "[{filename}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Starte Synchronisierungsvorschau" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Synchronisierungsvorschau wird erstellt." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Synchronisierungsvorschau erstellt" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Halte Synchronisierungsvorschau an" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Synchronisierungsvorschau wurde angehalten." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Synchronisierungsvorschau erstellt." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Synchronisierungsvorschau angehalten" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Ein anderes Plugin wurde ausgewählt – Vorschau anhalten" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Die Synchronisierung wird:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "{count} Datei schreiben" msgstr[1] "{count} Dateien schreiben" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "{count} doppelte Datei auslassen" msgstr[1] "{count} doppelte Dateien auslassen" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "{count} Datei löschen" msgstr[1] "{count} Dateien löschen" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Kein Zielpfad angegeben" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" "Bitte geben Sie den Ordner an, in den die Titel exportiert werden sollen." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Kein Exportmuster angegeben" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" "Bitte geben Sie ein Exportmuster für die Dateinamen der zu exportierenden " "Titel an." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Exportpfad ist nicht absolut" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Das Muster\n" "\n" "{}\n" "\n" "enthält »/«, startet aber nicht vom Wurzelverzeichnis. Bitte geben Sie einen " "absoluten Zielpfad an, indem Sie sicherstellen, dass dieser mit »/« oder " "»~/« beginnt." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Keine Suchläufe ausgewählt" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Bitte wählen Sie mindestens einen gespeicherten Suchlauf aus." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Keine Titel durch die gewählten Suchläufe ausgewählt" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Die gewählten Suchläufe sind leer." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "{} zu synchronisierende Titel gefunden" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Zielpfad und Exportmuster passen nicht zusammen" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Das Exportmuster startet mit einem Pfad, der sich vom Zielpfad " "unterscheidet. Bitte korrigieren Sie das Muster.\n" "\n" "Fehler:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Synchronisierung kann nicht gestartet werden" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" "Die Synchronisierung kann nicht gestartet werden, solange nach <b>Status</b> " "sortiert wird." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Starte Titelsynchronisierung" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Synchronisierung läuft." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Titelsynchronisierung abgeschlossen" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Halte Titelsynchronisierung an" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Synchronisierung wurde angehalten." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Synchronisierung abgeschlossen." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Titelsynchronisierung angehalten" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Ein anderes Plugin wurde ausgewählt – halte Synchronisierung an" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} – »{filename}«" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Entferne »{}«" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Die Synchronisierung hat:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "{count}/{total} Datei geschrieben" msgstr[1] "{count}/{total} Dateien geschrieben" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "({count} existierende Datei ausgelassen)" msgstr[1] "({count} existierende Dateien ausgelassen)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "{count}/{total} doppelte Datei ausgelassen" msgstr[1] "{count}/{total} doppelte Dateien ausgelassen" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "{count}/{total} Datei gelöscht" msgstr[1] "{count}/{total} Dateien gelöscht" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "{count} Datei nicht erfolgreich synchronisiert" msgstr[1] "{count} Dateien nicht erfolgreich synchronisiert" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "{count} schon synchronisierte Datei ausgelassen" msgstr[1] "{count} schon synchronisierte Dateien ausgelassen" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synchronisierte Liedtexte" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Zeigt Liedtexte aus einer .lrc-Datei mit demselben (oder einem ähnlichen) " "Namen wie der abgespielte Titel synchron an." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Text:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Hintergrund:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Schrift" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Größe (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy-Statusnachrichten" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Aktualisiert alle Telepathy-basierten Instant-Messenger-Konten (wie in " "Empathy u.ä. konfiguriert) mit einer Statusnachricht, die auf dem aktuell " "abgespielten Titel basiert." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Wiedergabe:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Statustext für den Fall, dass die Wiedergabe eines Titels gestartet wird. " "Akzeptiert QL-Muster wie z.B. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Pausiert:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Statustext für den Fall, dass die Wiedergabe pausiert ist. Akzeptiert QL-" "Muster wie z.B. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Einfacher Text für den Fall, dass aktuell kein Titel abgespielt wird" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Keine Wiedergabe:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Statusmuster" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Erscheinungsbild-Wechsler" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Ändert das aktive GTK+-Thema." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Thema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Standardthema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Die dunkle Themenvariante bevorzugen" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Daumen-Bewertung" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Fügt ein Daumen-hoch/Daumen-runter-Bewertungssystem hinzu. Die Daumen-" "Bewertung wird in eine reguläre Bewertung umgewandelt. Nützlich, um " "Abstimmungssummen zu verfolgen und nach <b><tt>~#score</tt></b> zu sortieren." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Menüleiste anzeigen/verbergen" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Die Menüleiste durch Drücken der Alt-Taste anzeigen oder verbergen." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Keine Wiedergabe" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Taskleistensymbol" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Steuert Quod Libet von der System-Taskleiste aus." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "%(application-name)s anz_eigen" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "Abs_pielen" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Vorheriger" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Nächster" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Zufall" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "En_dlosschleife" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "N_ach diesem Titel stoppen" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "_Browser öffnen" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "_Metadaten bearbeiten" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informationen" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Wieder_gabelisten" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Beenden" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Verhalten" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Mausrad passt die Lautstärke an" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Mausrad wechselt den wiedergegebenen Titel" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Maus_rad" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Tooltip-Anzeige" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Liedtext anzeigen" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Zeigt metadaten- oder dateibasierte Liedtexte automatisch in einer " "Seitenleiste an." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Es wurden keine Liedtexte gefunden für\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Kein aktiver Titel" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Visualisierungen starten" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Externe Visualisierungen starten." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Visualisierungen konnten nicht mit »%s« ausgeführt werden" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Fehler" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Visualisierungsanwendung:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Neu laden" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Wellenform-Titelpositionsleiste" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" "∿ Eine Titelpositionsleiste in Gestalt der Wellenform des aktuell " "abgespielten Titels." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Vordergrund-Farbe überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Mouse-over-Farbe überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Farbe für die verbleibende Zeit überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Aktuelle Position anzeigen" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Zeitmarken anzeigen" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Titelpositionsbetrag beim Scrollen (Millisekunden):" # »Grafiksicherer« oder »Grafikspeicherer« ist in meinen Augen weniger klar #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Grafik speichern" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Speichert das Coverbild des aktuell abgespielten Titels in eine Datei." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Datei:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Schwellenwert:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Schwellenwert, ab dem der Filter aktiviert wird" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "R_ate:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Kompressionsrate" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Audiokompressor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Ändert die Amplitude aller Samples, die über einem spezifischen " "Schwellenwert liegen, mit einer spezifischen Kompressionsrate." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Vorgabe:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filtervorgabe" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "Grenz_frequenz:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Tiefpassfilter-Grenzfrequenz" # Ich weiß nicht, ob das eine treffende Übersetzung ist. Wenn jemand mehr Ahnung von der Materie hat, bitte verbessern #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Einspeis_pegel:" # Ich weiß nicht, ob das eine treffende Übersetzung ist. Wenn jemand mehr Ahnung von der Materie hat, bitte verbessern #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Einspeispegel" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Standard" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Einer virtuellen Lautsprecher-Aufstellung am nächsten (30°, 3 Meter)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Ähnlich zu Chu Moys Crossfeeder (beliebt)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Ähnlich zu Jan Meiers CORDA-Verstärkern (wenig Änderung)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Benutzerdefiniert" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Benutzerdefinierte Einstellungen" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mischt den linken und den rechten Kanal derart, dass ein Lautsprechersetup " "bei der Benutzung von Kopfhörern simuliert wird, oder um die Ausgabe für " "frühe Stereoaufnahmen anzupassen." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filter_band:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Das Frequenzband des Filters" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filterb_reite:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Die Frequenzbreite des Filters" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Grad:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Grad des Effekts" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Entfernt die Hauptgesangsstimme aus dem Audiosignal." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono-Downmix" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Mischt die Audiokanäle zu einem Monosignal." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "R_ate:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "Ton_höhe:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Audio-Tonhöhe/-Geschwindigkeit" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Steuert die Tonhöhe eines Audiostroms." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Wiedergabeliste in Ordner exportieren" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exportieren" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Zielordner:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Muster für Dateinamen:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" "Eine Wiedergabeliste exportieren, indem die Dateien in einen Ordner kopiert " "werden." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Die Wiedergabeliste konnte nicht exportiert werden" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" "Stellen Sie sicher, dass sie Schreibzugriff auf das Zielverzeichnis haben." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Standardmuster für Dateinamen:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Geben Sie einen Namen für eine neue Wiedergabeliste ein,\n" "oder wählen Sie eine existierende Sonos-Wiedergabeliste zum Überschreiben aus" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "In Sonos-Wiedergabeliste exportieren" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "" "Eine Wiedergabeliste exportieren, indem die Dateien in einen Ordner kopiert " "werden." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Fehler beim Finden der Sonos-Geräte" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Fehler beim Finden von Sonos. Bitte überprüfen Sie die Einstellungen" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Fehler beim Löschen der vorhandenen Sonos Wiedergabeliste %s:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Exportiere in Wiedergabeliste %(playlist)r (%(total)d Titel)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Squeezebox-Export" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Exportiert dynamisch eine Wiedergabeliste zu einer Logitech-Squeezebox-" "Wiedergabeliste. Dafür müssen beide dieselbe Verzeichnisstruktur teilen." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Teilt die Konfiguration mit dem <a href=\"%(plugin_link)s\">Squeezebox-" "Synchronisierungs-Plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Wiedergabeliste zu Squeezebox exportieren" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Name der Wiedergabeliste (wird den existierenden überschreiben)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Zu Squeezebox-Wiedergabeliste exportieren" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Duplikate in Wiedergabelisten entfernen" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Entfernt doppelte Einträge in einer Wiedergabeliste." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Sind Sie sicher, dass Sie %d Duplikat entfernen möchten?" msgstr[1] "Sind Sie sicher, dass Sie %d Duplikate entfernen möchten?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplikate werden aus der Wiedergabeliste »%s« entfernt." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Wiedergabeliste durcheinanderwürfeln" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Ordnet die Einträge einer Wiedergabeliste auf zufällige Weise neu an." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Cursor folgen" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Fügt einen Wiedergabemodus hinzu, bei dem die Wiedergabe der Auswahl folgt. " "Ist die Auswahl erschöpft, wird der nächste Titel in der Liste wiedergegeben." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Cursor folgen" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Cursor folgen" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Wiedergabeanzahl ausgleichen" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Fügt einen Zufallsmodus hinzu, bei dem Titel bevorzugt werden, die seltener " "wiedergegeben wurden." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Seltener wiedergegebene bevorzugen" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "_Seltener wiedergegebene bevorzugen" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Nur Warteschlange" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Beschränkt die Wiedergabe von Titeln auf die Warteschlange.\n" "\n" "Wenn diese Wiedergabereihenfolge im Hauptfenster gewählt ist, fügt ein " "Doppelklick auf einen beliebigen Titel diesen der Warteschlange hinzu, " "anstatt ihn wiederzugeben." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Nur Warteschlange" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "Nur _Warteschlange" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Doppelklick startet Wiedergabe" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Umkehren" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Fügt einen Zufallsmodus hinzu, der die Wiedergabereihenfolge von Titeln " "umkehrt." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Um_kehren" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Zufällige Wiedergabe nach Gruppierung" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Fügt einen Zufallsmodus hinzu, der über ein gemeinsames Metadatenfeld " "definierte Gruppierungen von Titeln per Zufall wiedergibt, ähnlich dem Modus " "»Zufälliges Album wiedergeben«.\n" "\n" "Dieser Modus erlaubt es, mehrsätzige klassische Werke in zufälliger " "Reihenfolge wiederzugeben, ohne dabei die Originalreihenfolge der einzelnen " "Sätze eines Werkes zu verändern." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Zufall nach Gruppierung" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "Zufall nach _Gruppierung" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Warte auf den Start einer neuen Gruppe …" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Gruppierungsfeld:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Feld, nach dem Titel gruppiert werden" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filterfeld:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Eine Gruppierung wird nur angewendet, wenn das Filterfeld definiert ist.\n" "Ein Titel mit einem undefinierten Filterfeld wird als eigenständige Gruppe\n" "behandelt. Üblicherweise sollte das Filterfeld dem Gruppierungsfeld\n" "vollständig oder teilweise entsprechen." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Verzögerung:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Verzögerung in Sekunden, bevor die nächste Gruppierung gestartet wird" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Standardwerte wiederherstellen" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Ungeliebte Titel überspringen" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Fügt einen Zufallsmodus hinzu, der Titel in der Ursprungsreihenfolge " "wiedergibt, aber Titel mit einer Bewertung unter (oder gleich) einem " "gegebenen Schwellenwert überspringt." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Ungeliebte Titel überspringen" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "_Ungeliebte Titel überspringen" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Jeden Titel wiederholen" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Fügt einen Wiedergabemodus hinzu, der Titel in der ursprünglichen " "Reihenfolge wiedergibt, dabei aber jeden Titel eine feste Anzahl von Malen " "wiederholt." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Jeden Titel wiederholen" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "_Jeden Titel wiederholen" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Anzahl der Wiedergaben pro Titel:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Bedingte Abfrage" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" "Erlaubt es, eine Abfrage abhängig von einer Bedingungsabfrage zu wählen." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: Bedingungsabfrage, Dann-Abfrage, Sonst-Abfrage)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Abfrage nach fehlenden Metadaten" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Titel ohne das angegebene Metadatenfeld finden." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Leere Felder einschließen" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python-Abfrage" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍 Python-Ausdrücke in Abfragen verwenden." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: Ausdruck)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Die Variable <tt>s</tt> (oder <tt>a</tt>) ist der Titel (bzw. das Album), " "auf dem die Abfrage aktuell arbeitet.\n" "\n" "<tt>_ts</tt> ist ein Zeitstempel (reelle Zahl) zu Beginn der Abfrage.\n" "\n" "Die Module <tt>time</tt> und <tt>random</tt> sind verfügbar, ebenso wie die " "Klasse <tt>Random</tt> (<tt>random.Random</tt>)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Gespeicherten Suchlauf einschließen" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" "💾 Die Ergebnisse eines gespeicherten Suchlaufs als Teil einer anderen " "Abfrage einschließen." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: Suchlaufname)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Einmalige Abfrage" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Suchergebnisse nach eindeutigen Metadaten filtern." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: tag)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox okay. Nutze den einzigen Player (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Konnte nicht mit %s verbinden" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Hostname:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Benutzername:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Passwort:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Bibliotheksverzeichnis, mit dem sich der Server verbindet" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Bibliothekspfad:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "Einstellungen _verifizieren" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox-Server" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Debug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-Server unter {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "Unidentifizierter Squeezebox-Server" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "Unidentifizierter Squeezebox-Player: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Squeezebox-Player auswählen" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Squeezebox-Server gefunden.\n" "Bitte wählen Sie den Player" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Grafik an _Fenster anpassen" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Siehe den Konfigurationseintrag »[plugins] cover_filenames« für " "Bilddateinamen" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programm:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "Bild nach Speichern b_earbeiten" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Datei_name:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Speichern fehlgeschlagen" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "»%s« konnte nicht gespeichert werden." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-Fehler: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Album-Cover-Downloader" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "von %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Auflösung: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Größe: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Ergebnis-Limit pro Suchengine" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Suche" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Suche läuft …" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Fertig" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Alben-Cover herunterladen" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Alben-Cover von verschiedenen Websites herunterladen." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Quellen" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 zu ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Wandelt APEv2-Tags in ID3v2-Tags um. Löscht die APEv2-Tags nach der " "Umwandlung." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Zu Lesezeichen gehen" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Lesezeichen in den ausgewählten Dateien verwalten." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Lesezeichen bearbeiten …" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Keine Lesezeichen" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-Lookup" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" "Versieht ein Album basierend auf einer MusicBrainz-Suche mit neuen Metadaten." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Nur das Jahr für das »date«-Feld verwenden" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "»_albumartist« schreiben, wenn nötig" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Sortierungsfelder für Künstlernamen schreiben" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "_Standard-MusicBrainz-Felder schreiben" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "»labelid«-Feld schreiben" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Dateiname" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "CD" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Titel-Nr." #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Titel" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Künstler" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz-Lookup" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "Ab_frage:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "Such_en" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Ergebnisse <i>(zum Ändern der Reihenfolge ziehen)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Bitte geben Sie eine Abfrage ein." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Lade Ergebnis …" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Keine Ergebnisse gefunden." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python-Konsole" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktive Python-Konsole. Öffnet ein neues Fenster." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} für {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python-Konsole-Seitenleiste" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Eine interaktive Python-Konsole in der Seitenleiste, die den im Hauptfenster " "ausgewählten Titeln folgt." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Sie können standardmäßig auf die folgenden Objekte zugreifen:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Ihr aktuelles Arbeitsverzeichnis ist:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Vervollständigung" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Cover-Art herunterladen" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Lädt Alben-Cover in hoher Qualität über Cover-Plugins herunter." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klassisch" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Groß" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Cover-Art-Downloader" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "%(source)s – %(dimensions)s wird geladen …" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Keine Ergebnisse für die folgenden Alben:\n" "%(albums)s.\n" "\n" "Verwendete Provider:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Keine Cover gefunden" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Vorschaugröße" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Speicherort" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Das Bild in ein hochqualitatives JPEG derselben Größe konvertieren, sofern " "es noch kein JPEG ist" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Als JPEG speichern" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Befehl" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "Name" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Der Name dieses Befehls" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "Befehl" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Der Shellbefehl, der ausgeführt werden soll" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "Parameter" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Ein Parameter, dessen Vorkommen im Befehl mit einem benutzerspezifizierten " "Wert ersetzt werden. Beispiel: Ist der Feldwert »PARAM«, werden alle " "Vorkommen von »{PARAM}« im Befehl mit dem Wert ersetzt, den der Benutzer in " "einer Eingabeaufforderung eingibt" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Das QL-Muster, z.B. <~filename>, das benutzt werden soll, um einen Wert für " "den Befehl zu berechnen. Für Wiedergabelisten werden auch die virtuellen " "Felder <~playlistname> und <~#playlistindex> unterstützt." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "Einzigartig" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Wenn gesetzt, werden Duplikate aus der Ergebnisliste des Musters entfernt" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "Maximale Argumente" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Die maximale Anzahl an Argumenten, die dem Befehl zur selben Zeit übergeben " "werden sollen (wie xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "Umkehren" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Wenn gesetzt, wird die Reihenfolge der Argumente umgekehrt" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Eingabewert" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Wert für %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Benutzerdefinierte Befehle" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Benutzerdefinierte Befehle auf Titel anwenden, wobei beliebige ihrer " "Metadatenfelder benutzt werden können. Stapelverarbeitung ist bei Bedarf " "möglich." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Benutzerdefinierte Befehle bearbeiten" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Der benutzerdefinierte Befehl »%s« konnte nicht ausgeführt werden" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d Duplikatgruppe" msgstr[1] "%d Duplikatgruppen" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Alle einklappen/ausklappen" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Schlüsselausdruck für Duplikate ist »%s«" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Duplikatbrowser" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" "Findet Versionen von Titeln mit ähnlichen Metadaten und zeigt diese an." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Akzeptiert QL-Feldausdrücke wie <tt>~artist~title</tt> oder " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "Duplikate _gruppieren nach:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplikatschlüssel" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "_Leerräume entfernen" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "_Diakritische Zeichen entfernen" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "_Interpunktion entfernen" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Groß-/Kleinschreibung _nicht beachten" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Optionen für die Übereinstimmung" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Wiedergabeanzahl bearbeiten" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Bearbeitet die Anzahl der Wiedergaben und des Überspringens für einen Titel " "(<tt>~#playcount</tt> bzw. <tt>~#skipcount</tt>).\n" "\n" "Sind mehrere Titel ausgewählt, werden die Werte inkrementiert statt " "gesetzt.\n" "\n" "Wird <tt>~#playcount</tt> für einen Titel auf 0 gesetzt, werden die Einträge " "<tt>~#lastplayed</tt> und <tt>~#laststarted</tt> geleert. Wenn allerdings " "ein Titel mit 0 Wiedergaben auf eine positive Anzahl gesetzt wird, werden " "keine Wiedergabezeiten erzeugt." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Anzahl der Wiedergaben" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Anzahl übersprungen" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Mehrere Dateien ausgewählt." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Werte werden inkrementiert." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Eingebettete Bilder bearbeiten" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" "Ermöglicht es, eingebettete Bilder hinzuzufügen, zu entfernen oder zu " "ersetzen." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Einbetten" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Bild zum Einbetten in %d Titel auswählen" msgstr[1] "Bild zum Einbetten in %d Titel auswählen" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "Alle Bilder entfe_rnen" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "Aktuelles Bild _einbetten" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "Bild _auswählen …" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Exakte Bewertung setzen" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Erlaubt es, die Bewertung eines Titels mit einer Zahl zu setzen." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" "Bitte geben Sie die gewünschte Bewertung auf einer Skala von 0.0 bis 1.0 an" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Nach beliebigen Metadaten filtern" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Erzeugt eine Abfrage, die auf Metadaten des ausgewählten Titels basiert." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Nach Verzeichnis filtern" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Nach Verzeichnis in einem neuen Browser-Fenster filtern." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akustischer-Fingerabdruck-Lookup" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Schlägt Titelmetadaten über den akustischen Fingerabdruck nach." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Akustische Fingerabdrücke einsenden" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Generiert akustische Fingerabdrücke mit chromaprint und sendet diese an " "acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API-Schlüssel fehlt" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Sie müssen einen acoustid.org-API-Schlüssel in den Plugin-Einstellungen " "angeben, bevor Sie Fingerabdrücke einsenden können." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "API-Schlüssel anfordern" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API-_Schlüssel:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID-Webservice" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Warteschlange" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analysiere" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Nachschlagen" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Schreiben" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Veröffentlichung" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "MusicBrainz-Felder schreiben" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Nach Verzeichnis gruppieren" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Album-Modus" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Albumbezogene Metadatenfelder schreiben und versuchen, die Anzahl " "verschiedener Albumveröffentlichungen zu reduzieren" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generiere Fingerabdrücke:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Details" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "Ein_senden" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Titel brauchen entweder eine <i><b>musicbrainz_trackid</b></i>, oder " "<i><b>artist</b></i>-/<i><b>title</b></i>-/<i><b>album</b></i>-Felder, um " "eingesendet werden zu können." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Fingerabdrücke:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Titel mit MBIDs:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Titel mit ausreichenden Metadaten:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Einzusendende Titel:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Fertig. %(to-send)d/%(all)d Titel einzusenden." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Sende Fingerabdrücke:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Sende ein …" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Metadaten in Dateien aktualisieren" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Geänderte Metadaten in Dateien aktualisieren. Stellt sicher, dass " "Wiedergabeanzahl und Bewertungen aktuell sind." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Nach HTML exportieren" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exportiert die ausgewählte Titelliste nach HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "An iFP senden" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Titel zu einem iRiver-iFP-Gerät hochladen." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Kein iFP-Gerät gefunden" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Ihr iFP-Gerät konnte nicht angesprochen werden. Bitte überprüfen Sie, dass " "das Gerät eingeschaltet und eingesteckt ist, und dass Sie ifp-line (http://" "ifp-driver.sf.net) installiert haben." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Lade %(current)d/%(total)d hoch" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "%s konnte nicht hochgeladen werden. Das Gerät hat möglicherweise keinen " "Speicherplatz mehr oder ist ausgeschaltet." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Fehler während des Hochladens" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Benutzerdaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Metadaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Metadaten und Benutzerdaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Dateinamenstämme und Benutzerdaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Dateinamenstämme und Metadaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Dateinamenstämme, Metadaten und Benutzerdaten exportieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Import/Export" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Importiert und exportiert Metadaten und Titel-Benutzerdaten." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Weitere Informationen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Der Begriff »Titel-Benutzerdaten« schließt die Wiedergabelisten, die die " "ausgewählten Titel enthalten, ein und außerdem die folgenden Metadaten:\n" "\n" "%s\n" "\n" "Seien Sie sich im Klaren darüber, dass alles, was beim Export ausgewählt " "wurde, auch wieder importiert wird. Wenn die Dateinamenstämme (Dateinamen " "ohne Erweiterung) exportiert wurden, dann werden die ausgewählten Dateien " "beim Import umbenannt.\n" "\n" "Nach dem Export eines Albums können die Daten in eine andere Version des " "Albums importiert werden. Reihenfolge und Anzahl der Titel können sich dabei " "vom ursprünglichen Album unterscheiden. Das Plugin ordnet die exportieren " "Daten den neuen Titeln zu, auch wenn die Namen der Titel leicht voneinander " "abweichen. Die automatische Zuordnung ist nicht immer korrekt, weswegen es " "besser ist, die folgenden Ähnlichkeitswerte nicht zu weit zu reduzieren." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Benutzerinteraktion beim Import" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Bestätigung erfordern, wenn sich Anzahl der Titel unterscheidet" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Bestätigung erfordern, wenn sich Anzahl der Alben unterscheidet" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Liegt die Ähnlichkeit unter dem angegebenen Prozentwert, muss manuell " "ausgewählt werden, welche Daten welchem Titel zugeordnet werden sollen." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Titel-Ähnlichkeit:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Album-Ähnlichkeit:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Exportdateien" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Formatiertes JSON schreiben (langsamer)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Exportdateien nach dem Import löschen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Export-Verzeichnis öffnen" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "CDs" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Titel" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Künstler" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Pfadende" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Alben zuordnen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Fortfahren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Nichts zu importieren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Sie müssen etwas exportieren, bevor Sie importieren können." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Der Index war beschädigt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "JSON in %s konnte nicht eingelesen werden" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "%s konnte nicht gelesen werden" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Dateiname" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Titel zuordnen" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Aktualisiere die Aufstellungsliste." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Schon auf dem neusten Stand." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Rufe Aufstellung für die Woche vom %s ab." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronisierung abgeschlossen." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Fehler während der Synchronisierung (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm-Synchronisierung" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Aktualisiert die Statistiken der Bibliothek über Ihr Last.fm-Profil." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Benutzername:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Sortierungs-Metadatenfelder erstellen" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Wandelt Album- und Künstlernamen auf dürftige Weise in Sortierungsnamen um." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Als M3U-/PLS-Wiedergabeliste exportieren" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exportiert Titel in eine M3U- oder PLS-Wiedergabeliste." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Relative Pfade benutzen" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Absolute Pfade benutzen" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "Schreiben nach %s fehlgeschlagen." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Titel neu einlesen" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Prüft auf Dateiänderungen und lädt die Titel neu oder entfernt sie, wenn " "nötig." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Titel neu einlesen" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain-Analysator" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Titel" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Fortschritt" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Verstärkung" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Spitzenpegel" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "%(to-process)s Album zu aktualisieren (von %(all)s)" msgstr[1] "%(to-process)s Alben zu aktualisieren (von %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain-Lautstärkeanpassung" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analysiert und aktualisiert <a href=\"%(rg_link)s\">ReplayGain</a>-" "Informationen unter der Verwendung von GStreamer. Die Ergebnisse werden nach " "Album gruppiert." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://de.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "immer" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "wenn <b>irgendwelche</b> RG-Felder fehlen" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "wenn <b>Album</b>-RG-Felder fehlen" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "Alben _verarbeiten:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Existierende Metadaten" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Metadatenfelder aufteilen" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Gleichzeitig die CD-Nummer vom Album und die Version vom Titel trennen." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Album aufteilen" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "CD-Nummer abtrennen." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "k. A." #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Zurücksetzen" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Klopfen" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "BPM klopfen" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Die Schläge pro Minute (BPM) für den ausgewählten Titel klopfen." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Websitesuche" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Durchsucht die ausgewählte Website mithilfe beliebiger Metadaten.\n" "Unterstützt Muster, z. B. %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Such-URL-Muster" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Such-URLs bearbeiten" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Suchen bearbeiten …" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Metadaten auf Wikipedia suchen" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Öffnet ein Browserfenster mit dem Wikipedia-Artikel über die gewählten " "Metadaten des ausgewählten Titels." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Suche auf %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Metadaten bearbeiten" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Suche fehlgeschlagen" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Feld »%s« wurde nicht gefunden." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliothek" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Prüfe Einhängepunkte" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Audio-Bibliothek wird eingelesen" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "%s wird eingelesen" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Lade Dateien" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Bibliotheksdateien werden verschoben" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Bibliotheksdateien werden entfernt" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Füge Überwachungen für %s hinzu" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "Es konnten keine Bibliothekstitel in der veralteten Wiedergabeliste " "%(filename)r gefunden werden (Größe %(size).1f kB)." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" "Haben Sie das Wurzelverzeichnis der Bibliothek geändert, nicht jedoch diese " "Wiedergabeliste?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d Wiedergabeliste konnte nicht umgewandelt werden" msgstr[1] "%d Wiedergabelisten konnten nicht umgewandelt werden" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Musikwiedergabe und Musikbibliotheksverwaltung" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Datei konnte nicht geladen werden: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Metadaten auflisten" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Knappe Ausgabe anzeigen" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" "Listenspalten, die im knappen Modus ausgegeben werden sollen, und deren " "Reihenfolge (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Auch programmatische Felder anzeigen" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Nicht genügend Argumente" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Zu viele Argumente" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Beschreibung" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Wert" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Alle allgemeinen Metadatenfelder auflisten" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Metadaten von einer Datei in eine andere Datei kopieren" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Änderungen anzeigen, aber nicht anwenden" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Nicht schreibbare Felder überspringen" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" "Das Feld »{tagname}« kann nicht in die Datei »{filename}« kopiert werden" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Metadaten in einem Texteditor bearbeiten" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Bearbeitung abgebrochen" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Starten des Texteditors »%(editor-name)s« fehlgeschlagen." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Keine Änderungen erkannt" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Einen Metadatenfeld setzen und existierende Werte entfernen" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "%(tag)r kann für %(format)s-Datei %(file)r nicht gesetzt werden" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Metadatenfelder entfernen" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Wert ist ein regulärer Ausdruck" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Alle Metadatenfelder entfernen" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "»--all« kann nicht mit »--regexp« kombiniert werden" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "»{tagname}« kann nicht aus »{filename}« entfernt werden" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Einen Feldwert entfernen" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Einen Feldwert hinzufügen" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "%r kann nicht gesetzt werden" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Dateiinformationen anzeigen" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Das angegebene Bild als Hauptbild einbetten und alle anderen eingebetteten " "Bilder entfernen" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Die Bilddatei konnte nicht geladen werden: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Bearbeiten von Bildern nicht unterstützt in %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Alle eingebetteten Bilder entfernen" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Eingebettete Bilder nach %(filepath)s extrahieren" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Pfad, in den die Bilder gespeichert werden sollen (Vorgabe ist das " "Arbeitsverzeichnis)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Dateien anhand von Metadaten umbenennen" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Metadatenfelder anhand des Dateipfads ausfüllen" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Datei" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Titelnummern in allen Dateien einfügen" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Metadaten basierend auf dem angegebenen Muster ausgeben" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Hilfeinformationen anzeigen" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" "»%(column-id)s« ist kein gültiger Name für eine Spalte (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Unbekannt" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Normal" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Normal" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Zufall" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Zufall" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Höher bewertete bevorzugen" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "_Höher bewertete bevorzugen" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Diesen Titel wiederholen" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "_Diesen Titel wiederholen" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Alle Titel wiederholen" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "_Alle Titel wiederholen" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Einzelner Titel" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "_Einzelner Titel" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Puffer wird gefüllt" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "GStreamer-Pipeline konnte nicht angelegt werden (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Kein GStreamer-Element für das Medienformat gefunden" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Medienformat: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer-Plugin »%(name)s« konnte nicht initialisiert werden" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Die Pipeline für die GStreamer-Audioausgabe. Leer lassen, um die " "Standardpipeline zu verwenden. Enthält die Pipeline eine Senke, wird diese " "anstelle der Standardsenke verwendet." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Audio-Pipeline:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Pufferdauer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Über_gangslose Wiedergabe deaktivieren" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Durch Deaktivieren der übergangslosen Wiedergabe können Probleme beim " "Titelwechsel, die in einigen GStreamer-Versionen auftreten, vermieden werden" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "JACK für die Wiedergabe verwenden, falls verfügbar" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Benutzt »jackaudiosink« als Audiosenke, falls verfügbar" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Automatisch mit JACK-Ausgabegeräten verbinden" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "»jackaudiosink« anweisen, sich automatisch zu verbinden" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Keine GStreamer-Audiosenke gefunden. Versuchte: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Ungültige GStreamer-Ausgabe-Pipeline" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Der Audioausgang konnte nicht angelegt werden" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Das Audiogerät %r wurde nicht gefunden. Überprüfen Sie die Xine-" "Einstellungen in ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Das Modul »{module}« wurde nicht gefunden. Ist das Paket installiert?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Das GStreamer-Element »{element}« wurde nicht gefunden." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Bitte rufen Sie das Plugin-Fenster auf, um ListenBrainz einzurichten. " "Solange werden keine Statistiken gesendet." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Zu viele aufeinanderfolgende Einsendungen fehlgeschlagen (%d). Wechsle in " "Offline-Modus. Bitte rufen Sie das Plugin-Fenster auf, um ListenBrainz " "zurückzusetzen. Solange werden keine Statistiken gesendet." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz-Einsendung" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Hörstatistiken an ListenBrainz senden." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Benutzer-_Token:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "Metad_atenfelder:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Die Liste der Metadatenfelder, die in der Einsendung enthalten sein sollen. " "Kommasepariert, bei Bedarf doppelte Anführungszeichen verwenden." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Titel, die diesem Filter entsprechen, werden nicht eingesendet." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Das Plugin »%(name)s« auf %(count)s Wiedergabeliste anwenden?" msgstr[1] "Das Plugin »%(name)s« auf %(count)s Wiedergabelisten anwenden?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "Plugin ausfüh_ren" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Verwendung" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Titelanfang" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "k. A." #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Zeit" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Lesezeichenname" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Lesezeichen" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filter" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Zuletzt _abgespielt" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Zuletzt _hinzugefügt" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Alle _Titel" # Mit Plural wird der Menüeintrag sehr lang (etwa: Nach aktuellem Genre/aktuellen Genres). Ich denke, dass er auch ohne den Plural verständlich ist und außerdem schneller zu erkennen. #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Nach aktuellem _Genre" # Siehe Kommentar für »On Current _Genre(s)« #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Nach aktuellem _Künstler" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Nach aktuellem Al_bum" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "G_enre zufällig auswählen" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Kü_nstler zufällig auswählen" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Alb_um zufällig auswählen" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "Die 40 meist gespielten Titel (bei Gleichstand werden mehr als 40 ausgewählt)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Name:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Wert:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Gespeicherte Werte" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Gespeicherte Werte bearbeiten …" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matisch" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Titel-Modus" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Album-Modus" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Stumm" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_ReplayGain-Modus" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Neuer %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(unbekannt)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Hinzufügen …" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Bearbeiten" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Feldausdruck" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Feldausdruck, z.B. people:real oder ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Neues Metadatenfeld eingeben" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Feldausdruck bearbeiten" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Dateien:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Die ausgewählten Titel werden aus der Bibliothek entfernt und die " "entsprechenden Dateien vom Datenträger gelöscht." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Die ausgewählten Dateien werden vom Datenträger gelöscht." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "%(file_count)d Datei unwiderruflich löschen?" msgstr[1] "%(file_count)d Dateien unwiderruflich löschen?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Dateien löschen" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Die ausgewählten Titel werden aus der Bibliothek entfernt und die " "entsprechenden Dateien in den Papierkorb verschoben." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Die ausgewählten Dateien werden in den Papierkorb verschoben." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "%(file_count)d Datei in den Papierkorb verschieben?" msgstr[1] "%(file_count)d Dateien in den Papierkorb verschieben?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "In den _Papierkorb verschieben" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Verschiebe %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Verschieben in den Papierkorb fehlgeschlagen" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "" "Das Verschieben einer oder mehrerer Dateien in den Papierkorb ist " "fehlgeschlagen." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Lösche %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Dateien konnten nicht gelöscht werden" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Löschen einer oder mehrerer Dateien fehlgeschlagen." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Browser" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Dateien werden heruntergeladen" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "fehlt in %d Titel" msgstr[1] "fehlt in %d Titeln" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "unterschiedlich in %d Titel" msgstr[1] "unterschiedlich in %d Titeln" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "In _mehrere Werte aufteilen" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "CD von _Album trennen" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "_Version von Titel trennen" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Arrangeur von Küns_tler trennen" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "_Interpret von Künstler trennen" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "_Interpret von Titel trennen" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "_Originalkünstler von Titel trennen" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Feld hinzufügen" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Feld:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "_Programmatische Felder anzeigen" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Auf alle Felder zugreifen, auch auf solche, die z.B. durch MusicBrainz oder " "Replay Gain automatisch erstellt wurden" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "_Mehrzeilige Felder anzeigen" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "Felder anzeigen, die potenziell mehrzeilig sind (z. B. »lyrics«)" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "Zu_rücksetzen" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Speichern" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Konfigurieren" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "Feld _aufteilen" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "Wert(e) _kopieren" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Feld konnte nicht hinzugefügt werden" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "%s konnte nicht hinzugefügt werden" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Die momentan ausgewählten Dateien unterstützen keine mehrfachen Werte für %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Ungültiges Feld" msgstr[1] "Ungültige Felder" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Ungültiges Feld %s\n" "\n" "Die ausgewählten Dateien unterstützen das Bearbeiten dieses Feldes nicht." msgstr[1] "" "Ungültige Felder %s\n" "\n" "Die ausgewählten Dateien unterstützen das Bearbeiten dieser Felder nicht." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Ungültiger Wert" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Ungültiger Wert: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Feld ist möglicherweise ungenau" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s wurde verändert, während das Programm lief. Wenn Sie " "speichern, ohne die Bibliothek zu aktualisieren, werden möglicherweise " "andere Änderungen an dem Titel überschrieben." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Der Titel konnte nicht gespeichert werden" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Speichern von %(file-name)s fehlgeschlagen. Die Datei ist möglicherweise nur " "lesbar, beschädigt, oder Sie haben keine ausreichenden Benutzerrechte zum " "Bearbeiten der Datei." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Weitere Optionen …" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Rückgängig" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Wiederholen" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Info" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "Nach Aktualisierungen _suchen …" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "P_lugins" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s und %(count)s weiterer" msgstr[1] "%(title)s und %(count)s weitere" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex-Falso-Einstellungen" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Ordner" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Neuer Ordner …" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "Alle Unterordner au_swählen" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Neuer Ordner" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Geben Sie einen Namen für den neuen Ordner ein:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Ordner konnte nicht angelegt werden" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Ordner konnte nicht gelöscht werden" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Titel" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "von %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "CD %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Titel %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Aktueller _Titel" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "Anzeige b_earbeiten …" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Keine Titel ausgewählt." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Keine Titel" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informationen" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Texte" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produziert von %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "Künstler" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "Künstler" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "Interpreten" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nie" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d-mal" msgstr[1] "%(n)d-mal" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "Hinzugefügt" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "Letzte Wiedergabe" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "Wiedergegeben" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "Übersprungen" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "Bewertung" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "Pfad" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "Dauer" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "Format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "Codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "Kodierung" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "Bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "Dateigröße" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "Geändert" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Weiteres" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d ausgewählt" msgstr[1] "%d ausgewählt" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Titel nicht verfügbar" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d Titel ohne Album" msgstr[1] "%d Titel ohne Album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Ausgewählte Diskographie" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d Titel ohne Künstler" msgstr[1] "%d Titel ohne Künstler" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "Alben" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Gesamtdauer:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Gesamtgröße:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Dateien" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "Online _anzeigen" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Für diesen Titel wurde kein Liedtext gefunden." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Sind Sie sicher, dass Sie alle Titel entfernen möchten?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Die ausgewählten Titel werden aus der Bibliothek entfernt." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Einblenden" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Einblenden" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Prüfen Sie, ob die Spalten auf der linken Seite ungefähr denen auf der " "rechten entsprechen. Wenn nicht, können Sie hier die Reihenfolge ändern (_ " "für Zeilen benutzen, die nicht zugeordnet werden sollen):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Reihenfolge auf der rechten Seite:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Änderungen an den Metadaten verwerfen?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Die Metadaten wurden verändert, aber noch nicht gespeichert. Sollen die " "Änderungen gespeichert oder verworfen werden?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Zu_rücksetzen" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Datei existiert" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "»%(file-name)s« ersetzen?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "Datei e_rsetzen" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktive Prozesse" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d aktive Prozesse" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Zufallsmodus ein-/ausschalten" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Endlosschleife ein-/ausschalten" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Ereignisse" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Wiedergabereihenfolge" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Bearbeitung" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Umbenennung" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Abfragen" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Cover" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plugin-Fehler" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Beliebiger Status" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Aktiviert" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Deaktiviert" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Keine Kategorie" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Beliebige Kategorie" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Keine Plugins gefunden." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Plugins" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Nach Pluginstatus filtern" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Nach Pluginart filtern" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Nach Pluginname oder -beschreibung filtern" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "_Fehler anzeigen" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_CD" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Titel-Nr." #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Gru_ppierung" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Künstler" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Album" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Datei_name" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "Dau_er" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Automatisch zu aktuellem Titel _springen" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Zu Titel in der Titelliste gehen, sobald dessen Wiedergabe beginnt" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "Titel nach Änderung der Metadaten sortieren" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" "Die Titel in der Titelliste automatisch neu anordnen, wenn sich die " "Metadaten ändern" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Sortierung immer ermöglichen" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" "Sortierung nach Spaltenüberschriften erlauben, auch für Wiedergabelisten usw." #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Weitere:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "B_earbeiten …" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Weitere Listenspalten hinzufügen oder entfernen" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Anzuzeigende Listenspalten" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Titel mit _Version" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albu_m mit CD-Untertitel" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Künstler mit allen _Mitwirkenden" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Dateiname mit _Pfad" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Einstellungen für Listenspalten" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "Spalten _aktualisieren" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Aktuelle Konfiguration auf Titelliste anwenden. Neue Listenspalten werden am " "Ende hinzugefügt" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Titelliste" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Listenspalten bearbeiten" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Gesamtdauer" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globaler Filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Diese Abfrage zusätzlich zu allen anderen anwenden" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Suche" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Browser" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Gleichzeitiges Bewerten _mehrerer Titel bestätigen" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Eine Bestätigung anfordern, bevor die Bewertungen mehrerer Titel " "gleichzeitig geändert werden" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Bewertungen mit _einfachem Klick zulassen" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Das Ändern von Bewertungen durch Klicken in der Spalte »Bewertung« zulassen" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Bewertungen" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "_Eingebettete Coverbilder bevorzugen" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Falls verfügbar, immer die in Audiodateien eingebetteten Coverbilder " "verwenden" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Die zu verwendenden Coverbild-Dateien, sofern vorhanden. Mehrere Einträge " "können mit Kommata getrennt werden. Unterstützt Platzhalter." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Bevorzugte feste Dateinamen für Coverbilder" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Alben-Cover" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Wiedergabe" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Konfiguration der Tonausgabe" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Lautstärke um diesen Wert skalieren, falls ein Titel keine ReplayGain-" "Informationen bietet" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Standardverstärkung:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Lautstärke aller Titel um diesen Wert skalieren, solange dadurch keine " "Übersteuerung auftritt" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Vorverstärkung:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_ReplayGain-Lautstärkeanpassung aktivieren" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "ReplayGain-Lautstärkeanpassung" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "Wiedergabe beim Programmstart _fortsetzen" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Wird beim Beenden Musik wiedergegeben, die Wiedergabe beim nächsten " "Programmstart automatisch fortsetzen" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Standard_bewertung:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Bewertungs_skala:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayes-Faktor (C) des Mittelwerts für aggregierte Bewertungen.\n" "»0« bedeutet einen herkömmlichen Mittelwert, höhere Werte bewirken, dass " "Alben mit wenigen Titeln schwächere Bewertungen erhalten. Eine Änderung " "dieses Wertes bewirkt eine Neubewertung aller Alben." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Bayesscher _Mittelwert:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-Mail:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Bewertungen und Angaben zur Wiedergabeanzahl werden zu dieser E-Mail-Adresse " "in den Metadaten gespeichert" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "Änderungen an Metadaten _automatisch speichern" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Änderungen an den Metadaten beim Bearbeiten mehrerer Dateien ohne Rückfrage " "speichern" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Liste von Trennzeichen, die zum Aufteilen von Feldern im Metadaten-Editor " "verwendet werden. Einträge dieser Liste werden durch Leerzeichen voneinander " "getrennt." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Trenne _Felder nach:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Liste von Trennzeichen, die zum Abtrennen von Unterfeldern im Metadaten-" "Editor verwendet werden. Einträge dieser Liste werden durch Leerzeichen " "voneinander getrennt, und jeder Eintrag muss aus exakt zwei Zeichen bestehen." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Trenne _Unterfelder nach:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Metadaten" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Metadaten-Bearbeitung" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Aktualisiere Bewertungen" # »Einlesen« würde nach einem aufwendigeren Vorgang klingen #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "Bibliothek aktuali_sieren" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Bibliothek auf Änderungen überprüfen" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Bibliothek neu auf_bauen" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Alle Titel in der Bibliothek neu laden. Dieser Vorgang dauert möglicherweise " "lange." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Ausgeblendete Titel" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Bibliothek beim _Programmstart aktualisieren" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "Verzeichnisse auf Änderungen über_wachen" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Bibliotheksverzeichnisse automatisch auf externe Dateiänderungen hin " "überwachen." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Ordner einlesen" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s und %(count)d weiterer" msgstr[1] "%(title)s und %(count)d weitere" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Eigenschaften" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Warteschlange" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Warteschlange leeren" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" "Warteschlange deaktivieren – die Warteschlange wird bei der Wiedergabe " "ignoriert" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Flüchtig" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Titel nach Wiedergabe aus der Warteschlange entfernen" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Persistent" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Titel nach Wiedergabe in der Warteschlange behalten" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modus" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Am Ende anhalten" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d Titel (%(time)s)" msgstr[1] "%(count)d Titel (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Bibli_othek durchsuchen" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Warteschlange anzeigen/verbergen" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Wiedergabefehler" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Ordner für Bibliothek einrichten?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" "Sie haben noch keine Musikbibliothek eingerichtet. Möchten Sie das jetzt tun?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Nicht jetzt" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Einrichten" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Titel konnten nicht hinzugefügt werden" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s verwendet ein nicht unterstütztes Protokoll." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Zum abgespielten Titel springen" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Datei" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Titel" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Ansicht" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "D_urchsuchen" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Steuerung" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Hilfe" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Ordner hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Datei hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_URL hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "_Lesezeichen bearbeiten …" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Stop" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Nach diesem Titel _stoppen" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Tastenkürzel" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Online-Hilfe" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Hilfe zu Sucheingaben" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "URL hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Geben Sie die URL einer Audio-Datei an:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Die URL konnte nicht hinzugefügt werden" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s ist keine gültige URL." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Musik hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Ordner hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Musikdateien" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Dateien hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" "Sind Sie sicher, dass Sie %d Titel zur Warteschlange hinzufügen möchten?" msgstr[1] "" "Sind Sie sicher, dass Sie %d Titel zur Warteschlange hinzufügen möchten?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Hinzufügen" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Sind Sie sicher, dass Sie die Bewertung von %d Titeln ändern möchten?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Die gespeicherten Bewertungen werden entfernt" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "Bewertung entfe_rnen" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Die Bewertung aller ausgewählten Titel wird zu %s geändert" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Bewertung _ändern" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Leerzeichen durch _Unterstriche ersetzen" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Doppelpunkte und Semikolons durch Bindestriche ersetzen" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "Z. B. »iv: allegro.flac« → »iv - allegro.flac«" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Von MS _Windows nicht unterstützte Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "_Diakritische Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Nicht-_ASCII-Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Nur _Kleinschreibung verwenden" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Dateien umbenennen" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Voransicht" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Dateinamen" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "Alben-Cover _verschieben" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Siehe den Konfigurationseintrag »[albumart] filenames« für die Dateinamen, " "nach denen gesucht wird" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "Album-Cover am Zielort _überschreiben" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "Leere Verzeichnisse _entfernen" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Alben-Cover" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Neuer Name" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Die Datei konnte nicht umbenannt werden" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Umbenennen von %(old-name)s nach %(new-name)s fehlgeschlagen. Möglicherweise " "existiert die Zieldatei bereits, oder Sie haben keine ausreichenden " "Benutzerrechte, um die neue Datei anzulegen oder die alte zu entfernen." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "_Alle Fehler ignorieren" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stop" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Fortfahren" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Der Pfad ist nicht absolut" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Das Muster\n" "\t%s\n" "enthält »/«, startet aber nicht vom Stammverzeichnis. Um zu vermeiden, dass " "Ordner falsch benannt werden, sollte das Muster entweder mit »/« oder »~/« " "beginnen." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "In den aufgeführten Ordnern abgelegte Audiotitel werden Ihrer Bibliothek " "hinzugefügt, wenn diese aktualisiert wird" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Das neue Verzeichnis wird nach dem Hinzufügen eingelesen" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" "Es werden auch alle Titel in den ausgewählten Verzeichnissen aus der " "Bibliothek entfernt" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Verschieben" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Eine Einlesewurzel verschieben (aber nicht die Dateien), wodurch die " "Metadaten für alle betroffenen Titel migriert werden." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "»{dir}« und alle zugehörigen Titel entfernen?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "{n} Bibliothekspfade und alle zugehörigen Titel entfernen?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Bibliothekspfad entfernen?" msgstr[1] "Bibliothekspfade entfernen?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Entfernen" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Ordner auswählen" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Dieses Verzeichnis wählen" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Tatsächliches/neues Verzeichnis für »{dir}« wählen" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Dieser Vorgang verschiebt die Quod-Libet-Metadaten:\n" "\n" "»{old}« → »{new}«\n" "\n" "Die Audiodateien selbst werden dadurch nicht verschoben. Eine Sicherung wird " "trotz allem empfohlen (inklusive der Quod-Libet-Datei »songs«)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Die Einlesewurzel »{dir}« verschieben?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "OK, verschieben!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Gespeicherte Suchläufe" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Gespeicherte Suchläufe bearbeiten …" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Bibliothek mit Freitexteingaben oder QL-Abfragen durchsuchen" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Suche bei Eingabe _starten" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Suchergebnisse umgehend nach Beenden der Eingabe anzeigen" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limit:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Bewertung" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Abfrage hinzufügen" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" "Eine QL-Abfrage oder Freitexteingabe hinzufügen, um die Suche weiter " "einzuschränken" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Verbleibende Abspieldauer anzeigen" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hauptfenster" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Im aktuell abgespielten Titel um 10 Sekunden zurückspringen" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Im aktuell abgespielten Titel um 10 Sekunden vorwärtsspringen" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Fokus auf den Sucheintrag setzen" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Filter zurücksetzen und zum aktuell abgespielten Titel springen" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Informationsfenster für den ausgewählten Titel öffnen" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Metadaten-Editor für den ausgewählten Titel öffnen" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Die ausgewählten Titel zur Warteschlange hinzufügen" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Den ausgewählten Titel löschen" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Das Suchfeld für die Schnellsuche anzeigen" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Linksklick auf einen Listenspaltenkopf" # The line break ensures that the keyboard shortcut window fits on a 1280 px width screen #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" "Die Spalte der Liste der Spalten, nach denen sortiert\n" "werden soll, hinzufügen" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Baumansicht" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Das Element einklappen oder das Elternelement auswählen" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Das Element ausklappen" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Textfelder" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Die letzte Änderung rückgängig machen" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Die letzte rückgängig gemachte Änderung wiederholen" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Alle Titel in allen Leisten auswählen" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "Nach %s _filtern" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "_Alle Listenspalten" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Listenspalten zu _Titeln" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Listenspalten zu _Alben" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Listenspalten zu _Mitwirkenden" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Listenspalten zum _Datum" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Listenspalten zu _Dateien" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Listenspalten zur _Produktion" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "Listenspalten _anpassen …" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "Listenspalte ausd_ehnen" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Möchten Sie den Titel »%(title)s« aus der Bibliothek entfernen?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Möchten Sie die %(count)d Titel aus der Bibliothek entfernen?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Aus der Bibliothek entfernen" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Das Plugin »%(name)s« auf %(count)d Titel anwenden?" msgstr[1] "Das Plugin »%(name)s« auf %(count)d Titel anwenden?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Das Plugin »%(name)s« auf %(count)d Album anwenden?" msgstr[1] "Das Plugin »%(name)s« auf %(count)d Alben anwenden?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Plugins konfigurieren …" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Zur _Warteschlange hinzufügen" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "Aus der Bibliothek entfe_rnen …" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Die Dateien konnten nicht angezeigt werden" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Fehler beim Anzeigen der Dateien oder es ist kein Programm verfügbar, um sie " "anzuzeigen." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "In der Dateiverwaltung _anzeigen" msgstr[1] "%(total)d Dateien in der Dateiverwaltung _anzeigen" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Datei herunterladen …" msgstr[1] "%(total)d _Dateien herunterladen …" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "erfolgreich" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "fehlgeschlagen" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Downloads abgeschlossen" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "»{name}« herunterladen nach" msgstr[1] "{total} Dateien herunterladen nach" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Hierhin herunterladen" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "_Unterstriche durch Leerzeichen ersetzen" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Titel_anfang in Großbuchstaben" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "In _mehrere Werte aufteilen" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Metadaten aus Dateipfad erzeugen" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Neue Felder überschreiben bestehende Felder" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Neue Felder werden zu den vorhandenen Feldern hinzugefügt" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Das Muster\n" "\t%s\n" "ist ungültig. Möglicherweise enthält es das gleiche Feld zweimal, oder es " "enthält nicht zueinander passende Klammern (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Das von Ihnen eingegebene Muster ist ungültig. Bitte geben Sie »<«; und " "»>«; als »\\<«; und »\\>«; ein. Achten Sie darauf, dass Tags richtig " "geschlossen werden.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Anzeige bearbeiten" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Titelnummern" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "_Starten bei:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Titel insgesamt:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Abspielen/Pause" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Vorheriger" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "und %d weitere …" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Geänderte Titel werden gespeichert." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d Titel gespeichert\n" "(%(remaining)s übrig)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s von %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Nach Aktualisierungen suchen" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Verbindung fehlgeschlagen" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Sie benutzen bereits die aktuelle Version %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Eine neue Version %(new-version)s ist verfügbar\n" "\n" "Sie benutzen aktuell Version %(old-version)s\n" "\n" "Besuchen Sie die <a href='%(url)s'>Website</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Leere Wiedergabeliste" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Wiedergabelisten müssen einen Namen haben" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "" "Eine Wiedergabeliste mit dem Namen »%(name)s« existiert bereits in %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Eingebettete Album-Cover" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "In Audiodateien eingebettete Coverbilder verwenden." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Dateisystem-Cover" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Mit üblichen Dateinamen benannte Bilder in üblichen Verzeichnissen neben dem " "Titel benutzen." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Alben-Cover" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Album-Cover-Provider werden abgefragt" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Kurzinfo zur Benutzung anzeigen" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Info zu Version und Copyright anzeigen" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Debugginginformationen ausgeben" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Verwendung: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[Optionen]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Die Option %r ist ungültig." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Die Option %r erfordert ein Argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r ist kein eindeutiger Präfix." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbit/s" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s Sekunde" msgstr[1] "%s Sekunden" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Keine Informationen zur Abspieldauer" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d Sekunde" msgstr[1] "%d Sekunden" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d Minute" msgstr[1] "%d Minuten" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d Stunde" msgstr[1] "%d Stunden" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d Tag" msgstr[1] "%d Tage" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d Jahr" msgstr[1] "%d Jahre" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "no title-casing" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Das Datum muss in einem der folgenden Formate eingegeben werden: »JJJJ«, " "»JJJJ-MM-TT« oder »JJJJ-MM-TT HH:MM:SS«." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" "Die ReplayGain-Wiedergabeverstärkung muss im Format »x.yy dB« eingegeben " "werden." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "ReplayGain-Spitzenpegel müssen im Format »x.yy« eingegeben werden." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz-IDs müssen dem Format UUID entsprechen." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Der MusicBrainz Release-Status muss »official«, »promotional«, oder " "»bootleg« sein." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Der Sprachcode muss aus drei Buchstaben bestehen (ISO 639-2)" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Speichere %d Datei" msgstr[1] "Speichere %d Dateien" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Automatisches Speichern" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Der Titel kann nicht bearbeitet werden" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Speichern von %s fehlgeschlagen. Die Datei ist möglicherweise nur lesbar, " "beschädigt, oder Sie haben keine ausreichenden Benutzerrechte zum Bearbeiten " "der Datei." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Ungültige Kodierung]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "Album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "Arrangeur" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "Arrangeure" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "Arrangement" #: quodlibet/util/tags.py:86 msgid "author" msgstr "Autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "Autoren" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "Kommentar" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "Komponist" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "Komponisten" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "Komposition" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "Dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "Dirigenten" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "Dirigat" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "Kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "Copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "Datum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "Beschreibung" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "Genre" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "Genres" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "Interpret" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "Darbietung" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "Gruppierung" #: quodlibet/util/tags.py:98 msgid "language" msgstr "Sprache" #: quodlibet/util/tags.py:99 msgid "license" msgstr "Lizenz" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "Texter" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "Texter" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "Liedtext" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "Plattenfirma" #: quodlibet/util/tags.py:104 msgid "title" msgstr "Titel" #: quodlibet/util/tags.py:105 msgid "version" msgstr "Version" #: quodlibet/util/tags.py:106 msgid "website" msgstr "Website" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "Album-Künstler" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "CD-Untertitel" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "CD" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "Titel-Nr." #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "Label-ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "Erste Veröffentlichung" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "Originalalbum" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "Originalkünstler" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "Aufnahmedatum" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "Erschienen in" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "Anfängliche Tonart" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz Aufnahme-ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz Veröffentlichungs-Titel-ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz Veröffentlichungs-ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz Künstler-ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz Veröffentlichungs-Künstler-ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM-ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz Albumstatus" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz Albumtyp" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz Veröffentlichungsgruppen-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "Lautstärkeverstärkung per Titel" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "Titel-Spitzenpegel" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "Lautstärkeverstärkung per Album" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "Album-Spitzenpegel" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "Referenzlautstärke" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "CDs" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "Titel" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "Zuletzt angespielt" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "Vollst. Dateiname" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "Einhängepunkt" #: quodlibet/util/tags.py:166 msgid "people" msgstr "Mitwirkende" #: quodlibet/util/tags.py:168 msgid "year" msgstr "Jahr" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "Jahr der Erstveröffentlichung" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "Lesezeichen" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "Bittiefe" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "Dateiformat" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "Wiedergabelisten" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "Abtastrate" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "Anzahl der Kanäle" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "sortieren" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "Rollen" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor für Audio-Metadaten" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Metadaten in Audiodateien bearbeiten" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musikwiedergabe" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Anhören, Durchsuchen und Bearbeiten Ihrer Audiosammlung" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso ist ein Editor für die Bearbeitung von Metadaten mit der " "Benutzeroberfläche von Quod Libet. Mit ihm können Audio-Tags in allen " "unterstützten Dateiformaten angezeigt und bearbeitet werden." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Zu den unterstützten Dateiformaten gehören Ogg Vorbis/Opus/Speex/FLAC, MP3, " "FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, " "MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet ist eine Anwendung zum Verwalten der Musiksammlung. Sie kann Ihre " "Audiobibliothek auf verschiedene Arten darstellen und unterstützt " "Internetradio sowie Audio-Feeds. Quod Libet enthält äußerst flexible " "Funktionen zur Metadaten-Bearbeitung und Suche." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Exportiert eine Wiedergabeliste zu einer Sonos-Wiedergabeliste. Dafür " #~ "müssen beide dieselbe Verzeichnisstruktur teilen." #~ msgid "Export to Sonos playlist" #~ msgstr "In Sonos-Wiedergabeliste exportieren" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "<b>%s</b> konnte nicht hinzugefügt werden" #~ msgid "Invalid tags" #~ msgstr "Ungültige Felder" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Ungültige Felder <b>%s</b>\n" #~ "\n" #~ "Die momentan ausgewählten Dateien unterstützen das Bearbeiten dieser " #~ "Felder nicht." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Bewertet Titel automatisch, wenn sie abgespielt oder übersprungen werden. " #~ "Benutzt den »beschleunigten« Algorithmus aus vux von Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f Sekunden" #~ msgid "Startup" #~ msgstr "Start" #~ msgid "Audio Feeds" #~ msgstr "Audio-Feeds" #~ msgid "_Audio Feeds" #~ msgstr "_Audio-Feeds" #~ msgid "New" #~ msgstr "Neu" #~ msgid "Automatic Library Update" #~ msgstr "Automatische Bibliotheks-Aktualisierung" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Hält die Bibliothek mit inotify aktuell. Benötigt %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Erlaubt die Steuerung von Quod Libet über die MPRIS-2-D-Bus-Interface-" #~ "Spezifikation." #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Exportiert die Metadaten der ausgewählten Titel in eine .tags-Datei." #~ msgid "Import Metadata" #~ msgstr "Metadaten importieren" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Importiert Metadaten für die ausgewählten Titel aus einer .tags-Datei." #~ msgid "Migrate Metadata" #~ msgstr "Metadaten übertragen" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Überträgt die Quod-Libet-spezifischen Metadaten zwischen Titeln." #~ msgid "_Copy" #~ msgstr "_Kopieren" #~ msgid "_Paste" #~ msgstr "_Einfügen" #~ msgid "Information to copy/paste" #~ msgstr "Informationen, die kopiert/eingefügt werden sollen" #~ msgid "Map tracks by disc and track number" #~ msgstr "Titel über CD- und Titelnummer zuordnen" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Wählen Sie diese Option aus, um die Metadaten von einem Album auf ein " #~ "anderes zu übertragen, wobei die Titel über CD- und Titelnummer " #~ "zugeordnet werden.\n" #~ "\n" #~ "<b>Hinweis:</b> Muss beim Kopieren von Metadaten ausgewählt sein, damit " #~ "Titelinformationen gespeichert werden." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "%d Titel ist gespeichert." #~ msgstr[1] "%d Titel sind gespeichert." #~ msgid "Unsupported file type" #~ msgstr "Dateityp wird nicht unterstützt" #~ msgid "Unable to add station" #~ msgstr "Sender konnte nicht hinzugefügt werden" #~ msgid "Search Library" #~ msgstr "Bibliothek durchsuchen" #~ msgid "_Search Library" #~ msgstr "Bibliothek d_urchsuchen" #~ msgid "Quit Program" #~ msgstr "Programm beenden" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Verhindert die Aktivierung des GNOME-Bildschirmschoners während ein Titel " #~ "wiedergegeben wird." #~ msgid "No lyrics found" #~ msgstr "Kein Liedtext gefunden" #~ msgid "_Zoom level:" #~ msgstr "_Vergößerungsfaktor:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Über die oben angegebene URL suchen, wenn der Liedtext nicht\n" #~ "auf LyricsWikia gefunden werden kann." #~ msgid "Alternate search" #~ msgstr "Alternative Suche" #~ msgid "Web Lyrics" #~ msgstr "Web-Liedtext" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Zeigt eine Seitenleiste mit Online-Liedtext des aktuell wiedergegebenen " #~ "Titels an." #~ msgid "Skip Songs" #~ msgstr "Titel überspringen" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Bei der Wiedergabe werden Titel, deren Bewertung gleich oder niedriger " #~ "als ein festgelegter Schwellenwert ist, übersprungen." #~ msgid "Burn CD" #~ msgstr "CD brennen" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Brennt CDs mit K3b, Brasero oder xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "Der für die Bilddatei zu verwendende Dateiname" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "" #~ "Die zwingend zu verwendende Bilddatei (unterstützt Platzhaltersymbole)" #~ msgid "Ignore" #~ msgstr "Ignorieren" #~ msgid "Keep Songs" #~ msgstr "Titel behalten" #~ msgid "Rate the playing song" #~ msgstr "Abgespielten Titel bewerten" #~ msgid "_Wide Mode" #~ msgstr "_Breitbildmodus" #~ msgid "Top of screen" #~ msgstr "Oberer Teil des Bildschirms" #~ msgid "Middle of screen" #~ msgstr "Mitte des Bildschirms" #~ msgid "Bottom of screen" #~ msgstr "Unterer Teil des Bildschirms" #~ msgid "_Clear" #~ msgstr "L_eeren" #~ msgid "Stop Once Empty" #~ msgstr "Stoppen, sobald leer" #~ msgid "File Bug Report" #~ msgstr "Problembericht erstellen" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgid "Size" #~ msgstr "Größe" #~ msgid "Lyrics:" #~ msgstr "Liedtext:" #~ msgid "Lyrics Window" #~ msgstr "Liedtext-Fenster" #~ msgid "_Lyrics" #~ msgstr "_Liedtext" #~ msgid "_Download" #~ msgstr "_Download" #~ msgid "Device Properties" #~ msgstr "Geräte-Eigenschaften" #~ msgid "Device:" #~ msgstr "Gerät:" #~ msgid "Not mounted" #~ msgstr "Nicht eingebunden" #~ msgid "Mount point:" #~ msgstr "Einhängepunkt:" #~ msgid "Media Devices" #~ msgstr "Mediaplayer" #~ msgid "_Media Devices" #~ msgstr "_Mediaplayer" #~ msgid "_Eject" #~ msgstr "Aus_werfen" #~ msgid "_Properties" #~ msgstr "_Eigenschaften" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s verwendet, %(free-size)s verfügbar" #~ msgid "%s is not connected." #~ msgstr "%s ist nicht verbunden." #~ msgid "Copying %(song)s" #~ msgstr "Kopiere %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Titel konnte nicht kopiert werden" #~ msgid "There is not enough free space for this song." #~ msgstr "Für diesen Titel reicht der freie Speicherplatz nicht aus." #~ msgid "%s could not be copied." #~ msgstr "%s konnte nicht kopiert werden." #~ msgid "Unable to delete songs" #~ msgstr "Titel konnten nicht gelöscht werden" #~ msgid "Deleting %(song)s" #~ msgstr "Lösche %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s konnte nicht gelöscht werden." #~ msgid "Unable to delete song" #~ msgstr "Der Titel konnte nicht gelöscht werden" #~ msgid "Ejecting %s failed." #~ msgstr "Auswerfen von %s fehlgeschlagen." #~ msgid "Unable to eject device" #~ msgstr "Datenträger konnte nicht ausgeworfen werden" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Kein Backend für Geräte gefunden, der Mediaplayer-Browser wurde " #~ "deaktiviert." #~ msgid "Unknown Device" #~ msgstr "Unbekanntes Gerät" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "»%s« konnte nicht importiert werden, wird jedoch für die " #~ "Geräteunterstützung benötigt." #~ msgid "%r is not a supported device." #~ msgstr "%r ist kein unterstütztes Gerät." #~ msgid "Initializing device backend." #~ msgstr "Initialisiere Geräte-Backend." #~ msgid "Trying '%s'" #~ msgstr "Versuche »%s«" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Konnte nicht mit einem Geräte-Backend verbinden." #~ msgid "Device backend initialized." #~ msgstr "Geräte-Backend initialisiert." #~ msgid "_Filename pattern:" #~ msgstr "Muster für _Dateinamen:" #~ msgid "_Copy to Device" #~ msgstr "Auf _Gerät übertragen" #~ msgid "_Open" #~ msgstr "_Öffnen" #~ msgid "browsers" #~ msgstr "Browser" #~ msgid "tooltip" #~ msgstr "Tooltip" #~ msgid "Event Logging" #~ msgstr "Ereigniserfassung" #~ msgid "Sends song events to the Zeitgeist event logging service." #~ msgstr "Sendet Titelereignisse zum Zeitgeist-Ereigniserfassungsservice." #~ msgid "Unable to download lyrics." #~ msgstr "Liedtext konnte nicht heruntergeladen werden." #~ msgid "Set or toggle the playback order" #~ msgstr "Wiedergabereihenfolge einstellen oder wechseln" #~ msgid "Uninitialized iPod" #~ msgstr "Nicht initialisierter iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Möchten Sie eine leere Datenbank auf diesem iPod anlegen?" #~ msgid "Combine tags with _multiple values" #~ msgstr "Tags _mit unterschiedlichen Werten zusammenführen" #~ msgid "Capacity:" #~ msgstr "Speicherkapazität:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Unable to save iPod database" #~ msgstr "Die iPod-Datenbank konnte nicht gespeichert werden" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "»libgpod« nicht gefunden, iPod-Unterstützung deaktiviert." #~ msgid "Shuffle" #~ msgstr "Zufall" #~ msgid "Weighted" #~ msgstr "Bewertung" #~ msgid "_Weighted" #~ msgstr "_Bewertung" #~ msgid "Restart the playlist when finished" #~ msgstr "Wiedergabeliste nach Abspielen aller Titel von vorn beginnen" #~ msgid "_Music" #~ msgstr "_Musik" #~ msgid "Add Bookmark" #~ msgstr "Lesezeichen hinzufügen" #~ msgid "Song _List" #~ msgstr "_Titelliste" #~ msgid "Embed cover" #~ msgstr "Cover einbetten" #~ msgid "Unable to open input files" #~ msgstr "Die Eingabedateien konnten nicht geöffnet werden" #~ msgid "Print all tags to stdout" #~ msgstr "Alle Tags auf Standardausgabe ausgeben" #~ msgid "command|filename" #~ msgstr "Dateiname" #~ msgid "command|tag" #~ msgstr "Tag" #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: »libudev« wurde nicht gefunden." #~ msgid "heading|Search" #~ msgstr "Suche" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "<b>%s</b> überschreiben?" #~ msgid "Output Error" #~ msgstr "Ausgabefehler" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet läuft bereits." #~ msgid "No song is currently playing." #~ msgstr "Momentan wird kein Titel wiedergegeben." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Nach %s konnte nicht geschrieben werden; es wird daher entfernt." #~ msgid "_Add to Playlist" #~ msgstr "Zur Wiederg_abeliste hinzufügen" #~ msgid "Output Log" #~ msgstr "Protokoll" #~ msgid "Are you sure?" #~ msgstr "Sind Sie sicher?" #~ msgid "_Output Log" #~ msgstr "Pr_otokoll" #~ msgid "Invalid command %r received." #~ msgstr "Ungültigen Befehl %r empfangen." #~ msgid "Unknown browser %r." #~ msgstr "Unbekannter Browser %r." #~ msgid "Custom _Sort..." #~ msgstr "Benutzerdefinierte _Sortierung..." #~ msgid "Tag:" #~ msgstr "Tag:" #~ msgid "Descending" #~ msgstr "Absteigend" #~ msgid "Too Many Errors" #~ msgstr "Zu viele Fehler" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Wiedergabe wird gestoppt, da %d Fehler in Folge auftraten." #~ msgid "Warnings" #~ msgstr "Warnungen" #~ msgid "No log available." #~ msgstr "Kein Protokoll verfügbar." #~ msgid "errors" #~ msgstr "Fehler" #~ msgid "_Cause an Error" #~ msgstr "Einen Fehler _herbeiführen" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Das Album-Cover \"%s\" konnte nicht gelesen werden" #~ msgid "Permanently delete this file?" #~ msgstr "Diese Datei unwiderruflich löschen?" #~ msgid "Permanently delete these files?" #~ msgstr "Diese Dateien unwiderruflich löschen?" #~ msgid "Version:" #~ msgstr "Version:" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s konnte nicht zu Ihrer Bibliothek hinzugefügt werden.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Fehler beim Ausführen des Befehls %r, verursacht durch: %r." #~ msgid "Do you wish to continue?" #~ msgstr "Möchten Sie fortfahren?" #~ msgid "No eject command found." #~ msgstr "Kein Befehl zum Auswerfen gefunden." #~ msgid "" #~ "Cannot save library contents to %s (it's a directory). Please remove it " #~ "and try again." #~ msgstr "" #~ "Die Inhalte der Bibliothek können nicht auf %s (dies ist ein Verzeichnis) " #~ "gespeichert werden. Bitte entfernen und erneut versuchen." #~ msgid "Library Error" #~ msgstr "Fehler in Bibliothek" #~ msgid "_Output device:" #~ msgstr "_Ausgabe-Gerät:" #~ msgid "_Edit and Continue" #~ msgstr "_Bearbeiten und Fortfahren" #~ msgid "Confirm rating" #~ msgstr "Bewertung bestätigen" #~ msgid "Search your library" #~ msgstr "Bibliothek durchsuchen" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r enthält keine Browser." #~ msgid "%r doesn't contain any devices." #~ msgstr "%r enthält keine Geräte." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: media-player-info wurde nicht gefunden." #~ msgid "Unkown" #~ msgstr "Unbekannt" #~ msgid "Not setting process title." #~ msgstr "Prozessname wird nicht gesetzt." #~ msgid "Couldn't find module %s." #~ msgstr "Modul %s wurde nicht gefunden." #~ msgid "Total size unknown" #~ msgstr "Gesamtgröße unbekannt" #~ msgid "Not Played To_day" #~ msgstr "Heute n_och nicht abgespielt" #~ msgid "Not Played in a _Week" #~ msgstr "Seit einer _Woche nicht abgespielt" #~ msgid "Not Played in a _Month" #~ msgstr "Seit einem _Monat nicht abgespielt" #~ msgid "B_ottom 40" #~ msgstr "Fl_op 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "Die 40 am wenigsten gespielten Titel (mehr als 40 werden ausgewählt bei " #~ "Gleichstand)" #~ msgid "Add" #~ msgstr "Hinzufügen" #~ msgid "Bitrate" #~ msgstr "Bitrate" #~ msgid "Genre" #~ msgstr "Genre" #~ msgid "Date" #~ msgstr "Datum" #~ msgid "Sort by title" #~ msgstr "Nach Titel sortieren" #~ msgid "Sort by artist" #~ msgstr "Nach Künstler sortieren" #~ msgid "Lyrics provided by %s." #~ msgstr "Liedtext zur Verfügung gestellt von %s." ���������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/el.po����������������������������������������������������������������������������0000644�0001750�0001750�00001072523�14436352625�013605� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Language po/el translations for PACKAGE package. # Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Dimitris Papageorgiou <dipap@gmx.com>, 2012. # msgid "" msgstr "" "Project-Id-Version: el\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/el/>\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Τίτλος" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "συντελεστές" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Ημερομηνία" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Ημερομηνία Προσθήκης" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Αρχική Ημερομηνία" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Είδος μουσικής" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Βαθμολογία" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Μετρητής Αναπαραγωγών" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Τα_ξινόμηση κατά…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Προτιμήσεις" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Λίστα Άλμπουμ" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Λίστα Ά_λμπουμ" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Όλα τα Άλμπουμ" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d άλμπουμ" msgstr[1] "%d άλμπουμς" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Επαναφόρτωση ε_ξώφυλλου του άλμπουμ" msgstr[1] "Επαναφόρτωση ε_ξώφυλλων των άλμπουμ" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Τραγούδια που δεν ανήκουν σε κάποιο άλμπουμ" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d τραγούδι" msgstr[1] "%d τραγούδια" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d δίσκος" msgstr[1] "%d δίσκοι" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Ένα Άλμπουμ για παράδειγμα" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Προτιμήσεις Λίστας Άλμπουμ" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Δείξε _εξώφυλλα των άλμπουμ" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Η _αναζήτηση συμπεριλαμβάνει ονόματα συντελεστών" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Επιλογές" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Προβολή Άλμπουμ" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Κλείσιμο" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Περιηγητής Μουσικοθήκης" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d τραγούδι" msgstr[1] "%d τραγούδια" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Μη έγκυρη αναζήτηση" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Συλλογή Άλμπουμ" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Σ_υλλογή Άλμπουμ" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Άγνωστο %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Πολλαπλές Τιμές %s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Προσαρμοσμένο" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Προσθήκη" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Αφαίρεση" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Ετικέτα" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Συγχώνευση" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Προτιμήσεις Συλλογής Άλμπουμ" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Εφαρμογή" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Ακύρωση" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Πλέγμα Εξώφυλλων" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Πλέγμα Εξώφυλλων" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Προτιμήσεις Πλέγματος Εξώφυλλων" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Δείξε _κείμενο άλμπουμ" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Εμφάνιση αντικειμένου \"Όλα τα Άλμπουμ\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Λειτουργία Πλατιάς προβολής" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Μεγέθυνση Εξώφυλλου" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Σύστημα Αρχείων" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Σύστημα Αρχείων" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Αδυναμία αντιγραφής τραγουδιών" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Τα επιλεγμένα τραγούδια δεν μπορούν να αντιγραφούν σε άλλες λίστες ή στην " "ουρά αναπαραγωγής." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Προσθήκη στην Μουσικοθήκη" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Οι λίστες σταθμών μπορούν να περιέχουν μόνο τοποθεσίες σταθμών, όχι άλλες " "λίστες σταθμών ή λίστες αναπαραγωγής. Οι ακόλουθες τοποθεσίας δεν μπορούν να " "εισαχθούν:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Διαδικτυακό Ραδιόφωνο" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Προσθήκη σταθμών" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Κατέβασμα λίστας σταθμών" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Νέος Σταθμός" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Εισήγαγε ραδιοφωνικό σταθμό:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Ηλεκτρονική" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Ιαπωνική" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Ινδική" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Θρησκευτική" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Τουρκική" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Κολεγιακό Ραδιόφωνο" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Ομιλία / Νέα" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Κλασική" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Ποπ" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Εναλακτική" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Νέα" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Σλαβική" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Ελληνική" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Ροκ" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Θα θέλατε να φορτωθεί μια λίστα δημοφιλών σταθμών;" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Φόρτωση Σταθμών" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Διαδικτυακό Ραδιό_φωνο" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Όλοι οι Σταθμοί" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Αγαπημένα" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Χωρίς Κατηγορία" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Νέος Σταθμός…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Ανανέωση Σταθμών" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Δεν βρέθηκαν σταθμοί" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Δεν βρέθηκε σταθμός ραδιοφώνου στο %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Τίποτα για προσθήκη" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Όλοι οι σταθμοί που επεστράφησαν ανήκουν ήδη στην μουσικοθήκη" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Προσθήκη στα Αγαπημένα" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Αφαίρεση από τα Αγαπημένα" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d σταθμός" msgstr[1] "%(count)d σταθμοί" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Περιηγητής με Στήλες" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Περιηγητής με _Στήλες" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Επιλογή Όλ_ων" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Άγνωστο" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Όλα" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Μικρή" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Πλατιά" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Με στήλες" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Πρότυπο ετικετών με προαιρετική επισήμανση π.χ. <tt>composer</tt> ή\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Προτιμήσεις Περιηγητή με Στήλες" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Διάταξη στηλών" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Περιεχόμενο στηλών" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Ισομεγέθη παράθυρα" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Λίστες Αναπαραγωγής" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Λίστες Αναπαραγωγής" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Αφαίρεση από την Λίστα" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Νέο" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Εισαγωγή" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Αδυναμία εισαγωγής λίστας αναπαραγωγής" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Ο Quod Libet μπορεί να εισάγει λίστες τύπου M3U/M3U8 και PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Διαγραφή Αρχείων" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Μετονομασία" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Αδυναμία μετονομασίας λίστας αναπαραγωγής" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Εισαγωγή" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Νέα Λίστα Αναπαραγωγής…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Τι θέλετε να κάνετε με αυτό το %d τραγούδι;" msgstr[1] "Τι θέλετε να κάνετε με αυτά τα %d τραγούδια;" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Επιβεβαίωση ενέργειας στην λίστα \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "κενό" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Παράδειγμα Λίστας Αναπαραγωγής" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Προτιμήσεις Περιηγητή Λιστών Αναπαραγωγής" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Εμφάνιση Λιστών Αναπαραγωγής" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Θέλετε σίγουρα να διαγραφεί η λίστα αναπαραγωγής '%s';" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Οι πληροφορίες που αφορούν την επιλεγμένη λίστα αναπαραγωγής θα διαγραφούν " "χωρίς δυνατότητα ανάκτησης" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Κομμάτι" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Νέα Λίστα Αναπαραγωγής" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Εισάγετε όνομα για την νέα λίστα" #: quodlibet/browsers/playlists/util.py:73 #, fuzzy msgid "_Create" msgstr "_Δημιουργία βάσης δεδομένων" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Εισαγωγή λίστας αναπαραγωγής.\n" "\n" "%(current)d/%(total)d τραγούδια προστέθηκαν." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Νέα Ροή" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Εισήγαγε την τοποθεσία μιας ροής ήχου" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Προσθήκη _Αρχείου…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Α_νανέωση" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Παρακολούθηση αυτού του φακέλου για νέα τραγούδια" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Αδυναμία προσθήκης ροής" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Η ροή <b>%s</b> δεν ήταν δυνατό να προστεθεί. Ίσως ο διακομιστής να είναι " "εκτός λειτουργίας, ή η τοποθεσία δεν είναι ροή ήχου." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Το τρέχων ηχητικό σύστημα δεν υποστηρίζει απομακρυσμένες διευθύνσεις ο " "περιηγητής Ροών Ήχου απενεργοποιήθηκε" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Περιορισμός Αποτελεσμάτων" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Επέτρεψε πολλαπλά ερωτήματα" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Λίστα Κομματιών" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "Λίστα _Κομματιών" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Περιηγητής Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Περιηγητής Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Αναζήτηση" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Τα κομμάτια μου" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Μετάβαση στο %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Συνδεδεμένο" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Ο Quod Libet είναι πλέον συνδεδεμένος, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Αποσύνδεση %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Εισαγωγή κωδικού…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Σύνδεση στο %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Εξουσιοδότηση Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Εισαγωγή κωδικού εξουσιοδότησης Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Ο Quod Libet δεν εκτελείται (προσθέστε '--run' για να τον ξεκινήσετε)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "Μουσικοθήκη και αναπαραγωγέας" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[επιλογή]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Εμφάνιση του αναπαραγόμενου τραγουδιού και έξοδος" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Έναρξη αναπαραγωγής άμεσα" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Μην προβάλεις παράθυρα στην εκκίνηση" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Μεταπήδηση στο επόμενο τραγούδι" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Μεταπήδηση στην αρχή του τραγουδιού ή στο προηγούμενο αν είναι ήδη κοντά " "στην αρχή" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Μεταπήδηση στο προηγούμενο τραγούδι" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Έναρξη αναπαραγωγής" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Παύση αναπαραγωγής" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Σταμάτημα αναπαραγωγής" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Αύξηση της έντασης αναπαραγωγής" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Μείωση της έντασης αναπαραγωγής" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Αύξησε τη βαθμολογία του αναπαραγόμενου τραγουδιού κατά ένα αστέρι" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Μείωση βαθμολογίας αναπαραγόμενου τραγουδιού κατά ένα αστέρι" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Εμφάνιση της κατάστασης του αναπαραγωγέα" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Απόκρυψη του κυρίου παραθύρου" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Εμφάνιση του κυρίου παραθύρου" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Εναλλαγή ορατότητας κυρίου παραθύρου" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Εστίαση του εκτελούμενου αναπαραγωγέα" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Αφαίρεση ενεργών φίλτρων περιηγητή" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Ανανέωση και σάρωση ξανά της μουσικοθήκης" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Προβολή διαθέσιμων περιηγητών" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Εμφάνιση της τρέχουσας λίστας αναπαραγωγής" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Εμφάνιση των περιεχομένων της ουράς αναπαραγωγής" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Εμφάνιση της ενεργής αναζήτησης" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Εκκίνηση χωρίς πρόσθετα" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Εκκινήστε τον Quod Libet αν δεν εκτελείται" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Έξοδος από τον Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Αναζήτηση στο αναπαραγόμενο τραγούδι" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ΩΩ:]ΛΛ:ΔΔ" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Ενεργοποίηση ή εναλλαγή τυχαίας σειράς" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Ρύθμιση λειτουργίας τυχαίας σειράς" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Ενεργοποίηση, απενεργοποίηση ή εναλλαγή της επανάληψης" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Ρύθμιση λειτουργίας επανάληψης" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Καθορισμός έντασης" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Αναζήτηση στην μουσικοθήκη" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "ερώτημα" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Αναπαραγωγή αρχείου" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "όνομα αρχείου" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Ορισμός βαθμολογίας τρέχοντος τραγουδιού" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Καθορισμός τρέχοντος περιηγητή" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Βαθμολόγηση τρέχοντος τραγουδιού" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Άνοιγμα νέου περιηγητή" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Εμφάνιση ή απόκρυψη της ουράς αναπαραγωγής" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Φιλτρο βάσει τυχαίας τιμής" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "ετικέτα" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Φίλτρο βάσει ετικέτας" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "ετικέτα=τιμή" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Προσθήκη ενός αρχείου ή ενός ερωτήματος στην ουρά" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Προσθήκη στην ουρά αρχείων διαχωρισμένων με κόμματα" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "όνομα αρχείου" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" "Εμφάνιση ονομάτων αρχείων ή αποτελεσμάτων ερωτήματος στην κανονική έξοδο" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Αφαίρεση αρχείου ή ερωτήματος από την ουρά αναπαραγωγής" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Προσθήκη αρχείου ή φακέλου στη μουσικοθήκη" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "τοποθεσία" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "πρότυπο" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Μη έγκυρο όρισμα για το '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Δοκιμάστε το %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Παρουσιάστηκε Σφάλμα" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Μπορείτε να αγνοήσετε το σφάλμα αλλά η εφαρμογή ίσως παρουσιάσει αστάθεια " "μέχρι να γίνει επανεκκίνηση. Η υποβολή αναφοράς σφάλματος θα σας πάρει λίγα " "δευτερόλεπτα και θα μας βοηθούσε πολύ." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Υποβολή Αναφοράς Σφάλματος" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Επανεκκίνηση" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Αγνόηση Σφάλματος" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Λεπτομέρειες σφάλματος:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Διάφορες λεπτομέρειες σχετικά με το σφάλμα και το σύστημά σας θα σταλούν σε " "μια τρίτη σελίδα (<a href='https://www.sentry.io'>www.sentry.io</a>). " "Μπορείτε να επιθεωρήσετε τα δεδομένα πριν αποσταλούν." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(προαιρετικό) Μια σύντομη περιγραφή των συμβάντων πριν την εμφάνιση του " "σφάλματος:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Αποστολή" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Σύντομη περιγραφή…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Δεδομένα προς αποστολή:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "ένας επεξεργαστής ετικετών μουσικής" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "κατάλογος" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Επεξεργαστής ηχητικών μεταδεδομένων" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Πηγή URL Εξωφύλλου" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Κατεβάζει εξώφυλλα συνδεδεμένα με την ετικέτα artwork_url. Χρησιμοποιείται " "με τον περιηγητή Soundcloud." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Πηγή Εξωφύλλου Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Λήψη εξώφυλλων άλμπουμ από το Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Πηγή Εξωφύλλου Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Λήψη εικόνας από το αρχείο εξώφυλλων του Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Πηγή Εξωφύλλου MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Λήψη εικόνας από το αρχείο εξώφυλλων του musicbrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Μετατροπή κωδικοποιήσεων" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Διόρθωση λάθος εντοπισμένων κωδικοποιήσεων στις ετικέτες." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Μετατροπή Κωδικοποιήσεων…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Απλός μετατροπέας Kana/Kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" "Μετατροπή των γραμμάτων kana/kanji σε λατινικούς χαρακτήρες (romaji) πριν " "την μετονομασία." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Μετατροπή _Ιαπωνικού κειμένου σε λατινικούς χαρακτήρες" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Δεν βρέθηκε το πρόγραμμα μετατροπής Kanji Kana (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Αντικατάσταση με χρήση Regex" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Επιτρέπει αντικαταστάσεις με χρήση κανονικών εκφράσεων (s///) στην " "επεξεργασία ετικετών ή την μετονομασία αρχείων." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Διόρθωση πεζών/Κεφαλαίων γραμμάτων" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Διόρθωση των κεφαλαίων στις ετικέτες." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "_Κεφαλαιοποίηση Του Πρώτου Γράμματος Κάθε Λέξης" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Να επιτρέπονται Τ_Α ΚΕΦΑΛΑΙΑ στις ετικέτες" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Κεφαλαιοποίηση με α_γγλικούς κανόνες" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Χρήση κοινών αγγλικών κανόνων για την κεφαλαιοποίηση, όπως στο \"Dark Night " "of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Προχωρημένες Προτιμήσεις" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Επιτρέψτε την επεξεργασία ρυθμίσεων για προχωρημένους." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Ξέρω τι κάνω" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Κινούμενες Ειδοποιήσεις Οθόνης" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Εμφανίζει πληροφορίες στην οθόνη σας στην αλλαγή τραγουδιού." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Θέση:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Μέγεθος _Εξώφυλλου:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Προβολή" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Γραμματοσειρά:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Αριστερά" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Κέντρο" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Δεξιά" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Στοίχιση κειμένου:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Κείμενο" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Κείμενο:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Φόντο:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Χρώματα" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Σκιές" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Περίγραμμα" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Στρογγυλεμένες _Γωνίες" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "Κα_θυστέρηση:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Εφέ" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Επεξεργασία Πρότυπου Εμφάνισης…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Προεπισκόπηση" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Πληροφορίες Εφαρμογής" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Διάφορες πληροφορίες για την εφαρμογή και το περιβάλλον της." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Υποστηριζόμενοι Τύποι Αρχείων" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Κατάλογος Ρυθμίσεων" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Κατάλογος Κρυφής Μνήμης" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Υποσύστημα Ήχου" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Μετά από κάθε αναπαραγωγή (προεπιλογή)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Κάθε φορά που ένα τραγούδι αναπαράγεται πλήρως, το πρόσθετο θα αποθηκεύει " "τις ετικέτες στο αρχείο. Οι υπερπηδήσεις τραγουδιών δεν αποθηκεύονται, " "αποφεύγοντας έτσι αχρείαστες εγγραφές." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Μετά από κάθε αναπαραγωγή ή υπερπήδηση" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Όποτε ένα τραγούδι αναπαράγεται ή υπερπηδάτε, το πρόσθετο θα γράφει τις " "ετικέτες στο αρχείο. Ίσως είναι χρήσιμο αν θέλετε να είστε σίγουροι πως η " "βαθμολογία των τραγουδιών που δεν σας αρέσουν, οπότε και δεν τα ακούτε, " "γράφονται στα αρχεία." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Μία φορά, όταν το άλμπουμ έχει βαθμολογηθεί πλήρως" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Δεν βρέθηκε το %s." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Ανανέωση Σταθμών" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Αποθήκευση των αρχείων ξανά. Οι μετρητές αναπαραγωγής και οι βαθμολογίες " "ενημερώνονται υποχρεωτικά." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Αποθήκευση βαθμολογιών και _μετρητών αναπαραγωγών" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "ημερομηνία ηχογράφησης" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Σφάλμα κατά τον συγχρονισμό" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Ανανέωση Σταθμών" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Προτιμήσεις" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Αυτόματη Απόκρυψη" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Αυτόματη εμφάνιση και απόκρυψη δίσκων καθώς προσαρτώνται ή αφαιρούνται." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Αυτόματη Βαθμολογία" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Αυτόματη βαθμολόγιση των τραγουδιών καθώς αναπαράγωνται ή προσπερνούνται. Με " "τη χρήση του 'επιταχυνόμενου' αλγόριθμου του Brian Nelson από το vux." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Η Εισαγωγή Απέτυχε" #: quodlibet/ext/events/bansheeimport.py:118 #, fuzzy, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Επιτυχής εισαγωγή βαθμολογιών και στατιστικών για %d τραγούδια" msgstr[1] "Επιτυχής εισαγωγή βαθμολογιών και στατιστικών για %d τραγούδια" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "Ξεκίνα την εισαγωγή" #: quodlibet/ext/events/bansheeimport.py:128 #, fuzzy msgid "Imports ratings and song statistics from Banshee." msgstr "Εισάγει βαθμολογίες και στατιστικά τραγουδιών από το Rhythmbox." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Ξεκίνα την εισαγωγή" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Ξυπνητήρι" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Σας ξυπνά με δυνατή μουσική." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Νανούρισμα" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Σταδιακή σίγαση και μετά παύση της μουσικής σας." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Μήνυμα Κατάστασης Gajim" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Μήνυμα Κατάστασης Gajim" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Αλλαγή του μηνύματος κατάστασης του Gajim σύμφωνα με το τι ακούτε." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Παυμένο:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Κατάσταση" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Κατάσταση" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Επίπεδο" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Ζωντανή" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Πλήρης Μπάσα και Πρίμα" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Κλαμπ" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Μεγάλη Αίθουσα" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Πάρτυ" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Απαλή" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Πλήρης Μπάσα" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Ακουστικά" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Απαλή Ροκ" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Πλήρης Πρίμα" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Χορευτική" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Φορητός Υπολογιστής" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Αντισταθμιστής" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Το τρέχων ηχητικό σύστημα δεν υποστηρίζει αντιστάθμιση." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Προεπιλεγμένο Θέμα" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "Επιλογή Όλ_ων" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Προκαθορισμένο:" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Προσαρμοσμένες ρυθμίσεις" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Αδυναμία διαγραφής τραγουδιών" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Αποθήκευση" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Μήνυμα Κατάστασης Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Αλλαγή του μηνύματος κατάστασης του Gajim σύμφωνα με το τι ακούτε." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "παυμένο" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "πρότυπο" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Γράψτε τους λογαριασμούς, διαχωρισμένους με κενά, για την αλλαγή μηνύματος. " "Αν το αφήσετε κενό θα αλλαχθεί το μήνυμα κατάστασης σε όλους τους " "λογαριασμούς." #: quodlibet/ext/events/gajim_status.py:157 #, fuzzy msgid "Accounts:" msgstr "Λογαριασμός" #: quodlibet/ext/events/gajim_status.py:161 #, fuzzy msgid "Add '[paused]'" msgstr "παυμένο" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Αν τσεκαριστεί κατά την παύση θα προστεθεί το '[paused]' στο μήνυμα " "κατάστασης" #: quodlibet/ext/events/gajim_status.py:188 #, fuzzy msgid "Statuses for which message will be changed" msgstr "Καταστάσεις για τις οποίες θα αλλαχθεί το μήνυμα κατάστασης" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Αναστολή Προστασίας Οθόνης" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Αναπαράγεται μουσική" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Μοντέλο:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Αναστολή Προστασίας Οθόνης" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Αναστολή Προστασίας Οθόνης" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Καταγραφή Διαδικτυακού Ραδιοφώνου" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Καταγράφει τα τελευταία 10 τραγούδια που έχουν αναπαραχθεί σε ραδιοφωνικούς " "σταθμούς και τα εμφανίζει στο μενού της αναζήτησης χρόνου." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Εξάγει αρχείο μουσικής χρήστη Jabber στο ~/.quodlibet/jabber" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "Αλλαγή _Βαθμολογίας" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Προεπιλογή" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Διακομιστής πολυμέσων UPnP AV Media Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Εξάγει όλα τα άλμπουμ στον διακομιστή πολυμέσων Rygel UPnP μέσω της διεπαφής " "D-Bus MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Διακομιστής MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Έλεγχος του Quod Libet απομακρυσμένα με χρήση πελάτη MPD. Οι ροές και η " "διαχείριση λιστών αναπαραγωγής και της μουσικοθήκης δεν υποστηρίζονται." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Θύρα:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Τοπική _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 #, fuzzy msgid "P_assword:" msgstr "Κωδικός:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Σύνδεση" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Δοκιμασμένοι Πελάτες" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Υποστήριξη MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Απόκρυψη του κυρίου παραθύρου στο κλείσιμο" #: quodlibet/ext/events/mqtt.py:56 #, fuzzy, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" "Μήνυμα κατάστασης όταν κάποιο τραγούδι είναι παυμένο. Δέχεται πρότυπα QL π." "χ. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Προεπιλογή" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "Πρότυπα Διαδρομών" #: quodlibet/ext/events/mqtt.py:150 #, fuzzy msgid "Status text when a song is started." msgstr "" "Μήνυμα κατάστασης όταν αναπαράγεται κάποιο τραγούδι. Δέχεται πρότυπα QL π.χ. " "%s" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "Πρότυπα Καταστάσεων" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "Χωρίς τρέχων τραγούδι:" #: quodlibet/ext/events/mqtt.py:158 #, fuzzy msgid "Plain text for when there is no current song" msgstr "Απλό κείμενο για την κατάσταση για όταν δεν υπάρχει τρέχων τραγούδι" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Ρύθμιση Εξόδου" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "Κατάσταση" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Δεν ήταν δυνατή η σύνδεση στο %s" #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "Σφάλμα σύνδεσης" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Αναζήτηση σε MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Επιτρέπει να ορισθεί η βαθμολογία τραγουδιού με αριθμό." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Όνομα _χρήστη:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Κωδικός:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Λογαριασμός" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Κείμενο ειδοποίησης" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Τίτλος:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Επαναφορά στο προκαθορισμένο πρότυπο" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Σώμα:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Εμφάνιση ειδοποίησης" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Εμφάνιση ειδοποιήσεων" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Μόνο σε <i>_χειροκίνητες</i> αλλαγές τραγουδιών" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Μόνο σε <i>_αυτόματες</i> αλλαγές τραγουδιών" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Σε <i>Ό_λες</i> τις αλλαγές τραγουδιών" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Μόνο όταν το κύριο παράθυρο δεν είναι _εστιασμένο" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Σφάλμα σύνδεσης" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Δεν ήταν δυνατή η σύνδεση με τον δαίμονα ειδοποιήσεων." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Ειδοποιήσεις Τραγουδιών" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Εμφανίζει ειδοποίηση στην αλλαγή τραγουδιού." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Επόμενο" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Ειδοποιήσεις Τραγουδιών" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Παρακαλώ ανοίξτε το παράθυρο προσθέτων και ρυθμίστε το QLScrobbler. " "Διαφορετικά τα τραγούδια δεν θα υποβάλλονται." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Δεν ήταν δυνατή η σύνδεση στην υπηρεσία '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Η πιστοποίηση απέτυχε: μη έγκυρο URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Η πιστοποίηση απέτυχε: Μη έγκυρο όνομα χρήστη '%s' ή λάθος κωδικός." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Ο πελάτης έχει απαγορευτεί. Ειδοποιήστε τον συγγραφέα." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Λάθος ώρα συστήματος. Οι υποβολές μπορεί να αποτυγχάνουν μέχρι να διορθωθεί." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Υποβολή AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Πελάτης Audioscrobbler για το Last.fm, Libre.fm και άλλες υπηρεσίες " "Audioscrobbler." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Επιτυχημένη πιστοποίηση" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Υπηρεσία:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Άλλο…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Επαλήθευση δεδομένων λογαριασμού" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Πρότυπο _Καλλιτέχνη:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Πρότυπο Τίτλου:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_Φίλτρο εξαιρέσεων:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Το πρότυπο που θα χρησιμοποιηθεί για την υποβολή του ονόματος καλλιτέχνη. " "Αφήστε το κενό για τη χρήση προκαθορισμένου." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Το πρότυπο που θα χρησιμοποιηθεί για την υποβολή του τίτλου. Αφήστε το κενό " "για τη χρήση προκαθορισμένου." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Τα τραγούδια που ταιριάζουν με αυτό το φίλτρο δεν θα υποβάλλονται" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Λειτουργία Εκτός _Σύνδεσης (να μην υποβληθεί τίποτα)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Υποβολή" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Σίγαση Ραδιοφωνικών Διαφημίσεων" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Σίγαση κατά την αναπαραγωγή ραδιοφωνικών διαφημίσεων.\n" "Σταθμοί: di.fm" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Αναπαραγωγή Τυχαίου Άλμπουμ" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Θα ξεκινήσει ένα τυχαίο άλμπουμ όταν τελειώσει η λίστα αναπαραγωγής σας. " "Χρειάζεται ο ενεργός περιηγητής να υποστηρίζει φιλτράρισμα κατά άλμπουμ." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Πιο υψηλά βαθμολογημένο" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Έχει αναπαραχθεί συχνά" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Έχει παραληφθεί συχνά" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Έχει αναπαραχθεί πρόσφατα" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Έχει ξεκινήσει να αναπαράγεται πρόσφατα" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Έχει προστεθεί πρόσφατα" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Μεγαλύτερα σε διάρκεια άλμπουμ" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "δευτερόλεπτα πριν την εκκίνηση του επόμενου άλμπουμ" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Βαρύτητες" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Να προτιμούνται κάποια άλμπουμ περισσότερο" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "απέφυγε" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "προτίμησε" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Τυχαίο Άλμπουμ" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Ξεκινά το %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Επιτυχής εισαγωγή βαθμολογιών και στατιστικών για %d τραγούδια" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Εισαγωγή από τον Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Εισάγει βαθμολογίες και στατιστικά τραγουδιών από το Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Παύση με την Προστασία Οθόνης" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Παύει τη μουσική όταν ενεργοποιηθεί η προστασία οθόνης του GNOME." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Δεν έχει εγκατασταθεί ο πάροχος αναζήτησης του Quod Libet για το GNOME Shell." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Πάροχος Αναζήτησης GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Αναζήτηση στην μουσικοθήκη μέσα από το GNOME Shell." #: quodlibet/ext/events/seekbar.py:122 #, fuzzy msgid "Alternative Seek Bar" msgstr "Εναλακτική" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Χωρίς Σελιδοδείκτες" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Όνομα Σελιδοδείκτη" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Όνομα Σελιδοδείκτη" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Συγχρονισμός με το Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Κάντε το Logitech Squeezebox να καθρεφτίζει την έξοδο του Quod Libet, αρκεί " "να διαβάζουν από όμοια μουσικοθήκη" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Σφάλμα στην εύρεση του διακομιστή Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Σφάλμα στην εύρεση του %s. Παρακαλώ ελέγξτε τις ρυθμίσεις" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Επιλογές" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "Αύξουσα" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "ημερομηνία ηχογράφησης" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Διαγραφή Αρχείων" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Διαγραφή Αρχείων" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Έχει παραληφθεί συχνά" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Δεν βρέθηκαν σταθμοί" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Πρότυπα Διαδρομών" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Επεξεργασία αποθηκευμένων προτύπων…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "Πρότυπο _Καλλιτέχνη:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Προεπισκόπηση" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Κατάσταση" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Πηγές" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Εξαγωγή Μεταδεδομένων" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "οργάνωση" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Η διαδρομή αρχείου δεν είναι απόλυτη" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Το πρότυπο\n" "\t<b>%s</b>\n" "περιέχει το / μα δεν ξεκινά από τη βάση του συστήματος αρχείων. Για να " "αποφύγετε λάθος ονομασμένους φακέλους, ξεκινήστε το πρότυπό σας με / ή ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Δεν υπάρχουν επιλεγμένα τραγούδια." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Δεν υπάρχουν επιλεγμένα τραγούδια." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Αδυναμία αποθήκευσης τραγουδιού" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Έχει παραληφθεί συχνά" msgstr[1] "Έχει παραληφθεί συχνά" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Αδυναμία ανοίγματος αρχείων" msgstr[1] "Αδυναμία ανοίγματος αρχείων" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 #, fuzzy msgid "Text:" msgstr "_Κείμενο:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 #, fuzzy msgid "Font" msgstr "_Γραμματοσειρά:" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Μηνύματα Κατάστασης Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Ενημερώνει όλους τους λογαριασμούς στιγμιαίων μηνυμάτων Telepathy (από το " "Empathy κτλ) με μήνυμα κατάστασης βασισμένο στο τρέχων τραγούδι." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Αναπαράγεται:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Μήνυμα κατάστασης όταν αναπαράγεται κάποιο τραγούδι. Δέχεται πρότυπα QL π.χ. " "%s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Παυμένο:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Μήνυμα κατάστασης όταν κάποιο τραγούδι είναι παυμένο. Δέχεται πρότυπα QL π." "χ. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Απλό κείμενο για την κατάσταση για όταν δεν υπάρχει τρέχων τραγούδι" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Χωρίς τρέχων τραγούδι:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Πρότυπα Καταστάσεων" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Εναλλαγέας Θεμάτων" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Αλλάξτε το ενεργό θέμα GTK+." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Θέμα:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Προεπιλεγμένο Θέμα" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Χρήση της σκοτεινής παραλλαγής του θέματος" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Αυτόματη Βαθμολογία" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Δεν αναπαράγεται" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Εικονίδιο Περιοχής Συστήματος" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Έλεγχος του Quod Libet από την περιοχή συστήματος." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Αναπαραγωγή" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Παύση" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Προη_γούμενο" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "Επό_μενο" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Ανακάτεμα" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Επανάληψη" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Σταμάτησε μετά από αυτό το τραγούδι" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Άνοιγμα _Περιηγητή" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Επε_ξεργασία Ετικετών" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "Π_ληροφορίες" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Λίστες Αναπαραγωγής" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "Έ_ξοδος" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Συμπεριφορά" #: quodlibet/ext/events/trayicon/prefs.py:48 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Ο τροχός του ποντικιού αυξομειώνει την ένταση ήχου\n" "Ο τροχός με πατημένο το Shift αλλάζει τραγούδια" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Τροχός Ποντικιού" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Προβολή Συμβουλής" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Προβολή Στίχων" #: quodlibet/ext/events/viewlyrics.py:26 #, fuzzy msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Προβολή στίχων κάτω από την λίστα τραγουδιών" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Δεν βρέθηκαν στίχοι γι' αυτό το τραγούδι." #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Δεν υπάρχει ενεργό τραγούδι" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Σφάλμα" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 #, fuzzy msgid "Waveform Seek Bar" msgstr "Εναλακτική" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "_Εμφάνιση ειδοποίησης" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Αποθηκευτής Εικόνων" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Η εικόνα εξωφύλλου του τρέχοντος τραγουδιού αποθηκεύεται σε αρχείο." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Αρχείο:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Κατώφλι:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Κατώφλι για την ενεργοποίηση του φίλτρου" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Αναλογία" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Αναλογία συμπίεσης" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Συμπιεστής Ήχου" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Αλλαγή του πλάτους κύματος όλων των δειγμάτων πάνω από κάποιο συγκεκριμένο " "κατώφλι με καθορισμένη αναλογία." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Προκαθορισμένο:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Προκαθορισμένο φίλτρο" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Συχνότητα αποκοπής:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Συχνότητα αποκοπής φίλτρου χαμηλής συχνότητας" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Επίπεδο _εισόδου:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Επίπεδο εισόδου" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Προεπιλογή" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Πλησιέστερο σε τοποθέτηση εικονικών ηχείων (30°, 3 μέτρα)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Πλησίον του διατροφοδοτητή του Chu Moy (δημοφιλές)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Πλησίον στους ενισχυτές CORDA του Jan Meier (μικρή αλλαγή)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Προσαρμοσμένο" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Προσαρμοσμένες ρυθμίσεις" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Διατροφοδότηση" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Αναμιγνύει το αριστερό και δεξιό κανάλι με τέτοιο τρόπο ώστε να προσομοιώνει " "ηχεία κατά την χρήση ακουστικών, ή για να διορθώσει κάποιες παλιές στέρεο " "ηχογραφήσεις." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Ζώνη φίλτρου:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Η ζώνη συχνοτήτων του φίλτρου" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "_Εύρος φίλτρου:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Το εύρος συχνοτήτων του φίλτρου" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "Επίπε_δο:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Η στάθμη επίδρασης" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Αφαίρεση ανθρώπινης φωνής από τον ήχο." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Μονοφωνική μίξη" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Μίξη των καναλιών σε μονοφωνικό." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Ποσοστό:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Τέμπο:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "Τό_νος:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Τόνος / Ταχύτητα Ήχου" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Έλεγχος του ηχητικού τόνου." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Εξαγωγή της λίστας αναπαραγωγής στο Squeezebox" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Εισαγωγή" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Δεν βρέθηκαν σταθμοί" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Πρότυπο ονόματος αρχείου:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Αδυναμία εξαγωγής λίστας αναπαραγωγής" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Πρότυπο ονόματος αρχείου:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Εντάξει" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Σφάλμα στην εύρεση του διακομιστή Squeezebox" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Σφάλμα στην εύρεση του %s. Παρακαλώ ελέγξτε τις ρυθμίσεις" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 #, fuzzy msgid "Export to Squeezebox" msgstr "Εξαγωγή στο Squeezebox…" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Εξαγωγή λίστας αναπαραγωγής στο Logitech Squeezebox, αρκεί να χρησιμοποιούν " "την ίδια δομή καταλόγων. Χρησιμοποιεί τις ρυθμίσεις του προσθέτου Squeezebox " "Sync." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Εξαγωγή της λίστας αναπαραγωγής στο Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Όνομα λίστας (θα αντικαταστήσει τυχών υπάρχουσα)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Εξαγωγή σε λίστα του Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Αφαίρεση Διπλότυπων Από Λίστα" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Αφαιρεί διπλότυπες καταχωρήσεις σε λίστα αναπαραγωγής." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Σίγουρα θέλετε να αφαιρέσετε %d διπλότυπο τραγούδι;" msgstr[1] "Σίγουρα θέλετε να αφαιρέσετε %d διπλότυπα τραγούδια;" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Τα διπλότυπα τραγούδια θα αφαιρεθούν από την λίστα αναπαραγωγής '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Ανακάτεμα Λίστας Αναπαραγωγής" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Ανακατεύει τυχαία μια λίστα αναπαραγωγής." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Ακολούθηση Επιλογής" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Ακολούθηση Επιλογής" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Ακολούθηση Επιλογής" #: quodlibet/ext/playorder/playcounteq.py:21 #, fuzzy msgid "Playcount Equalizer" msgstr "Αντισταθμιστής" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "τελευταία αναπαραγωγή" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "τελευταία αναπαραγωγή" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Μόνο Ουρά" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Αναπαραγωγή μόνο τραγουδιών από την ουρά. Διπλό κλικ σε τραγούδι για να το " "προσθέσετε στην ουρά αναπαραγωγής." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Μόνο Ουρά" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Μόνο Ουρά" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Αντίστροφα" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Αντιστρέφει τη σειρά αναπαραγωγής." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Αντίστροφα" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 #, fuzzy msgid "Waiting to start new group…" msgstr "Ξεκινά το %s" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "Ομα_δοποίηση" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Αδυναμία αντιγραφής τραγουδιών" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "_Ζώνη φίλτρου:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 #, fuzzy msgid "Delay:" msgstr "Κα_θυστέρηση:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 #, fuzzy msgid "Time delay in seconds before starting next group" msgstr "δευτερόλεπτα πριν την εκκίνηση του επόμενου άλμπουμ" #: quodlibet/ext/playorder/shufflebygrouping.py:184 #, fuzzy msgid "Reset to defaults" msgstr "Επαναφορά στο προκαθορισμένο πρότυπο" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Τυχαία σειρά, αλλά κάθε τραγούδι επαναλαμβάνεται έναν προκαθορισμένο αριθμό " "φορών." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Πόσες φορές να αναπαραχθεί το κάθε τραγούδι:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Μη έγκυρες ετικέτες" #: quodlibet/ext/query/pythonexpression.py:18 #, fuzzy msgid "Python Query" msgstr "Κονσόλα Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Πρότυπο ετικέτας" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Αποθηκευμένες Αναζητήσεις" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Αποθηκευμένες Αναζητήσεις" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "μοναδικό" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Το Squeezebox σε λειτουργία. Χρήση του μοναδικού αναπαραγωγέα (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Δεν ήταν δυνατή η σύνδεση στο %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Όνομα Συσκευής:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Θύρα:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Όνομα Χρήστη:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Κωδικός:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Κατάλογος μουσικοθήκης στον οποίο συνδέεται ο διακομιστής" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Τοποθεσία μουσικοθήκης:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Επαλήθευση ρυθμίσεων" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Διακομιστής Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Αποσφαλμάτωση" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Διακομιστής Squeezebox στο {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "άγνωστος διακομιστής Squeezebox" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "άγνωστος αναπαραγωγέας Squeezebox: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Επιλογή αναπαραγωγέα Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Βρέθηκε ο διακομιστής Squeezebox.\n" "Παρακαλώ επιλέξτε τον αναπαραγωγέα" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Προσαρμογή _μεγέθους εικόνας στο μέγεθος παραθύρου" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Πρόγραμμα:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Επεξεργασία της εικόνας μετά την αποθήκευση" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Όνομα _αρχείου" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Η αποθήκευση απέτυχε" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Αδυναμία αποθήκευσης \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Σφάλμα HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "από %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Ανάλυση: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Μέγεθος: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Αναζήτηση" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Αναζήτηση…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Τελείωσε" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Λήψη εξώφυλλων άλμπουμ από διάφορες ιστοσελίδες." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Πηγές" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 σε ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Μετατροπή των ετικετών APEv2 σε ID3v2. Μετά την μετατροπή θα διαγραφούν οι " "ετικέτες APEv2." #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "Μεταπήδηση σε Σελιδοδείκτη…" #: quodlibet/ext/songsmenu/bookmarks.py:24 #, fuzzy msgid "Manages bookmarks in the selected files." msgstr "Εμφάνιση όλων των σελιδοδεικτών στα επιλεγμένα αρχεία." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Επεξεργασία Σελιδοδεικτών…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Χωρίς Σελιδοδείκτες" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Αναζήτηση σε MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Συμπλήρωση ετικετών άλμπουμ βάσει αναζήτησης στο MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Χρήση μόνο του έτους για την ετικέτα \"ημερομηνία\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Προσθήκη ετικέτας \"_albumartist\" όταν χρειάζεται" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Εγγραφή ετικετών ταξινόμησης για τα ονόματα καλλιτεχνών" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Εγγραφή _κανονικών ετικετών MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Όνομα Αρχείου" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Δίσκος" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Κομμάτι" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Τίτλος" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Καλλιτέχνης" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Αναζήτηση σε MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Ερώτημα:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Αναζήτηση" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Αποτελέσματα <i>(τραβήχτε με το ποντίκι για αλλαγή σειράς)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Παρακαλώ εισάγεται ένα ερώτημα." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Παρουσιάστηκε σφάλμα. Παρακαλώ δοκιμάστε ξανά." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Φόρτωση αποτελέσματος…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Δεν βρέθηκαν αποτελέσματα." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Κονσόλα Python" #: quodlibet/ext/songsmenu/console.py:42 #, fuzzy msgid "Interactive Python console. Opens a new window." msgstr "Διαδραστική κονσόλα Python" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 #, fuzzy msgid "Python Console Sidebar" msgstr "Κονσόλα Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Έχετε πρόσβαση στα ακόλουθα αντικείμενα από προεπιλογή:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Ο τρέχων κατάλογος εργασίας σας είναι:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Σύνδεση" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Κλασική" #: quodlibet/ext/songsmenu/cover_download.py:160 #, fuzzy msgid "Large" msgstr "Μεγάλη Αίθουσα" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 #, fuzzy msgid "Full HD" msgstr "Πλήρης Μπάσα" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Δεν βρέθηκαν στίχοι" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "Προεπισκόπηση" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Εντολή" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "όνομα" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Η ονομασία αυτής της εντολής" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "εντολή" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Η εντολή κελύφους που θα εκτελεσθεί" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "παράμετρος" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Αν οριστεί, μια παράμετρος η οποία θα αντικατασταθεί όπου βρεθεί με μια " "καθορισμένη από τον χρήστη τιμή, π.χ. χρησιμοποιώντας το 'PARAM' όλα τα " "'{PARAM}' στην εντολή σας θα αντικατασταθούν με τιμή που θα σας ζητηθεί κατά " "την εκτέλεση." #: quodlibet/ext/songsmenu/custom_commands.py:56 #, fuzzy msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Το πρότυπο QL, π.χ. <~filename>, που χρησιμοποιείται για την δημιουργία της " "εντολής" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "μοναδικό" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Αν ορισθεί, θα αφαιρεθούν τυχών διπλότυπα αποτελέσματα του προτύπου" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "Μέγιστα ορίσματα" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Ο μέγιστος αριθμός ορισμάτων που θα δωθούν στην εντολή σε κάθε εκτέλεση " "(όπως στο xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Αντίστροφα" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Εισαγωγή τιμής" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Τιμή του %s;" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Προσαρμοσμένες Εντολές" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Εκτελεί προσαρμοσμένες εντολές (σε δέσμες αν χρειάζεται) σε τραγούδια " "χρησιμοποιώντας τις τιμές ετικετών τους" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Επεξεργασία Προσαρμοσμένων Εντολών" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Αδυναμία εκτέλεσης προσαρμοσμένης εντολής %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d ομάδα διπλότυπων" msgstr[1] "%d ομάδες διπλότυπων" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Σύμπτυξη / Ανάπτυξη όλων" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Το πρότυπο για το κλειδί διπλοτύπων είναι '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Αναζήτηση Διπλότυπων" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Εύρεση παρόμοιων εκδόσεων τραγουδιών." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Δέχεται εκφράσεις QL όπως <tt>~artist~title</tt> ή <tt>musicbrainz_track_id</" "tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Ομαδοποίηση διπλοτύπων με βάση:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Κλειδί Διπλοτύπων" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Διαγραφή _Κενών" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Διαγραφή _Διακριτικών Σημείων" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Διαγραφή _Στίξης" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Αγνόησε διαφορές πεζών/Κεφαλαίων" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Επιλογές ταιριάσματος" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Επεξεργασία Μετρητή Αναπαραγωγών" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Επεξεργασία των μετρητών ~#playcount και ~#skipcount τραγουδιού.\n" "\n" "Όταν έχουν επιλεχθεί πολλαπλά τραγούδια, οι μετρητές θα προσαυξηθούν αντί " "να\n" "καθοριστούν.\n" "\n" "Αν ορίσετε το ~#playcount ενός τραγουδιού σε 0, οι καταχωρήσεις " "~#lastplayed\n" "και ~#laststarted διαγράφονται. Αν όμως ορίσετε θετική τιμή σε τραγούδι που\n" "δεν έχετε παίξει ποτέ δεν θα δημιουργηθούν αυτές οι τιμές." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Μετρητής Αναπαραγωγών" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Μετρητής Παραλείψεων" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Πολλαπλές Τιμές %s" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Επεξεργασία Ενσωματωμένων Εικόνων" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Διαγραφή ή αντικατάσταση των ενσωματωμένων εικόνων." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "_Διαγραφή όλων των εικόνων" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "_Ενσωμάτωση τρέχουσας εικόνας" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Καθορισμός Ακριβούς Βαθμολογίας" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Επιτρέπει να ορισθεί η βαθμολογία τραγουδιού με αριθμό." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Παρακαλώ εισάγετε την επιθυμητή βαθμολογία με κλίμακα από 0,0 ως 1,0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Φίλτρο Βάσει Οποιασδήποτε Ετικέτας" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Δημιουργία αναζήτησης βασισμένης σε ετικέτες των επιλεγμένων τραγουδιών." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Φίλτρο βάσει Καταλόγου" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Φιλτράρισμα βάσει καταλόγου συστήματος αρχείων σε ένα νέο παράθυρο." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Αναζήτηση Ακουστικού Αποτυπώματος" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" "Αναζήτηση μεταδεδομένων τραγουδιών χρησιμοποιώντας τα ακουστικά αποτυπώματά " "τους" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Υποβολή Ακουστικών Αποτυπωμάτων" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Παράγει ακουστικά αποτυπώματα χρησιμοποιώντας το chromaprint και τα " "υποβάλλει στο 'acoustid.org'" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Λείπει το κλεδί API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Πρέπει να καθορίσετε ένα κλειδί API για το Acoustid.org στις προτιμήσεις του " "προσθέτου πριν υποβάλλετε αποτυπώματα." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Αίτηση για κλειδί API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Κλειδί API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Διαδικτυακή Υπηρεσία AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Σε αναμονή" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Αναλύονται" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Αναζήτηση" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Αποθήκευση" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Κυκλοφορία" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Αποθήκευση ετικετών MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Ομαδοποίηση κατά κατάλογο" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Λειτουργία Άλμπουμ" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Αποθήκευση ετικετών σχετικών με το άλμπουμ και προσπάθησε να μειώσεις τις " "διαφορετικές κυκλοφορίες άλμπουμ" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Παραγωγή αποτυπωμάτων:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Λεπτομέρειες" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Υποβολή" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Για να υποβληθούν τα τραγούδια χρειάζονται ετικέτες " "<i><b>musicbrainz_trackid</b></i> ή <i><b>artist</b></i> / <i><b>title</b></" "i> / <i><b>album</b></i>." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Αποτυπώματα:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Τραγούδια με MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Τραγούδια με επαρκείς ετικέτες:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Τραγούδια για υποβολή:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Τέλος. %(to-send)d/%(all)d τραγούδια για υποβολή." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Υποβάλλονται Αποτυπώματα:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Υποβάλλονται…" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Ανανέωση Σταθμών" #: quodlibet/ext/songsmenu/forcewrite.py:18 #, fuzzy msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Αποθήκευση των αρχείων ξανά. Οι μετρητές αναπαραγωγής και οι βαθμολογίες " "ενημερώνονται υποχρεωτικά." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Εξαγωγή σε HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Εξαγωγή της λίστας επιλεγμένων τραγουδιών σε HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Αποστολή στο iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Μεταφόρτωση τραγουδιών σε συσκευή iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Δεν βρέθηκαν στίχοι" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Μετακίνηση %(current)d από %(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Σφάλμα κατά τον συγχρονισμό" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Εξαγωγή Μεταδεδομένων" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Εξαγωγή Μεταδεδομένων" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Εξαγωγή Μεταδεδομένων" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Εξαγωγή Μεταδεδομένων" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Χωρίς πληροφορίες χρόνου" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Εξώφυλλα Άλμπουμ" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Η Εισαγωγή Απέτυχε" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Εισαγωγή" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Φίλτρο βάσει Καταλόγου" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Δίσκος" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Κομμάτι" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Καλλιτέχνης" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "άλμπουμ" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "Συνέ_χεια" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 #, fuzzy msgid "Nothing to import" msgstr "Τίποτα για προσθήκη" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Δεν βρέθηκε το %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Δεν βρέθηκε το %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Όνομα Αρχείου" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Τα κομμάτια μου" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Ενημέρωση λίστας chart." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Ήδη ενημερωμένο." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Λήψη chart εβδομάδας %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Ο συγχρονισμός ολοκληρώθηκε." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Σφάλμα κατά τον συγχρονισμό" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Συγχρονισμός last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" "Ενημερώστε τα στατιστικά της μουσικοθήκης σας από το προφίλ σας στο Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Όνομα χρήστη:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Δημιουργία Ετικετών Ταξινόμησης" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Μετατροπή ονομάτων άλμπουμ και καλλιτέχνη σε ετικέτες ταξινόμησης, συχνά " "αστόχως." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Εξαγωγή τραγουδιών σε λίστα M3U ή PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Χρήση σχετικών διαδρομών" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Χρήση απόλυτων διαδρομών" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Η εγγραφή στο <b>%s</b> απέτυχε." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Ανανέωση Τραγουδιών" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Ελέγχει για αλλαγές αρχείων και ξαναφορτώνει / αφαιρεί τα τραγούδια όπου " "χρειάζεται." #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Ανανέωση τραγουδιών" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Αναλυτής ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Κομμάτι" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Πρόοδος" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Ενίσχυση" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Κορυφή" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" "Υπάρχει ακόμα <b>%(to-process)d</b> άλμπουμ για ενημέρωση (από %(all)d)" msgstr[1] "" "Υπάρχουν ακόμα <b>%(to-process)d</b> άλμπουμ για ενημέρωση (από %(all)d)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, fuzzy, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Ανάλυση <a href=\"%(rg_link)s\">ReplayGain</a> με το GStreamer, με " "ομαδοποίηση κατά άλμπουμ." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "πάντα" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "αν λείπουν <b>οποιεσδήποτε</b> ετικέτες RG" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "Αν λείπουν οι ετικέτες RG του <b>άλμπουμ</b>" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Επεξεργασία άλμπουμ:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Υπάρχουσες Ετικέτες" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Διαχωρισμός Ετικετών" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Διαχωρισμός του αριθμού δίσκου από το όνομα άλμπουμ και της έκδοσης από τον " "τίτλο ταυτοχρόνως." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Διαχωρισμός Άλμπουμ" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Διαχωρισμός αριθμού δίσκου." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Προκαθορισμένο:" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Ετικέτα" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Αδυναμία διαγραφής τραγουδιών" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Αναζήτηση σε Ιστοσελίδα" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Αναζητεί σε ιστοσελίδα επιλογής σας χρησιμοποιώντας ετικέτες τραγουδιών.\n" "Υποστηρίζει πρότυπα π.χ. %(pattern-example)s" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Πρότυπα URL αναζήτησης" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Επεξεργασία των URL αναζήτησης" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Επεξεργασία αναζητήσεων…" #: quodlibet/ext/songsmenu/wikipedia.py:36 #, fuzzy msgid "Search Tag in Wikipedia" msgstr "Αναζήτηση του άλμπουμ στη Βικιπαίδεια" #: quodlibet/ext/songsmenu/wikipedia.py:37 #, fuzzy msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Ανοίγει ένα παράθυρο περιηγητή με το άρθρο της Βικιπαίδειας για το τρέχον " "άλμπουμ" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Αναζήτηση σε %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Επεξεργασία Ετικετών" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Η αποθήκευση απέτυχε" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Μουσικοθήκη" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Έλεγχος σημείων προσάρτησης" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Σάρωση της μουσικοθήκης" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Σάρωση του %s" #: quodlibet/library/file.py:250 #, fuzzy msgid "Loading files" msgstr "Η αποθήκευση απέτυχε" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Σάρωση της μουσικοθήκης" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Αφαίρεση ενεργών φίλτρων περιηγητή" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "Μουσικοθήκη και αναπαραγωγέας" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Αποτυχία ανοίγματος αρχείου: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Εμφάνιση ετικετών" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Εμφάνιση ωμής εξόδου" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Στήλες και η σειρά που θα εμφανιστούν στην ωμή έξοδο (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Εμφάνιση _προγραμματικών ετικετών" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Μη αρκετός αριθμός ορισμάτων" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Υπερβολικός αριθμός ορισμάτων" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Περιγραφή" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Τιμή" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Εμφάνιση όλων των κοινών ετικετών" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Αντιγραφή ετικετών από ένα αρχείο σε άλλο" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Δείξε τις αλλαγές χωρίς να τις εφαρμόσεις" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Παράλειψη ετικετών που δεν μπορούν να γραφούν" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Αδύνατη αντιγραφή της ετικέτας %r στο αρχείο %r" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Επεξεργασία ετικετών σε κειμενογράφο" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Ακύρωση επεξεργασίας" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Η εκκίνηση του επεξεργαστή κειμένου '%(editor-name)s' απέτυχε." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Δεν ανιχνεύθηκαν αλλαγές" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Καθόρισε μια ετικέτα και αφαίρεσε τις παρούσες τιμές της" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Αδύνατη αντιγραφή της ετικέτας %r στο αρχείο %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Διαγραφή ετικετών" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Η τιμή είναι κανονική παράσταση" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Διαγραφή όλων των ετικετών" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Αδύνατος ο συνδυασμός του '--all' με το '--regexp'" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Αδύνατη η αφαίρεση του %r από το %r" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Διαγραφή της τιμής ετικέτας" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Προσθήκη τιμής σε ετικέτα" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Αδύνατος ο ορισμός του %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Προβολή πληροφοριών αρχείου" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Καθορισμός της εικόνας ως κύριας ενσωματωμένης εικόνας και αφαίρεση των " "υπολοίπων ενσωματωμένων εικόνων." #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Αποτυχία ανοίγματος αρχείου εικόνας: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Η επεξεργασία εικόνων δεν επιτρέπεται για %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Διαγραφή όλων των ενσωματωμένων εικόνων" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Εξαγωγή ενσωματωμένων εικόνων σε %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Τοποθεσία αποθήκευσης εικόνων (η προεπιλογή είναι ο κατάλογος εργασίας)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Μετονομασία αρχείων βάσει ετικετών" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Συμπλήρωση ετικετών βάσει διαδρομής αρχείου" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Αρχείο" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Συμπλήρωση αριθμών κομματιού για όλα τα αρχεία" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Εμφάνιση ετικετών βάσει παρεχόμενου προτύπου" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Προβολή σύντομων πληροφοριών χρήσης" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "Το '%(column-id)s' δεν είναι έγκυρο όνομα στήλης (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "Ά_γνωστο" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Με τη Σειρά" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "Με τη _Σειρά" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Τυχαία" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Τυχαία" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "τελευταία αναπαραγωγή" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Επανάληψη" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Επανάληψη" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Ένα Τραγούδι" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Ένα Τραγούδι" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Ροή" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Buffering" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Αδυναμία δημιουργίας διασωλήνωσης GStreamer" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" "Δεν βρέθηκε στοιχείο GStreamer ικανό να χειριστεί αυτό το είδος αρχείου" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Μορφή πολυμέσου: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Το πρόσθετο '%(name)s' του Gstreamer δεν ήταν δυνατό να αρχικοποιηθεί" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Η διασωλήνωση του GStreamer που χρησιμοποιείται για αναπαραγωγή. Αφήστε το " "κενό για χρήση της προεπιλεγμένης τιμής. Αν η διασωλήνωση περιέχει και " "τελική έξοδο θα χρησιμοποιηθεί αντί της προεπιλεγμένης." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Διασωλήνωση εξόδου:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f δευτερόλεπτα" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Διάρκεια _Buffer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Απενεργοποίηση αναπαραγωγής χωρίς κενά (_gapless)" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Η απενεργοποίηση της αναπαραγωγής χωρίς κενά μερικές φορές αποτρέπει " "προβλήματα αλλαγής τραγουδιών με ορισμένες εκδόσεις του Gstreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Δεν βρέθηκε έξοδος ήχου GStreamer" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Μη έγκυρη διασωλήνωση εξόδου GStreamer" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Αδυναμία δημιουργίας εξόδου ήχου" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Η συσκευή ήχου %r δεν βρέθηκε. Ελέγξτε τις ρυθμίσεις του Xine στο ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Δεν βρέθηκε το πρόσθετο '{module}'. Ίσως χρειάζεται να εγκατασταθεί το " "πακέτο." #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Αδυναμία εύρεσης του στοιχείου '{element}' του GStreamer." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Παρακαλώ ανοίξτε το παράθυρο προσθέτων και ρυθμίστε το QLScrobbler. " "Διαφορετικά τα τραγούδια δεν θα υποβάλλονται." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Παρακαλώ ανοίξτε το παράθυρο προσθέτων και ρυθμίστε το QLScrobbler. " "Διαφορετικά τα τραγούδια δεν θα υποβάλλονται." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Υποβολή" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "Όνομα _χρήστη:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Τα τραγούδια που ταιριάζουν με αυτό το φίλτρο δεν θα υποβάλλονται" #: quodlibet/plugins/playlist.py:23 #, fuzzy, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d λίστα αναπαραγωγής;" msgstr[1] "" "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d λίστες αναπαραγωγής;" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Εκτέλεση Πρόσθετου" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Αρχή" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Μ/Δ" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Χρόνος" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Όνομα Σελιδοδείκτη" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "ΛΛ:ΔΔ" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Σελιδοδείκτες" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Φίλτρα" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Πρόσφατα _Αναπαραχθέντα" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Πρόσφατα _Προστεθέντα" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "Κορυφαία _40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Όλα τα Τ_ραγούδια" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Τυχαίο Εί_δος" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Τυχαίος Καλλι_τέχνης" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Τυχαίο Άλ_μπουμ" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "Τα 40 τραγούδια που έχετε ακούσει περισσότερο (θα επιλεχθούν πάνω από 40 αν " "υπάρχουν ισοπαλίες)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "Ό_νομα:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Τιμή" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Αποθηκευμένες Τιμές" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Επεξεργασία αποθηκευμένων τιμών…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Αυτό_ματα" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Λειτουργία _Κομματιού" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Λειτουργία Ά_λμπουμ" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Αναλυτής ReplayGain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Νέο %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(άγνωστο)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Προσθήκη" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Επεξεργασία…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Πρότυπο ετικέτας" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Πρότυπο ετικέτας π.χ. people:real ή ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Εισάγετε τη νέα ετικέτα" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Πρότυπο ετικέτας" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Αρχεία:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Τα επιλεγμένα τραγούδια θα αφαιρεθούν από τη μουσικοθήκη και τα αντίστοιχα " "αρχεία θα διαγραφούν από τον δίσκο." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Τα επιλεγμένα τραγούδια θα διαγραφούν από τον σκληρό σας δίσκο." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Να διαγραφεί %(file_count)d αρχείο μόνιμα;" msgstr[1] "Να διαγραφούν %(file_count)d αρχεία μόνιμα;" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Διαγραφή Αρχείων" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Τα επιλεγμένα τραγούδια θα αφαιρεθούν από τη μουσικοθήκη και τα αντίστοιχα " "αρχεία θα μετακινηθούν στα απορρίματα." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Τα επιλεγμένα τραγούδια θα μεταφερθούν στον κάδο απορριμάτων." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Μετακίνηση του %(file_count)d αρχείου στα απορρίματα;" msgstr[1] "Μετακίνηση των %(file_count)d αρχείων στα απορρίματα;" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Μετακίνηση στα Απορρίμματα" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Μετακίνηση %(current)d από %(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Αδυναμία μετακίνησης στα απορρίμματα" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Η μετακίνηση ενός ή περισσότερων αρχείων στα απορρίμματα απέτυχε." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Διαγραφή %(current)d από %(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Αδυναμία διαγραφής αρχείου" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Η διαγραφή ενός ή περισσότερων αρχείων απέτυχε." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Περιηγητές" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Κατέβασμα Αρχείων" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "Λείπει από %d τραγούδι" msgstr[1] "Λείπει από %d τραγούδια" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "Διαφορετικό σε %d τραγούδι" msgstr[1] "Διαφορετικό σε %d τραγούδια" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "_Διαμοιρασμός σε Πολλαπλές Τιμές" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Διαχωρισμός του Δίσκου από το Ά_λμπουμ" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Διαχωρισμός της Έκ_δοσης από τον Τίτλο" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Διαχωρισμός του Διευθετώντα από τον _Καλλιτέχνη" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Διαχωρισμός του _Εκτελεστή από τον Καλλιτέχνη" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Διαχωρισμός του _Εκτελεστή από τον Τίτλο" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Διαχωρισμός του _Αρχικού Καλλιτέχνη από τον Τίτλο" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Προσθήκη Ετικέτας" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "Ε_τικέτα:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Εμφάνιση _προγραμματικών ετικετών" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Επεξεργασία όλων των ετικετών, συμπεριλαμβανομένων και των αυτόματα " "δημιουργημένων απο λογισμικό όπως π.χ. MusicBrainz ή ετικέτες του Replay Gain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Εμφάνιση _προγραμματικών ετικετών" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "Επαναφο_ρά" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Αποθήκευση" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "Συνέ_χεια" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Διαχωρισμός Ετικετών" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Αντιγραφή εξώφυλλων ά_λμπουμ" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Αδυναμία προσθήκης ετικέτας" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Αδυναμία προσθήκης τραγουδιών" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Τα επιλεγμένα αρχεία δεν υποστηρίζουν πολλαπλές τιμές <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Μη έγκυρη ετικέτα" msgstr[1] "Μη έγκυρη ετικέτα" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Μη έγκυρη ετικέτα <b>%s</b>\n" "\n" "Τα επιλεγμένα αρχεία δεν υποστηρίζουν επεξεργασία αυτής της ετικέτας." msgstr[1] "" "Μη έγκυρη ετικέτα <b>%s</b>\n" "\n" "Τα επιλεγμένα αρχεία δεν υποστηρίζουν επεξεργασία αυτής της ετικέτας." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Μη έγκυρη τιμή" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Μη έγκυρη τιμή: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Η ετικέτα ίσως να μην είναι ακριβής" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "Το %(file-name)s άλλαξε ενώ το πρόγραμμα εκτελούταν. Η αποθήκευση χωρίς " "ανανέωση της μουσικοθήκης ίσως αντικαταστήσει άλλες αλλαγές στο τραγούδι." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Αδυναμία αποθήκευσης τραγουδιού" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Η αποθήκευση του %(file-name)s απέτυχε. Το αρχείο ίσως είναι μόνο για " "ανάγνωση, κατεστραμμένο, ή δεν έχετε δικαιώματα επεξεργασίας του." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Περισσότερες επιλογές…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Αναίρεση" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Ξανακάνε" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "Σ_χετικά" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Πρόσθετα" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s και %(count)d ακόμη" msgstr[1] "%(title)s και %(count)d ακόμη" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Προτιμήσεις του Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Φάκελοι" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Νέος Φάκελος…" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Επιλογή όλων των Υποφακέλων" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Νέος Φάκελος" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Εισάγετε όνομα για τον νέο φάκελο:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Αδυναμία δημιουργίας φακέλου" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Αδυναμία διαγραφής φακέλου" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Τραγούδια" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "από %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Δίσκος %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Κομμάτι %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Επεξεργασία Εμφάνισης…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Δεν υπάρχουν επιλεγμένα τραγούδια." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Κανένα Τραγούδι" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Πληροφορίες" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Στίχοι" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Παραγωγή από %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "καλλιτέχνης" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "καλλιτέχνες" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "εκτελεστές" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Ποτέ" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d φορά" msgstr[1] "%(n)d φορές" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "προστέθηκε" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "τελευταία αναπαραγωγή" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "αναπαραγωγές" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "παραλήψεις" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "βαθμολογία" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "διάρκεια" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "μορφή" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "Αύξουσα" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "μέγεθος αρχείου" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "τροποποίηση" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d επιλεγμένο" msgstr[1] "%d επιλεγμένα" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Μη διαθέσιμο κομμάτι" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d τραγούδι χωρίς άλμπουμ" msgstr[1] "%d τραγούδια χωρίς άλμπουμ" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Επιλεγμένη Δισκογραφία" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d τραγούδι χωρίς καλλιτέχνη" msgstr[1] "%d τραγούδια χωρίς καλλιτέχνες" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "άλμπουμ" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Συνολική διάρκεια:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Συνολικό μέγεθος:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Αρχεία" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Δεν βρέθηκαν στίχοι γι' αυτό το τραγούδι." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Θέλετε σίγουρα να αφαιρέσετε όλα τα τραγούδια;" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Τα επιλεγμένα τραγούδια θα αφαιρεθούν από τη μουσικοθήκη." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Επανεμφάνιση" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "Επανεμ_φάνιση" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Απόρριψη αλλαγών στις ετικέτες;" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Ετικέτες έχουν αλλαχθεί αλλά δεν έχουν αποθηκευθεί. Αποθήκευση αυτών των " "αρχείων ή επαναφορά και απόρριψη των αλλαγών;" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Επανέφε_ρε" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Το αρχείο υπάρχει" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Αντικατάσταση του %(file-name)s;" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "Αντικατάσταση Α_ρχείου" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Ενεργές διεργασίες" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d διεργασίες εκτελούνται" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Σειρά Αναπαραγωγής" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Επεξεργασία ετικετών" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Μετονομασία" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Ερώτημα:" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Μέγεθος _Εξώφυλλου:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Σφάλματα Πρόσθετων" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Ενεργοποιημένα" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Απενεργοποιημένα" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Χωρίς κατηγορία" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Χωρίς κατηγορία" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Δεν βρέθηκαν πρόσθετα." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Πρόσθετα" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Εμφάνιση _Λαθών" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Δίσκος" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Κομμάτι" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Ομα_δοποίηση" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Καλλιτέχνης" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Ά_λμπουμ" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Ό_νομα Αρχείου" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Διάρκεια" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Α_υτόματη μεταπήδηση στο αναπαραγώμενο τραγούδι" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Όταν το αναπαραγώμενο τραγούδι αλλάζει, μετάβαση σε αυτό στην λίστα " "τραγουδιών" #: quodlibet/qltk/prefs.py:72 #, fuzzy msgid "_Sort songs when tags are modified" msgstr "Προβολή στίχων κάτω από την λίστα τραγουδιών" #: quodlibet/qltk/prefs.py:74 #, fuzzy msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "Προβολή στίχων κάτω από την λίστα τραγουδιών" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "Ά_λλα:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Επεξεργασία…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Προσθαφαίρεση κεφαλίδων στηλών" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Ορατές Στήλες" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Ο Τίτλος να περιλαμβάνει την έκ_δοση" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Το Άλμπουμ περιλαμβάνει τον υπότιτλο του _δίσκου" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Το πεδίο Καλλιτέχνης συμπεριλαμβάνει τα ονόματα όλων των συντελεστών" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Το Όνομα Αρχείου συμπεριλαμβάνει και τον _φάκελο" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Προτιμήσεις Στηλών" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Επεξεργασία Στηλών" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Εφαρμογή τρεχόντων ρυθμίσεων στην λίστα τραγουδιών, προσθέτοντας νέες στήλες " "στο τέλος" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Λίστα Τραγουδιών" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Επεξεργασία Στηλών" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Κα_θολικό φίλτρο:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Εφαρμογή αυτού του ερωτήματος επιπροσθέτως από όλα τα άλλα" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Αναζήτηση" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Περιηγητές" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Επιβεβαίωση πο_λλαπλών βαθμολογήσεων" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Ζήτησε επιβεβαίωση πριν αλλάξεις τις βαθμολογίες πολλαπλών τραγουδιών " "μονομιάς" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Ενεργοποίηση βαθμολόγησης με έ_να κλικ" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Επέτρεψε τη βαθμολόγηση κάνοντας κλικ στην στήλη βαθμολογίας της λίστας " "τραγουδιών" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Βαθμολογίες" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Προτίμηση _ενσωματωμένων εικόνων" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Χρήση εξώφυλλων ενσωματωμένων στο αρχείο ήχου (όταν είναι διαθέσιμο) αντί " "από άλλες πηγές" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "Ε_ξαναγκασμός ονόματος αρχείου εικόνας:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Εξώφυλλα Άλμπουμ" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Αναπαραγωγή" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Ρύθμιση Εξόδου" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Αν δεν είναι διαθέσιμες πληροφορίες Replay Gain για ένα τραγούδι, κλιμάκωσε " "την ένταση του ήχου κατά αυτή την τιμή" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Εναλλακτική τιμή gain (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Κλιμάκωσε την ένταση για όλα τα τραγούδια κατά αυτή την τιμή, αρκεί να μην " "υπάρξει αποκοπή" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Gain _προενίσχυσης (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Ρύθμιση της έντασης ήχου από το Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Ρύθμισης Έντασης Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Προεπιλεγμένη βαθμολογία:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Βαθμολογική κλίμακα:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Μέσος Μπαγεσιανός παράγοντας (C) για την συγκεντρωτική βαθμολογία.\n" "Το 0 σημαίνει χρήση συμβατικού μέσου όρου, υψηλότερες τιμές σημαίνουν πως τα " "άλμπουμ με λίγα τραγούδια θα έχουν λιγότερο ακραίες βαθμολογίες. Αν αλλαχθεί " "αυτή η τιμή ενεργοποιείται επανυπολογισμός για όλα τα άλμπουμ." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Μπαγεσιανός παράγοντας μέσου όρου:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "Διεύθυνση ηλεκτρονικού _ταχυδρομείου:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Οι βαθμολογίες και οι μετρητές αναπαραγωγών θα καθοριστούν γι' αυτή την " "διεύθυνση" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Αυτόματη αποθήκευση αλλαγών στις ετικέτες" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Αποθήκευση αλλαγών στις ετικέτες χωρίς επιβεβαίωση όταν γίνεται επεξεργασία " "πολλαπλών αρχείων" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Λίστα διαχωριστών που θα χρησιμοποιηθούν κατά των διαχωρισμό τιμών ετικετών. " "Η λίστα είναι διαχωρισμένη με κενά" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Διαχωρισμός _στο:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Λίστα διαχωριστών που θα χρησιμοποιηθούν κατά των διαχωρισμό τιμών ετικετών. " "Η λίστα είναι διαχωρισμένη με κενά" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Διαχωρισμός _στο:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Ετικέτες" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Επεξεργασία ετικετών" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Ανανέωση για τις νέες βαθμολογίες" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Αναζήτηση στην Μουσικοθήκη" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Έλεγχος για αλλαγές στην μουσικοθήκη σας" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "_Επαναφόρτωση Μουσικοθήκης" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Επαναφόρτωση όλων των τραγουδιών της μουσικοθήκης σας. Πιθανό να χρειαστεί " "αρκετό χρόνο." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Κρυμμένα Τραγούδια" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "_Ανανέωση της μουσικοθήκης κατά την εκκίνηση" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Σάρωση Καταλόγων" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s και %(count)d ακόμη" msgstr[1] "%(title)s και %(count)d ακόμη" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Ιδιότητες" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Ουρά Αναπαραγωγής" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Καθαρισμός" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Γενικά" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Αφαίρεση όλων των τραγουδιών από τη ουρά" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Μοντέλο:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d τραγούδι (%(time)s)" msgstr[1] "%(count)d τραγούδια (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Περιήγηση στην Μουσικοθήκη" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Εναλλαγή ορατότητας κυρίου παραθύρου" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Σφάλμα Αναπαραγωγής" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Να οριστούν οι κατάλογοι της μουσικοθήκης;" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Δεν έχετε ορίσει την μουσικοθήκη σας. Θα θέλατε να το κάνετε τώρα;" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Αργότερα" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Ρύθμιση" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Αδυναμία προσθήκης τραγουδιών" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "Το πρωτόκολλο του %s δεν υποστηρίζεται." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Μεταπήδηση στο Αναπαραγώμενο Τραγούδι" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Αρχείο" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Τραγούδια" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Προβολή" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Περιηγητές" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "Έ_λεγχος" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Βοήθεια" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "Προσθήκη _Φακέλου…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Προσθήκη _Αρχείου…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Προσθήκη _Τοποθεσίας" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Επεξεργασία Σελιδοδεικτών…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Σταμάτα" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Σταμάτησε μετά από αυτό το τραγούδι" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Βοήθεια στο Διαδίκτυο" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Αναζήτηση στη Βοήθεια" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Προσθήκη Τοποθεσίας" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Εισάγετε την τοποθεσία ενός αρχείου ήχου:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Αδυναμία προσθήκης τοποθεσίας" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "Το %s δεν είναι έγκυρη τοποθεσία." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Προσθήκη Μουσικής" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "Προσθήκη _Φακέλου…" #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Αναπαραγωγή Μουσικής" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "Προσθήκη _Αρχείου…" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Θέλετε σίγουρα να αφαιρέσετε όλα τα τραγούδια;" msgstr[1] "Θέλετε σίγουρα να αφαιρέσετε όλα τα τραγούδια;" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Ουρά Αναπαραγωγής" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Σίγουρα θέλετε να αλλάξετε βαθμολογία και στα %d τραγούδια;" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Οι αποθηκευμένες βαθμολογίες θα διαγραφούν" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Διαγραφή Βαθμολογίας" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Η βαθμολογία όλων των επιλεγμένων τραγουδιών θα αλλαχθεί σε '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Αλλαγή _Βαθμολογίας" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Αντικατάσταση κενών με _κάτω παύλες" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Αφαίρεση χαρακτήρων μη συμβατών με τα _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Αφαίρεση _διακριτικών συμβόλων" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Αφαίρεση μη-_ASCII χαρακτήρων" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Χρήση μόνο πε_ζών γραμμάτων" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Μετονομασία Αρχείων" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Προεπισκόπηση" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Όνομα Αρχείου" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "καλλιτέχνης άλμπουμ" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Αφαίρεση αχρείαστων εξώφυλλων και φακέλων" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Εξώφυλλα Άλμπουμ" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Νέο Όνομα" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Αδυναμία μετονομασίας αρχείου" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Η μετονομασία του <b>%(old-name)s</b> σε <b>%(new-name)s</b> απέτυχε. " "Πιθανότατα το αρχείο προορισμού υπάρχει ήδη, ή δεν έχετε δικαιώματα " "δημιουργίας νέου αρχείου ή διαγραφής του παλιού." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Αγνόηση Όλων των Σ_φαλμάτων" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Σταμάτα" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "Συνέ_χεια" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Η διαδρομή αρχείου δεν είναι απόλυτη" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Το πρότυπο\n" "\t<b>%s</b>\n" "περιέχει το / μα δεν ξεκινά από τη βάση του συστήματος αρχείων. Για να " "αποφύγετε λάθος ονομασμένους φακέλους, ξεκινήστε το πρότυπό σας με / ή ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Τραγούδια από τους εμφανιζόμενους φακέλους θα προστεθούν στην μουσικοθήκη " "σας μετά από ανανέωση" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Τα επιλεγμένα τραγούδια θα αφαιρεθούν από τη μουσικοθήκη." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Removing orphaned iPod track" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Τοποθεσία μουσικοθήκης:" msgstr[1] "Τοποθεσία μουσικοθήκης:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Αφαίρεση" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Επιλεγμένοι Κατάλογοι" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Επιλεγμένοι Κατάλογοι" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Αποθηκευμένες Αναζητήσεις" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Επεξεργασία αποθηκευμένων αναζητήσεων…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" "Αναζήτηση στην μουσικοθήκη σας, με χρήση ελεύθερου κειμένου ή ερωτημάτων QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Αναζήτηση με την _πληκτρολόγηση" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" "Εμφάνισε τα αποτελέσματα αναζήτησης αφού ο χρήστης σταματήσει την " "πληκτρολόγηση" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "Ό_ριο:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Βαρύτητα" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "ερώτημα" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Προβολή χρόνου που υπολείπεται" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Παράθυρο Στίχων" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Εστίαση του εκτελούμενου αναπαραγωγέα" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Αναζήτηση στο αναπαραγόμενο τραγούδι" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Αδυναμία διαγραφής τραγουδιών" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Αδυναμία διαγραφής τραγουδιών" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 #, fuzzy msgid "Expands the element" msgstr "_Επέκταση Στήλης" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Φίλτρο στο %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Όλες οι Κε_φαλίδες" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Κεφαλίδες _Κομματιών" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Κεφαλίδες Ά_λμπουμ" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Κεφαλίδες _Συντελεστών" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Κεφαλίδες _Ημερομηνιών" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Κεφαλίδες Αρ_χείων" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Κεφαλίδες Παρα_γωγής" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "Προσαρμογή _Κεφαλίδων…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Επέκταση Στήλης" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Α_φαίρεση από την μουσικοθήκη" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Α_φαίρεση από την μουσικοθήκη" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "Α_φαίρεση από την μουσικοθήκη" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d τραγούδι;" msgstr[1] "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d τραγούδια;" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d άλμπουμ;" msgstr[1] "Εκτέλεση του πρόσθετου \"%(name)s\" σε %(count)d άλμπουμ;" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Επεξεργασία αναζητήσεων…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Προσθήκη στην _Ουρά" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "Α_φαίρεση από την μουσικοθήκη" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Αδυναμία διαγραφής αρχείου" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Λήψη" msgstr[1] "_Λήψη" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Η αποθήκευση απέτυχε" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Κατέβασμα Αρχείου" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Λήψη Εξώφυλλων Άλμπουμ" msgstr[1] "Λήψη Εξώφυλλων Άλμπουμ" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Κατέβασμα Αρχείου" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Αντικατάσταση _κάτω παύλων με κενά" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Κάντε _Κεφαλαία Τα Πρώτα Γράμματα Κάθε Λέξης Στις Ετικέτες" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Διαχωρισμός σε πο_λλαπλές τιμές" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Ετικέτες από την Διαδρομή Αρχείου" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Οι ετικέτες αντικαθιστούν τις ήδη υπάρχουσες" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Οι ετικέτες προστίθενται στις ήδη υπάρχουσες" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Το πρότυπο\n" "\t<b>%s</b>\n" "δεν είναι έγκυρο. Πιθανότατα περιέχει την ίδια ετικέτα δύο φορές ή έχει μη " "ισορροπημένες γωνιακές αγκύλες (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Το πρότυπο που εισάγατε δεν ήταν έγκυρο. Βεβαιωθείτε πως εισάγετε τα < " "και > ως \\< και \\> και πως οι ετικέτες σας είναι ισορροπημένες.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Επεξεργασία Προβολής" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Αριθμοί Κομματιών" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Αρ_χή από:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Συνολικός αριθμός κομματιών:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Αναπαραγωγή/Παύση" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Προηγούμενο" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "και %d ακόμη…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Αποθήκευση των τραγουδιών που επεξεργαστήκατε" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d τραγούδια αποθηκεύτηκαν\n" "(%(remaining)s απομένουν)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "%(current)d από %(all)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Έλεγχος σημείων προσάρτησης" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "Σύνδεση" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Υπάρχει ήδη λίστα αναπαραγωγής με το όνομα %s." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Επαναφόρτωση ε_ξώφυλλου του άλμπουμ" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Χρήση ενσωματωμένων εξώφυλλων άλμπουμ." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Εξώφυλλο άλμπουμ από το σύστημα αρχείων" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "Χρήση εικόνων που βρίσκονται στον κατάλογο μαζί με το τραγούδι" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Μέγεθος _Εξώφυλλου:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Προβολή σύντομων πληροφοριών χρήσης" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Προβολή έκδοσης και πνευματικών δικαιωμάτων" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Προβολή πληροφοριών αρχείου" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Χρήση: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[επιλογές]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Η επιλογή %r δεν αναγνωρίστηκε" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Η επιλογή %r χρειάζεται ένα όρισμα" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "Το %r δεν είναι μοναδικά ταυτοποιήσιμο πρόθεμα" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d δευτερόλεπτο" msgstr[1] "%d δευτερόλεπτα" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Χωρίς πληροφορίες χρόνου" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d δευτερόλεπτο" msgstr[1] "%d δευτερόλεπτα" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d λεπτό" msgstr[1] "%d λεπτά" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d ώρα" msgstr[1] "%d ώρες" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d ημέρα" msgstr[1] "%d ημέρες" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d χρόνος" msgstr[1] "%d χρόνια" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Η ημερομηνία πρέπει να εισαχθεί με μορφή 'ΧΧΧΧ', 'ΧΧΧΧ-ΜΜ-ΗΗ' ή 'ΧΧΧΧ-ΜΜ-ΗΗ " "ΩΩ:ΛΛ:ΔΔ'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Οι ενισχύσεις του Replay Gain πρέπει να εισαχθούν με μορφή 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Οι μέγιστες κορυφές Replay Gain πρέπει να εισαχθούν σε μορφή 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Οι ταυτότητες του MusicBrainz πρέπει να είναι σε μορφή UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Η κατάσταση κυκλοφορίας του MusicBrainz πρέπει να είναι 'επίσημη', " "'διαφημιστική' ή 'πειρατική'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Η γλώσσα πρέπει να είναι σε μορφή κώδικα τριών γραμμάτων ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Η αποθήκευση απέτυχε" msgstr[1] "Η αποθήκευση απέτυχε" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Αδυναμία επεξεργασίας τραγουδιού" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Η αποθήκευση του <b>%s</b> απέτυχε. Το αρχείο ίσως είναι μόνο για ανάγνωση, " "κατεστραμμένο, ή δεν έχετε δικαιώματα επεξεργασίας του." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Μη έγκυρη Κωδικοποίηση]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "άλμπουμ" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "διευθετών" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "διευθετώντες" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "διευθέτηση" #: quodlibet/util/tags.py:86 msgid "author" msgstr "συγγραφέας" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "συγγραφείς" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "εντολή" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "συνθέτης" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "συνθέτες" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "σύνθεση" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "διευθυντής ορχήστρας" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "διευθυντές ορχήστρας" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "διεύθυνση ορχήστρας" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "σύνδεσμος" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "πνευματική ιδιοκτησία" #: quodlibet/util/tags.py:93 msgid "date" msgstr "ημερομηνία" #: quodlibet/util/tags.py:94 msgid "description" msgstr "περιγραφή" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "είδος" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "είδη" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "εκτελεστής" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "εκτελεστής" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "ομαδοποίηση" #: quodlibet/util/tags.py:98 msgid "language" msgstr "γλώσσα" #: quodlibet/util/tags.py:99 msgid "license" msgstr "άδεια" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "στιχουργός" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "στιχουργοί" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "στιχουργός" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "οργάνωση" #: quodlibet/util/tags.py:104 msgid "title" msgstr "τίτλος" #: quodlibet/util/tags.py:105 msgid "version" msgstr "έκδοση" #: quodlibet/util/tags.py:106 msgid "website" msgstr "ιστοσελίδα" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "καλλιτέχνης άλμπουμ" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "ρυθμός (BPM - διακροτήματα ανά λεπτό)" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "υπότιτλος δίσκου" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "δίσκος" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "κομμάτι" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "δισκογραφική ταυτότητα" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "ημερομηνία αρχικής κυκλοφορίας" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "αρχικό άλμπουμ" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "αρχικός καλλιτέχνης" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "ημερομηνία ηχογράφησης" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "χώρα κυκλοφορίας" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "Ταυτότητα ηχογράφησης MusicBrainz" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "Ταυτότητα κυκλοφορίας κομματιού MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "Ταυτότητα κυκλοφορίας MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "Ταυτότητα καλλιτέχνη MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "Ταυτότητα καλλιτέχνη κυκλοφορίας MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "Ταυτότητα TRM MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "Ταυτότητα PUID MusicBrainz" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Κατάσταση κυκλοφορίας άλμπουμ MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Τύπος άλμπουμ MusicBrainz" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "Ταυτότητα κυκλοφορίας MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "ενίσχυση κομματιού" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "ηχητική κορυφή κομματιού" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "ενίσχυση άλμπουμ" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "ηχητική κορυφή άλμπουμ" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "ηχητική ένταση αναφοράς" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "δίσκοι" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "κομμάτια" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "τελευταία εκκίνηση αναπαραγωγής" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "πλήρες όνομα" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "σημείο προσάρτησης" #: quodlibet/util/tags.py:166 msgid "people" msgstr "συντελεστές" #: quodlibet/util/tags.py:168 msgid "year" msgstr "έτος" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "έτος αρχικής κυκλοφορίας" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "σελιδοδείκτης" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "τύπος αρχείου" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "λίστες αναπαραγωγής" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 #, fuzzy msgid "channel count" msgstr "Λογαριασμός" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "ταξινόμηση" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "ρόλοι" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Επεξεργαστής ετικετών μουσικής" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Επεξεργάσου τις ετικέτες στα αρχεία μουσικής σου" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Έξοδος από τον Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Αναπαραγωγή Μουσικής" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Ακούστε, περιηγηθείτε ή επεξεργαστείτε την μουσική σας συλλογή" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Το Ex Falso είναι επεξεργαστής ετικετών μουσικής με διεπαφή ίδια με τον Quod " "Libet. Επιτρέπει την προβολή και επεξεργασία όλων των ετικετών του αρχείου, " "για κάθε τύπο αρχείου που υποστηρίζει." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Οι υποστηριζόμενοι τύποι αρχείων περιλαμβάνουν τα Ogg Vorbis/Opus/Speex/" "FLAC, MP3, FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, " "WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "O Quod Libet είναι ένα πρόγραμμα διαχείρισης της μουσικής σας. Παρέχει " "πολλούς διαφορετικούς τρόπους προβολής της μουσικοθήκης σας, καθώς και " "υποστήριξη για διαδικτυακό ραδιόφωνο και ροών ήχου. Έχει απίστευτα ευέλικτες " "δυνατότητες επεξεργασίας και αναζήτησης μεταδεδομένων ετικετών μουσικής." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Εξαγωγή σε λίστα του Squeezebox" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Αδυναμία προσθήκης <b>%s></b>" #~ msgid "Invalid tags" #~ msgstr "Μη έγκυρες ετικέτες" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Μη έγκυρες ετικέτες <b>%s</b>\n" #~ "\n" #~ "Τα επιλεγμένα αρχεία δεν υποστηρίζουν την επεξεργασία αυτών των ετικετών." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Αυτόματη βαθμολόγιση των τραγουδιών καθώς αναπαράγωνται ή προσπερνούνται. " #~ "Με τη χρήση του 'επιταχυνόμενου' αλγόριθμου του Brian Nelson από το vux." #, fuzzy #~ msgid "Startup" #~ msgstr "Ξεκίνα την εισαγωγή" #~ msgid "Audio Feeds" #~ msgstr "Ροές Ήχου" #~ msgid "_Audio Feeds" #~ msgstr "_Ροές Ήχου" #~ msgid "New" #~ msgstr "Νέο" #~ msgid "Automatic Library Update" #~ msgstr "Αυτόματη Ανανέωση Μουσικοθήκης" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "" #~ "Διατηρεί τη μουσικοθήκη σας ενημερωμένη με χρήση inotify. Χρειάζεται το " #~ "%s." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "Έλεγχος του Quod Libet με χρήση της διεπαφής D-Bus MPRIS 1.0/2.0." #~ msgid "Searching for lyrics…" #~ msgstr "Αναζήτηση στίχων…" #, fuzzy #~ msgid "<artist>" #~ msgstr "καλλιτέχνης" #, fuzzy #~ msgid "<album>" #~ msgstr "άλμπουμ" #, fuzzy #~ msgid "<title>" #~ msgstr "τίτλος" #, fuzzy #~ msgid "OK" #~ msgstr "_Εντάξει" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Εξαγωγή μεταδεδομένων των επιλεγμένων τραγουδιών σε ένα αρχείο .tags." #~ msgid "Import Metadata" #~ msgstr "Εισαγωγή Μεταδεδομένων" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Εισαγωγή μεταδεδομένων για τα επιλεγμένα τραγούδια από ένα αρχείο .tags." #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Εξαγωγή Μεταδεδομένων" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Πληροφορίες" #~ msgid "Unsupported file type" #~ msgstr "Μη υποστηριζόμενος τύπος αρχείου" #~ msgid "Unable to add station" #~ msgstr "Δεν μπορεί να προστεθεί ο σταθμός" #~ msgid "Device Properties" #~ msgstr "Ιδιότητες Συσκευής" #~ msgid "Device:" #~ msgstr "Συσκευή:" #~ msgid "Not mounted" #~ msgstr "Μη προσαρτημένο" #~ msgid "Mount point:" #~ msgstr "Σημείο Προσάρτησης:" #~ msgid "Media Devices" #~ msgstr "Συσκευές Μέσων" #~ msgid "_Media Devices" #~ msgstr "_Συσκευές Μέσων" #~ msgid "_Eject" #~ msgstr "_Εξαγωγή" #~ msgid "_Properties" #~ msgstr "_Ιδιότητες" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s σε χρήση, %(free-size)s διαθέσιμο" #~ msgid "%s is not connected." #~ msgstr "%s δεν είναι συνδεδεμένο." #~ msgid "Copying %(song)s" #~ msgstr "Αντιγραφή %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Αδυναμία αντιγραφής τραγουδιού" #~ msgid "There is not enough free space for this song." #~ msgstr "Δεν υπάρχει αρκετός ελεύθερος χώρος γι' αυτό το τραγούδι" #~ msgid "%s could not be copied." #~ msgstr "Το %s δεν μπόρεσε να αντιγραφεί." #~ msgid "Unable to delete songs" #~ msgstr "Αδυναμία διαγραφής τραγουδιών" #~ msgid "Deleting %(song)s" #~ msgstr "Διαγραφή %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "Δεν ήταν δυνατό να διαγραφεί το %s." #~ msgid "Unable to delete song" #~ msgstr "Αδυναμία διαγραφής τραγουδιού" #~ msgid "Ejecting %s failed." #~ msgstr "Η εξαγωγή του %s απέτυχε." #~ msgid "Unable to eject device" #~ msgstr "Αδυναμία εξαγωγής συσκευής" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Χωρίς υποστήριξη συσκευών, ο περιηγητής Συσκευών Μέσων απενεργοποιήθηκε." #~ msgid "Search Library" #~ msgstr "Αναζήτηση στην Μουσικοθήκη" #~ msgid "_Search Library" #~ msgstr "_Αναζήτηση στην Μουσικοθήκη" #~ msgid "Rate the playing song" #~ msgstr "Βαθμολόγηση αναπαραγόμενου τραγουδιού" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Εμφάνιση ή απόκρυψη της κύριας λίστας τραγουδιών" #~ msgid "Unknown Device" #~ msgstr "Άγνωστη Συσκευή" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Δεν μπόρεσε να εισαχθεί το %s, που χρειάζεται για υποστήριξη συσκευών." #~ msgid "%r is not a supported device." #~ msgstr "Το %r δεν είναι υποστηριζόμενη συσκευή." #~ msgid "Initializing device backend." #~ msgstr "Αρχικοποίηση υποστήριξης συσκευών" #~ msgid "Trying '%s'" #~ msgstr "Δοκιμή '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Δεν ήταν δυνατή η σύνδεση σε κάποιο σύστημα υποστήριξης συσκευών." #~ msgid "Device backend initialized." #~ msgstr "Αρχικοποιήθηκε η υποστήριξη συσκευών." #~ msgid "_Filename pattern:" #~ msgstr "_Πρότυπο ονόματος αρχείου:" #, fuzzy #~ msgid "Quit Program" #~ msgstr "_Πρόγραμμα:" #~ msgid "Top of screen" #~ msgstr "Κορυφή της οθόνης" #~ msgid "Middle of screen" #~ msgstr "Μέση της οθόνης" #~ msgid "Bottom of screen" #~ msgstr "Κάτω μέρος της οθόνης" #~ msgid "_Clear" #~ msgstr "_Καθαρισμός" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Απενεργοποίηση της προστασίας οθόνης του GNOME κατά την αναπαραγωγή." #~ msgid "Lyrics:" #~ msgstr "Στίχοι:" #, fuzzy #~ msgid "_Zoom level:" #~ msgstr "Επίπε_δο:" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Καθαρισμός αναζήτησης" #~ msgid "Lyrics Window" #~ msgstr "Παράθυρο Στίχων" #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "Εμφανίζει ένα παράθυρο με στίχους του αναπαραγώμενου τραγουδιού." #~ msgid "_Lyrics" #~ msgstr "_Στίχοι" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Μετρητής Παραλείψεων" #~ msgid "Browse Folders" #~ msgstr "Άνοιγμα Φακέλου" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Άνοιγμα του φακέλου του τραγουδιού με τον διαχειριστή αρχείων." #~ msgid "Unable to open folders" #~ msgstr "Αδυναμία ανοίγματος φακέλων" #~ msgid "No program available to open folders." #~ msgstr "Δεν υπάρχει διαθέσιμη εφαρμογή για το άνοιγμα φακέλων." #, fuzzy #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Υποστηρίζει πρότυπα QL\n" #~ "π.χ. <tt><~artist~title></tt>" #~ msgid "Fix MP3 Duration" #~ msgstr "Διόρθωση της διάρκειας του MP3" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Αφαιρεί από τις ID3 ετικέτες τις καταχωρήσεις TLEN, που ίσως δημιουργούν " #~ "λανθασμένες διάρκειες τραγουδιών." #~ msgid "Burn CD" #~ msgstr "Κάψιμο CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Δημιουργία CD με το K3b το Brasero ή το xfburn." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Αναζήτηση του καλλιτέχνη στη Βικιπαίδεια" #~ msgid "" #~ "Opens a browser window with Wikipedia article on the playing song artist." #~ msgstr "" #~ "Ανοίγει ένα παράθυρο περιηγητή με το άρθρο της Βικιπαίδειας για τον " #~ "καλλιτέχνη του τρέχοντος τραγουδιού." #~ msgid "Audio device: %s" #~ msgstr "Συσκευή ήχου: %s" #~ msgid "Downloads" #~ msgstr "Λήψεις" #~ msgid "Size" #~ msgstr "Μέγεθος" #~ msgid "_Download" #~ msgstr "_Λήψη" #~ msgid "The single image filename to use if selected" #~ msgstr "Το όνομα αρχείου εικόνας που θα χρησιμοποιηθεί υποχρεωτικά" #~ msgid "The album art image file to use when forced" #~ msgstr "Το όνομα αρχείου εικόνας που θα χρησιμοποιηθεί υποχρεωτικά" #~ msgid "_Copy to Device" #~ msgstr "Αντιγραφή στην _Συσκευή" #~ msgid "Save" #~ msgstr "Αποθήκευση" #, fuzzy #~ msgid "browsers" #~ msgstr "Περιηγητές" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Δεν μπόρεσα να εισάγω τη λειτουργία %s, ο περιηγητής ροών ήχου " #~ "απενεργοποιήθηκε." #~ msgid "Controls the tone of your music with an equalizer." #~ msgstr "Έλεγχος της χροιάς της μουσικής σας με χρήση αντισταθμιστή." #~ msgid "Event Logging" #~ msgstr "Καταγραφή Συμβάντων" #~ msgid "Sends song events to the Zeitgeist event logging service." #~ msgstr "Αποστολή συμβάντων αναπαραγωγής στην υπηρεσία καταγραφής Zeitgeist." #~ msgid "Audio Backend Failed to Load" #~ msgstr "Αδυναμία Φόρτωσης Ηχητικού Συστήματος" #~ msgid "" #~ "Loading the audio backend '%(name)s' failed. Audio playback will be " #~ "disabled." #~ msgstr "" #~ "Η φόρτωση του ηχητικού συστήματος '%(name)s' απέτυχε. Η αναπαραγωγή ήχου " #~ "θα απενεργοποιηθεί." #~ msgid "_Open" #~ msgstr "Άν_οιγμα" #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Σημειώθηκε μια εξαίρεση στον Quod Libet. Ένα αρχείο καταγραφής σώθηκε στο " #~ "<b>%(dump-path)s</b> που θα βοηθήσει στην επίλυση του σφάλματος. Παρακαλώ " #~ "καταχωρήστε μια αναφορά στο %(new-issue-url)s και συμπεριλάβετε αυτό το " #~ "αρχείο. Αυτό το αρχείο ίσως περιέχει στοιχεία που προσωποποιούν εσάς ή το " #~ "σύστημά σας, π.χ. η λίστα των πρόσφατα παιγμένων αρχείων σας. Αν αυτό δεν " #~ "είναι επιθυμητό στείλτε το αρχείο <b>%(mini-dump-path)s</b> μαζί με μια " #~ "περιγραφή του τι κάνατε." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "Ο Quod Libet ίσως είναι ασταθής. Συνίσταται επανεκκίνησή του. Η " #~ "μουσικοθήκη σας θα αποθηκευθεί." #~ msgid "Unable to download lyrics." #~ msgstr "Αδυναμία λήψης στίχων." #~ msgid "Set or toggle the playback order" #~ msgstr "Καθορισμός ή εναλλαγή της σειράς αναπαραγωγής" #~ msgid "Uninitialized iPod" #~ msgstr "Μη αρχικοποιημένο iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Θέλεις να δημιουργήσεις μια άδεια βάση δεδομένων σε αυτό το iPod;" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Αύξηση Ήχου (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Συνδύασε ετικέτες με _πολλαπλές τιμές" #~ msgid "Capacity:" #~ msgstr "Χωρητικότητα:" #~ msgid "Firmware:" #~ msgstr "Έκδοση Υλικολογισμικού:" #~ msgid "Saving iPod database…" #~ msgstr "Αποθήκευση της βάσης δεδομένων του iPod…" #~ msgid "Unable to save iPod database" #~ msgstr "Αδυναμία αποθήκευσης της βάσης δεδομένων του iPod" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Δεν βρέθηκε το libgpod, η υποστήριξη iPod απενεργοποιήθηκε." #~ msgid "Playback follows your selection." #~ msgstr "Αναπαραγωγή επιλεγμένων τραγουδιών." #~ msgid "Track Repeat" #~ msgstr "Επανάληψη Κομματιού" #~ msgid "Shuffle" #~ msgstr "Ανακάτεμα" #~ msgid "Weighted" #~ msgstr "Με τη Βαρύτητα" #~ msgid "_Weighted" #~ msgstr "Με τη _Βαρύτητα" #~ msgid "_One Song" #~ msgstr "Ένα _Τραγούδι" #~ msgid "Restart the playlist when finished" #~ msgstr "Εκκίνηση ξανά της λίστας αναπαραγωγής όταν φτάσει στο τέλος" #~ msgid "Disable Browser" #~ msgstr "Απενεργοποίηση Περιηγητή" #~ msgid "_Disable Browser" #~ msgstr "_Απενεργοποίηση Περιηγητή" #~ msgid "Use header bars" #~ msgstr "Χρήση επικεφαλίδων παραθύρων GNOME" #~ msgid "Force Write" #~ msgstr "Υποχρεωτική Αποθήκευση" #~ msgid "Filter on _Genre" #~ msgstr "Φίλτρο στο _Είδος" #~ msgid "Filter on _Artist" #~ msgstr "Φίλτρο στον _Καλλιτέχνη" #~ msgid "Filter on Al_bum" #~ msgstr "Φίλτρο στο Ά_λμπουμ" #~ msgid "_Music" #~ msgstr "_Μουσική" #~ msgid "Add Bookmark" #~ msgstr "Προσθήκη Σελιδοδείκτη" #~ msgid "Song _List" #~ msgstr "_Λίστα Τραγουδιών" #, fuzzy #~ msgid "Rate the selected songs with 0-4 stars" #~ msgstr "Εξαγωγή της λίστας επιλεγμένων τραγουδιών σε HTML." #~ msgid "Embed cover" #~ msgstr "Ενσωμάτωσε το εξωφύλλο άλμπουμ" #~ msgid "D:" #~ msgstr "Α:" #~ msgid "W:" #~ msgstr "Π:" #~ msgid "E:" #~ msgstr "Σ:" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Ο τροχός του ποντικιού αλλάζει τραγούδια\n" #~ "Ο τροχός με πατημένο το Shift αυξομειώνει την ένταση" #~ msgid "Stop _after this song" #~ msgstr "Σταμάτησε _μετά από αυτό το τραγούδι" #~ msgid "_Release:" #~ msgstr "_Κυκλοφορία:" #~ msgid "%d _release:" #~ msgid_plural "%d _releases:" #~ msgstr[0] "%d _κυκλοφορία:" #~ msgstr[1] "%d _κυκλοφορίες:" #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "Βρέθηκε %d αποτέλεσμα." #~ msgstr[1] "Βρέθηκαν %d αποτελέσματα." #~ msgid "Split _disc from album" #~ msgstr "_Διαχωρισμός του δίσκου από το άλμπουμ" #~ msgid "Split _featured performers from track" #~ msgstr "Διαχωρισμός των εμφανιζόμενων (_featured) εκτελεστών από το κομμάτι" #~ msgid "Write _labelid tag (fixes multi-disc albums)" #~ msgstr "Εγγραφή ετικέτας _labelid (διορθώνει άλμπουμ με πολλαπλούς δίσκους)" #~ msgid "CDDB Lookup" #~ msgstr "Αναζήτηση σε CDDB" #~ msgid "Looks up album information in FreeDB. Requires CDDB.py." #~ msgstr "Εύρεση πληροφοριών άλμπουμ στο FreeDB. Χρειάζεται το CDDB.py." #~ msgid "Timeout" #~ msgstr "Χρονικό όριο" #~ msgid "Query could not be executed, connection timed out" #~ msgstr "Η αναζήτηση απέτυχε, υπέρβαση χρονικού ορίου" #~ msgid "Select an album" #~ msgstr "Επιλέξτε ένα άλμπουμ" #~ msgid "Select the album you wish to retrieve." #~ msgstr "Επιλέξτε το άλμπουμ που θέλετε να ανακτήσετε." #~ msgid "CDDB lookup failed (%s)" #~ msgstr "Η αναζήτηση στο CDDB απέτυχε (%s)" #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s και %(count)d ακόμη…" #~ msgstr[1] "%(title)s και %(count)d ακόμη…" #~ msgid "Send To…" #~ msgstr "Αποστολή Σε…" #~ msgid "Generic file-opening plugin." #~ msgstr "Γενικό πρόσθετο ανοίγματος αρχείων." #~ msgid "Playlist Export" #~ msgstr "Εξαγωγή Λίστας Αναπαραγωγής" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Χρήση στρογγυλεμένων γωνιών στις εικόνες επισκόπησης" #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "Στρογγύλεψε τις γωνίες των μικρογραφιών των εξώφυλλων άλμπουμ." #~ msgid "Re_fresh Library" #~ msgstr "_Ανανέωση Μουσικοθήκης" #~ msgid "_Remove rating" #~ msgstr "_Διαγραφή βαθμολογίας" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "Το GStreamer δεν έχει κάποιο στοιχείο για να χειριστεί την ανάγνωση " #~ "αρχείων. Ελέγξτε τις ρυθμίσεις εγκατάστασης του GStreamer." #~ msgid "Invalid audio backend" #~ msgstr "Μη έγκυρο ηχητικό σύστημα υποστήριξης" #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "" #~ "Δεν ήταν δυνατό να φορτωθεί η υποστήριξη ηχητικού συστήματος '%(backend-" #~ "name)s'." #~ msgid "Print all tags to stdout" #~ msgstr "Εκτύπωση όλων των ετικετών στην κανονική έξοδο" #~ msgid "Load tags dumped with 'dump'" #~ msgstr "Φόρτωση ετικετών από προηγούμενη εκτύπωση στην έξοδο" #~ msgid "command|filename" #~ msgstr "εντολή|όνομα αρχείου" #~ msgid "command|tag" #~ msgstr "εντολή|ετικέτα" #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Δεν βρέθηκε το 'libudev'." #, fuzzy #~ msgid "<i>Searching…</i>" #~ msgstr "<i>Αναζητείται…</i>" #~ msgid "" #~ "You can access the following objects by default:\\n '%s' (SongWrapper " #~ "objects)\\n '%s' (Song dictionaries)\\n '%s' (Filename list)\\n " #~ "'%s' (Application instance)" #~ msgstr "" #~ "Έχετε πρόσβαση σε αυτά τα αντικείμενα εξ' ορισμού:\n" #~ " '%s' (SongWrapper objects)\n" #~ " '%s' (Song dictionaries)\n" #~ " '%s' (Filename list)\n" #~ " '%s' (Application instance)" #~ msgid "" #~ "\n" #~ "\n" #~ "<i>Fingerprints:</i> %d/%d" #~ msgstr "" #~ "\n" #~ "\n" #~ "\n" #~ "<i>Αποτυπώματα:</i> %d/%d" #~ msgid "heading|Search" #~ msgstr "Αναζήτηση" #~ msgid "%d of %d" #~ msgstr "%d από %d" #~ msgid "Usage: %s %s\n" #~ msgstr "Χρήση: %s %s\n" #~ msgid "_Download..." #~ msgstr "_Κατέβασμα" #~ msgid "_New Station..." #~ msgstr "_Νέος Σταθμός..." #~ msgid "_New Playlist..." #~ msgstr "_Νέα Λίστα Αναπαραγωγής..." #~ msgid "Use LastFM database to fetch covers" #~ msgstr "Χρήση της βάσης δεδομένων του LastFM για την λήψη εξώφυλλων" #~ msgid "_Convert Encoding..." #~ msgstr "_Μετατροπή Κωδικοποίησης..." #~ msgid "A simple play order plugin that plays songs in reverse order." #~ msgstr "" #~ "Ένα απλό πρόσθετο σειράς αναπαραγωγής που παίζει τα τραγούδια σε " #~ "αντίστροφη σειρά." #~ msgid "" #~ "\n" #~ "<small>from <i>%s</i></small>" #~ msgstr "" #~ "\n" #~ "<small>από <i>%s</i></small>" #~ msgid "_Edit Bookmarks..." #~ msgstr "_Επεξεργασία Σελιδοδεικτών..." #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s και %(count)d ακόμη..." #~ msgstr[1] "%(title)s και %(count)d ακόμη..." #~ msgid "_New Folder..." #~ msgstr "_Νέος Φάκελος..." #~ msgid "_Edit Display..." #~ msgstr "_Επεξεργασία Εμφάνισης..." #~ msgid "Output Log" #~ msgstr "Καταγραφή Εξόδου" #~ msgid "_Add a Location..." #~ msgstr "Προσθήκη _Τοποθεσίας" #~ msgid "_Output Log" #~ msgstr "_Καταγραφή Εξόδου" #~ msgid "Warnings" #~ msgstr "Προειδοποιήσεις" #~ msgid "Errors" #~ msgstr "Σφάλματα" #~ msgid "No log available." #~ msgstr "Δεν υπάρχει διαθέσιμη καταγραφή" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Αντικατάσταση του <b>%s</b>;" #~ msgid "Output Error" #~ msgstr "Σφάλμα Εξόδου" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Η διασωλήνωση εξόδου του GStreamer δεν μπόρεσε να αρχικοποιηθεί. Ίσως να " #~ "μην είναι έγκυρη ή η συσκευή να είναι απασχολημένη. Ελέγξτε τις " #~ "προτιμήσεις." #~ msgid "Quod Libet is already running." #~ msgstr "Ο Quod Libet εκτελείται ήδη." #~ msgid "No song is currently playing." #~ msgstr "Κανένα τραγούδι δεν αναπαράγεται αυτή τη στιγμή." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Αδυναμία εγγραφής στο %s. Αφαίρεσή του." #~ msgid "_Add to Playlist" #~ msgstr "Προσθήκη στην _Λίστα Αναπαραγωγής" #~ msgid "%(song_count)d songs" #~ msgstr "%(song_count)d τραγούδια" #~ msgid "Are you sure?" #~ msgstr "Είστε σίγουρη/ος;" #~ msgid "Invalid command %r received." #~ msgstr "Ελήφθη μη έγκυρη εντολή %r." #~ msgid "Unknown browser %r." #~ msgstr "Άγνωστος περιηγητής %r." #~ msgid "Custom _Sort..." #~ msgstr "Προσαρμοσμένη _Ταξινόμηση..." #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "Σίγουρα θέλετε να τρέξετε το πρόσθετο \"%s\" σε %d τραγούδι;" #~ msgstr[1] "Σίγουρα θέλετε να τρέξετε το πρόσθετο \"%s\" σε %d τραγούδια;" #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "Σίγουρα θέλετε να τρέξετε το πρόσθετο \"%s\" σε %d άλμπουμ;" #~ msgstr[1] "Σίγουρα θέλετε να τρέξετε το πρόσθετο \"%s\" σε %d άλμπουμ;" #~ msgid "Track Headers" #~ msgstr "Κεφαλίδες Κομματιών" #~ msgid "People Headers" #~ msgstr "Κεφαλίδες Συντελεστών" #~ msgid "Album Headers" #~ msgstr "Κεφαλίδες Άλμπουμ" #~ msgid "Date Headers" #~ msgstr "Κεφαλίδες Ημερομηνιών" #~ msgid "File Headers" #~ msgstr "Κεφαλίδες Αρχείων" #~ msgid "Production Headers" #~ msgstr "Κεφαλίδες Παραγωγής" #~ msgid "Tag:" #~ msgstr "Ετικέτα:" #~ msgid "Descending" #~ msgstr "Φθήνουσα" #~ msgid "Too Many Errors" #~ msgstr "Υπερβολικά Πολλά Σφάλματα" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Σταματά η αναπαραγωγή διότι υπήρξαν %d συνεχόμενα σφάλματα." #~ msgid "album artist (sort)" #~ msgstr "καλλιτέχνης άλμπουμ (ταξινόμηση)" #~ msgid "artist (sort)" #~ msgstr "καλλιτέχνης (ταξινόμηση)" #~ msgid "album (sort)" #~ msgstr "άλμπουμ (ταξινόμηση)" #~ msgid "performer (sort)" #~ msgstr "εκτελεστής (ταξινόμηση)" #~ msgid "performers (sort)" #~ msgstr "εκτελεστές (ταξινόμηση)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz Ταυτότητα καλλιτέχνη άλμπουμ" #~ msgid "errors" #~ msgstr "σφάλματα" #~ msgid "" #~ "Extract embedded images to <destination>/<filename>-<index>.(jpeg|png|..)" #~ msgstr "" #~ "Εξαγωγή των ενσωματωμένων εικόνων στο αρχείο <προορισμός>/<όνομα>-" #~ "<δείκτης>.(jpeg|png|..)" #~ msgid "Refresh Library" #~ msgstr "Ανανέωση της Μουσικοθήκης" #~ msgid "_Cause an Error" #~ msgstr "Πρόκληση _Λάθους" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Αποτυχία ανάγνωσης εξώφυλλου \"%s\"" #~ msgid "Permanently delete this file?" #~ msgstr "Μόνιμη διαγραφή αυτού του αρχείου;" #~ msgid "Permanently delete these files?" #~ msgstr "Μόνιμη διαγραφή αυτών των αρχείων;" #~ msgid "Version:" #~ msgstr "Έκδοση:" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "Το %s δεν μπόρεσε να προστεθεί στην μουσικοθήκη σας.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Σφάλμα κατά την εκτέλεση της εντολής %r, προκλήθηκε από: %r." #~ msgid "Do you wish to continue?" #~ msgstr "Θέλεις να συνεχίσεις;" #~ msgid "Confirm duplicates removal" #~ msgstr "Επιβεβαίωση αφαίρεσης διπλότυπων" #~ msgid "No eject command found." #~ msgstr "Δεν βρέθηκε εντολή εξαγωγής." #~ msgid "Unable to start web browser" #~ msgstr "Αδυναμία εκκίνησης περιηγητή διαδικτύου" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Δεν βρέθηκε περιηγητής διαδικτύου. Παρακαλώ καθορίστε την μεταβλητή " #~ "%BROWSER, ή βεβαιωθείτε πως το /usr/bin/sensible-browser υπάρχει." #~ msgid "" #~ "Cannot save library contents to %s (it's a directory). Please remove it " #~ "and try again." #~ msgstr "" #~ "Δεν μπορώ να αποθηκεύσω τα περιεχόμενα της μουσικοθήκης στο %s (είναι " #~ "κατάλογος). Παρακαλώ διαγράψτε το και προσπαθήστε ξανά." #~ msgid "Library Error" #~ msgstr "Σφάλμα Μουσικοθήκης" #~ msgid "_Output device:" #~ msgstr "_Συσκευή Εξόδου:" #~ msgid "translator-credits" #~ msgstr "Δημήτρης Παπαγεωργίου <dipap@gmx.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Άλλες στήλες για εμφάνιση, διαχωρισμένες με κενά" #~ msgid "_Edit and Continue" #~ msgstr "Επεξεργασία και Συνέχεια" #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "Πρόκειται να αλλάξεις τη βαθμολογία %d τραγουδιού." #~ msgstr[1] "Πρόκειται να αλλάξεις τη βαθμολογία %d τραγουδιών." #~ msgid "Confirm rating" #~ msgstr "Επιβεβαίωση βαθμολογίας" #~ msgid "Search your library" #~ msgstr "Αναζήτηση στην μουσικοθήκη σας" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Πνευματική ιδιοκτησία {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "Το %r δεν περιέχει περιηγητές" #~ msgid "%r doesn't contain any devices." #~ msgstr "Το %r δεν περιέχει συσκευές." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Δεν βρέθηκε το media-player-info." #~ msgid "Unkown" #~ msgstr "Άγνωστο" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/en_CA.po�������������������������������������������������������������������������0000644�0001750�0001750�00000670472�14436352625�014160� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# English/Canada translation of Quod Libet. # Copyright (C) 2004 Joe Wreschnig # This file is distributed under the same license as the Quod Libet package. # Joe Wreschnig <piman@sacredchao.net>, 2004 # # NB: I am not actually Canadian, but I need a translation to test my i18n # support, and I know Canadian better than, say, Kurdish. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.18\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2013-07-20 22:32+0100\n" "Last-Translator: Joe Wreschnig <piman@sacredchao.net>\n" "Language-Team: Joe Wreschnig <piman@sacredchao.net>\n" "Language: en_CA\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 1.5.4\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Title" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "people" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Date" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Date Headers" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "original artist" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Rating" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Edit Display" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Sort by date" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Preferences" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Album List" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Album List" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "All Albums" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Show album _covers" msgstr[1] "Show album _covers" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Songs not in an album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d track" msgstr[1] "%d tracks" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disc" msgstr[1] "%d discs" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "All Albums" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Album List Preferences" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Show album _covers" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[options]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Album Display" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Library Browser" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d song" msgstr[1] "%d songs" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Invalid pattern" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Unknown" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Split into _Multiple Values" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Custom" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "_Remove Station" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Album List Preferences" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Total size:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Total size:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Paned Browser Preferences" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Show album _covers" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "All Albums" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "No new stations" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "File System" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_File System" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Unable to copy songs" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "The files selected cannot be copied to other song lists or the queue." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Add to Library" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet Radio" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "New Station" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Download Files" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "New Station" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Enter the location of an Internet radio station:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "rating" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_New Station" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internet Radio" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "New Station" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "New Station" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "_New Station" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "No stations found" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "No Internet radio stations were found at %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "All stations listed are already in your library." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "_Add to Playlist" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "_Remove from Playlist" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" msgstr[1] "%(count)d stations" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paned Browser" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Paned Browser" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Select _All" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Unknown" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "All" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Visible Columns" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Paned Browser Preferences" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Playlists" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Playlists" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Remove from Playlist" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Import" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Unable to import playlist" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet can only import playlists in the M3U and PLS formats." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Delete Files" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Rename" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Unable to rename playlist" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Import Playlist" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Import" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_New Playlist" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "New Playlist" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Paned Browser Preferences" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Playlists" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Track" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "New Playlist" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Enter a name for the new folder:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importing playlist.\n" "\n" "%d/%d songs added." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "New Feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Enter the location of an audio feed:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Add a File..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Re_fresh Library" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Watch this folder for new songs" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Unable to add feed" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> could not be added. The server may be down, or the location may " "not be an audio feed." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limit Results" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Split into multiple _values" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Track List" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Track List" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Paned Browser" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Paned Browser" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Search" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "tracks" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "location" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> is not connected." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet is not running." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "a music library and player" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[options]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Print the playing song and exit" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Begin playing immediately" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Jump to next song" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Jump to previous song" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Start playback" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pause playback" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Toggle play/pause mode" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Start playback" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Turn up volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Turn down volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Print player status" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Hide main window" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Show main window" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Toggle main window visibility" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Focus the running player" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Remove active browser filters" #: quodlibet/cli.py:113 #, fuzzy msgid "Refresh and rescan library" msgstr "Re_fresh Library" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Disable Browser" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Print the current playlist" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Print the contents of the queue" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Print the contents of the queue" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet is not running." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Exit Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Seek within the playing song" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Toggle play/pause mode" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Toggle play/pause mode" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Turn repeat off, on, or toggle it" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Toggle play/pause mode" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Set the volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Search your audio library" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "query" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Play a file" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "filename" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Seek within the playing song" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Set the current browser" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Rate the playing song" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Open a new browser" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Show or hide the queue" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filter on a random value" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filter on a tag value" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=value" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Enqueue a file or query" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "filename" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Unqueue a file or query" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "location" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "pattern" #: quodlibet/cli.py:216 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Invalid argument for '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Try %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Show _Errors" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "description" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "an audio tag editor" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "directory" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Audio tag editor" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz track ID" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz track ID" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Invalid Encoding]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Title" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Audio tag editor" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Title-case tags" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Paned Browser Preferences" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 #, fuzzy msgid "Animated On-Screen Display" msgstr "_On-Screen Display" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Total size:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Edit Display" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Weighted" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Edit Display" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Preview" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Information" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Supported formats:" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filter on _Genre" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "directory" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Audio Feeds" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Could not play %s." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_New Station" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Save ratings and play counts" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "recording date" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Errors" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_New Station" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Preferences" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Import Playlist" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Import" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Import" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Discard tag changes?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Discard tag changes?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "_Pause" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Invalid Pattern" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Invalid Pattern" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 #, fuzzy msgid "Party" msgstr "_Part" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "1 second" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Set Rating" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Select" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Preview" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Custom" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Unable to delete songs" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "pattern" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Music Player" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Model:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Internet Radio" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Rating" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Set Rating" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "location" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Hide main window" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Set Rating" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "Invalid Pattern" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "Invalid Pattern" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d song" #: quodlibet/ext/events/mqtt.py:158 #, fuzzy msgid "Plain text for when there is no current song" msgstr "Pause/resume the current song" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Information" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "Invalid Pattern" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Could not play %s." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "location" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz album type" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Name:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Title" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 #, fuzzy msgid "Show notifications" msgstr "No new stations" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 #, fuzzy msgid "Song Notifications" msgstr "No new stations" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 #, fuzzy msgid "Next" msgstr "_Next" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "No new stations" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Device:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Others: " #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Filename Pattern:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Random Al_bum" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "albums" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Weighted" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Random Al_bum" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Bookmarks" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Bookmark Name" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Bookmark Name" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[options]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "[Invalid Encoding]" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "recording date" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Delete Files" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Deleting %d/%d." #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "No stations found" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "Invalid Pattern" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Edit saved values..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Artist" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Preview" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Music Player" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Import Playlist" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organization" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Choose New Stations" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Path is not absolute" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "The pattern\n" "\t<b>%s</b>\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "No songs are selected." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "No songs are selected." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Unable to save song" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, fuzzy, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "Tag by Filename" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Unable to open files" msgstr[1] "Unable to open files" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Lyrics" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Play _song" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 #, fuzzy msgid "Plain text for status when there is no current song" msgstr "Pause/resume the current song" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d song" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "Invalid Pattern" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "_Rating" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Not playing" #: quodlibet/ext/events/trayicon/__init__.py:52 #, fuzzy msgid "Tray Icon" msgstr "Tray Icon Preferences" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Player" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "_Pause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "Pre_vious" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 #, fuzzy msgid "_Next" msgstr "_Next" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Shuffle" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repeat" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Stop after this song" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Open a new browser" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Edit _Tags" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Information" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Playlists" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Scroll wheel adjusts volume\n" "Shift and scroll wheel changes song" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Scroll _Wheel" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Tooltip Display" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Lyrics" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "No lyrics found for this song." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Unable to save song" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Errors" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "No new stations" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Files" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Preview" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filter on _Artist" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 #, fuzzy msgid "Default" msgstr "Set Rating" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Custom" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Custom" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filter on _Genre" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filter on _Artist" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio Feeds" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Enter the location of an audio feed:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Import Playlist" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Import" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "No stations found" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Filename Pattern:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Unable to import playlist" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Filename Pattern:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Import Playlist" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Remove selected tag" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "New Playlist" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "last played" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "last played" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "_Queue" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "_Queue" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "_Queue" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Never" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Never" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "grouping" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Unable to copy songs" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filter on _Genre" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Invalid tags" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Saved Values" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Saved Values" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Could not play %s." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Rename" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Library" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Hide main window" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Filename" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Unable to save song" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Album List" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Size" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Search:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Search" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Album List" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Edit Bookmarks..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Edit Bookmarks..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Bookmarks" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz album type" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Filename" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Disc" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Track" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Title" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Artist" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz album type" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "query" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Search" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "No plugins found." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "location" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Album List" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Album List" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "No plugins found." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Preview" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "tag" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Rename" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "tag" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Never" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Invalid value" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Custom" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Unable to copy songs" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Disable Browser" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "_Remove Station" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Edit Display" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 #, fuzzy msgid "Skip Count" msgstr "skip count" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Split into _Multiple Values" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "Remove selected tag" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filter on a tag value" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer was unable to load the selected song." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filter on _Genre" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "_Queue" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Write" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz track ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "directory" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Album Headers" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_New Station" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "No plugins found." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "%(current)s/%(total)s" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Import Playlist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Import Playlist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "No time information" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Album List" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Import Playlist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Import" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filter on _Genre" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Disc" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Track" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Artist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albums" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Continue" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Could not play %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Could not play %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Filename" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "tracks" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Errors" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Rename" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Import Playlist" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Ejecting <b>%s</b> failed." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Re_fresh Library" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Re_fresh Library" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Track" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Edit Tags" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Edit Tags" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "All Albums" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Preview" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Tag" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Unable to delete songs" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Search" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "Invalid Pattern" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Edit saved values..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Colour _search terms" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Edit Tags" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Search Bar" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Library" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Checking mount points" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Scanning library" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Scanning %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Scanning library" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Remove active browser filters" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "a music library and player" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Show _programmatic tags" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "Description" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Value" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Audio tag editor" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "No songs are selected." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 #, fuzzy msgid "Remove tags" msgstr "_Remove Station" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 #, fuzzy msgid "Remove all tags" msgstr "Remove selected tag" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Filter on a tag value" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Filter on a tag value" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "No time information" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Unable to rename file" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "Remove selected tag" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "File" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Display brief usage information" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> is not a valid location." #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "Unknown" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "In Order" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_In Order" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Random" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Random" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "last played" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Repeat" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Repeat" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "One Song" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "One Song" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "1 second" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "No audio device found" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "Unable to create folder" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Name:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Plugins" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Beginning" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Time" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Bookmark Name" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Bookmarks" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filters" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Never Played" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "All songs" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Random _Genre" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Random _Artist" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Random Al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Name:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Value:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Saved Values" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Edit saved values..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "_Track Headers" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "_Album Headers" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "_Replay Gain volume adjustment" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Unknown" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Add a File..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Edit Display..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filter on a tag value" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Audio tag editor" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Files" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Delete Files" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Move to Trash" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "%(current)s/%(total)s" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Unable to save iPod database" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Ejecting <b>%s</b> failed." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "%(current)s/%(total)s" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Unable to delete file" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Deleting <b>%s</b> failed." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Browsers" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Download Files" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "missing from %d song" msgstr[1] "missing from %d songs" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "different across %d song" msgstr[1] "different across %d songs" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Split into _Multiple Values" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Split Disc out of _Album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Split _Version out of Title" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Split Arranger out of Ar_tist" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Split _Performer out of Artist" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Split _Performer out of Artist" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Split _Version out of Title" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Add a Tag" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Show _programmatic tags" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Show _programmatic tags" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Never" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Continue" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Edit Tags" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Copy _album covers" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Unable to add tag" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Unable to add songs" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Unable to add <b>%s</b>\n" "\n" "The files currently selected do not support multiple values." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Invalid tag" msgstr[1] "Invalid tag" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr[1] "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Invalid value" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tag may not be accurate" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> changed while the program was running. Saving without refreshing " "your library may overwrite other changes to the song.\n" "\n" "Save this song anyway?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Unable to save song" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_More options..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_About" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Plugins" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s and %(count)d more" msgstr[1] "%(title)s and %(count)d more" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso Preferences" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Folders" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "New Folder" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Select All Subfolders" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "New Folder" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Enter a name for the new folder:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Unable to create folder" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Unable to delete folder" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Songs" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "by %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disc %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Track %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Edit Display" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "No songs are selected." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "No Songs" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Information" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Lyrics" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produced by %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artist" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artists" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "performers" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Never" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d time" msgstr[1] "%d times" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "added" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "last played" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "plays" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "skips" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "rating" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "length" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Information" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[Invalid Encoding]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "file size" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modified" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selected" msgstr[1] "%d selected" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Track unavailable" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d song with no album" msgstr[1] "%d songs with no album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Selected Discography" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d song with no artist" msgstr[1] "%d songs with no artist" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albums" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Total length:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Total size:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Files" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "No lyrics found for this song." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Discard tag changes?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Never" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "File exists" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Rename Files" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet is running" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Toggle play/pause mode" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Toggle play/pause mode" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "Play _Order" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Tag Editing" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Rename" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "query" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Total size:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plugin Errors" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "Disable Browser" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "No plugins found." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Plugins" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Show _Errors" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disc" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Track" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "grouping" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artist" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Filename" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Length" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Jump to playing song automatically" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "When the playing song changes, scroll to it in the song list" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Others: " #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Edit Display..." #: quodlibet/qltk/prefs.py:107 #, fuzzy msgid "Add or remove additional column headers" msgstr "Set and save column headers" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Visible Columns" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Title includes _version" #: quodlibet/qltk/prefs.py:139 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Album includes _part" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Title includes _version" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Filename includes _folder" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Preferences" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Visible Columns" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Song List" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Visible Columns" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Global filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Search" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Browsers" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "When the playing song changes, scroll to it in the song list" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 #, fuzzy msgid "Ratings" msgstr "Rating" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Album List" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Pause playback" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Volume Gain (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Volume Gain (dB):" #: quodlibet/qltk/prefs.py:428 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "_Replay Gain volume adjustment" #: quodlibet/qltk/prefs.py:445 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "_Replay Gain volume adjustment" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 #, fuzzy msgid "_Default rating:" msgstr "Set Rating" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Rating" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Ratings and play counts will be set for this email address" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Discard tag changes?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Split _on:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Split _on:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Edit Tags" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tag Editing" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_New Station" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Search Library" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Check for changes in your library" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Re_load Library" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Reload all songs in your library (this can take a long time)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "No Songs" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "Re_fresh Library" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Scan _Directories" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, fuzzy, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s and %(count)d more" msgstr[1] "%(title)s and %(count)d more" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Properties" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Queue" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Clear Errors" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Remove all songs from the queue" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Model:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d song (%(time)s)" msgstr[1] "%(count)d songs (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Browse Library" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Toggle main window visibility" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Pause playback" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Select Directories" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Unable to add songs" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> uses an unsupported protocol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Jump to Playing Song" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "File" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Songs" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_View" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Browsers" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Control" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Help" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Add a Folder..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Add a File..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Add a Location" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Edit Bookmarks..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Stop after this song" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Search" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Add a Location" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Enter the location of an audio file:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Unable to add location" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> is not a valid location." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Add Music" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Add a Folder..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Music Player" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Add a File..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Queue" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "_Remove Station" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Rating" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Replace spaces with _underscores" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Strip _Windows-incompatible characters" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Strip _diacritical marks" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Strip non-_ASCII characters" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Rename Files" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Preview" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Filename" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "album artist" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Remove unused covers and directories" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Album List" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "New Name" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Unable to rename file" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Renaming <b>%s</b> to <b>%s</b> failed. Possibly the target file already " "exists, or you do not have permission to make the new file or remove the old " "one." #: quodlibet/qltk/renamefiles.py:346 #, fuzzy msgid "Ignore _All Errors" msgstr "Show _Errors" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continue" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Path is not absolute" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "The pattern\n" "\t<b>%s</b>\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Songs placed in these folders (separated by ':') will be added to your " "library" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "W: removing orphaned iPod track" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Library" msgstr[1] "Library" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Remove Station" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Select Directories" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Select Directories" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Saved Values" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Edit saved values..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "search-string" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limit:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Weighted" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "query" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Display remaining time" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Lyrics" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Focus the running player" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Seek within the playing song" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Unable to delete songs" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Unable to delete songs" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filter on %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "_Album Headers" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Track Headers" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Album Headers" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_People Headers" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Date Headers" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_File Headers" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Production Headers" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Customize Headers..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Remove from Library" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Remove from Library" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Remove from Library" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Colour _search terms" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Add to _Queue" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Remove from Library" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Unable to delete file" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Download" msgstr[1] "_Download" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Search Bar" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Download File" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Album List" msgstr[1] "Album List" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Download File" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Replace _underscores with spaces" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Title-case tags" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Split into multiple _values" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tags From Path" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tags replace existing ones" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tags are added to existing ones" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Edit Display" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Track Numbers" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Start fro_m:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Total tracks:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "_Pause" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "Pre_vious" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "and %d more..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Saving the songs you changed." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s/%(total)s" #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Checking mount points" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "location" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Import Playlist" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "A playlist named %s already exists." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Show album _covers" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "File System" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Total size:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Display brief usage information" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Display version and copyright" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "No time information" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[options]" #: quodlibet/util/__init__.py:167 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Option '%s' not recognized." #: quodlibet/util/__init__.py:170 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Option '%s' requires an argument." #: quodlibet/util/__init__.py:173 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' is not a unique prefix." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d second" msgstr[1] "%d seconds" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "No time information" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d second" msgstr[1] "%d seconds" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hour" msgstr[1] "%d hours" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d day" msgstr[1] "%d days" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d year" msgstr[1] "%d years" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "check|titlecase?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain gains must be entered in 'x.yy dB' format." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain peaks must be entered in 'x.yy' format." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDs must be in UUID format." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Ejecting <b>%s</b> failed." msgstr[1] "Ejecting <b>%s</b> failed." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Unable to edit song" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Invalid Encoding]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arranger" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangers" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "arranger" #: quodlibet/util/tags.py:86 msgid "author" msgstr "author" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "authors" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "tag" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "composer" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "composers" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "composer" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "conductor" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "conductors" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "conductor" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contact" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "date" #: quodlibet/util/tags.py:94 msgid "description" msgstr "description" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "genre" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "performer" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "performer" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grouping" #: quodlibet/util/tags.py:98 msgid "language" msgstr "language" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licence" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "lyricist" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "lyricists" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "lyricist" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organization" #: quodlibet/util/tags.py:104 msgid "title" msgstr "title" #: quodlibet/util/tags.py:105 msgid "version" msgstr "version" #: quodlibet/util/tags.py:106 msgid "website" msgstr "website" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "album artist" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disc" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "track" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "label ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "original release date" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "original album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "original artist" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "recording date" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "release country" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz album type" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Preferences" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "discs" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "tracks" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "last started" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "full name" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "mount point" #: quodlibet/util/tags.py:166 msgid "people" msgstr "people" #: quodlibet/util/tags.py:168 msgid "year" msgstr "year" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "original release date" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "Bookmarks" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "format" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Playlists" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Audio tag editor" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Edit tags in your audio files" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Exit Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Music Player" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Listen to, browse, or edit your audio collection" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Import Playlist" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Unable to add song" #~ msgid "Invalid tags" #~ msgstr "Invalid tags" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "1 second" #, fuzzy #~ msgid "Startup" #~ msgstr "_Import" #~ msgid "Audio Feeds" #~ msgstr "Audio Feeds" #~ msgid "_Audio Feeds" #~ msgstr "_Audio Feeds" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Searching for lyrics..." #, fuzzy #~ msgid "<artist>" #~ msgstr "artist" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "title" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Import Playlist" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Import Playlist" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Information" #~ msgid "Unsupported file type" #~ msgstr "Unsupported file type" #~ msgid "Unable to add station" #~ msgstr "Unable to add station" #~ msgid "Device Properties" #~ msgstr "Device Properties" #~ msgid "Device:" #~ msgstr "Device:" #~ msgid "Not mounted" #~ msgstr "Not mounted" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Mount Point:" #~ msgid "Media Devices" #~ msgstr "Media Devices" #~ msgid "_Media Devices" #~ msgstr "_Media Devices" #~ msgid "_Eject" #~ msgstr "_Eject" #, fuzzy #~ msgid "_Properties" #~ msgstr "Properties" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> used, <b>%s</b> available" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Copying <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "Unable to copy song" #~ msgid "There is not enough free space for this song." #~ msgstr "There is not enough free space for this song." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> could not be copied." #~ msgid "Unable to delete songs" #~ msgstr "Unable to delete songs" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Deleting <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> could not be deleted." #~ msgid "Unable to delete song" #~ msgstr "Unable to delete song" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Ejecting <b>%s</b> failed." #~ msgid "Unable to eject device" #~ msgstr "Unable to eject device" #~ msgid "Search Library" #~ msgstr "Search Library" #~ msgid "_Search Library" #~ msgstr "_Search Library" #~ msgid "Rate the playing song" #~ msgstr "Rate the playing song" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Show or hide the main song list" #~ msgid "Unknown Device" #~ msgstr "Unknown Device" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: '%s' is not a unique prefix." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Invalid tag name" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Filename Pattern:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Clear Errors" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Lyrics" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Clear search" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Lyrics" #, fuzzy #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "View and edit tags in the playing song" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Lyrics" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "skip count" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Browsers" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Unable to create folder" #~ msgid "Supported formats: %s" #~ msgstr "Supported formats: %s" #~ msgid "Audio device: %s" #~ msgstr "Audio device: %s" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgid "Size" #~ msgstr "Size" #~ msgid "_Download" #~ msgstr "_Download" #~ msgid "_Copy to Device" #~ msgstr "_Copy to Device" #, fuzzy #~ msgid "browsers" #~ msgstr "Browsers" #~ msgid "Unable to download lyrics." #~ msgstr "Unable to download lyrics." #~ msgid "Set or toggle the playback order" #~ msgstr "Set or toggle the playback order" #~ msgid "Uninitialized iPod" #~ msgstr "Uninitialized iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Do you want to create an empty database on this iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volume Gain (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combine tags with _multiple values" #~ msgid "Capacity:" #~ msgstr "Capacity:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Unable to save iPod database" #~ msgid "Unable to save iPod database" #~ msgstr "Unable to save iPod database" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "track peak" #~ msgid "Shuffle" #~ msgstr "Shuffle" #~ msgid "Weighted" #~ msgstr "Weighted" #~ msgid "_Weighted" #~ msgstr "_Weighted" #~ msgid "_One Song" #~ msgstr "_One Song" #~ msgid "Restart the playlist when finished" #~ msgstr "Restart the playlist when finished" #~ msgid "Disable Browser" #~ msgstr "Disable Browser" #~ msgid "_Disable Browser" #~ msgstr "_Disable Browser" #, fuzzy #~ msgid "Force Write" #~ msgstr "Write" #~ msgid "Filter on _Genre" #~ msgstr "Filter on _Genre" #~ msgid "Filter on _Artist" #~ msgstr "Filter on _Artist" #~ msgid "Filter on Al_bum" #~ msgstr "Filter on Al_bum" #~ msgid "_Music" #~ msgstr "_Music" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Bookmarks" #~ msgid "Song _List" #~ msgstr "Song _List" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Stop after this song" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "and %d more..." #~ msgstr[1] "and %d more..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Split Disc out of _Album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Time" #, fuzzy #~ msgid "Select an album" #~ msgstr "Select _All" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s and %(count)d more" #~ msgstr[1] "%(title)s and %(count)d more" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Playlists" #~ msgid "Re_fresh Library" #~ msgstr "Re_fresh Library" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Remove Station" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Invalid tag name" #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "filename" #~ msgid "command|tag" #~ msgstr "tag" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "Could not play %s." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Search" #~ msgid "%d of %d" #~ msgstr "%d of %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Usage: %s %s" #~ msgid "_Download..." #~ msgstr "_Download..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_New Station" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Overwrite <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet is already running." #~ msgid "No song is currently playing." #~ msgstr "No song is currently playing." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Unable to write to %s. Removing it." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Edit Bookmarks..." #~ msgid "_New Folder..." #~ msgstr "_New Folder..." #~ msgid "_Add to Playlist" #~ msgstr "_Add to Playlist" #~ msgid "_Edit Display..." #~ msgstr "_Edit Display..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d station" #~ msgid "_Order:" #~ msgstr "_Order:" #~ msgid "_Add a Location..." #~ msgstr "_Add a Location..." #, fuzzy #~ msgid "Unknown browser %r." #~ msgstr "Opening web browser: %s" #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Customize Headers..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Track Headers" #, fuzzy #~ msgid "People Headers" #~ msgstr "_People Headers" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Album Headers" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Date Headers" #, fuzzy #~ msgid "File Headers" #~ msgstr "_File Headers" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Production Headers" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tag:" #, fuzzy #~ msgid "Warnings" #~ msgstr "Rating" #, fuzzy #~ msgid "No log available." #~ msgstr "No information available" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "album artist" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artists" #, fuzzy #~ msgid "album (sort)" #~ msgstr "album artist" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "performers" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "performers" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artist ID" #~ msgid "errors" #~ msgstr "errors" #~ msgid "Permanently delete this file?" #~ msgstr "Permanently delete this file?" #~ msgid "Permanently delete these files?" #~ msgstr "Permanently delete these files?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s and %(count)d more..." #~ msgstr[1] "%(title)s and %(count)d more..." #, fuzzy #~ msgid "Version:" #~ msgstr "_Version" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "_Clear Errors" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "No eject command found." #~ msgid "Unable to start web browser" #~ msgstr "Unable to start web browser" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #, fuzzy #~ msgid "Library Error" #~ msgstr "Library Browser" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Copy to Device" #~ msgid "translator-credits" #~ msgstr "translator-credits" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Other columns to display, separated by spaces" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Continue" #~ msgid "Search your library" #~ msgstr "Search your library" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Total size:" #, fuzzy #~ msgid "%s: Could not import ctypes." #~ msgstr "Could not play %s." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet Plugins" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgid "Separators for splitting tags" #~ msgstr "Separators for splitting tags" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet Preferences" #~ msgid "Not Played To_day" #~ msgstr "Not Played To_day" #~ msgid "Not Played in a _Week" #~ msgstr "Not Played in a _Week" #~ msgid "Not Played in a _Month" #~ msgstr "Not Played in a _Month" #~ msgid "B_ottom 40" #~ msgstr "B_ottom 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Date" #~ msgid "Add" #~ msgstr "Add" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stations..." #~ msgid "Unable to save library" #~ msgstr "Unable to save library" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Unable to play song" #~ msgid "Sort by title" #~ msgstr "Sort by title" #~ msgid "Sort by artist" #~ msgstr "Sort by artist" #~ msgid "Lyrics provided by %s." #~ msgstr "Lyrics provided by %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgid "part" #~ msgstr "part" #~ msgid "Opening audio device." #~ msgstr "Opening audio device." #~ msgid "Moving %d/%d." #~ msgstr "Moving %d/%d." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d songs saved" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album ID" #~ msgid "Loaded song library." #~ msgstr "Loaded song library." #~ msgid "Unable to open audio device" #~ msgstr "Unable to open audio device" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgid "C_opy album covers" #~ msgstr "C_opy album covers" #~ msgid "Unable to retag multiple values" #~ msgstr "Unable to retag multiple values" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Changing the name of a tag with multiple values is not supported." #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s is not a QL song database." #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Per-song (\"Radio\") volume adjustment" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Per-album (\"Audiophile\") volume adjustment" #~ msgid "_Volume Normalization" #~ msgstr "_Volume Normalization" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3U playlists cannot be loaded." #~ msgid "This station is already in your library." #~ msgstr "This station is already in your library." #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "The library cannot be refreshed while Quod Libet is running." #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Loading, scanning, and saving your library." #~ msgid "Rescan your library and exit" #~ msgstr "Rescan your library and exit" #~ msgid "Old Plugins" #~ msgstr "Old Plugins" #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgid "GStreamer status %r != %r" #~ msgstr "GStreamer status %r != %r" #~ msgid "_Pane %d:" #~ msgstr "_Pane %d:" #~ msgid "Double-click a tag value to change it, right-click for other options" #~ msgstr "" #~ "Double-click a tag value to change it, right-click for other options" #~ msgid "Add a new tag" #~ msgstr "Add a new tag" #~ msgid "The first letter of each word will be capitalized" #~ msgstr "The first letter of each word will be capitalized" #~ msgid "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgstr "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgid "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgstr "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgid "Apply to these _files..." #~ msgstr "Apply to these _files..." #~ msgid "Path" #~ msgstr "Path" #~ msgid "Tray Preferences - Quod Libet" #~ msgstr "Tray Preferences - Quod Libet" #~ msgid "%(different)s, %(missing)s" #~ msgstr "%(different)s, %(missing)s" #~ msgid "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgstr "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgid "E: You have GTK+ %s and PyGTK %s." #~ msgstr "E: You have GTK+ %s and PyGTK %s." #~ msgid "E: Please upgrade GTK+/PyGTK." #~ msgstr "E: Please upgrade GTK+/PyGTK." #~ msgid "Play songs in random order" #~ msgstr "Play songs in random order" #~ msgid "S_ong" #~ msgstr "S_ong" #~ msgid "_Choose randomly" #~ msgstr "_Choose randomly" #~ msgid "Drag songs here to add them to the play queue" #~ msgstr "Drag songs here to add them to the play queue" #~ msgid "" #~ "Deleting <b>%s</b> failed. Possibly the target file does not exist, or " #~ "you do not have permission to delete it." #~ msgstr "" #~ "Deleting <b>%s</b> failed. Possibly the target file does not exist, or " #~ "you do not have permission to delete it." #~ msgid "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgstr "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgid "_New/Edit Playlist..." #~ msgstr "_New/Edit Playlist..." #~ msgid "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgstr "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgid "Turn shuffle off, on, or toggle it" #~ msgstr "Turn shuffle off, on, or toggle it" #~ msgid "Closing _minimizes to system tray" #~ msgstr "Closing _minimizes to system tray" #~ msgid "Performed by %s" #~ msgstr "Performed by %s" #~ msgid "arranged by %s" #~ msgstr "arranged by %s" #~ msgid "conducted by %s" #~ msgstr "conducted by %s" #~ msgid "composed by %s" #~ msgstr "composed by %s" #~ msgid "written by %s" #~ msgstr "written by %s" #~ msgid "Add songs to your library" #~ msgstr "Add songs to your library" #~ msgid "Visit the artist's website" #~ msgstr "Visit the artist's website" #~ msgid "Change volume" #~ msgstr "Change volume" #~ msgid "" #~ "Invalid tag <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing this tag.Invalid tags " #~ "<b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Invalid tag <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing this tag.Invalid tags " #~ "<b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgid "(shared across all %d songs)" #~ msgstr "(shared across all %d songs)" #~ msgid "(different across %d songs, missing from %d songs)" #~ msgstr "(different across %d songs, missing from %d songs)" #~ msgid "1 minute" #~ msgstr "1 minute" #~ msgid "1 hour" #~ msgstr "1 hour" #~ msgid "1 day" #~ msgstr "1 day" #~ msgid "An audio player and tag editor" #~ msgstr "An audio player and tag editor" #~ msgid "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgstr "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgid "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgstr "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgid "Initialized multimedia key support." #~ msgstr "Initialized multimedia key support." #~ msgid "1 track" #~ msgstr "1 track" #~ msgid "Adjust audio volume" #~ msgstr "Adjust audio volume" #~ msgid "Check for changes in the library made since the program was started" #~ msgstr "Check for changes in the library made since the program was started" #~ msgid "1 time" #~ msgstr "1 time" #~ msgid "Add a new tag to the file" #~ msgstr "Add a new tag to the file" #~ msgid "Invalid date format" #~ msgstr "Invalid date format" #~ msgid "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgstr "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgid "No on-screen display" #~ msgstr "No on-screen display" #~ msgid "Display OSD on the top" #~ msgstr "Display OSD on the top" #~ msgid "Display OSD on the bottom" #~ msgstr "Display OSD on the bottom" #~ msgid "Select a color for the OSD" #~ msgstr "Select a colour for the OSD" #~ msgid "Select a second color for the OSD" #~ msgstr "Select a second colour for the OSD" #~ msgid "Song _list" #~ msgstr "Song _list" #, fuzzy #~ msgid "[directory]" #~ msgstr "directory" #~ msgid "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgstr "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgid "" #~ "Quod Libet %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE." #~ msgstr "" #~ "Quod Libet %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE." #~ msgid "E: Unknown command line option: %s" #~ msgstr "E: Unknown command line option: %s" #~ msgid "%d:%02d:%02d" #~ msgstr "%d:%02d:%02d" #~ msgid "%d:%02d" #~ msgstr "%d:%02d" #~ msgid "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgstr "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgid "Quod Libet is free software licensed under the GNU GPL v2." #~ msgstr "Quod Libet is free software licensed under the GNU GPL v2." #~ msgid "Songs heard:" #~ msgstr "Songs heard:" #~ msgid "Listening" #~ msgstr "Listening" #~ msgid "%s and %d more - Properties" #~ msgstr "%s and %d more - Properties" #~ msgid "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgstr "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgid "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgid "Perfor_mer" #~ msgstr "Perfor_mer" #~ msgid "Pick a random album from your library" #~ msgstr "Pick a random album from your library" #~ msgid "Pick a random artist from your library" #~ msgstr "Pick a random artist from your library" #~ msgid "Pick a random genre from your library" #~ msgstr "Pick a random genre from your library" #~ msgid "Play next song" #~ msgstr "Play next song" #~ msgid "Pre_vious song" #~ msgstr "Pre_vious song" #~ msgid "Select a font for the OSD" #~ msgstr "Select a font for the OSD" #~ msgid "Pause _song" #~ msgstr "Pause _song" #~ msgid "xx minutes, " #~ msgstr "xx minutes, " ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/en_GB.po�������������������������������������������������������������������������0000644�0001750�0001750�00000613636�14436352625�014164� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# British English translation of Quod Libet. # Copyright (C) 2004 Joe Wreschnig # This file is distributed under the same license as the Quod Libet package. # Joe Wreschnig <piman@sacredchao.net>, 2004 # # msgid "" msgstr "" "Project-Id-Version: Quod Libet 2.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-02-06 21:53+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: English (United Kingdom) <https://hosted.weblate.org/projects/" "quodlibet/quodlibet/en_GB/>\n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Playcount Equaliser" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favourites" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Add a Location..." #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Add to Favourites" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Remove from Favourites" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "_Track Headers" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Watch this folder for new songs" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "The current backend does not support equalisation." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "" #: quodlibet/cli.py:88 msgid "[option]" msgstr "" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "" #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanise _Japanese text" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equaliser" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Controls the tone of your music with an equaliser.\n" "Click or use keys to customise levels (right-click resets the band)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "The current backend does not support equalisation." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchronises all songs from the selected saved searches with the specified " "folder." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synchronise the following saved searches:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organisation" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Choose New Stations" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "A different plugin was selected – stop preview" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Found {} songs to synchronise" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Unable to copy song" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "A different plugin was selected – stop synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, fuzzy, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "Tag by Filename" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, fuzzy, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "skipped {count} {file_str} synchronised previously" msgstr[1] "skipped {count} {file_str} synchronised previously" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "Shows synchronised lyrics from .lrc file with same name as the track." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Behaviour" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "_Add to Playlist" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Playcount Equaliser" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "ql-remove" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Loading %(source)s – %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "ql-remove" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analysing" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "_Track Headers" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "_File Headers" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain Analyser" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "1 track" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyses and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped per album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "_One Song" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "_One Song" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer plugin '%(name)s' could not be initialised" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Browsers" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Download Files" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Unable to add station" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "The current backend does not support equalisation." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag.Invalid tags <b>" "%s</b>\n" "\n" "The files currently selected do not support editing these tags." msgstr[1] "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag.Invalid tags <b>" "%s</b>\n" "\n" "The files currently selected do not support editing these tags." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Deleting <b>%s</b> failed. Possibly the target file does not exist, or you " "do not have permission to delete it." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "" #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Disable queue – the queue will be ignored when playing" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Deleting <b>%s</b> failed. Possibly the target file does not exist, or you " "do not have permission to delete it." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Remove Station" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Customise Headers…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "Download Files" msgstr[1] "Download Files" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Download Files" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Download Files" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "_Add to Playlist" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Option %r not recognised." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "" msgstr[1] "" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Deleting <b>%s</b> failed. Possibly the target file does not exist, or you " "do not have permission to delete it." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "" #: quodlibet/util/tags.py:83 msgid "album" msgstr "" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "" #: quodlibet/util/tags.py:86 msgid "author" msgstr "" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "" #: quodlibet/util/tags.py:93 msgid "date" msgstr "" #: quodlibet/util/tags.py:94 msgid "description" msgstr "" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "" #: quodlibet/util/tags.py:98 msgid "language" msgstr "" #: quodlibet/util/tags.py:99 msgid "license" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisation" #: quodlibet/util/tags.py:104 msgid "title" msgstr "" #: quodlibet/util/tags.py:105 msgid "version" msgstr "" #: quodlibet/util/tags.py:106 msgid "website" msgstr "" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "" # label ID #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "" #: quodlibet/util/tags.py:166 msgid "people" msgstr "" #: quodlibet/util/tags.py:168 msgid "year" msgstr "" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #~ msgid "Unsupported file type" #~ msgstr "Unsupported file type" #~ msgid "Device Properties" #~ msgstr "Device Properties" #~ msgid "Device:" #~ msgstr "Device:" #~ msgid "Not mounted" #~ msgstr "Not mounted" #~ msgid "Media Devices" #~ msgstr "Media Devices" #~ msgid "_Media Devices" #~ msgstr "_Media Devices" #~ msgid "_Eject" #~ msgstr "_Eject" #~ msgid "There is not enough free space for this song." #~ msgstr "There is not enough free space for this song." #~ msgid "Unable to delete songs" #~ msgstr "Unable to delete songs" #~ msgid "Unable to delete song" #~ msgstr "Unable to delete song" #~ msgid "Unable to eject device" #~ msgstr "Unable to eject device" #~ msgid "Search Library" #~ msgstr "Search Library" #~ msgid "_Search Library" #~ msgstr "_Search Library" #~ msgid "Rate the playing song" #~ msgstr "Rate the playing song" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Show or hide the main song list" #~ msgid "Unknown Device" #~ msgstr "Unknown Device" #~ msgid "%r is not a supported device." #~ msgstr "%r is not a supported device." #~ msgid "Initializing device backend." #~ msgstr "Initialising device backend." #~ msgid "Device backend initialized." #~ msgstr "Device backend initialised." #, fuzzy #~ msgid "Skip Songs" #~ msgstr "No Songs" #~ msgid "Supported formats: %s" #~ msgstr "Supported formats: %s" #~ msgid "Audio device: %s" #~ msgstr "Audio device: %s" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgid "Size" #~ msgstr "Size" #~ msgid "_Download" #~ msgstr "_Download" #~ msgid "_Copy to Device" #~ msgstr "_Copy to Device" #~ msgid "Unable to download lyrics." #~ msgstr "Unable to download lyrics." #~ msgid "Uninitialized iPod" #~ msgstr "Uninitialised iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Do you want to create an empty database on this iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volume Gain (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combine tags with _multiple values" #~ msgid "Capacity:" #~ msgstr "Capacity:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Unable to save iPod database" #~ msgstr "Unable to save iPod database" #~ msgid "Shuffle" #~ msgstr "Shuffle" #~ msgid "Weighted" #~ msgstr "Weighted" #~ msgid "_Weighted" #~ msgstr "_Weighted" #~ msgid "Restart the playlist when finished" #~ msgstr "Restart the playlist when finished" #~ msgid "Disable Browser" #~ msgstr "Disable Browser" #~ msgid "_Disable Browser" #~ msgstr "_Disable Browser" #~ msgid "Filter on _Genre" #~ msgstr "Filter on _Genre" #~ msgid "Filter on _Artist" #~ msgstr "Filter on _Artist" #~ msgid "Filter on Al_bum" #~ msgstr "Filter on Al_bum" #~ msgid "_Music" #~ msgstr "_Music" #~ msgid "Song _List" #~ msgstr "Song _List" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Stop after this song" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "and %d more..." #~ msgstr[1] "and %d more..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Split Disc out of _Album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Time" #, fuzzy #~ msgid "Select an album" #~ msgstr "Select _All" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Playlists" #~ msgid "Re_fresh Library" #~ msgstr "Re_fresh Library" #~ msgid "command|filename" #~ msgstr "filename" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Search" #~ msgid "%d of %d" #~ msgstr "%d of %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Usage: %s %s" #~ msgid "_Download..." #~ msgstr "_Download..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_New Station" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Overwrite <b>%s</b>?" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "GStreamer output pipeline could not be initialised. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet is already running." #~ msgid "No song is currently playing." #~ msgstr "No song is currently playing." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Unable to write to %s. Removing it." #~ msgid "_New Folder..." #~ msgstr "_New Folder..." #~ msgid "_Edit Display..." #~ msgstr "_Edit Display..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d station" #~ msgid "_Order:" #~ msgstr "_Order:" #, fuzzy #~ msgid "People Headers" #~ msgstr "_People Headers" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Album Headers" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Date Headers" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Production Headers" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tag:" #~ msgid "errors" #~ msgstr "errors" #~ msgid "Permanently delete this file?" #~ msgstr "Permanently delete this file?" #~ msgid "Permanently delete these files?" #~ msgstr "Permanently delete these files?" #, fuzzy #~ msgid "Version:" #~ msgstr "_Version" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "No eject command found." #~ msgid "Unable to start web browser" #~ msgstr "Unable to start web browser" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #, fuzzy #~ msgid "Library Error" #~ msgstr "Library Browser" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Copy to Device" #~ msgid "translator-credits" #~ msgstr "translator-credits" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Other columns to display, separated by spaces" #~ msgid "Search your library" #~ msgstr "Search your library" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "Quod Libet %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet Plugins" #~ msgid "Not Played To_day" #~ msgstr "Not Played To_day" #~ msgid "Not Played in a _Week" #~ msgstr "Not Played in a _Week" #~ msgid "Not Played in a _Month" #~ msgstr "Not Played in a _Month" #~ msgid "B_ottom 40" #~ msgstr "B_ottom 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgid "Separators for splitting tags" #~ msgstr "Separators for splitting tags" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #~ msgid "Add" #~ msgstr "Add" #~ msgid "_Stations..." #~ msgstr "_Stations..." #~ msgid "Unable to save library" #~ msgstr "Unable to save library" #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Unable to dump logs at all." #~ msgid "Sort by title" #~ msgstr "Sort by title" #~ msgid "Sort by artist" #~ msgstr "Sort by artist" #~ msgid "Lyrics provided by %s." #~ msgstr "Lyrics provided by %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgid "part" #~ msgstr "part" #~ msgid "Opening audio device." #~ msgstr "Opening audio device." #~ msgid "Moving %d/%d." #~ msgstr "Moving %d/%d." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d songs saved" #~ msgid "Loaded song library." #~ msgstr "Loaded song library." #~ msgid "Unable to open audio device" #~ msgstr "Unable to open audio device" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgid "C_opy album covers" #~ msgstr "C_opy album covers" #~ msgid "Unable to retag multiple values" #~ msgstr "Unable to retag multiple values" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Changing the name of a tag with multiple values is not supported." #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s is not a QL song database." #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Per-song (\"Radio\") volume adjustment" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Per-album (\"Audiophile\") volume adjustment" #~ msgid "_Volume Normalization" #~ msgstr "_Volume Normalisation" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3U playlists cannot be loaded." #~ msgid "This station is already in your library." #~ msgstr "This station is already in your library." #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "The library cannot be refreshed while Quod Libet is running." #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Loading, scanning, and saving your library." #~ msgid "Rescan your library and exit" #~ msgstr "Rescan your library and exit" #~ msgid "Old Plugins" #~ msgstr "Old Plugins" #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgid "GStreamer status %r != %r" #~ msgstr "GStreamer status %r != %r" #~ msgid "_Pane %d:" #~ msgstr "_Pane %d:" #~ msgid "Double-click a tag value to change it, right-click for other options" #~ msgstr "" #~ "Double-click a tag value to change it, right-click for other options" #~ msgid "Add a new tag" #~ msgstr "Add a new tag" #~ msgid "The first letter of each word will be capitalized" #~ msgstr "The first letter of each word will be capitalised" #~ msgid "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgstr "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgid "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgstr "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgid "Apply to these _files..." #~ msgstr "Apply to these _files..." #~ msgid "Path" #~ msgstr "Path" #~ msgid "Tray Preferences - Quod Libet" #~ msgstr "Tray Preferences - Quod Libet" #~ msgid "%(different)s, %(missing)s" #~ msgstr "%(different)s, %(missing)s" #~ msgid "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgstr "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgid "E: You have GTK+ %s and PyGTK %s." #~ msgstr "E: You have GTK+ %s and PyGTK %s." #~ msgid "E: Please upgrade GTK+/PyGTK." #~ msgstr "E: Please upgrade GTK+/PyGTK." #~ msgid "Play songs in random order" #~ msgstr "Play songs in random order" #~ msgid "S_ong" #~ msgstr "S_ong" #~ msgid "_Choose randomly" #~ msgstr "_Choose randomly" #~ msgid "Drag songs here to add them to the play queue" #~ msgstr "Drag songs here to add them to the play queue" #~ msgid "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgstr "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgid "_New/Edit Playlist..." #~ msgstr "_New/Edit Playlist..." #~ msgid "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgstr "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgid "Turn shuffle off, on, or toggle it" #~ msgstr "Turn shuffle off, on, or toggle it" #~ msgid "Closing _minimizes to system tray" #~ msgstr "Closing _minimises to system tray" #~ msgid "Performed by %s" #~ msgstr "Performed by %s" #~ msgid "arranged by %s" #~ msgstr "arranged by %s" #~ msgid "conducted by %s" #~ msgstr "conducted by %s" #~ msgid "composed by %s" #~ msgstr "composed by %s" #~ msgid "written by %s" #~ msgstr "written by %s" #~ msgid "Add songs to your library" #~ msgstr "Add songs to your library" #~ msgid "Visit the artist's website" #~ msgstr "Visit the artist's website" #~ msgid "(shared across all %d songs)" #~ msgstr "(shared across all %d songs)" #~ msgid "(different across %d songs, missing from %d songs)" #~ msgstr "(different across %d songs, missing from %d songs)" #~ msgid "1 minute" #~ msgstr "1 minute" #~ msgid "1 hour" #~ msgstr "1 hour" #~ msgid "1 day" #~ msgstr "1 day" #~ msgid "An audio player and tag editor" #~ msgstr "An audio player and tag editor" #~ msgid "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgstr "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgid "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgstr "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgid "Initialized multimedia key support." #~ msgstr "Initialised multimedia key support." #~ msgid "Adjust audio volume" #~ msgstr "Adjust audio volume" #~ msgid "Check for changes in the library made since the program was started" #~ msgstr "Check for changes in the library made since the program was started" #~ msgid "1 time" #~ msgstr "1 time" #~ msgid "Add a new tag to the file" #~ msgstr "Add a new tag to the file" #~ msgid "Invalid date format" #~ msgstr "Invalid date format" #~ msgid "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgstr "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgid "No on-screen display" #~ msgstr "No on-screen display" #~ msgid "Display OSD on the top" #~ msgstr "Display OSD on the top" #~ msgid "Display OSD on the bottom" #~ msgstr "Display OSD on the bottom" #~ msgid "Select a color for the OSD" #~ msgstr "Select a colour for the OSD" #~ msgid "Select a second color for the OSD" #~ msgstr "Select a second colour for the OSD" #~ msgid "Song _list" #~ msgstr "Song _list" #, fuzzy #~ msgid "[directory]" #~ msgstr "directory" #~ msgid "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgstr "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgid "E: Unknown command line option: %s" #~ msgstr "E: Unknown command line option: %s" #~ msgid "%d:%02d:%02d" #~ msgstr "%d:%02d:%02d" #~ msgid "%d:%02d" #~ msgstr "%d:%02d" #~ msgid "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgstr "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgid "Quod Libet is free software licensed under the GNU GPL v2." #~ msgstr "Quod Libet is free software licensed under the GNU GPL v2." #~ msgid "Songs heard:" #~ msgstr "Songs heard:" #~ msgid "Listening" #~ msgstr "Listening" #~ msgid "%s and %d more - Properties" #~ msgstr "%s and %d more - Properties" #~ msgid "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgstr "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgid "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgid "Perfor_mer" #~ msgstr "Perfor_mer" #~ msgid "Pick a random album from your library" #~ msgstr "Pick a random album from your library" #~ msgid "Pick a random artist from your library" #~ msgstr "Pick a random artist from your library" #~ msgid "Pick a random genre from your library" #~ msgstr "Pick a random genre from your library" #~ msgid "Play next song" #~ msgstr "Play next song" #~ msgid "Pre_vious song" #~ msgstr "Pre_vious song" #~ msgid "Select a font for the OSD" #~ msgstr "Select a font for the OSD" #~ msgid "Pause _song" #~ msgstr "Pause _song" #~ msgid "xx minutes, " #~ msgstr "xx minutes, " ��������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/es.po����������������������������������������������������������������������������0000644�0001750�0001750�00001006313�14436352625�013606� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Spanish translation of Quod Libet # Copyright (C) 2010 Johám-Luís Miguéns Vila # This file is distributed under the same license as the Quod Libet package. # Contacta conmigo para: # - Indicar errores, comentarios, sugerencias sobre la traducción. # - Colaborar / tomar el relevo en la misma. # Johám-Luís Miguéns Vila <galiza.ceive@gmail.com>, 2005-2010. # msgid "" msgstr "" "Project-Id-Version: QuodLibet dev\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2022-09-26 20:56+0000\n" "Last-Translator: Adolfo Jayme Barrientos <fitojb@ubuntu.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/es/>\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.14.1\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Título" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Personas" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Fecha" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "Fecha de a_dición" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "Fecha _original" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Género" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Puntuación" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Recuento de _reproducciones" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Or_denar por…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Preferencias" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista de álbumes" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Lista de á_lbumes" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Todos los álbumes" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbumes" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Recargar _cubierta de álbum" msgstr[1] "Recargar _cubiertas de álbum" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Canciones sin álbum" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d pista" msgstr[1] "%d pistas" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disco" msgstr[1] "%d discos" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Un álbum de ejemplo" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferencias de lista de álbumes" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Mostrar _cubiertas de álbumes" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "La _búsqueda insertada incluye personas" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opciones" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Vista de álbumes" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Cerrar" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navegador de fonoteca" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d canción" msgstr[1] "%d canciones" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "La pauta no es válida" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Colección de álbumes" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Colección de álbumes" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Desconocido" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Valores %s múltiples" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizada" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Añadir" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Quitar" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etiqueta" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Fusionar" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Preferencias de colección de álbumes" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "Ap_licar" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Cancelar" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Cuadrícula de cubiertas" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "Cuadrícula de _cubiertas" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Preferencias de la cuadrícula de cubiertas" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Mostrar _texto de álbum" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Mostrar elemento «Todos los álbumes»" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Modo ancho" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Ampliación de cubiertas" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Sistema de archvos" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "Sistema de _archivos" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "No se pudieron copiar las canciones" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "No se pueden copiar los archivos seleccionados en otras listas ni en la cola." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Añadir a fonoteca" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Las listas de emisoras pueden contener solo ubicaciones de emisoras, no " "otras listas de emisoras o de reproducción. No es posible cargar las " "ubicaciones siguientes:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio por Internet" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Añadir emisoras" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Descargando lista de emisoras" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Emisora nueva" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Proporcione la ubicación de una emisora de radio por Internet:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Electrónica" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip hop/rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Viejos éxitos" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonesa" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "India" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religiosa" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Éxitos" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latinoamericana" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Radio universitaria" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Debate/noticias" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambiente" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clásica" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Noticias" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Independiente" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reguetón" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Eslava" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Griega" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gótica" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "¿Quiere cargar una lista de emisoras de radio populares?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Cargar emisoras" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Radio por _Internet" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Todas las emisoras" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoritas" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Sin categoría" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Añadir emisora…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "Act_ualizar emisoras" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "No se encontró ninguna emisora" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "No se han encontrado emisoras en %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Nada que añadir" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Todas las emisoras referidas ya se encuentran en su fonoteca." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Añadir a Favoritos" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Quitar de Favoritos" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d emisora" msgstr[1] "%(count)d emisoras" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Vista en paneles" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Vista en paneles" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Seleccionar _todo" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Desconocido" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Todo" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Pequeño" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Ancho" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "En columnas" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Pauta de etiquetas con marcado opcional, p. ej., <tt>composer</tt> o\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferencias de la vista por paneles" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Disposición de columnas" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Contenido de columnas" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Misma anchura de paneles" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listas" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Listas" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Quitar de lista" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nuevo" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Importar…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "No se pudo importar la lista" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet solo puede importar listas en los formatos M3U/M3U8 y PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Eliminar" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Cambia_r nombre" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "No se pudo cambiar el nombre de la lista" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importar lista" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importar" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "Lista _nueva…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "¿Qué quiere hacer con %d canción?" msgstr[1] "¿Qué quiere hacer con estas %d canciones?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Confirmar acción sobre la lista «%s»" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "vacía" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Lista de ejemplo" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Preferencias del navegador de listas" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Visualización de listas" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "¿Confirma que quiere eliminar la lista «%s»?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Toda la información sobre la lista seleccionada será eliminada y no se podrá " "restaurar." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Pistas" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Lista nueva" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Proporcione un nombre para la lista nueva:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Crear" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importando la lista de reproducción.\n" "\n" "%(current)d/%(total)d canciones añadidas." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Suministro nuevo" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Proporcione la ubicación de un suministro de audio o pódcast:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Pódcast" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Pódcast" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "_Añadir suministro…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Act_ualizar" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Buscar episodios nuevos en el origen" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Reconstruir" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "Eliminar todos los episodios existentes y recargar desde el origen" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Eliminar este pódcast y sus episodios" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "No se pudo añadir el suministro" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "No se pudo añadir %s. Puede que el servidor esté inactivo o que la ubicación " "no apunte a un pódcast o suministro de audio." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "El motor de audio actual no admite los URL; por tanto, el navegador de " "pódcast está desactivado." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limitar resultados" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "Permitir _varias consultas" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Lista de pistas" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Lista de pistas" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Navegador de Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Buscar" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Mis pistas" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Ir a %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Conectado" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet está ahora conectado, %s." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Salir de %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Introduzca el código…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Acceder a %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Autorización de Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Introduzca el código de autenticación de Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet no se está ejecutando (añada «--run» para iniciarlo)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "un gestor y reproductor de música" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[opción]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Muestra la canción reproducida y termina" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Comenzar a reproducir de inmediato" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "No mostrar ninguna ventana al iniciar" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Saltar hasta la canción siguiente" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Ir a la canción anterior o reiniciar la actual si está próxima al comienzo" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Volver a la canción anterior" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Comenzar reproducción" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Poner reproducción en pausa" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Alternar modo de reproducción/pausa" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Detener la reproducción" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Aumentar volumen" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Disminuir volumen" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Aumentar una estrella la puntuación de la canción actual" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Disminuir una estrella la puntuación de la canción actual" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Mostrar el estado del reproductor" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Ocultar ventana principal" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Mostrar ventana principal" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Alternar visibilidad de la ventana principal" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Centrarse en el reproductor" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Eliminar los filtros de navegación activos" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Actualizar y redetectar fonoteca" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Enumerar navegadores disponibles" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Mostrar lista de reproducción actual" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Mostrar las canciones en la cola de reproducción" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Mostrar la consulta de texto activa" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Iniciar sin complementos" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Iniciar Quod Libet si no se está ejecutando" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Salir de Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Avanzar en la canción activa" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Establecer o alternar modo aleatorio" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Establecer tipo de modo aleatorio" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Activar o desactivar el modo repetición" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Establecer tipo de modo de repetición" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ajustar el volumen" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Buscar en la fonoteca" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "consulta" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Reproducir un archivo" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "nombre de archivo" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Establecer puntuación de canción actual" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Configurar el navegador actual" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Detener tras la canción actual" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Abrir un navegador nuevo" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Mostrar u ocultar la cola" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtro en un valor aleatorio" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "etiqueta" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtro en un valor de las etiquetas" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etiqueta=valor" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Poner en cola un archivo o búsqueda" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Añadir nombres de archivo separados por comas a la cola" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nombre de archivo" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" "Mostrar nombres de archivo de los resultados de la consulta en la salida " "estándar" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Quitar de la cola un archivo o consulta" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Añadir un archivo o directorio a la fonoteca" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "ubicación" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "pauta" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "El argumento no es válido para «%s»." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Pruebe «%s --help»." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Se produjo un error" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Puede ignorar este error, pero es posible que la aplicación sea inestable " "hasta que se la reinicie. Enviar un informe de error le tomará solo unos " "segundos y nos ayudaría mucho." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Enviar informe de error" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Reiniciar" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorar error" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Detalles del error:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Se enviarán determinados detalles acerca del error y de su sistema a un " "servicio de terceros (<a href='https://www.sentry.io'>www.sentry.io</a>). A " "continuación podrá revisar los datos antes de que se envíen." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(opcional) Proporcione una descripción breve de lo que ocurrió cuando se " "produjo el error:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Enviar" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Descripción breve…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Datos que se enviarán:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "un editor de etiquetas de audio" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "ruta" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Editor de metadatos de audio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Fuente de cubiertas por URL de imágenes" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Descarga cubiertas enlazadas mediante la etiqueta <tt>artwork_url</tt>. " "Funciona con los navegadores de Soundcloud y de pódcast." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Fuente de cubiertas Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Descarga cubiertas desde Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Fuente de cubiertas Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Descarga cubiertas del archivo de imágenes de Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Fuente de cubiertas MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Descarga cubiertas del archivo de imágenes de MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Convertir codificaciones" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Arregla las codificaciones de valor de etiqueta mal interpretadas en el " "editor de etiquetas." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Convertir codificación…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Conversor kana/kanji simple" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" "Transforma los kana y los kanji en romaji antes de efectuar el cambio de " "nombre." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanizar texto _japonés" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "No se pudo encontrar el «Kanji Kana Simple Inverter» (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Sustitución por expresiones regulares" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Permite efectuar cualquier reemplazo con expresiones regulares (<tt>s/de/a/</" "tt>) al etiquetar o cambiar de nombre los archivos." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Mayusculación anglicada" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Pone mayúsculas iniciales en las palabras en el editor de etiquetas." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "_Mayuscular valor" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Permitir etiquetas enteramente en MA_YÚSCULAS" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Mayusculación anglicada _humana" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Utiliza reglas inglesas comunes para la mayusculación de tipo título, como " "en «Dark Night of the Soul»" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Preferencias avanzadas" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Permite la edición de las opciones de configuración avanzadas." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Sé lo que hago" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Muestra información de la canción en pantalla cuando cambia." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Posición:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Tamaño de _cubierta:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Visualización" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "Tipo de _letra:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Izquierda" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centro" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Derecha" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Alinear texto:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Texto" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Texto:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Relleno:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Colores" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Sombras" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "C_ontorno" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Esquinas redo_ndeadas" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Demora:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efectos" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ed_itar pauta de visualización…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Previsualizar" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Información de la aplicación" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Información diversa sobre la aplicación y su entorno." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Formatos admitidos" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Directorio de configuración" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Directorio de antememoria" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Motor de audio" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Tras cada reproducción (predeterminado)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Tras cada reproducción o salto" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Cuando se reproduce o salta una canción, se comprueba el álbum al que " "pertenece. Si se han puntuado todas las canciones del álbum y por lo menos " "una carece de puntuación o recuentos de reproducción en su archivo, el " "complemento escribirá las etiquetas en los archivos de las canciones.\n" "\n" "Utilícelo para evitar actualizaciones constantes en los archivos, pero tenga " "en cuenta que, una vez que se haya actualizado un álbum, deberá utilizar el " "complemento «Actualizar etiquetas en archivos» siempre que quiera que las " "puntuaciones y las reproducciones queden registradas en los archivos." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "No se pudo escribir «%s»" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Actualizar automáticamente etiquetas en archivos" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Se activó la opción siguiente, dado que es necesaria para que funcione este " "complemento:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Guardar puntuaciones y co_ntadores" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Se actualizó la configuración" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Error en %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "Estrategia de act_ualización:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Preferencias" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Enmascaramiento automático" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Enmascara o desenmascara automáticamente las unidades cuando se desmontan o " "montan." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Puntuación automática" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Puntúa las canciones automáticamente al reproducirlas o al saltarlas. " "Utiliza el algoritmo «acelerado» de Vux, de Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" "La base de datos de Banshee que se especificó tiene un formato erróneo o no " "existe" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Falló la importación" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" "Se importaron correctamente las puntuaciones y estadísticas de %d canción" msgstr[1] "" "Se importaron correctamente las puntuaciones y estadísticas de %d canciones" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Importación desde Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Importa las puntuaciones y estadísticas de canciones desde Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "Ruta a base de _datos:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Iniciar importación" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Reloj despertador" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Le despierta con música fuerte." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Arrullo" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Disminuye gradualmente el volumen de la música y la pone en pausa." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Mensaje de estado de Discord" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Mensaje de estado de Discord" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Cambia el mensaje de estado de Discord según lo que esté escuchando en este " "momento." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "En pausa" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "1.ᵉʳ renglón de estado" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "2.º renglón de estado" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Plano" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "En directo" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Bajos y agudos al máximo" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Discoteca" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Salón grande" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Fiesta" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Suave" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Bajos al máximo" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Auriculares" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Rock suave" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Agudos al máximo" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Baile" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Tecno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "PC portátil" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Ecualizador" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Controla las frecuencias de su música por medio de un ecualizador.\n" "Pulse o use las teclas para personalizar los niveles (el botón secundario " "del ratón restablece la banda)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "El motor de audio actual no admite la ecualización." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Preselecciones predeterminadas" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Seleccionar…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Restablecer ecualizador" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Preselecciones personalizadas" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Eliminar seleccionados" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Nombre de la preselección que se guardará:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Guardar" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "en línea" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "sin conexión" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "charla" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "ausente" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "ocupado" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "invisible" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Mensaje de estado de Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" "Cambia el mensaje de estado de Gajim según lo que esté escuchando en este " "momento." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "en pausa" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Pauta:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Enumere cuentas, separadas por espacios, para cambiarles el mensaje de " "estado. Si no se especifica ninguna, se cambiará el mensaje de estado de " "todas las cuentas." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Cuentas:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Añadir «[en pausa]»" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Si se activa, se añadirá «[en pausa]» al mensaje de estado durante la pausa" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Estados en que el mensaje se cambiará" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pausar al desconectar auriculares" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pone en pausa la reproducción al desenchufar los auriculares y la reanuda si " "se vuelven a enchufar." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Inhibir salvapantallas/suspensión" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "En el escritorio GNOME, cuando se reproduce una canción, evita que el " "salvapantallas se active o que el equipo se suspenda." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Se reproduce música" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Modo:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Inhibir salvapantallas" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Inhibir suspensión" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Registro de radio por Internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Registra las últimas 10 canciones tocadas en emisoras radiales y las enumera " "en el menú contextual de la posición." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Crea un archivo User Tunes de Jabber en <tt>~/.quodlibet/jabber</tt>." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Cambiar idioma" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Cambie el idioma de la interfaz de usuario." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Predeterminado del sistema" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Se necesita reiniciar para que los cambios surtan efecto" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Servidor multimedia AV UPnP" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Exhibe todos los álbumes al servidor multimedia UPnP de Rygel a través de la " "interfaz MediaServer2 de D-Bus." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Cerciórese de que lo siguiente esté en su archivo de configuración de Rygel " "(~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Servidor MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Permite controlar Quod Libet remotamente a través de un cliente MPD. No se " "admite la gestión de transmisiones, listas y fonoteca." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Puerto:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_IP local:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "C_ontraseña:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Conexión" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Clientes puestos a prueba" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Compatibilidad MPRIS de D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Ocultar ventana principal al cerrar" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Acepta pautas de QL, como %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Publicador MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publica mensajes de estado en un tema de MQTT." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Nombre de anfitrión/IP de agente" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "«localhost» de manera predeterminada" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Puerto de agente" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "1883 de manera predeterminada" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Nombre de usuario de agente" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Contraseña de agente" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Tema" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Pauta al reproducir" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Texto de estado cuando inicia una canción." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Pauta en pausa" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Texto cuando la canción esta pausada." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Sin texto de la canción" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Texto sencillo para cuando no se reproduce nada" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Configuración de MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Texto de estado" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Se conectó con el agente en %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "No se pudo conectar con %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Error de conexión" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "Sincronización con MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Sincroniza la puntuación de una canción con MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Nombre de usuario:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Contraseña:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Cuenta" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Texto de notificación" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Título:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Revertir a la pauta predeterminada" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "C_uerpo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Mostrar notificación" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Mostrar notificaciones" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Solo en cambios de canción <i>_automáticos</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "En <i>c_ualesquier</i> cambios de canción" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Solo cuando la ventana principal no esta _enfocada" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Mostrar botón «_Siguiente»" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Error de conexión" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "No se pudo conectar con el demonio de notificaciones." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Notificaciones de canciones" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Muestra una notificación cuando cambia la canción." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Siguiente" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Notificaciones de canciones" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Vaya a la ventana Complementos para configurar QLScrobbler. Mientras no lo " "haga, no se enviará ninguna canción." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "No se pudo contactar al servicio «%s»." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Falló la autenticación: el URL no es válido." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Falló la autenticación: el nombre de usuario «%s» no es válido o la " "contraseña es incorrecta." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "El cliente se ha vetado. Contacte al autor." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "La hora del sistema es incorrecta. Hasta que no se corrija, podrían fallar " "los envíos." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Envío por AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Cliente de Audioscrobbler para servicios compatibles como Last.fm y Libre.fm." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Autenticación correcta." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Servicio:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Otro…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Verificar datos de cuenta" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Pauta de _artistas:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Pauta de _títulos:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_Filtro de exclusión:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "La pauta utilizada para dar formato al nombre de artista para su envío. Deje " "en blanco para utilizar la predeterminada." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "La pauta utilizada para dar formato al título para su envío. Deje en blanco " "para utilizar la predeterminada." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "No se enviarán aquellas canciones que encuentre este filtro" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Modo _sin conexión (no enviar nada)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Envío" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Silenciar publicidad radial" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Silencia la salida mientras se reproducen los anuncios en la radio.\n" "Emisoras: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Reproducción de álbumes al azar" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Inicia un álbum al azar cuando se acaba la lista de reproducción. El " "navegador activo debe admitir filtrar por álbumes." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Mejor puntuados" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Reproducidos más veces" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Saltados más veces" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Reproducidos más recientemente" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Iniciados más recientemente" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Añadidos más recientemente" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Álbumes más extensos" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "segundos antes de iniciar el próximo álbum" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Ponderaciones" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Reproducir algunos álbumes más que otros" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "evitar" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "preferir" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Álbum al azar" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Esperando a empezar %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" "Se importaron las puntuaciones y las estadísticas de %d canciones " "correctamente" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Importación desde Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importa puntuaciones y estadísticas musicales de Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pausar salvapantallas" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pausa la reproducción mientras el salvapantallas de GNOME esté activo." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "No se instaló ningún proveedor de búsquedas de GNOME Shell para Quod Libet." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Proveedor de búsquedas de GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Permite que GNOME Shell busque en la fonoteca." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Barra de posición alternativa" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "La barra de posición alternativa siempre está visible y abarca la anchura " "entera de la ventana." #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Puntos de mira de marcadores" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nombre del marcador para el punto A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nombre del marcador para el punto B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Sincronización con Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Hace que el Squeezebox de Logitech emita la misma salida que Quod Libet, " "siempre y cuando ambos lean de idéntica fonoteca." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Comparte la configuración con el <a href=\"%(plugin_link)s\">complemento " "Exportar a Squeezebox</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Error al buscar el servidor Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Error al buscar %s. Compruebe la configuración" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Opciones del complemento" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Copia pendiente" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Eliminación pendiente" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "eliminar" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Saltar" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLICADA" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Sincronizando" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Eliminando" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Éxito" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "FALLO" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Se saltó un archivo existente" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "No se puede establecer el nombre de archivo de una canción." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Sincronizar a dispositivo" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Sincroniza todas las canciones de las búsquedas guardadas seleccionadas con " "la carpeta que se especifique." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Sincronizar estas búsquedas guardadas:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "La ruta absoluta a la ubicación de exportación" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Se eliminará todo aquel archivo preexistente en la carpeta de destino que no " "figure en las búsquedas guardadas." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "Si utiliza un dispositivo montado mediante MTP, exporte a una carpeta de " "destino local y luego transfiera al aparato con rsync. O bien, si va a " "sincronizar muchos archivos con un dispositivo Android, sírvase de adb-sync, " "que es mucho más rápido." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Ruta de destino:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Pautas de rutas" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Editar pautas guardadas…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" "La estructura de los nombres de archivo exportados, basándose en sus " "etiquetas" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Pauta de exportación:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Dejar de previsualizar" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Estado" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Archivo de origen" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Ruta de exportación" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Se detectaron rutas duplicadas. Las rutas anteriores pueden editarse antes " "de comenzar la sincronización." #: quodlibet/ext/events/synchronize_to_device.py:256 #, fuzzy msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "Se eliminará cualquier archivo que exista en la ruta de destino." #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Iniciar sincronización" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Detener sincronización" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "No hay ninguna búsqueda guardada. Cree una y vuelva aquí." #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Elija la ruta de destino" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "La ruta de exportación del archivo «{filename}» cambió de «{old_path}» a " "«{new_path}»" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Empezando previsualización de la sincronización" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Finalizó la previsualización de la sincronización" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Parando previsualización de la sincronización" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Se detuvo la previsualización de la sincronización." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "La previsualización de la sincronización ha terminado." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Se detuvo la previsualización de la sincronización" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "La sincronización:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "intentará escribir {count} archivo" msgstr[1] "intentará escribir {count} archivos" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "pasará por alto {count} archivo duplicado" msgstr[1] "pasará por alto {count} archivos duplicados" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "eliminará {count} archivo" msgstr[1] "eliminará {count} archivos" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "No se proporcionó ninguna ruta de destino" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Especifique el directorio donde se deben exportar las canciones." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "No se proporcionó ninguna pauta de exportación" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Especifique una pauta para los nombres de las canciones exportadas." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "La ruta de exportación no es absoluta" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "La pauta\n" "\n" "<b>{}</b>\n" "\n" "contiene «/» pero no inicia desde la raíz. Proporcione una ruta de destino " "absoluta cerciorándose de que comience por / o ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "No se seleccionó ninguna búsqueda guardada" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Seleccione por lo menos una búsqueda guardada." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "No hay ninguna canción en las búsquedas guardadas seleccionadas" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Todas las búsquedas guardadas seleccionadas están vacías." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Se encontraron {} canciones para sincronizar" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "La ruta de destino y la pauta de exportación no coinciden" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "La pauta de exportación comienza con una ruta que difiere de la de destino. " "Corrija la pauta.\n" "\n" "Error:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "No se pudo sincronizar" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" "No se puede comenzar la sincronización cuando se ordena por <b>Estado</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Comenzando sincronización de canciones" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Sincronización en curso." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Finalizó la sincronización de canciones" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Deteniendo sincronización de canciones" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Se detuvo la sincronización." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Finalizó la sincronización." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Se detuvo la sincronización de canciones" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Se seleccionó un complemento diferente; detener sincronización" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag}: «{filename}»" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Quitando «{}»" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "La sincronización ha:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "escrito {count}/{total} archivo" msgstr[1] "escrito {count}/{total} archivos" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(se pasó por alto {count} archivo existente)" msgstr[1] "(se pasaron por alto {count} archivos existentes)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "pasado por alto {count}/{total} archivo duplicado" msgstr[1] "pasado por alto {count}/{total} archivos duplicados" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "eliminado {count}/{total} archivo" msgstr[1] "eliminado {count}/{total} archivos" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "fallado en sincronizar {count} archivo" msgstr[1] "fallado en sincronizar {count} archivos" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "pasado por alto {count} archivo que ya se había sincronizado" msgstr[1] "pasado por alto {count} archivos que ya se habían sincronizado" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Letra en sincronía" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Muestra letras sincronizadas a partir de archivos .lrc con el mismo nombre " "(o uno similar) que cada pista." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Texto:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Fondo:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Tipo de letra" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Tamaño (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Mensajes de estado de Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Actualiza todas las cuentas de mensajería instantánea basadas en Telepathy " "(como las configuradas en Empathy) con un mensaje de estado basado en la " "canción actual." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Al reproducir:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Texto de estado al iniciar una canción. Acepta pautas QL, como %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "En pausa:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Texto de estado cuando se pone en pausa la canción. Acepta pautas QL, como %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Texto sin formato de estado cuando no se reproduce nada" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Ninguna canción:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Pautas de estado" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Cambiador de temas" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Cambia el tema de GTK activo." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Tema predeterminado" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Preferir versión oscura del tema" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Puntuación de pulgar" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Alternar barra de menús" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Conmute la barra de menús al presionar la tecla Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Sin reproducción" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Icono en área de notificación" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Controla Quod Libet desde el área de notificación del sistema." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Mostrar %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Reproducir" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Pausar" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "A_nterior" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Siguiente" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Mezclar" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetir" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "_Detener tras esta canción" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Abrir _navegador" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editar _etiquetas" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Información" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Listas" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Salir" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Comportamiento" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "La rueda del ratón ajusta el volumen" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "La rueda del ratón cambia la canción" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Rueda del ratón" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Visualización de descripciones emergentes" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Ver letra" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Muestra automáticamente la letra, de etiqueta o de archivo, en una barra " "lateral." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "No se encontró ninguna letra para\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Ninguna canción activa" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Iniciar visualizaciones" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Iniciar visualizaciones externas." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "No se pudieron ejecutar las visualizaciones con «%s»" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Error" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Ejecutable de visualizador:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Volver a cargar" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Barra de posición con onda" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" "∿ Una barra de posición que adquiere la forma de la onda de la canción " "actual." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Mostrar posición actual" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Mostrar etiquetas de tiempo" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Guardaimágenes" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Guarda la imagen de cubierta de la canción actual en un archivo." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Archivo:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Umbral:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Umbral de activación del filtro" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "R_elación:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Relación de compresión" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Compresor de audio" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Cambia la amplitud de todas las muestras por encima de un umbral específico, " "con una relación determinada." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Preselección:" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtrar por _artista" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "Corte de _frecuencia:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 #, fuzzy msgid "Feed level" msgstr "Nivel de feed" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Predeterminado" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Lo más cercano a la colocación del altavoz virtual (30°, 3 metros)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Personalizado" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Configuración personalizada" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mezcla los canales izquierdo y derecho para simular una instalación de " "altavoces al utilizar auriculares, o bien, para compensar al reproducir " "grabaciones estéreo antiguas." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Banda de filtro:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "La banda de frecuencia del filtro" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "A_nchura de filtro:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "La anchura de frecuencia del filtro" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Nivel:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Nivel del efecto" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Quita la voz principal del audio." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "Ta_sa:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "T_ono:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Tono/velocidad de audio" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Controla el tono de una transmisión de audio." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Exportar lista en carpeta" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exportar" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Carpeta de destino:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Pauta de nombres de archivo:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Exporta una lista copiando archivos en una carpeta." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "No se pudo exportar la lista" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Cerciórese de tener acceso de escritura en el destino." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Pauta de nombres de archivo predeterminada:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Aceptar" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Escriba un nombre nuevo para la lista,\n" "o bien elija una lista de Sonos existente para sobrescribirla" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Exportar a lista de Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Exporta una lista copiando archivos en una carpeta." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Error al buscar dispositivos Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Error de búsqueda de Sonos. Compruebe la configuración" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exportar a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Exporta dinámicamente una lista de reproducción al Squeezebox de Logitech, " "siempre y cuando ambos compartan la estructura de directorios." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Comparte la configuración con el <a href=\"%(plugin_link)s\">complemento " "Sincronización con Squeezebox</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Exportar lista a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Nombre de lista (sobrescribirá el existente)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exportar a lista de Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Quitar duplicados en lista" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Quita las entradas duplicadas en una lista." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "¿Confirma que quiere quitar %d canción duplicada?" msgstr[1] "¿Confirma que quiere quitar %d canciones duplicadas?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Se quitarán las canciones duplicadas de la lista «%s»." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Mezclar lista" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Mezcla al azar una lista." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Seguir cursor" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Añade un modo de orden de reproducción que obedece su selección, o la " "canción siguiente de la lista cuando se agota." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Seguir cursor" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Seguir cursor" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Igualador de reproducciones" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Añade un modo aleatorio que prioriza las canciones con menos reproducciones " "totales." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Preferir menos reproducidas" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Preferir _menos reproducidas" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Solo en cola" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Limita la reproducción de canciones a la cola.\n" "\n" "Seleccione este orden de reproducción en la ventana principal y, al pulsar " "dos veces en una canción, esta se añadirá a la cola en vez de reproducirse " "de inmediato." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Solo en cola" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Solo en cola" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Iniciar a reproducir automáticamente las canciones pulsadas dos veces" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Invertido" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Añade un modo aleatorio que invierte el orden de reproducción de las " "canciones." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Invertido" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Aguardando inicio de un grupo nuevo…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Etiqueta de agrupación:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Etiqueta con que agrupar canciones" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Etiqueta de filtro:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "El agrupamiento se aplica solo si se define la etiqueta para filtrar.\n" "Aquellas canciones sin etiqueta de filtro definida se considerarán\n" "para grupos propios. Por lo general, la etiqueta de filtro debe\n" "coincidir, al menos parcialmente, con la etiqueta de agrupamiento." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Demora:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Restablecer valores predeterminados" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Saltar pistas que no me gustan" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 #, fuzzy msgid "Skip disliked tracks" msgstr "Saltar pistas que no me gustan" #: quodlibet/ext/playorder/skip_disliked.py:30 #, fuzzy msgid "Skip _disliked tracks" msgstr "Saltar pistas que no me gustan" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Repetir cada pista" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Repetir cada pista" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Repetir cada pista" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Número de veces que reproducir cada canción:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Consulta condicional" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Incluir etiquetas vacías" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Consulta de Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Utilice expresiones de Python en las consultas." #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Expresión de etiqueta" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Incluir búsqueda guardada" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" "💾 Incluya los resultados de una búsqueda guardada como parte de otra " "consulta." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Búsquedas guardadas" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" "La Squeezebox está en buen estado. Se utiliza el único reproductor (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "No se pudo conectar con %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nombre de anfitrión:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Puerto:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nombre de usuario:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Contraseña:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Directorio de fonoteca al que el servidor se conecta" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Ruta de fonoteca:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Servidor Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Depuración" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Servidor Squeezebox en {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "servidor Squeezebox no identificado" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "reproductor Squeezebox no identificado: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Elija el reproductor Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Se encontró un servidor Squeezebox.\n" "Seleccione el reproductor" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Encajar imagen en _ventana" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programa:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Editar imagen tras guardarla" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Nombre de archivo:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "No se pudo guardar" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "No se pudo guardar «%s»." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Descargador de cubiertas" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "de %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Resolución: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Tamaño: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Buscar" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Buscando…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Hecho" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Descargar cubierta de álbum" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Descarga cubiertas de álbumes de varios sitios web." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Fuentes" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "De APEv2 a ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Convierte las etiquetas APEv2 en sus equivalentes en ID3v2. Tras la " "conversión se eliminarán las etiquetas APEv2." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Ir al marcador" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Gestiona los marcadores en los archivos seleccionados." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Editar marcadores…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "No hay ningún marcador" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Búsqueda en MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Utilizar solo el año para la etiqueta «date»" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Escribir «_albumartist» cuando haga falta" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Escribir etiquetas e_stándares de MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Escribir etiqueta «labelid»" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nombre del archivo" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Título" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Búsqueda en MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Consulta:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Buscar" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Resultados <i>(arrastre para reordenar)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Introduzca una consulta." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Se produjo un error. Vuelva a intentarlo." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Cargando resultado…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "No se encontró ningún resultado." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Consola de Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Consola interactiva para Python. Se abre en una ventana nueva." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Barra lateral de la consola de Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Puede acceder a los objetos siguientes de manera predeterminada:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Su directorio de trabajo actual es:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Compleción" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Descargar cubiertas de álbumes" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Descarga cubiertas de álbumes de alta calidad mediante complementos de " "cubiertas." #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Clásica" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Grande" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "Alta definición" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "1080p" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Descarga de cubiertas" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Cargando %(source)s; %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "No se encontró nada para los álbumes:\n" "<i>%(albums)s</i>.\n" "\n" "Proveedores utilizados:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "No se encontró ninguna cubierta" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} × {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Tamaño de previsualización" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Destino de guardado" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Si no es ya JPEG, se convierte la imagen en un JPEG de alta calidad con las " "mismas dimensiones" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Guardar como JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Orden" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nombre" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "El nombre de esta orden" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "orden" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "La sintaxis de las órdenes de consola que se ejecutarán" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parámetro" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "args. máxs." #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "invertir" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Valor de entrada" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Órdenes personalizadas" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Ejecuta órdenes personalizadas (en lotes si es necesario) sobre las " "canciones, utilizando cualquiera de sus etiquetas." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Editar órdenes personalizadas" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "No se pudo ejecutar la orden personalizada %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d grupo duplicado" msgstr[1] "%d grupos duplicados" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Contraer/ampliar todo" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "La expresión de clave duplicada es «%s»" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Explorador de duplicados" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" "Encuentra y muestra versiones de canciones etiquetadas de forma semejante." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "A_grupar duplicados por:" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Eliminar la etiqueta seleccionada" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Eliminar la etiqueta seleccionada" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Quitar _diacríticos" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Quitar _puntuación" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Editar recuento de reproducciones" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Recuento de reproducciones" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Recuento de saltos" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Valores %s múltiples" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Editar imágenes incrustadas" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Quita o sustituye las imágenes incrustadas." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Incrustar" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Quitar todas las imágenes" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Incrustar imagen actual" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Establecer puntuación exacta" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Permite definir la puntuación de las canciones con un número." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrar con cualquier etiqueta" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Crea una consulta basada en etiquetas de las canciones actuales." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrar con directorio" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Búsqueda de huellas acústicas" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Encuentra metadatos de canciones a través de huellas acústicas." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Enviar huellas acústicas" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Genera huellas acústicas mediante Chromaprint y las envía a acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Falta la clave de API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Debe especificar una clave de API de acoustid.org en las preferencias del " "complemento para poder enviar huellas." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Solicitar clave de API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Clave de API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Servicio web de AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "En cola" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analizando" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Búsqueda" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Guardar" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Escribir etiquetas de MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Agrupar por directorio" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Modo de álbum" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generando huellas:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detalles" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Enviar" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Huellas:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Canciones con MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Canciones con etiquetas suficientes:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Canciones que enviar:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Hecho. %(to-send)d/%(all)d canciones por enviar." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Enviando huellas:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Enviando…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Actualizar etiquetas en archivos" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exportar a HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exporta la lista de canciones seleccionada en HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Enviar a iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Carga canciones en un dispositivo iFP de iRiver." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "No se encontró ningún dispositivo iFP" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "No se pudo contactar con el dispositivo iFP. Cerciórese de que esté " "encendido y conectado y de que se haya instalado ifp-line (http://ifp-driver." "sf.net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Cargando %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "No se pudo cargar <b>%s</b>. Puede que el dispositivo carezca de espacio o " "esté apagado." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Error al cargar" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Exportar datos de usuario" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Exportar etiquetas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Exportar etiquetas y datos de usuario" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Exportar metadatos" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Importar/exportar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Importa y exporta etiquetas y datos de usuario en las pistas." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Información adicional" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Interacción de usuario al importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Requerir confirmación si el número de pistas difiere" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Requerir confirmación si el número de álbumes difiere" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Semejanza entre pistas:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Semejanza entre álbumes:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Exportar archivos" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Generar JSON legible (más lento)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Eliminar archivos de exportación tras importarlos" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Abrir directorio de exportación" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Discos" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Pistas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artista(s)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Final de ruta" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Relacionar álbumes" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Continuar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Nada que importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Debe efectuar una exportación antes de poder importar." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "El índice estaba dañado." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "No se pudo procesar el JSON en %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "No se pudo leer %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Nombre de archivo" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Relacionar pistas" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Actualizando listas de éxitos." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Ya está al día." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Sincronización completada." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Error al sincronizar (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Sincronización con Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" "Actualiza las estadísticas de su fonoteca a partir de su perfil de Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Nombre de _usuario:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Crear etiquetas de ordenación" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Exportar como archivo de lista M3U/PLS" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exporta las canciones en una lista de reproducción M3U o PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Utilizar rutas relativas" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Utilizar rutas absolutas" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "No se pudo escribir en <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Redetectar canciones" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Comprueba si hay cambios en los archivos y vuelve a cargar o quita las " "canciones en caso necesario." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Redetectar canciones" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Analizador de Replay Gain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Progreso" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Ganancia" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Pico" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Hay <b>%(to-process)s</b> álbum por actualizar (de %(all)s)" msgstr[1] "Hay <b>%(to-process)s</b> álbumes por actualizar (de %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analiza y actualiza la información de <a href=\"%(rg_link)s\">ReplayGain</a> " "a través de GStreamer. Los resultados se agrupan por álbum." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "siempre" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Procesar álbumes:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Etiquetas existentes" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Extraer etiquetas" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Extrae el número de disco del álbum y la versión del título al mismo tiempo." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Extraer álbum" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Extraer el número de disco." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/d" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "PPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Restablecer" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etiqueta" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "No se han podido eliminar las canciones" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Búsqueda en sitios web" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Buscar pautas de URL" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Editar URL de búsqueda" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Configurar búsquedas…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Buscar etiqueta en Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Abre una ventana del navegador con el artículo de la Wikipedia sobre la " "etiqueta correspondiente a la canción seleccionada." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Buscar en %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Editar etiquetas" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Falló la búsqueda" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "No se encontró la etiqueta «%s»." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Fonoteca" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Comprobando los puntos de montaje" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Detectando fonoteca" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Detectando %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Cargando archivos" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Moviendo archivos de la fonoteca" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Quitando archivos de la fonoteca" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Reproductor y gestor de fonotecas musicales" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Error al abrir el archivo: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Mostrar las etiquetas" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Mostrar salida para depuración" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Columnas y orden de disposición en el modo depuración (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Mostrar también etiquetas programáticas" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Sin argumentos suficientes" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Demasiados argumentos" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Descripción" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valor" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Mostrar las etiquetas habituales" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Copiar las etiquetas de un archivo a otro" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Mostrar los cambios, sin aplicarlos" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Saltar las etiquetas que no se puedan escribir" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "No se puede copiar la etiqueta {tagname} en el archivo: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Editar etiquetas en editor de texto" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Se interrumpió la edición" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Falló el inicio del editor de textos «%(editor-name)s»." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "No se detectó ningún cambio" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Establecer una etiqueta y eliminar los valores existentes" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "No se puede establecer %(tag)r para el archivo %(format)s «%(file)r»" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Quitar etiquetas" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "El valor es una expresión regular" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Quitar todas las etiquetas" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "No se puede combinar «--all» con «--regexp»" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "No se puede quitar {tagname} de {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Quitar un valor de etiqueta" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Añadir un valor de etiqueta" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "No se pudo establecer %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Información del archivo de lista" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "No se pudo cargar el archivo de imagen: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Quitar todas las imágenes incrustadas" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraer imágenes incrustadas en %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Ruta en que se guardarán las imágenes (directorio de trabajo de manera " "predeterminada)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Cambiar nombre de archivos según las etiquetas" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Rellenar las etiquetas según la ruta al archivo" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Archivo" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Rellenar los números de pista de todos los archivos" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Mostrar etiquetas basándose en la pauta indicada" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Mostrar información de ayuda" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" "«%(column-id)s» no es un nombre válido para una columna (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Desconocido" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "En orden" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_En orden" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Al azar" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "Al a_zar" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Preferir mejor puntuadas" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Preferir _mejor puntuadas" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Repetir esta pista" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Repetir _esta pista" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Repetir todo" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Repetir _todo" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Una canción" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Una _canción" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Transmisión" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Almacenando en búfer" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "No se pudo crear la canalización de GStreamer (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" "No se encontró ningún elemento de GStreamer para manipular el formato " "multimedia" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Formato multimedia: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "No se pudo inicializar el complemento «%(name)s» de GStreamer" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "La canalización de salida de GStreamer utilizada para la reproducción. Deje " "en blanco para utilizar la predeterminada. Si la canalización incluye un " "receptor, se utilizará este en lugar del predeterminado." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Canalización de _salida:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Duración de _búfer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Desactivar la reproducción sin pausas puede evitar problemas de cambio de " "pista en ciertas versiones de GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Utilizar JACK para reproducir, si está disponible" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" "Utiliza «jackaudiosink» para el receptor de reproducción, si puede detectarse" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Conectar automáticamente a dispositivos de salida de JACK" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Indica a «jackaudiosink» que efectúe conexiones automáticamente" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "No se encontró ningún receptor de audio de GStreamer. Se intentó: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "La canalización de salida de GStreamer no es válida" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "No se pudo generar la salida de audio" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "No se encontró el dispositivo de audio %r. Compruebe la configuración de " "Xine en ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "No se pudo encontrar el módulo «{module}». Quizá necesita instalar el " "paquete correspondiente." #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "No se pudo encontrar el elemento «{element}» de GStreamer." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Vaya a la ventana Complementos para configurar ListenBrainz. Mientras no lo " "haga, no se enviará ninguna escucha." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Se produjeron demasiados errores de envío (%d). Se estableció el modo sin " "conexión. Visite el diálogo Complementos para restablecer ListenBrainz. " "Hasta entonces, no se enviará ninguna escucha." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "Envío a ListenBrainz" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Envíe las escuchas a ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "_Ficha de usuario:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "E_tiquetas:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "La lista de etiquetas que incluir en el envío. Sepárelas con comas y utilice " "comillas dobles si es necesario." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "No se enviará ninguna de las canciones que encuentre este filtro." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "¿Quiere ejecutar el complemento «%(name)s» en %(count)s lista?" msgstr[1] "¿Quiere ejecutar el complemento «%(name)s» en %(count)s listas?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Ejecutar complemento" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Uso" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Comienzo" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Posición" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nombre del marcador" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Marcadores" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtros" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Reproducidas _recientemente" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "_Añadidas recientemente" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _más escuchadas" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "_Todas las canciones" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "De _géneros actuales" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "De _artistas actuales" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Del ál_bum actual" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "_Género al azar" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "_Artista al azar" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Ál_bum al azar" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "Las 40 canciones que más ha escuchado (pueden mostrarse más de 40 si algunas " "se reprodujeron el mismo número de veces)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nombre:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valor:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Valores guardados" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Editar valores guardados…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_mática" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Modo de _pista" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Modo de ál_bum" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Silenciar" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "Modo de _ReplayGain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(desconocido)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Añadir…" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Editar la vista..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Expresión de etiqueta" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Proporcione una etiqueta nueva" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Expresión de etiqueta" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Archivos:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Las canciones seleccionadas desaparecerán de la fonoteca y sus archivos se " "eliminarán del disco." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Los archivos seleccionados se eliminarán del disco." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "¿Quiere eliminar %(file_count)d archivo permanentemente?" msgstr[1] "¿Quiere eliminar %(file_count)d archivos permanentemente?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Eliminar archivos" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Las canciones seleccionadas desaparecerán de la fonoteca y sus archivos se " "enviarán a la papelera." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Los archivos seleccionados se enviarán a la papelera." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "¿Quiere enviar %(file_count)d archivo a la papelera?" msgstr[1] "¿Quiere enviar %(file_count)d archivos a la papelera?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mover a la papelera" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Moviendo %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "No se pudo enviar a la papelera" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "No se pudo enviar uno o más archivos a la papelera." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Eliminando %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "No se pudieron eliminar los archivos" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Falló la eliminación de uno o más archivos." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Navegador" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Descargando archivos" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "no fue encontrada de %d canción" msgstr[1] "no se hallaron de %d canciones" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "difiere a lo largo de %d canción" msgstr[1] "difieren a lo largo de %d canciones" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Extraer en valores _múltiples" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Extraer disco del ál_bum" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Extraer _versión del título" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Extraer arreglista del ar_tista" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Extraer _intérprete del artista" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Extraer _intérprete del título" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Extraer artista _original del título" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Añadir una etiqueta" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Etiqueta:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Mostrar etiquetas _programáticas" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Acceso a todas las etiquetas, incluso a aquellas generadas automáticamente, " "p.ej. las etiquetas MusicBrainz o ReplayGain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Mostrar etiquetas _programáticas" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Revertir" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Guardar" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Configurar" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "E_xtraer etiqueta" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Copiar valor(es)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "No se pudo añadir la etiqueta" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "No se pudo añadir canciones" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Los archivos seleccionados no admiten valores múltiples para <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "La etiqueta no es válida" msgstr[1] "La etiqueta no es válida" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "La etiqueta <b>%s</b> no es válida.\n" "\n" "Los archivos seleccionados no permiten la edición de la etiqueta." msgstr[1] "" "La etiqueta <b>%s</b> no es válida.\n" "\n" "Los archivos seleccionados no permiten la edición de la etiqueta." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "El valor no es válido" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "El valor no es válido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "La etiqueta puede no ser precisa" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "Se modificó %(file-name)s mientras el programa se ejecutaba. Si guarda sin " "actualizar la fonoteca, podrían sobrescribirse otros cambios efectuados en " "la canción." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "No se pudo guardar la canción" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "No se pudo guardar %(file-name)s. Puede que el archivo sea de solo lectura, " "que esté dañado o que no tenga permisos para editarlo." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Más opciones…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Deshacer" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Rehacer" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Acerca de" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Buscar actualizaciones…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Complementos" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s y %(count)s más" msgstr[1] "%(title)s y %(count)s más" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferencias de Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Carpetas" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "Carpeta _nueva…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Seleccionar todas las subcarpetas" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Carpeta nueva" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Proporcione un nombre para la carpeta nueva:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "No se pudo crear la carpeta" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "No se pudo eliminar la carpeta" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Canciones" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "por %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Pista %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Editar vista…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "No se seleccionó ninguna canción." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Sin canciones" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Información" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Letra" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Producida por %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistas" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "intérpretes" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nunca" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d vez" msgstr[1] "%(n)d veces" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "añadida" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "última reproducción" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "reproducciones" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "saltos" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "puntuación" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "ruta" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "duración" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formato" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "códec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codificación" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "tasa de bits" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "tamaño de archivo" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificada" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d seleccionada" msgstr[1] "%d seleccionadas" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Pista no disponible" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d canción sin álbum" msgstr[1] "%d canciones sin álbum" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discografía seleccionada" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d canción sin artista" msgstr[1] "%d canciones sin artista" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "álbumes" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Duración total:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Tamaño total:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Archivos" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Ver en la web" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "No se encontró la letra de esta canción." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "¿Confirma que quiere quitar todas las canciones?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Las canciones seleccionadas desaparecerán de la fonoteca." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "¿Quiere descartar los cambios en las etiquetas?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Las etiquetas se han modificado pero no se han guardado. ¿Quiere guardar los " "archivos o revertir y descartar dichos cambios?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Revertir" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "El archivo existe" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "¿Quiere reemplazar %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Reemplazar archivo" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Tareas activas" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d tareas en ejecución" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Alternar modo aleatorio" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Alternar modo de repetición" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Sucesos" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Orden de reproducción" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Edición" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Cambio de nombre" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Consulta" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Cubiertas" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Errores en los complementos" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Cualquier estado" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Activado" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Desactivado" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Sin categoría" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Cualquier categoría" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "No se encontró ningún complemento." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Complementos" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrar por estado/etiqueta de complemento" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrar por tipo de complemento" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrar por nombre o descripción de complemento" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Mostrar _errores" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "Pis_ta" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "agrupación" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artista" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Ál_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Nombre de _archivo" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "Durac_ión" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Ir automáticamente a la canción reproducida" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Cuando cambie la canción reproducida, centrar la lista en esta" #: quodlibet/qltk/prefs.py:72 #, fuzzy msgid "_Sort songs when tags are modified" msgstr "Ordenar canciones cuando se modifican las etiquetas" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" "Reordena automáticamente las canciones de la lista cuando se les modifican " "etiquetas" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Otras:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Editar…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Añadir o eliminar columnas de información adicional" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Columnas visibles" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "El título incluye la _versión" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "El álbum incluye el _subtítulo" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "El artista incluye a todas las _personas" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "El nombre incluye la _carpeta" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Preferencias de columnas" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Editar columnas" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Aplicar la configuración actual a la lista, añadiendo nuevas etiquetas al " "final" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de canciones" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Editar columnas" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Totales de duración" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Filtro _global:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Aplicar esta consulta añadiéndola a las demás" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Búsqueda" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Confirmar la puntuación _múltiple" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Solicitar confirmación antes de cambiar la puntuación de varias canciones a " "la vez" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Activar las puntuaciones con _un click" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Permitir las puntuaciones al hacer click en la columna de puntuaciones de la " "lista" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Puntuaciones" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Preferir cubierta _incrustada" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Elegir utilizar la carátula incrustada en el archivo de audio (si está " "disponible) antes que la tomada de otras fuentes" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "El o los archivos de imagen de cubierta que utilizar en caso de estar " "disponibles (permite comodines). Para definir más de uno, sepárelos con " "comas." #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "Nombres de archivo de imagen _preferidos:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Cubiertas de álbumes" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Reproducción" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Configuración de salida" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Si no existe información de Replay Gain para una canción, multiplicar el " "volumen por este valor" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Ganancia por defecto (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Multiplicar el volumen de todas las canciones por este valor, siempre que el " "resultado no provoque cortes" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Ganancia de _volumen (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Activar el ajuste de volumen _replay gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Ajuste de volumen _replay gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Puntuación pre_determinada:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "E_scala de puntuación:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Factor de promedio bayesiano (C) para puntuaciones totalizadas.\n" "0 indica un promedio convencional. Los valores mayores indican que los " "álbumes con pocas pistas tendrán puntuaciones menos extremas. Al cambiar " "este valor se hará un recálculo de todos los álbumes." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Cantidad de media _bayesiana:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "Correo _electrónico:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Las puntuaciones y los recuentos de reproducción se guardarán en etiquetas " "para esta dirección de correo electrónico" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Guardar automáticamente cambios en etiquetas" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Guardar los cambios en las etiquetas sin confirmación individual al editar " "varios archivos" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Conjunto de separadores que utilizar al extraer valores de etiqueta en el " "editor. Los elementos de la lista se separan con espacios." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Dividir e_tiqueta en:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Conjunto de separadores que utilizar al extraer valores de etiqueta en el " "editor. Los elementos de la lista se separan con espacios y cada entrada " "debe contener dos caracteres solamente." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Dividir _subetiqueta en:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Etiquetas" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Edición de etiquetas" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Nueva emisora" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Detectar fonoteca" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Comprobar si hay cambios en la fonoteca" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Re_construir fonoteca" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Recarga todas las canciones de la fonoteca. El proceso puede demorar " "bastante." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Canciones ocultas" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Detectar fonoteca al _inicio" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Detectar en directorios" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s y %(count)d más" msgstr[1] "%(title)s y %(count)d más" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Propiedades" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Cola de reproducción" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Vaciar cola" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Efímera" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Quita las canciones de la cola después de reproducirlas" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Persistente" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Mantiene las canciones en la cola después de reproducirlas" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modo" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Detener al finalizar" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d canción (%(time)s)" msgstr[1] "%(count)d canciones (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Examinar la colección" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Alternar visibilidad de cola" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Error de reproducción" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "¿Quiere configurar los directorios de la fonoteca?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "No ha configurado ninguna fonoteca. ¿Quiere hacerlo ahora?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "Ahora _no" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Configurar" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "No se pudo añadir canciones" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s utiliza un protocolo no admitido." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Ir a la canción reproducida" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Archivo" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Canción" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Ver" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Explorar" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "C_ontrol" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "Ay_uda" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Añadir carpeta…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Añadir archivo…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Añadir ubicación…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Editar marcadores…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Detener" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Detener después de esta canción" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Atajos de _teclado" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Ayuda en línea" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Buscar en la ayuda" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Añadir ubicación" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Introduzca la ubicación de un archivo de audio:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "No se pudo añadir la ubicación" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s no es una ubicación válida." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Añadir música" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Añadir carpetas" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Archivos de música" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Añadir archivos" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "¿Confirma que quiere quitar todas las canciones?" msgstr[1] "¿Confirma que quiere quitar todas las canciones?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Cola de reproducción" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "¿Confirma que quiere cambiar la puntuación de todas las %d canciones?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Se quitarán las puntuaciones guardadas" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Quitar puntuación" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Se cambiará la puntuación de todas las canciones seleccionadas a %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Cambiar _puntuación" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Reemplazar espacios por guiones _bajos" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Reempl. delim. por dos puntos o punto y coma por guiones" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "p. ej., «iv: allegro.flac» → «iv - allegro.flac»" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Eliminar caracteres incompatibles con _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Eliminar _diacríticos" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Eliminar caracteres no _ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Utilizar únicamente caracteres en minúscula" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Cambiar el nombre del archivo" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Previsualizar" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Nombres de archivo" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Mover cubierta" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Quitar directorios vacíos" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Cubierta de álbum" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nombre nuevo" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "No se pudo cambiar el nombre del archivo" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "No se pudo cambiar el nombre de <b>%(old-name)s</b> a <b>%(new-name)s</b>. " "Es posible que el archivo de destino ya exista, o bien, que no tenga " "permisos para crear el archivo nuevo o eliminar el antiguo." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "_Ignorar todos los errores" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Detener" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continuar" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "La ruta no es absoluta" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "La pauta\n" "\t<b>%s</b>\n" "contiene / pero no comienza por root (/). Para evitar problemas con los " "nombres, comience la pauta con / o ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Las canciones localizadas en estas carpetas se añadirán a la fonoteca tras " "actualizarla" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Se detectará en el directorio nuevo tras su adición" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" "Todas las canciones de los directorios seleccionados desaparecerán también " "de la fonoteca" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Mover" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Mueva una raíz de detección (pero no los archivos), migrando los metadatos " "de todas las pistas incluidas." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "¿Quiere quitar {dir!r} y todas sus pistas?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "¿Quiere quitar {n} rutas de fonoteca y todas sus pistas?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "¿Quiere quitar la ruta de la fonoteca?" msgstr[1] "¿Quiere quitar las rutas de la fonoteca?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Quitar" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Seleccionar directorios" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Seleccionar este directorio" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Esto moverá los metadatos de QL:\n" "\n" "{old!r} → {new!r}\n" "\n" "Los archivos de audio mismos no se moverán.\n" "No obstante, es recomendable hacer una copia de respaldo (incluido el " "archivo «songs» de Quod Libet)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "¿Quiere mover la raíz de detección {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "De acuerdo, mover" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Búsquedas guardadas" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Editar búsquedas guardadas…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Buscar en la fonoteca mediante texto o consultas de QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Buscar _tras escribir" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Mostrar los resultados después de terminar de escribir" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "Lím_ite:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Importancia" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Añadir consulta" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Mostrar el tiempo restante" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Ventana principal" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Posicionarse 10 segundos antes" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Posicionarse 10 segundos después" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Centrarse en el reproductor" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Restablecer filtros y saltar a la canción en reproducción" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Abrir la ventana de información para las canciones seleccionadas" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Abrir el editor de etiquetas para las canciones seleccionadas" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Añadir a cola las canciones seleccionadas" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Eliminar las canciones seleccionadas" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Vista de árbol" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Contrae el elemento o selecciona el elemento de nivel superior" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Expande el elemento" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Entradas de texto" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Deshacer el último cambio" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Rehacer el último cambio deshecho" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Seleccionar todas las canciones en todos los paneles" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "_Todas las cabeceras" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Cabeceras de p_ista" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Cabeceras de _álbumes" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Cabeceras de _personas" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Cabeceras de la _fecha" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Cabeceras de _archivo" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Cabeceras de la _producción" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Personalizar cabeceras…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Expandir columna" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "¿Quiere quitar la pista «%(title)s» de la fonoteca?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "¿Quiere quitar %(count)d pistas de la fonoteca?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Quitar de fonoteca" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "¿Quiere ejecutar el complemento «%(name)s» en %(count)d canción?" msgstr[1] "¿Quiere ejecutar el complemento «%(name)s» en %(count)d canciones?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "¿Quiere ejecutar el complemento «%(name)s» en %(count)d álbum?" msgstr[1] "¿Quiere ejecutar el complemento «%(name)s» en %(count)d álbumes?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Configurar complementos…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Añadir a la _cola" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Quitar de fonoteca…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "No se pueden mostrar los archivos" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Se produjo un error al mostrar los archivos, o bien, no hay ningún programa " "disponible para mostrarlos." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Mostrar en gestor de archivos" msgstr[1] "_Mostrar %(total)d archivos en gestor de archivos" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Descargar archivo…" msgstr[1] "_Descargar %(total)d archivos…" #: quodlibet/qltk/songsmenu.py:443 #, fuzzy msgid "successful" msgstr "Éxito" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "No se pudo guardar" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Descargas completadas" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Descargar {name!r} en" msgstr[1] "Descargar {total} archivos en" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Descargar aquí" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Reemplazar _guiones bajos por espacios" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "May_uscular etiquetas" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Extraer en valores _múltiples" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etiquetas a partir de ruta" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Las etiquetas reemplazan a las existentes" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Las etiquetas se añaden a las existentes" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "El patrón\n" "\t<b>%s</b>\n" "es inválido. Es posible que contenga la misma etiqueta dos veces o que tenga " "paréntesis o llaves desemparejados (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "La pauta introducida no es válida. Asegúrese de introducir < y > como " "\\< y \\> y de que las etiquetas estén bien emparejadas.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Editar vista" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Números de pista" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Comienza de_sde:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Pistas _totales:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Reproducir/pausar" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Anterior" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "y %d más…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Guardando las canciones modificadas..." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "Guardadas %(current)d/%(total)d canciones.\n" "(restan %(remaining)s)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s de %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Buscando actualizaciones" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Falló la conexión" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Ya utiliza la versión más reciente, %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Está disponible una versión nueva, la %(new-version)s\n" "\n" "Actualmente utiliza la versión %(old-version)s\n" "\n" "Visite el <a href='%(url)s'>sitio web</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Lista vacía" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Las listas deben tener nombre" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Ya existe una lista denominada %(name)s en %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Cubiertas de álbum incrustadas" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Utiliza las cubiertas incrustadas en los archivos de audio." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Cubierta del sistema de archivos" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Utiliza imágenes con nombres usuales y ubicadas en lugares habituales junto " "a la canción." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Cubierta" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Efectuando consulta en proveedores de cubiertas" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Mostrar información breve sobre el uso" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Mostrar versión y derechos de autor" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Mostrar información de depuración" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Uso: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opciones]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Opción %r no reconocida." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "La opción %r requiere un argumento." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r no es un prefijo único." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s segundo" msgstr[1] "%s segundos" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "No existe información sobre la duración" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d día" msgstr[1] "%d días" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d año" msgstr[1] "%d años" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" "La mayusculación anglicada de tipo título no se ajusta a las reglas del " "español." #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "La fecha ha de introducirse en el formato «AAAA», «AAAA-MM-DD» o «AAAA-MM-DD " "HH:MM:SS»." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Las ganancias Replay Gain deben introducirse en el formato «x.yy dB»." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Los picos Replay Gain deben introducirse en el formato «x.yy»." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Los identificadores MusicBrainz deben ser en el formato UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "El estado de publicación de MusicBrainz debe ser «official», «promotional» o " "«bootleg»." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "El idioma ha de ser un código de tres letras ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "No se pudo guardar" msgstr[1] "No se pudo guardar" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "No se pudo editar la canción" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "No se pudo guardar <b>%s</b>. Es posible que el archivo sea de solo lectura, " "que esté dañado o que no tenga permisos para editarlo." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codificación no válida]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "álbum" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arreglista" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arreglistas" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arreglo" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autores" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "comentario" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compositor/a" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compositores/as" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "composición" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "director/a" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "directores/as" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirección" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contacto" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "derechos de autor" #: quodlibet/util/tags.py:93 msgid "date" msgstr "fecha" #: quodlibet/util/tags.py:94 msgid "description" msgstr "descripción" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "género" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "géneros" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "intérprete" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "interpretación" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "agrupación" #: quodlibet/util/tags.py:98 msgid "language" msgstr "idioma" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licencia" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "letrista" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "letristas" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "letra" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "compañía" #: quodlibet/util/tags.py:104 msgid "title" msgstr "título" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versión" #: quodlibet/util/tags.py:106 msgid "website" msgstr "sitio web" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "artista del álbum" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "subtítulo de disco" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "pista" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "número de catálogo" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "fecha de publicación original" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "álbum original" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artista original" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "fecha de grabación" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "país de publicación" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "clave inicial" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "Id. de grabación de MusicBrainz" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID MusicBrainz de la publicación" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID MusicBrainz de la publicación" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "Id. de artista de MusicBrainz" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID MusicBrainz de la publicación" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "Id. de TRM de MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID de MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Estado del álbum según MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Tipo de álbum según MusicBrainz" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID MusicBrainz de la publicación" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "ganancia de volumen de la pista" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "pico de ganancia de la pista" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "ganancia de volumen del álbum" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "pico de ganancia del álbum" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "sonoridad de referencia" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "discos" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "pistas" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "comenzada por última vez" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nombre completo" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "punto de montaje" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personas" #: quodlibet/util/tags.py:168 msgid "year" msgstr "año" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "año de publicación original" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "marcador" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "profundidad de bits" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "formato de archivo" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "listas" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "frecuencia de muestreo" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "recuento de canales" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor de etiquetas de audio" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Edite las etiquetas de sus archivos de audio" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Reproductor de música" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Escuche, examine o edite su fonoteca" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso es un editor de etiquetas que brinda la misma interfaz de edición " "que Quod Libet. Le permite visualizar y modificar cualquier etiqueta en " "todos los formatos de archivo que admite." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Entre los formatos de archivo admitidos se encuentran Ogg Vorbis/Opus/Speex/" "FLAC, MP3, FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, " "WMA, SPC y MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet es un programa de gestión musical. Ofrece varias maneras de " "visualizar la fonoteca y admite la reproducción de radios por Internet y " "suministros de audio. Brinda una edición muy flexible de etiquetas de " "metadatos y posee funciones de búsqueda avanzadas." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Exporta una lista de reproducción al formato Sonos, siempre y cuando " #~ "ambos compartan la estructura de directorios." #~ msgid "Export to Sonos playlist" #~ msgstr "Exportar a lista de Sonos" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "No se pudo añadir <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Etiquetas no válidas" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Etiquetas <b>%s</b> no válidas\n" #~ "\n" #~ "Los archivos seleccionados no permiten la edición de estas etiquetas." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Puntúa las canciones automáticamente al reproducirlas o al saltarlas. " #~ "Utiliza el algoritmo «acelerado» de Vux, de Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f segundos" #~ msgid "Startup" #~ msgstr "Inicio" #~ msgid "Audio Feeds" #~ msgstr "Suministros de audio" #~ msgid "_Audio Feeds" #~ msgstr "Suministros de _audio" #~ msgid "New" #~ msgstr "Nuevo" #~ msgid "Automatic Library Update" #~ msgstr "Actualización automática de fonoteca" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Mantiene la fonoteca actualizada mediante inotify. Requiere %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Permite controlar Quod Libet mediante la especificación MPRIS 2 de D-Bus." #~ msgid "Searching for lyrics…" #~ msgstr "Buscando letra…" #~ msgid "broker username" #~ msgstr "nombre de usuario de agente" #~ msgid "broker password" #~ msgstr "contraseña de agente" #~ msgid "<artist>" #~ msgstr "<artista>" #~ msgid "<album>" #~ msgstr "<álbum>" #~ msgid "<title>" #~ msgstr "<título>" #~ msgid "OK" #~ msgstr "Aceptar" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Exporta los metadatos de las canciones seleccionadas como un archivo ." #~ "tags." #~ msgid "Import Metadata" #~ msgstr "Importar metadatos" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Importa metadatos para las canciones seleccionadas a partir de un " #~ "archivo .tags." #~ msgid "Migrate Metadata" #~ msgstr "Migrar metadatos" #~ msgid "_Copy" #~ msgstr "_Copiar" #~ msgid "_Paste" #~ msgstr "_Pegar" #~ msgid "Information to copy/paste" #~ msgstr "Información que copiar/pegar" #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Hay %d pista almacenada." #~ msgstr[1] "Hay %d pistas almacenadas." #~ msgid "Unsupported file type" #~ msgstr "Tipo de archivo no admitido" #~ msgid "Unable to add station" #~ msgstr "No se ha podido añadir la emisora" #~ msgid "Device Properties" #~ msgstr "Propiedades del dispositivo" #~ msgid "Device:" #~ msgstr "Dispositivo:" #~ msgid "Not mounted" #~ msgstr "No montado" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Punto de montaje:" #~ msgid "Media Devices" #~ msgstr "Dispositivos externos" #~ msgid "_Media Devices" #~ msgstr "Dispositivos _externos" #~ msgid "_Eject" #~ msgstr "_Expulsar" #, fuzzy #~ msgid "_Properties" #~ msgstr "Propiedades" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> utilizado, <b>%s</b> disponible" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> no está conectado." #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Copiando <b>%(song)s</b>" #~ msgid "Unable to copy song" #~ msgstr "No se ha podido copiar la canción" #~ msgid "There is not enough free space for this song." #~ msgstr "No hay espacio libre suficiente para esta canción" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "No se ha podido copiar <b>%s<b>." #~ msgid "Unable to delete songs" #~ msgstr "No se han podido eliminar las canciones" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Eliminando <b>%(song)s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "No ha podido eliminarse <b>%s</b>.." #~ msgid "Unable to delete song" #~ msgstr "No se ha podido eliminar la canción" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Error al expulsar <b>%s</b>." #~ msgid "Unable to eject device" #~ msgstr "No ha sido posible expulsar el dispositivo" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Sin infraestructura de dispositivos. El navegador de dispositivos ha sido " #~ "desactivado." #~ msgid "Search Library" #~ msgstr "Buscar en la colección" #~ msgid "_Search Library" #~ msgstr "_Buscar en la colección" #~ msgid "Rate the playing song" #~ msgstr "Puntuar la canción activa" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Mostrar o esconder la lista principal de canciones" #~ msgid "Unknown Device" #~ msgstr "Dispositivo desconocido" #, fuzzy #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "No se ha podido importar la librería dbus-python, necesaria para la " #~ "interacción con dispositivos externos" #~ msgid "%r is not a supported device." #~ msgstr "%r no es un dispositivo admitido." #~ msgid "Initializing device backend." #~ msgstr "Activando la infraestructura de dispositivos." #~ msgid "Trying '%s'" #~ msgstr "Intentando '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "No se ha podido conectar a una infraestructura de dispositivos" #~ msgid "Device backend initialized." #~ msgstr "La infraestructura de dispositivos ha sido iniciada." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "Patrón para el nombre de _archivo:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Eliminar errores" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Letra" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Borrar la búsqueda" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Letra" #, fuzzy #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "Ver y editar las etiquetas de la canción reproducida" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Letra" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "saltar el contador" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "No se ha podido crear la carpeta" #~ msgid "Audio device: %s" #~ msgstr "Dispositivo de sonido: %s" #~ msgid "Downloads" #~ msgstr "Descargas" #~ msgid "Size" #~ msgstr "Tamaño" #~ msgid "_Download" #~ msgstr "_Descargar" #, fuzzy #~ msgid "The single image filename to use if selected" #~ msgstr "El nombre de la imagen de portada para utilizar al predeterminarlo" #~ msgid "The album art image file to use when forced" #~ msgstr "El nombre de la imagen de portada para utilizar al predeterminarlo" #~ msgid "_Copy to Device" #~ msgstr "_Copiar al dispositivo" #, fuzzy #~ msgid "browsers" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "No ha sido posible importar python-feedparser, el navegador de fuentes " #~ "(feed) de audio ha sido desactivado." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Quod Libet ha tenido un problema. Un archivo de depuración que nos puede " #~ "ayudar a analizar el error ha sido guardado en <b>%s</b>.\n" #~ "Por favor, crea un nuevo tema en http://code.google.com/p/quodlibet/" #~ "issues/list y anexa dicho archivo o copia su contenido . \n" #~ "Ese archivo puede contener información sobre tu sistema, tal como la " #~ "lista de música reproducida recientemente. Si no deseas hacer\n" #~ "pública dicha información envía el fichero <b>%s</b> con una descripción " #~ "sobre lo que estabas haciendo." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "Puede ser que QuodLibet esté inestable. Se recomienda cerrarlo y abrirlo " #~ "de nuevo. Se guardará la colección." #~ msgid "Unable to download lyrics." #~ msgstr "No ha sido posible descargar la letra." #~ msgid "Set or toggle the playback order" #~ msgstr "Configurar o alternar el orden de reproducción" #~ msgid "Uninitialized iPod" #~ msgstr "iPod sin configurar" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Deseas crear una base de datos vacía en este iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Ganancia de _volumen (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combinar las etiquetas con valores _múltiples" #~ msgid "Capacity:" #~ msgstr "Capacidad:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "No ha sido posible guardar la base de datos del iPod" #~ msgid "Unable to save iPod database" #~ msgstr "No ha sido posible guardar la base de datos del iPod" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "" #~ "No se ha podido importar python-gpod. La interacción con el iPod se ha " #~ "desactivado." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "pico de ganancia de la pista" #~ msgid "Shuffle" #~ msgstr "Aleatoriamente" #~ msgid "Weighted" #~ msgstr "Dinámica" #~ msgid "_Weighted" #~ msgstr "_Dinámica" #~ msgid "_One Song" #~ msgstr "_Una canción" #~ msgid "Restart the playlist when finished" #~ msgstr "Reinicia la lista de reproducción al terminar" #~ msgid "Disable Browser" #~ msgstr "Desactivar el navegador" #~ msgid "_Disable Browser" #~ msgstr "_Desactivar el Navegador" #, fuzzy #~ msgid "Force Write" #~ msgstr "Guardar" #~ msgid "Filter on _Genre" #~ msgstr "Filtrar por _género" #~ msgid "Filter on _Artist" #~ msgstr "Filtrar por _artista" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrar por ál_bum" #~ msgid "_Music" #~ msgstr "_Música" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Marcadores" #~ msgid "Song _List" #~ msgstr "_Lista de canciones" #, fuzzy #~ msgid "D:" #~ msgstr "A:" #, fuzzy #~ msgid "W:" #~ msgstr "A:" #, fuzzy #~ msgid "E:" #~ msgstr "E:" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "La rueda del ratón cambia la canción\n" #~ "Shift y la rueda del ratón ajusta el volumen" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Parar después de esta canción" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "y %d más..." #~ msgstr[1] "y %d más..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Extraer el disco del ál_bum" #, fuzzy #~ msgid "Timeout" #~ msgstr "Posición" #, fuzzy #~ msgid "Select an album" #~ msgstr "Seleccionar _todo" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s y %(count)d más" #~ msgstr[1] "%(title)s y %(count)d más" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Listas" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Utilizar esquinas redondeadas en las miniaturas de las imágenes" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Redondear las esquinas de las imágenes correspondientes a las portadas de " #~ "los discos.\n" #~ "Puede ser necesario reiniciar la aplicación para que sea efectivo." #~ msgid "Re_fresh Library" #~ msgstr "Ac_tualizar la colección" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Eliminar la emisora" #~ msgid "Unable to open input files" #~ msgstr "No ha sido posible abrir los archivos" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer no tiene ningún elemento para leer archivos. Comprueba las " #~ "opciones de instalación de GStreamer." #~ msgid "Invalid audio backend" #~ msgstr "Infraestructura de sonido inválida" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "La infraestructura de sonido %r no está instalada" #~ msgid "ql-save" #~ msgstr "Guardar" #, fuzzy #~ msgid "ql-revert" #~ msgstr "_Eliminar de la colección" #~ msgid "Print all tags to stdout" #~ msgstr "Mostrar todas las etiquetas en la salida estandard" #~ msgid "Load tags dumped with 'dump'" #~ msgstr "Cargar las etiquetas extraídas con 'dump'" #~ msgid "command|filename" #~ msgstr "archivo" #~ msgid "command|tag" #~ msgstr "etiqueta" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: no se ha podido encontrar media-player-info" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Buscar" #~ msgid "%d of %d" #~ msgstr "%d de %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Utilización: %s %s" #~ msgid "_Download..." #~ msgstr "_Descargar..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nueva emisora" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Sobreescribir <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Error en la salida de audio" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "No ha podido ser iniciada la salida de GStreamer. Es posible que\n" #~ "la configuración sea inválida o que el dispositivo esté siendo " #~ "utilizado.\n" #~ "Verifica las opciones de configuración." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet ya está siendo ejecutado" #~ msgid "No song is currently playing." #~ msgstr "No se está a reproducir ninguna canción" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "No ha sido posible escribir en %s. Eliminándolo." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Editar los marcadores..." #~ msgid "_New Folder..." #~ msgstr "Nueva _carpeta..." #~ msgid "_Add to Playlist" #~ msgstr "_Añadir a la lista" #~ msgid "_Edit Display..." #~ msgstr "_Editar la vista..." #~ msgid "Output Log" #~ msgstr "Registro" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d emisora" #~ msgid "_Order:" #~ msgstr "_Orden" #~ msgid "_Add a Location..." #~ msgstr "_Añadir una dirección..." #~ msgid "_Output Log" #~ msgstr "_Salida del log" #~ msgid "Invalid command %r received." #~ msgstr "Se ha recibido el comando inválido %r." #~ msgid "Unknown browser %r." #~ msgstr "Navegador desconocido %r." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Personalizar cabeceras..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #~ msgstr[1] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #~ msgstr[1] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "Cabeceras de _fichero" #, fuzzy #~ msgid "People Headers" #~ msgstr "Cabeceras de los _componentes" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Cabeceras de _álbumes" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Cabeceras de la _fecha" #, fuzzy #~ msgid "File Headers" #~ msgstr "Cabeceras de _archivo" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Cabeceras de la _producción" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Etiqueta:" #~ msgid "Descending" #~ msgstr "Descendiente" #~ msgid "Too Many Errors" #~ msgstr "Demasiados errores" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "" #~ "Parando la reproducción porque se sucedieron %d errores consecutivos." #~ msgid "Warnings" #~ msgstr "Advertencias" #~ msgid "No log available." #~ msgstr "Sin registros" #~ msgid "album artist (sort)" #~ msgstr "artista del álbum (ordenar)" #~ msgid "artist (sort)" #~ msgstr "artista (ordenar)" #~ msgid "album (sort)" #~ msgstr "álbum (ordenar)" #~ msgid "performer (sort)" #~ msgstr "intérprete (ordenar)" #~ msgid "performers (sort)" #~ msgstr "intérpretes (ordenar)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID MusicBrainz del artista del álbum" #~ msgid "errors" #~ msgstr "errores" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Error al leer la carátula \"%s\"" #~ msgid "Permanently delete this file?" #~ msgstr "¿Eliminar definitivamente el archivo?" #~ msgid "Permanently delete these files?" #~ msgstr "¿Eliminar definitivamente los archivos?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s y %(count)d más..." #~ msgstr[1] "%(title)s y %(count)d más..." #, fuzzy #~ msgid "Version:" #~ msgstr "versión" #~ msgid "_Cause an Error" #~ msgstr "_Provocar un error" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s no se ha podido añadir a tu colección.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Error al ejecutar el comando %r, causado por: %r." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%s</b> that will help us debug the crash. Please file a new issue at " #~ "http://code.google.com/p/quodlibet/issues /list and attach this file or " #~ "include its contents. This file may contain some identifying information " #~ "about you or your system, such as a list of recent files played. If this " #~ "is unacceptable, send <b>% s</b> instead with a description of whatyou " #~ "were doing." #~ msgstr "" #~ "Quod Libet ha tenido un problema. Un archivo de depuración que nos puede " #~ "ayudar a analizar el error ha sido guardado en <b>%s</b>.\n" #~ "Por favor, crea un nuevo tema en http://code.google.com/p/quodlibet/" #~ "issues/list y anexa dicho archivo o copia su contenido . \n" #~ "Ese archivo puede contener información sobre tu sistema, tal como la " #~ "lista de música reproducida recientemente. Si no deseas hacer\n" #~ "pública dicha información envía el fichero <b>%s</b> con una descripción " #~ "sobre lo que estabas haciendo.\n" #~ "\n" #~ "A partir de ahora Quod Libet puede volverse inestable. Se recomienda " #~ "salir del programa y ejecutarlo de nuevo. \n" #~ "Se guardará tu colección." #~ msgid "Could not import python-gpod, iPod support disabled." #~ msgstr "" #~ "No se ha podido importar python-gpod. La interacción con el iPod se ha " #~ "desactivado." #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Infraestructura de salida de sonido:" #~ msgid "Search your library" #~ msgstr "Buscar en la colección" #~ msgid "No eject command found." #~ msgstr "No se ha encontrado el comando para expulsar (eject)." #~ msgid "Unable to start web browser" #~ msgstr "No ha sido posible iniciar el navegador de Internet" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "No se ha encontrado un navegador de Internet. Por favor, configura la " #~ "variable $BROWSER o asegúrate de que /usr/bin/nombre_del_navegador existe." #, fuzzy #~ msgid "Library Error" #~ msgstr "Navegador de la colección" #~ msgid "translator-credits" #~ msgstr "ashtophet" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Mostrar otras columnas, separadas por espacios" #~ msgid "_Edit and Continue" #~ msgstr "_Editar y continuar" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #~ msgstr[1] "" #~ "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" #~ "Deseas continuar?" #~ msgid "Confirm rating" #~ msgstr "Confirmar la puntuación" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Copyright 2004-2010 Joe Wreschnig, Michael Urman, et alii\n" #~ "\n" #~ "Este programa es software libre; accede al código fuente para comprobar " #~ "las\n" #~ "condiciones de copia. No existe garantía alguna, ni siquiera de APTITUD " #~ "PARA EL\n" #~ "COMERCIO o de AJUSTARSE a alguna finalidad particular.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r no contiene ningún navegador" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Tamaño total:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r no contiene ningún dispositivo." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: No se puede importar ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: no se ha podido encontrar media-player-info" #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: no se ha podido encontrar media-player-info" #~ msgid "Quod Libet Plugins" #~ msgstr "Extensiones del Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Muestra las búsquedas simples en azul, las avanzadas en verde, y las " #~ "inválidas en rojo" #~ msgid "Separators for splitting tags" #~ msgstr "Separadores para extraer las etiquetas" #~ msgid "Quod Libet Preferences" #~ msgstr "Preferencias de Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "No reproducidas ho_y" #~ msgid "Not Played in a _Week" #~ msgstr "No reproducidas en una s_emana" #~ msgid "Not Played in a _Month" #~ msgstr "No reproducidas en un _mes" #~ msgid "B_ottom 40" #~ msgstr "Úl_timas 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "Las 40 canciones que menos has escuchado (pueden mostrarse más de 40 si " #~ "algunas se reproducieron el mismo número de veces)" #~ msgid "gtk-media-next" #~ msgstr "_Siguiente" #~ msgid "gtk-media-previous" #~ msgstr "_Anterior" #~ msgid "gtk-media-play" #~ msgstr "_Reproducir" #~ msgid "gtk-media-pause" #~ msgstr "_Parar" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #~ msgid "Date" #~ msgstr "Fecha" #~ msgid "Add" #~ msgstr "Añadir" #~ msgid "Bitrate" #~ msgstr "Tasa de bits" #~ msgid "_Stations..." #~ msgstr "_Emisoras..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Activando la infraestructura de sonido (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Cargando la colección principal (%s)" #~ msgid "Unable to save library" #~ msgstr "No ha sido posible guardar la colección" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Imposible añadir canción" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "No se ha podido crear la salida de audio %r. Comprueba la configuración " #~ "de GStreamer en ~/.quodlibet/config" #~ msgid "Sort by title" #~ msgstr "Ordenar por título" #~ msgid "Sort by artist" #~ msgstr "Ordenar por artista" #~ msgid "Lyrics provided by %s." #~ msgstr "Letras obtenidas de %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "No se han encontrado las letras.\n" #~ "\n" #~ "Puedes hacer clic en el botón de descargar para que Quod Libet las busque " #~ "online. También las puedes introducir tú mism@ y guardarlas. " #~ msgid "_LastFM webservice URL: http://" #~ msgstr "URL del servicio _LastFM: http://" #~ msgid "The main url for lastfm webservices. Must end in a trailing /" #~ msgstr "La URL para acceder a los servicios lastfm. Debe terminar con un /" #~ msgid "LastFM _similar artist webservice: " #~ msgstr "Servicio LastFM de artistas _similares" #~ msgid "" #~ "Enter here the xml webservice lookup that gets appended to the main " #~ "service url" #~ msgstr "" #~ "Introduce aquí el fichero xml de búsqueda que se añade a la URL principal." #~ msgid "LastFM top _tracks webservice: " #~ msgstr "Canciones _más escuchadas en LastFM" #~ msgid "LastFM top _albums webservice: " #~ msgstr "Álbums más _escuchados en LastFM" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d canciones guardadas" #~ msgid "part" #~ msgstr "parte" #~ msgid "Opening audio device." #~ msgstr "Accediendo al dispositivo de sonido" #~ msgid "MusicBrainz album ID" #~ msgstr "ID MusicBrainz del álbum" #~ msgid "Loaded song library." #~ msgstr "La colección fue cargada" #~ msgid "Unable to open audio device" #~ msgstr "Imposible acceder al dispositivo de audio" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet ha intentado acceder a los plugins 'autosink' y '%(sink)ss' " #~ "pero no ha podido utilizar ninguno de ellos. Configura el plugin de " #~ "GStreamer editando\n" #~ " <b>pipeline = %(sink)s</b>/nen ~/.quodlibet/config" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet no ha podido encontrar el elemento 'filesrc' de GStreamer. " #~ "Verifica la instalación de GStreamer." #~ msgid "Unable to retag multiple values" #~ msgstr "Imposible renombrar una etiqueta" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "" #~ "No se permite editar el nombre de una etiqueta con múltiples valores." #~ msgid "Select _recursively" #~ msgstr "Seleccionar _recursivamente" #~ msgid "Select Recursively" #~ msgstr "Seleccionar recursivamente" #~ msgid "Also select files from subdirectory when in file system view." #~ msgstr "" #~ "También seleccionará los ficheros de los subdirectorios en la vista de " #~ "sistema de ficheros" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Quod Libet está examinando tu colección. Este proceso puede demorar " #~ "varios minutos. \n" #~ "%d canciones recargadas\n" #~ "%d canciones eliminadas" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Quod Libet está examinando la colección y de haber nuevas canciones las \n" #~ "añadirá a la colección.\n" #~ "\n" #~ "%d canciones añadidas" #~ msgid "W: %s is not a QL song database." #~ msgstr "A: %s no es una canción de la colección del QL" #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "por <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disco <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Pista <tracknumber>>>" #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Ajuste de voumen por canción (\"Radio\")" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Ajuste de volumen por álbum (\"Audiófilo\")" #~ msgid "_Volume Normalization" #~ msgstr "Normalización del _volumen" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "Las listas M3U no pueden ser cargadas" #~ msgid "This station is already in your library." #~ msgstr "Esta emisora ya se encuentra en la Colección" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "" #~ "La colección no puede ser actualizada mientras se está ejecutando el Quod " #~ "Libet" #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Cargando, examinando y guardando su colección" #~ msgid "Rescan your library and exit" #~ msgstr "Actualiza tu colección" #~ msgid "Old Plugins" #~ msgstr "Extensiones antiguas" #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "Parece que estás ejecutandor Quod Libet. Si editas las canciones al mismo " #~ "tiempo en la colección de Quod Libet mientras se está ejecutando, nece-" #~ "sitarás actualizarla o añadirlas de nuevo.\n" #~ "\n" #~ "Si no estás ejecutando Quod Libet, o estás editando canciones que no " #~ "están en su colección, puedes ignorar esta advertencia." #~ msgid "GStreamer status %r != %r" #~ msgstr "Estado del GStreamer %r != %r" #~ msgid "_Pane %d:" #~ msgstr "_Panel %d:" #~ msgid "Double-click a tag value to change it, right-click for other options" #~ msgstr "" #~ "Haz doble-click en un valor de la etiqueta para modificarlo, clic \n" #~ "derecho para otras opciones." #~ msgid "Add a new tag" #~ msgstr "Añadir una nueva etiqueta" #~ msgid "The first letter of each word will be capitalized" #~ msgstr "La primera letra de cada palabra será puesta en mayúsculas" #~ msgid "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgstr "" #~ "Los caracteres que no son permitidos en los nombres de ficheros de " #~ "windows (\\:?;\"<>|) serán reemplazados por guiones bajos" #~ msgid "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgstr "" #~ "Los caracteres no incluidos en la especificación ASCII (A-Z, a-z, 09, y " #~ "los de puntuación) serán reemplazados por guiones bajos" #~ msgid "Apply to these _files..." #~ msgstr "Aplicar a estes _ficheros..." #~ msgid "Path" #~ msgstr "Ruta" #~ msgid "Tray Preferences - Quod Libet" #~ msgstr "Preferencias del icono - Quod Libet" #~ msgid "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgstr "E: Necesitas GTK+ 2.6 y PyGTK 2.6 o superior" #~ msgid "E: You have GTK+ %s and PyGTK %s." #~ msgstr "E: Tienes GTK+ %s y PyGTK %s." #~ msgid "E: Please upgrade GTK+/PyGTK." #~ msgstr "E: Por favor, actualiza GTK+/PyGTK" #~ msgid "Set play order" #~ msgstr "Establecer el orden de reproducción" #~ msgid "" #~ "Deleting <b>%s</b> failed. Possibly the target file does not exist, or " #~ "you do not have permission to delete it." #~ msgstr "" #~ "La elminación de <b>%s</b> erró. Posiblemente el fichero no existe o no " #~ "tienes permisos para eliminarlo." #~ msgid "%(different)s, %(missing)s" #~ msgstr "%(different)s, %(missing)s" #~ msgid "Play songs in random order" #~ msgstr "Reproduce las canciones en orden aleatorio" #~ msgid "S_ong" #~ msgstr "Canció_n" #~ msgid "_Choose randomly" #~ msgstr "_Escoger aleatoriamente" #~ msgid "Drag songs here to add them to the play queue" #~ msgstr "" #~ "Arrastra las canciones aquí para añadirlas a la cola de reproducción" #~ msgid "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgstr "" #~ "Quod Libet no pudo acceder a tu dispositivo de audio. Esto suele " #~ "significar que otro programa lo está utilizando o que los controladores " #~ "no están configurados. \n" #~ "\n" #~ "Quod Libet terminará ahora." ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/eu.po����������������������������������������������������������������������������0000644�0001750�0001750�00000671536�14436352625�013626� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Basque translation of Quod Libet # Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # Piarres Beobide <pi@beobide.net>, 2010. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2010-11-29 00:37+0200\n" "Last-Translator: Piarres Beobide <pi@beobide.net>\n" "Language-Team: Basque <librezale@librezale.es>\n" "Language: eu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Pootle 2.0.5\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Titulua" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "jendea" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Data goiburuak" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "jatorrizko artista" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "Genero" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Balorazioa" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Editatu bistaratzea" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Ordena_tu:" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Hobespenak" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Album zerrenda" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Album zerrenda" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Album guztiak" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "album %d" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Ikusi album _karatulak" msgstr[1] "Ikusi album _karatulak" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Album gabeko kantak" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "kanta %d" msgstr[1] "%d kantak" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "disko %d" msgstr[1] "%d disko" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Album guztiak" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Album zerrenda hobespenak" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Ikusi album _karatulak" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Sarezko _bilaketa jendea barneratuz" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[aukerak]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Album bistaratzea" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Liburutegi nabigatzailea" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "kanta %d" msgstr[1] "%d kanta" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Patroi baliogabea" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Diska bilduma" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Diska _bilduma" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Ezezaguna" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Zatitu _hainbat baliotan" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizatu" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "Bikoiztuak ezabatu" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etiketa" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Batu" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Album zerrenda hobespenak" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Tamaina guztira:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Tamaina guztira:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Ikusi album _karatulak" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Album guztiak" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "erakundea" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Fitxategi sistema" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Fixtategi sistema" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Ezin dira kantak kopiatu" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "Hautatutako kantak ezin dira kopiatu beste zerrenda edo ilara batera." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Gehitu liburutegira" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Kate zerrendak kate helbideak bakarrik izan ditzake ez beste kate zerrenda " "edo erreprodukzio-zerrendarik. Hurrengo kateak ezin dira kargatu:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet irratia" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Kate berria" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Deskargatu fitxategiak" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Kate berria" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Sar Internet bidezko irrati kate kokapena:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronikoa" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japaniarra" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indiarra" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Erlijio-musika" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Salduenak" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turkiarra" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dantzatzeko" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "balorazioa" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Unibertsitate irratia" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Eztabaidak / Berriak" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasikoa" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatiboa" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Berriak" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Eslaboa" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Greziarra" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotikoa" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_Kate berria" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internet irratia" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Kate berria" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Kuttunak" #: quodlibet/browsers/iradio.py:598 #, fuzzy msgid "No Category" msgstr "Kategoria gabe" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Kate berria" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "_Kate berria" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Ez da katerik aurkitu" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Ez da Intenet irrati katerik topatu %s-en." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Zerrendatutako kate guztiak dagoeneko badaude liburutegian." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "_Gehitu erreprodukzio-zerrendara" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d kate" msgstr[1] "%(count)d kate" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneldun nabigatzailea" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Paneldun nabigatzailea" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Hautatu _denak" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Ezezaguna" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Dena" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Zutabe gehigarriak" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Erreprodukzio-zerrendak" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Erreprodukzio-zerrendak" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Inporatu" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Ezin da erreprodukzio-zerrenda inportatu" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet M3U eta PLS formatuko erreprodukzio-zerrendak bakarrik " "inportatzeko gai da." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Ezabatu fitxategiak" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Be_rrizendatu" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Ezin da erreprodukzio-zerrenda berrizendatu" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Inporatu" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_Sortu erreprodukzio-zerrenda" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" msgstr[1] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Sortu erreprodukzio-zerrenda" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Erreprodukzio-zerrendak" #: quodlibet/browsers/playlists/util.py:34 #, fuzzy, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "<i>%s</i> zerrenda ezabatzera zoaz.\n" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Aukeratutako zerrendari buruzko informazio guztia ezabatzera doa eta\n" "ezin da berreskuratu izango." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Pista" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Sortu erreprodukzio-zerrenda" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Idatzi erreprodukzio-zerrenda berriaren izena:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Erreprodukzio-zerrenda inportatzen.\n" "\n" "%(current)d/%(total)d kanta gehiturik." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Jario berria" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Idatzi audio jarioaren kokapena:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Gehitu fitxategi bat..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "_Freskatu liburutegia" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Bilatu kanta berriak karpeta honetan" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Ezin da jarioa gehitu" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> ezin da gehitu. Zerbitzaria eroria egon liteke edo kokapena ez da " "audio jario bat." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Uneko audio azpiegiturak ez ditu URLak onartzen, audio jario nabigatzailea " "ezgaiturik." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Emaitza muga" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Zatitu hainbat _ baliotan" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Pista zerrenda" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Pista zerrenda" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Paneldun nabigatzailea" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Paneldun nabigatzailea" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Bilatu" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "pistak" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "kokapena" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> ez dago konektaturik." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet ez dago martxan." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "musika liburutegi eta erreproduzigailua" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[aukerak]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Erreproduzitzen den abestia inprimatu eta irten" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Segituan erreproduzitzen hasiko da" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Salto hurrengo abestira" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Salto aurreko abestira, edota, hasieratik gertu balego, berrabiatu" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Salto aurreko abestira" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Hasi erreproduzitzen" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Gelditu erreproduzitzeaz" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Hasi erreproduzitzen" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Igo bolumena" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Beheratu bolumena" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Inprimatu erreproduzigailu egoera" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Ezkutatu leiho nagusia" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Ikusi leiho nagusia" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Txandakatu leiho nagusi ikusgarritasuna" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokoa ipini erreproduzigailua martxan" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Kendu nabigatzaile filtroak" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Freskatu eta liburutegia berrarakatu" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Desgaitu nabigatzailea" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Inprimatu uneko erreprodukzio-zerrenda" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Inprimatu ilararen edukiak" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Inprimatu ilararen edukiak" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Hasi pluginik gabe" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet ez dago martxan." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Itxi Qoud Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Bilatu jotzen ari den anestian" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Errepikapenak gaitu, desgaitu edo txanda" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ezarri bolumena" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Bilatu audio liburutegian" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "bilaketa" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Erreproduzitu fitxategi bat" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "fitxategi-izena" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Bilatu jotzen ari den anestian" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Ezarri nabigatzailea" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Baloratu erreproduzitutako abestia" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Ireki nabigatzaile berri bat" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Erakutsi edo ezkutatu ilara" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Iragazi ausazko balio batez" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "Etiketa" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Iragazi etiketa balio batez" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etiketa=balioa" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Ilaran ipini fitxategi bat edo bilatu" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Ilaran ipini komaz bereiztutako fitxategiak" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "fitxategi-izena" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Erakutsi bilaketaren emaitzen izenak" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Ilaratik kendu fitxategi bat edo bilatu" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "kokapena" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Patroi baliogabea" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumentu baliogabea '%s'-rentzat." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Saiatu %s --help." #: quodlibet/errorreport/ui.py:58 #, fuzzy msgid "An Error Occurred" msgstr "Errore bat gertatu da" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Baztertu errore _guztiak" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "azalpena" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "audio etiketa editorea" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "direktorioa" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Audio etiketa editorea" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz pista IDa" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz pista IDa" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Kodeketa baliogabea]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Titulua" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Audio etiketa editorea" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Titulu-gisako etiketak" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 #, fuzzy msgid "_Human title case" msgstr "Gaitu _gizakizko izenburu larritasuna" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Erabili ingelesezko arau arruntak letra larrientzat, \"Dark Night of the " "Soul\" gisa" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Tamaina guztira:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Editatu bistaratzea" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Tamaina" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 #, fuzzy msgid "_Outline" msgstr "_Irteera kanalizazioa:" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editatu bistaratzea" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Aurreikusi" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informazioa" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Onartutako formatuak: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Iragazi _generoz" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "direktorioa" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Audio jarioak" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "%s: Ezin da media-player-info aurkitu." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Kate berria" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Gorde balorazio eta erreprodukzio _kontaketak" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "grabaketa data" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Errorea %r kargatzean" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Kate berria" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Hobespenak" #: quodlibet/ext/events/automask.py:22 #, fuzzy msgid "Automatic Masking" msgstr "Automati_koa" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 #, fuzzy msgid "Automatic Rating" msgstr "Automati_koa" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Inporatu" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Inporatu" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Baztertu etiketa aldaketak?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Baztertu etiketa aldaketak?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Erreproduzigailua" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Bide patroiak" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Bide patroiak" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 #, fuzzy msgid "Reggae" msgstr "Reggaeton" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 #, fuzzy msgid "Soft Rock" msgstr "Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "Uneko audio azpiegiturak ez ditu URLak onartzen, audio jario nabigatzailea " "ezgaiturik." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "segundo %d" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Berezkoa" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Hautatu" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Aurreikusi" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Personalizatu" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Ezin dira kantak ezabatu" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Patroi baliogabea" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Musika erreproduzigailua" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modeloa:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Internet irratia" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Balorazioa" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Berezkoa" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "kokapena" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Ezkutatu leiho nagusia" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Berezkoa" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "Bide patroiak" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "Bide patroiak" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "kanta %d" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Erregistro irteera" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "Bide patroiak" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Ezin da gailu azpiegiturarekin konektatu." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "kokapena" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz album mota" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "Ize_na:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Titulua" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Ezin da gailu azpiegiturarekin konektatu." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Hurrengoa" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Laster-marka izena" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Ezin da gailu azpiegiturarekin konektatu." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Gailua:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Besteak:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Artista" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Fixategi-izen patroia:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Ausazko Al_buma" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "album" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Tamaina" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Ausazko Al_buma" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 #, fuzzy msgid "Alternative Seek Bar" msgstr "Alternatiboa" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Laster-markak" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Laster-marka izena" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Laster-marka izena" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[aukerak]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "Goraka" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "grabaketa data" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Ezabatu fitxategiak" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Hitzak" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Ezabatu fitxategiak" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Hitzak" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Ez da katerik aurkitu" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Bide patroiak" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Editatu gordetako balioak..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Artista" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Aurreikusi" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Musika erreproduzigailua" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "erakundea" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Hautatu kate berriak" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Hitzak" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Bidea ez da absolutua" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "\t<b>%s</b>\n" "patroiak / du baina ez da errotik hasten. Okerreko izeneko direktorioak " "saihesteko patroia / edo ~/ -rekin hasi behar da." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Ez da abestirik hautatu." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Ez da abestirik hautatu." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Ezin da abestia gorde" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Hitzak" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Ezin dira sarrera fitxategiak ireki" msgstr[1] "Ezin dira sarrera fitxategiak ireki" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Hitzak" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Ez da erreproduzitzen" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "kanta %d" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "Bide patroiak" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Automati_koa" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Ez da erreproduzitzen" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "_Erreprodukzio-zerrendak" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Erreproduzigailua" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "_Aurreikusi" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 #, fuzzy msgid "_Next" msgstr "Hurrengoa" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Ausaz" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "E_rrepikatu" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Gelditu kanta honen ondoren" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Ireki nabigatzaile berri bat" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editatu etiketak" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Information" msgstr "Informazioa" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Erreprodukzio-zerrendak" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Portaera" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Editatu bistaratzea" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Hitzak" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Ez da kanta honen letrarik aurkitu." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Ezin da abestia gorde" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Erroreak" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternatiboa" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Fixategiak" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Aurreikusi" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Iragazi _artistaz" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 #, fuzzy msgid "Default" msgstr "Berezkoa" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Personalizatu" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Personalizatu" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Iragazi _generoz" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Iragazi _artistaz" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio jarioak" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Idatzi audio jarioaren kokapena:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Inporatu" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Ez da katerik aurkitu" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Fixategi-izen patroia:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Ezin da erreprodukzio-zerrenda inportatu" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Fixategi-izen patroia:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, fuzzy, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" msgstr[1] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Sortu erreprodukzio-zerrenda" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "azken erreproduzitua" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "azken erreproduzitua" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Ilaran" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Ilaran" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Ilaran" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Inoiz" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Inoiz" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "taldekatzea" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Ezin dira kantak kopiatu" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Iragazi _generoz" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Etiketa baliogabeak" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Balorea expresio erregularra da (RE)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Gordetako balioak" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Gordetako balioak" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Ezin da gailu azpiegiturarekin konektatu." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "Be_rrizendatu" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Liburutegia" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Debug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Ezkutatu leiho nagusia" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Fitxategi-izena" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Ezin da abestia gorde" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Album zerrenda" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Tamaina" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Bilaketa:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Bilatu" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Album zerrenda" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Editatu laster-markak..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Editatu laster-markak..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Laster-markak" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz album mota" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Fitxategi-izena" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Diskoa" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Titulua" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz album mota" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "bilaketa" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Bilatu" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Ez da pluginik aurkitu." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "kokapena" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Album zerrenda" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Klasikoa" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Album zerrenda" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Ez da pluginik aurkitu." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Aurreikusi" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "komandoa|etiketa" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "Be_rrizendatu" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "komandoa|etiketa" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Inoiz" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Okerreko balioa" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Personalizatu" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Ezin dira kantak kopiatu" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Desgaitu nabigatzailea" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Editatu bistaratzea" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Zatitu _hainbat baliotan" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "Atera irudi txertatuak" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Atera irudi txertatuak" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "Bikoiztuak ezabatu" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "Atera irudi txertatuak" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Iragazi etiketa balio batez" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Iragazi _generoz" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Ilaran" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Idatzi" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz pista IDa" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "direktorioa" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Album goiburuak" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Kate berria" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Ez da pluginik aurkitu." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Mugitzen: %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Errorea %r kargatzean" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Ez dago denbora informaziorik" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Album zerrenda" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Inporatu" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Iragazi _generoz" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Diskoa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Pista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Artista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Jarraitu" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "%s: Ezin da media-player-info aurkitu." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "%s: Ezin da media-player-info aurkitu." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Fitxategi-izena" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "pistak" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Errorea %r kargatzean" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "Be_rrizendatu" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "<b>%s</b> ebazteak huts egin du." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "_Freskatu liburutegia" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "_Freskatu liburutegia" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Editatu etiketak" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Editatu etiketak" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Album guztiak" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Aurreikusi" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etiketa" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Ezin dira kantak ezabatu" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Bilatu" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "Bide patroiak" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Editatu gordetako balioak..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Kolore bil_keta terminoak" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Editatu etiketak" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Bilatu" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Liburutegia" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Muntatze puntuak arakatzen" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Liburutegia arakatzen" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "%s arakatzen" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Liburutegia arakatzen" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Kendu nabigatzaile filtroak" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "musika liburutegi eta erreproduzigailua" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "%r fitxategia kargatzeak huts egin du" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Erakutsi etiketak" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Erakutsi debugarako informazioa" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Zutabeak eta ordena Debugarako moduan (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Ikusi etiketa _programatikoak" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Argumentu nahikorik ez" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 #, fuzzy msgid "Too many arguments" msgstr "Errore gehiegi" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "azalpena" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Balioa" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Erakutsi ohiko etiketak" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopiatu etiketak fitxategi batetik beste batera" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Erakutsi aldaketak, ez ezarri" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Jauzi egin idatzi ezin daitezkeen etiketak" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Ezin da %r %r fitxategira kopiatu" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Audio etiketa editorea" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Ez da abestirik hautatu." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Jarri etiketa bat eta ezabatu aurreko baloreak" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Ezin da %r %r fitxategira kopiatu" #: quodlibet/operon/commands.py:321 #, fuzzy msgid "Remove tags" msgstr "Bikoiztuak ezabatu" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Balorea expresio erregularra da (RE)" #: quodlibet/operon/commands.py:330 #, fuzzy msgid "Remove all tags" msgstr "Bikoiztuak ezabatu" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Ezin da '--all' eta '--regexp' aldi berean erabili" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Ezin da %r %r -tik ezabatu" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Iragazi etiketa balio batez" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Iragazi etiketa balio batez" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Ezin da %r jarri" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Ez dago denbora informaziorik" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "%r fitxategia kargatzeak huts egin du" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "Atera irudi txertatuak" #: quodlibet/operon/commands.py:571 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Atera irudi txertatuak" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Izenaz aldatu etiketeen arabera" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Bete etiketak fitxategiaren helbidearen arabera" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fitxategia" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Bete pista zenbakiak fitxategi guztietan" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Erakutsi emandako patroiarekin bat datozen etiketak" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Erakutsi erabiltze argibide laburpena" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> ez da baliozko kokapen bat." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Ezezaguna" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Ordenean" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Ordenean" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Ausaz" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Ausaz" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "azken erreproduzitua" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "E_rrepikatu" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "E_rrepikatu" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Abesti bat" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Abesti bat" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Buffering" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Ezin da berezko GStreamer pipeline-a sortu." #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Erreprodukziorako erabiltzen den GStreamer kanalizazio 'alsasink " "device=default' gisakoa. Zurian utzi lehenetsitako kanalizaziorako." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Irteera kanalizazioa:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "segundo %d" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buferren iraupena:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Ez da katerik aurkitu" #: quodlibet/player/gstbe/util.py:167 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "GStreamer irteera kanalizazio baliogabea, lehenetsia saiatzen." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Ezin da audio irteera sortu" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Ez da %r audio gailua aurkitu. Aztertu zure Xine ezarpenak ~/.quodlibet/" "config-en." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Ezin da GStreamer pipeline-a lotu: '%s'" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "Ize_na:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Pluginak" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Hasten" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "E/G" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Denbora" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Laster-marka izena" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Laster-markak" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Iragazkia" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Inoiz ez erreproduzituak" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Duela gutxi _gehituak" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 gehien e_rabiliak" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Kate berria" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Ausazko _generoa" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Ausazko _artista" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Ausazko Al_buma" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "Gehien erreproduzitutako 40 abestiak (40 baino gehiago egon litezke " "berdinketarik badago)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "Ize_na:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Balioa:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Gordetako balioak" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Editatu gordetako balioak..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Automati_koa" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "Pis_ta goiburuak" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "_Album goiburuak" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Erreprodukzio bolumen irabazi doitzea" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Ezezaguna" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Gehitu fitxategi bat..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Editatu bistaratzea..." #: quodlibet/qltk/data_editors.py:365 #, fuzzy msgid "Tag expression" msgstr "Balorea expresio erregularra da (RE)" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Iragazi etiketa balio batez" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Balorea expresio erregularra da (RE)" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Fixategiak" #: quodlibet/qltk/delete.py:63 #, fuzzy msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/delete.py:72 #, fuzzy msgid "The selected files will be deleted from disk." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Ezabatu fitxategiak" #: quodlibet/qltk/delete.py:106 #, fuzzy msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/delete.py:115 #, fuzzy msgid "The selected files will be moved to the trash." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mugitu zakarrontzira" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Mugitzen: %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Ezin da iPod datu-basea gorde" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "<b>%s</b> ebazteak huts egin du." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Ezabatzen: %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Ezin da fitxategia ezabatu" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Huts <b>%s</b> ezabatzean." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Nabigatzaileak" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Deskargatu fitxategiak" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "abesti %d-etan falta da" msgstr[1] "%d absetitan falta da" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "desberdina kanta %d-etan" msgstr[1] "desberdina %d kantetan" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Zatitu _hainbat baliotan" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Atera diskoa _albumetik" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Atera _bertsioa izenburutik" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Atera moldatzailea ar_tistatik" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Atera _interpretea atistatik" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Atera _interpretea atistatik" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Atera _bertsioa izenburutik" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Gehitu etiketa bat" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "E_tiketa:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Ikusi etiketa _programatikoak" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Atzitu etiketa guztiak, automatikoki sortuak barne: MusicBrainz edo " "ReplayGain, besteak beste" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Ikusi etiketa _programatikoak" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Inoiz" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Jarraitu" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Editatu etiketak" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Kopiatu _album karatulak" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Ezin da etiketa gehitu" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Ezin dira abestiak gehitu" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Ezin da <b>%s</b> gehitu\n" "\n" "Unean hautatutako fitxategiak ez ditu balio anitz onartzen." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Okerreko etiketa" msgstr[1] "Okerreko etiketa" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "<b>%s</b> okerreko etiketa\n" "\n" "Unean hautatutako fitxategiak ez du ha editatzea onartzen." msgstr[1] "" "<b>%s</b> okerreko etiketa\n" "\n" "Unean hautatutako fitxategiak ez du ha editatzea onartzen." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Okerreko balioa" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Okerreko balioa: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Etiketa ez zehatza izatea liteke" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> aldatu egin da programa martxan zegoela. Liburutegia freskatu gabe " "gordetzeak abestiaren beste aldaketa batzuk gainidatzi ditzake.\n" "\n" "Gorde abesti hau hala ere?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Ezin da abestia gorde" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Huts <b>%s</b> gordetzean. Fitxategia irakurketa soilekoa izan daiteke, " "hondaturik egon edo zuk berau editatzeko baimenik ez izatea izan liteke." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Aukera gehiago..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Pluginak" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s eta %(count)d gehiago" msgstr[1] "%(title)s eta %(count)d gehiago" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso hobespenak" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Karpetak" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Sortu karpeta" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "__Hautatu azpikarpeta guztiak" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Sortu karpeta" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Idatzi izen bat karpeta berriarentzat:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Ezinda karpeta sortu" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Ezin da karpeta ezabatu" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Abestiak" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "%s -ez" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "%s diskoa" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "%s pista" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Editatu bistaratzea" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ez da abestirik hautatu." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Abestirik ez" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informazioa" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Hitzak" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "%s-ek sortua" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistak" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "interpreteak" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Inoiz" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d-etan" msgstr[1] "%(n)d aldiz" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "gehiturik" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "azken erreproduzitua" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "erreproduzitzen" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "salto" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "balorazioa" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "iraupena" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Informazioa" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "Goraka" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bit-tasa" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "fitxategi tamaina" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "eraldatua" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d hautatua" msgstr[1] "%d hautatuak" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Pista erabilezina" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "kanta %d album gabe" msgstr[1] "%d kanta album gabe" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Hautatu diskografia" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "abesti %d artista gabe" msgstr[1] "%d abesti artista gabe" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Iraupena guztira:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Tamaina guztira:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Fixategiak" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Ez da kanta honen letrarik aurkitu." #: quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" #: quodlibet/qltk/maskedbox.py:21 #, fuzzy msgid "The selected songs will be removed from the library." msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Baztertu etiketa aldaketak?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Etiketak aldatu egin dira baina ez gorde. Fitxategi hauek gorde edo atzera " "egin eta aldaketa baztertu?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Inoiz" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Fitxategia badago" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Berrizendatu fitxategiak" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Lan aktiboak" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "Lan aktiboak: %d" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Ordena:" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Etiketa editatzea" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "Be_rrizendatu" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "bilaketa" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Tamaina guztira:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plugin erroreak" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Gaitua" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Desgaitua" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Kategoria gabe" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Kategoria gabe" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Ez da pluginik aurkitu." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Pluginak" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Ikusi erroreak" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Diskoa" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Pista" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "taldekatzea" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artista" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_buma" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Fitxategi-izena" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Iraupena" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Salto erreproduzitzen den abestira automatikoki" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Erreproduzitzen ari den abestia aldatzean, joan abesti zerrendan uneko " "abestiraino" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Besteak:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Editatu bistaratzea..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Gehitu edo ezabatu informazio gehigarriko zutabeak" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Zutabe ikusgarriak" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Izenburuak bertsioa barneratzen du" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albumak _disko azpititulua barneratzen du" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Sarezko _bilaketa jendea barneratuz" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Fitxategi-izenak _karpeta barneratzen du" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Hobespenak" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Zutabe gehigarriak" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Ezarri oraingo konfigurazioa zerrendari, zutabe berriak bukaeran jarriz" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Abesti zerrenda" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Zutabe gehigarriak" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Iragazki na_gusia:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Ezarri bilaketa hau besteei gehituz" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Bilatu" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Nabigatzaileak" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Berretsi balorazio a_nitz" #: quodlibet/qltk/prefs.py:314 #, fuzzy msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Berrespena eskatu abesti anitzen balorazioa batera aldatu aurretik" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Gaitu klik-bakarreko balorazioak" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "Balorazio gaitu abesti zerrendak balorazio zutabea klikatuaz" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Balorazioak" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Hobetsi album arte lan _txertatuak" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "Aukeratu album arte lan txertatuak hobestea, dagoenean" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Ezarritako irudiaren izena:" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Album zerrenda" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Gelditu erreproduzitzeaz" #: quodlibet/qltk/prefs.py:400 #, fuzzy msgid "Output Configuration" msgstr "Erregistro irteera" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ez badago erreprodukzio argibiderik kanta batentzat, bidertu bolumena balio " "hau erabiliaz" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Lehenetsiriko irabazia (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Biderkatu abesti guztien bolumena balio honez, beti mozketak sortzen ez " "baditu" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Aurre-amp irabazia (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Gaitu erreprodukzio irabazte bolumen doitzea" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Erreprodukzio bolumen irabazi doitzea" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 #, fuzzy msgid "_Default rating:" msgstr "Berezkoa" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Balorazioak" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Erantsitako balorazioa osatzeko Batezbesteko Bayesianaren faktorea (C).\n" "0k ohiko batezbesteko esan nahi du, balore handiagok esan nahi dute \n" "pista gutxiko albumek puntuazio estremo gutxiago izango dutela.\n" "Balore hau aldatutakoan, album guztientzat birkalkulatzea abiaraziko da." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Batezbesteko Bayesianaren kopurua:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Eposta:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Balorazio eta erreprodukzio kontuak ezarriko dira posta helbide honentzat" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Baztertu etiketa aldaketak?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Gorde aldaketak baiespen indibidualarik eskatu gabe fitxategi asko editatzen " "denean" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Etiketatik baloreak bereizterakoan erabil daitezkeen bereizle zerrenda " "(komaz bereiztuta)." #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Zati_tu:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Etiketatik baloreak bereizterakoan erabil daitezkeen bereizle zerrenda " "(komaz bereiztuta)." #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Zati_tu:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Editatu etiketak" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Etiketa editatzea" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Kate berria" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Bilatu liburutegia" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Aztertu zure liburutegiko aldaketak" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Birkargatu _liburutegia" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Birkargatu liburutegiko kanta guztiak (denbora luzea har lezake)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Abestirik ez" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "F_reskatu liburutegia abiaraztean" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Arakatu _direktorioak" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s eta %(count)d gehiago" msgstr[1] "%(title)s eta %(count)d gehiago" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Propietateak" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Ilara" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Garbitu errorea" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Orokorra" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Kendu ilarako abesti guztiak" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modeloa:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "kanta %(count)d (%(time)s)" msgstr[1] "%(count)d kanta (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Arakatu liburutegia" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Txandakatu leiho nagusi ikusgarritasuna" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Gelditu erreproduzitzeaz" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Hautatu direktorioak" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Ezin dira abestiak gehitu" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b>k onartzen ez den protokolo bat erabiltzen du." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Salto erreproduzitzen den abestira" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Fitxategia" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Abestiak" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Ikusi" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Nabigatzaileak" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Kontrola" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Laguntza" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Gehitu karpeta bat..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Gehitu fitxategi bat..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Gehitu kokapena" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editatu laster-markak..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Gelditu kanta honen ondoren" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Laguntza sarean" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Bilatu" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Gehitu kokapena" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Idatzi audio fitxategiaren kokapena:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Ezin da kokapena gehitu" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> ez da baliozko kokapen bat." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Gehitu musika" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Gehitu karpeta bat..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Musika erreproduzigailua" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Gehitu fitxategi bat..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" msgstr[1] "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Ilara" #: quodlibet/qltk/ratingsmenu.py:26 #, fuzzy, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "%d abestiren balorazioa aldatzera zoaz.\n" "Jarraitu nahi duzu?" #: quodlibet/qltk/ratingsmenu.py:29 #, fuzzy msgid "The saved ratings will be removed" msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "Bikoiztuak ezabatu" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Hautatuko %d abestien balorazioa '%s'-ra aldatuko da" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Balorazioa" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Ordeztu zuriuneak a_zpimarrez" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Kendu windows-ekin bateragarriak ez diren karaktereak" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Kendu marka _diakritikoak" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Kendu ASCII ez diren karaktereak" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Erabili letra _xeheak bakarrik" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Berrizendatu fitxategiak" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Aurreikusi" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Fitxategi-izena" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "album artista" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Kendu erabili gabeko karatula eta direktorioak" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Album zerrenda" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Izen berria" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Ezin da fitxategia berrizendatu" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Huts <b>%s</b> <b>%s</b>-ra berrizendatzean. Ziurrenik edo helburua " "fixtategi badago dagoeneko edo ez duzu baimenik fitxategi berria sortu edo " "zaharra kentzeko." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Baztertu errore _guztiak" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Jarraitu" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Bidea ez da absolutua" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "\t<b>%s</b>\n" "patroiak / du baina ez da errotik hasten. Okerreko izeneko direktorioak " "saihesteko patroia / edo ~/ -rekin hasi behar da." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Karpeta hauetan kokatutako abestiak (':' erabiliaz bereziak) zure " "liburutegira gehituko dira" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "iPod pista umezurtzak kentzen" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Liburutegia" msgstr[1] "Liburutegia" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "Bikoiztuak ezabatu" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Hautatu direktorioak" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Hautatu direktorioak" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Gordetako balioak" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Editatu gordetako balioak..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Bilatu zure bilduman, testua edo QL bilaketak erabiliz" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Bilatu ida_tzi ondoren" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" "Bistarazi bilaketa emaitzak erabiltzaileak tekleatzeari utzi bezain laster" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Muga:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Tamaina" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "bilaketa" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Bistarazi faltako denbora" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Hitzak" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Fokoa ipini erreproduzigailua martxan" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Bilatu jotzen ari den anestian" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Ezin dira kantak ezabatu" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Ezin dira kantak ezabatu" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 #, fuzzy msgid "Expands the element" msgstr "Zutabe gehigarriak" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Iragazi %s-ez" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "_Album goiburuak" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Pis_ta goiburuak" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Album goiburuak" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Pertsona goiburuak" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Data goiburuak" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_fixategi goiburuak" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "P_rodukzio goiburuak" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Pertsonalizatu goiburuak..." #: quodlibet/qltk/songlist.py:1219 #, fuzzy msgid "_Expand Column" msgstr "Zutabe gehigarriak" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Kolore bil_keta terminoak" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Gehitu _ilarara" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Kendu erreprodukzio-zerrendatik" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Ezin da fitxategia ezabatu" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Deskargatu" msgstr[1] "_Deskargatu" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Bilatu" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Deskargatu fitxategia" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Album zerrenda" msgstr[1] "Album zerrenda" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Deskargatu fitxategia" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Ordeztu azpimarrak zuriunez" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Titulu-gisako etiketak" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Zatitu hainbat _ baliotan" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etiketak bidetik" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Etiketak daudenak ordezkatzen dituzte" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Etiketak daudenei gehituko zaizkie" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "\t<b>%s</b>\n" "patroia baliogabea da. Baliteke etiketa berdina bi aldiz edukitzea edo itxi " "gabeko parentesiak ditu (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Sartutako patroia baliogabea da. Ziuratu < eta > \\< eta \\> " "gisa sartu dituzula eta etiketak parekatuak daudela.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Editatu bistaratzea" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Pista zenbakiak" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Hasi he_mendik:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Pista _guztira:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Erreproduzigailua" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "_Aurreikusi" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "eta %d gehiago..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Aldatu dituzun abestiak gordetzen." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d abesti gordeak\n" "(%(remaining)s falta dira)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Mugitzen: %(current)d/%(total)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Muntatze puntuak arakatzen" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "kokapena" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Inportatu erreprodukzio-zerrenda" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Badago %s izeneko erreprodukzio-zerrenda bat." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Ikusi album _karatulak" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Fitxategi sistema" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Tamaina guztira:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Erakutsi erabiltze argibide laburpena" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Bertsio eta kopia-eskubideak bistarazi" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Ez dago denbora informaziorik" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[aukerak]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Ez da %r aukera ezagutzen." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "%r aukerak argumentu bat behar du." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r ez da aurrizki bakana." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "segundo %d" msgstr[1] "%d segundo" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Ez dago denbora informaziorik" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "segundo %d" msgstr[1] "%d segundo" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "minutu %d" msgstr[1] "%d minutu" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "ordu %d" msgstr[1] "%d ordu" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "egun %d" msgstr[1] "%d egun" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "urte %d" msgstr[1] "%d urte" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "Lehen hizkia larriz hitz bakoitzean?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Data 'UUUU', 'UUUU-HH-EE' edo 'UUUU-HH-EE OO:MM:SS' formatuan sartu behar da." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Erreprodukzio irabazia 'x.yy dB' formatuan idatzi behar da." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Erreprodukzio irabazi gailurra 'x.yy' formatuan sartu behar da." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDak UUID formatuan izan behar dira." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz argitaratze egoera 'official', 'promotional', edo 'bootleg' izan " "behar da." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Hizkuntzak ISO 639-2tik hiru letratako kodea izan behar du" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "<b>%s</b> ebazteak huts egin du." msgstr[1] "<b>%s</b> ebazteak huts egin du." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Ezin da abestia editatu" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Huts <b>%s</b> gordetzean. Fitxategia irakurketa soilekoa izan daiteke, " "hondaturik egon edo zuk berau editatzeko baimenik ez izatea izan liteke." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Kodeketa baliogabea]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "albuma" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "Moldatzailea" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "moldatzaileak" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "Moldatzailea" #: quodlibet/util/tags.py:86 msgid "author" msgstr "egilea" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "egileak" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "komandoa|etiketa" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "konposatzailea" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "konposatzaileak" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "konposatzailea" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "gidaria" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "gidariak" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "gidaria" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontaktua" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "Copyright-a" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "azalpena" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "generoa" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "generoa" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "interpretea" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "interpretea" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "taldekatzea" #: quodlibet/util/tags.py:98 msgid "language" msgstr "hizkuntza" #: quodlibet/util/tags.py:99 msgid "license" msgstr "lizentzia" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "idazlea" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "Idazleak" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "idazlea" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "erakundea" #: quodlibet/util/tags.py:104 msgid "title" msgstr "izenburua" #: quodlibet/util/tags.py:105 msgid "version" msgstr "bertsioa" #: quodlibet/util/tags.py:106 msgid "website" msgstr "webgunea" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "album artista" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "disko azpititulua" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "diskoa" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "pista" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "etiketa IDa" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "jatorrizko argitaratze data" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "jatorrizko albuma" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "jatorrizko artista" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "grabaketa data" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "argitaratzen nazioa" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz pista IDa" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz argitaratze IDa" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz argitaratze IDa" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "Musicbrainz artista IDa" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz argitaratze IDa" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM IDa" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz album egoera" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz album mota" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz argitaratze IDa" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "Pistaren irabazpena" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "Pistaren erpina" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "Albumaren irabazpena" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "Albumaren gailurra" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "erreferentzia ozena" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diskoak" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "pistak" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "azken abiarazia" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "Izen osoa" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "muntatze puntua" #: quodlibet/util/tags.py:166 msgid "people" msgstr "jendea" #: quodlibet/util/tags.py:168 msgid "year" msgstr "urtea" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "jatorrizko argitaratze data" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "laster-marka" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "Ez dago denbora informaziorik" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Erreprodukzio-zerrendak" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Audio etiketa editorea" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Editatu zure audio fitxategietako etiketak" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musika erreproduzigailua" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Entzun, arakatu edo editatu zure audio bilduma" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Inportatu erreprodukzio-zerrenda" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Ezin da abestia gehitu" #~ msgid "Invalid tags" #~ msgstr "Etiketa baliogabeak" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "<b>%s</b> etiketa baliogabeak\n" #~ "\n" #~ "Hautatutako fitxategiek ez dute onartzen etiketa hauek ezabatzea." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "segundo %d" #, fuzzy #~ msgid "Startup" #~ msgstr "_Inporatu" #~ msgid "Audio Feeds" #~ msgstr "Audio jarioak" #~ msgid "_Audio Feeds" #~ msgstr "_Audio jarioak" #, fuzzy #~ msgid "New" #~ msgstr "Berriak" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Letrak bilatzen..." #, fuzzy #~ msgid "<artist>" #~ msgstr "artista" #, fuzzy #~ msgid "<album>" #~ msgstr "albuma" #, fuzzy #~ msgid "<title>" #~ msgstr "izenburua" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Inportatu erreprodukzio-zerrenda" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Inportatu erreprodukzio-zerrenda" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informazioa" #~ msgid "Unsupported file type" #~ msgstr "Onartzen ez den fitxategi mota" #~ msgid "Unable to add station" #~ msgstr "Ezin da katea gehitu" #~ msgid "Device Properties" #~ msgstr "Gailu propietateak" #~ msgid "Device:" #~ msgstr "Gailua:" #~ msgid "Not mounted" #~ msgstr "Ez dago muntaturik" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Muntatze puntua:" #~ msgid "Media Devices" #~ msgstr "Medio gailuak" #~ msgid "_Media Devices" #~ msgstr "_Medio gailuak" #~ msgid "_Eject" #~ msgstr "_Ebatzi" #, fuzzy #~ msgid "_Properties" #~ msgstr "Propietateak" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> erabilia, <b>%s</b> erabilgarri" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "<b>%(song)s</b> kopiatzen" #~ msgid "Unable to copy song" #~ msgstr "Ezin da kanta kopiatu" #~ msgid "There is not enough free space for this song." #~ msgstr "Ez kanta honentzako behar aina leku." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> ezin izan da kopiatu." #~ msgid "Unable to delete songs" #~ msgstr "Ezin dira kantak ezabatu" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "<b>%(song)s</b> ezabatzen" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> ezin izan da ezabatu." #~ msgid "Unable to delete song" #~ msgstr "Ezin da abestiak ezabatu" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "<b>%s</b> ebazteak huts egin du." #~ msgid "Unable to eject device" #~ msgstr "Ezin da gailua ebatzi" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Ez dago gailu azpiegiturarik, media gailu nabigatzailea desgaiturik." #~ msgid "Search Library" #~ msgstr "Bilatu liburutegia" #~ msgid "_Search Library" #~ msgstr "_Bilatu liburutegia" #~ msgid "Rate the playing song" #~ msgstr "Baloratu erreproduzitutako abestia" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Erakutsi edo ezkutatu kanten zerrenda nagusia" #~ msgid "Unknown Device" #~ msgstr "Gailu ezezaguna" #, fuzzy #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Ezin da dbus-python inportatu, beharrezkoa da gailu euskarriarentzat." #~ msgid "%r is not a supported device." #~ msgstr "%r ez da onartzen den gailu bat." #~ msgid "Initializing device backend." #~ msgstr "Gailu azpiegitura abiarazten." #~ msgid "Trying '%s'" #~ msgstr "'%s' saiatzen" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Ezin da gailu azpiegiturarekin konektatu." #~ msgid "Device backend initialized." #~ msgstr "Gailu azpiegitura abiarazia." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Fixategi-izen patroia:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Garbitu errorea" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Hitzak" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Garbitu bilaketa" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Hitzak" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Hitzak" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Abestirik ez" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Nabigatzaileak" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Ezinda karpeta sortu" #~ msgid "Audio device: %s" #~ msgstr "Audio gailua: %s" #~ msgid "Downloads" #~ msgstr "Deskargak" #~ msgid "Size" #~ msgstr "Tamaina" #~ msgid "_Download" #~ msgstr "_Deskargatu" #, fuzzy #~ msgid "The single image filename to use if selected" #~ msgstr "Album arte lanaren irudia erabiltzeko, izena ezartzen denean" #~ msgid "The album art image file to use when forced" #~ msgstr "Album arte lanaren irudia erabiltzeko, izena ezartzen denean" #~ msgid "_Copy to Device" #~ msgstr "_Kopiatu gailura" #, fuzzy #~ msgid "browsers" #~ msgstr "Nabigatzaileak" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Ezin da python-feedparser inportatu, audio jario nabigatzaile desgaiturik." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Salbuespen bat gertatu da Quod Libet-en. Iraulketa fitxategi bat gorde da " #~ "<b>%s</b>-en zuri kraskatzea arazten laguntzeko. Mesedez ireki programa- " #~ "errore txostena at http://code.google.com/p/quodlibet/issues/list gunean " #~ "eta erantsi fitxategia edo bertako edukia. Fitxategi honek zure sistema " #~ "ezagutagarri egin dezakeen informazioa izan dezake, azken " #~ "erreproduzitutako abestiak adibidez. Hau onartezina bada bidali <b>%s</b> " #~ "zer egiten ari zinen azalpenarekin.." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "QuodLibet ezegonkor egon liteke. Itxi eta berriz irekitzea gomendatzen " #~ "da. \n" #~ "Bilduma gordea izango da." #~ msgid "Unable to download lyrics." #~ msgstr "Ezin dira letrak deskargatu." #~ msgid "Set or toggle the playback order" #~ msgstr "Ezarri edo txandakatu erreprodukzio ordena" #~ msgid "Uninitialized iPod" #~ msgstr "Hasieratu-gabeko iPoda" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Data-base huts bat sortu nahi al duzu iPod honentzat?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Bolumen irabazia (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Nahasi etiketak balio a_nitzekin" #~ msgid "Capacity:" #~ msgstr "Kapazitatea:" #~ msgid "Firmware:" #~ msgstr "Firmwarea:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Ezin da iPod datu-basea gorde" #~ msgid "Unable to save iPod database" #~ msgstr "Ezin da iPod datu-basea gorde" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Ezin da python-gpod inporatu, iPod euskarria desgaitua." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "Pistaren erpina" #~ msgid "Shuffle" #~ msgstr "Ausaz" #~ msgid "Weighted" #~ msgstr "Iraupena" #~ msgid "_Weighted" #~ msgstr "_Iraupena" #~ msgid "_One Song" #~ msgstr "_Abesti bat" #~ msgid "Restart the playlist when finished" #~ msgstr "Berriz hasi erreprodukzio-zerrenda amaitzean" #~ msgid "Disable Browser" #~ msgstr "Desgaitu nabigatzailea" #~ msgid "_Disable Browser" #~ msgstr "_Desgaitu nabigatzailea" #, fuzzy #~ msgid "Force Write" #~ msgstr "Idatzi" #~ msgid "Filter on _Genre" #~ msgstr "Iragazi _generoz" #~ msgid "Filter on _Artist" #~ msgstr "Iragazi _artistaz" #~ msgid "Filter on Al_bum" #~ msgstr "Iragazi al_bumez" #~ msgid "_Music" #~ msgstr "_Musika" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Laster-markak" #~ msgid "Song _List" #~ msgstr "Abesti _zerrenda" #, fuzzy #~ msgid "D:" #~ msgstr "W: " #, fuzzy #~ msgid "W:" #~ msgstr "W: " #, fuzzy #~ msgid "E:" #~ msgstr "E: " #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Gelditu kanta honen ondoren" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "eta %d gehiago..." #~ msgstr[1] "eta %d gehiago..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Atera diskoa _albumetik" #, fuzzy #~ msgid "Timeout" #~ msgstr "Denbora" #, fuzzy #~ msgid "Select an album" #~ msgstr "Hautatu _denak" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s eta %(count)d gehiago" #~ msgstr[1] "%(title)s eta %(count)d gehiago" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Erreprodukzio-zerrendak" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Erabili borobildutako ertzak argazkitxoentzat" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Borobildu album arte-lan argazkitxo irudiaren ertzak. Berrabiarazte behar " #~ "dezake eragin izateko." #~ msgid "Re_fresh Library" #~ msgstr "_Freskatu liburutegia" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Bikoiztuak ezabatu" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "Gstreamer-ek ez du irakurritako fitxategiak kudeatzeko elementurik. " #~ "Aztertu zure Gstreamer instalazio ezarpenak." #~ msgid "Invalid audio backend" #~ msgstr "Audio azpiegitura baliogabea" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "%r audio azpiegitura ez dago instalaturik." #~ msgid "ql-save" #~ msgstr "Gorde" #, fuzzy #~ msgid "ql-revert" #~ msgstr "E_zabatu bilduma" #~ msgid "Print all tags to stdout" #~ msgstr "Erakutsi etiketa guztiak irteera estandarrean" #~ msgid "Load tags dumped with 'dump'" #~ msgstr "Kargatu 'dump'-ek jaurkitako etiketak" #~ msgid "command|filename" #~ msgstr "komandoa|fixtategi-izena" #~ msgid "command|tag" #~ msgstr "komandoa|etiketa" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Ezin da media-player-info aurkitu." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Bilatu" #~ msgid "%d of %d" #~ msgstr "%d %d-tik" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Erabilera: %s %s" #~ msgid "_Download..." #~ msgstr "_Deskargak..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Kate berria" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Gainidatzi <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Irteera erroreak" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Ezin izan da GStreamer irteera kanalizazioa abiatu.Kanalizazioa baliogaea " #~ "izanda daiteke edo gailua erabilita egon. Aztertu erreproduzigailu " #~ "ezarpenak." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet martxan dago." #~ msgid "No song is currently playing." #~ msgstr "Ez dago abestirik erreproduzitzen." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Ezin da %s-en idatzi. Ezabatzen." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Editatu laster-markak..." #~ msgid "_New Folder..." #~ msgstr "_Sortu karpeta..." #~ msgid "_Add to Playlist" #~ msgstr "_Gehitu erreprodukzio-zerrendara" #~ msgid "_Edit Display..." #~ msgstr "_Editatu bistaratzea..." #~ msgid "Output Log" #~ msgstr "Erregistro irteera" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d kate" #~ msgid "_Add a Location..." #~ msgstr "_Gehitu kokapen bat..." #~ msgid "_Output Log" #~ msgstr "_Irteera erregistroa" #~ msgid "Invalid command %r received." #~ msgstr "%r komando baliogabea jasoa." #~ msgid "Unknown browser %r." #~ msgstr "%r nabigatzaile ezezaguna." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Pertsonalizatu goiburuak..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #~ msgstr[1] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #~ msgstr[1] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "Pis_ta goiburuak" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Pertsona goiburuak" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Album goiburuak" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Data goiburuak" #, fuzzy #~ msgid "File Headers" #~ msgstr "_fixategi goiburuak" #, fuzzy #~ msgid "Production Headers" #~ msgstr "P_rodukzio goiburuak" #, fuzzy #~ msgid "Tag:" #~ msgstr "E_tiketa:" #~ msgid "Descending" #~ msgstr "Beheraka" #~ msgid "Too Many Errors" #~ msgstr "Errore gehiegi" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Errenkada batean %d errore daudelako erreprodukzioa gelditzen." #~ msgid "Warnings" #~ msgstr "Abisuak" #~ msgid "No log available." #~ msgstr "Erregistrurik gabe." #~ msgid "album artist (sort)" #~ msgstr "album artista (ordenatu)" #~ msgid "artist (sort)" #~ msgstr "artista (ordenatu)" #~ msgid "album (sort)" #~ msgstr "album (ordenatu)" #~ msgid "performer (sort)" #~ msgstr "interpretea (ordenatu)" #~ msgid "performers (sort)" #~ msgstr "interpreteak (ordenatu)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artista IDa" #~ msgid "errors" #~ msgstr "erroreak" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Album arte-lan \"%s\" irakurteak huts egin du" #~ msgid "Permanently delete this file?" #~ msgstr "Betirako ezabatu fitxategi hau?" #~ msgid "Permanently delete these files?" #~ msgstr "Betirako ezabatu fitxategi hauek?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s eta %(count)d gehiago..." #~ msgstr[1] "%(title)s eta %(count)d gehiago..." #, fuzzy #~ msgid "Version:" #~ msgstr "bertsioa" #~ msgid "_Cause an Error" #~ msgstr "E_rrore bat sortzen du" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s ezin da liburutegian gehitu.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "%r komando exekutatzeak huts egin du, %r dela eta." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%s</b> that will help us debug the crash. Please file a new issue at " #~ "http://code.google.com/p/quodlibet/issues /list and attach this file or " #~ "include its contents. This file may contain some identifying information " #~ "about you or your system, such as a list of recent files played. If this " #~ "is unacceptable, send <b>% s</b> instead with a description of whatyou " #~ "were doing." #~ msgstr "" #~ "Salbuespen bat gertatu da Quod Libet-en. Iraulketa fitxategi bat gorde da " #~ "<b>%s</b>-en zuri kraskatzea arazten laguntzeko. Mesedez ireki programa- " #~ "errore txostena at http://code.google.com/p/quodlibet/issues/list gunean " #~ "eta erantsi fitxategia edo bertako edukia. Fitxategi honek zure sistema " #~ "ezagutagarri egin dezakeen informazioa izan dezake, azken " #~ "erreproduzitutako abestiak adibidez. Hau onartezina bada bidali <b>%s</b> " #~ "zer egiten ari zinen azalpenarekin..\n" #~ "\n" #~ "Quod Libet erabilezina egon liteke.Itxi eta berriz irekitzea gomendatzen " #~ "da. Zure liburutegia gordea izango da." #~ msgid "Could not import python-gpod, iPod support disabled." #~ msgstr "Ezin da python-gpod inporatu, iPod euskarria desgaitua." #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Irteera kanalizazioa:" #~ msgid "Search your library" #~ msgstr "Bilatu zure liburutegian" #~ msgid "No eject command found." #~ msgstr "Ez da ebazpen komandorik aurkitu." #~ msgid "Unable to start web browser" #~ msgstr "Ezinda web nabigatzaile abiarazi" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Ezin da nabigatzailerik aurkitu. Mesedez ezarri $BROWSER aldagaia, edo " #~ "ziurtatu /usr/bin/sensible-browser egotea." #, fuzzy #~ msgid "Library Error" #~ msgstr "Liburutegi nabigatzailea" #~ msgid "translator-credits" #~ msgstr "Piarres Beobide <pi@beobide.net>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Bistaratzeko beste zutabeak, zuriunez bereizirik" #~ msgid "_Edit and Continue" #~ msgstr "_Editatu eta jarraitu" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #~ msgstr[1] "" #~ "%d abestiren balorazioa aldatzera zoaz.\n" #~ "Jarraitu nahi duzu?" #~ msgid "Confirm rating" #~ msgstr "Berretsi balorazioa" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, eta beste zenbait\n" #~ "\n" #~ "Hau software librea da, kopiatze baldintzak ikusteko begiratu iturburuan. " #~ "EZ dago bermerik \n" #~ "ezta MERKATARITZA edo ERABILERA warranty; not even for MERCHANTABILITY or " #~ "FITNESS FOR A PARTICULAR PURPOSE.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r-ek ez du nabigatzailerik." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Tamaina guztira:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r-ek ez du gailurik." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: Ezin da ctypes inportatu." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Ezin da media-player-info aurkitu." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: Ezin da media-player-info aurkitu." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet pluginak" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Bistarazi bilaketa arruntak urdinez, hedatutakoak berdez eta baliogabeak " #~ "gorriz" #~ msgid "Separators for splitting tags" #~ msgstr "Bereizleak zatitutako etiketentzat" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet hobespenak" #~ msgid "Not Played To_day" #~ msgstr "_Gaur erreproduzitu gabe" #~ msgid "Not Played in a _Week" #~ msgstr "_Aste batean erreproduzitu gabe" #~ msgid "Not Played in a _Month" #~ msgstr "_Hilabete batean erreproduzitu gabe" #~ msgid "B_ottom 40" #~ msgstr "40 gutxien era_biliak" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "Azken erreproduzitutako 40 abestiak (40 baino gehiago egon litezke " #~ "berdinketarik badago)" #~ msgid "gtk-media-next" #~ msgstr "_Hurrengoa" #~ msgid "gtk-media-previous" #~ msgstr "_Aurrekoa" #~ msgid "gtk-media-play" #~ msgstr "_Erreproduzitu" #~ msgid "gtk-media-pause" #~ msgstr "_Gelditu" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | kontrol ]" #~ msgid "Date" #~ msgstr "Data" #~ msgid "Add" #~ msgstr "Gehitu" #~ msgid "Bitrate" #~ msgstr "Bit-tasa" #~ msgid "_Stations..." #~ msgstr "Ka_teak..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Audio azpiegitura abiarazten (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Liburutegi nagusia hasieratzen (%s)" #~ msgid "Unable to save library" #~ msgstr "Ezin da liburutegia gorde" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "Ezin izan da %r audio irteera kanalizazioa sortu. Aztertu zure GStreamer " #~ "ezarpenak ~/.quodlibet/config-en." ������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/fi.po����������������������������������������������������������������������������0000644�0001750�0001750�00000774314�14470736246�013614� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Finnish translation of Quod Libet. # Copyright (C) 2005-2007 Joe Wreschnig, Michael Urman & others # This file is distributed under the same license as the Quod Libet package. # Jari Rahkonen <jari.rahkonen@pp1.inet.fi>, 2005-2007. # Kristian Laakkonen, 2017. # # msgid "" msgstr "" "Project-Id-Version: quodlibet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-07-06 12:50+0000\n" "Last-Translator: Kristian Laakkonen <kristian.laakkonen@gmail.com>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/fi/>\n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 5.0-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Nimi" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Tekijät" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Päivämäärä" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "L_isäyspäivämäärä" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "A_lkuperäinen päivämäärä" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Tyylilaji" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "Ar_vosana" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "Toistokertojen _määrä" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "_Järjestä…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Asetukset" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumilista" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumilista" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Kaikki albumit" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albumi" msgstr[1] "%d albumia" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Lataa albumin _kansi uudelleen" msgstr[1] "Lataa albumin kanne_t uudelleen" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Kappaleet, jotka eivät ole millään albumilla" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d raita" msgstr[1] "%d raitaa" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d levy" msgstr[1] "%d levyä" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Esimerkkialbumi" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albumilistan asetukset" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Näytä albumien _kannet" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Sisäinen _haku hakee myös tekijänimistä" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Valinnat" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albuminäkymä" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Sulje" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Kirjaston selain" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d kappale" msgstr[1] "%d kappaletta" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Virheellinen hakukaava" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumikokoelma" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Albumi_kokoelma" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Tuntematon %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Useita %s-arvoja" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Mukautettu" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Lisää" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Poista" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tunniste" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Yhdistä" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Albumikokoelman asetukset" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Käytä" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Peruuta" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Albumiruudukko" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "Albumi_ruudukko" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Albumiruudukon asetukset" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Näytä albumien kuvaukset" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Näytä ”Kaikki albumit” -valinta" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Leveä tila" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Kansikuvan koko" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Tiedostojärjestelmä" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "Tie_dostojärjestelmä" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Kappaleiden kopiointi epäonnistui" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Valittuja tiedostoja ei voi kopioida toisiin kappalelistoihin tai jonoon." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Lisää kirjastoon" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Asemalistat voivat sisältää ainoastaan asemien sijainteja, ei toisia " "asemalistoja tai soittolistoja. Seuraavien sijaintien avaaminen ei " "onnistunut:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet-radio" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Lisää asemia" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Ladataan asemalistaa" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Uusi asema" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Anna Internet-radioaseman sijainti:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektroninen" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Klassikot" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japanilainen" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Intialainen" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Uskonnollinen" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Listamusiikki" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turkkilainen" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latino" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Kampusradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Puhe / Uutiset" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassinen" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metalli" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Uutiset" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Iskelmä" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slaavilainen" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Kreikkalainen" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Goottilainen" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Ladataanko lista suosituista radioasemista?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Lataa asemat" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "I_nternet-radio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Kaikki asemat" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Suosikit" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Ei luokkaa" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Lisää asema…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Päivitä asemat" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Asemia ei löytynyt" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Internet-radioasemia ei löytynyt sijainnista %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Ei lisättävää" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Kaikki luetellut asemat ovat jo kirjastossasi." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "_Lisää suosikkeihin" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "_Poista suosikeista" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d asema" msgstr[1] "%(count)d asemaa" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneeliselain" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Paneeliselain" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Näytä _kaikki" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Tuntematon" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Kaikki" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Pieni" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Leveä" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Sarakkeittainen" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Tunnistekaava, joka voi sisältää muotoiluja, esim. <tt>composer</tt> tai\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Paneeliselaimen asetukset" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Paneelien sijoittelu" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Paneelien sisältö" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Samanlevyiset paneelit" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Soittolistat" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Soittolistat" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Poista soittolistalta" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Uusi" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Tuo…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Soittolistan tuonti ei onnistu" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet voi tuoda vain M3U/M3U8- ja PLS-muotoisia soittolistoja." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Poista" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Nimeä uudelleen" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Soittolistan uudelleennimeäminen ei onnistu" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Tuo soittolista" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Tuo" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Uusi soittolista…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Mitä haluat tehdä tälle %d kappaleelle?" msgstr[1] "Mitä haluat tehdä näille %d kappaleelle?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Varmista toimenpide soittolistalle ”%s”" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "tyhjä" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Esimerkkisoittolista" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Soittolistaselaimen asetukset" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Soittolistanäkymä" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Haluatko varmasti poistaa soittolistan ”%s”?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "Valitun soittolistan kaikki tiedot poistetaan eikä sitä voi palauttaa." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "Lisätäänkö soittolistaan \"{pl_name}\" {num} kappale?" msgstr[1] "Lisätäänkö soittolistaan \"{pl_name}\" {num} kappaletta?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Lisää kappaleita" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Uusi soittolista" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Anna uuden soittolistan nimi:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Luo" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Tuodaan soittolista.\n" "\n" "%(current)d/%(total)d kappaletta lisätty." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Uusi syöte" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Anna podcastin / äänisyötteen sijainti:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Podcastit" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Podcastit" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "Lisää _syöte…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Päivitä" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Etsi uusia jaksoja lähteestä" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Hae kaikki uudelleen" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "Poista olemassa olevat jaksot ja hae kaikki uudelleen lähteestä" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Poista tämä podcast ja sen jaksot" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Syötettä ei voitu lisätä" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Sijainnin %s lisääminen ei onnistunut. Ehkä palvelin ei ole linjoilla tai " "sijainti ei ole podcast / äänisyöte." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Nykyinen äänen taustaohjelma ei tue URL-osoitteita. Podcast-selain on " "poistettu käytöstä." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Rajoita tulosten _määrää" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Salli useampi hakukysely" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Kappaleet" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "Kappale_lista" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud-selain" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Hae" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Omat raidat" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Siirry osoitteeseen %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Yhdistetty" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet on nyt muodostanut yhteyden, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Kirjaudu ulos palvelusta %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Anna koodi…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Kirjaudu palveluun %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud-valtuutus" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Anna Soundcloud-valtuutuskoodi:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet ei ole käynnissä (lisää '--run' käynnistääksesi sen)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "musiikkikirjasto ja toistin" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[valitsin]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Tulosta soiva kappale ja poistu" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Aloita toisto välittömästi" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Älä avaa ikkunoita käynnistyksen yhteydessä" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Hyppää seuraavaan kappaleeseen" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Hyppää edelliseen kappaleeseen tai nykyisen alkuun" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Hyppää edelliseen kappaleeseen" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Aloita toisto" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Keskeytä toisto" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Keskeytä toisto tai jatka sitä" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Pysäytä toisto" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Lisää äänenvoimakkuutta" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Vähennä äänenvoimakkuutta" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Nosta soivan kappaleen arvosanaa yhdellä tähdellä" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Laske soivan kappaleen arvosanaa yhdellä tähdellä" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Tulosta toistimen tila" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Piilota pääikkuna" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Näytä pääikkuna" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Piilota tai näytä pääikkuna" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Kohdista käynnissä olevaan toistimeen" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Poista aktiiviset selainsuodattimet" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Päivitä kirjasto" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Listaa käytettävissä olevat selaimet" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Tulosta nykyinen soittolista" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Tulosta jonon sisältö" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Tulosta aktiivinen hakukysely" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Käynnistä ilman liitännäisiä" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Käynnistä Quod Libet jos se ei ole jo käynnissä" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Poistu Quod Libetistä" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Siirry toistettavassa kappaleessa" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Aseta sekoitustila tai vaihda sen tilaa" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Aseta sekoituksen tyyppi" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Aseta kertaus päälle, pois, tai vaihda sen tilaa" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Aseta kertauksen tyyppi" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Aseta äänenvoimakkuus" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Hae äänikirjastosta" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "kysely" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Toista tiedosto" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "tiedostonimi" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Aseta toistettavan kappaleen arvosana" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Valitse nykyinen selain" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Pysäytä soivan kappaleen jälkeen" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Avaa uusi selain" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Näytä tai piilota jono" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Suodata satunnaisen arvon perusteella" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tunniste" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Suodata tunnisteen arvon perusteella" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tunniste=arvo" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Lisää tiedosto tai kysely jonoon" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Lisää jonoon pilkulla erotellut tiedostot" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "tiedostonimi" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Tulosta kyselyn tulosten tiedostonimet stdout:iin" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Poista tiedosto tai kysely jonosta" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Lisää tiedosto tai kansio kirjastoon" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "sijainti" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Aseta malli --print-*-komentoja varten" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "kaava" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Virheellinen argumentti valitsimelle %s." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Kokeile komentoa %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Tapahtui virhe" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Voit jättää tämän virheen huomiotta, mutta sovellus saattaa olla epävakaassa " "tilassa kunnes se käynnistetään uudelleen. Virheraportin lähettäminen kestää " "vain muutaman sekunnin ja auttaa kehittäjiä paljon." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Lähetä virheraportti" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Käynnistä uudelleen" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Jätä virhe huomiotta" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Virheen tiedot:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Virheen yksityiskohdat ja järjestelmän tiedot lähetetään kolmannen osapuolen " "verkkopalveluun (<a href='https://www.sentry.io'>www.sentry.io</a>). " "Lähetettävät tiedot voi tarkistaa alta ennen lähettämistä." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(valinnainen) Anna lyhyt kuvaus siitä, mitä tapahtui virheen ilmetessä:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Lähetä" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Lyhyt kuvaus…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Lähetettävät tiedot:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "äänitiedostojen tunniste-editori" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "kansio" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Äänitiedostojen tunniste-editori" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Artwork URL -kansikuvalähde" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Lataa kansikuva kappaleen <tt>artwork_url</tt>-tunnisteessa määritetystä " "osoitteesta. Toimii Soundcloud- ja Podcast-selainten kanssa." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs-kansikuvalähde" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Lataa kansikuvia Discogs:stä." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm-kansikuvalähde" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Lataa kansikuvia Last.fm:n kansikuva-arkistosta." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-kansikuvalähde" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Lataa kansikuvia MusicBrainzin kansikuva-arkistosta." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Muunna merkistökoodaus" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Korjaa väärintulkitut tunnisteiden arvojen merkistökoodaukset tunniste-" "editorissa." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Muunna merkistökoodaus…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/kanji-muunnin" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" "Muuntaa kana/kanji-kirjoituksen latinalaisiksi aakkosiksi ennen " "uudelleennimeämistä." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Latinisoi _japanilainen teksti" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Kanji Kana Simple Inverter (kakasi) -ohjelmistoa ei löytynyt." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Säännöllisellä lausekkeella korvaaminen" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Mahdollistaa säännöllisten lausekkeiden korvausoperaation (<tt>s/korvattava/" "korvaava/</tt>) käyttämisen tiedostojen tunnisteita tai nimiä muokattaessa." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Iso alkukirjain" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Asettaa tunnisteiden arvoille ison alkukirjaimen tunniste-editorissa." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "_Isot alkukirjaimet tunnisteisiin" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Salli KAIKKI ISOLLA tunnisteissa" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Normaalien englannin sääntöjen käyttö" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Käytä normaaleja englannin kielen sääntöjä isojen kirjainten käytössä, esim. " "”Dark Night of the Soul”" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Lisäasetukset" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Muokkaa lisäasetuksia." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Tiedän, mitä olen tekemässä" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animoitu kuvaruutunäyttö" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Näyttää kappaleen tiedot ruudulla kappaleen vaihtuessa." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Sijainti:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Kansikuvan koko:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Näkymä" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Fontti:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Vasen" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Keskitä" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Oikea" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "T_asaus:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Teksti" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Teksti:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "Tä_yttö:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Värit" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Varjot" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "Ää_riviiva" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "_Pyöristetyt kulmat" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Viive:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Tehosteet" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Muokkaa näkymää…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Esikatsele" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Tietoja sovelluksesta" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Tietoja sovelluksesta ja sen ympäristöstä." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Tuetut muodot" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Asetuskansio" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Välimuistikansio" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Äänentoiston taustaosa" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Jokaisen toiston jälkeen (oletus)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Liitännäinen kirjoittaa tunnisteet tiedostoon kappaleen toiston jälkeen, " "mutta ei ohituksen jälkeen. Ohituskertoja ei kirjoiteta tiedostoihin " "ollenkaan, näin vältetään turhat kirjoituskerrat." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Jokaisen toiston tai ohituksen jälkeen" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Liitännäinen kirjoittaa tunnisteet tiedostoon kappaleen toiston tai " "ohituksen jälkeen. Hyödyllinen tilanteissa, joissa halutaan varmistaa, että " "myös vähemmän suosittujen ja näin ollen ohitettujen kappaleiden arvosanat " "kirjoitetaan tiedostoihin." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Kun koko albumi on arvosteltu" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Kappaleen toiston tai ohituksen jälkeen kaikki samassa albumissa olevat " "kappaleet tarkistetaan. Jos kaikki albumin kappaleet on arvosteltu ja " "ainakin yhden kappaleen arvosanoja tai toistokertoja ei ole tallennettu " "kappaleen tiedostoon, liitännäinen kirjoittaa tunnisteet tiedostoihin.\n" "\n" "Tätä voi käyttää jatkuvien tiedostojen päivittämisen välttämiseen, mutta " "samalla on huomioitava, että albumin päivityksen jälkeen on käytettävä " "Päivitä tiedostojen tunnisteet -liitännäistä kun halutaan kirjoittaa " "muokatut arvosanat ja toistokerrat tiedostoihin." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Kirjoitettaessa albumin tunnisteita, 0 kertaa toistettujen kappaleiden " "toistokerroiksi asetetaan arvo 1.\n" "Tästä on hyötyä tilanteissa, joissa tiedät jo ennen yhtään toistokertaa, " "ettet pidä kappaleesta. Myöhemmin tästä on hyötyä esim. etsittäessä " "albumeita, jotka on kuunneltu kokonaan (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Kappaletta ”%s” ei voitu kirjoittaa" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Päivitä tiedostojen tunnisteet automaattisesti" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Päivitä kappaletiedostojen tunnisteet kappaleiden toiston jälkeen. " "Varmistaa, että toistokerrat ja arvosanat ovat ajan tasalla." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Seuraava asetus laitettiin päälle, koska se vaaditaan liitännäisen " "toimimiseen:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Tallenna arvosanat ja toisto_kerrat tunnisteisiin" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Asetukset päivitetty" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Virhe liitännäisessä %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Varmista toistokertojen määrän olevan nollaa suurempi tallennettaessa" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Päivitystapa:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Asetukset" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automaattinen maskaus" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Maskaa tai poista maskaus automaattisesti asemista kun ne liitetään tai " "irrotetaan." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automaattinen arvosana" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Arvostelee kappaleita automaattisesti kun ne toistetaan tai ohitetaan. " "Käyttää accelerated-algoritmia ohjelmasta vux (Vacillating Utilitarian " "eXtemporizer), jonka on kehittänyt Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" "Annettu Banshee-tietokanta on väärän muotoinen tai sitä ei ole olemassa" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Tuonti epäonnistui" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Arvosanat ja tilastot tuotiin onnistuneesti %d kappaleelle" msgstr[1] "Arvosanat ja tilastot tuotiin onnistuneesti %d kappaleelle" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee-tuonti" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Tuo arvosanat ja kappaletilastot Banshee-ohjelmasta." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Tietokannan polku:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Aloita tuonti" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Herätyskello" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Herättää kovaäänisellä musiikilla." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Kehtolaulu" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Häivyttää ja keskeyttää musiikin toiston." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord-tilaviesti" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discord-tilaviesti" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Muuttaa Discordin tilaviestiä kullakin hetkellä soivan kappaleen mukaan." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Keskeytetty" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Tilarivi 1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Tilarivi 2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Tasainen" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Live" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Täysi basso ja diskantti" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klubi" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Suuri sali" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Bileet" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Soft" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Täysi basso" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Kuulokkeet" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Soft Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Täysi diskantti" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Tekno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Kannettava tietokone" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Taajuuskorjain" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Säädä musiikin äänensävyä taajuuskorjaimella.\n" "Käytä hiirtä tai näppäimistöä tasojen säätämiseksi (hiiren oikea nappi " "nollaa)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Nykyinen äänen taustaohjelma ei tue taajuuskorjausta." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Oletusesiasetus" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Valitse…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Nollaa" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Mukautetut esiasetukset" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Poista valittu" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Esiasetuksen nimi tallennusta varten:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Tallenna" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "online" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "offline" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "poissa" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "näkymätön" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim-tilaviesti" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Muuttaa Gajimin tilaviestiä kullakin hetkellä soivan kappaleen mukaan." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "keskeytetty" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Kaava:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Listaa välilyönnillä eroteltuina käyttäjätilit, joille tilaviesti muutetaan. " "Jos jätetty tyhjäksi, kaikkien käyttäjätilien tilaviestiä muutetaan." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Tilit:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Lisää ”[keskeytetty]”" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Jos valittu, teksti ”[keskeytetty]” lisätään tilaviestiin toiston ollessa " "keskeytetty" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Tilat, joille viesti muutetaan" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Keskeytä kuulokkeiden irrottua" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Keskeytä toisto, kun kuulokkeet irrotetaan ja jatka toistoa, kun ne taas " "kytketään." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Estä näytönsäästäjä / keskeytystila" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Estää näytönsäästäjää käynnistymästä tai tietokoneen menemistä " "keskeytystilaan kappaleen soidessa ja käytettäessä GNOME-työpöytää." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musiikin toisto käynnissä" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Tila:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Estä näytönsäästäjä" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Estä keskeytystila" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Internet-radioloki" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Muistaa 10 viimeisintä radioasemilla toistettua kappaletta ja listaa ne " "aikasiirtymävalinnan kontekstivalikossa." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Kirjoittaa Jabber User Tunes -tiedoston polkuun %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Vaihda kieli" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Vaihda käyttöliittymän kieli." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Järjestelmän oletus" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Ohjelma täytyy käynnistää uudelleen, jotta muutokset tulevat voimaan" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Media Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Paljastaa kaikki albumit Rygel UPnP Media Serverille MediaServer2 D-Bus -" "rajapinnan kautta." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Varmista, että Rygel-konfiguraatiotiedosto (~/.config/rygel.conf) sisältää " "seuraavat rivit:" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD-palvelin" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Mahdollistaa Quod Libetin etähallinnan käyttäen MPD-asiakasohjelmaa. " "Suoratoisto sekä jonon- ja kirjastonhallinta eivät ole tuettuja." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Portti:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Paikallinen IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "_Salasana:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Yhteys" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Testatut asiakasohjelmat" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus -tuki" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Hallitse Quod Libetiä käyttäen <a href=\"https://mpris2.readthedocs.io/en/" "latest/\">MPRIS 2</a> -D-Bus-rajapintaa. Mahdollistaa erilaisia " "integraatioita Linux-työpöytäympäristön kanssa, mm. multimedianäppäinten " "käytön." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Piilota pääikkuna kun se suljetaan" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Hyväksyy QL-kaavat, esim. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT-julkaisija" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Julkaisee tilaviestejä MQTT-aiheeseen." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Välittäjän verkkotunnus / IP-osoite" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Oletus: localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Välittäjän portti" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Oletus: 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Välittäjän käyttäjätunnus" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Välittäjän salasana" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Aihe" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Toiston tilaviestikaava" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Tilaviesti, kun kappaleen toisto alkaa." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Keskeytyksen tilaviestikaava" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Tilaviesti, kun kappaleen toisto keskeytetään." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Ei kappaletta -teksti" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Teksti, kun toistettavaa kappaletta ei ole" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT-asetukset" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Tilaviestit" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Yhdistetty välittäjään osoitteessa %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" "Yhteyden muodostus osoitteeseen %(host)s:%(port)d epäonnistui (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Yhteysvirhe" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz-synkronointi" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synkronoi kappaleen arvostelun MusicBrainzin kanssa." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Käyttäjänimi:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Salasana:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Tili" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Ilmoitusteksti" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Otsikko:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Palauta oletuskaava" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Runko:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Näytä ilmoitus" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Näytä ilmoitukset" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Vain kun kappaletta vaihdetaan <i>_käsin</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Vain kun kappale vaihtuu <i>_automaattisesti</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "<i>Aina</i> kun kappale _vaihtuu" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Vain kun kohdistus ei ole pääikkunassa" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Näytä ”_Seuraava”-painike" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Yhteysvirhe" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Yhteyden muodostus ilmoituksia hoitavaan taustaohjelmaan epäonnistui." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Ilmoitukset kappaleista" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Näytä ilmoitus, kun toistettava kappale muuttuu." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Seuraava" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Ilmoitukset kirjanmerkeistä" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Käyttää ilmoituksia näyttääkseen kirjanmerkkejä / kommentteja reaaliajassa. " "Toimii hyvin Soundcloud-selaimen kanssa." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Määritä asetukset QLScrobblerille Liitännäiset-ikkunassa. Ennen tätä " "kappaleita ei lähetetä." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Palveluun %s ei saatu yhteyttä." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Todennus epäonnistui: virheellinen URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Todennus epäonnistui: virheellinen käyttäjänimi ”%s” tai väärä salasana." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Asiakasohjelma on estetty. Ota yhteyttä tämän ohjelman tekijään." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Järjestelmän kello on väärässä. Lähetykset voivat epäonnistua ennen kuin " "ongelma on korjattu." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-lähetys" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "Audioscrobbler-asiakasohjelma palveluille kuten Last.fm ja Libre.fm." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Todennus onnistui." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Palvelu:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Muu…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Testaa tilitiedot" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Kaava _artistille:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Kaava kappale_nimelle:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Poissulkeva _suodatin:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Kaava, jonka mukaan artistin nimi muotoillaan lähetystä varten. Jätä " "tyhjäksi käyttääksesi oletusasetusta." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Kaava, jonka mukaan kappaleen nimi muotoillaan lähetystä varten. Jätä " "tyhjäksi käyttääksesi oletusasetusta." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Tähän suodattimeen täsmääviä kappaleita ei lähetetä" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Yhteydetön tila (älä lähetä mitään)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Lähetys" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Vaimenna radiomainokset" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Vaimentaa ääniulostulon radiomainosten aikaan.\n" "Asemat: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Satunnaisen albumin toisto" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Aloittaa satunnaisen albumin toiston, kun soittolista päättyy. Vaatii sen, " "että aktiivinen selain tukee suodatusta albumin perusteella." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Parempi arvosana" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Toistettu useammin" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Ohitettu useammin" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Toistettu äskettäin" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Toisto aloitettu äskettäin" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Lisätty äskettäin" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Pidemmät albumit" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekuntia ennen seuraavan albumin aloittamista" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Painoarvot" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Toista joitakin albumeita toisia useammin" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "vältä" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "suosi" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Satunnainen alb_umi" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Odotetaan albumin %s toiston alkamista" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Arvosanat ja tilastot tuotiin onnistuneesti %d kappaleelle" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox-tuonti" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Tuo arvosanat ja kappaletilastot Rhythmbox-ohjelmasta." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Näytönsäästäjä-keskeytys" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Keskeyttää toiston GNOME-näytönsäästäjän ollessa aktiivisena." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Ei asennettua GNOME Shell -hakupalveluntarjoajaa Quod Libetille." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "Onko ini-tiedosto kopioitu polkuun %s (tai vastaavaan)?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME-hakupalveluntarjoaja" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Sallii GNOME Shellin hakea kirjastosta." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Vaihtoehtoinen aikasiirtymäpalkki" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Vaihtoehtoinen aikasiirtymäpalkki, joka on aina näkyvissä ja täyttää koko " "ikkunan leveyden." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Aikasiirtymä-kirjanmerkit" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Tallenna kappaleelle kirjanmerkit A ja/tai B. Kun kappale toistetaan, toisto " "aloitetaan pisteestä A ja lopetetaan pisteeseen B.\n" "\n" "ℹ Huomaa, että pisteiden nimien muuttaminen alla ei päivitä jo " "tallennettujen kirjanmerkkien nimiä. Se vain määrittää kirjanmerkkien nimet, " "joiden perusteella liitännäinen tekee mahdolliset aikasiirtymät." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Kirjanmerkin nimi pisteelle A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Jos kirjanmerkki tällä nimellä on olemassa, kappaleen toisto aloitetaan sen " "kohdalta" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Kirjanmerkin nimi pisteelle B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Jos kirjanmerkki tällä nimellä on olemassa, kappaleen toisto päätetään " "siihen." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox-synkronointi" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Vastaa siitä, että Logitech Squeezebox toistaa saman minkä Quod Libet, " "olettaen, että molemmat käyttävät samaa kirjastoa." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Asetukset ovat yhteiset <a href=\"%(plugin_link)s\">Vie Squeezeboxiin</a> -" "liitännäisen kanssa." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Virhe Squeezebox-palvelimen löytämisessä" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Virhe kohteen %s löytämisessä. Tarkista asetukset." #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Pysäytä toisto keskeytyksen sijaan" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Muuttaa keskeytä toisto -toiminnon niin, että se pysäyttää toiston " "keskeytyksen sijaan.\n" "\n" "Hyödyllinen tilanteissa, joissa Quod Libet ei pysty vaihtamaan äänilaitetta " "kun uusi laite (Bluetooth-kaiutin, USB DAC jne.) liitetään järjestelmään.\n" "\n" "Varmistaa, että sijainti nykyisessä äänilähteessä säilytetään, jos nykyinen " "äänilähde tukee kelausta. Jos lähde ei tue kelausta ja \"Vain kelausta " "tukevat lähteet\" -asetus ei ole valittuna, toisto alkaa alusta." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Vain kelausta tukevat lähteet" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Liitännäisen asetukset" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Odottaa kopiointia" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Odottaa poistamista" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "poista" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Ohita" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "KAKSOISKAPPALE" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Synkronoidaan" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Poistetaan" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Suoritus onnistui" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "SUORITUS EPÄONNISTUI" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Olemassa oleva tiedosto ohitettu" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Kappaleen tiedostonimen asettaminen epäonnistui." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Synkronoi laitteelle" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synkronoi valittujen tallennettujen hakujen määrittämät kappaleet määritetyn " "kansion kanssa." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synkronoi seuraavat tallennetut haut:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Vientisijainnin absoluuttinen polku" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Kaikki kohdekansiossa jo olemassa olevat tiedostot, jotka eivät sisälly " "hakutuloksiin, poistetaan." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "MTP:llä yhdistettyyn laitteeseen viemistä varten vie tulokset ensin " "paikalliseen kansioon ja siirrä ne sieltä laitteeseen rsync-ohjelmalla. " "Synkronoidessa suurta määrää tiedostoja Android-laitteeseen voi käyttää " "huomattavasti nopeampaa adc-sync-ohjelmaa." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Polku kohdekansioon:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Kaavat tiedostopoluille" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Muokkaa tallennettuja kaavoja…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Vietyjen tiedostonimien rakenne (perustuen kappaleiden tunnisteisiin)" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Vientikaava:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Pysäytä esikatselu" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Tila" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Lähdetiedosto" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Vientipolku" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Kahdentuneita vientipolkuja havaittu. Yllä olevia vientipolkuja voi muokata " "ennen synkronoinnin aloittamista." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Olemassa olevat tiedostot kohdepolussa poistetaan (paitsi cover.jpg-nimiset " "tiedostot)!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Aloita synkronointi" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Pysäytä synkronointi" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "Ei tallennettuja hakuja" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Valitse kohdepolku" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Vientipolku muutettu arvosta ”{old_path}” arvoon ”{new_path}” tiedostolle " "”{filename}”" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Aloitetaan synkronoinnin esikatselu" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Synkronoinnin esikatselu käynnissä." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Synkronoinnin esikatselu valmis" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Pysäytetään synkronoinnin esikatselua" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Synkronoinnin esikatselu pysäytettiin." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Synkronoinnin esikatselu on valmis." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Synkronoinnin esikatselu pysäytettiin" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Toinen liitännäinen valittu - pysäytä esikatselu" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Synkronointi tekee seuraavat asiat:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "yrittää kirjoittaa {count} tiedoston" msgstr[1] "yrittää kirjoittaa {count} tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "ohittaa {count} kaksoiskappaleen" msgstr[1] "ohittaa {count} kaksoiskappaletta" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "poistaa {count} tiedoston" msgstr[1] "poistaa {count} tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Kohdepolkua ei ole määritetty" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Määritä kohdekansio, johon kappaleet viedään." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Vientikaavaa ei ole määritetty" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Määritä vientikaava vietävien kappaleiden tiedostonimille." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Vientipolku ei ole absoluuttinen" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Kaava\n" "\n" "{}\n" "\n" "sisältää merkin /, mutta ei ala juurihakemistosta. Määritä absoluuttinen " "kohdepolku aloittamalla kaava merkeillä / tai ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Ei tallennettuja hakuja valittuna" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Valitse vähintään yksi tallennettu haku." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Ei kappaleita valituissa tallennetuissa hauissa" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Kaikki valitut tallennetut haut ovat tyhjiä." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Löydetty {} synkronoitavaa kappaletta" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Kohdepolku ja vientikaava eivät vastaa toisiaan" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Vientikaava alkaa polulla, joka on eri kuin määritetty kohdepolku. Korjaa " "vientikaava.\n" "\n" "Virhe:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Ei voi synkronoida" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" "Synkronointia ei voi aloittaa järjestettäessä sarakkeen <b>Tila</b> mukaan." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Aloitetaan kappaleiden synkronointi" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Synkronointi käynnissä." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Kappaleiden synkronointi valmis" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Kappaleiden synkronointia pysäytetään" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Kappaleiden synkronointi pysäytettiin." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Kappaleiden synkronointi on valmis." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Kappaleiden synkronointi pysäytetty" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Toinen liitännäinen valittu - pysäytä synkronointi" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - ”{filename}”" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Poistetaan ”{}”" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Synkronointi on tehnyt seuraavat asiat:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "kirjoitettu {count}/{total} tiedosto" msgstr[1] "kirjoitettu {count}/{total} tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(ohitettu {count} olemassa oleva tiedosto)" msgstr[1] "(ohitettu {count} olemassa olevaa tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "ohitettu {count}/{total} kaksoiskappale" msgstr[1] "ohitettu {count}/{total} kaksoiskappaletta" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "poistettu {count}/{total} tiedosto" msgstr[1] "poistettu {count}/{total} tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "ei voitu synkronoida {count} tiedostoa" msgstr[1] "ei voitu synkronoida {count} tiedostoa" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "ohitettu {count} aikaisemmin synkronoitu tiedosto" msgstr[1] "ohitettu {count} aikaisemmin synkronoitua tiedostoa" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Tahdistetut sanoitukset" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Näyttää tahdistetut sanoitukset .lrc-tiedostosta, jonka nimi vastaa " "kappaleen tiedostonimeä." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Teksti:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Tausta:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Fontti" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Koko (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy-tilaviestit" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Päivittää tilaviestin kaikille Telepathy-pohjaisille pikaviestitileille " "(kuten määritetty mm. Empathy-sovelluksessa) toistettavan kappaleen " "perusteella." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Toistetaan:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Tilaviesti, kun kappaleen toisto alkaa. Hyväksyy QL-kaavoja, kuten %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Keskeytetty:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Tilaviesti, kun kappaleen toisto on keskeytetty. Hyväksyy QL-kaavoja, kuten " "%s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Tilateksti, kun toistettavaa kappaletta ei ole" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Ei kappaletta:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Tilaviestien kaavat" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Teeman vaihtaja" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Vaihtaa käytetyn GTK+-teeman." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Teema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Oletusteema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Suosi tummaa teemaa" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Peukkuarvostelu" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Lisää mahdollisuuden arvostella kappaleita antamalla peukalo ylös / alas -" "ääniä. Arvostelun tulos muunnetaan arvosanaksi. Voi käyttää yhteisäänten " "laskemiseen ja kappaleiden järjestämiseen <b><tt>~#score</tt></b>-tunnisteen " "mukaan." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Valikkorivin näyttö / piilotus" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Näytä / piilota valikkorivi Alt-näppäintä painamalla." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Toisto pysäytetty" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Ilmaisinalueen kuvake" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Hallitse Quod Libetiä ilmaisinalueelta." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Näytä %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Toista" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Keskeytä" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Edellinen" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Seuraava" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "S_ekoita" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "Ke_rtaus" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "_Pysäytä tämän kappaleen jälkeen" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Avaa _selain" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Muokkaa t_unnisteita" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "T_iedot" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Soitto_listat" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Lopeta" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Toiminta" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Rulla säätää äänenvoimakkuutta" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Rulla vaihtaa kappaletta" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Vieritysrulla" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Työkaluvihjenäyttö" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Näytä sanat" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Näyttää tunnisteesta tai tiedostosta haetut kappaleen sanat sivupaneelissa." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Seuraavalle kappaleelle ei löydy sanoja:\n" "%s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Ei aktiivista kappaletta" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Käynnistä visualisaatio" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Käynnistä ulkopuolinen visualisaatio." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Visuaalisaatiota ei voitu suorittaa käyttämällä ohjelmaa %s" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Virhe" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Visualisointiohjelma:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Lataa uudelleen" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Aaltomuoto-aikasiirtymäpalkki" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" "∿ Aikasiirtymäpalkki, joka on toistettavan kappaleen aaltomuodon muotoinen." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Edustaväri:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Väri osoitettaessa:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Jäljellä olevan osan väri:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Näytä nykyinen sijainti" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Näytä aikatiedot" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Aikasiirtymä vieritettäessä (millisekunteina):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Kansikuvatallentaja" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" "Tallentaa kullakin hetkellä toistettavan kappaleen kansikuvan tiedostoon." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Tiedosto:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Kompressointikynnys:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Kynnysarvo, jonka kohdalla suodatin otetaan käyttöön" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Kompressointisuhde:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Kompressointisuhde" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Äänikompressori" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Vaimentaa kompressointikynnystä voimakkaamman signaalin tasoa tietyn suhteen " "mukaan." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Esiasetus:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Suodattimen esiasetus" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Rajataajuus:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Alipäästösuodattimen rajataajuus" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Syötön _taso:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Syötön taso" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Oletus" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Lähimpänä virtuaalista kaiutinasettelua (30°, 3 metriä)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Muistuttaa Chu Moyn crossfeederiä (suosittu)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Muistuttaa Jan Meierin CORDA-vahtistimia (pieni muutos)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Mukautettu" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Mukautettu" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Ristiinsyöttö" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Miksaa oikean ja vasemman kanavan tavalla, joka simuloi kaiutinasettelua " "käytettäessä kuulokkeita, tai jota voidaan käyttää varhaisten " "stereoäänitteiden säätämiseen." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Taajuuskaista:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Suodattimen taajuuskaista" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Kaistanleveys:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Suodattimen kaistanleveys" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Taso:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Tehosteen taso" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Poistaa äänestä päälauluäänen." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono-alasmiksaus" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Alasmiksaa äänikanavat monoääneksi." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Näytenopeus:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Sävelkorkeus:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Äänenkorkeus / toistonopeus" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Säätää äänivirran äänenkorkeutta." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Vie soittolista kansioon" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Vie" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Kohdekansio:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Tiedostonimen kaava:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Vie soittolistan kopioimalla tiedostot kansioon." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Soittolistan vienti ei onnistu" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Varmista, että kohteeseen on kirjoitusoikeus." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Tiedostonimen oletuskaava:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Anna uuden soittolistan nimi,\n" "tai valitse olemassa oleva Sonos-soittolista ylikirjoitettavaksi" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Vie Sonos-soittolistaksi" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "Vie soittolistan Sonosiin täsmäyttämällä kappaleita." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Virhe Sonos-laitteiden löytämisessä" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Virhe Sonos-laitteiden löytämisessä. Tarkista asetukset." #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Olemassa olevan Sonos-soittolistan %s poistaminen epäonnistui:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Vie soittolistaan %(playlist)r (%(total)d kappaletta)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Vie Squeezeboxiin" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Vie soittolistan Logitech Squeezebox -soittolistaksi edellyttäen, että " "molemmilla on sama hakemistorakenne." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Asetukset ovat yhteiset <a href=\"%(plugin_link)s\">Squeezebox-synkronointi</" "a>-liitännäisen kanssa." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Vie soittolista Squeezeboxiin" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Soittolistan nimi (ylikirjoittaa olemassa olevan)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Vie Squeezebox-soittolistaksi" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Poista soittolistalta kaksoiskappaleet" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" "Poistaa soittolistalta useaan kertaan esiintyvien kappaleiden " "kaksoiskappaleet." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Haluatko varmasti poistaa %d kaksoiskappaleen?" msgstr[1] "Haluatko varmasti poistaa %d kaksoiskappaletta?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Kaksoiskappaleet poistetaan soittolistalta ”%s”." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Sekoita soittolista" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Sekoittaa soittolistan satunnaiseen järjestykseen." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Seuraa kursoria" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Lisää toistojärjestyksen, joka toistaa valittuja kappaleita, tai listassa " "seuraavana olevaa kappaletta kun kaikki valitut on toistettu." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Seuraa kursoria" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Seuraa kursoria" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Toistokertojen tasaaja" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Lisää sekoitustilan, joka suosii vähemmän toistettuja kappaleita." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Suosi vähemmän toistettuja" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Suosi _vähemmän toistettuja" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Vain jono" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Rajoittaa toistettavat kappaleet jonossa oleviin.\n" "\n" "Kun tämä on valittuna pääikkunassa, niin kappaleen kaksoisklikkaus lisää sen " "jonoon toistamisen sijaan." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Vain jono" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "Vain _jono" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Ala automaattisesti toistaa kaksoisklikattuja kappaleita" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Käänteinen järjestys" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Lisää sekoitustilan, joka toistaa kappaleet käänteisessä järjestyksessä." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "_Käänteinen järjestys" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Sekoita ryhmittäen" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Lisää sekoitustilan, joka ryhmittää yhteisen tunnisteen omaavat kappaleet " "soimaan peräkkäin (samalla periaatteella kuin albumisekoitus).\n" "\n" "Hyödyllinen esimerkiksi moniosaisten klassisten teosten toistamiseen " "satunnaisessa järjestyksessä kuitenkin niin, että yhden teoksen kaikki osat " "soitetaan järjestyksessä ennen seuraavaan teokseen siirtymistä." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Sekoita ryhmittäen" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "Sekoita _ryhmittäen" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Odotetaan uuden ryhmän toiston alkamista…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Ryhmittävä tunniste:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Tunniste, jonka perusteella kappaleet ryhmitellään" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Suodattava tunniste:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Kappaleet ryhmitetään yhteen vain, jos suodattava tunniste\n" "on määritetty. Kappale, jolla ei ole suodattavaa tunnistetta,\n" "käsitellään yhden kappaleen ryhmänä. Tyypillisesti suodattavan\n" "tunnisteen pitäisi täsmätä ainakin osittain ryhmittävän tunnisteen kanssa." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Viive:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Viive (sekunneissa) ennen seuraavan ryhmän aloittamista" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Palauta oletukset" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Ohita huonot kappaleet" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Lisää toistojärjestyksen, joka toistaa kappaleet valitussa järjestyksessä, " "mutta ohittaa kappaleet, joiden arvosana on pienempi (tai yhtä suuri kuin) " "määritelty raja." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Ohita huonot kappaleet" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Ohita _huonot kappaleet" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Kertaa jokainen kappale" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Lisää sekoitustilan, joka toistaa kappaleet valitussa järjestyksessä, mutta " "kertaa jokaisen kappaleen tietyn määrän kertoja." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Kertaa jokainen kappale" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "Kertaa _jokainen kappale" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Kappaleen toistokertojen määrä:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Ehdollinen kysely" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Valitsee käytettävän kyselyn ehdollisen kyselyn pohjalta." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: ehtokysely, sitten-kysely, muutoin-kysely)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Puuttuvan tunnisteen kysely" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Täsmää kappaleisiin, joilla ei ole annettua tunnistetta." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Sisällytä tyhjät tunnisteet" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python-kysely" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍 Käytä Python-lausekkeita kyselyissä." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: lauseke)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Muuttuja <tt>s</tt> on täsmäytettävä kappale, tai vastaavasti muuttuja " "<tt>a</tt> on täsmäytettävä albumi.\n" "\n" "<tt>_ts</tt> on aikaleima kyselyn suorituksen alkaessa (reaalilukuna).\n" "\n" "Moduulit <tt>time</tt> ja <tt>random</tt> sekä luokka <tt>Random</tt> (eli " "<tt>random.Random</tt>) ovat myös käytettävissä." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Sisällytä tallennettu haku" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 Sisällytä tallennetun haun tulokset toiseen hakuun." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: haun nimi)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Yksilöllinen haku" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Suodata hakutulokset yksilöllisten tunnisteiden mukaan." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: tunniste)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Käytetään ainoaa toistinta (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Yhteyden muodostus kohteeseen %s epäonnistui" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Verkko-osoite:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Portti:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Käyttäjänimi:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Salasana:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Kirjastokansio, johon palvelin kytkeytyy" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Kirjaston polku:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Tarkista asetukset" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox-palvelin" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Virheenpaikannus" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-palvelin osoitteessa {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "tunnistamaton Squeezebox-palvelin" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "tunnistamaton Squeezebox-palvelin: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Valitse Squeezebox-palvelin" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Squeezebox-palvelin löydetty.\n" "Valitse toistin" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Sovita kuva ikkunaan" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Katso asetus ”[plugins] cover_filenames”, jossa määritetään kuvien " "tiedostonimet" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Ohjelma:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Muokkaa kuvaa tallennuksen jälkeen" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Tiedostonimi:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Tallennus epäonnistui" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Kohdetta ”%s” ei voitu tallentaa." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-virhe: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Albumin kansikuvien lataaja" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "lähteestä %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Resoluutio: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Koko: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Palvelukohtainen parhaiden tulosten määrän rajoitus" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Hae" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Haetaan…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Valmis" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Lataa albumien kansikuvia" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Lataa albumien kansikuvia eri verkkosivuilta." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Lähteet" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 -> ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Muuntaa APEv2-tunnisteet ID3v2-tunnisteiksi. Poistaa APEv2-tunnisteet " "muunnoksen jälkeen." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Siirry kirjanmerkkiin" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Hallitsee kirjanmerkkejä valituissa tiedostoissa." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Muokkaa kirjanmerkkejä…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Ei kirjanmerkkejä" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-haku" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Asettaa albumin tunnisteet MusicBrainz-hakuun perustuen." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Käytä ainoastaan vuotta date-tunnisteelle" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Kirjoita ”_albumartist” tarvittaessa" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Kirjoita järjestyksen määräävät tunnisteet artistinimille" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Kirjoita standardit MusicBrainz-tunnisteet" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Kirjoita labelid-tunniste" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Tiedostonimi" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Levy" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Raita" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Nimi" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artisti" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz-haku" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Kysely:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Hae" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Tulokset <i>(raahaa muuttaaksesi järjestystä)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Anna haku." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Virhetilanne, yritä uudelleen." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Ladataan tuloksia…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Tuloksia ei löytynyt." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python-konsoli" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktiivinen Python-konsoli. Avaa uuden ikkunan." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} - {songs} valittuna ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python-konsoli (sivupalkki)" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Interaktiivinen Python-konsoli sivupalkissa. Seuraa pääikkunassa valittuja " "kappaleita." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Seuraavat objektit ovat käytössä oletuksena:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Nykyinen työhakemisto:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Täydennys" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Lataa kansikuvia" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Lataa korkealaatuisia albumikansikuvia Quod Libetin kansikuvalisäosien " "avulla." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Normaali" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Suuri" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Kansikuvien lataaja" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Ladataan %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Kansikuvia ei löytynyt albumeille:\n" "%(albums)s.\n" "\n" "Käytetyt lähteet:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Ei löydettyjä kansikuvia" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Esikatselukuvan koko" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Tallennuskohde" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Jos kuva ei jo ole JPEG-muodossa, muunna se korkealaatuiseksi, " "samankokoiseksi JPEG-kuvaksi" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Tallenna JPEG-muodossa" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Komento" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nimi" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Komennon nimi" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "komento" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Päätteessä suoritettava komento" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parametri" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Jos määritetty, komennossa olevat esiintymät korvataan käyttäjän antamalla " "arvolla. Esim. parametrin nimellä ”PARAM” kaikki ”{PARAM}”-ilmentymät " "komennossa korvataan suoritettaessa käyttäjältä kysytyllä arvolla." #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL-kaava, esim. <~filename>, jota käytetään komennolle välitettävän arvon " "määrittämiseen. Soittolistojen tapauksessa myös virtuaaliset tunnisteet " "<~playlistname> ja <~#playlistindex> ovat tuettuja." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "yksilöllinen" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Jos asetettu, duplikaatit poistetaan kaavan tuloksista" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "Maks. argum." #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Komennolle annettavien argumenttien maksimimäärä (kuten xargs-komennolla)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "käänteinen järjestys" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Kääntää argumenttilistan järjestyksen" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Anna arvo" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Arvo parametrille %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Mukautetut komennot" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Suorita mukautettuja komentoja (tarvittaessa eräajona) kappaleille käyttäen " "niiden haluttuja tunnisteita." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Muokkaa mukautettuja komentoja" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Mukautetun komennon %s suorittaminen epäonnistui" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d kaksoiskappaleryhmä" msgstr[1] "%d kaksoiskappaleryhmää" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Supista / laajenna kaikki" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Kaksoiskappalelauseke on ”%s”" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Kaksoiskappaleiden selain" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Etsii ja näyttää samat tunnisteet omaavat versiot kappaleista." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Hyväksyy QL-tunnistelausekkeet kuten <tt>~artist~title</tt> tai " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Kaksoiskappaleet ryhmittelevä ehto:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Kaksoiskappaleavain" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Jätä tyhjämerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Jätä tarkemerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Jätä välimerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Jätä kirjainkoko huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Täsmäytyksen säännöt" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Toistomäärän muokkaus" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Muokkaa kappaleen toistokertojen ja ohituskertojen määrää (<tt>~#playcount</" "tt> ja <tt>~#skipcount</tt>).\n" "\n" "Useamman kappaleen ollessa valittuna lukuja kasvatetaan / pienennetään " "asettamisen sijaan.\n" "\n" "Jos kappaleen toistokertamääräksi (<tt>~#playcount</tt>) asetetaan 0, " "<tt>~#lastplayed</tt> (viimeksi toistettu) ja <tt>~#laststarted</tt> (toisto " "viimeksi aloitettu) -tiedot nollataan. Kuitenkin jos 0 kertaa toistetulle " "kappaleelle asetetaan positiivinen toistokertamäärä, toistopäivämääriä ei " "luoda." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Toistokertojen määrä" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Ohituskertojen määrä" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Useita tiedostoja valittu." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Lukumääriä kasvatetaan." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Muokkaa upotettuja kuvia" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Lisää, poistaa tai korvaa upotettuja kuvia." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Upota" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Valitse upotettava kuva (kohdistuu %d kappaleeseen)" msgstr[1] "Valitse upotettava kuva (kohdistuu %d kappaleeseen)" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Poista kaikki kuvat" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Upota nykyinen kuva" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Valitse kuva…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Aseta tarkka arvosana" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Mahdollistaa kappaleen arvostelun numeroarvolla." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Anna haluamasi arvosana asteikolla 0.0-1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Suodata halutulla tunnisteella" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Luo hakukyselyn valittujen kappaleiden tunnisteiden perusteella." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Suodata kansion perusteella" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Suodattaa kansion perusteella uudessa selainikkunassa." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akustinen sormenjälki -haku" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Hakee kappaleen metatiedot akustisen sormenjäljen perusteella." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Lähetä akustisia sormenjälkiä" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Luo akustiset sormenjäljet käyttäen chromaprintiä ja lähettää ne acoustid." "org-palveluun." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API-avain puuttuu" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Acoustid.org-palvelulle on määritettävä API-avain liitännäisten asetuksissa " "ennen kuin sormenjälkiä voi lähettää." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Pyydä API-avainta" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_API-avain:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID-verkkopalvelu" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Jonossa" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analysoidaan" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Haku" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Kirjoita" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Julkaisu" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Kirjoita MusicBrainz-tunnisteet" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Ryhmittele kansion perusteella" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Albumitila" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Kirjoita albumiin liittyvät tunnisteet ja yritä vähentää eri " "albumijulkaisujen määrää" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Luodaan sormenjälkiä:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Tiedot" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Lähetä" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Kappaleilla pitää olla asetettuna joko <i><b>musicbrainz_trackid</b></i>, " "tai <i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i> -" "tunnisteet, jotta ne voidaan lähettää." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Sormenjäljet:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Kappaleet, joilla on MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Kappaleet, joilla on riittävät tunnisteet:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Lähetettävät kappaleet:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Valmis. %(to-send)d/%(all)d lähetettävää kappaletta." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Lähetetään sormenjälkiä:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Lähetetään…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Päivitä tiedostojen tunnisteet" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Päivitä muokatut tunnisteet tiedostoissa. Varmistaa, että toistokerrat ja " "arvosanat ovat ajan tasalla." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Vie HTML-muotoon" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Vie valitun kappalelistan HTML-muotoon." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Lähetä iFP:hen" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Lähettää kappaleita iRiver iFP -laitteeseen." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "iFP-laitetta ei löytynyt" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "iFP-laitteeseen ei saatu yhteyttä. Tarkista, että laite on päällä ja " "kytkettynä, ja että koneellasi on ifp-line (http://ifp-driver.sf.net) " "asennettuna." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Lähetetään kappaletta %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Tiedostoa %s ei voitu lähettää. Laitteen tallennustila voi olla täynnä tai " "laite voi olla pois päältä." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Virhe lähetyksessä" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Vie käyttäjätiedot" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Vie tunnisteet" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Vie tunnisteet ja käyttäjätiedot" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Vie tiedostonimien rungot ja käyttäjätiedot" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Vie tiedostonimien rungot ja tunnisteet" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Vie tiedostonimien rungot, tunnisteet ja käyttäjätiedot" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Tuo / vie" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Tuo ja vie tunnisteita ja kappaleisiin liittyviä käyttäjätietoja." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Lisätietoja" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "”Kappaleisiin liittyvät käyttäjätiedot” tarkoittaa tietoa soittolistoista, " "joihin valitut kappaleet kuuluvat, sekä seuraavia metatietoja:\n" "\n" "%s\n" "\n" "Huomaa, että tuodessa tietoja takaisin kaikki viedyt tiedot muutetaan. Jos " "tiedostonimien rungot (nimet ilman tiedostopäätteitä) sisällytetään " "vientiin, tiedot tuodessa valitut tiedostot uudelleennimetään vastaavasti.\n" "\n" "Albumin tietojen viennin jälkeen tiedot voi tuoda albumin toiseen versioon. " "Kappaleiden järjestys ja määrä voi olla eri. Liitännäinen täsmäyttää viedyt " "tiedot uusiin kappaleisiin, vaikka kappaleiden nimet eroaisivat hieman " "toisistaan. Automaattinen täsmäytys ei välttämättä aina toimi oikein, joten " "on suositeltavaa olla pienentämättä vaaditun samankaltaisuuden asetuksia " "liian paljon." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Varmistukset tuodessa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Kysy varmistusta, jos kappaleiden määrä ei täsmää" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Kysy varmistusta, jos albumien määrä ei täsmää" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Jos samankaltaisuus on alle määritetyn prosenttiluvun, käyttäjän on käsin " "tarkistettava ja tarvittaessa muutettava, mikä kappale täsmätään mihinkin." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Kappaleiden samankaltaisuus:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Albumien samankaltaisuus:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Vientitiedostot" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Kirjoita JSON siististi muotoiltuna (hitaampi)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Poista vientitiedostot tuonnin jälkeen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Tuo" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Avaa vientikansio" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Levyt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Raidat" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artisti(t)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Polun loppuosa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Täsmäytä albumit" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Jatka" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Ei tuotavaa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Ennen tuontia on en sin vietävä jotain." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Indeksitiedosto on vahingoittunut." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "Tiedoston %s JSON-rakennetta ei voitu lukea" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Tiedostoa %s ei voitu lukea" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Tiedostonimi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Täsmäytä kappaleet" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Päivitetään soitetuimpien listaa." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Tiedot jo ajan tasalla." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Haetaan listaa päivän %s viikolle." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synkronointi valmis." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Virhe synkronoinnissa (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm-synkronointi" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Päivittää kirjaston tilastot Last.fm-profiilisi perusteella." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Käyttäjänimi:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Luo järjestystunnisteet" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Muuntaa albumi- ja artistinimet järjestelyyn käytetyiksi tunnisteiksi " "yksinkertaisella tavalla." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Vie M3U-/PLS-soittolistaksi" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Vie kappaleet M3U- tai PLS-soittolistaksi." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Käytä suhteellisia polkuja" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Käytä absoluuttisia polkuja" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "Kirjoittaminen kohteeseen %s epäonnistui." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Päivitä kappaleet" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Tarkistaa tiedostomuutokset ja lataa uudelleen / poistaa kappaleet " "tarvittaessa." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Päivitä kappaleet" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analysoija" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Kappale" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Edistyminen" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Vahvistus" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Huippu" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "%(to-process)s albumi päivitettäväksi (yhteensä %(all)s)" msgstr[1] "%(to-process)s albumia päivitettäväksi (yhteensä %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analysoi ja päivittää <a href=\"%(rg_link)s\">ReplayGain</a>-tiedot käyttäen " "GStreameriä. Tulokset ryhmitellään albumeittain." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://fi.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "aina" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "jos <b>mikä tahansa</b> RG-tunniste puuttuu" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "jos <b>albumi</b>-RG-tunnisteet puuttuvat" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Käy albumit läpi:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Olemassa olevat tunnisteet" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Jaa tunnisteet" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Erottaa levynumeron albumin nimestä ja version kappaleen nimestä " "samanaikaisesti." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Erota albumin levynumero" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Erota albumin levynumero albumin nimestä." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "-" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "Iskua minuutissa:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Nollaa" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Naputa" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Naputa BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Naputa valitulle kappaleelle BPM (iskuja minuutissa) -tieto." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Verkkosivuhaku" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Suorittaa haun haluamallasi verkkosivulla kappaleiden tunnisteiden " "perusteella.\n" "Tukee kaavoja, esim. %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "URL-hakukaava" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Muokkaa hakuosoitteita" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Hakuasetukset…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Hae tunnistetta Wikipediasta" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Avaa selainikkunan, jossa näytetään Wikipedia-artikkeli toistettavan " "kappaleen valitusta tunnisteesta." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Hae sivulta %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Muokkaa tunnisteita" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Haku epäonnistui" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Tunnistetta ”%s” ei löytynyt." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Kirjasto" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Tarkistetaan liitoskohdat" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Luetaan musiikkikirjastoa" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Luetaan kohdetta %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Ladataan tiedostoja" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Siirretään kirjaston tiedostoja" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Poistetaan kirjaston tiedostoja" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Lisätään seuranta polulle %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "Vanhalta soittolistalta %(filename)r (koko %(size).1f kt) ei löytynyt " "kirjastossa olevia kappaleita." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" "Onko kirjaston luettavaa kansiopolkua muutettu, mutta ei tätä soittolistaa?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d soittolistan muuntaminen epäonnistui" msgstr[1] "%d soittolistan muuntaminen epäonnistui" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Musiikkisoitin ja musiikkikirjaston hallinnoija" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Tiedoston lataus epäonnistui: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Listaa tunnisteet" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Tulosta lyhytsanaisesti" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Näytettävät sarakkeet ja niiden järjestys lyhytsanaisessa tilassa (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Listaa myös ohjelmalliset tunnisteet" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Ei tarpeeksi argumentteja" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Liikaa argumentteja" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Kuvaus" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Arvo" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Listaa kaikki yleiset tunnisteet" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopioi tunnisteet tiedostosta toiseen" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Näytä muutokset, mutta älä käytä niitä" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Ohita tunnisteet, joita ei voi kirjoittaa" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Tunnistetta {tagname} ei voi kopioida tiedostoon {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Muokkaa tunnisteita tekstieditorissa" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Muokkaus keskeytetty" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Tekstieditorin %(editor-name)s käynnistäminen epäonnistui." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Ei muutoksia havaittu" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Aseta tunniste ja poista olemassa olevat arvot" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" "%(format)s-muotoiselle tiedostolle %(file)r ei voi asettaa tunnistetta " "%(tag)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Poista tunnisteita" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Arvo on säännöllinen lauseke" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Poista kaikki tunnisteet" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Argumenttia --all ei voi yhdistää argumenttiin --regexp" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Tunnistetta {tagname} ei voi poistaa tiedostosta {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Poista tunnisteen arvo" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Lisää tunnisteelle arvo" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Ei voi asettaa: %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Listaa tiedoston tiedot" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Aseta annettu kuva ensisijaiseksi upotetuksi kuvaksi ja poista kaikki muut " "upotetut kuvat" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Kuvatiedoston lataaminen epäonnistui: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Kuvien muokkaus ei ole tuettu tiedostolle %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Poista kaikki upotetut kuvat" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Vie upotetut kuvat kansioon %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Polku, johon tiedostot tallennetaan (oletus: työhakemisto)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Nimeä tiedostoja uudelleen tunnisteisiin perustuen" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Aseta tunnisteet tiedostopolun perusteella" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Tiedosto" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Aseta raitanumerot kaikille tiedostoille" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Tulosta tunnisteita annetun kaavan mukaan" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Näytä käyttöohje" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" "”%(column-id)s” ei ole kelvollinen sarakkeen nimi (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Tuntematon" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Järjestyksessä" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Järjestyksessä" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Satunnainen" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Satunnainen" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Suosi parempia arvosanoja" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Suosi _parempia arvosanoja" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Kertaa tämä kappale" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Kertaa _tämä kappale" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Kertaa kaikki" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Kertaa _kaikki" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Yksi kappale" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "_Yksi kappale" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Virta" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Puskuroidaan" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "GStreamer-liukuhihnan luominen epäonnistui (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Mediamuodon käsittelyyn ei löytynyt sopivaa GStreamer-elementtiä" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Mediamuoto: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer-liitännäistä %(name)s ei voitu alustaa" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer-ulostuloliukuhihna (output pipeline), jota käytetään toistoon. " "Jätä tyhjäksi oletusliukuhihnan käyttämiseksi. Jos liukuhihna sisältää " "nielun (sink), sitä käytetään oletusnielun sijaan." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Ulostuloliukuhihna:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Puskurin pituus:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Poista katkoton toisto käytöstä" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Katkottoman toiston poistamisella käytöstä voi välttää kappaleen vaihtumisen " "ongelmat joidenkin GStreamerin versioiden kanssa" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Käytä JACK-järjestelmää toistoon, jos käytettävissä" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Käyttää ”jackaudiosink”-ääninielua, jos se on käytettävissä" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Muodosta yhteys JACK-ulostulolaitteisiin automaattisesti" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Käskee ”jackaudiosink”-ääninielun muodostaa yhteys automaattisesti" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Ei löydettyä GStreamer-ääninielua. Kokeillut: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Virheellinen GStreamer-ulostuloliukuhihna (output pipeline)" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Ääniulostuloa ei voitu luoda" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Äänilaitetta %r ei löytynyt. Tarkista Xinen asetukset tiedostossa ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Moduulia {module} ei löytynyt. Onko tarvittava paketti asennettu?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "GStreamer-elementtiä {element} ei löytynyt." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Määritä asetukset ListenBrainzille Liitännäiset-ikkunassa. Ennen tätä " "kuuntelutietoja ei lähetetä." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Liikaa peräkkäisiä epäonnistuneita lähetyksiä (%d). Siirrytään " "yhteydettömään tilaan. Määritä asetukset ListenBrainzille Liitännäiset-" "ikkunassa. Ennen tätä kuuntelutietoja ei lähetetä." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz-lähetys" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Lähetä kuuntelutiedot ListenBrainziin." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "_Käyttäjän tunniste (token):" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "_Tunnisteet:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Lähetykseen sisällytettävät tunnisteet. Erota tunnisteet pilkulla, käytä " "tarvittaessa lainausmerkkejä." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Tähän suodattimeen täsmääviä kappaleita ei lähetetä." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Suorita liitännäinen %(name)s” %(count)s soittolistalle?" msgstr[1] "Suorita liitännäinen ”%(name)s” %(count)s soittolistalle?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Suorita liitännäinen" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Käyttö" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Alku" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "-" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Aika" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Kirjanmerkin nimi" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Kirjanmerkit" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "S_uodattimet" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Äskettäin _toistettu" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Äskettäin _lisätty" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Kaikki _kappaleet" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Nykyisen tyylilajin mukaan" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Nykyisen artistin mukaan" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Nykyisen albumin mukaan" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Satunnainen _tyylilaji" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Satunnainen a_rtisti" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Satunnainen alb_umi" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 eniten toistamaasi kappaletta (tasapelitilanteissa saatetaan valita " "enemmän kuin 40)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nimi:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Arvo:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Tallennetut arvot" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Muokkaa tallennettuja arvoja…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_maattinen" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Raita" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albumi" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Vaimennus" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain -tila" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Uusi %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(tuntematon)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Lisää…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Muokkaa" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Tunnistelauseke" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tunnistelauseke, esim. people:real tai ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Anna uusi tunniste" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Muokkaa tunnistelauseketta" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Tiedostot:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Valitut kappaleet poistetaan kirjastosta ja niitä vastaavat tiedostot " "poistetaan levyltä." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Valitut tiedostot poistetaan levyltä." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Poistetaanko %(file_count)d tiedosto pysyvästi?" msgstr[1] "Poistetaanko %(file_count)d tiedostoa pysyvästi?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Poista tiedostot" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Valitut kappaleet poistetaan kirjastosta ja niitä vastaavat tiedostot " "siirretään roskakoriin." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Valitut tiedostot siirretään roskakoriin." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Siirretäänkö %(file_count)d tiedosto roskakoriin?" msgstr[1] "Siirretäänkö %(file_count)d tiedostoa roskakoriin?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Siirrä roskakoriin" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Siirretään tiedostoa %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Siirto roskakoriin epäonnistui" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Yhden tai useamman tiedoston siirto roskakoriin epäonnistui." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Poistetaan tiedostoa %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Tiedostojen poistaminen epäonnistui" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Yhden tai useamman tiedoston poistaminen epäonnistui." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Selain" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Ladataan tiedostoja" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "puuttuu %d kappaleesta" msgstr[1] "puuttuu %d kappaleesta" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "eri %d kappaleessa" msgstr[1] "eri %d kappaleessa" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Jaa _useammaksi arvoksi" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Erota levyn numero _albumin nimestä" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Erota _versio kappaleen nimestä" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Erota sovittaja ar_tistin nimestä" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Erota _esittäjä artistin nimestä" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Erota _esittäjä kappaleen nimestä" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Erota _alkuperäinen esittäjä kappaleen nimestä" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Lisää tunniste" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tunniste:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Näytä _ohjelmalliset tunnisteet" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Näytä kaikki tunnisteet, mukaan lukien koneellisesti luodut, kuten " "MusicBrainz- tai Replay Gain -tunnisteet" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Näytä _moniriviset tunnisteet" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "Näytä myös mahdollisesti moniriviset tunnisteet (esim. ”lyrics”)" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Palauta" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Tallenna" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Asetukset" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Jaa tunniste" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Kopioi arvo(t)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Tunnistetta ei voi lisätä" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "Tunnistetta %s ei voi lisätä" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Valitut tiedostot eivät tue useaa arvoa tunnisteelle %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Virheellinen tunniste" msgstr[1] "Virheelliset tunnisteet" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Virheellinen tunniste %s\n" "\n" "Valitut tiedostot eivät tue tämän tunnisteen muokkaamista." msgstr[1] "" "Virheelliset tunnisteet %s\n" "\n" "Valitut tiedostot eivät tue näiden tunnisteiden muokkaamista." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Virheellinen arvo" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Virheellinen arvo: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tunniste saattaa olla epätarkka" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s muuttui ohjelman ollessa käynnissä. Jos tallennat " "päivittämättä kirjastoa, saatat korvata muita kappaleeseen tehtyjä muutoksia." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Kappaletta ei voi tallentaa" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Tiedoston %(file-name)s tallentaminen epäonnistui. Tiedosto saattaa olla " "vain luku -muodossa, viallinen, tai sen muokkaamiseen ei ole oikeuksia." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Lisäasetukset…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Kumoa" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Tee uudelleen" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Tietoja" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "Tarkista _päivitykset…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "Liitä_nnäiset" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s ja %(count)s muu" msgstr[1] "%(title)s ja %(count)s muuta" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falson asetukset" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Kansiot" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Uusi kansio…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Valitse kaikki alikansiot" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Uusi kansio" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Anna uuden kansion nimi:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Kansiota ei voi luoda" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Kansiota ei voi poistaa" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Kappaleet" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "%s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Levy %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Raita %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Nykyinen kappale" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Muokkaa näkymää…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ei kappaleita valittuna." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Ei kappaleita" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Tiedot" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Sanat" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Tuottanut %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artisti" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistit" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "esittäjät" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Ei koskaan" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d kerran" msgstr[1] "%(n)d kertaa" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "lisätty" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "viimeksi toistettu" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "toistokertoja" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "ohituksia" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "arvosana" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "polku" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "kesto" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "muoto" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "koodekki" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "enkoodaus" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bittinopeus" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "tiedostokoko" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "muokattu" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Lisätiedot" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valittu" msgstr[1] "%d valittu" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Raita ei ole käytettävissä" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d albumiton kappale" msgstr[1] "%d albumitonta kappaletta" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Valittu diskografia" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d kappale, jonka artisti tuntematon" msgstr[1] "%d kappaletta, joiden artisti tuntematon" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumit" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Kesto yhteensä:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Koko yhteensä:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Tiedostot" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Näytä verkossa" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Kappaleelle ei löydy sanoja." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Haluatko varmasti poistaa kaikki kappaleet?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Valitut kappaleet poistetaan kirjastosta." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Palauta" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Palauta" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Tarkista, että vasemmanpuoleisten sarakkeiden tiedot vastaavat suunnilleen " "oikeanpuoleisten sarakkeiden tietoja. Muuta tarvittaessa rivien järjestystä " "(käytä merkintää ”_” riveille, joita ei pidä täsmäyttää):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Oikean puolen järjestys:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Hylkää muutokset tunnisteisiin?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tunnisteita on muutettu, mutta ei tallennettu. Tallennetaanko tiedostot, vai " "hylätäänkö muutokset ja palautetaan vanhat arvot?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Palauta" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Tiedosto on olemassa" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Korvaa %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Korvaa tiedosto" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktiiviset tehtävät" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d tehtävää käynnissä" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Sekoitus päälle/pois" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Kertaus päälle/pois" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Tapahtumat" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Toistojärjestys" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Muokkaus" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Uudelleennimeäminen" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Kyselyiden teko" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Kansikuvat" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Liitännäisten virheet" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Kaikki tilat" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Käytössä olevat" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Käytöstä poistetut" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Ei tyyppiä" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Kaikki tyypit" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Liitännäisiä ei löytynyt." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Liitännäiset" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Suodata liitännäisen tilan / tunnisteen perusteella" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Suodata liitännäisen tyypin perusteella" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Suodata liitännäisen nimen tai kuvauksen perusteella" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Näytä _virheet" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Levy" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Raita" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "_Ryhmittely" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artisti" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bumi" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Tie_dostonimi" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Kesto" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Hyppää toistettavaan kappaleeseen automaattisesti" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Kun toistettava kappale vaihtuu, vieritä kappalelista sen kohdalle" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "_Järjestä kappaleet kun tunnisteita muokataan" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" "Järjestä kappalelistalla olevat kappaleet automaattisesti uudelleen kun " "tunnisteita muokataan" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Salli järjestäminen aina" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "Salli järjestäminen sarakeotsakkeiden mukaan, myös soittolistoille jne." #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "M_uut:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Muokkaa…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Lisää tai poista sarakeotsakkeita" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Näytettävät sarakkeet" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Nimi sisältää v_ersion" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albumi sisältää _levyn alaotsikon" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Artisti sisältää kaikki tekijät" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Tiedostonimi sisältää _kansion" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Sarakeasetukset" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Päivitä sarakkeet" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "Käytä asetuksia kappalelistassa. Uudet sarakkeet lisätään loppuun." #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Kappalelista" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Muokkaa sarakkeita" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Yhteiskesto" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Yleissuodatin:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Käytä tätä hakua kaikkien muiden lisäksi" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Haku" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Selaimet" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Kysy _varmistusta usealle arvosanalle" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Kysy varmistusta ennen usean kappaleen arvosanan muuttamista kerralla" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Salli yhden napsautuksen arvostelu" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Salli arvostelu napsauttamalla arvosana-saraketta kappalelistassa" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Arvosanat" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Suosi _upotettuja kansikuvia" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Käytä ensisijaisesti tiedostoon upotettua kansikuvaa, jos sellainen on " "käytettävissä" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Käytettävät albumien kansikuvatiedostot, jos ovat olemassa (tukee " "jokerimerkkejä). Erota useampi tiedostonimi toisistaan pilkulla." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Ensisijaiset kiinteät kuvatiedostonimet" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumien kansikuvat" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Toisto" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Ulostulon asetukset" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Jos kappaleella ei ole Replay Gain -tietoa, säädä äänenvoimakkuutta tämän " "arvon verran" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Oletusvahvistus:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Säädä äänenvoimakkuutta kaikille kappaleille tämän arvon verran, kunhan ääni " "ei leikkaannu" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Esivahvistus:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Käytä Replay Gain -äänenvoimakkuuden säätöä" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain -äänenvoimakkuuden säätö" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Jatka toistoa käynnistettäessä" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Jos toisto on käynnissä ohjelmaa suljettaessa, toisto aloitetaan uudestaan " "automaattisesti seuraavalla käynnistyskerralla" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Oletusarvosana:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "A_rvosteluasteikko:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesin keskiarvokaavan vakio (C) kootuille arvosanoille.\n" "Arvo 0 vastaa perinteistä keskiarvoa. Suuremmilla arvoilla albumit, joilla " "on vähän raitoja, eivät saa yhtä äärimmäisiä arvosanoja. Jos tätä arvoa " "muutetaan, kaikkien albumien arvosanat lasketaan uudelleen." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesin keskiarvotekijä:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Sähköposti:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Arvosanat ja toistokertojen määrät asetetaan tälle osoitteelle" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "Tallenna muutokset tunnisteisiin _automaattisesti" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Tallenna muutokset tunnisteisiin ilman varmistusta muokattaessa useampaa " "tiedostoa" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Erotinmerkit, joita käytetään jaettaessa tunnisteiden arvoja osiin. Erota " "merkit välilyönnillä toisistaan." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "_Tunniste-erottimet:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Erotinmerkkiparit, joita käytetään alitunnisteiden erottamiseen tunnisteista " "tunniste-editorissa. Erota parit välilyönnillä toisistaan. Jokaisen parin on " "muodostuttava vain kahdesta merkistä." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "_Alitunniste-erottimet:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tunnisteet" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tunnisteiden muokkaus" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Päivitetään arvosanoja" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Päivitä kirjasto" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Etsi muutoksia kirjastosta" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Rakenna kirjasto _uudelleen" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Käy läpi kaikki kirjaston kappaleet uudelleen (tämä saattaa kestää kauan)" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Piilotetut kappaleet" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "_Päivitä kirjasto käynnistyksen yhteydessä" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "_Seuraa muutoksia kansioissa" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Seuraa tiedostojen lisäyksiä, poistoja ja uudelleennimeämisiä " "kirjastokansioissa." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Luettavat kansiot" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s ja %(count)d muu" msgstr[1] "%(title)s ja %(count)d muuta" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Ominaisuudet" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "J_ono" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Tyhjennä jono" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Poista jono käytöstä – jono jätetään huomiotta toistettaessa" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Väliaikainen" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Poista kappaleet jonosta kun ne on soitettu" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Pysyvä" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Pidä kappaleet jonossa kun ne on soitettu" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Tila" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Pysäytä lopuksi" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d kappale (%(time)s)" msgstr[1] "%(count)d kappaletta (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Selaa kirjastoa" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Näytä / piilota jono" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Toistovirhe" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Määritä kirjaston kansiot" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Musiikkikirjastoa ei ole määritetty. Tehdäänkö se nyt?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Ei nyt" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Määritä" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Kappaleita ei voi lisätä" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "Kohteen %s käyttämää protokollaa ei tueta." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Hyppää toistettavaan kappaleeseen" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Tiedosto" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Kappale" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Näytä" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Selaa" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "O_hjaus" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Ohje" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "Lisää _kansio…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Lisää _tiedosto…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Lisää _sijainti…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Muokkaa kirjanmerkkejä…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Pysäytä" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Pysäytä tämän kappaleen jälkeen" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Pikanäppäimet" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Ohje verkossa" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Ohje hakujen tekemiseen" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Lisää sijainti" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Anna äänitiedoston sijainti:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Sijaintia ei voi lisätä" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s ei ole kelvollinen sijainti." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Lisää musiikkia" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "Lisää _kansioita" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Musiikkitiedostot" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "Lisää _tiedostoja" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Haluatko varmasti lisätä jonoon %d kappaleen?" msgstr[1] "Haluatko varmasti lisätä jonoon %d kappaletta?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Lisää jonoon" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Haluatko varmasti muuttaa %d kappaleen arvosanaa?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Tallennetut arvosanat poistetaan" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Poista arvosana" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Valittujen kappaleiden arvosanaksi asetetaan %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Muuta arvosanaa" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Korvaa _välilyönnit alaviivoilla" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Korvaa kaksois- tai puolipiste erottimena viivalla" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "esim. ”iv: allegro.flac” → ”iv - allegro.flac”" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Poista _Windows-yhteensopimattomat merkit" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Poista ta_rkkeet" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Poista _ASCII:hin kuulumattomat merkit" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Käytä vain pieniä kirjaimia" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Nimeä tiedostot" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Esikatsele" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Tiedostonimet" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Siirrä kansikuvat" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Katso asetus ”[albumart] filenames”, jossa määritetään kuvien hakulausekkeet" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Ylikirjoita kohdenimellä olevat kansikuvat" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Poista tyhjät kansiot" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Albumien kansikuvat" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Uusi nimi" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Tiedoston nimeäminen ei onnistu" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Nimeäminen lähteestä %(old-name)s kohteeseen %(new-name)s ei onnistu. " "Kohdetiedosto on mahdollisesti jo olemassa, tai uuden tiedoston luomiseen " "tai vanhan poistamiseen ei ole oikeuksia." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ohita kaikki virheet" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Pysäytä" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Jatka" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Polku ei ole absoluuttinen" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Kaava\n" "\t%s<\n" "sisältää merkin /, mutta ei ala juurihakemistosta. Välttääksesi kansioiden " "nimeämisen väärin, aloita kaavasi merkeillä / tai ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Näissä kansioissa olevat kappaleet lisätään kirjastoon, kun kirjasto " "päivitetään" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Uusi kansio luetaan lisäämisen jälkeen" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Kaikki valituissa kansioissa olevat kappaleet poistetaan kirjastosta" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Siirrä" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Siirrä luettava kansiopolku (mutta ei tiedostoja), migroiden samalla myös " "kappaleiden metatiedot." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Poista {dir!r} ja kaikki sen kappaleet?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Poistetaanko {n} kirjaston kansiota ja niiden kappaleet?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Poistetaanko kirjaston kansio?" msgstr[1] "Poistetaanko kirjaston kansiot?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Poista" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Valitse kansiot" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Valitse tämä kansio" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Valitse todellinen / uusi kansio kohteelle {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Quod Libetin metatiedot siirretään seuraavasti:\n" "\n" "{old!r} → {new!r}\n" "\n" "Tiedostoja itsessään ei siirretä.\n" "Varmuuskopion ottaminen on joka tapauksessa suositeltavaa (myös Quod Libetin " "”songs”-tiedostosta)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Siirretäänkö luettava kansiopolku {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "OK, siirrä" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Tallennetut haut" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Muokkaa tallennettuja hakuja…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Hae kirjastosta vapaalla tekstihaulla tai käyttäen QL-kyselyitä" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Päivitä hakutuloksia jatkuvasti" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Päivitä haun tuloksia jatkuvasti kirjoituksen aikana" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Määrä:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Painota arvosanalla" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Lisää kysely" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Lisää QL-kysely tai vapaa teksti hakuehtoon" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Näytä jäljellä oleva aika" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Pääikkuna" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Siirry taaksepäin 10 sekuntia" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Siirry eteenpäin 10 sekuntia" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Kohdista hakukenttään" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Tyhjennä suodattimet ja hyppää toistettavan kappaleen kohdalle" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Avaa tietoikkuna valituille kappaleille" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Avaa tunniste-editori valituille kappaleille" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Lisää valitut kappaleet jonoon" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Poista valitut kappaleet" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Näytä pikahakukenttä" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Vasen napsautus sarakeotsakkeen päällä" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Käytä saraketta järjestämiseen (usean valinta mahdollinen)" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Puunäkymä" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Supista taso tai valitse ylätaso" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Laajenna taso" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Tekstikentät" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Kumoa viimeisin muutos" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Tee uudelleen viimeisin kumottu muutos" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Valitse kaikki kappaleet kaikissa paneeleissa" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Suodata sarakkeen %s perusteella" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Kaikki _otsakkeet" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Raitaotsakkeet" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumiotsakkeet" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Tekijäotsakkeet" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Ai_kaotsakkeet" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Tie_dosto-otsakkeet" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "T_uotanto-otsakkeet" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Mukauta otsakkeita…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Laajenna sarake" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Poistetaanko kappale ”%(title)s” kirjastosta?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Poistetaanko %(count)d kappaletta kirjastosta?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Poista kirjastosta" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Suoritetaanko liitännäinen ”%(name)s” %(count)d kappaleelle?" msgstr[1] "Suoritetaanko liitännäinen ”%(name)s” %(count)d kappaleelle?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Suoritetaanko liitännäinen ”%(name)s” %(count)d albumille?" msgstr[1] "Suoritetaanko liitännäinen ”%(name)s” %(count)d albumille?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Liitännäisten asetukset…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Lisää _jonoon" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Poista kirjastosta…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Tiedostojen näyttäminen epäonnistui" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Tiedostojen näyttämisessä tapahtui virhe tai niiden näyttämiseen ei ole " "sopivaa ohjelmaa." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Näytä tiedostonhallinnassa" msgstr[1] "_Näytä %(total)d tiedostoa tiedostonhallinnassa" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Lataa tiedosto…" msgstr[1] "_Lataa %(total)d tiedostoa…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "onnistui" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "epäonnistui" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Lataukset valmiit" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Lataa {name!r} kansioon" msgstr[1] "Lataa {total} tiedostoa kansioon" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Lataa tänne" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Korvaa alaviivat _välilyönneillä" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Isot alkukirjaimet tunnisteisiin" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Jaa _useampaan arvoon" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tunnisteet polusta" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tunnisteet korvaavat jo olemassa olevat" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tunnisteet lisätään jo olemassa oleviin" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Kaava\n" "\t%s\n" "on virheellinen. Se saattaa sisältää saman tunnisteen kahdesti tai " "parittomia kulmasulkumerkkejä (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Annettu kaava ei kelpaa. Varmista, että merkit < ja > ovat muodossa " "\\< ja \\> ja että tunnisteita ei jää sulkematta.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Muokkaa näkymää" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Raitanumerot" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Aloita _luvusta:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Raitoja _yhteensä:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Toista/keskeytä" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Edellinen" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "ja %d muuta…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Tallennetaan muutettuja kappaleita." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d kappaletta tallennettu\n" "(%(remaining)s jäljellä)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s/%(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Tarkistetaan päivityksiä" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Yhteyden muodostaminen epäonnistui" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Käytössä on jo uusin versio %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Uusi versio %(new-version)s on saatavilla\n" "\n" "Tällä hetkellä käytössä on versio %(old-version)s\n" "\n" "Käy <a href='%(url)s'>kotisivulla</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Tyhjä soittolista" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Soittolistoilla täytyy olla nimi" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Soittolista nimeltä %(name)s on jo olemassa polussa %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Upotetut albumien _kannet" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Käyttää äänitiedostoihin upotettuja kansikuvia." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Kansikuva tiedostojärjestelmästä" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Käyttää tavanomaisesti nimettyjä kuvia kappaleen yhteydessä olevista " "kansioista." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Kansikuvat" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Lähetetään kyselyä kansikuvalähteille" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Näytä lyhyt käyttöohje" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Näytä versio ja tekijänoikeustiedot" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Kirjoita virheenkorjaustiedot" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Käyttö: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[valitsimet]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Valitsin %r ei kelpaa." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Valitsin %r vaatii argumentin." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r ei ole yksikäsitteinen etuliite." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekunti" msgstr[1] "%s sekuntia" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Ei aikatietoa" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunti" msgstr[1] "%d sekuntia" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuutti" msgstr[1] "%d minuuttia" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d tunti" msgstr[1] "%d tuntia" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d päivä" msgstr[1] "%d päivää" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d vuosi" msgstr[1] "%d vuotta" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "no" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Päivämäärä täytyy antaa muodossa ”VVVV”, ”VVVV-KK-PP” tai ”VVVV-KK-PP HH:MM:" "SS”." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain -vahvistukset annetaan muodossa ”x.yy dB”." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain -huiput annetaan muodossa ”x.yy”." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz-kappaletunnisteiden on oltava UUID-muodossa." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-julkaisun tilaksi kelpaa ”official”, ”promotional” tai ”bootleg”." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Kielen täytyy olla ISO 639-2:n mukainen kolmikirjaiminen koodi" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Tallennetaan %d tiedosto" msgstr[1] "Tallennetaan %d tiedostoa" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Automaattinen tallennus" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Kappaleen muokkaaminen epäonnistui" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Kappaleen %s tallentaminen epäonnistui. Tiedosto saattaa olla vain luku -" "muodossa, viallinen, tai sen muokkaamiseen ei ole oikeuksia." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Virheellinen koodaus]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "albumi" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "sovittaja" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "sovittajat" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "sovitus" #: quodlibet/util/tags.py:86 msgid "author" msgstr "tekijä" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "tekijät" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "kommentti" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "säveltäjä" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "säveltäjät" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "sävellys" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "kapellimestari" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "kapellimestarit" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "orkesterinjohto" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "yhteystieto" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "tekijänoikeus" #: quodlibet/util/tags.py:93 msgid "date" msgstr "päivämäärä" #: quodlibet/util/tags.py:94 msgid "description" msgstr "kuvaus" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "tyylilaji" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "tyylilajit" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "esittäjä" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "esitys" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "ryhmittely" #: quodlibet/util/tags.py:98 msgid "language" msgstr "kieli" #: quodlibet/util/tags.py:99 msgid "license" msgstr "lisenssi" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "sanoittaja" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "sanoittajat" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "sanat" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisaatio" #: quodlibet/util/tags.py:104 msgid "title" msgstr "nimi" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versio" #: quodlibet/util/tags.py:106 msgid "website" msgstr "verkkosivusto" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albumin artisti" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM (iskua minuutissa)" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "levyn alaotsikko" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "levy" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "raita" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "Levykoodi" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "alkuperäinen julkaisupvm" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "alkuperäinen albumi" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "alkuperäinen artisti" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "nauhoituspäivämäärä" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "julkaisumaa" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "alkusävellaji" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainzin äänitteen tunniste" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainzin julkaisukappaleen tunniste" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainzin julkaisun tunniste" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainzin artistin tunniste" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainzin julkaisuartistin tunniste" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainzin TRM-tunniste" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainzin albumin tila" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainzin albumin tyyppi" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainzin julkaisuryhmän tunniste" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "raidan vahvistus" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "raidan huippu" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albumin vahvistus" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albumin huippu" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "voimakkuuden vertailuarvo" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "levyjä" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "raitoja" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "toisto viimeksi aloitettu" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "Koko polku" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "liitoskohta" #: quodlibet/util/tags.py:166 msgid "people" msgstr "tekijät" #: quodlibet/util/tags.py:168 msgid "year" msgstr "vuosi" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "alkuperäinen julkaisuvuosi" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "kirjanmerkki" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bittisyvyys" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "tiedostomuoto" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "soittolistat" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "näytteenottotaajuus" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "kanavien lkm" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "järjestys" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "roolit" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Äänitiedostojen tunniste-editori" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Muokkaa äänitiedostojesi tunnisteita" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musiikkitoistin" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Kuuntele, selaa tai muokkaa äänikokoelmaasi" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso on tunniste-editori Quod Libetin kanssa yhteisellä tunnisteiden " "muokkausnäkymällä. Sen avulla voi katsella ja muokata kaikkien tuettujen " "tiedostomuotojen tunnisteita." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Tuettuihin tiedostomuotoihin kuuluvat Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, " "MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet on musiikinhallintaohjelma. Se tarjoaa useita eri tapoja selata " "musiikkikirjastoasi ja tukee myös Internet-radioita ja äänisyötteitä. Siinä " "on hyvin joustavat metatietotunnisteiden muokkaus- ja hakuominaisuudet." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Vie soittolistan Sonos-soittolistaksi edellyttäen, että molemmilla on " #~ "sama hakemistorakenne." #~ msgid "Export to Sonos playlist" #~ msgstr "Vie Sonos-soittolistaksi" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Tunnistetta <b>%s</b> ei voi lisätä" #~ msgid "Invalid tags" #~ msgstr "Tunnisteet eivät kelpaa" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Tunnisteet <b>%s</b> eivät kelpaa\n" #~ "\n" #~ "Valitut tiedostot eivät tue näiden tunnisteiden muokkaamista." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Arvostelee kappaleita automaattisesti kun ne toistetaan tai ohitetaan. " #~ "Käyttää accelerated-algoritmia ohjelmasta vux, jonka on kehittänyt Brian " #~ "Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekuntia" #~ msgid "Startup" #~ msgstr "Käynnistys" #~ msgid "Audio Feeds" #~ msgstr "Äänisyötteet" #~ msgid "_Audio Feeds" #~ msgstr "Äänis_yötteet" #~ msgid "New" #~ msgstr "Uusi" #~ msgid "Automatic Library Update" #~ msgstr "Automaattinen kirjaston päivitys" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "" #~ "Pitää kirjaston ajan tasalla käyttämällä inotify-toimintoa. Vaatii " #~ "kirjaston %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Mahdollistaa Quod Libetin hallinnan käyttäen MPRIS 2 D-Bus -" #~ "rajapintamäärittelyä." #~ msgid "Searching for lyrics…" #~ msgstr "Etsitään laulun sanoja…" #~ msgid "broker username" #~ msgstr "välittäjän käyttäjätunnus" #~ msgid "broker password" #~ msgstr "välittäjän salasana" #~ msgid "<artist>" #~ msgstr "<artisti>" #~ msgid "<album>" #~ msgstr "<albumi>" #~ msgid "<title>" #~ msgstr "<nimi>" #~ msgid "OK" #~ msgstr "OK" #~ msgid "" #~ "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " #~ "both share a directory structure. Shares configuration with <a href=" #~ "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</" #~ "a>." #~ msgstr "" #~ "Vie soittolistan dynaamisesti Logitech Squeezebox -soittolistaksi, " #~ "olettaen, että Squeezebox jakaa Quod Libetin kanssa saman " #~ "kansiorakenteen. Asetukset ovat yhteisiä <a href=\"quodlibet:///prefs/" #~ "plugins/Squeezebox Output\">Squeezebox-synkronointilisäosan</a> kanssa." #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Vie valittujen kappaleiden metatiedot .tags-tiedostoon." #~ msgid "Import Metadata" #~ msgstr "Tuo metatietoja" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Tuo valituille kappaleille metatiedot .tags-tiedostosta." #~ msgid "Migrate Metadata" #~ msgstr "Siirrä metatietoja" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Kopioi Quod Libet -metatietoja kappaleiden välillä." #~ msgid "_Copy" #~ msgstr "_Kopioi" #~ msgid "_Paste" #~ msgstr "_Liitä" #~ msgid "Information to copy/paste" #~ msgstr "Kopioitavat/liitettävät tiedot" #~ msgid "Map tracks by disc and track number" #~ msgstr "Yhdistä kappaleet levy- ja raitanumeron perusteella" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Valitse tämä, kun haluat kopioida metatietoja albumista toiseen " #~ "täsmäävien levy- ja raitanumeroiden perusteella.\n" #~ "\n" #~ "<b>Huom.:</b> valinnan täytyy olla päällä kopiointivaiheessa, jotta " #~ "kappaletiedot tulevat mukaan." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "%d tallennettu kappale." #~ msgstr[1] "%d tallennettua kappaletta." #~ msgid "Unsupported file type" #~ msgstr "Tiedostomuotoa ei tueta" #~ msgid "Unable to add station" #~ msgstr "Asemaa ei voitu lisätä" #~ msgid "Search Library" #~ msgstr "Hae kirjastosta" #~ msgid "_Search Library" #~ msgstr "_Hae kirjastosta" #~ msgid "Quit Program" #~ msgstr "Poistu ohjelmasta" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Estä GNOME-näytönsäästäjää aktivoitumasta toiston ollessa käynnissä." #~ msgid "No lyrics found" #~ msgstr "Kappaleelle ei löydy sanoja" #~ msgid "_Zoom level:" #~ msgstr "_Suurennuksen taso:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Etsi yllä olevan URLin kautta jos kappaleen sanoja ei löytynyt " #~ "LyricsWikiasta." #~ msgid "Alternate search" #~ msgstr "Vaihtoehtoinen haku" #~ msgid "Web Lyrics" #~ msgstr "Kappaleen sanat verkosta" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Näyttää sivupalkin, jossa on verkosta haetut toistettavan kappaleen sanat." #~ msgid "Skip Songs" #~ msgstr "Ohita kappaleet" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Ohita kappaleet, joiden arvosana on pienempi tai yhtä suuri kuin annettu " #~ "arvo." #~ msgid "Burn CD" #~ msgstr "Polta CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Polttaa CD-levyjä K3b-, Brasero- tai xfburn-ohjelmalla." #~ msgid "The single image filename to use if selected" #~ msgstr "Jos määritetty, vain tätä kuvatiedostonimeä käytetään" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "Kuvatiedostonimi, jota käytetään pakotetusti (tukee jokerimerkkejä)" #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Tukee QL-kaavoja\n" #~ "esim. eg <tt><~artist~title></tt>" #~ msgid "_Wide Mode" #~ msgstr "_Leveä tila" #~ msgid "Rate the playing song" #~ msgstr "Arvostele soiva kappale" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Näytä tai piilota pääkappalelista (vanhentunut)" #~ msgid "Top of screen" #~ msgstr "Ruudun yläreuna" #~ msgid "Middle of screen" #~ msgstr "Ruudun keskiosa" #~ msgid "Bottom of screen" #~ msgstr "Ruudun alareuna" #~ msgid "_Clear" #~ msgstr "_Nollaa" #~ msgid "Search Artist in Wikipedia" #~ msgstr "Hae artistia Wikipediasta" #~ msgid "" #~ "Opens a browser window with the Wikipedia article on the playing song's " #~ "artist." #~ msgstr "" #~ "Avaa selainikkunan, jossa näytetään Wikipedia-artikkeli toistettavan " #~ "kappaleen artistista." #~ msgid "" #~ "Opens a browser window with the Wikipedia article on the playing song's " #~ "album." #~ msgstr "" #~ "Avaa selainikkunan, jossa näytetään Wikipedia-artikkeli toistettavan " #~ "kappaleen albumista." #~ msgid "Search Composer in Wikipedia" #~ msgstr "Hae säveltäjää Wikipediasta" #~ msgid "Ignore" #~ msgstr "Jätä jono huomiotta" #~ msgid "Keep Songs" #~ msgstr "Pidä kappaleet jonossa" #~ msgid "File Bug Report" #~ msgstr "Lähetä bugiraportti" #~ msgid "Browse Folders" #~ msgstr "Selaa kansioita" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Avaa kappaleiden kansiot tiedostonhallintasovelluksessa." #~ msgid "Unable to open folders" #~ msgstr "Kansioita ei voitu avata" #~ msgid "No program available to open folders." #~ msgstr "Ei ohjelmaa kansioiden avaamiseen." #~ msgid "Fix MP3 Duration" #~ msgstr "Korjaa MP3-kappaleen pituus" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Poistaa ID3-tunnisteista TLEN-kehykset, jotka voivat aiheuttaa kappalen " #~ "pituuden tulkitsemisen väärin." #~ msgid "Audio device: %s" #~ msgstr "Äänilaite: %s" #~ msgid "Downloads" #~ msgstr "Lataukset" #~ msgid "Size" #~ msgstr "Koko" #~ msgid "Stop Once Empty" #~ msgstr "Pysäytä, kun jono tyhjä" #~ msgid "Lyrics:" #~ msgstr "Sanat:" #~ msgid "Lyrics Window" #~ msgstr "Kappaleen sanat -ikkuna" #~ msgid "_Lyrics" #~ msgstr "_Sanat" #~ msgid "" #~ "Use Python expressions in queries. Syntax is '@(python: expression)'. The " #~ "variable 's' is the song being matched." #~ msgstr "" #~ "Käyttää Python-lausekkeita kyselyissä. Syntaksi: @(python: lauseke). " #~ "Muuttuja ”s” on täsmäytettävä kappale." #~ msgid "_Download" #~ msgstr "_Lataa" #~ msgid "Device Properties" #~ msgstr "Laitteen ominaisuudet" #~ msgid "Device:" #~ msgstr "Laite:" #~ msgid "Not mounted" #~ msgstr "Ei liitetty" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Liitoskohta:" #~ msgid "Media Devices" #~ msgstr "Medialaitteet" #~ msgid "_Media Devices" #~ msgstr "_Medialaitteet" #~ msgid "_Eject" #~ msgstr "_Irrota laite" #, fuzzy #~ msgid "_Properties" #~ msgstr "Ominaisuudet" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> käytössä, <b>%s</b> vapaana" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> ei ole yhdistetty." #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Kopioidaan <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "Kappaletta ei voi kopioida" #~ msgid "There is not enough free space for this song." #~ msgstr "Kappaleelle ei ole riittävästi tilaa." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "Kohdetta <b>%s</b> ei voitu kopioida." #~ msgid "Unable to delete songs" #~ msgstr "Kappaleita ei voi poistaa" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Poistetaan <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "Kohdetta <b>%s</b> ei voitu poistaa." #~ msgid "Unable to delete song" #~ msgstr "Kappaletta ei voi poistaa" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Laitteen <b>%s</b> irrottaminen epäonnistui." #~ msgid "Unable to eject device" #~ msgstr "Laitetta ei voi irrottaa" #~ msgid "Unknown Device" #~ msgstr "Tuntematon laite" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "VIRHE: '%s' ei ole ainutkertainen etuliite." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Virheellinen arvo" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Tiedoston hakukuvio:" #~ msgid "_Copy to Device" #~ msgstr "_Kopioi laitteeseen" #, fuzzy #~ msgid "browsers" #~ msgstr "Selaimet" #~ msgid "Unable to download lyrics." #~ msgstr "Laulun sanojen lataaminen ei onnistu" #~ msgid "Remove all songs from the queue" #~ msgstr "Poista kaikki kappaleet jonosta" #~ msgid "Set or toggle the playback order" #~ msgstr "Aseta tai vaihda soittojärjestystä" #~ msgid "Uninitialized iPod" #~ msgstr "Alustamaton iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Haluatko luoda iPodiin tyhjän tietokannan?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Äänen vahvistus (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Yhdistä _moniarvoiset tunnisteet" #~ msgid "Capacity:" #~ msgstr "Tallennustila:" #~ msgid "Firmware:" #~ msgstr "Laiteohjelmisto:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "iPod-tietokantaa ei voi tallentaa" #~ msgid "Unable to save iPod database" #~ msgstr "iPod-tietokantaa ei voi tallentaa" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "raidan huippu" #~ msgid "Shuffle" #~ msgstr "Sekoitettu" #~ msgid "Weighted" #~ msgstr "Painotettu" #~ msgid "_Weighted" #~ msgstr "_Painotettu" #~ msgid "_One Song" #~ msgstr "_Yksi kappale" #~ msgid "Restart the playlist when finished" #~ msgstr "Aloita soittolista alusta, kun kaikki kappaleet on soitettu" #~ msgid "Disable Browser" #~ msgstr "Sulje selain" #~ msgid "_Disable Browser" #~ msgstr "S_ulje selain" #, fuzzy #~ msgid "Force Write" #~ msgstr "Kirjoita" #~ msgid "Filter on _Genre" #~ msgstr "Suodata t_yylilajin perusteella" #~ msgid "Filter on _Artist" #~ msgstr "Suodata _artistin perusteella" #~ msgid "Filter on Al_bum" #~ msgstr "Suodata al_bumin perusteella" #~ msgid "_Music" #~ msgstr "_Musiikki" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Kirjanmerkit" #~ msgid "Song _List" #~ msgstr "_Kappalelista" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Pysäytä tämän kappaleen jälkeen" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "ja %d muuta..." #~ msgstr[1] "ja %d muuta..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Erota levyn numero _albumin nimestä" #, fuzzy #~ msgid "Timeout" #~ msgstr "Aika" #, fuzzy #~ msgid "Select an album" #~ msgstr "Valitse _Kaikki" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s ja %(count)d muuta" #~ msgstr[1] "%(title)s ja %(count)d muuta" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Soittolistat" #~ msgid "Re_fresh Library" #~ msgstr "_Virkistä kirjasto" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Ar_vosana" #, fuzzy #~ msgid "Unable to open input files" #~ msgstr "Tiedostojen avaaminen ei onnistu" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Virheellinen arvo" #, fuzzy #~ msgid "ql-revert" #~ msgstr "P_oista kirjastosta" #~ msgid "command|filename" #~ msgstr "tiedostonimi" #~ msgid "command|tag" #~ msgstr "tunniste" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Hae" #~ msgid "%d of %d" #~ msgstr "%d/%d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Käyttö: %s %s" #~ msgid "_Download..." #~ msgstr "_Lataa..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Uusi kanava" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Korvataanko <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet on jo käynnissä" #~ msgid "No song is currently playing." #~ msgstr "Ei kappaletta soitossa." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Kohteeseen %s ei voi kirjoittaa. Poistetaan." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Muokkaa kirjanmerkkejä..." #~ msgid "_New Folder..." #~ msgstr "_Uusi kansio..." #~ msgid "_Add to Playlist" #~ msgstr "_Lisää soittolistaan" #~ msgid "_Edit Display..." #~ msgstr "_Muokkaa näkymää..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d kanava" #~ msgid "_Add a Location..." #~ msgstr "Lisää s_ijainti..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Mukauta otsakkeita..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Raitaotsakkeet" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Tekijäotsakkeet" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Albumiotsakkeet" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Ai_kaotsakkeet" #, fuzzy #~ msgid "File Headers" #~ msgstr "Tie_dosto-otsakkeet" #, fuzzy #~ msgid "Production Headers" #~ msgstr "T_uotanto-otsakkeet" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tunniste:" #, fuzzy #~ msgid "Warnings" #~ msgstr "Ar_vosana" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "albumin artisti" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artistit" #, fuzzy #~ msgid "album (sort)" #~ msgstr "albumin artisti" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "esittäjää" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "esittäjää" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz albumin artistin tunniste" #~ msgid "errors" #~ msgstr "virheet" #~ msgid "Permanently delete this file?" #~ msgstr "Poistetaanko tiedosto lopullisesti?" #~ msgid "Permanently delete these files?" #~ msgstr "Poistetaanko tiedostot lopullisesti?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s ja %(count)d muu..." #~ msgstr[1] "%(title)s ja %(count)d muuta..." #, fuzzy #~ msgid "Version:" #~ msgstr "versio" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "Tyhje_nnä virheet" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "Kohdetta %s ei voitu lisätä kirjastoosi.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Irrotuskomentoa ei löytynyt." #~ msgid "Unable to start web browser" #~ msgstr "Web-selainta ei voi käynnistää" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Web-selainta ei löydy. Aseta $BROWSER-muuttujasi, tai varmista, että /usr/" #~ "bin/sensible-browser on olemassa." #, fuzzy #~ msgid "Library Error" #~ msgstr "Kirjaston selain" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Kopioi laitteeseen" #~ msgid "translator-credits" #~ msgstr "Jari Rahkonen <jari.rahkonen@pp1.inet.fi>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Muut näytettävät sarakkeet välilyönneillä erotettuna" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Jatka" #~ msgid "Search your library" #~ msgstr "Hae kirjastostasi" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, ja muut\n" #~ "\n" #~ "Tämä on vapaa ohjelma; kopiointiehdot löydät lähdekoodista. " #~ "Minkäänlaista\n" #~ "takuuta EI ole; ei edes koskien KAUPPAKELPOISUUTTA tai TIETTYYN " #~ "TEHTÄVÄÄN\n" #~ "SOVELTUVUUTTA.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Koko yhteensä:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libetin liitännäiset" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Näytä yksinkertaiset haut sinisinä, erityishaut vihreinä ja virheelliset " #~ "haut punaisina" #~ msgid "Separators for splitting tags" #~ msgstr "Erottimet tunnisteiden katkaisemiseen" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libetin asetukset" #~ msgid "Not Played To_day" #~ msgstr "Ei soitettu _tänään" #~ msgid "Not Played in a _Week" #~ msgstr "Ei soitettu _viikkoon" #~ msgid "Not Played in a _Month" #~ msgstr "Ei soitettu _kuukauteen" #~ msgid "B_ottom 40" #~ msgstr "_Viimeiset 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "40 vähiten soittamaasi kappaletta (tasapelitilanteissa saatetaan valita " #~ "enemmän kuin 40)" #~ msgid "gtk-media-next" #~ msgstr "S_euraava" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Päivämäärä" #~ msgid "Choose New Stations" #~ msgstr "Valitse uusia kanavia" #~ msgid "Add" #~ msgstr "Lisää" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bittinopeus" #~ msgid "_Stations..." #~ msgstr "_Kanavat..." #~ msgid "Unable to save library" #~ msgstr "Kirjastoa ei voi tallentaa" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Kappaletta ei voi soittaa" #~ msgid "Sort by title" #~ msgstr "Järjestys: nimi" #~ msgid "Sort by artist" #~ msgstr "Järjestys: artisti" #~ msgid "Lyrics provided by %s." #~ msgstr "Laulun sanat tarjoaa %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Laulun sanoja ei löytynyt.\n" #~ "\n" #~ "Voit pyytää Quod Libetiä etsimään sanoja verkosta Lataa-painikeella. Voit " #~ "myös syöttää ne itse ja klikata sitten tallennuspainiketta." #~ msgid "part" #~ msgstr "osa" #~ msgid "Opening audio device." #~ msgstr "Avataan äänilaite." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d kappaletta tallennettu" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz albumin tunniste" #~ msgid "Loaded song library." #~ msgstr "Musiikkikirjasto ladattu." #~ msgid "Unable to open audio device" #~ msgstr "Äänilaitetta ei voi avata" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet yritti käyttää ajureita 'autosink' ja '%(sink)s', mutta niiden " #~ "avaaminen ei onnistunut. Aseta GStreamerin pipeline rivillä\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "tiedostossa ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet ei löytänyt GStreamerin 'filesrc' -elementtiä. Tarkista " #~ "GStreamer-asennuksesi." ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/fr.po����������������������������������������������������������������������������0000644�0001750�0001750�00001027466�14436352625�013622� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# translation of fr.po to Français # Olivier Gambier <dev@viapanda.com>, 2006. # Ludovic DRUETTE <ludovicdruette@gmail.com>, 2016. # Olivier Humbert <trebmuh@tuxfamily.org>, 2017. # Jean-Michel Pouré <jm@poure.com>, 2017. # Bundy01, 2019. # msgid "" msgstr "" "Project-Id-Version: fr\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-05-20 14:48+0000\n" "Last-Translator: Jej <weblate@gogomail.trickip.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/fr/>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" "X-Generator: Weblate 4.18-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titre" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Personnes" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Date" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Date d'ajout" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Date d'origine" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "Évaluation" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "_Nombre de lectures" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "_Trier par…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Préférences" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Liste des albums" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Liste des _albums" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Tous les albums" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Recharger la _pochette de l'album" msgstr[1] "Recharger les _pochettes de l'album" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Titres absents d'un album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d piste" msgstr[1] "%d pistes" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disque" msgstr[1] "%d disques" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Un exemple d'album" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Préférences de l'affichage liste d'albums" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Montrer les _pochettes de l'album" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Inclure les personnes dans la _recherche" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Options" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Affichage des albums" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Fermer" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navigateur de bibliothèque" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d titre" msgstr[1] "%d titres" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Motif invalide" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Collection d'albums" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Collection d'albums" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "%s inconnu" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "%s : valeurs multiples" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personnalisé" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Ajouter" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "Supp_rimer" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Étiquette" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Fusionner" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Préférences de la collection d'albums" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Appliquer" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Annuler" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Mur de pochettes" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Mur de pochettes" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Préférences du mur de pochettes" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Montrer les _textes des albums" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Montrer l'élément \"Tous les albums\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Mode étendu" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Agrandissement de la pochette" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Système de fichiers" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Système de fichiers" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Impossible de copier les titres" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Impossible de copier les fichiers sélectionnés vers des listes de titres ou " "dans la file d'attente." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Ajouter à la bibliothèque" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Les listes de radio doivent contenir uniquement des emplacements de radio. " "Elles ne peuvent pas contenir des listes de radio ou des listes de lecture. " "Impossible de charger les emplacements suivants :\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Ajouter des stations" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Télécharger la liste des stations" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nouvelle radio Internet" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Saisissez l'adresse d'une radio Internet :" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Électronique" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Vieilles chansons" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonais" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indien" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religieux" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Charts" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turc" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Radio Universitaire" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Discussions / Actualités" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambiance" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Classique" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatif" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Métal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Actualités" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Chansons Populaires" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slave" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grec" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothique" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Souhaitez-vous charger une liste de stations de radios populaires ?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Charger les stations" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Radio Internet" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Toutes les stations" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoris" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Aucune catégorie" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Ajouter une station…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Mise à jour des stations" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Aucune radio trouvée" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Aucune station radio ne correspond à %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Rien à ajouter" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Tous les radios listées sont déjà dans votre bibliothèque." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "_Ajouter à la liste des favoris" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Supprimer des Favoris" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d radio" msgstr[1] "%(count)d radios" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Navigateur à panneaux" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Navigateur à _panneaux" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Choisir _tous" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Inconnu" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Tous" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Petit" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Large" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Chronique" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Modèle de balise avec balisage facultatif, par exemple <tt>compositeur</tt> " "ou \n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Préférences du navigateur à panneaux" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Disposition en colonne" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Contenu de la colonne" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Largeur de volet égal" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listes de lecture" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Listes de lecture" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Supp_rimer de la liste de lecture" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nouveau" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Importer…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Impossible d'importer la liste de lecture" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet ne peut importer que les listes de lecture aux formats M3U/M3U8 " "et PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Supprimer" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Re_nommer" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Impossible de renommer la liste de lecture" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importer une liste de lecture" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importer" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nouvelle liste de lecture…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Que souhaitez-vous faire de ce %d titre ?" msgstr[1] "Que souhaitez-vous faire de ces %d titres ?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Confirmez l'action pour la liste de lecture \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "Vide" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Exemple de liste de lecture" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Préférences du navigateur de liste de lecture" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Affichage de liste de lecture" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Confirmer la suppression de la liste de lecture '%s' ?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Toutes les informations de cette liste de lecture vont être supprimées et ne " "pourront être récupérées." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "Prolonger \"{pl_name}\" avec {num} piste supplémentaire ?" msgstr[1] "Prolonger \"{pl_name}\" avec {num} pistes supplémentaires ?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Ajouter des pistes" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Créer une liste de lecture" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Saisissez un nom pour la nouvelle liste de lecture :" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Créer" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importation de liste de lecture.\n" "\n" "%(current)d/%(total)d titres ajoutés." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nouveau flux" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Indiquer l'emplacement du podcast / flux audio :" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Podcasts" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Podcasts" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "_Ajouter un flux…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Rafraîchir" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Chercher de nouveaux épisodes à la source" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Reconstruire" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" "Supprimer tous les événements existants puis recharger à partir de la source" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Supprimer ce podcast et ses épisodes" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Impossible d'ajouter le flux" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s n'a pas pu être ajouté. Le serveur est peut-être en panne, ou " "l'emplacement n'est peut-être pas un podcast / flux audio." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Le système audio actuel ne prend pas en charge les URL, navigateur de " "podcast désactivé." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limiter les résultats" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Permettre plusieurs requêtes" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Liste de pistes" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Liste des pistes" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Navigateur Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Rechercher" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Mes pistes" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Aller à %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Connecté" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet est maintenant connecté, %s !" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Se déconnecter de %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Saisir le code …" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Se connecter à %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Autorisation Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Saisir le code d'authentification Soundcloud :" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" "Quod Libet n'est pas en fonctionnement (ajouter '--run' pour le lancer)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "un lecteur et une bibliothèque de musique" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[option]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Afficher le titre en cours de lecture et quitter" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Commencer la lecture immédiatement" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Cacher toutes les fenêtres au démarrage" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Aller au titre suivant" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Aller au titre précédent ou recommencer si proche du début" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Aller au titre précédent" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Commencer la lecture" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Suspendre la lecture" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Basculer entre le mode lecture et pause" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Arrêter la lecture" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Augmenter le volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Diminuer le volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Augmenter la note d'une étoile pour la lecture d'un titre" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Diminuer la note d'une étoile pour la lecture d'un titre" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Afficher l'état du lecteur" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Cacher la fenêtre principale" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Afficher la fenêtre principale" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Basculer la visibilité de la fenêtre principale" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Focaliser le lecteur en fonction" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Enlever les filtres actifs du navigateur" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Rafraîchir et rescanner la bibliothèque" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Lister les navigateurs disponibles" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Afficher la liste de lecture" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Afficher le contenu de la file d'attente" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Afficher le texte de la recherche en cours" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Démarrer sans greffons" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Démarrer Quod Libet s'il n'est pas en fonctionnement" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quitter Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Se déplacer dans le titre en cours de lecture" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Activer ou désactiver la lecture aléatoire" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Définir le type de mode de lecture aléatoire" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Activer, désactiver ou basculer le mode répétition" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Définir le mode de répétition" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Régler le volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Rechercher dans votre bibliothèque de musique" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "requête" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Lire un fichier" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "nom de fichier" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Définir l'évaluation de la lecture d'un morceau" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Définir le navigateur courant" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Arrêter après ce titre" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Démarrer un nouveau navigateur" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Afficher ou cacher la file d'attente" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrer au hasard sur une valeur" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "étiquette" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrer sur la valeur d'une étiquette" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "étiquette=valeur" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "" "Mettre un fichier ou le résultat d'une recherche dans la file d'attente" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" "Mettre des fichiers séparés par un point-virgule dans la file d'attente" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nom de fichier" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Afficher les résultats de la requête dans la sortie standard stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Enlever un fichier ou le résultat d'une recherche de la file d'attente" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Ajouter un fichier ou un répertoire à la bibliothèque" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "emplacement" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Définir le modèle pour les commandes --print-*" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "motif" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argument non valide pour '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Essayez %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Une erreur s'est produite" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Vous pouvez ignorer cette erreur, mais l'application peut être instable " "jusqu'à ce qu'elle soit redémarrée. La soumission d'un rapport d'erreur ne " "prendra que quelques secondes. Aidez-nous un peu." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Soumettre un rapport d'erreur" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Redémarrer" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorer l'erreur" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Détails de l'erreur :" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Divers détails concernant l'erreur et votre système sera envoyé à un tiers " "(<a href='https://www.sentry.io'>www.sentry.io</a>). Vous pouvez consulter " "les données avant de les envoyer ci-dessous." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(facultatif) Veuillez fournir une brève description de ce qui s'est passé " "lorsque l'erreur s'est produite :" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Envoyer" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Description courte…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Données à envoyer :" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "un éditeur d'étiquettes audio (tags)" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "répertoire" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Éditeur de métadonnées audio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL des sources de pochettes" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Téléchargements de pochettes liées par la balise <tt>artwork_url</tt>. Cela " "fonctionne avec les navigateurs Soundcloud et Podcasts." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Pochettes depuis Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Télécharger les pochettes depuis Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Pochettes depuis Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Télécharger les pochettes depuis les archives d'illustrations Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Source d'illustrations MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" "Télécharger les pochettes depuis les archives d'illustrations MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Transcoder" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Corriger dans l'éditeur d'étiquettes les balises comportant des erreurs " "d'encodage." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Convertir le codage…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Convertisseur simple Kana/Kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Convertit les kana/kanji en romaji avant de les renommer." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romaniser le _texte Japonais" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Impossible de trouver le 'Convertisseur Simple Kanji Kana' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Substitution Regex" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Permet des substitutions regex arbitraires (<tt>s/from/to/</tt>) lors du " "balisage ou du renommage de fichiers." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Majuscules de titre" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Ajoute des majuscules au titre dans l'éditeur d'étiquette." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Ajout de majuscules" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Autoriser les titres entièrement en MAJUSCULES" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Majuscule à chaque mot" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Modifier le titre selon les règles typographiques britanniques (majuscule à " "chaque nom), en écrivant par exemple \"Dark Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Préférences avancées" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Permet d'éditer les paramètres de configurations avancées." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Je confirme que je comprends ce que je fais" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Incrustation d'informations" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Afficher les informations de la piste lorsqu'elle change." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Position :" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Taille de la pochette :" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Affichage" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Police :" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Gauche" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centre" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Droite" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Alignement :" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Texte" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Texte :" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "Remplissage :" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Couleurs" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "Ombré" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "S_ouligné" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Coins arrondis" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Délai :" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effets" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Éd_iter le gabarit d'affichage…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "A_perçu" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Information sur l'application" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Diverses informations sur l'application et son environnement." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Formats supportés" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Répertoire de configuration" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Répertoire du cache" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Pilote audio" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Après chaque lecture (par défaut)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Chaque fois qu'un morceau a été joué mais pas sauté, le greffon écrira les " "étiquettes dans le fichier. Le nombre de sauts n'est pas du tout stocké dans " "les fichiers, ce qui évite les écritures inutiles." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Après chaque lecture ou saut" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Chaque fois qu'un morceau est joué ou sauté, le greffon écrira les " "étiquettes dans le fichier. Cela peut être utile si vous voulez vous assurer " "que les évaluations des titres que vous avez sautés soient écrites dans les " "fichiers." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Une fois, lorsque l'album est entièrement évalué" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Quand un morceau a été joué ou sauté, l'album de ce morceau sera vérifié. Si " "tous les morceaux de l'album ont été évalués et qu'au moins l'un d'entre eux " "n'a pas d'évaluation ou de compte de lecture dans son fichier, le greffon " "écrira les étiquettes dans les fichiers des morceaux.\n" "\n" "Utilisez cette méthode pour éviter les mises à jour constantes des fichiers, " "mais sachez qu'une fois qu'un album a été mis à jour, vous devrez utiliser " "le greffon \" Mise à jour des étiquettes dans les fichiers \" chaque fois " "que vous voudrez que les évaluations et les comptes de lecture modifiés " "soient écrits dans les fichiers." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Lorsque le greffon écrit les étiquettes d'un album, il met d'abord le compte " "de lecture des morceaux qui sont à zéro à un.\n" "Parfois, vous savez déjà que vous n'aimez pas un morceau, donc le mettre à " "un lors de la sauvegarde peut être utile plus tard, lors de la recherche " "d'albums que vous avez entièrement écoutés (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Impossible d'écrire '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Mise à jour automatique des étiquettes dans les fichiers" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Lorsque des pistes sont jouées, met à jour les étiquettes dans leur fichier. " "Cela permet de s'assurer que le nombre de lectures et les évaluations sont à " "jour." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Le paramètre suivant a été activé car il est nécessaire pour le " "fonctionnement de ce greffon :\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "" "Enregistrer les évaluations et le _nombre de lectures dans les étiquettes" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Paramètres mis à jour" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Erreur dans %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" "Lors de l'enregistrement, s'assurer que le nombre de lectures est supérieur " "à zéro" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Stratégie de mise à jour :" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Préférences" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Masquer automatiquement" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Afficher et masquer automatiquement les lecteurs lorsqu'ils sont montés ou " "démontés." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Évaluation automatique" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Classe les morceaux automatiquement lorsqu'ils sont lus ou sautés. Ceci " "utilise l'algorithme 'accéléré' de vux (Vacillating Utilitarian " "eXtemporizer) de Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "La base de données spécifiée de Banshee est malformée ou manquante" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "L'importation a échoué" # python-format #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" "Succès de l'importation des classifications et des statistiques pour le " "titre %d" msgstr[1] "" "Succès de l'importation des classifications et des statistiques pour les " "titres %d" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Importation Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" "Importe les classifications et les statistiques des chansons depuis Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Chemin de la base de données :" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Démarrer l'importation" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Réveil" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Vous réveille en musique." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Berceuse" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Abaisse le son et met votre musique en pause." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Message de statut Discord" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Message de Statut Discord" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Modifiez votre message de statut Discord en fonction de ce que vous écoutez " "actuellement." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "En pause" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Ligne d'état #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Ligne d'état #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Plat" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Concert" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Basses et aigus complets" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Club" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Grande salle" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Soirée" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Doux" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Basses profondes" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Écouteurs" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Rock doux" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Aigus Complets" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Portable" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Équaliseur" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Contrôle la tonalité de votre musique avec un équaliseur.\n" "Cliquez ou utilisez les touches pour personnaliser les niveaux (clic droit " "pour réinitialiser la bande)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Le gestionnaire de périphérique ne supporte pas d'équalisateur." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Préréglages par défaut" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Choisir…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Réinitialiser équaliseur" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Préréglages personnalisés" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Supprimer les titres sélectionnés" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Nom prédéfini pour la sauvegarde :" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "Enregi_strer" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "en ligne" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "non-connecté" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "lointain" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "invisible" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Message de Statut Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" "Modifie le message de statut de Gajim en fonction de ce que vous écoutez " "actuellement." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "en pause" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Motif :" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Liste des comptes, séparés par des espaces, pour modifier le message de " "statut. Si aucun n'est spécifié, le message de statut de tous les comptes " "sera modifié." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Comptes :" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Ajouter '[paused]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "Si coché, '[paused]' sera ajouté au message de statut en pause" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statuts pour lesquels le message sera modifié" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Suspendre la lecture quand le casque audio est débranché" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Suspendre la lecture quand le casque audio est débranché et la reprendre dès " "qu'il est rebranché." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Inhiber l'économiseur d'écran/la mise en veille" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Sur un bureau GNOME, quand un morceau est en cours de lecture, empêche soit " "l'économiseur d'écran de s'activer, soit l'ordinateur de se mettre en veille." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "La musique est en cours de lecture" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Mode :" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Désactiver l'économiseur d'écran" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Inhiber la mise en veille" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Logs radio Internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Enregister les 10 derniers titres joués sur les stations radio, et les " "lister dans le menu contextuel." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Produit un fichier Jabber User Tunes vers %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Changer la langue" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Afficher l'interface utilisateur dans une autre langue." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Valeurs systèmes par défaut" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Pour appliquer les changements, un redémarrage est nécessaire" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Serveur UPnP AV Media" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Rendre disponible les albums via le serveur de média UPnP Rygel, en " "utilisant l'interface D-Bus MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Assurez-vous que ce qui suit se trouve dans votre fichier de configuration " "rygel (~/.config/rygel.conf) :" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Serveur MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Permet de contrôler Quod Libet en utilisant un client MPD. Le streaming, les " "files de lecture et la gestion de la bibliothèque ne sont pas supportés." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port :" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_IP locale :" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "Mot de p_asse :" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Connexion" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Clients testés" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Support D-Bus MPRIS" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Permet le contrôle de Quod Libet en utilisant la spécification d'interface D-" "Bus <a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a>. Cela " "permet diverses intégrations au bureau Linux (par exemple, des touches " "multimédia)." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Cacher la fenêtre principale lors de la sortie" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Accepte les modèles de QL, p. ex. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Éditeur MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publie des messages de statut à un thème MQTT." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Nom d'hôte de l'intermédiaire / IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "La valeur par défaut est localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Port de l'intermédiaire" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "La valeur par défaut est 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Nom d'utilisateur de l'intermédiaire" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Mot de passe de l'intermédiaire" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Sujet" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Motif de lecture" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Texte de statut lorsqu'un morceau est lancé." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Modèle en Pause" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Texte affiché quand un titre est en pause." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Texte sans chanson" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Texte brut pour quand il n'y a pas de chanson en cours" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Configuration MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Texte indiquant le statut" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Connecté à l'intermédiaire à l'adresse : %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Impossible de se connecter à %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Erreur de connexion" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "Synchronisation de MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synchronise le classement d'un morceau avec MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Nom d'utilisateur :" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "Mot de _passe :" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Compte" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Texte de la notification" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Titre :" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Rétablir le motif par défaut" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "Corps :" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "Afficher les notification_s" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Afficher les notifications" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Si le titre est changé <i>_manuellement</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Si le titre est changé <i>_automatiquement</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Sur <i>tous</i> les changements de titre" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Ouvrir uniquement lorsque la fenêtre principale n'est pas activée" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Afficher le bouton \"Suiva_nt\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Erreur de connexion" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Impossible de se connecter au démon de notification." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Notifications de titre" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Affiche une notification lorsque le morceau change." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Suivant" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Notifications du signet" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Utilise les notifications pour afficher les signets / commentaires en temps " "réel. Fonctionne bien pour le navigateur Soundcloud." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Veuillez visiter la fenêtre Greffons pour configurer QLScrobbler. D'ici là, " "les morceaux ne seront pas soumises." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Impossible de se connecter au service '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Authentification impossible : URL invalide." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "L'authentification a échoué : nom d'utilisateur '%s' invalide ou mauvais mot " "de passe." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Le client a été banni. Veuillez contacter l'auteur." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Heure du système incorrecte. Les soumissions peuvent échouer jusqu'à ce " "qu'elle soit corrigée." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Soumission à AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Client Audioscrobbler pour Last.fm, Libre.fm et autres services " "Audioscrobbler." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Authentification validée." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Service :" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL :" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Autre…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Vérification des données du compte" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Motif de l'_artiste :" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Motif du _titre :" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_Filtre d'exclusion :" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Le motif utilisé pour formater un artiste avant soumission. Laisser vide " "pour la valeur par défaut." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Le motif utilisé pour formater un titre avant soumission. Laisser vide pour " "la valeur par défaut." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Les titres correspondant à cette recherche ne seront pas soumis" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "M_ode non-connecté (ne rien soumettre)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Soumission" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Publicités radio muettes" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Couper le son pendant la diffusion des publicités radio.\n" "Stations : di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Lecture aléatoire de l'album" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Lance la lecture d'un album au hasard lorsque votre liste de lecture se " "termine. Nécessite que le navigateur en cours d'utilisation supporte le " "filtrage par album." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Le mieux évalué" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Le plus joué" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Le plus sauté" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Joué récemment" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Lancé récemment" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Ajouté récemment" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Albums les plus longs" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "secondes avant de lire l'album suivant" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Poids" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Lire des albums plus souvent que d'autres" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "éviter" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "préférer" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Album aléatoire" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "En attente de lecture de %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Évaluations et statistiques de %d titres importés avec succès" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Importation Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" "Importe les évaluations et les statistiques des titres à partir de Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pause de l'économiseur d'écran" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Suspendre la lecture quand l'économiseur d'écran Gnome s'affiche." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Aucun fournisseur Gnome de recherche en ligne de commande n'est installé " "dans Quod Libet." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "Avez-vous copié le fichier ini dans %s (ou équivalent) ?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Fournisseur de recherche Gnome" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Autoriser GNOME Shell à effectuer des recherches dans la bibliothèque." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Barre de progression alternative" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Barre de progression alternative, visible sur toute la largeur de la fenêtre." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Signets Seekpoint" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Mémoriser les points de recherche A et/ou B pour les pistes. Passer au temps " "A et s'arrêter après le temps B lorsque la piste est jouée.\n" "\n" "ℹ Notez que changer le nom des points ci-dessous ne met pas à jour les noms " "de signets actuels, mais seulement les noms de signets que le greffon " "recherche lorsqu'il décide de les chercher." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nom du signet pour le point A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Nom du signet pour vérifier quand une piste est démarrée, et si elle est " "trouvée, le lecteur cherche l'horodatage" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nom du signet pour le point B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Nom du signet pour utiliser chaque coche pendant la lecture d'une piste si " "elle existe. Si la position actuelle dépasse l'horodatage, chercher jusqu'à " "la fin de la piste." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Synchronisation Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Fait la sortie Quod Libet du miroir Logitech Squeezebox, à condition que les " "deux lisent dans une bibliothèque identique." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Partage la configuration avec <a href=\"%(plugin_link)s\">le greffon " "Exporter vers Squeezebox</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Recherche d'erreurs serveur Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Recherche d'erreurs %s. Veuillez vérifier les paramètres" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Arrêt sur Pause" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Ce greffon change Pause en Stop/Lecture/Recherche.\n" "\n" "Utile si Quod Libet ne peut pas changer de périphérique audio lorsqu'un " "nouveau matériel (enceinte Bluetooth, DAC USB, etc.) est ajouté au système.\n" "\n" "Assure le maintien de la position dans la source actuelle tant que l'option " "'Seulement les sources recherchées' est désactivée. Sinon, la lecture est " "arrêtée et doit être reprise depuis le début." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Seulement les sources recherchées" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Options du greffon" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Copie en attente" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "En attente de suppression" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "supprimer" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Sauter" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLICATA" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Suppression" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Succès" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "ÉCHEC" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Fichier existant ignoré" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Impossible de définir le nom de fichier d'un morceau." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Synchroniser vers le Périphérique" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchronise tous les morceaux des recherches enregistrées sélectionnées avec " "le dossier spécifié." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synchronise les recherches enregistrées suivantes :" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Le chemin absolu vers votre emplacement d'exportation" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Tous les fichiers préexistants dans le dossier de destination qui ne " "figurent pas dans les recherches enregistrées seront supprimés." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "Pour les appareils montés avec MTP, exportez vers un dossier de destination " "local, puis transférez-le vers votre appareil avec rsync. Ou, lorsque vous " "synchronisez de nombreux fichiers vers un appareil Android, utilisez adb-" "sync, qui est beaucoup plus rapide." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Chemin de destination :" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Chemin des motifs" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Éditer les motifs enregistrés…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "La structure des noms de fichiers exportés, basée sur leurs étiquettes" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Modèle d'exportation :" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Arrêter l'aperçu" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Etat" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Fichier Source" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Chemin d'exportation" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Duplication des chemins d'exportation détectée ! Les chemins d'exportation " "ci-dessus peuvent être modifiés avant de lancer la synchronisation." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Les fichiers existants dans le chemin de destination seront supprimés (sauf " "les fichiers nommés 'cover.jpg') !" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Démarrer la synchronisation" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Arrêter la synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" "Pas encore de recherches enregistrées, créez-en quelques-unes et revenez !" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Choisir le chemin de destination" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Le chemin d'exportation a été modifié de [{old_path}] à [{new_path}] pour le " "fichier [{filename}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Démarrage de l'aperçu de la synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Aperçu de la synchronisation en cours." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Aperçu de la synchronisation terminée" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Arrêt de l'aperçu de la synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "L'aperçu de la synchronisation a été arrêté." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "L'aperçu de la synchronisation est terminé." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Aperçu de la synchronisation arrêté" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Un autre greffon a été sélectionné - arrêter la prévisualisation" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "La synchronisation sera :" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "tenter d'écrire le fichier {count}" msgstr[1] "tenter d'écrire les fichiers {count}" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "ignorer le fichier dupliqué {count}" msgstr[1] "ignorer les fichiers dupliqués {count}" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "supprimer le fichier {count}" msgstr[1] "supprimer les fichiers {count}" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Aucun chemin de destination n'a été fourni" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" "Veuillez spécifier le répertoire où les morceaux doivent être exportés." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Aucun modèle d'exportation n'est fourni" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" "Veuillez spécifier un modèle d'exportation pour les noms des morceaux " "exportés." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Le chemin d'exportation n'est pas absolu" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Le modèle \n" " \n" "{} \n" " \n" "contient \"/\" mais ne commence pas à la racine. Merci de fournir un chemin " "de destination absolu en vous assurant qu'il commence par / ou ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Aucune recherche sauvegardée sélectionnée" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Veuillez sélectionner au moins une recherche enregistrée." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Pas de morceaux dans les recherches sauvegardées sélectionnées" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Toutes les recherches enregistrées sélectionnées sont vides." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Trouvé {} morceaux à synchroniser" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Inadéquation entre le chemin de destination et le modèle d'exportation" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Le modèle d'exportation commence par un chemin qui diffère du chemin de " "destination. Veuillez corriger le modèle.\n" "\n" "Erreur :\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Synchronisation impossible" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Impossible de lancer la synchronisation lors du tri par <b>Status</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Démarrage de la synchronisation des morceaux de musique" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Synchronisation en cours." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Synchronisation du morceau terminée" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Arrêt de la synchronisation du morceau" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "La synchronisation a été arrêtée." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "La synchronisation est terminée." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Arrêt de la synchronisation du morceau" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Un autre greffon a été sélectionné - Arrêt de la synchronisation" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Suppression de \"{}\"" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "La synchronisation a :" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "écrire le fichier {count}/{total}" msgstr[1] "écrire les fichiers {count}/{total}" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "( ignorer le fichier existant {count})" msgstr[1] "( ignorer les fichier existants {count})" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "ignorer le fichier en double {count}/{total}" msgstr[1] "ignorer les fichiers en double {count}/{total}" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "supprimer le fichier {count}/{total}" msgstr[1] "supprimer les fichiers {count}/{total}" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "échec de la synchronisation du fichier {count}" msgstr[1] "échec de la synchronisation des fichiers {count}" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "ignorer le fichier {count} synchronisé précédemment" msgstr[1] "ignorer les fichiers {count} synchronisés précédemment" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Paroles synchronisées" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Affiche les paroles synchronisées d'un fichier .lrc portant le même nom que " "la piste (ou similaire)." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Texte :" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Arrière plan :" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Police" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Taille (en pixel) :" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Messages d'état de Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Mises à jour de tous les comptes de messagerie instantanée basés sur " "Telepathy (tels que configurés dans Empathy, etc.) avec un message d'état " "basé sur le titre en cours." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "En cours de lecture :" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Texte de statut lorsqu'un morceau est lancé. Accepte les modèles de QL, p. " "ex. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "En pause :" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Texte de statut lorsqu'un morceau est mis en pause. Accepte les modèles de " "QL, p. ex. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Texte brut pour le statut lorsqu'il n'y a pas de titre en cours" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Aucun titre :" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Modèles de statut" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Changer de thème" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Permet de changer de thème GTK+." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Thème :" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Thème par défaut" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Préférer la version sombre du thème" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Évaluation du pouce" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Ajoute un système de notation pouce en haut / pouce en bas qui est converti " "en une valeur de notation. Utile pour garder les totaux de vote en cours et " "trier par <b><tt>~#score</tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Basculer la Barre de Menu" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Appuyez sur la touche Alt pour faire basculer la barre de menu." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Pas de lecture en cours" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Icône de la barre des tâches" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Contrôle Quod Libet depuis la barre d'état système." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "Afficher %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Lecture" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Précédent" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "Suivant" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "Lecture aléatoire" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Répéter" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "_Arrêter après ce titre" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Ouvrir le _Navigateur" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Éditer les étique_ttes" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informations" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Listes de lecture" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Quitter" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Comportement" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "La molette de la souris ajuste le volume" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "La molette de la souris change de titre" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Molette de la souris" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Affichage de l'infobulle" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Voir les paroles" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Affiche automatiquement les paroles basées sur une balise ou un fichier dans " "une barre latérale." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Pas de paroles trouvées pour\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Aucun titre actif" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Lancer des Visualisations" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Lancer des visualisations externes." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Impossible d'exécuter des visualisations à l'aide de '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Erreur" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Exécutable de visualisation :" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Recharger" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Barre de recherche Waveform" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ Une barre de recherche sous la forme d'onde du morceau en cours." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Remplacer la couleur d'avant-plan :" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Remplacer la couleur du survol :" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Remplacer la couleur restante :" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Afficher la position actuelle" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Afficher les vignettes de temps" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Cherchez la quantité lors du défilement (millisecondes) :" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Économiseur d'écran" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Enregistrer la pochette du titre courant dans un fichier." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Fichier :" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "Seuil :" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Niveau en deçà duquel le filtre est activé" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "Ratio :" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Taux de compression" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Compresseur audio" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Modifie l'amplitude de tous les échantillons au-dessus d'un seuil spécifique " "avec un rapport spécifique." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "Présélection :" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Préréglage du filtre" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Fréquence de coupure :" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Fréquence de coupure du filtre passe-bas" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Niveau d'entrée :" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Niveau d'entrée" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Par défaut" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Positionnement le plus proche de l'enceinte virtuelle (30°, 3 mètres)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Proche du crossfeeder Chu Moy (populaire)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Proche des amplificateurs CORDA de Jan Meier (peu de changement)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Personnalisé" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Paramètres personnalisés" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Flux croisés" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mixe les deux canaux à la manière du réglage d'un casque audio, ou pour " "ajuster le son des anciens enregistrements audio." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filtrer sur le _groupe :" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "La largeur de bande du filtre" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filtrer sur la _taille :" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "La largeur de fréquence du filtre" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "Niveau :" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Niveau de l'effet" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoké" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Supprimer les paroles dans l'audio." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mixage Mono" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Mixer les canaux audio vers un seul canal mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "T_aux :" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "Tempo :" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Tonalité :" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Tonalité / Vitesse Audio" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Contrôle la tonalité d'un flux audio." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Exporter la liste de lecture dans le dossier" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exporter" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Dossier de destination :" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Modèle de nom de fichier :" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Exporte une liste de lecture en copiant les pistes dans un dossier." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Impossible d'exporter la liste de lecture" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Assurez-vous d'avoir un accès en écriture vers la destination." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Modèle de nom de fichier par défaut :" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Tapez un nouveau nom de liste de lecture,\n" "ou choisissez une liste de lecture Sonos existante à écraser" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Exporter vers liste de lecture de Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" "Exporte une liste de lecture vers Sonos en fonction des pistes " "correspondantes." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Erreur lors de la recherche de périphérique(s) Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Erreur dans la recherche de Sonos. Veuillez vérifier les paramètres" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Échec de la suppression de la liste de lecture Sonos existante %s :" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Exporter vers la liste de lecture %(playlist)r (%(total)d pistes)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exporter vers Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Exporte dynamiquement une liste de lecture vers une liste de lecture " "Logitech Squeezebox, à condition que les deux partagent une structure de " "répertoire." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Partage la configuration avec <a href=\"%(plugin_link)s\">le greffon " "Synchronisation Squeezebox</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Exporter la liste de lecture vers Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Le nom de la liste de lecture (écrase le nom précédent)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exporter vers une liste de lecture Sqeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Supprimer les doublons dans la liste de lecture" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Supprime les doublons dans une liste de lecture." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Confirmer la suppression du titre %d en doublon ?" msgstr[1] "Confirmer la suppression des %d titres en doublon ?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Les titres en double seront supprimés de la liste de lecture '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Lecture aléatoire" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Joue aléatoirement les titres d'une liste de lecture." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Suivre le curseur" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Ajoute un mode d'ordre de lecture qui suit votre sélection, ou le morceau " "suivant dans la liste une fois épuisé." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Suivre le curseur" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Suivre le curseur" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Égaliseur de nombre de lectures" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Ajoute un mode de lecture aléatoire qui privilégie les titres dont le nombre " "de lectures est moindre." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Préférer les moins joués" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Préférer _les moins joués" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Uniquement en file d'attente" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Limite la lecture des morceaux à la file d'attente.\n" "\n" "Sélectionnez cet ordre de lecture dans la fenêtre principale, puis double-" "cliquez sur un morceau pour le mettre en file d'attente au lieu de le lire." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "File d'attente uniquement" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "_File d'attente uniquement" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Lancement automatique de la lecture des titres obtenus par double-clic" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Inverser" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Ajoute un mode de lecture aléatoire qui inverse l'ordre de lecture des " "morceaux." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "In_verser" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Lecture aléatoire par regroupement" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Ajoute un mode de lecture aléatoire qui regroupe les morceaux avec une " "étiquette commune - similaire à la lecture aléatoire des albums.\n" "\n" "Ceci est utile pour mélanger des pièces classiques à plusieurs mouvements, " "en s'assurant que tous les mouvements sont joués dans l'ordre avant de " "passer à la pièce suivante." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Lecture aléatoire par regroupement" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "Lecture aléatoire par re_groupement" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "En attendant de commencer un nouveau groupe…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Étiquette de regroupement :" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Étiquette pour grouper les titres par" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Étiquette de filtre :" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Le regroupement n'est appliqué que si l'étiquette de filtre est définie.\n" "Un morceau avec une étiquette de filtre indéfinie sera traité comme\n" "un groupe constitué uniquement de lui-même. Typiquement, le filtre\n" "doit correspondre ou correspondre partiellement à l'étiquette de " "regroupement." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Délai :" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Temporisation en secondes avant le démarrage du groupe suivant" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Retour aux valeurs par défaut" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Sauter les morceaux que vous n'aimez pas" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Ajoute un mode de lecture (aléatoire) qui lit dans l'ordre, mais ignore les " "pistes dont l'évaluation est inférieure (ou égale) à un seuil donné." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Sauter les morceaux que vous n'aimez pas" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Sauter les _morceaux que vous n'aimez pas" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Répéter chaque piste" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Ajoute un mode de lecture aléatoire qui lit les pistes dans l'ordre, mais en " "répétant chaque piste un nombre donné de fois." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Répéter chaque piste" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "Répéter chaqu_e piste" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Nombre de répétitions pour chaque titre :" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Requêtes conditionnelle" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" "Choisit la requête à faire correspondre sur la base d'une requête " "conditionnelle." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if : requête de condition, puis-requête, sinon-requête)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Requête Manquante" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Correspond aux chansons sans étiquette donnée." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Inclure des étiquettes vides" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Requête Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Utiliser des expressions Python dans les requêtes." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python : expression)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "La variable <tt>s</tt> (ou <tt>a</tt>) est le morceau/l'album " "correspondant.\n" "\n" "<tt>_ts</tt> est un horodatage (nombre réel) au début de la requête.\n" "\n" "Les modules <tt>time</tt> et <tt>random</tt> sont également disponibles, " "ainsi que la classe <tt>Random</tt> (==<tt>random.Random</tt>)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Inclure les recherches sauvegardées" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" "💾 Inclure les résultats d'une recherche sauvegardée dans une autre requête." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(enregistré : nom-recherche)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Requête Unique" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Filtrer les résultats de la recherche par étiquettes uniques." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique : étiquette)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Utilisation de (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Impossible de se connecter à %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nom d'hôte :" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port :" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nom d'utilisateur :" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Mot de passe :" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Répertoire la bibliothèque auquel le serveur se connecte" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Chemin de la librairie :" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Vérifier la configuration" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Serveur Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Débug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Serveur Sqeezebox à l'adresse {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "Serveur Squeezebox inconnu" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "lecteur Squeezebox non-identifié : %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Sélectionner un lecteur Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Serveur Squeezebox trouvé.\n" "Veuillez sélectionner le lecteur" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Ajuster l'image à la fenêtre" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Voir l'entrée de configuration de '[plugins] cover_filenames' pour les " "chaînes de nom de fichier image" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programme :" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Éditer l'image après enregistrement" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Nom de fichier :" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Échec de l'enregistrement" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Impossible d'enregistrer \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Erreur HTTP : %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Téléchargement de pochettes" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "depuis %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Solution : %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Taille : %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Limite de résultats 'au mieux' par moteur" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Rechercher" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Recherche en cours…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Fait." #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Télécharger des illustrations" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Téléchargement de pochettes d'album depuis plusieurs sites Web." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Sources" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 vers ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Convertit des étiquettes APEv2 en étiquettes ID3v2. Les étiquettes APEv2 " "sont supprimées après conversion." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Aller aux signets" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Gère les signets des fichiers sélectionnés." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "Modifi_er les signets…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Aucun signet" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Recherche MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Étiqueter l'album à nouveau, en utilisant MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Indiquer uniquement l'année dans l'étiquette \"date\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" "Utiliser l'étiquette \"_albumartist\" (artiste auteur de l'album) si " "nécessaire" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Trier les noms des artistes avant de les enregistrer dans l'étiquette" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Écrire les étiquettes standard MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Ecrire l'étiquette \"labelid\" (référence de l'étiquette)" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nom de fichier" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disque" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Piste" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Titre" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artiste" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Recherche MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "Re_quête :" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "R_echercher" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Résultats <i>(cliquer-déplacer pour trier)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Veuillez saisir une requête." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Des erreurs ont été rencontrées. Veuillez recommencer." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Chargement des résultats…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Aucun résultat." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Console Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Console Python interactive. Ouvre une nouvelle fenêtre." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} pour {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Barre latérale de la console Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Barre latérale interactive de la console Python, qui suit les titres " "sélectionnés dans la fenêtre principale." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Par défaut, vous avez accès aux objets suivants :" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Votre répertoire par défaut est :" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Compléter" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Télécharger l'illustration de la pochette" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Télécharger des pochettes d'album de haute qualité en utilisant les greffons " "de Quod Libet dédiés aux pochettes." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Classique" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Large" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Téléchargement de la pochette" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Chargement %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Rien trouvé pour les albums : \n" "%(albums)s. \n" " \n" "Fournisseurs utilisés : \n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Les pochettes n'ont pas été trouvées" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Taille de l'aperçu" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Enregistrer vers" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Si ce n'est pas déjà un JPEG, convertissez l'image en un JPEG de haute " "qualité et de même taille" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Enregistrer en JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Commande" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nom" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Le nom de cette commande" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "commande" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Syntaxe de la commande à lancer" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "paramètre" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Si spécifié, un paramètre dont les occurrences dans la commande seront " "remplacées par une valeur fournie par l'utilisateur, par exemple en " "utilisant 'PARAM' toutes les instances de '{PARAM}' dans votre commande " "auront la valeur demandée lors de son exécution" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Le modèle QL, par exemple <~filename>, à utiliser pour calculer une valeur " "pour la commande. Pour les listes de lecture, cela prend également en charge " "les balises virtuelles <~playlistname> et <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unique" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Si cette option est activée, cela supprimera les valeurs calculées en double " "du modèle" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "Nombre maximum d'arguments" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Le nombre maximum d'arguments à passer à la commande en même temps (comme " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "inverser" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Si cette option est activée, la liste des arguments sera inversée" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Valeur en entrée" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Valeurs pour %s ?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Commandes personnalisée" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Lance des commanded personnalisée (par lots si nécessaire) sur des titres à " "partir de leurs étiquettes." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Éditer une commande personnalisée" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Impossible de lancer la commande personnalisée %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "groupe en double %d" msgstr[1] "groupes en double %d" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Replier / Déplier tout" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "L'expression de la clé dupliquée est '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Navigateur de doublons" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Recherche et affiche les titres ayant des étiquettes similaires." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Accepte les expressions de la balise QL comme <tt>~artist~title</tt> ou " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "Regrouper les doublons par :" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Clé en double" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Supprimer les espaces" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Supprimer les caractères spéciaux" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Supprimer la ponctuation" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Non-sensible à la casse" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Options de correspondance" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Modifier le compteur de lectures" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Modifier le <tt>~#playcount</tt> et le <tt>~#skipcount.</tt> d'une chanson.\n" "\n" "Lorsque plusieurs chansons sont sélectionnées, les calculs seront " "incrémentés, plutôt que définis.\n" "\n" "Lorsque vous réglez le <tt>~#playcount</tt> d'un morceau sur 0, les entrées " "<tt>~#lastplayed</tt> et <tt>~#laststarted</tt> sont effacées. Cependant, " "lors du réglage d'une chanson 0-play à un calcul de lecture positif, aucun " "temps de lecture ne sera créé." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Nombre de lectures" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Comptage du nombre de fois où un titre est sauté" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Plusieurs fichiers sélectionnés." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Les comptes seront incrémentés." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Editer les images incorporées" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Ajouter, supprimer ou remplacer les images intégrées." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Intégrer" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Choisir l'image à intégrer dans la piste %d" msgstr[1] "Choisir l'image à intégrer dans les pistes %d" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "Supp_rimer toutes les images" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "Incorporer l'image actuelle" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Choisir l'image…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Évaluer avec précision" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Permet d'évaluer un titre en utilisant un nombre." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Veuillez évaluer en utilisant une échelle allant de 0.0 à 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrer sur la valeur d'une étiquette" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Créé une requête de recherche à partir des étiquettes des titres " "sélectionnés." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrer sur le répertoire" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtrer sur le répertoire dans un nouvelle fenêtre de navigation." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Rechercher à partir d'une empreinte accoustique" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" "Recherche les méta-données d'un titre en utilisant l'empreinte Acoustid." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Soumettre une empreinte accoustique" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Génère une empreinte acoustique en utilisant Chromaprint et la soumet à " "Acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Clé API manquante" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Pour soumettre des empreintes, vous devez au préalable saisir votre clé API " "dans les préférences du greffon." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Demander une clé API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "Clé API :" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Service Web AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Dans la file d'attente" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "En cours d'analyse" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Recherche" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Écrire" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Publication" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Ecrire les étiquettes MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Regrouper par répertoire" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Mode Album" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Ecrire les étiquettes concernant l'album en essayant de réduire le nombre de " "parutions différentes de l'album" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "En cours de génération des empreintes :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "Informations _détaillés" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Soumettre" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Pour être soumis, les titres doivent comporter des étiquettes avec un " "identifiant de piste MusicBrainz <i><b>trackid</b></i>, ou un identifiant " "<i><b>artist</b></i> (artiste) / <i><b>title</b></i> (titre)/ <i><b>album</" "b></i>." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Empreintes :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Titres comportant un identifiant MBIDs :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Titres suffisamment étiquettés :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Titres à soumettre :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Fait. %(to-send)d/%(all)d titres à soumettre." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "En cours de soumission des empreintes :" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "En cours de soumission …" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Mettre à jour les étiquettes dans les fichiers" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Mettre à jour les étiquettes dans les fichiers. C'est la certitude que le " "compteur de lecture et les évaluations sont à jour." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exporter vers HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exporter les titres sélectionnés vers HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Envoyer à iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Envoyer des titres vers un périphérique iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Aucun dispositif iFP trouvé" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Impossible de contacter votre appareil iFP. Vérifiez que l'appareil est sous " "tension et branché et que vous avez installé ifp-line (http://ifp-driver.sf." "net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Téléchargement de %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Impossible de télécharger %s. L'appareil peut manquer d'espace ou être " "éteint." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Erreur de téléchargement" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Exportation des Données Utilisateur" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Exportation des étiquettes" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Exportation des étiquettes et des Données Utilisateur" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Exportation des Sources de Fichiers et des Données Utilisateur" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Exportation des Sources de Fichiers et des Étiquettes" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" "Exportation des Sources de Fichiers, des Étiquettes et des Données " "Utilisateur" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Importation / Exportation" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Importe et exporte des étiquettes et des données utilisateur de suivi." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Plus d'information" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Le terme \"données utilisateur des pistes\" comprend les listes de lecture " "dans lesquelles se trouvent les pistes sélectionnées et les métadonnées " "suivantes : \n" " \n" "%s \n" " \n" "Sachez que tout ce que vous avez choisi d'exporter sera importé. Si vous " "avez exporté les troncs de fichiers (noms de fichiers sans extension), " "alors, à l'importation, les fichiers sélectionnés seront renommés. \n" " \n" "Après avoir exporté un album, vous pouvez importer les données dans une " "autre version de l'album. L'ordre et le nombre de pistes peuvent être " "différents. Le greffon fait correspondre les données exportées aux nouvelles " "pistes, même si les noms de celles-ci sont légèrement différents. La " "correspondance automatique n'est pas toujours correcte, il est donc " "conseillé de ne pas trop réduire les valeurs de similarité suivantes." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Interaction de l'utilisateur lors de l'importation" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Demander une confirmation si le nombre de pistes diffère" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Demande de confirmation si le nombre d'albums diffère" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Pourcentage en dessous duquel l'utilisateur devra vérifier manuellement et " "éventuellement modifier quelle piste est associée à quelle autre." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Similitude des pistes :" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Similitude de l'album :" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Exportation de fichiers" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Écriture d'un JSON joli et clair (plus lent)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Suppression des fichiers d'exportation après qu'ils aient été importés" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Ouvrir le répertoire d'exportation" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Disques" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Pistes" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artiste(s)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Fin du dossier" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Correspondance des Albums" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Continuer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Rien à importer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Vous devez exporter quelque chose avant de pouvoir l'importer." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "L'index a été corrompu." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "Impossible d'analyser le JSON dans %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Impossible de lire %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Nom du fichier" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Correspondances des pistes" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Mise à jour de la liste du graphique." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Déjà à jour." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Récupération du classement pour la semaine de %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronisation terminée." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Erreur durant la synchronisation (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Synchronisation Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" "Met à jour les statistique de votre bibliothèque à partir de votre profil " "Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Nom d'_utilisateur :" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Créer des étiquettes de tri" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Convertit les noms d'albums et d'artistes vers les noms de tri, sans " "adaptation." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Exporter comme fichier de liste de lecture M3U / PLS" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exporter les titres sous vers liste de lecture M3U ou PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Utiliser des chemins relatifs" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Utiliser des chemins absolus" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "L'écriture dans %s a échoué." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Rescanner les titres" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Vérifie si un fichier a été modifié et le recharge ou le supprime si " "nécessaire." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Rescanner les titres" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Analyseur ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Piste" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Progression" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Pic" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Il y a %(to-process)s album à mettre à jour (sur %(all)s)" msgstr[1] "Il y a %(to-process)s albums à mettre à jour (sur %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Gain de relecture" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyse et met à jour l' information <a href=\"%(rg_link)s\">ReplayGain</a>, " "en utilisant GStreamer. Les résultats sont regroupés par album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "toujours" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "si <b>une ou plusieurs étiquettes</b> RG sont absentes" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "si les étiquettes RG de <b>album</b> sont absentes" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "Appliquer aux albums :" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Étiquettes existantes" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Séparer les étiquettes" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Séparer en une seule opération le numéro de disque de l'album et la version " "du titre." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Séparer l'album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Séparer les numéros de disque." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/a" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM :" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Réinitialiser" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Appuyez" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Appuyez sur BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Taper le BPM pour la chanson sélectionnée." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Recherche site Internet" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Recherche sur le site Web de votre choix en utilisant les balises des " "morceaux. \n" "Prend en charge les motifs, par exemple %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Rechercher selon des motifs d'URL" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Éditer les URLs sauvegardées" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Configurer les recherches …" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Recherche d'étiquettes dans Wikipédia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Ouvre une fenêtre de navigateur avec l'article Wikipédia sur l'étiquette " "correspondante du titre sélectionné." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Rechercher dans %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Éditer les étiquettes" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Échec de la recherche" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Étiquette \"%s\" introuvable." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliothèque" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Vérification des points de montage" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Parcours de la bibliothèque" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Parcours de %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Chargement des fichiers en cours" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Déplacement des fichiers de la bibliothèque" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Suppression de fichiers de la bibliothèque" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Ajout de surveillances pour %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "Aucun morceau de la bibliothèque n'a été trouvé dans l'ancienne liste de " "lecture %(filename)r (d'une taille de %(size).1f Ko)." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" "Avez-vous modifié le(s) répertoire(s) racine(s) de la bibliothèque, mais pas " "cette liste de lecture ?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "la liste de lecture %d n'a pas pu être convertie" msgstr[1] "les listes de lecture %d n'ont pas pu être converties" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Un lecteur de musique et un gestionnaire de bibliothèque musicale" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Impossible de charger le fichier : %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Lister les étiquettes" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Afficher en sortie des informations détaillées" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Colonnes à afficher et à ordonner en mode laconique (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Lister également les étiquettes programmables" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Pas assez d'arguments" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Trop d'arguments" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Description" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valeur" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Lister les étiquettes courantes" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Recopier les étiquettes d'un fichier vers un autre" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Montrer les modifications sans les appliquer" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Sauter les étiquettes qui ne peuvent pas être écrites" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" "Impossible de copier l'étiquette {tagname} dans le fichier : {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Éditer les étiquettes dans un éditeur de texte" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Modifications annulées" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Le lancement de l'éditeur de texte '%(editor-name)s' a échoué." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Aucun changement détecté" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Définir une étiquette et supprimer les valeurs existantes" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Ne peut pas définir %(tag)r pour le fichier %(format)s %(file)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Supprimer les étiquettes" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "La valeur est une expression régulière" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Supprimer toutes les étiquettes" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Impossible de combiner '--all' avec '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Impossible de supprimer {tagname} de {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Supprimer la valeur d'une étiquette" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Ajouter une valeur d'étiquette" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Impossible de définir %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Lister les informations du fichier" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Transforme l'image fournie en image embarquée et supprimer toutes les autres " "images embarquées" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Impossible de charger le fichier image : %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "L'édition de l'image %(file_name)s au format (%(file_format)s) n'est pas " "supporté par le logiciel" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Supprimer toutes les images incorporées" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraire les images embarquées dans %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Chemin dans lequel les images sont sauvegardée (par défaut dans le " "répertoire en cours)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Renommer les fichiers à partir des étiquettes" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Remplir les étiquettes en fonction du chemin du fichier" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fichier" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Remplir les numéros de pistes pour tous les fichiers" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Afficher les étiquettes selon un motif donné" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Afficher des informations d'aide" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" "'%(column-id)s' n'est pas un nom valide pour la colonne (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Inconnu(e)" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Dans l'ordre" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "Dans l'_ordre" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Aléatoire" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Aléatoire" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Préférer les meilleures évaluations" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Préférer les _meilleures évaluations" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Répéter cette piste" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Répé_ter ce morceau" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Tout répéter" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Tout _répéter" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Une seule chanson" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Une seule _chanson" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Flux" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Mise en mémoire tampon" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Impossible de créer le pipeline GStreamer (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Aucun élément GStreamer n'est disponible pour gérer le format du média" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Format du support : %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Le greffon GStreamer '%(name)s' n'a pas pu être lancé correctement" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Le canal de sortie GStreamer utilisé pour la lecture. Laisser vide pour le " "canal par défaut. Si le canal contient un récepteur, il sera utilisé à la " "place de celui par défaut." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Pipeline de s_ortie :" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Mémoire tampon :" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Désactiver la _lecture sans blanc" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Désactiver la lecture sans blanc peut éviter les problèmes de changement de " "piste avec certaines versions de GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Utiliser JACK pour la lecture si disponible" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Utilise `jackaudiosink` pour le flux de playbin s'il peut être détecté" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Connexion automatique aux périphériques de sortie JACK" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Demande à `jackaudiosink` de se connecter automatiquement" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Aucun récepteur audio GStreamer n'a été trouvé. Essayé : %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Pipeline de sortie GStreamer invalide" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Impossible de créer la sortie audio" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Le périphérique audio %r n'a pas été trouvé. Vérifiez vos paramètres Xine " "dans ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Impossible de trouver le module '{module}'. Peut-être avez-vous besoin " "d'installer le paquet ?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Impossible de trouver l'élément GStreamer '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Veuillez visiter la fenêtre des greffons pour configurer ListenBrainz. En " "attendant, les écoutes ne seront pas soumises." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Trop d'échecs de soumission consécutifs (%d). Passage en mode hors ligne. " "Veuillez visiter la fenêtre des greffons pour réinitialiser ListenBrainz. En " "attendant, les écoutes ne seront pas soumises." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "Soumission ListenBrainz" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Soumettre des écoutes à ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Je_ton d'utilisateur :" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "É_tiquettes :" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Liste de étiquettes à inclure dans la soumission. Séparées par des virgules, " "utilisez des guillemets si nécessaire." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Les morceaux correspondant à ce filtre ne seront pas soumis." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Lancer le greffon \"%(name)s\" sur la liste %(count)s ?" msgstr[1] "Lancer le greffon \"%(name)s\" sur les listes %(count)s ?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Lancer un greffon" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Utilisation" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Début de la piste" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Non disponible" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Temps" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nom du signet" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Signets" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtres" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "_Joué(s) récemment" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "_Ajouté(s) récemment" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Tous les titres" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Genre(s) en cours" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Artiste(s) en cours" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Album(s) en cours" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "_Genre aléatoire" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "_Artiste aléatoire" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Al_bum aléatoire" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "Les 40 titres les plus joués (plus de 40 peuvent être choisis en cas " "d'égalité)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nom :" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valeur :" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Entrées sauvegardées" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Éditer les entrées sauvegardées …" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matique" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Mode Piste" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Mode _Album" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Muet" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "Mode Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nouveau %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(Inconnu)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Ajouter…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Éditer" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Motif d'étiquette" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Motif d'étiquette, c'est-à-dire people:nom ou ~album~année" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Saisir une nouvelle étiquette" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Modifier l'expression de la balise" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Fichiers :" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Les titres sélectionnés seront supprimés de la bibliothèque et leurs " "fichiers supprimés du disque." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Les fichiers sélectionnés seront supprimés du disque." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Supprimer %(file_count)d fichier de manière permanente ?" msgstr[1] "Supprimer %(file_count)d fichiers de manière permanente ?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Supprimer les fichiers" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Les titres sélectionnés seront supprimés de la bibliothèque et leurs " "fichiers déplacés vers la corbeille." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Les fichiers sélectionnés seront supprimés de la corbeille." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Déplacer %(file_count)d fichier vers la corbeille ?" msgstr[1] "Déplacer %(file_count)d fichiers vers la corbeille ?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mettre à la corbeille" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Déplacement de %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Impossible à déplacer vers la corbeille" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "" "Le déplacement d'un ou de plusieurs fichiers vers la corbeille a échoué." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Suppression en cours de %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Impossible de supprimer les fichiers" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "La suppression d'un ou de plusieurs fichiers a échouée." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Navigateur" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Téléchargement des fichiers" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "manquant dans %d titre" msgstr[1] "manquant dans %d titres" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "différent dans le titre %d" msgstr[1] "différent dans les %d titres" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Séparer en _plusieurs valeurs" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Séparer le disque de l'_album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Séparer la _version du titre" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Séparer l'arrangeur de l'ar_tiste" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Séparer l'intér_prète de l'artiste" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Séparer l'intér_prète du titre" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Séparer l'artiste d'origine (Originalartist) du titre" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Ajouter une étiquette" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "É_tiquette :" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Afficher les étiquettes _programmables" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Accéder à toutes les étiquettes, y compris celles générées par une machine, " "par exemple les étiquettes MusicBrainz ou Replay Gain" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Afficher les étiquettes _multi-lignes" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" "Affichez les étiquettes potentiellement multi-lignes (par exemple 'paroles') " "ici aussi" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Rétablir" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "Enregi_strer" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Configurer" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Séparer l'étiquette" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Valeur(s) de la ou des copie(s)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Impossible d'ajouter l'étiquette" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "Impossible d'ajouter %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Les fichiers actuellement sélectionnés ne supportent pas les valeurs " "multiples pour %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Étiquette non valide" msgstr[1] "Étiquettes non valides" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Étiquette invalide %s \n" " \n" "Les fichiers sélectionnés actuellement ne permettent pas l'édition de cette " "balise." msgstr[1] "" "Étiquettes invalides %s \n" " \n" "Les fichiers sélectionnés actuellement ne permettent pas l'édition de ces " "balises." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Valeur non valide" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Valeur invalide : %(value)s \n" " \n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "L'étiquette peut ne pas être correcte" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s semble avoir été modifié pendant le fonctionnement du " "programme. Enregistrer maintenant sans réactualiser votre bibliothèque " "pourrait écraser d'autres modifications appliquées au titre." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Impossible d'enregistrer le titre" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "L'enregistrement de %(file-name)s a échoué. Le fichier peut être en lecture " "seule, corrompu ou vous n'avez pas la permission pour le modifier." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Plus d'options …" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "Ann_uler" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Rétablir" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_À propos" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "Vérifier les mises à jour …" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Greffons" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s et %(count)s de plus" msgstr[1] "%(title)s et %(count)s de plus" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Préférences d'Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Dossiers" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nouveau dossier …" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Sélectionner tous les sous-dossiers" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nouveau dossier" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Saisissez un nom pour le nouveau dossier :" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Impossible de créer le dossier" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Impossible de supprimer le dossier" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Titres" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "par %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disque %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Piste %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "_Morceau Actuel" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "Modifi_er l'affichage…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Aucun titre n'est sélectionné." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Aucun titre" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informations" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Paroles" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produit par %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artiste" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistes" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "interprètes" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Jamais" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d fois" msgstr[1] "%(n)d fois" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "ajoutée" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "dernière écoute" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "joué" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "sauts" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "évaluation" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "chemin" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "durée" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "encodage" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "débit des données" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "taille du fichier" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modifiée" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Additionnel" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d sélectionnée" msgstr[1] "%d sélectionnées" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Piste indisponible" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d titre sans album" msgstr[1] "%d titres sans album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discographie sélectionnée" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d titre sans artiste" msgstr[1] "%d titres sans artiste" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albums" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Durée totale :" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Taille totale :" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Fichiers" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Voir en ligne" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Ce titre ne contient aucune parole." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Confirmer la suppression de tous les titres ?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Les titres sélectionnés seront supprimés de la bibliothèque." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Réafficher" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "Réafficher" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Vérifiez si les colonnes de la partie gauche correspondent approximativement " "à celles de la partie droite. Si ce n'est pas le cas, vous pouvez changer " "l'ordre ici (utiliser _ pour les lignes qui ne doivent pas correspondre) :" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Ordre du côté droit :" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Abandonner les modifications apportées aux étiquettes ?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Des étiquettes ont été changées, mais n'ont pas été enregistrées. " "Enregistrer ces fichiers, ou abandonner les changements ?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Rétablir" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Le fichier existe" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Remplacer %(file-name)s ?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Remplacer le fichier" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Tâches actives" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d tâches en cours" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Basculer le mode lecture aléatoire" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Basculer le mode Répétition" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Événements" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Ordre de lecture" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Édition" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Renommer" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Requête" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Pochettes" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Erreurs de greffon" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Tout statut" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Activé" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Désactivé" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Aucune catégorie" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Toute catégorie" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Aucun greffon trouvé." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Greffons" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrer sur l'état du greffon / étiquette" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrer par type de greffon" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrer par nom ou description du greffon" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Montrer les _erreurs" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disque" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "Pis_te" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Regrou_per" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artiste" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Nom de _fichier" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "D_urée" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Aller automatiquement au titre en cours de lecture" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Défiler jusqu'au titre, dès qu'il est joué" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "_Trier les morceaux lorsque les étiquettes sont modifiées" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" "Re-tri automatique des morceaux dans la liste des chansons lorsque les " "étiquettes sont modifiées" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Toujours autoriser le tri" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" "Autoriser le tri par en-tête de colonne, y compris pour les listes de " "lecture, etc" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "Au_tres :" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Éditer …" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Ajouter ou supprimer des colonnes supplémentaires" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Colonnes visibles" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Le titre contient la _version" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "L'album contient le sous-titre du _disque" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "L'artiste contient toutes les personnes" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Le nom de _fichier contient le répertoire" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Préférences des colonnes" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Mettre à jour les colonnes" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Appliquer la configuration courante à la liste de titres, en ajoutant les " "nouvelles colonnes à la fin" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Liste des titres" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Modifier les colonnes" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Durée totale" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Filtre _global :" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Appliquer cette recherche avec tous les autres" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Rechercher" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navigateurs" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Confirmer les évaluations _multiples" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Demander confirmation avant d'évaluer plusieurs titres à la fois" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Activer les n_otations en un clic" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Activer l'évaluation par un clic dans la colonne évaluation des titres" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Evaluations" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Préférer les illustrations incorporées aux fichiers" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Choisir d'utiliser une illustration incorporée dans l'audio (si disponible) " "plutôt que d'autres sources" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Le(s) fichier(s) image(s) de pochette d'album à utiliser lorsqu'ils sont " "disponibles (supporte les caractères spéciaux). Si vous souhaitez en fournir " "plusieurs, séparez-les par des virgules." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Nom(s) de fichier d'image(s) fixe(s) préférée(s)" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Pochette d'Album" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Lecture" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Afficher la configuration" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Si aucune information de Replay Gain n'est disponible pour un titre, " "multiplier le volume par cette valeur" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Gain de repli :" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Multiplier le volume pour tous les titres par cette valeur, tant que le " "résultat ne sature pas" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "Gain de _préamplification :" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Activer l'ajustement de volume par les valeurs Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Ajustement du volume par Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Poursuivre la lecture au démarrage" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Si la musique est en cours de lecture au moment de l'arrêt, lancez " "automatiquement la lecture au prochain démarrage" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Évaluation par _défaut :" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Échelle d'évaluation :" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Facteur bayésien moyen (C) pour les notations agrégées.\n" "0 signifie une moyenne conventionnelle, des valeurs plus élevées signifient " "que les albums avec peu de pistes auront des notes moins extrêmes. La " "modification de cette valeur déclenche un nouveau calcul pour tous les " "albums." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Montant moyen bayésien :" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "Courri_el :" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Les évaluations et le nombre de lectures seront sauvegardés dans les " "étiquettes pour cette adresse électronique" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "_Enregistrement automatique des changements de balises" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Enregistrer les étiquettes modifées sans confirmation lorsque plusieurs " "fichiers sont édités en même temps" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Un ensemble de séparateurs à utiliser lors de la division des valeurs de " "balises dans l'éditeur de balises. La liste est séparée par des espaces." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Séparer l' _étiquette sur :" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Un ensemble de séparateurs à utiliser lors de l'extraction de sous-" "étiquettes à partir des étiquettes dans l'éditeur d'étiquettes. La liste est " "séparée par des espaces et chaque entrée ne doit contenir que deux " "caractères." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "_Séparer la sous-étiquette sur :" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Étiquettes" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Édition d'étiquettes" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Mise à jour pour de nouvelles notations" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Rechercher dans la bibliothèque" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Chercher les changements dans la bibliothèque" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Re_charger la bibliothèque" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Recharger tous les titres de votre bibliothèque. Cette opération peut durer " "un certain temps." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Titre cachés" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Rafraîchir la bibliothèque au démarrage" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "_Surveillance des répertoires en cas de changement" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Surveillance des répertoires de la bibliothèque pour les ajouts, " "suppressions et renommages de fichiers externes." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Analyser les répertoires" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s et %(count)d de plus" msgstr[1] "%(title)s et %(count)d de plus" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Propriétés" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_File d'attente" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Effacer la file d'attente" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" "Désactiver la file d'attente - la file d'attente sera ignorée lors de la " "lecture" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Éphémère" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Supprimer les titres de la file d'attente après les avoir joués" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Persistant" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Garder les titres dans la file d'attente après les avoir joués" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modèle" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Arrêter à la Fin" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d titre (%(time)s)" msgstr[1] "%(count)d titres (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Parcourir la bibliothèque" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Basculer la visibilité de la file d'attente" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Erreur de lecture" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Configurer les répertoires de la bibliothèque ?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" "Vous n'avez pas de bibliothèque musicale. Voudriez-vous faire ça maintenant ?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "Pas mai_ntenant" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "Configurer" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Impossible d'ajouter les titres" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s utilise un protocole non supporté." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Aller au titre en cours de lecture" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Fichier" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "Titre_s" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "Afficha_ge" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "Navigation" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "Lecture" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Aide" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Ajouter un dossier…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Ajouter un fichier…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Ajouter un emplacement…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Modifier les signets…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Stop" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Arrêter après ce titre" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Raccourcis clavier" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Aide en ligne" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Aide à la recherche" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Ajouter un chemin" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Saisir le chemin vers un fichier audio :" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Impossible d'ajouter le chemin" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s n'est pas un chemin valide." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Ajouter de la musique" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Ajouter des dossiers" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Fichiers de musique" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Ajouter des fichiers" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Voulez-vous vraiment mettre en file d'attente le titre %d ?" msgstr[1] "Voulez-vous vraiment mettre en file d'attente les titres %d ?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Mettre en file d'attente" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Confirmer la modification de l'évaluation de ces %d titres ?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Les évaluations enregistrées seront supprimées" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "Supprime_r les évaluations" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Le classement de tous les morceaux sélectionnés sera modifié en %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Modifie_r l'évaluation" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Remplacer les espaces par des _soulignés" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Remplacer les [double]points par des traits d'union" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "Par exemple. \"iv : allegro.flac \" → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Remplacer les caractères incompatibles avec _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Enlever les signes _diacritiques" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Remplacer les caractères non-_ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Utiliser uniquement des caractères minuscules" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Renommer les fichiers" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "A_perçu" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Noms du fichier" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Déplacer la pochette de l'album" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Voir '[albumart] nom de fichier' entrée pour la configuration des chaînes de " "recherche d'images" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Réécrire la pochette de l'album vers la cible" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Supprimer les répertoires vides" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Pochette d'Album" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nouveau nom" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Impossible de renommer le fichier" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Le renommage de %(old-name)s en %(new-name)s a échoué. Il est possible que " "le fichier cible existe déjà, ou que vous n'ayez pas la permission pour " "créer le nouveau fichier ou de supprimer l'ancien." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorer _toutes les erreurs" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "Arrêter" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continuer" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Le chemin n'est pas absolu" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Le modèle \n" "\t%s \n" "contient / mais ne commence pas à la racine. Pour éviter les dossiers mal " "nommés, utilisez la racine de votre modèle en le commençant par / ou ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Les titres placés dans ces répertoires seront ajoutées à votre bibliothèque " "au prochain rafraîchissement de la bibliothèque" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Le nouveau répertoire sera analysé après ajout" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" "Tous les morceaux des répertoires sélectionnés seront également supprimés de " "la bibliothèque" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Déplacer" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Déplacer la racine d'un scan (mais pas les fichiers), en migrant les " "métadonnées de toutes les pistes incluses." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Supprimer {dir!r} et toutes ses pistes ?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Supprimer les chemins de bibliothèque {n} et leurs pistes ?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Supprimer le chemin de bibliothèque ?" msgstr[1] "Supprimer les chemins de bibliothèque ?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Supprimer" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Choisir des répertoires" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Sélectionner Ce Répertoire" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Sélectionner le Répertoire Actuel / Nouveau Répertoire pour {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Ceci déplacera les métadonnées QL :\n" "\n" "{old!r} → {new!r}\n" "\n" "Les fichiers audio eux-mêmes ne sont pas déplacés par cette opération.\n" "Néanmoins, il est recommandé de faire une sauvegarde (y compris du fichier " "'songs' de Quodlibet)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Déplacer la racine du scan {dir!r} ?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "OK, déplacer !" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Recherches sauvegardées" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Éditer les recherches sauvegardées…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" "Rechercher dans votre bibliothèque, en utilisant un texte libre ou des " "requêtes QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Rechercher après avoir _tapé au clavier" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" "Afficher le résultat d'une recherche dès que l'utilisateur a terminé la " "saisie" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limite :" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Pondéré" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Ajouter une requête" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Ajouter une requête QL ou du texte libre pour être &édité ensemble" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Montrer la durée restante" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Fenêtre principale" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Reculer de 10 secondes" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Avancer de 10 secondes" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Focaliser sur la requête de recherche" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Réinitialiser les filtres et aller au titre en cours de lecture" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Ouvrir la fenêtre d'informations des titres sélectionnés" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Ouvrir le gestionnaire d'étiquettes des titres sélectionnés" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Placer en file d'attente les titres sélectionnés" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Supprimer les titres sélectionnés" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Afficher le contenu de la recherche interne" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Clic gauche sur le titre de la colonne" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Ajouter la colonne à la liste des colonnes à trier" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Vue arborescente" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Replier l'élément ou sélectionner l'élément parent" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Déplier l'élément" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Entrées texte" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Annuler la dernière modification" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Rétablir les derniers changement annulés" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Sélectionner tous les titres des panneaux" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrer sur %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Toutes les entêtes" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Colonnes « _Piste »" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Colonnes « _Album »" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Colonnes « Ar_tistes »" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Colonnes « _Date »" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "En-têtes _Fichier" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "En-têtes _Production" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Personnaliser les en-têtes…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "Dépli_er la colonne" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Retirer la piste : \"%(title)s\" de la bibliothèque ?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Retirer les pistes %(count)d de la bibliothèque ?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Supprimer de la bibliothèque" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Lancer le greffon \"%(name)s\" sur la piste %(count)d ?" msgstr[1] "Lancer le greffon \"%(name)s\" sur les pistes %(count)d ?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Lancer le greffon \"%(name)s\" sur l'album %(count)d ?" msgstr[1] "Lancer le greffon \"%(name)s\" sur les albums %(count)d ?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Configurer les greffons …" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "A_jouter à la file d'attente" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Supprimer de la bibliothèque…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Impossible d'afficher les fichiers" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Erreur d'affichage des fichiers, ou aucun programme disponible pour les " "afficher." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Afficher dans le gestionnaire de fichiers" msgstr[1] "_Afficher %(total)d Fichiers dans le gestionnaire de fichiers" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Télécharger un fichier…" msgstr[1] "_Télécharger %(total)d fichiers…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "réussi" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "échoué" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Téléchargement terminé" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Télécharger {name!r} vers" msgstr[1] "Télécharger {total} fichiers vers" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Télécharger ici" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Remplacer les so_ulignés par des espaces" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Mettre une _majuscule aux valeurs résultantes" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Séparer en plusieurs _valeurs" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Étiquettes par chemin" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Les étiquettes remplacent celles existantes" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Les étiquettes sont ajoutées à celles existantes" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Le modèle \n" "\t%s \n" "n'est pas valide. Il est possible qu'il contienne deux fois la même balise " "ou qu'il ait des parenthèses déséquilibrées (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Le motif saisi est invalide. Assurez-vous d'avoir saisi < et > comme " "\\< et \\> et que vos étiquettes sont judicieuses.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Modifier l'affichage" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Numéros de pistes" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Co_mmencer à :" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Nombre _total de pistes :" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Lecture/Pause" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Précédent" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "et %d de plus …" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Enregistrement en cours des titres modifés." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d titres enregistrés\n" "(%(remaining)s restantes)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s sur %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Vérifier les mises à jour" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "La connexion a échoué" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Vous utilisez bien la dernière version %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "La version plus récente %(new-version)s est disponible\n" "\n" "Vous utilisez actuellement l'ancienne version %(old-version)s\n" "\n" "Visiter notre <a href='%(url)s'>site Internet</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Liste de lecture Vide" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Les listes de lectures doivent être nommées" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Une liste de lecture nommée %(name)s existe déjà à %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Pochettes embarquées dans les étiquettes/titres" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Utilise les pochettes inclues dans les fichiers audio." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Pochette du système de fichiers" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "Utilise les images trouvées dans les répertoires contenant le titre." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Illustration de la pochette" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Interroger les fournisseurs de pochettes d'albums" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Afficher des informations d'utilisation succinctes" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Afficher la version et le copyright" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Imprimer les informations de débogage" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Utilisation : %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[options]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "L'option %r n'est pas reconnue." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "L'option %r nécessite un argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r n'est pas un préfixe unique." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s seconde" msgstr[1] "%s secondes" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Aucun renseignement de durée" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d secondes" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d heure" msgstr[1] "%d heures" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d jour" msgstr[1] "%d jours" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d année" msgstr[1] "%d années" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "intitulé ?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "La date doit être saisie au format 'AAAA', 'AAAA-MM-JJ' ou 'AAAA-MM-JJ HH:MM:" "SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Les gains ReplayGain doivent être saisis au format « x.yy dB »." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Les pics ReplayGain doivent être saisis au format 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "" "Les identifiants de piste MusicBrainz doivent être dans le format UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Le statut de publication MusicBrainz doit être « official » (officiel), " "« promotional » (promotionnel) ou « bootleg » (illégal)." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "La langue doit être au format ISO 639-2 avec trois caractères" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Sauvegarder le fichier %d" msgstr[1] "Sauvegarder les fichiers %d" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Sauvegarde automatique" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Impossible d'éditer le titre" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "La sauvegarde de %s a échoué. Le fichier peut être en lecture seule, " "corrompu, ou vous n'avez pas la permission de le modifier." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codage invalide]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangeur" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangeurs" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arrangement" #: quodlibet/util/tags.py:86 msgid "author" msgstr "auteur" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "auteurs" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "commenter" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compositeur" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compositeurs" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "composition" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "chef d'orchestre" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "chefs d'orchestre" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigeant" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contact" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "date" #: quodlibet/util/tags.py:94 msgid "description" msgstr "description" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "genres" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "interprète" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "performance" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "regrouper" #: quodlibet/util/tags.py:98 msgid "language" msgstr "langue" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licence" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "parolier" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "paroliers" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "paroles" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisation" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titre" #: quodlibet/util/tags.py:105 msgid "version" msgstr "version" #: quodlibet/util/tags.py:106 msgid "website" msgstr "site web" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "Artiste de l'album" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "sous-titre du disque" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disque" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "piste" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "numéro catalogue" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "date de première publication" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "album original" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "Artiste (première édition)" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "date d'enregistrement" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "pays de publication" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "clé initiale" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "Identifiant MusicBrainz d'enregistrement" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "Identifiant MusicBrainz de piste" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID de la version de MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "ID de l'artiste MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "ID de l'artiste publié par MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "ID TRM de MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Statut de l'album MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Type d'album MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "ID du groupe de diffusion de MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "gain de piste" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "pic de la piste" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "gain pour l'album" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "pic de l'album" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "volume sonore de référence" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "disques" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "pistes" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "dernier démarrage" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nom complet" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "point de montage" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personnes" #: quodlibet/util/tags.py:168 msgid "year" msgstr "année" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "année de première publication" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "signet" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "profondeur de bits" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "format de fichier" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "listes de lecture" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "fréquence d'échantillonnage" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "Nombre de canaux" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "trier" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "rôles" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Éditeur d'étiquettes audio (tags)" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Éditer les étiquettes dans vos fichiers audio" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Lecteur de Musique" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Écouter, parcourir ou éditer votre collection musicale" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso est un éditeur d'étiquette avec la même interface d'édition que " "Quod Libet. Il vous permet de voir et d'éditer n'importe quelles étiquettes " "que vous voulez, pour tous les formats de fichiers supportés." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Les formats de fichiers pris en charge incluent Ogg Vorbis/Opus/Speex/FLAC, " "MP3, FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, " "SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet est un programme de gestion de musique. Il offre plusieurs façons " "différentes de visualiser votre bibliothèque audio, ainsi que la prise en " "charge de la radio Internet et des flux audio. Il dispose de capacités " "extrêmement souples d'édition et de recherche des étiquettes de métadonnées." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Exporte une liste de lecture vers une liste de lecture Sonos, à condition " #~ "que les deux partagent une structure de répertoire." #~ msgid "Export to Sonos playlist" #~ msgstr "Exporter vers une liste de lecture Sonos" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Impossible d'ajouter <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Étiquettes non valides" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Étiquettes invalides <b>%s</b>\n" #~ "\n" #~ "Les fichiers sélectionnés actuellement ne permettent pas l'édition de ces " #~ "étiquettes." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Évaluer automatiquement les titres, selon qu'il sont joués ou passés. " #~ "Cette méthode utilise l'algorithme 'accéléré' de vux par Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f secondes" #~ msgid "Startup" #~ msgstr "Démarrage" #~ msgid "Audio Feeds" #~ msgstr "Flux audio" #~ msgid "_Audio Feeds" #~ msgstr "_Flux audio" #~ msgid "New" #~ msgstr "Nouveau" #~ msgid "Automatic Library Update" #~ msgstr "Rafraîchir la bibliothèque automatiquement" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "" #~ "Maintenir votre bibliothèque à jour avec <i>inotify</i>. Dépend de %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Permet le contrôle de Quod Libet à l'aide de la spécification d'interface " #~ "D-Bus MPRIS 2." #~ msgid "Searching for lyrics…" #~ msgstr "Recherche de paroles…" #, fuzzy #~ msgid "broker username" #~ msgstr "nom d'utilisateur du courtier" #, fuzzy #~ msgid "broker password" #~ msgstr "mot de passe du courtier" #~ msgid "<artist>" #~ msgstr "<artiste>" #~ msgid "<album>" #~ msgstr "<album>" #~ msgid "<title>" #~ msgstr "<titre>" #~ msgid "OK" #~ msgstr "OK" #~ msgid "" #~ "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " #~ "both share a directory structure. Shares configuration with <a href=" #~ "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</" #~ "a>." #~ msgstr "" #~ "Exporte dynamiquement une liste de lecture vers une liste de lecture " #~ "Logitech Squeezebox, à condition que les deux partagent une structure de " #~ "répertoire. Partage la configuration avec <a href=\"quodlibet:////prefs/" #~ "plugins/Squeezebox Output\">Squeezebox Sync plugin</a>." #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Exporter les méta-données des titres sélectionnés vers un fichier .tags." #~ msgid "Import Metadata" #~ msgstr "Importer les méta-données" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Importe les méta-data des titres sélectionnés à partir d'un fichier .tags." #~ msgid "Migrate Metadata" #~ msgstr "Migrer les méta-données" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "" #~ "Ajoute les métadata propres à Quodlibet dans les fichiers des titres." #~ msgid "_Copy" #~ msgstr "_Copier" #~ msgid "_Paste" #~ msgstr "Coller" #~ msgid "Information to copy/paste" #~ msgstr "Informations vers copier/coller" #~ msgid "Map tracks by disc and track number" #~ msgstr "" #~ "Se baser sur le numéro de disque et le numéro de piste pour établir des " #~ "correspondances" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Activez cette option lorsque vous souhaitez migrer les métadonnées d'un " #~ "album à un autre tout en faisant correspondre les numéros de disque et de " #~ "piste. \n" #~ "\n" #~ "<b>Note:</b> Ceci doit être activé lorsque les métadonnées sont copiées " #~ "pour que les informations de piste soient stockées." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "%d piste est stockée." #~ msgstr[1] "%d pistes sont stockées." #~ msgid "Unsupported file type" #~ msgstr "Type de fichier non supporté" #~ msgid "Unable to add station" #~ msgstr "Impossible d'ajouter la radio" #~ msgid "Search Library" #~ msgstr "Rechercher dans la bibliothèque" #~ msgid "_Search Library" #~ msgstr "_Rechercher dans la bibliothèque" #~ msgid "Quit Program" #~ msgstr "Quitter le Programme" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "Désactive l'économiseur d'écran durant la lecture d'un titre." #~ msgid "No lyrics found" #~ msgstr "Les paroles n'ont pas été trouvées." #~ msgid "_Zoom level:" #~ msgstr "Niveau de _Zoom :" #~ msgid "URL:" #~ msgstr "URL :" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Effectuer une recherche en utilisant l'URL ci-dessous si les paroles " #~ "n'ont pu être trouvées dans LyricsWika." #~ msgid "Alternate search" #~ msgstr "Recherche alternative" #~ msgid "Web Lyrics" #~ msgstr "Paroles sur le Web" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Affiche une barre latérale contenant les paroles en ligne de la chanson " #~ "jouée." #~ msgid "Skip Songs" #~ msgstr "Sauter des chansons" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "La lecture saute par-dessus les chansons dont la classification est égale " #~ "ou inférieure à un seuil donné." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Supporte les modèles QL\n" #~ "par exemple <tt><~artist~title></tt>" #~ msgid "Burn CD" #~ msgstr "Graver un CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Gaver des CD avec K3b, Brasero ou xfburn" #~ msgid "The single image filename to use if selected" #~ msgstr "Le nom de fichier de l'image à utiliser si sélectionné" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "" #~ "Le fichier image d'illustration d'album à utiliser en cas de contrainte " #~ "(supporte les caractères génériques)" #~ msgid "Vertical Split" #~ msgstr "Séparer verticalement" #~ msgid "Device Properties" #~ msgstr "Propriétés du périphérique" #~ msgid "Device:" #~ msgstr "Périphérique :" #~ msgid "Not mounted" #~ msgstr "Non monté" #~ msgid "Mount point:" #~ msgstr "Point de montage :" #~ msgid "Media Devices" #~ msgstr "Périphériques multimedia" #~ msgid "_Media Devices" #~ msgstr "Périphériques _multimedia" #~ msgid "_Eject" #~ msgstr "_Éjecter" #~ msgid "_Properties" #~ msgstr "_Propriétés" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s utilisé(es), %(free-size)s disponible(s)" #~ msgid "%s is not connected." #~ msgstr "%s n'est pas connecté." #~ msgid "Copying %(song)s" #~ msgstr "Copie de %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Impossible de copier le titre" #~ msgid "There is not enough free space for this song." #~ msgstr "Espace libre insuffisant pour ce titre" #~ msgid "%s could not be copied." #~ msgstr "%s n'a pas pu être copié." #~ msgid "Unable to delete songs" #~ msgstr "Impossible de supprimer les titres" #~ msgid "Deleting %(song)s" #~ msgstr "Suppression en cours de %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s ne peut pas être supprimé." #~ msgid "Unable to delete song" #~ msgstr "Impossible de supprimer le titre" #~ msgid "Ejecting %s failed." #~ msgstr "L'éjection de %s a échoué." #~ msgid "Unable to eject device" #~ msgstr "Impossible d'éjecter le périphérique" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Aucun périphérique, désactivation du navigateur de périphériques de média." #~ msgid "Rate the playing song" #~ msgstr "Évaluer le titre en cours de lecture" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Afficher ou cacher la liste principale des titres (abandonné)" #~ msgid "Unknown Device" #~ msgstr "Périphérique inconnu" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Impossible d'importer %s, qui est nécessaire au support matériel." #~ msgid "%r is not a supported device." #~ msgstr "Le système %r n'est pas supporté." #~ msgid "Initializing device backend." #~ msgstr "Initialisation du gestionnaire de périphériques." #~ msgid "Trying '%s'" #~ msgstr "Tentative avec '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Impossible de se connecter au gestionnaire de périphériques." #~ msgid "Device backend initialized." #~ msgstr "Gestionnaire de périphériques initialisé." #~ msgid "_Filename pattern:" #~ msgstr "Motif du nom de _fichier :" #~ msgid "File Bug Report" #~ msgstr "Rapport de Bogue de Fichier" #~ msgid "Top of screen" #~ msgstr "Haut d'écran" #~ msgid "Middle of screen" #~ msgstr "Milieu d'écran" #~ msgid "Bottom of screen" #~ msgstr "Bas d'écran" #~ msgid "_Clear" #~ msgstr "_Nettoyer" #~ msgid "Lyrics:" #~ msgstr "Paroles :" #~ msgid "Lyrics Window" #~ msgstr "Fenêtre des paroles" #~ msgid "_Lyrics" #~ msgstr "Paro_les" #~ msgid "" #~ "Use Python expressions in queries. Syntax is '@(python: expression)'. The " #~ "variable 's' is the song being matched." #~ msgstr "" #~ "Utiliser dans les requêtes des expression Python. La syntaxe est " #~ "'@(python: expression)'. La variables 's' contient le titre analysé." #~ msgid "Browse Folders" #~ msgstr "Naviguer dans les dossiers" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Ouvre les dossiers des titres dans un gestionnaire de fichiers" #~ msgid "Unable to open folders" #~ msgstr "Impossible d'ouvrir les dossiers" #~ msgid "No program available to open folders." #~ msgstr "Aucun programme disponible pour ouvrir les dossiers." #~ msgid "Fix MP3 Duration" #~ msgstr "Corriger la durée du MP3" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Supprime les trames TLEN des étiquettes ID3, qui peuvent être sources " #~ "d'erreurs dans le calcul de la durée." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Rechercher un artiste dans Wikipedia" #~ msgid "" #~ "Opens a browser window with Wikipedia article on the playing song artist." #~ msgstr "" #~ "Ouvre un navigateur avec l'article Wikipedia concernant l'artiste dont le " #~ "titre est en cours de lecture." #~ msgid "Audio device: %s" #~ msgstr "Périphérique audio: %s" #~ msgid "Downloads" #~ msgstr "Téléchargements" #~ msgid "Size" #~ msgstr "Taille" #~ msgid "_Download" #~ msgstr "_Télécharger" #~ msgid "Stop Once Empty" #~ msgstr "Arrêter une fois vide" #~ msgid "_Copy to Device" #~ msgstr "_Copier sur le périphérique" #~ msgid "Save" #~ msgstr "Enregistrer" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Impossible d importer %s. Désactivation de navigateur de flux audio." #~ msgid "High Res" #~ msgstr "Haute résolution" #~ msgid "Audio Backend Failed to Load" #~ msgstr "Impossible de charger le gestionnaire audio" #~ msgid "" #~ "Loading the audio backend '%(name)s' failed. Audio playback will be " #~ "disabled." #~ msgstr "" #~ "Le chargement du périphérique audio '%(name)s' a échoué. La sortie audio " #~ "est désactivée." #~ msgid "_Open" #~ msgstr "_Ouvrir" #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Une exception est survenue dans Quod Libet. Un fichier de débuggage a été " #~ "enregistré dans <b >%(dump-path)s</b>, qui nous aidera à trouver la cause " #~ "du problème. Veuillez ouvrir un ticket d'incident à %(new-issue-url)s et " #~ "attachez-y ce fichier ou son contenu. Ce fichier peut contenir certaines " #~ "informations vous identifiant, telles qu'une liste de titres récemment " #~ "écoutés. Si ceci est inacceptable, envoyez à la place <b>%(mini-dump-" #~ "path)s</b> accompagné d'une description détaillée du problème." #~ msgid "browsers" #~ msgstr "navigateurs" #, fuzzy #~ msgid "Controls the tone of your music with an equalizer." #~ msgstr "Contrôlez la tonalité de votre musique avec un égaliseur" #~ msgid "Unable to download lyrics." #~ msgstr "Impossible de télécharger des paroles." #~ msgid "Set or toggle the playback order" #~ msgstr "Définir ou basculer d'un ordre de lecture à un autre" #~ msgid "Uninitialized iPod" #~ msgstr "iPod non initialisé" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Voulez-vous créer une base de données vide sur cet iPod ?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Gain du _volume (dB) :" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combiner les tags à valeurs _multiples" #~ msgid "Capacity:" #~ msgstr "Capacité :" #~ msgid "Firmware:" #~ msgstr "Firmware :" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Impossible d'enregistrer la base de données de l'iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Impossible d'enregistrer la base de données de l'iPod" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "" #~ "Impossible d importer %s. Désactivation de navigateur de flux audio." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "pic de la piste" #~ msgid "Shuffle" #~ msgstr "Mélangé" #~ msgid "Weighted" #~ msgstr "Mélangé et pondéré" #~ msgid "_Weighted" #~ msgstr "Mélangé et _pondéré" #~ msgid "_One Song" #~ msgstr "_Une chanson" #~ msgid "Restart the playlist when finished" #~ msgstr "" #~ "Recommencer la liste de lecture après que toutes les chansons ont été " #~ "jouées" #~ msgid "Disable Browser" #~ msgstr "Désactiver le navigateur" #~ msgid "_Disable Browser" #~ msgstr "_Désactiver le navigateur" #, fuzzy #~ msgid "Force Write" #~ msgstr "Écrire" #~ msgid "Filter on _Genre" #~ msgstr "Filtrer sur ce _genre" #~ msgid "Filter on _Artist" #~ msgstr "Filtrer sur cet _artiste" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrer sur cet al_bum" #~ msgid "_Music" #~ msgstr "_Musique" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Signets" #~ msgid "Song _List" #~ msgstr "_Liste de chansons" #, fuzzy #~ msgid "D:" #~ msgstr "A:" #, fuzzy #~ msgid "W:" #~ msgstr "A:" #, fuzzy #~ msgid "E:" #~ msgstr "E: " #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Arrêter après cette chanson" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "et %d de plus..." #~ msgstr[1] "et %d de plus..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Séparer le disque de l'_album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Temps" #, fuzzy #~ msgid "Select an album" #~ msgstr "Choisir _tous" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s et %(count)d de plus" #~ msgstr[1] "%(title)s et %(count)d de plus" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Listes de lecture" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Utiliser des coins arrondis pour les vignettes" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Arrondir les coins des jaquettes d'album. Peut nécessiter un redémarrage " #~ "pour prendre effet." #~ msgid "Re_fresh Library" #~ msgstr "Ra_fraîchir la bibliothèque" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Supprimer les doublons" #, fuzzy #~ msgid "Unable to open input files" #~ msgstr "Impossible d'ouvrir les fichiers" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer n'a aucun élément pour gérer la lecture de fichiers. Vérifiez " #~ "votre installation." #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Valeur non valide" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "Le moteur audio %r n'est pas installé." #~ msgid "ql-save" #~ msgstr "Enregi_strer" #~ msgid "command|filename" #~ msgstr "nom_de_fichier" #~ msgid "command|tag" #~ msgstr "etiquette" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Impossible de trouver %s." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Rechercher" #~ msgid "%d of %d" #~ msgstr "%d sur %d" #~ msgid "Usage: %s %s\n" #~ msgstr "Utilisation: %s %s\n" #~ msgid "_Download..." #~ msgstr "_Télécharger..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nouvelle radio internet" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Écraser <b>%s</b> ?" #~ msgid "Output Error" #~ msgstr "Erreur de sortie" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet est déjà en fonctionnement." #~ msgid "No song is currently playing." #~ msgstr "Il n'y a pas de chanson en cours de lecture." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Impossible d'écrire le fichier %s. Suppression." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Modifier les signets" #~ msgid "_New Folder..." #~ msgstr "_Nouveau dossier..." #~ msgid "_Add to Playlist" #~ msgstr "_Ajouter à la liste de lecture" #~ msgid "_Edit Display..." #~ msgstr "_Éditer l'affichage des informations..." #~ msgid "Output Log" #~ msgstr "Journal" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d radio" #~ msgid "_Add a Location..." #~ msgstr "_Ajouter une adresse..." #~ msgid "_Output Log" #~ msgstr "J_ournal" #~ msgid "Invalid command %r received." #~ msgstr "Commande invalide (%r) reçue." #~ msgid "Unknown browser %r." #~ msgstr "Navigateur inconnu (%r)." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Configurer les colonnes..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Vous êtes sur le point de changer la notation de %d chansons.\n" #~ "Voulez-vous continuer?" #~ msgstr[1] "" #~ "Vous êtes sur le point de changer la notation de %d chansons.\n" #~ "Voulez-vous continuer?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "Vous allez supprimer %d chanson." #~ msgstr[1] "Vous allez supprimer %d chansons." #, fuzzy #~ msgid "Track Headers" #~ msgstr "Colonnes « _Piste »" #, fuzzy #~ msgid "People Headers" #~ msgstr "Colonnes « Ar_tistes »" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Colonnes « _Album »" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Colonnes « _Date »" #, fuzzy #~ msgid "File Headers" #~ msgstr "Colonnes « _Fichier »" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Colonnes « _Production »" #~ msgid "Tag:" #~ msgstr "É_tiquette :" #~ msgid "Too Many Errors" #~ msgstr "Trop d'erreurs" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Arrêt de la lecture suite à %d erreurs successives." #~ msgid "Warnings" #~ msgstr "Avertissements" #~ msgid "No log available." #~ msgstr "Aucun journal disponible" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "Artiste de l'album" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artistes" #, fuzzy #~ msgid "album (sort)" #~ msgstr "Artiste de l'album" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "interprètes" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "interprètes" #~ msgid "MusicBrainz album artist ID" #~ msgstr "Identifiant MusicBrainz - artiste (album)" #~ msgid "errors" #~ msgstr "erreurs" #~ msgid "Permanently delete this file?" #~ msgstr "Supprimer définitivement ce fichier?" #~ msgid "Permanently delete these files?" #~ msgstr "Supprimer définitivement ces fichiers?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s et %(count)d de plus..." #~ msgstr[1] "%(title)s et %(count)d de plus..." #~ msgid "Version:" #~ msgstr "Version:" #~ msgid "_Cause an Error" #~ msgstr "_Provoquer une erreur" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "Impossible d'ajouter %s à la bibliothèque.\n" #~ "\n" #~ msgid "Do you wish to continue?" #~ msgstr "Voulez-vous continuer?" #, fuzzy #~ msgid "Confirm duplicates removal" #~ msgstr "Confirmez la suppression de la liste de lecture" #~ msgid "No eject command found." #~ msgstr "Pas de commande d'éjection trouvée." #~ msgid "Unable to start web browser" #~ msgstr "Impossible de lancer un navigateur web" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Aucun navigateur web n'a pu être trouvé. Veuillez positionner votre " #~ "variable $BROWSER, ou assurez-vous de l'existence de /usr/bin/sensible-" #~ "browser." #~ msgid "Library Error" #~ msgstr "Erreur de bibliothèque" #, fuzzy #~ msgid "_Output device:" #~ msgstr "Pipeline de s_ortie" #~ msgid "translator-credits" #~ msgstr "" #~ "Joshua Kwan <joshk@triplehelix.org>\n" #~ "kwikwi <kwiskas@gmail.com>\n" #~ "fab <fab@gnux.info>\n" #~ "Bastien Gorissen <kadomony@gmail.com>\n" #~ "Nick Boultbee <nick.boultbee@googlemail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "" #~ "Listez les autres en-têtes que vous voulez voir affichés, séparées par " #~ "des espaces" #~ msgid "_Edit and Continue" #~ msgstr "Éditer et Continuer" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Vous êtes sur le point de changer la notation de %d chanson.\n" #~ "Voulez-vous continuer?" #~ msgstr[1] "" #~ "Vous êtes sur le point de changer la notation de %d chansons.\n" #~ "Voulez-vous continuer?" #~ msgid "Confirm rating" #~ msgstr "Vérifier notation" #~ msgid "Search your library" #~ msgstr "Rechercher dans votre bibliothèque de musique" #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "Ce programme est un logiciel libre ; veuillez voir la source pour les\n" #~ "conditions de duplication. Il n'y a PAS de garantie; même pour la\n" #~ "COMMERCIALISATION ou L'APTITUDE À UN OBJET PARTICULIER.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r ne contient aucun navigateur." #~ msgid "Total size unknown" #~ msgstr "Taille totale inconnue" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r ne contient aucun périphérique." #~ msgid "Quod Libet Plugins" #~ msgstr "Greffons de Quod Libet" #~ msgid "Quod Libet Preferences" #~ msgstr "Préférences de Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Pas jouée aujour_d'hui" #~ msgid "Not Played in a _Week" #~ msgstr "Pas jouée depuis une _semaine" #~ msgid "Not Played in a _Month" #~ msgstr "Pas jouée depuis un _mois" #~ msgid "B_ottom 40" #~ msgstr "Fl_op 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "Les 40 chansons que vous avez le moins jouées (plus de 40 peuvent être " #~ "choisies en cas d'égalité)" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Afficher les recherches simples en bleu, les avancées en vert, et les " #~ "invalides en rouge" #~ msgid "Separators for splitting tags" #~ msgstr "Séparateurs pour la séparation des étiquettes (\"tags\")" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | contrôle ]" #~ msgid "Date" #~ msgstr "Date" #~ msgid "Choose New Stations" #~ msgstr "Choisir des nouvelles radios Internet" #~ msgid "Add" #~ msgstr "Ajouter" #, fuzzy #~ msgid "Bitrate" #~ msgstr "Débit des données" #~ msgid "_Stations..." #~ msgstr "_Radios internet..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Initialisation du moteur audio (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Initialisation de la librairie (%s)" #~ msgid "Unable to save library" #~ msgstr "Impossible d'enregistrer la bibliothèque de données." #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "Le canal de sortie %r n'a pas pu être créée. Vérifiez vos paramètres " #~ "GStreamer dans ~/.quodlibet/config." #~ msgid "Sort by title" #~ msgstr "Tri par titre" #~ msgid "Sort by artist" #~ msgstr "Tri par artiste" #~ msgid "Lyrics provided by %s." #~ msgstr "Paroles fournies par %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Des paroles n'ont pas été trouvées.\n" #~ "\n" #~ "Vous pouvez appuyer le bouton Télécharger pour faire une recherche de " #~ "paroles en ligne. Vous pouvez aussi saisir les paroles vous-même et " #~ "appuyer 'Enregistrer'." #~ msgid "part" #~ msgstr "partie" #~ msgid "Opening audio device." #~ msgstr "Ouverture du périphérique audio." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d chansons sauvegardées" #~ msgid "MusicBrainz album ID" #~ msgstr "Identifiant MusicBrainz - album" #~ msgid "Loaded song library." #~ msgstr "Bibliothèque de chansons chargée." #~ msgid "Unable to open audio device" #~ msgstr "Impossible d'ouvrir la périphérique audio" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet a essayé d'accéder aux pilotes 'autosink' et '%(sink)s' mais " #~ "aucun n'a pu être ouvert. Définissez votre canal GStreamer en changeant " #~ "la ligne\n" #~ "<b>pipeline = %(sink)s</b>\n" #~ " dans ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet n'a pas pu trouver l'élément 'filesrc' de GStreamer. Vérifiez " #~ "votre installation de GStreamer." ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/gl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000720003�14436352625�013577� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Ex Falso / Quod Libet galician translation # Copyright (C) 2005 Johám-Luís Miguéns Vila # Johám-Luís Miguéns Vila <galiza.ceive@gmail.com>, 2005 - 2010 # Galician: galego reintegracionista, seguindo as normas da Associaçom Galega da Língua <http://www.agalgz.org>. # msgid "" msgstr "" "Project-Id-Version: Quod Libet VC\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-09-23 11:34+0000\n" "Last-Translator: Adolfo Jayme Barrientos <fitojb@ubuntu.com>\n" "Language-Team: Galician <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/gl/>\n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Título" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "componentes" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Cabeçeiras de _data" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "artista original" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "Estilo" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Puntuación" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Editar a vista" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Ordenar _por:" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Preferências" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista de álbuns" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Lista de álbuns" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Todos os álbuns" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbuns" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Mostrar _cobertas dos discos" msgstr[1] "Mostrar _cobertas dos discos" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Cancións sen álbum" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d pista" msgstr[1] "%d pistas" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disco" msgstr[1] "%d discos" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Todos os Álbuns" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferencias da lista de álbuns" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Amosar as _portadas dos álbuns" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "A procura _inclúi os componentes" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[opções]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Vista de álbuns" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navegador da colección" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d canción" msgstr[1] "%d cancións" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Padrón inválido" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Colección de álbuns" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Colección de álbuns" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Desconhecido" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Extraer em valores _múltiplos" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizada" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "_Eliminar Emisora" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etiqueta" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Xuntar" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Preferências da Lista de Álbuns" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Tamanho total:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Tamanho total:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Preferências do Navegador em paneis" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Mostrar _cobertas dos discos" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Todos os Álbuns" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "Nom há novas emisoras" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Sistema de arquivos" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Sistema de arquivos" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Non se puideron copiar as cancións" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Os arquivos seleccionados non se puideron copiar a outra lista ou á fileira." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Engadir á colección" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "As listas de emisoras só poden conter enderezos de emisoras, non outras " "listas de emisoras nen listas de reproducción. Os seguintes enderezos non se " "puideron cargar:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio por Internet" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Nova Emisora" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Baixar os arquivos" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nova emisora" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Insire o enderezo dunha emisora de radio por Internet:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Electrónica" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Éxitos antigos" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Xaponesa" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "India" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Relixiosa" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Éxitos" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Baile" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "qualificaçom" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Radio universitaria" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Faladoiro / Novas" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambiente" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clásica" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Novas" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Eslava" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grega" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gótica" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_Nova Emisora" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Radio por Internet" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Nova Emisora" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Preferidos" #: quodlibet/browsers/iradio.py:598 #, fuzzy msgid "No Category" msgstr "Sem categoria" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Nova Emisora" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "_Nova Emisora" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Non se atoparon emisoras" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Non se atoparon emisoras de radio por Internet en %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Todas as emisoras relacionadas xa están na túa colección." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "_Engadir à lista" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "Elimina_r da Lista" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d emisora" msgstr[1] "%(count)d emisoras" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Vista por paneis" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Vista por paneis" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Seleccionar _todo" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Descoñecido" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Todo" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Colunas adicionais" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferencias da vista por paneis" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listas" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Listas" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Eliminar da lista" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importar" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Non se puido importar a lista de reproducción" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "O Quod Libet só pode importar listas nos formatos M3U ou PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Eliminar os ficheiros" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Muda_r o nome" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Non se puido mudar o nome da lista" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importar lista" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importar" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_Nova Lista" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" msgstr[1] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Nova Lista" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Preferências do Navegador em paneis" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Listas" #: quodlibet/browsers/playlists/util.py:34 #, fuzzy, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Está a piques de apagar a lista <i>%s</i>.\n" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Toda a información sobre a lista seleccionada váise eliminar e non se poderá " "repor." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Pista" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nova lista" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Introduz um nome para o novo cartafol:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "A importar a lista de reproducción.\n" "\n" "%(current)d/%(total)d cancións engadidas." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nova fonte" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Insire o enderezo dunha fonte de audio (feed)" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Engadir um arquivo..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Ac_tualizar a colecçom" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Verificar a existência de novas canções no cartafol" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Non se puido engadir a fonte" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> nom puido ser engadida. O servidor pode estar caído, ou o endereço " "pode nom ser o de umha fonte de áudio (feed)." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "A infraestrutura de audio activada non soporta URLs. Desactivóuse o " "navegador de fontes (feeds)." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limitar os resultados" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Dividir em _valores múltiplos" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Lista de pistas" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Lista de pistas" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Vista em paneis" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Vista em paneis" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Procurar" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "pistas" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "endereço" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> nom está conectado." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "O Quod Libet nom está a ser executado." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "un xestor de música e reproductor de son" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[opções]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Amosa a canción que se está a reproducir" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Comezar a tocar inmediatamente" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Ir á canción seguinte" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Ir á canción anterior ou, de estarmos próximos ao inicio, recomezar a " "presente" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Ir á canción anterior" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Comezar a reproducción" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Parar a reproducción" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Alternar entre tocar e parar" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Começar a reproduçom" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Aumentar o volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Diminuir o volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Amosar o estado da reproducción" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Agochar a fiestra principal" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Amosar a fiestra principal" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Alternar entre mostrar ou non a fiestra principal" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Centrarse no reproductor activo" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Eliminar os filtros de navegación activos" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Reler e actualizar a colección" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Desactivar o Navegador" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Amosar a lista de reproducción activa" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Amosar o contido da fileira" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Mostrar o conteúdo da fileira" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Comezar sen extensións" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "O Quod Libet nom está a ser executado." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Saír do Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Avanzar na canción activa" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Alternar entre reproduzir e parar" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Alternar entre reproduzir e parar" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Activar ou desactivar o modo de repetición" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Alternar entre reproduzir e parar" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Axustar o volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Procurar na colección de música" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "procura" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Reproducir un arquivo" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "nome do ficheiro" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Avançar na cançom reproduzida" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Configurar o navegador activo" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Qualificar a cançom activa" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Abrir un novo navegador" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Amosar ou agochar a fileira" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrar nun valor aleatorio" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "etiqueta" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrar nun valor da etiqueta" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etiqueta=valor" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Pór un arquivo ou unha procura na fileira" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Engadir á fileira os arquivos (separados por comas)" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nome" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Mostrar os resultados da procura na saída estándard" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Tirar da fileira un ficheiro ou unha procura" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "localización" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Padrom inválido" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumento inválido para '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Proba %s --help" #: quodlibet/errorreport/ui.py:58 #, fuzzy msgid "An Error Occurred" msgstr "Ocorreu un erro" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Ignorar todos os _erros" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "descriçom" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "un editor de etiquetas de música" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "cartafol" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Editor de etiquetas de áudio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "ID do MusicBraniz da pista" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID do MusicBraniz da pista" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Codificaçom inválida]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Título" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Editor de etiquetas de áudio" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Letras capitais nas etiquetas" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Preferências do Navegador em paneis" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Tamanho total:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Editar a vista" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Importância" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 #, fuzzy msgid "_Outline" msgstr "Infraestrutura de _saída:" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editar a vista" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Antever" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informaçom" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Formatos admitidos: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtrar no e_stilo" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "cartafol" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Fontes de Áudio (feeds)" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "%s: Nom se puido achar media-player-info." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Nova Emisora" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Guardar qualificações e o _contador" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "data da gravaçom" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Erro ao carregar %r" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Nova Emisora" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Preferências" #: quodlibet/ext/events/automask.py:22 #, fuzzy msgid "Automatic Masking" msgstr "Auto_mática" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 #, fuzzy msgid "Automatic Rating" msgstr "Auto_mática" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Importar lista" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importar" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Importar" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Descartar as modificacións nas etiquetas?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Descartar as modificacións nas etiquetas?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "_Parar" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "padrom" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "padrom" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 #, fuzzy msgid "Reggae" msgstr "Reggaeton" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 #, fuzzy msgid "Soft Rock" msgstr "Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "A infraestrutura de áudio activa nom admite URLs. \n" "Desactivou-se o navegador de fontes (feeds)." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d segundo" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Predefinido" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Seleccionar" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Antever" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Personalizada" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Nom se puidérom eliminar as canções" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Padrom inválido" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Reprodutor de música" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modelo:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Radio por Internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Qualificaçom" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Predefinido" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "endereço" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Agochar a fiestra principal" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Predefinido" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "padrom" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "padrom" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d cançom" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Saída do registro" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "padrom" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "endereço" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Tipo de álbum segundo MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Nome:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Título" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 #, fuzzy msgid "Show notifications" msgstr "Nom há novas emisoras" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: quodlibet/ext/events/notify.py:222 #, fuzzy msgid "Song Notifications" msgstr "Nom há novas emisoras" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Seguinte" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Nom há novas emisoras" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Dispositivo:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Outros:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Artista" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "Padrom para o _nome:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Ál_bum aleatório" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "álbuns" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Importância" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Ál_bum aleatório" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 #, fuzzy msgid "Alternative Seek Bar" msgstr "Alternativa" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Marcadores" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Nome do marcador" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Nome do marcador" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[opções]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "Ascendente" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "data da gravaçom" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Eliminar os ficheiros" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Letra" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Eliminar os ficheiros" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Letra" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Nom se atopárom emisoras" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "padrom" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Editar os valores guardados..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Artista" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Antever" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Reprodutor de música" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Importar lista" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "companhia" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Escolher Novas Emisoras" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Letra" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "A rota nom é absoluta" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "O padrom\n" "\t<b>%s</b>\n" "contém / mais nom começa no cartafol pai (/). Para previr cartafoles com " "nomes errados, começa o padrom por / or ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Sem canções seleccionadas." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Sem canções seleccionadas." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Nom foi possível guardar a cançom" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, fuzzy, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "Tag a partires do Nome" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Letra" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Nom se puiderom abrir os arquivos" msgstr[1] "Nom se puiderom abrir os arquivos" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Letra" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Parado" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d cançom" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "padrom" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Auto_mática" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Sen reproducción" #: quodlibet/ext/events/trayicon/__init__.py:52 #, fuzzy msgid "Tray Icon" msgstr "Preferências da Ícona" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Reprodutor" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "_Parar" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "_Antever" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 #, fuzzy msgid "_Next" msgstr "Seguinte" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Barallar" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetición" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Parar despois desta cançom" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Abrir um novo navegador" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editar as e_tiquetas" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Información" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Listas" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Comportamento" #: quodlibet/ext/events/trayicon/prefs.py:48 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "A roda do rato axusta o volume;\n" "Shift e a roda do rato muda de cançom" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Roda do _Rato" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Editar vista" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Letra" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Nom se atopou a letra desta cançom" #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Nom foi possível guardar a cançom" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Erros" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternativa" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "Nom há novas emisoras" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Arquivos" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Antever" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtrar no _artista" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 #, fuzzy msgid "Default" msgstr "Predefinido" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Personalizada" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Personalizada" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filtrar no e_stilo" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filtrar no _artista" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Fontes de Áudio (feeds)" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Por favor, introduça a localizaçom da fonte (feed):" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importar lista" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Importar" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Nom se atopárom emisoras" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "Padrom para o _nome:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Non foi possível importar a lista" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "Padrom para o _nome:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Importar lista" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Eliminar a tag seleccionada" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, fuzzy, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" msgstr[1] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "As cancións duplicadas serán eliminadas da lista '%s'." #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Nova Lista" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "última vez tocada" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "última vez tocada" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Na fileira" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Na fileira" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Na fileira" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Nunca" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Nunca" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "agrupaçom" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Nom foi possível copiar as canções" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtrar no e_stilo" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Etiquetas inválidas" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "O valor é umha expressom regular" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Valores guardados" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Valores guardados" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Mudar o nome" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Colecçom" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Debug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Agochar a fiestra principal" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Nome do ficheiro" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Nom foi possível guardar a cançom" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Lista de Álbuns" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Tamanho" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Procurar:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Procurar" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Lista de Álbuns" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Editar os marcadores..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Editar os marcadores..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Marcadores" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "Tipo de álbum segundo MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nome" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Título" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "Tipo de álbum segundo MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "procura" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Procurar" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Nom se atopárom extensões." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "endereço" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Lista de Álbuns" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Clássica" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Lista de Álbuns" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Nom se atopárom extensões." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Antever" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "etiqueta" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Mudar o nome" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "etiqueta" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Nunca" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Valor inválido" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Personalizada" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Nom foi possível copiar as canções" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Desactivar o Navegador" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Eliminar a tag seleccionada" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Eliminar a tag seleccionada" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "Eliminar a tag seleccionada" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "_Eliminar Emisora" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Editar a vista" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 #, fuzzy msgid "Skip Count" msgstr "saltar contador" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Extraer em valores _múltiplos" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "Extrair as imagens incrustadas" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Extrair as imagens incrustadas" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "Eliminar a tag seleccionada" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "Extrair as imagens incrustadas" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filtrar num valor da etiqueta" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "O GStreamer nom puido carregar a cançom seleccionada." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtrar no e_stilo" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Na fileira" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Gardar" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "ID do MusicBraniz da pista" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "cartafol" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "Cabeceiras dos _álbuns" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Nova Emisora" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Nom se atopárom extensões." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "A mover %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Erro ao carregar %r" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Importar lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Importar lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Sem informaçom sobre a duraçom" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Lista de Álbuns" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importar lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrar no e_stilo" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Disco" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Pista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Artista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "álbuns" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Continuar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "%s: Nom se puido achar media-player-info." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "%s: Nom se puido achar media-player-info." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Nome do ficheiro" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "pistas" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Erro ao carregar %r" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Mudar o nome" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Importar lista" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Erro ao expulsar <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Ac_tualizar a colecçom" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Ac_tualizar a colecçom" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Pista" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Editar as etiquetas" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Editar as etiquetas" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Todos os Álbuns" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Antever" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etiqueta" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Nom se puidérom eliminar as canções" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Procurar" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "padrom" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Editar os valores guardados..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Cores nos termos da _procura" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Editar etiquetas" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Barra de pesquisa" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Colección" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "A comprobar os pontos de montaxe" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "A analisar a colección" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "A analisar %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "A analisar a colecçom" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Eliminar os filtros de navegaçom activos" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "um gestor de música e reprodutor" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Imposíbel carregar o arquivo: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Mostrar as etiquetas" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Mostrar a saída para depuración" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Colunas e orde para mostralas no modo depuración (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Mostrar informaçom para de_puraçom" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Sen argumentos dabondo" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 #, fuzzy msgid "Too many arguments" msgstr "Demasiados erros" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "descriçom" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valor" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Mostrar todas as etiquetas habituais" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Copiar as etiquetas dun arquivo a outro" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Mostrar as mudanzas, sen aplicalas" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Saltar as etiquetas que nom se poidan escreber" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Nom se puido copiar a etiqueta %r para o arquivo: %r" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Editor de etiquetas de áudio" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Sem canções seleccionadas." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Estabelece unha etiqueta e elimina os valores existentes" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Nom se puido copiar a etiqueta %r para o arquivo: %r" #: quodlibet/operon/commands.py:321 #, fuzzy msgid "Remove tags" msgstr "_Eliminar Emisora" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "O valor é unha expresión regular" #: quodlibet/operon/commands.py:330 #, fuzzy msgid "Remove all tags" msgstr "Eliminar a tag seleccionada" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Non se pode combinar '--all' con '--regexp'" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Impossível eliminar %r de %r" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Filtrar num valor da etiqueta" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Filtrar num valor da etiqueta" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Non se puido estabelecer %r" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Sem informaçom sobre a duraçom" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Erro ao carregar o arquivo: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "Extrair as imagens incrustadas" #: quodlibet/operon/commands.py:571 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrair as imagens incrustadas" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Mudar o nome dos arquivos baseándose nas etiquetas" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Crear as etiquetas baseándose na rota ao arquivo" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Arquivo" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Crear os números de pista para todos os arquivos" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Mostrar as etiquetas coincidentes co padrón indicado" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Mostra informaçom sumária sobre o modo de utilizaçom" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nom é umha localizaçom válida." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Descoñecido" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "En orde" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_En orde" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "Aleató_rio" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Aleatorio" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "última vez tocada" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Repetir" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Repetir" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Umha cançom" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Umha cançom" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "A encher o buffer" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Nom se puido criar a pipeline GStreamer predefinida." #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "A saída de GStreamer utilizada para a reproduçom, e.g. 'alsasink " "device=default'.\n" "Deixa-a em branco para utilizar a predeterminada." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Infraestrutura de _saída:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%d segundo" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Duración do _buffer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nom foi atopado dispositivo de áudio" #: quodlibet/player/gstbe/util.py:167 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Saida de GStreamer inválida, tentará-se com a predeterminada." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Non se puido crear a saída de audio" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Non se atopou o dispositivo de son %r. Verifica as opcións do Xine en ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nom puido ligar-se com a pipeline do GStreamer: '%s'" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nome:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Extensões" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Comezo" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Intre" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nome do marcador" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Marcadores" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtros" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Nunca tocadas" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Engadidas _recentemente" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Principais 40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Nova Emisora" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Estilo _aleatorio" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Ar_tista aleatorio" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Ál_bum aleatorio" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "As 40 cancións máis tocadas (aparecerán máis de corenta se hai cancións " "tocadas o mesmo número de veces)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nome:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valor:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Valores gardados" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Editar os valores guardados..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_mática" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "Cabeceiras dos _números de pista" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "Cabeceiras dos _álbuns" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ajuste de volume do _Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Desconhecido" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Engadir um arquivo..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Editar a vista..." #: quodlibet/qltk/data_editors.py:365 #, fuzzy msgid "Tag expression" msgstr "O valor é umha expressom regular" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filtrar num valor da etiqueta" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "O valor é umha expressom regular" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Arquivos" #: quodlibet/qltk/delete.py:63 #, fuzzy msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/delete.py:72 #, fuzzy msgid "The selected files will be deleted from disk." msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Eliminar os ficheiros" #: quodlibet/qltk/delete.py:106 #, fuzzy msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/delete.py:115 #, fuzzy msgid "The selected files will be moved to the trash." msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mover para o lixo" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "A mover %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Nom foi possível guardar a base de dados do iPod" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Erro ao expulsar <b>%s</b>." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "A eliminar %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Nom foi possível eliminar o arquivo" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Erro ao intentar eliminar <b>%s</b>." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Navegadores" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Baixar os arquivos" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "non se atopou de %d canción" msgstr[1] "non se atopou de %d cancións" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "diferente en %d canción" msgstr[1] "diferente en %d cancións" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Extraer valores múltiplos" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Extraer o disco do _álbum" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Extraer a _versión do título" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Extraer o arranxista do a_rtista" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Extraer o intér_prete do artista" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Extraer o _Intérprete do Artista" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Extraer a _Versom do Título" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Engadir unha etiqueta" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Etiqueta" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Mostrar etiquetas _programáticas" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Acceder a todas as etiquetas, mesmo a aquelas xeradas automaticamente, p.ex. " "as etiquetas MusicBrainz ou ReplayGain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Mostrar etiquetas _programáticas" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nunca" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Gardar" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Continuar" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Editar as etiquetas" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Copiar as _cobertas dos discos" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Non se puido engadir a etiqueta" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Non se puideron engadir as cancións" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Nom foi possível engadir <b>%s</b>\n" "\n" "Os arquivos seleccionados nom permitem valores múltiplos." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Etiqueta inválida" msgstr[1] "Etiqueta inválida" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Etiqueta inválida: <b>%s</b>\n" "\n" "Os ficheiros seleccionados non permiten a edición desa etiqueta." msgstr[1] "" "Etiqueta inválida: <b>%s</b>\n" "\n" "Os ficheiros seleccionados non permiten a edición desa etiqueta." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Valor inválido" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Valor inválido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "A etiqueta pode non ser correcta" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> mudou mentres o programa está a ser executado. Guardar sem reler a " "colecçom pode eliminar outras modificações que se figéram.\n" "\n" "Guardar de todos xeitos?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Non se puido gardar a canción" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Erro ao guardar <b>%s</b>. Pode ser que o arquivo só permita a leitura, " "esteja corrompido, ou nom tenha permissões para o editar." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Mais opções..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Extensións" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s e %(count)d mais" msgstr[1] "%(title)s e %(count)d mais" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferencias do Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Cartafoles" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Novo Cartafol" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Seleccionar todos os _cartafoles subordinados" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Novo cartafol" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Insire un nome para o novo cartafol" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Non se puido crear o cartafol" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Non se puido eliminar o cartafol" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Cancións" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "por %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Pista %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Editar a vista" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Non foi seleccionada ningunha canción." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Sen cancións" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Información" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Letra" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Producido por %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistas" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "intérpretes" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nunca" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d vez" msgstr[1] "%d vezes" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "engadida" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "última vez tocada" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "contador" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "saltada" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "puntuación" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "duración" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Informaçom" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "Ascendente" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "taxa de bits" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "tamaño" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificada" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d seleccionada" msgstr[1] "%d seleccionadas" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Pista non disponíbel" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d canción sen álbum" msgstr[1] "%d cancións sen álbum" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discografía seleccionada" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d canción sen artista" msgstr[1] "%d cancións sen artista" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "álbuns" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Duración total:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Tamaño total:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Arquivos" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Non se atopou a letra desta canción." #: quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" #: quodlibet/qltk/maskedbox.py:21 #, fuzzy msgid "The selected songs will be removed from the library." msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Descartar as modificacións nas etiquetas?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "As etiquetas mudaron pero non se gardaron. Gardar os arquivos ou descartar " "as mudanzas?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Nunca" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "O arquivo existe" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Mudar o nome dos arquivos" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Tarefas activas" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "Número de tarefas activas: %d" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Alternar entre reproduzir e parar" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Alternar entre reproduzir e parar" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "Ordem de Repr_oduçom" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Ediçom das etiquetas" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Mudar o nome" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "procura" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Tamanho total:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Erros nas extensións" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Activado" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Desactivado" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Sen categoría" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Sen categoría" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Non se atoparon extensións." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Extensões" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Mostrar os _erros" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Pista" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "agrupaçom" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artista" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Ál_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Nome" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Duración" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Ir á canción reproducida automaticamente" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Ao mudar a canción reproducida, rolar cara ela na lista" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Outras:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Editar a vista..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Engadir ou eliminar colunas de información adicional" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Colunas visíbeis" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "O título inclúe a _versión" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "O álbum inclúe a _parte" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "A procura _inclúi \"componentes\"" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "O nome inclúe o carta_fol" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Preferências" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Colunas adicionais" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Aplicar a configuración actual á lista, engadindo as novas colunas ao final" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de cancións" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Colunas adicionais" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Filtro _global:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Aplicar esta procura engadíndoa ás demais" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Procurar" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Confirmar a puntuación _múltipla" #: quodlibet/qltk/prefs.py:314 #, fuzzy msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Obter confirmaçom antes de mudar a qualificaçom de várias canções à vez." #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Activar as puntuacións c_un click" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Permitir mudar a qualificaçom com um click na coluna de qualificações da " "lista" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Puntuacións" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Preferir as portadas _incrustadas" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Escoller utilizar as portadas incrustadas no ficheiro de audio (de estaren " "disponíbeis) antes que doutras fontes" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Forçar o nome de arquivo da imagem:" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Lista de Álbuns" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Parar a reproduçom" #: quodlibet/qltk/prefs.py:400 #, fuzzy msgid "Output Configuration" msgstr "Saída do registro" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "De non existir información sobre o axuste Replay Gain para a canción, " "multiplicar o volume por este valor" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Ganância por defeito (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Multiplicar o volume de todas as cancións por este valor, sempre que non se " "produzan cortes" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Ganância do _volume (dB)" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Activar o axuste do Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Axuste do Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 #, fuzzy msgid "_Default rating:" msgstr "Predefinido" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Qualificações" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Factor de media _Bayesiana (C) para as puntuacións acumuladas.\n" "0 significa unha media convencional, valores máis elevados significan que " "álbuns \n" "con poucas pistas terán menor puntuación extrema. Mudar este valor executa " "un recálculo \n" "para todos os álbuns." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Cantidade de media _Bayesiana:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Correo-e:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "As qualificações e o contador determinarám-se para este endereço de correio-e" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Descartar as mudanças na etiqueta?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Gardar as mudanzas nas etiquetas sen solicitar confirmación individual ao se " "editaren varios arquivos" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Relaçom de separadores para diferenciar os valores das etiquetas, separados " "por espaços" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Extraer _de:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Relaçom de separadores para diferenciar os valores das etiquetas, separados " "por espaços" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Extraer _de:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Editar as etiquetas" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Edición de etiquetas" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Nova Emisora" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Procurar na colecçom" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Escrutar por modificacións na colección de música" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Reler a colecçom" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Reler todas as canções da sua colecçom (pode demorar moito tempo)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Sem Canções" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "Actualizar a colecçom ao iniciar" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Analisar os _cartafoles" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s e %(count)d máis" msgstr[1] "%(title)s e %(count)d máis" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Propiedades" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Fileira" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Eliminar os erros" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Geral" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Eliminar todas as canções da fileira" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modelo:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d canción (%(time)s)" msgstr[1] "%(count)d cancións (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Examinar a colección" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Alternar entre mostrar e agochar a fiestra principal" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Parar a reproduçom" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Seleccionar os cartafoles" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Non se puideron engadir as cancións" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> emprega um protocolo nom admitido." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Ir á canción reproducida" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Arquivo" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "C_ançom" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Ver" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Navegadores" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Control" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Axuda" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Engadir um Cartafol..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Engadir um arquivo..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Engadir umha localizaçom" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editar os marcadores..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Parar despois desta cançom" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Axuda en Internet" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Procurar" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Engadir un enderezo" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Insire o enderezo dun arquivo de música:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Non se puido engadir o enderezo" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nom é umha localizaçom válida." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Engadir música" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Engadir um Cartafol..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Reprodutor de música" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Engadir um arquivo..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" msgstr[1] "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Fileira" #: quodlibet/qltk/ratingsmenu.py:26 #, fuzzy, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Está a piques de mudar as qualificações de %d canções.\n" "Deseja continuar?" #: quodlibet/qltk/ratingsmenu.py:29 #, fuzzy msgid "The saved ratings will be removed" msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "_Eliminar Emisora" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "A qualificaçom de todas as canções seleccionadas mudará para '%s'" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Qualificaçom" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Substituír os espazos por trazos _baixos" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Eliminar os caracters non compatíbeis co _Windows(tm)" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Eliminar as marcas diacríticas" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Eliminar os caracteres non-_ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Empregar unicamente caracteres de caixa-_baixa" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Mudar o nome dos arquivos" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Antever" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Nome do ficheiro" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "artista do álbum" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Eliminar cobertas e cartafoles nom utilizados" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Lista de Álbuns" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Novo nome" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Non se puido mudar o nome do arquivo" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Erro ao tentar mudar o nome de <b>%s</b> a <b>%s</b>. Pode ser que o arquivo " "de destino já exista, ou que nom tenha permissões para criar o novo arquivo " "ou eliminar o antigo." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorar todos os _erros" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continuar" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "O enderezo non é absoluto" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "O patrón\n" "\t<b>%s</b>\n" "contén / pero non comeza na raíz (/). Para evitar cartafoles mal indicados, " "comeza o teu padrón por / ou ~/" #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "As canções localizadas nesses cartafoles (separados por ':') serám engadidas " "à sua colecçom" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "A eliminar pista orfã do iPod" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Colecçom" msgstr[1] "Colecçom" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Eliminar Emisora" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Seleccionar cartafoles" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Seleccionar os cartafoles" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Valores guardados" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Editar os valores guardados..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Procurar na colección, empregando texto ou procuras QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "_Procurar despois de escreber" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Mostrar os resultados despois de rematar de escrever" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limite:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Importancia" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "procura" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Amosar o tempo restante" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Letra" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Centrar-se no reprodutor actual" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Avançar na cançom reproduzida" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Nom se puidérom eliminar as canções" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Nom se puidérom eliminar as canções" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 #, fuzzy msgid "Expands the element" msgstr "Colunas adicionais" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "Cabeceiras dos _álbuns" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Cabeceiras da pista" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Cabeceiras do á_lbum" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Cabeceiras dos _componentes" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Cabeceiras da _data" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Cabeceiras do _arquivo" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Cabeceiras de p_rodución" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Personalizar as cabeceiras..." #: quodlibet/qltk/songlist.py:1219 #, fuzzy msgid "_Expand Column" msgstr "Colunas adicionais" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Eliminar da Colecçom" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Eliminar da Colecçom" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Eliminar da Colecçom" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Cores nos termos da _procura" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Engadir á _fileira" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Eliminar da Colecçom" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Nom foi possível eliminar o arquivo" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Baixar" msgstr[1] "_Baixar" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Barra de pesquisa" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Baixar o arquivo" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Lista de Álbuns" msgstr[1] "Lista de Álbuns" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Baixar o arquivo" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Substituir os trazos _baixos por espazos" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Maiúsculas nas etiquetas (title-case)" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Extraer valores _múltiplos" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etiquetas a partires do enderezo" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "As etiquetas reemprazan ás anteriores" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "As etiquetas engádense ás anteriores" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "O patrón\n" "\t<b>%s</b>\n" "non é válido. Pode que conteña a mesma etiqueta dúas veces ou que teña " "parénteses ou chaves desaxustadas (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "O patrón que introduciches era inválido. Asegúrate de que insires < e " "> como \\< e \\> e que as etiquetas están equilibradas.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Editar a vista" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Números de pista" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Comezar de_nde:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Pistas _totais:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "_Parar" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "_Antever" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "e %d mais..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "A gardar as cancións modificadas." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d cancións gardadas\n" "(restan %(remaining)s)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "A mover %(current)d/%(total)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "A comprovar os pontos de montagem" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "endereço" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importar lista" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Xá existe umha lista co nome %s ." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Mostrar _cobertas dos discos" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Sistema de arquivos" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Tamanho total:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Amosar indicacións sumarias sobre o modo de utilización" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Amosar a versión e o copyright" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Sem informaçom sobre a duraçom" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opcións]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Non se recoñeceu a opción %r." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "A opción %r require un argumento." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r non é un prefixo único." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Non consta a duración" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d día" msgstr[1] "%d días" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d ano" msgstr[1] "%d anos" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "Nom há titlecase em galego" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "A data há ser inserida nos formatos 'YYYY', 'YYYY-MM-DD' ou 'YYYY-MM-DD HH:" "MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "As ganancias do Replay Gain han ser inseridas no formato 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Os limites do Replay Gain han ser inseridos no formato 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Os ID do MusicBrainz deben utilizar un formato UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "O estatus do lanzamento do MusicBrainz debe ser 'official', 'promotional' ou " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "O idioma debe ser un código de tres letras ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Erro ao expulsar <b>%s</b>." msgstr[1] "Erro ao expulsar <b>%s</b>." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Non se puido editar a canción" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Erro ao gardar <b>%s</b>. Pode ser que o arquivo sexa de só lectura, estea " "corrompido ou que non teñas permisos para editalo." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codificación inválida]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "álbum" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arranxista" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arranxistas" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "arrangista" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor/a" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autoras/es" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "Recomendada" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compositor/a" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compositoras/es" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "compositor/a" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "director/a" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "directoras/es" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "director/a" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contacto" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "descrición" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "estilo" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "estilo" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "intérprete" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "interpretación" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "agrupación" #: quodlibet/util/tags.py:98 msgid "language" msgstr "idioma" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licenza" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "letrista" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "Autores/as das letras" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "autor da letra" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "compañía" #: quodlibet/util/tags.py:104 msgid "title" msgstr "título" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versión" #: quodlibet/util/tags.py:106 msgid "website" msgstr "página de Internet" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "artista do álbum" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "subítulo / parte" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "pista" # label ID #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "número ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "data da publicación orixinal" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "álbum orixinal" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artista orixinal" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "data de gravación" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "país de publicación" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID do MusicBraniz da pista" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID do MusicBrainz do lançamento" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID do MusicBrainz da publicación" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID do MusicBrainz do artista" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID do MusicBrainz do lançamento" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "ID do MusicBrainz do TRM" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID do MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Estado do álbum no MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Tipo de álbum no MusicBrainz" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID do MusicBrainz do lançamento" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "ganancia de volume da pista" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "pico de ganancia da pista" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "ganancia de volume do álbum" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "pico de ganancia do álbum" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Preferências" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "discos" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "pistas" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "última vez comezada" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nome completo" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "ponto de montaxe" #: quodlibet/util/tags.py:166 msgid "people" msgstr "componentes" #: quodlibet/util/tags.py:168 msgid "year" msgstr "ano" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "data de publicaçom original" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "marcador" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "Formato" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Listas" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor de etiquetas de música" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Edita as etiquetas dos teus arquivos de música" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Reproductor de música" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Escoita, examina ou edita a túa colección de música" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Importar lista" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Nom foi possível engadir a cançom" #~ msgid "Invalid tags" #~ msgstr "Etiquetas inválidas" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Etiquetas inválidas <b>%s</b>\n" #~ "\n" #~ "Os arquivos seleccionados non permiten a edición das etiquetas." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d segundo" #, fuzzy #~ msgid "Startup" #~ msgstr "_Importar" #~ msgid "Audio Feeds" #~ msgstr "Fontes de audio" #~ msgid "_Audio Feeds" #~ msgstr "_Fontes de audio" #, fuzzy #~ msgid "New" #~ msgstr "Notícias" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "A procurar a letra..." #, fuzzy #~ msgid "<artist>" #~ msgstr "artista" #, fuzzy #~ msgid "<album>" #~ msgstr "álbum" #, fuzzy #~ msgid "<title>" #~ msgstr "título" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importar lista" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importar lista" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informaçom" #~ msgid "Unsupported file type" #~ msgstr "Tipo de arquivo nom admitido" #~ msgid "Unable to add station" #~ msgstr "Nom foi possível engadir a emisora" #~ msgid "Device Properties" #~ msgstr "Propriedades do dispositivo" #~ msgid "Device:" #~ msgstr "Dispositivo:" #~ msgid "Not mounted" #~ msgstr "Nom está montado" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Ponto de montagem:" #~ msgid "Media Devices" #~ msgstr "Dispositivos externos" #~ msgid "_Media Devices" #~ msgstr "Dispositivos _externos" #~ msgid "_Eject" #~ msgstr "_Expulsar" #, fuzzy #~ msgid "_Properties" #~ msgstr "Propriedades" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> utilizado, <b>%s</b> disponível" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "A copiar <b>%(song)s</b>" #~ msgid "Unable to copy song" #~ msgstr "Non foi possível copiar a cançom" #~ msgid "There is not enough free space for this song." #~ msgstr "Nom há espaço livre de abondo para essa cançom." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> nom puido ser copiada." #~ msgid "Unable to delete songs" #~ msgstr "Nom se puidérom eliminar as canções" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "A eliminar <b>%(song)s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> nom se puido eliminar." #~ msgid "Unable to delete song" #~ msgstr "Non foi possível eliminar a cançom" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Erro ao expulsar <b>%s</b>." #~ msgid "Unable to eject device" #~ msgstr "Nom foi possível expulsar o dispositivo" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Sem sistema de infraestrutura de dispositivos, desactivou-se o navegador " #~ "de dispositivos" #~ msgid "Search Library" #~ msgstr "Procurar na colecçom" #~ msgid "_Search Library" #~ msgstr "_Procurar na colecçom" #~ msgid "Rate the playing song" #~ msgstr "Qualificar a cançom activa" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Mostrar ou agochar a lista principal" #~ msgid "Unknown Device" #~ msgstr "Dispositivo desconhecido" #, fuzzy #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Nom se puido importar a biblioteca dbus-python, necessária para\n" #~ "a interacçom com os dispositivos." #~ msgid "%r is not a supported device." #~ msgstr "%r nom é um dispositivo admitido." #~ msgid "Initializing device backend." #~ msgstr "A iniciar a infraestrutura de dispositivos." #~ msgid "Trying '%s'" #~ msgstr "A tentar '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "" #~ "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #~ msgid "Device backend initialized." #~ msgstr "Iniciou-se a infraestrutura de dispositivos." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "Padrom para o _nome:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Eliminar os erros" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Letra" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Limpar a procura" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Letra" #, fuzzy #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "Ver e editar as tags da cançom reproduzida" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Letra" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "saltar contador" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Nom foi possível criar o cartafol" #~ msgid "Audio device: %s" #~ msgstr "Dispositivo de áudio: %s" #~ msgid "Downloads" #~ msgstr "Descargas" #~ msgid "Size" #~ msgstr "Tamanho" #~ msgid "_Download" #~ msgstr "_Baixar" #, fuzzy #~ msgid "The single image filename to use if selected" #~ msgstr "O nome do arquivo da capa que se pretender forçar" #~ msgid "The album art image file to use when forced" #~ msgstr "O nome do arquivo da capa que se pretender forçar" #~ msgid "_Copy to Device" #~ msgstr "_Copiar ao dispositivo" #, fuzzy #~ msgid "browsers" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Nom se puido importar o python-feedparser. Desactivou-se o navegador de " #~ "fontes (feeds) " #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Ocorreu un problema no Quod Libet. Un arquivo de depuraçom, que nos pode " #~ "ajudar a analisar o erro, foi guardado em <b>%s</b>. \n" #~ "Por favor, abre un novo tema en http://code.google.com/p/quodlibet/issues/" #~ "list e inclúi o arquivo ou o contido do mesmo. \n" #~ "O arquivo pode conter informaçom do teu sistema, p.ex. unha lista das " #~ "canções reproduzidas recentemente. \n" #~ "Se isso nom for aceitável, envia <b>%s</b> com umha descriçom do que " #~ "estavas a fazer." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "QuodLibet pode ressultar inestável. Recomenda-se fechá-lo e reiniciá-lo.\n" #~ "Guardará-se a colecçom." #~ msgid "Unable to download lyrics." #~ msgstr "Nom se puido baixar a letra" #~ msgid "Set or toggle the playback order" #~ msgstr "Configurar ou alternar a ordem de reproduçom" #~ msgid "Uninitialized iPod" #~ msgstr "iPod sem configurar" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Desejas criar umha base de dados baleira neste iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Ganância do _volume (dB)" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combinar as etiquetas com múltiplos _valores" #~ msgid "Capacity:" #~ msgstr "Capacidade:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Nom foi possível guardar a base de dados do iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Nom foi possível guardar a base de dados do iPod" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "" #~ "Nom se puido importar a biblioteca python-gpod,\n" #~ "as capacidades de interacçom com o iPod fôrom desactivadas." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "pico de ganância da pista" #~ msgid "Shuffle" #~ msgstr "Aleatoriamente" #~ msgid "Weighted" #~ msgstr "Dinâmica" #~ msgid "_Weighted" #~ msgstr "_Dinâmica" #~ msgid "_One Song" #~ msgstr "_Umha cançom" #~ msgid "Restart the playlist when finished" #~ msgstr "Recomeçar a lista de reproduçom ao rematar" #~ msgid "Disable Browser" #~ msgstr "Desactivar o Navegador" #~ msgid "_Disable Browser" #~ msgstr "_Desactivar o Navegador" #, fuzzy #~ msgid "Force Write" #~ msgstr "Guardar" #~ msgid "Filter on _Genre" #~ msgstr "Filtrar no e_stilo" #~ msgid "Filter on _Artist" #~ msgstr "Filtrar no _artista" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrar no ál_bum" #~ msgid "_Music" #~ msgstr "_Música" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Marcadores" #~ msgid "Song _List" #~ msgstr "_Lista de canções" #, fuzzy #~ msgid "D:" #~ msgstr "A:" #, fuzzy #~ msgid "W:" #~ msgstr "A:" #, fuzzy #~ msgid "E:" #~ msgstr "E:" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "A roda do rato muda de cançom;\n" #~ "Shift e a roda do rato configura o volume" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Parar despois desta cançom" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "e %d mais..." #~ msgstr[1] "e %d mais..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Extraer o disco do _Álbum" #, fuzzy #~ msgid "Timeout" #~ msgstr "Intre" #, fuzzy #~ msgid "Select an album" #~ msgstr "Seleccionar _tudo" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s e %(count)d mais" #~ msgstr[1] "%(title)s e %(count)d mais" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Listas" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Utilizar cantos redondeados nas miniaturas" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Redondear os cantos das miniaturas das cobertas. Pode ser necessário " #~ "reiniciar para que tenha efecto." #~ msgid "Re_fresh Library" #~ msgstr "Ac_tualizar a colecçom" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Eliminar Emisora" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "O GStreamer nom tem nengum elemento para ler arquivos. Verifica as opções " #~ "de instalaçom do GStreamer." #~ msgid "Invalid audio backend" #~ msgstr "A infraestrutura de som nom é válida" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "A infraestrutura de som %r nom está instalada." #~ msgid "ql-save" #~ msgstr "Guardar" #, fuzzy #~ msgid "ql-revert" #~ msgstr "E_liminar" #~ msgid "Print all tags to stdout" #~ msgstr "Mostrar todas as etiquetas na saída estándard" #~ msgid "Load tags dumped with 'dump'" #~ msgstr "Mostrar as etiquetas que arroja o 'dump'" #~ msgid "command|filename" #~ msgstr "nome de arquivo" #~ msgid "command|tag" #~ msgstr "etiqueta" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Nom se puido achar media-player-info." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Procurar" #~ msgid "%d of %d" #~ msgstr "%d de %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Utilizaçom: %s %s" #~ msgid "_Download..." #~ msgstr "_Baixar..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nova Emisora" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Sobreescrever <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Erro na saída" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Nom se puido iniciar a saída do GStreamer. Pode ser que a saída " #~ "especificada seja inválida\n" #~ "ou que o dispositivo esteja a ser utilizado. Verifique as configurações " #~ "do reprodutor." #~ msgid "Quod Libet is already running." #~ msgstr "O Quod Libet já se está a executar." #~ msgid "No song is currently playing." #~ msgstr "Nom se está a reproduzir cançom nengumha." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Nom foi possível escrever em %s. Eliminando-o." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Editar os marcadores..." #~ msgid "_New Folder..." #~ msgstr "Novo _cartafol..." #~ msgid "_Add to Playlist" #~ msgstr "_Engadir à lista" #~ msgid "_Edit Display..." #~ msgstr "_Editar a vista..." #~ msgid "Output Log" #~ msgstr "Saída do registro" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d emisora" #~ msgid "_Order:" #~ msgstr "_Ordem:" #~ msgid "_Add a Location..." #~ msgstr "_Engadir umha localizaçom..." #~ msgid "_Output Log" #~ msgstr "_Registro" #~ msgid "Invalid command %r received." #~ msgstr "Recebeu-se o comando inválido %r." #~ msgid "Unknown browser %r." #~ msgstr "Navegador desconhecido %r." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Personalizar as cabeceiras..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #~ msgstr[1] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #~ msgstr[1] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "Cabeceiras dos _números de pista" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Cabeceiras dos _componentes" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Cabeceiras dos _álbuns" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Cabeçeiras de _data" #, fuzzy #~ msgid "File Headers" #~ msgstr "Cabeceira dos _arquivos" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Cabeceiras da _produçom" #, fuzzy #~ msgid "Tag:" #~ msgstr "E_tiqueta:" #~ msgid "Descending" #~ msgstr "Descendente" #~ msgid "Too Many Errors" #~ msgstr "Demasiados erros" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "A parar a reproduçom porque se sucedérom %d erros seguidos." #~ msgid "Warnings" #~ msgstr "Advertências" #~ msgid "No log available." #~ msgstr "Sem registros" #~ msgid "album artist (sort)" #~ msgstr "artista do álbum (ordenar)" #~ msgid "artist (sort)" #~ msgstr "artista (ordenar)" #~ msgid "album (sort)" #~ msgstr "álbum (ordenar)" #~ msgid "performer (sort)" #~ msgstr "intérprete (ordenar)" #~ msgid "performers (sort)" #~ msgstr "intérpretes (ordenar)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID do MusicBrainz do artista do album" #~ msgid "errors" #~ msgstr "erros" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Erro ao ler a capa do álbum \"%s\"" #~ msgid "Permanently delete this file?" #~ msgstr "Eliminar permanentemente este arquivo?" #~ msgid "Permanently delete these files?" #~ msgstr "Eliminar permanentemente estes arquivos?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s e %(count)d mais..." #~ msgstr[1] "%(title)s e %(count)d mais..." #, fuzzy #~ msgid "Version:" #~ msgstr "versom" #~ msgid "_Cause an Error" #~ msgstr "_Provocar um erro" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s nom se puido engadir à colecçom.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Erro ao executar o comando %r, causado por: %r." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%s</b> that will help us debug the crash. Please file a new issue at " #~ "http://code.google.com/p/quodlibet/issues /list and attach this file or " #~ "include its contents. This file may contain some identifying information " #~ "about you or your system, such as a list of recent files played. If this " #~ "is unacceptable, send <b>% s</b> instead with a description of whatyou " #~ "were doing." #~ msgstr "" #~ "Ocorreu un problema no Quod Libet. Un arquivo de depuraçom, que nos pode " #~ "ajudar a analisar o erro, foi guardado em <b>%s</b>. \n" #~ "Por favor, abre un novo tema en http://code.google.com/p/quodlibet/issues/" #~ "list e inclúi o arquivo ou o contido do mesmo. \n" #~ "O arquivo pode conter informaçom do teu sistema, p.ex. unha lista das " #~ "canções reproduzidas recentemente. \n" #~ "Se isso non é aceitável, envia <b>%s</b> com umha descriçom do que " #~ "estavas a fazer.\n" #~ "\n" #~ "O Quod Libet pode-se tornar agora inestável. Fecha-lo e executá-lo de " #~ "novo é o recomendado. A base de dados da sua coleçom guardará-se." #~ msgid "Could not import python-gpod, iPod support disabled." #~ msgstr "" #~ "Nom se puido importar a biblioteca python-gpod,\n" #~ "as capacidades de interacçom com o iPod fôrom desactivadas." #, fuzzy #~ msgid "_Output device:" #~ msgstr "Infraestrutura de _saída:" #~ msgid "Search your library" #~ msgstr "Procurar na colecçom" #~ msgid "No eject command found." #~ msgstr "Nom foi encontrado o comando para expulsar (eject)." #~ msgid "Unable to start web browser" #~ msgstr "Nom foi possível iniciar um navegador de Internet" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Nom se atopu nengum navegador de Internet. Por favor, configure a " #~ "variável $BROWSER, ou verifique que /usr/bin/navegador existe." #, fuzzy #~ msgid "Library Error" #~ msgstr "Navegador da Colecçom" #~ msgid "translator-credits" #~ msgstr "ashtophet" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Outras colunas para seren mostradas, separadas por espaços" #~ msgid "_Edit and Continue" #~ msgstr "_Editar e continuar" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #~ msgstr[1] "" #~ "Está a piques de mudar as qualificações de %d canções.\n" #~ "Deseja continuar?" #~ msgid "Confirm rating" #~ msgstr "Confirmar a qualificaçom" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Copyright 2004-2010 Joe Wreschnig, Michael Urman, et alii\n" #~ "\n" #~ "Este programa é Software Livre: aceda ao código fonte para verificar as " #~ "condições de cópia.\n" #~ "NOM HÁ garantia nemgumha; nem sequera de APTITUDE PARA O COMÉRCIO ou de " #~ "SER\n" #~ "AXEITADO PARA ALGUM PROPÓSITO PARTICULAR.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r nom contém nengum navegador." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Tamanho total:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r nom contém nengum dispositivo." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: Nom se puido importar o ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Nom se puido achar media-player-info." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: Nom se puido achar media-player-info." #~ msgid "Quod Libet Plugins" #~ msgstr "Extensões do Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Mostrar as procuras simples em azul, as avançadas em verde, e as " #~ "inválidas em vermelho" #~ msgid "Separators for splitting tags" #~ msgstr "Separadores para extraer as etiquetas" #~ msgid "Quod Libet Preferences" #~ msgstr "Preferências do Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Nom tocadas _hoje" #~ msgid "Not Played in a _Week" #~ msgstr "Nom tocadas numha _semana" #~ msgid "Not Played in a _Month" #~ msgstr "Nom tocadas num _més" #~ msgid "B_ottom 40" #~ msgstr "Ú_ltimas 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "As 40 canções que menos tocadas (podem resultar mais se houverem canções " #~ "reproduzidas o mesmo número de vezes)" #~ msgid "gtk-media-next" #~ msgstr "_Seguinte" #~ msgid "gtk-media-previous" #~ msgstr "_Anterior" #~ msgid "gtk-media-play" #~ msgstr "_Reproduzir" #~ msgid "gtk-media-pause" #~ msgstr "_Parar" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #~ msgid "Date" #~ msgstr "Data" #~ msgid "Add" #~ msgstr "Engadir" #~ msgid "Bitrate" #~ msgstr "Taxa de bits" #~ msgid "_Stations..." #~ msgstr "_Emisoras..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "A activar a infraestrutura de som (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "A carregar a colecçom principal (%s)" #~ msgid "Unable to save library" #~ msgstr "Nom foi possível guardar a colecçom" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Impossível reproduzir a cançom" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "A saída de áudio %r non puido ser criada. Verifica as configurações do " #~ "GStreamer em ~/.quodlibet/config." #~ msgid "Sort by title" #~ msgstr "Ordenar polo título" #~ msgid "Sort by artist" #~ msgstr "Ordenar polo artista" #~ msgid "Lyrics provided by %s." #~ msgstr "Letra fornecida por %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Nom se atopou a letra.\n" #~ "\n" #~ "Pode premer em Baixar para que o QL as procure em Internet. Tamém pode " #~ "introduzi-la voçê e guardá-la" #~ msgid "_LastFM webservice URL: http://" #~ msgstr "URL do serviço web do _LastFM: http://" #~ msgid "The main url for lastfm webservices. Must end in a trailing /" #~ msgstr "A url principal para os serviços web do lastfm. Deve rematar em /" #~ msgid "LastFM _similar artist webservice: " #~ msgstr "Serviço web de artista _similar do LastFM:" #~ msgid "" #~ "Enter here the xml webservice lookup that gets appended to the main " #~ "service url" #~ msgstr "" #~ "Indroduz o enderezo do ficheiro xml que complementa a url do serviço " #~ "principal" #~ msgid "LastFM top _tracks webservice: " #~ msgstr "Canções mais _tocadas do serviço LastFM:" #~ msgid "LastFM top _albums webservice: " #~ msgstr "_Albums mais tocados do serviço LastFM:" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d canções guardadas" #~ msgid "part" #~ msgstr "Movimento" #~ msgid "Opening audio device." #~ msgstr "A aceder ao dispositivo de áudio." #~ msgid "MusicBrainz album ID" #~ msgstr "ID de MusicBrainz do álbum" #~ msgid "Loaded song library." #~ msgstr "A colecçom musical foi carregada." #~ msgid "Unable to open audio device" #~ msgstr "Impossível aceder ao dispositivo de som" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "O Quod Libet tentou aceder aos controladores 'autosink' e '%(sink)s' mais " #~ "nom puido abrir nengum deles. Configure o plugin do GStreamer mudando a\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "linha anterior em ~/.quodlibet/config" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "O Quod Libet nom puido atopar o elemento do GStreamer 'filesrc'. Comprove-" #~ "se a instalaçom do GStreamer." #~ msgid "Unable to retag multiple values" #~ msgstr "Impossível modificar distintos valores da etiqueta" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "" #~ "Mudar o nome dumha etiqueta com múltiplos valores non está suportado" #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s nom é umha cançom da colecçom do QL." #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Ajuste de volume por-cançom (\"Radio\")" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Ajuste de volume por-album (\"Audiophile\")" #~ msgid "_Volume Normalization" #~ msgstr "Normalizaçom do _Volume" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "A examinar a sua colecçom. Pode levar vários minutos.\n" #~ "\n" #~ "%d canções recarregadas\n" #~ "%d canções eliminadas" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "A procurar novas canções e a engadi-las à colecçom.\n" #~ "\n" #~ "%d canções engadidas" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "Nom podem ser carregadas listas M3U" #~ msgid "This station is already in your library." #~ msgstr "Esta emisora já está na sua colecçom" #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "por <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disco <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "" #~ "A colecçom nom pode ser actualizada no entanto o QL está a ser executado." #~ msgid "Loading, scanning, and saving your library." #~ msgstr "A carregar, a examinar e a guardar a sua colecçom." #~ msgid "Rescan your library and exit" #~ msgstr "Actualiza a sua colecçom" #~ msgid "Old Plugins" #~ msgstr "Extensões antigas" #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "Semelha que está a executar, assemade, o Quod Libet. Se editar as tags " #~ "das canções na colecçom do QL no entanto estiver a ser executado, " #~ "cumprirá que as engada ou actualize a colecçom.\n" #~ "\n" #~ "Se nom estiver a executar QL, ou estiver a editar as tags além da sua " #~ "colecçom, pode ignorar esta advertência." #~ msgid "GStreamer status %r != %r" #~ msgstr "Estado do GStreamer %r != %r" #~ msgid "_Pane %d:" #~ msgstr "_Panel %d:" #~ msgid "Double-click a tag value to change it, right-click for other options" #~ msgstr "" #~ "Duplo-clic num valor da tag para mudá-lo, clic-direito para outras opções" #~ msgid "Add a new tag" #~ msgstr "Engadir umha nova tag" #~ msgid "The first letter of each word will be capitalized" #~ msgstr "A primeira letra de cada palavra será posta em maiúsculas" #~ msgid "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgstr "" #~ "Os caracteres nom permitidos nos nomes de ficheiro de WindowsTM (\\:?;" #~ "\"<>|) serám reemprazados por barras baixas" #~ msgid "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgstr "" #~ "Os caracteres além do conjunto ASCII (A-Z, a-z, 0-9, e pontuaçom) serám " #~ "reemprazados com barras baixas" #~ msgid "Apply to these _files..." #~ msgstr "Aplicar a estes _ficheiros..." #~ msgid "Path" #~ msgstr "Endereço" #~ msgid "Tray Preferences - Quod Libet" #~ msgstr "Preferências da icona - Quod Libet" #~ msgid "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgstr "E: Necesita GTK+ 2.6 e PyGTK 2.6 (ou versões máis novas)." #~ msgid "E: You have GTK+ %s and PyGTK %s." #~ msgstr "E: Tem GTK+ %s e PyGTK %s." #~ msgid "E: Please upgrade GTK+/PyGTK." #~ msgstr "E: Por favor, actualize GTK+/PyGTK." #~ msgid "Set play order" #~ msgstr "Estabelecer a ordem de reproduçom" #~ msgid "" #~ "Deleting <b>%s</b> failed. Possibly the target file does not exist, or " #~ "you do not have permission to delete it." #~ msgstr "" #~ "A eliminaçom de <b>%s</b> errou. Possivelmente o ficheiro nom existe, ou " #~ "vostede nom tem permissões para eliminá-lo." #~ msgid "%(different)s, %(missing)s" #~ msgstr "%(different)s, %(missing)s" #~ msgid "Play songs in random order" #~ msgstr "Reproduz as canções em ordem aleatória" #~ msgid "S_ong" #~ msgstr "Canç_om" #~ msgid "_Choose randomly" #~ msgstr "_Escolher aleatoriamente" #~ msgid "Drag songs here to add them to the play queue" #~ msgstr "Arrastar canções para engadir" #~ msgid "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgstr "" #~ "Quod Libet nom puido aceder ao seu dispositivo de áudio. Às vezes isto " #~ "sucede quando outro programa o está a empregar, ou os drivers nom estám " #~ "configurados.\n" #~ "\n" #~ "Quod Libet fechará agora." �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/he.po����������������������������������������������������������������������������0000644�0001750�0001750�00000735616�14436352625�013611� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Hebrew translation of QuodLibet. # Copyright (C) 2005 THE QuodLibet'S COPYRIGHT HOLDER # This file is distributed under the same license as the QuodLibet package. # # msgid "" msgstr "" "Project-Id-Version: Quod Libet 4.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2019-10-28 13:13+0200\n" "Last-Translator: Avi Markovitz <avi.markovitz@gmail.com>\n" "Language-Team: Hebrew\n" "Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 2.2.1\n" "X-Poedit-Basepath: ../../../git/quodlibet/quodlibet\n" "X-Poedit-SearchPath-0: .\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_כותרת" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "יוצרים" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_תאריך" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "כותרות ת_אריך" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_תאריך מקורי" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_סוגה" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_דרוג" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_מספר השמעות" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "מיון _לפי…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_העדפות" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "רשימת אלבומים" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_רשימת אלבומים" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "כל האלבומים" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d אלבום" msgstr[1] "%d אלבומים" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "טעינה חוזרת של עטיפת _אלבום" msgstr[1] "טעינה חוזרת של עטיפות _אלבומים" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "שירים ללא אלבום" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d רצועה" msgstr[1] "%d רצועות" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d תקליטור" msgstr[1] "%d תקליטורים" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "אלבום דוגמה" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "מאפייני רשימת אלבומים" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "הצגת עטיפות _אלבום" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_חיפוש שורה כולל אנשים" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "אפשרויות" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "מַצָּג אלבום" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_סגירה" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "דפדפן ספריה" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "שיר %d" msgstr[1] "%d שירים" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "דפוס שגוי" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "אוסף אלבומים" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "אוסף _אלבומים" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "%s לא ידוע" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "ערכי %s מרובים" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_מותאם אישית" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_הוספה" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_הסרה" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "תג" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "מיזוג" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "מאפייני אוסף אלבומים" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_החלה" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_ביטול" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "שבכת תמונות עטיפה" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_שבכת תמונות עטיפה" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "מאפייני שבכת תמונות עטיפה" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "הצגת _מלל אלבום" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "הצגת כל האלבומים" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "מצב רחב" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "הגדלת תמונת עטיפה" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "מערכת קבצים" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_מערכת קבצים" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "לא ניתן להעתיק את השיר" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "לא ניתן להעתיק את הקבצים שנבחרו לרשימת השמעה אחרת או לתור." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_הוספה לספריה" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "רשימות תחנות יכולות להכיל רק תחנות ולא רשימת תחנות אחרת או רשימת השמעה. " "הנתיבים הבאים אינם יכולים להיטען: /n%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "רדיו מרשתת" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "כל התחנות" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "מוריד רשימת תחנות" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "תחנה חדשה" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "הזנת הכתובת של תחנת רדיו מרשתת:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "אלקטרוני" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "היפ הופ /ראפ" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "אולדיז" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "יפנית" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "הודית" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "דתי" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "רשימות" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "תורכית" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "רגאיי / אולם ריקודים" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "לטינית" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "רדיו מכללות" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "שיח / חדשות" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "אמביינט" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "ג'ז" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "קלסי" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "פופ" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "אלטרנטיב" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "מטאל" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "קאונטרי" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "חדשות" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "שלאגר" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "פונק" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "אינדי" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "בלוז" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "נשמה" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "לאונג'" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "פאנק" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "רגאטון" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "סלבי" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "יווני" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "גותי" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "רוק" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "האם לטעון רשימת תחנות רדיו פופולריות?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_טעינת תחנות" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "רדיו _מרשתת" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "כל התחנות" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "מועדפים" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "ללא קטגוריה" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_תחנה חדשה…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_עדכון תחנות" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "לא נמצאו תחנות" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "לא נמצאו תחנות רדיו מרשתת ב %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "כל התחנות שברשימה נמצאות כבר בספריה." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "הוספה למועדפים" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "הסרה ממועדפים" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d תחנה" msgstr[1] "%(count)d תחנות" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "חלוניות דפדפן" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_דפדפן חלוניות" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "בחירת _הכל" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "לא ידוע" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "הכל" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "קטן" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "רחב" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "עמודות" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "דפוס תיוג עם סימון אופציונלי כמו <tt>composer</tt> או\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "העדפות חלוניות דפדפן" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "פריסת עמודה" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "תוכן עמודה" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "רוחב חלונית שווה" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "רשימות השמעה" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_רשימות השמעה" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_הסרה מרשימת השמעה" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_חדש" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_יבוא" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "לא ניתן לייבא את רשימת ההשמעה" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "קְווֹדְלִיבֵּט יכולה לייבא רק רשימות השמעה בתבנית M3U או PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_מחיקה" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_שנוי שם" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "לא ניתן לשנות שם רשימת ההשמעה" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "ייבא רשימת השמעה" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_יבוא" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_רשימת השמעה חדשה…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "מה לעשות עם השיר %d?" msgstr[1] "מה לעשות עם השירים %d?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "אישור פעולה לרשימת השמעה \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "לרוקן" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "רשימת השמעה לדוגמה" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "מאפייני דפדפן רשימת השמעה" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "מַצָּג רשימות השמעה" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "האם למחוק רשימת השמעה '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "כל המידע לגבי רשימת ההשמעה שנבחרה ימחק ולא יהיה בר שחזור." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "רצועה" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "רשימת השמעה חדשה" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "הזנת שם חדש לרשימת ההשמעה:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "מייבא רשימת השמעה\n" "%(current)d/%(total)d שירים נוספו." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "ערוץ חדש" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "הזנת מיקום ערוץ שמע:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_הוספת קובץ…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_רענון" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "לא ניתן להוסיף את הערוץ המבוקש" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "לא ניתן להוסיף את %s. ייתכן שהשרת מושבת, או שהמיקום אינו הזנת שמע." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "רכיב השרת הנוכחי אינו תומך ב URL, דפדפן הזנות שמע נוטרל." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_הגבלת תוצאות" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_אפשור שאילתות מרובות" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "רשימת רצועות" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "רשימת רצועות" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "סאונד_קלאוד" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "דפדפן סאונדקלאוד" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "סאונד_קלאוד" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "חיפוש" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "הרצועות שלי" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "מעבר ל %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "מחובר" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "קְווֹדְלִיבֵּט מחוברת כעת, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "התנתקות מ %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "הזנת קוד…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "התחברות ל %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "אימות סאונדקלאוד" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "הזנת קוד אימות סאונדקלאוד:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "קְווֹדְלִיבֵּט אינה פועלת (הוספת '--run' לאתחול)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "ספרית מוזיקה ונגן" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[אפשרות]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "הדפסת השיר המושמע ויציאה" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "השמעה מיידית" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "לא להציג כל חלון בהפעלה" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "מעבר לשיר הבא" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "מעבר לשיר הקודם או השמעה מבראשית במידה וסמוך לתחילת השיר" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "מעבר לשיר הקודם" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "התחלת השמעה" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "השהיית השמעה" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "החלפה בין מצב השמעה/השהייה" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "עצירת השמעה" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "הגברת עצמה" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "הנמכת עצמה" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "הוספת כוכב אחד לדרוג השיר המושמע" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "הסרת כוכב אחד מדרוג השיר המושמע" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "הדפסת מצב נגן" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "הסתרת חלון ראשי" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "הצגת חלון ראשי" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "החלפת מצג חלון ראשי" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "מיקוד על הנגן שבשימוש כעת" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "הסרת מסנן דפדפן פעיל" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "רענון ספרית שירים" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "רשימת דפדפנים זמינים" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "הדפסת רשימת הדמעה נוכחית" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "הדפסת תוכן תור ההשמעה" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "הדפסת מלל שאילתה נוכחית" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "הפעלה ללא מתקעים" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "אתחול קְווֹדְלִיבֵּט במידה ואינה פועלת" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "יציאה מקְווֹדְלִיבֵּט" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "הזחה בתוך השיר המתנגן" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "הגדרת או החלפת מצב אקראי" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "הגדרת סוג מצב אקראי" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "כיבוי, הפעלת, או החלפת מצב חזרה" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "הגדרת סוג מצב חזרה" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "קביעת העוצמה" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "חיפוש בספרית השמע" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "שאילתה" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "השמעת קובץ" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "שם קובץ" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "דרוג השיר המתנגן" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "קביעת הדפדפן הנוכחי" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "עצירה לאחר השיר המושמע" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "פתיחת דפדפן חדש" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "הצגת או הסתרת התור" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "סינון לפי ערך אקראי" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "תג" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "סינון לפי ערך תג" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "תג=ערך" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "הוספת קובץ או שאילתה לתור" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "הוספת קבצים לתור, מופרדים בפסיק" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "שם קובץ" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "הדפסת שמות קבצים של תוצאות שאילתה ל- stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "הסרת קובץ או שאילתה מהתור" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "הוספת קובץ או מחיצה לספריה" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "מיקום" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "דפוס" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "ערך לא תקין עבור '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "נסו %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "ארעה שגיאה" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "ניתן להתעלם משגיאה זו, אבל, היישום עשוי לא להיות יציב עד להפעלתו המחודשת. " "שיגור דוח שגיאות אורכת מספר שניות ותסייע לנו רבות." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "שיגור דוח שגיאה" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "להתעלם מהשגיאה" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "פרטי שגיאה:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "פרטים שונים הנוגעים למערכת ולהודעת השגיאה ישלחו לשרות מקוון של צד ג' (<a " "href='https://www.sentry.io'>www.sentry.io</a>). ניתן לצפות במטה נתונים טרם " "שליחתם." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(אופציונלי) תיאור קצר של מה שארע בעת התרחשות השגיאה:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_שליחה" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "תיאור מקוצר…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "מועד שליחה:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "עורך תגי שמע" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "מחיצה" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "עורך ערכי מטה-דטה שמע" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL מקור תמונות עטיפה" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "הורדת תמונות עטיפה באמצעות הקישור בתג artwork_url. עובד עם דפדפן סאונדקלאוד." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "מקור תמונות עטיפה דיסקוגז" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "הורדת תמונות עטיפה מ דיסקוגז." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "מקור עטיפות Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "הורדת תמונות עטיפה מארכיב תמונות Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "מקור תמונות עטיפה מוזיקבריינז" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "הורדת תמונות עטיפה מארכיב תמונות מוזיקבריינז." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "המרת קידוד" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "מתקן ערכי תג בלתי מובנים בעורך התגים." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_המרת קידוד…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "ממיר Kana/Kanji פשוט" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "ממיר Kana/Kanji ל romaji לפני שינוי שם." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "המרת מלל _יפני לאותיות לטיניות" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "לא נמצא ממיר 'Kanji Kana' פשוט kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "שיחלוף ביטוי רגיל" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "מאפשר החלפת ביטויים רגילים (regex) שרירותיים (s///) בעת תיוג או שינוי שמות " "קבצים." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "אותיות רישיות" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "ערכי תגי אותיות רישיות בעורך התגים." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "ערך _אותיות רישיות" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "אפשור _רישיות לכל בתגים" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_אותיות רישיות ידי אדם" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "שימוש בכללים מקובלים של השפה האנגלית לאותיות רישיות, כמו ה \"Dark Night of " "the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "העדפות מתקדמות" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "אפשור עריכת תצורה מתקדמות." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "תסמכו עלי, אני בשליטה" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "מַצָּג צג מאויר" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "הצגת מידע אודות השיר על הצג כאשר השיר מתחלף." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_מיקום:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_גודל תמונת עטיפה:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "מַצָּג" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_גופן:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "שמאל" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "מרכז" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "ימין" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_יישור מלל:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "מלל" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_מלל:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_מילוי:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "צבעים" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_צללים" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_מתאר" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "פינו_ת מעוגלות" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_השהיה:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "פַּעֲלוּלִים" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "ער_יכת דפוס מַצָּג…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "תצוגה מקדימה" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "מידע יישומון" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "מידע אודות היישום וסביבת העבודה." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "תבניות נתמכות" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "מחיצת תְּצוּרָה" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "מחיצת מטמון" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "רכיב שרת שמע" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "הסגה לברירת מחדל" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "לא ניתן להתחבר לשרות '%s'." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "עדכון ערכי התגים בקבצים" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "עדכון תגים שהשתנו בקבצים. פעולה זו תבטיח עדכניות מונה השמעות ודרוג." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "שמירת דֵּרוּג ומספר _השמעות בתגים" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "הוקלט" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "אירעה שגיאה במהלך הסנכרון" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_עדכון תחנות" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "העדפות" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "מסוך אוטומטי" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "ממסך ומבטל מיסוך אוטומטי לכוננים כאשר הם מועלים או מורדים." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "דֵּרוּג אוטומטי" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "דרוג שירים אוטומטית במהלך השמעתם או דלוגום. המתקע משתמש באלוגריטם 'האצה' מאת " "vox שנכתב על ידי בריאן נלסון." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "מסד הנתונים של בנשי שצוין פגום או חסר" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "יבוא כשל" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "דרוג וסטטיסטיקה יובא בהצלחה עבור %d שיר" msgstr[1] "דרוג וסטטיסטיקה יובאו בהצלחה עבור %d שירים" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "יבוא בנשי" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "יבוא דרוג וסטטיסטיקת השמעות מבנשי." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_נתיב מסד נתונים:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "יבוא" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "שעון מעורר" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "להתעורר לצלילי מוזיקה קולנית." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "לולובאיי" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "עמעום והשהיית מוזיקה." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "מצב הודעות Gajim" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "מצב הודעות Gajim" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "שינוי מצב הודעות Gajim בהתאם למוזיקה המושמעת." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "מושהה:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "מלל מצב" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "מלל מצב" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "שטוח" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "חי" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "באס וטרבל מלא" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "מועדון" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "אולם גדול" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "מסיבה" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "רך" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "באס מלא" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "רגאיי" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "אוזניות" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "רוק רך" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "טרבל מלא" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "דאנס" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "טכנו" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "מחשב נייד" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "שוין" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "שליטה בטון המוזיקה בעזרת שויין.\n" "השויין ניתן לתיצור על ידי הקשה או שימוש במקלדת (הקשה ימנית תאפס את הרצועה)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "השרת הנוכחי אינו תומך בשויון ניחות." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "הגדרות מראש ברירת מחדל" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "בחירה…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_איפוס שויין" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "הגדרות מראש מותאמות אישית" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_מחיקת בחירה" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "שם הגדרה מראש לשמירה:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_שמירה" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "מקוון" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "לא מקוון" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "צ'אט" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "לא נוכח" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "מוסתר" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "מצב הודעות Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "שינוי מצב הודעות Gajim בהתאם למוזיקה המושמעת." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "מושהה" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "דפוס:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "רשימת חשבונות, מופרדים ברווח, לשינוי מצב הודעות. אם לא הוגדרו חשבונות, מצב " "ההודעות ישתנה בכל החשבונות." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "חשבונות:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "הוספה '[מושהה]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "אם סומן, '[משהה]' יתווסף למצב הודעה בזמן השהיה" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "המצבים בהם ההודעה תשתנה" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "השהייה עם ניתוק אוזניות" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "השהיה בזמן ניתוק אזניות וביטול השהיה עם חיבורן מחדש." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "עיכוב שומר צג" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "מוזיקה מושמעת" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "מצב" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "עיכוב שומר צג" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "עיכוב שומר צג" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "רישומי יומן רדיו מרשתת" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "תיעוד עשרת השירים האחרונים שהושמעו בתחנות הרדיו, שיוצגו כרשימה בתפריט תכולת " "הזחה." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "יצירת קובץ פלט מנגינה למשתמש ג'אבר ל ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "החלפת שפה" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "החלפת שפה בממשק משתמש." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "ברירת מחדל מערכת" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "נדרש אתחול על מנת שהשינויים ייכנסו לתוקף" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "שרת מדיה UPnP AV" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "חשיפת כל האלבומים לשרת מדיה Rygel UPnP ממשק MediaServer2 D-Bus." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "נא לוודא שהמשפט הבא כלול בקובץ התצורה(~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "שרת MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "מאפשר שלט רחוק של קְווֹדְלִיבֵּט תוך שימוש בלקוח MPD. הזרמה, רשימת השמעה וניהול " "ספריה אינם נתמכים." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_פתחה:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_IP מקומי:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "ס_סמה:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "חיבור" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "לקוחות שנבדקו" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "תמיכת MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "הסתרת חלון ראשי בסגירה" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "מתקבלים דפוסי קוודליבט, כלומר %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "מפרסם MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "פרסום מצב הודעות לנושא MQTT." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "שם מתוך מארח" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "שם מתוך מארח /IP (ברירת מחדל למחשב מקומי)" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "פִּתְחָת מתוך" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "פִּתְחָת מתוך (ברירת מחדל 1883)" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "שם מתוך מארח" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "פִּתְחָת מתוך" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "נושא" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "דפוס השמעה" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "מלל מצב בעת השמעת שיר." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "דפוס מושהה" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "מלל בעת השהיית שיר." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "אין מלל שיר" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "מלל פשוט כשלא מושמע שיר" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "תצור MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "מלל מצב" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "חיבור למתוך %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "לא ניתן להתחבר למתווך %(host)s:%(port)d (%(msg)s" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "שגיאת חיבור" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "חיפוש מוזיקבריינז" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "אפשרות להגדרת דרוג שיר בשימוש במספרים." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "שם _משתש:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_ססמה:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "חשבון" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "מלל התראה" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_כותרת:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "הסגה לדפוס ברירת מחדל" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_גוף:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_הצגת הודעות" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "הצגת התראות" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "שיר מתחלף רק בשינוי <i>_ידני</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "שיר מתחלף רק בשינוי <i>_אוטומטי</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "שיר מתחלף ב <i>_הכל</i>" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "רק כאשר החלון הראשי אינו _במוקד" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "הצגת לחצן \"_הבא\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "שגיאת התחברות" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "לא ניתן להתחבר לשרת ההתראות." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "התראות שירים" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "הצגת התראה כאשר השיר מתחלף." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "הבא" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "התראות שירים" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "נא להגדיר את QLScrobbler בחלון המתקעים. עד אז השירים לא ישוגרו." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "לא ניתן להתחבר לשרות '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "ההזדהות כשלה: URL שגוי." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "ההזדהות כשלה: שם משתמש '%s' או הססמה שגויים." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "חשבון לקוח מוחרם. נא ליצור קשר אם המחבר." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "שעון מערכת שגוי. השגור עשוי להכשל עד שיתוקן." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "הגשת אודיוסקרובלר" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "לקוח אודיוסקרובלר עבור Last.fm ושרותי אודיוסקרובלר אחרים." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "ההזדהות צלחה." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_שרות:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "אחר…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_אימות נתוני חשבון" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_דפוס אמן:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_דפוס שם קובץ:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_מסנן החרגה:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "הדפוס משמש תִּיבְנוּת שם האמן לשגור. להשאיר ריק לברירת המחדל." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "הדפוס משמש לתִּיבְנוּת כותרת לשגור. להשאיר ריק לברירת המחדל." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "שירים התואמים למסנן זה לא ישוגרו" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_מצב לא מקוון (לא לשגר דבר)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "שגור" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "השתקת פרסומות רדיו" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "השתקת פלט כאשר מושמעות פרסומות רדיו.\n" "תחנות: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "השמעת אלבום אקראי" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "הפעלת אלבום אקראי כאשר רשימת ההשמעה מגיעה לסיומה. נדרש שהדפדפן הפעיל יתמוך " "בסינון לפי אלבום." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "דרוג גבוהה" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "הושמעו בתכיפות" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "דולגו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "הושמעו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "התחלו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "נוספו לאחרונה" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "אלבומים ארוכים יותר" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "שניות לפני תחילת השמעת האלבום הבא" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "משקולות" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "השמעת אלבומים מסוימים יותר מאחרים" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "להמנע" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "העדפה" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "אלבום אקראי" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "בהמתנה ל %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "דרוג וסטטיסטיקה יובאו בהצלחה עבור %d שירים" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "יבוא ריטמבוקס" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "יבוא דרוג וסטטיסטיקת השמעות מ ריטמבוקס." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "השהיית שומר צג" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "השהיית השמעה כאשר שומר צג של גנום פעיל." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "לא מותקנת מעטפת ספק חיפוש גנום עבור קְווֹדְלִיבֵּט." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "ספק חיפוש גנום" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "מתן אפשרות למעטפת גנום לבצע חיפוש בספריה." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "סרגל הזחה חלופי" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "סרגל הזחה חלופי המוצג תמיד ומשתרע על פני כל רוחב החלוון." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "סימניות נקודת הזחה" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "אחסון נקודת הזחה א ו / או ב עבור רצועות. דלוג אל זמן א והפסיק לאחר זמן ב " "כאשר הרצועה מושמעת.\n" "לתשומת לב, שינוי שמות הנקודות שלהלן אינו מעדכן את שמות הסימניות בפועל, אלא " "רק משנה אילו שמות סימניה המתקע מחפש בזמן הזחה." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "שם סימניה לנקודה א" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "שם הסימניות לבדיקה עם החתלת השמעת הרצועה, ואם נמצא נגן, תתבצע הזחה עד לחותמת " "הזמן" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "שם סימניה לנקודה ב" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "שם הסימניה, במידה וקיימת, בה יעשה שימוש בכל רגע במהלך השמעת הרצועה. אם " "המיקום הנוכחי עולה על חותמת הזמן, תתבצע הזחה לסוף הרצועה." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "סנכרון סקוויזבוקס" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "הפיכת פלט לוג'טק סקוויזבוקס לתמונת מראה של קְווֹדְלִיבֵּט, בתנאי ששניהם קוראים " "מספריה זהה." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "אירעה שגיאה במציאת שרת סקוויזבוקס" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "אירעה שגיאה במציאת %s. נא לבדוק הגדרות" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "אפשרויות" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "קידוד" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "הוקלט" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_מחיקה" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_מחיקה" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "דולגו יותר לאחרונה" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "תיקית יעד:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "דפוס נתיב" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "עריכת דפוסים שמורים…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_דפוס אמן:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "תצוגה מקדימה" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "מצב" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "מקורות" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "יצוא מטה-דטה" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "חברת הקלטות" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "יעד לשמירה" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "הנתיב אינו מלא" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "הדפוס\n" "\t<b>%s</b>\n" "מכיל / אך אינה מתחיל מספרית השורש. על מנת למנוע שמות תיקיה שגויים על הדפוס " "להתחיל מ / או מ /~." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "לא נבחרו שירים." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "לא נבחרו שירים." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "לא ניתן לשמור שיר" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "דולגו יותר לאחרונה" msgstr[1] "דולגו יותר לאחרונה" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "טעינת קובץ כשלה: %r" msgstr[1] "טעינת קובץ כשלה: %r" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "הצגת תַּמְלִיל מסונכרן בעל שם זהה לשם הרצועה מקובץ .lrc." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "מלל:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "רקע:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "גופן" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "גודל (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "הודעות מצב טלהפאטי" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "עדכון כל החשבונות המבוססים על טלהפאטי IM (כפי שתוצר ב אמפאטי וכו') בהודעות " "מצב המבוססות על השיר הנוכחי." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "מושמע:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "מלל מצב בעת השמעת שיר. תומך בדפוסי QL לדוגמה %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "מושהה:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "מלל מצב בעת השהיית שיר. תומך בדפוסי QL לדוגמה %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "מלל פשוט כשלא מושמע שיר" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "אין שיר:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "דפוסי מצב" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "מחליף ערכת נושא" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "שינוי ערכת הנושא הפעילה של GTK+." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_ערכת נושא:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "ערכת נושא ברירת מחדל" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "העדפת גרסת ערכת נושא כהה" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "דֵּרוּג אגודל" #: quodlibet/ext/events/thumbrating.py:90 #, fuzzy msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "הוספת שיטת הערכה של בוהן מעלה/מטה שיומרו לערך דרוג. שמושי לסכימת תוצאות " "הצבעה ומיון לפי '~#score'." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "החלפת סרגל תפריט" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "החלפת סרגל התפריט על ידה לחיצה על מקש ה Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "לא מנגן" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "צלמית מגש המערכת" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "שליטה בקְווֹדְלִיבֵּט ממגש המערכת." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_הצגת %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_השמעה" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "ה_שהיה" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "הקו_דם" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_הבא" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_אקראי" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_חזרה" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "עצירה _לאחר השיר הנוכחי" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "פתיחת _דפדפן" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "עריכת _תגים" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_מידע" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "רשימות _השמעה" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_יצאה" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "התנהגות" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "גלגל הגלילה מכוונן עצמה" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "גלגל הגלילה מחליף שיר" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "גלגל _הגלילה" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "מַצָּג בלון" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "מצג תַּמְלִיל" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "תצוגת תג או תַּמְלִיל מבוסס קובץ אוטומטית בחלון צד." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "לא נמצא תַּמְלִיל עבור\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "אין שיר פעיל" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "השקת הדמיות" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "השקת הדמיות חיצוניות." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "לא ניתן להריץ הדמיות המשתמשות ב '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "שגיאה" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "בָּצִיעַ מדמה:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "טעינה מחודשת" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "סרגל הזחה בצורת גל" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "סרגל הזחה בתצורת גל של השיר המושמע." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "עֲקִיפָת צבע קִדְמָה:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "עֲקִיפָת צבע רחוף:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "עֲקִיפָת צבע נותר:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "הצגת מיקום נוכחי" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "הצגת תוויות זמן" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "משך הזחה בעת גלילה (מילי-שניות):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "שמירת תמונה" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "שמירת תמונת העטיפה של השיר הנוכחי לקובץ." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "קובץ:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_סף:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "סף שפעול המסנן" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "י_חס:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "יחס דחיסה" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "דוחס שמע" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "שינוי המִשְׂרַעַת של כל הדגימות מעל סף מסוים ביחס מסוים." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_מוגדר מראש:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "מסנן מוגדר מראש" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_קיצוץ תדר:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "קיצוץ תדר מסנן מעבר נמוך" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "_רמת הזנה:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "רמת הזנה" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "ברירת מחדל" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "הצבה קרובה ביותר לרמקול מדומה (30°, 3 מטר)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "צ'ו מוי" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "סגירת הצלבת ערוצים של Chu Moy (עממי)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "יאן מאיר" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "קרוב למגברי CORDA של ז'אן מאיר (שונה במקצת)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "מותאם אישית" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "הגדרות מותאמות אישית" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "הצלבת ערוצים" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "ערבול הערוץ השמאלי והימני באופן המדמה הגדרת רמקול בעת שימוש באזניות, או " "דימוי הקלטות סטריאו מוקדמות." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "סינון לפי _הרכב:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "פס התדר של המסנן" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "רוחב _מסנן:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "רוחב פס התדר של המסנן" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_רמה:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "רמת פעלול" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "קאראוקי" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "הסרת קול ראשי מהשמע." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "ערבול למונו" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "ערבול ערוצים למונו." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "ד_רוג:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_קצב:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_שיא:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "שיא / מהירות שמע" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "שולט על גובה הצליל של זרם שמע." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "יצוא רשימת השמעה לתקיה" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_יצוא" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "תיקית יעד:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "דפוס שם קובץ:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "יצוא רשימת שמע תוך העתקת קבצים לתיקיה." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "לא ניתן לייצא רשימת ההשמעה" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "נא לוודא כי קימות הרשאות כתיבה ליעד." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "דפוס שם קובץ ברירת מחדל:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_אוקיי" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "יצוא כרשימת השמעה" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "יצוא רשימת שמע תוך העתקת קבצים לתיקיה." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "אירעה שגיאה במציאת שרת סקוויזבוקס" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "אירעה שגיאה במציאת %s. נא לבדוק הגדרות" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "יצוא לסקוויזבוקס" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "יצוא דִּינָמִי של רשימת השמעה לרשימת השמעה לוג'יטק סקוויזבוקס, בהנתן ששניהם " "שותפים לאותה מחיצה. תצור שיתוף באמצעות <a href=\"quodlibet:///prefs/plugins/" "Squeezebox Output\">Squeezebox Sync plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "יצוא רשימת השמעה לסקוויזבוקס" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "שם רשימת שמע (ידרוס שם קיים)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "יצוא רשימת השמעה לסקוויזבוקס" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "הסרת כפולים מרשימת ההשמעה" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "הסרת רשומות כפולות מרשימת ההשמעה." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "האם להסיר %d שיר כפול?" msgstr[1] "האם להסיר %d שירים כפולים?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "השירים הכפולים יוסרו מרשימת השמעה '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "רשימת השמעה אקראית" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "השמעת שירים אקראית ברשימת השמעה." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "עקיבה אחר הסמן" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "השמעה עוקבת אחרי הבחירה או השיר הבא ברשימה עם סיום הנוכחי." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "עקיבה אחר הסמן" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "עקיבה אחר הסמן" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "שוין מספר השמעות" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "אקראי, העדפת שירים בעלי סך כל השמעות מעטות יותר." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "העדפת שירים שהושמעו פחות" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "העדפת שירים שהושמעו פחות" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "תור בלבד" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "הגבלת השמעת שיר לתור. בחירה בסדר השמעה זה מהחלון הראשי, הקשה כפולה על שיר " "כלשהו, יצרף אותו לתור במקום להשמיעו." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "תור בלבד" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "תור בלבד" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "הסגה" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "היפוך סדר השמעה של השירים." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "הסגה" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "אקראי לפי קיבוץ" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "השמעה אקראית תוך קיבוץ שירים בעלי תג קיבוץ משותף במקום רצועה, בדומה להשמעה " "אקראית של אלבום. שימושי בעיקר בהשמעה אקראית של יצירות קלאסיות בעלות מקטעים " "מרובים תוך הקפדה שכל מקטע יושמע לפני שיתבצע דִּלּוּג אקראי לחלק הבא." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "אקראי לפי קיבוץ" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "אקראי לפי קיבוץ" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "המתנה להתחלת קבוצה חדשה…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "תג קיבוץ:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "תג קיבוץ שירים" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "תג סינון:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "קיבוץ מיושם רק אם תג המסנן מוגדר.\n" "שיר עם תג מסנן לא מוגדר יטופל כקבוצה\n" "המורכבת מעצמה בלבד. בדרך כלל את המסנן\n" "אמור להתאים או להתאים באופן חלקי לתג הקיבוץ." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "השהיה:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "השהיה של שניות לפני תחילת השמעת הקבוצה הבאה" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "איפוס לברירת מחדל" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "חזרה על כל רצועה" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "השמעה אקראית של שירים, עם חזרה על כל רצועה מספר מוגדר של פעמים." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "חזרה על כל רצועה" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "חזרה על כל רצועה" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "מספר הפעמים להשמעת כל שיר:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "שאילתה מותנית" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "בחירת שאילתה כך שתתאים לשאילתת תנאי. התחביר הוא '@(if: condition, then, " "else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "שאילתה חסרה" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "התאמת שירים ללא התג הנתון." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "כולל תגים ריקים" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "שאילתת פייטון" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "ביטוי תג" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "שימוש בביטוי פייטון בשאילתות. התחביר הוא '@ (python: expression)'. המשתנה " "'(או' a ') הוא שיר / אלבום המותאם. '_ts' הוא חותמת זמן (מספר אמתי) בתחילת " "השאילתה. פִּרְקָן 'זמן' ו 'אקראי' זמינים, כמו גם 'אקראי' (== random.Random)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "הכללת ערכי חיפוש שמורים" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "מכליל תוצאות של חיפוש שמור כחלק משאילתה אחרת. התחביר הוא '@(saved: search " "name)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "ערכי חיפוש שמורים" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "יִחוּדִי" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "סקוויזבוקס OK. שימוש בנגן היחיד (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "לא ניתן להתחבר ל %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "שם מארח:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "פורט:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "שם משתש:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "סיסמה:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "מחיצת הספריה אליה מתחבר השרת" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "נתיב ספריה:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_אימות הגדרות" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "שרת סקוויזבוקס" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "ניפוי תקלים" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "שרת סקוויזבוקס ב {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "שרת סקוויזבוקס לא מוגדר" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "נגן סקוויזבוקס לא מוגדר: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "בחירת נגן סקוויזבוקס" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "נמצא שרת סקוויזבוקס.\n" "נא לבחור נגן" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "התאמת תמונה _לחלון" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "ראו תצורת '[plugins] cover_filenames'] עבור מחרוזות קובצי תמונות" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_תכנית:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_עריכת תמונה לאחר שמירה" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "שם _קובץ:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "פעולת השמירה כשלה" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "לא ניתן לשמור \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "שגיאת [תמונת עטיפה] HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "מוריד עטיפות אלבום" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "מ %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "רָמַת הפרדה: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "גודל: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "הגבלת התוצאות לפי מנוע 'לכל היותר'" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_חיפוש" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "חיפוש…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "בוצע" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "הורדת עטיפות אלבום" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "הורדת עטיפות אלבום מאתרים שונים." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "מקורות" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 ל ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "המרת תגי APEv2 לתגי ID3v2. פעולה זו תמחק את תגי APEv2 לאחר ההמרה." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "מעבר לסמניה" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "ניהול סימניות בקבצים שנבחרו." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_עריכת סימניות…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "אין סימניות" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "חיפוש מוזיקבריינז" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "תיוג מחודש של אלבום בעת חיפוש ב מוזיקבריינז." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "שימוש בשנה בלבד בתג תאריך" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "כתיבת \"_albumartist\" כשנדרש" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "כתיבת תגי מיון לשמות אמנים" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "כתיבת _תגי מוזיקבריינז סטנדרטיים" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "כתיבת תג \"labelid\"" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "שם קובץ" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "תקליטור" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "רצועה" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "כותרת" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "אמן" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "חיפוש מוזיקבריינז" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_שאילתה:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "ח_יפוש" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "תוצאות <i>(גרירה למיון מחדש)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "נא להזין שאילתה." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "אירעה שגיאה. נא לנסות שוב." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "טעינת תוצאת…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "לא נמצאו תוצאות." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "מסוף פייטון" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "מסוף פייטון הִדּוּדִי. פתיחה בחלון חדש." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} עבור {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "סרגל צד מסוף פייטון" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "מסוף פייטון הידודי, שעוקב אחר השירים שנבחרו בחלון הראשי." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "ניתן לגשת לאובייקטים הבאים כברירת מחדל:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "המחיצה הפעילה היא:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "חיבור" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "הורדת עטיפות אלבום" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "הורדת תמונות עטיפה באיכות גבוהה תוך שימוש במתקעי תמונות עטיפה." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "קלאסי" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "גדול" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "HD מלא" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "הורדת תמונת עטיפות" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "טעינת %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "לא נמצאו אלבומים:\n" "<i>%(albums)s</i>.\n" "\n" "על ידי ספקים:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "לא נמצאו עטיפות" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "גודל תצוגה מקדימה" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "יעד לשמירה" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "פקודה" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "שם" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "שם פקודה זו" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "פקודה" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "תַּחְבִּיר פקודה מַעֲטֶפֶת להרצה" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "מְאַפְיֵן" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "במידה והוגדר, פרמטר שהמופע שלו בפקודה יוחלף עם ערך שסופק על ידי המשתמש, " "לדוגמה בהזנת '{PARAM}' כל המופעים של '{PARAM}' בפקודה יקבלו את הערך הנחוץ " "בעת ההפעלה" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "דפוס ה QT לדוגמה <~filename>, משמש לחישוב ערך עבור הפקודה. עבור רשימת " "ההשמעה, תומך גם בתגים מְדֻמים <~playlistname> ו <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "יִחוּדִי" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "במידה והוגדר, פעולה זו תסיר ערכים כפולים של הדפוס" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "ארגומנטים מירבים" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "המספר המרבי של ארגומנטים להעברת הפקודה לפעם אחת (כמו xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "הסגה" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "הזנת ערך" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "ערך עבור %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "פקודות מותאמות אישית" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "הפעלת פקודות מותאמות אישית (באצווה אם נדרש) על שירים תוך שימוש תג כלשהו." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "עריכת פקודות מותאות אישית" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "לא ניתן להריץ פקודה מותאמת אישית %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d שכפול קבוצה" msgstr[1] "%d שכפול קבוצות" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "כיווץ / הרחבה הכל" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "ביטוי מפתח כפול הוא '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "דפדפן כפולים" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "חיפוש והצגת גרסאות שירים המתויגים דומה." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "מתקבלים ביטויי תג קוודליבט כמו <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_קיבוץ כפולים לפי:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "מפתח כפול" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "הסרת _רווח לבן" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "הסרת _סִימָן דִּיאָקְרִיטִי" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "הסרת _פיסוק" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "רגישות _לרישיות" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "אפשרויות התאמה" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "עריכת מספר השמעות" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "עריכת ~#playcount ו ~#skipcount לשיר.\n" " \n" "\n" "בבחירת שרים מרובים, מונה ההשמעות יגדל אינקרימנטלית.\n" "\n" "בעת הגדרת ~#playcount של שיר ל 0, ערכי ~#lastplayed ו ~#laststarted , הקימים " "ינוקו. עם זאת, בעת הגדרת מונה השמעות שיר מ 0-Play מונה ההשמעות חיובי, לא " "ייווצרו מוני השמעה." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "מונה השמעות" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "דִּלּוּג ספירה" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "ערכי %s מרובים" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "עריכת תמונות משובצות" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "הסרת או החלפת תמונות משובצות." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_הסרת כל התמונות" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_שיבוץ תמונה נוכחית" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "הגדרת אקזקט רייטינג" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "אפשרות להגדרת דרוג שיר בשימוש במספרים." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "דרוג מבוקש בסולם בין 0.0 ל 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "סינון לפי תג כלשהוא" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "יצירת שאילתת חיפוש המבוססת על תגי השירים שנבחרו." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "סינון על פי מחיצה" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "סינון לפי מחיצה בחלון דפדוף חדש." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "חיפוש טביעות אצבע שמע" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "חיפוש מטה-דטה של שיר על ידי טביעת אצבע שמע." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "שגור טביעות אצבע שמע" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "חלול טביעות אצבע שמע באמצעות כרומאפרינט ושיגורם ל acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "חסר מפתח API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "נדרש להגדיר מפחת API של acoustid.org בהעדפות המתקע לפני שיתאפשר לשגר תביעות " "אצבע." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "בקשה למפתח API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "מפתח_ API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "שרות רשת אקוסטיקאיידי" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "נוספו לתור" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "מנתח" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "איתור" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "כתיבה" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "מהדורה" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "כתיבת תגי מוזיקבריינז" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "קיבוץ על פי מחיצה" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "מצב אלבום" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "כתיבת תגים הקשורים לאלבום תוך ניסיון לצמצם את מספר המהדורות השונות של " "האלבומים" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "חילול טביעות אצבע:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_פרטים" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_שגור" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "על מנת שהשירים ישוגרו, נדרש <i><b>musicbrainz_trackid</b></i>, או " "<i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i>." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "טביעות אצבע:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "שירים בעלי MBIDs:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "שירים בעלי תגים מספקים:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "שירים לשגור:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "בוצע. %(to-send)d/%(all)d שירים לשגור." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "שגור טביעות אצבע:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "שגור…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "עדכון ערכי התגים בקבצים" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "עדכון תגים שהשתנו בקבצים. פעולה זו תבטיח עדכניות מונה השמעות ודרוג." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "יצוא ל HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "יצוא השירים שנבחרו לרשימת HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "שליחה ל iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "מעלה שירים להתקן iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "לא נמצא התקן iFP" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "לא ניתן ליצור קשר למכשיר ה- iFP. נא לודא שהמכשיר מופעל ומחובר, וכי ifp-line " "(http://ifp-driver.sf.net) מותקן." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "העלאת %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "לא ניתן לטעון את <b>% s </ b>. ייתכן שהמכשיר כבוי או הזיכרון מלא." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "שגיאת ההעלאה" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "יצוא מטה-דטה" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "יצוא מטה-דטה" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "יצוא מטה-דטה" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "יצוא מטה-דטה" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "נתוני זמן חסרים" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "עטיפת אלבום" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "יבוא כשל" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "יבוא" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "סינון על פי מחיצה" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "תקליטור" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "רצועה" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "אמן" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "אלבומים" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_להמשיך" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "לא ניתן להתחבר לשרות '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "לא ניתן להתחבר לשרות '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "שמות קובצים" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "חזרה על כל רצועה" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "עדכון רשימת לוח שידורים." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "מעודכן כבר." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "אחזור לוח שידורים לשבוע %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "סנכרון הושלם." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "אירעה שגיאה במהלך הסנכרון" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "סנכרון Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "עדכון הנתונים הסטטיסטיים של הספרייה מפרופיל Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_שם משתש:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "יצירת תגי מיון" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "המרת שמות אלבום ואמנים לשמות מיון, לא להיט." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "יצוא כרשימת השמעה" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "יצוא שירים לרשימת השמעה M3U או PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "שימוש בנתיבים יחסיים" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "שימוש בנתיבים מוחלטים" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "כתיבה ל <b>%s</b> כשלה." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "סריקת שירים חוזרת" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "בדיקת שינויים בקןבץ, טוען מחדש / מסיר את השירים במידת הצורך." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "סריקת שירים חוזרת" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "מנתח ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "רצועה" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "התקדמות" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "הגברה" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "שיא" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "יש <b>%(to-process)s</b> אלבום לעדכון (מ %(all)s)" msgstr[1] "ישנם <b>%(to-process)s</b> אלבומים לעדכון (מ %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ריפליי גאיין" #: quodlibet/ext/songsmenu/replaygain.py:571 #, fuzzy, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "ניתוח ועדכן מידע ריפלייגאיין באמצעות ג'סטרימר. התוצאות מקובצות לפי אלבום." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "תמיד" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "כאשר חסר תג <b>כלשהו</b> RG" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "כאשר חסר תג <b>אלבום</b> RG" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_עיבוד אלבומים:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "תגים קימים" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "פיצול תגים" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "פיצול בו זמני של מספר התקליטור מהאלבום והגרסה מהכותרת." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "פיצול האלבום" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "פיצול מספר תקליטור." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "לא זמין" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "קצב סיביות לדקה:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "איפוס" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "הקשה" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "הקשה לקבלת קצב סיביות לדקה" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "הקשה על BPM לקבלת קצב סיביות לדקה." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "חיפוש מרשתת" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "חיפוש באתר שנבחר על פי תגי שיר.\n" "תמיכה בדפוסים, לדוגמה %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "חיפוש דפוסי URL" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "עריכת חיפוש URLים" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "תיצור חיפוש…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "חיפוש תג בויקיפדיה" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "פתיחת חלון דפדפן, עם מאמרים מויקיפדיה, על פי תגי השיר שנבחר." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "חיפוש ב %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "עריכת תגים" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "פעולת חיפוש כשלה" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "תג \"%s\" לא נמצא." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "ספריה" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "בודק מחיצות מעוגנות" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "ספרית השירים נסרקת" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "סורק %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "טעינת קבצים" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "ספרית השירים נסרקת" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "הסרת מסנן דפדפן פעיל" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "מנהל ספרית מוזיקה ונגן" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "טעינת קובץ כשלה: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "הצגת תגים" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "הדפסת פלט מצומצם" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "עמודות וסדר עמודות לתצוגה באפן מצומצם (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "הצגת תגי תכנות" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "אין מספיק ארגומנטים" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "יותר מדי ארגומנטים" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "תיאור" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "ערך" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "הצגת כל התגים המשותפים" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "העתקת תגים מקובץ אחד למשנהו" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "הצגת שינויים, לא להחיל אותם" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "דִּלּוּג על תגים שאינם ניתנים לכתיבה" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "לא ניתן להעתיק תג {tagname} לקובץ: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "עריכת תגים במעבד תמלילים" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "ערכיה נזנחה" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "הפעלת מעבד תמלילים ''%(editor-name)s' כשלה." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "לא זוהו שינויים" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "הגדרת תג והסרת ערכים קימים" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "%r לא ניתן להגדרה" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "_הסרת תגים" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "ערך הוא ביטוי סדיר" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "הסרת כל התגים" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "לא ניתן לאחד '--all' עם '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "לא ניתן להסיר {tagname} מ {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "הסרת ערך תג" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "הוספת ערך תג" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "%r לא ניתן להגדרה" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "הצגת נתוני קובץ" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "קביעת התמונה שסופקה כתמונה משובצת עיקרית והסרת יתר התמונות המשובצות" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "לא ניתן לטעון קובץ תמונה: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "עריכת תמונות לא נתמכת עבור %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "הסרת כל התמונות המשובצות" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "חילוץ תמונות משובצות ל %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "הנתיב למיקום בו יישמרו התמונות (ברירות מחדל למחיצת העבודה)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "שינוי שמות קבצים על פי תגים" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "הזנת תגים על פי נתיב הקובץ" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "קובץ" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "הזנת מספר רצועה בכל הקבצים" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "הדפסת תגים על פי דפוס נתון" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "מַצָּג עזרה" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' אינו שם עמודה תקין (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_לא ידוע" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "לפי הסדר" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "לפי _סדר" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "אקראי" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_אקראי" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "העדפת דרוג גבוהה יותר" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "העדפת דרוג גבוהה יותר" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "חזרה על הרצועה" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "חזרה על הרצועה" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "חזרה על הכל" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "חזרה על הכל" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "שיר בודד" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "שיר בודד" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "הזרמה" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "חציצה" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "לא ניתן ליצר צנרת ג'סטרימר" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "לא נמצא רכיב ג'סטרימר לטיפול בתבנית המדיה" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "תבנית המדיה: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "לא ניתן לאתחל מתקע ‏ג'סטרימר '%(name)s'" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "פלט צנרת ג'סטרימר המשמש להשמעה. נא להשאיר ריק עבור צנרת ברירת המחדל. במידה " "והצנרת מחוברת ליעד, יעשה בה שימוש במקום בברירת המחדל." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_פלט צנרת:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_משך חוצץ:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "נטרול השמעת _נטול פערים" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "השבתת השמעת נטול פערים עשוי למנוע בעיות בהחלפת רצועה בעלת מספר גרסאות " "ג'סטרימר" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "לא נמצא יעד שמע ג'סטרימר" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "פלט צנרת ג'סטרימר שגויה" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "לא ניתן ליצור פלט שמע" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "התקן השמע %r לא נמצא. נא לבדוק את תצורת Xine ב- ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "לא נמצאה פִּרְקָן '{module}'. אולי צריך להתקין את החבילה?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "לא ניתן למצוא רכיב ג'סטרימר '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "נא להגדיר את QLScrobbler בחלון המתקעים. עד אז השירים לא ישוגרו." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "נא להגדיר את QLScrobbler בחלון המתקעים. עד אז השירים לא ישוגרו." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "שגור" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "שם _משתש:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "שירים התואמים למסנן זה לא ישוגרו" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "הפעלת מתקע \"%(name)s\" על %(count)s רשימת השמעה?" msgstr[1] "הפעלת מתקע \"%(name)s\" על %(count)s רשימות השמעה?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_הרצת מתקע" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "התחלה" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "לא זמין" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "זמן" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "שם סימניה" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "סימניות" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_מסננים" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "הושמעו _לאחרונה" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "נוספו _לאחרונה" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _המובילים" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "כל _השירים" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "לפי _סוגה(ות) נוכחית" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "לפי _אמן(נים) נוכחי" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "לפי אל_בום נוכחי" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "ס_וגה אקראית" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "א_מן אקראי" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "אל_בום אקראי" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 השירים שהושמעו מספר הפעמים הרב ביותר (ניתן לבחור יותר מ 40 שירים אם ישנם " "קשרים בינם)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_שם:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_ערך:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "ערכים שמורים" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "עריכת ערכים שמורים…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "אוטו_מטי" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_מצב רצועה" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_מצב אלבום" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_השתקה" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_מצב ריפליי גאיין" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "חדש %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(לא ידוע)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_הוספה" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_עריכה…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "ביטוי תג" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "ביטוי תג לדוגמה, אנשים: אמיתי או ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "הזנת תג חדש" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "ביטוי תג" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "קבצים:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "השירים שנבחרו יוסרו מהספריה והקבצים שלהם ימחקו מהכונן." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "הקבצים שנבחרו ייחקו מהכונן." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "מחיקת %(file_count)d קובץ לצמיתות?" msgstr[1] "מחיקת %(file_count)d קובצים לצמיתות?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_מחיקת קבצים" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "השירים שנבחרו יוסרו מהספריה והקבצים שלהם יועברו לסל האשפה." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "הקבצים שנבחרו יועברו לסל האשפה." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "העברת %(file_count)d קובץ לסל האשפה?" msgstr[1] "העברת %(file_count)d קבצים לסל האשפה?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_העברה לסל האשפה" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "מעביר %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "לא ניתן להעביר לסל האשפה" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "העברת קובץ אחד או יותר לפח האשפה כשלה." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "מוחק %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "לא ניתן למחוק קובצים" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "מחיקת אחד או יותר קבצים כשלה." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "דפדפנים" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "טעינת קבצים" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "חסר לשיר %d" msgstr[1] "חסר ל %d שירים" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "שונה בשיר %d" msgstr[1] "חסר ל %d שירים" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "פיצול לערכים _מרובים" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "פיצול תקליטור מתוך _אלבום" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "פיצול _גרסה מתוך שם" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "פיצול _אמרגן מתוך אמן" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "פיצול מ_בצע מתוך אמן" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "פיצול _מבצע מתוך כותרת" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "פיצול _אמרגן מתוך כותרת" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "הוספת תג" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_תג:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "הצגת _תגים תָכנותִיים" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "גישה לכל התגים, לרבות תגי ממוכנים כגון מוזיקבריינז או ריפליי גאיין" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "הצגת _תגים תָכנותִיים" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_הסגה" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_שמירה" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_תצור" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_פיצול תג" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_העתקת ערך(כים)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "לא ניתן להוסיף תג" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "לא ניתן להוסיף שיר או שירים" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "הקבצים שנבחרו אינם תומכים ערכים מרובים ב <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "תג שגוי" msgstr[1] "תג שגוי" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "תג שגוי <b>%s</b>\n" "\n" "הקבצים שנבחרו אינם תומכים בעריכת התג זה." msgstr[1] "" "תג שגוי <b>%s</b>\n" "\n" "הקבצים שנבחרו אינם תומכים בעריכת התג זה." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "ערך שגוי" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "ערך שגוי: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "התג עשוי להיות לא מדוייק" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s השתנה בזמן שהתוכנית רצה. שמירה ללא רענון הספריה עשויים לדרוס " "שינויים אחרים שבוצעו לשיר." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "לא ניתן לשמור שיר" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "שמירת %(file-name)s כשלה. יתכן והקובץ הוא לקריאה בלבד או שחסרה הרשאה מתאימה " "לעריכתו." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_אפשרויות נוספות…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_הסגה" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_מחדש" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_אודות" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_בדיקת זמינות עדכונים…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_מתקעים" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s ו %(count)s נוסף" msgstr[1] "%(title)s ו %(count)s נוספים" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "מאפייני אקס פאלסו" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "תיקיות" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_תיקיה חדשה…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_בחירת כל תקיות המשנה" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "תיקיה חדשה" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "הזנת שם לתיקיה החדשה:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "לא ניתן ליצור תיקיה חדשה" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "לא ניתן למחוק תיקיה" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "שירים" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "בביצוע %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "תקליטור %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "רצועה %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "לפי _סוגה(ות) נוכחית" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_עריכת מַצָּג…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "לא נבחרו שירים." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "ללא שירים" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "מידע" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "תַּמְלִיל" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "הופק על ידי %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "אמן" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "אמנים" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "מבצעים" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "מעולם לא" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "פעם %(n)d" msgstr[1] "%(n)d פעמים" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "נוספו בתאריך" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "הושמעו לאחרונה" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "השמעות" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "דולג" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "דֵּרוּג" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "נתיב" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "משך" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "תבנית" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "מקודד" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "קידוד" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "קצב סיביות" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "גודל קובץ" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "שונה לאחרונה" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "נוסף" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d נבחר" msgstr[1] "%d נבחרו" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "רצועה לא זמינה" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "שיר %d ללא אלבום" msgstr[1] "%d שירים ללא אלבום" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "דיסקוגרפיה נבחרת" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "שיר %d ללא אמן" msgstr[1] "%d שירים ללא אמן" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "אלבומים" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "משך כללי:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "גודל כללי:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "קבצים" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_צפיה מקוונת" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "לא נמצא תַּמְלִיל לשיר." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "האם להסיר את כל השירים?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "השירים שנבחרו יוסרו מהספריה." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "ביטול הסתרה" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_ביטול הסתרה" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "שמיטת שינויים בתג?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "תגים שונו אך לא נשמרו. נא לשמור שינויים, או לחזור למקור ולשמוט שינויים?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_הסגה" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "הקובץ קיים" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "החלפת %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_החלפת קובץ" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "משימות פעילות" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d משימות רצות" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "החלפת מצב אקראי" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "החלפת מצב חזרה" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "ארועים" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "סדר השמעה" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "ערכיה" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_שנוי שם" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_שאילתה:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "תמונות עטיפה" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "שגיאות מתקע" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "מאופשר" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "מנוטרל" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "ללא קטגוריה" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "ללא קטגוריה" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "לא נמצאו מתקעים." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "מתקעים" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "סינון לפי תג /מצב מתקע" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "סינון לפי סוג מתקע" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "סינון לפי שם או תאור מתקע" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "הצג שגיא_ות" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_תקליטור" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_רצועה" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "קי_בוץ" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_אמן" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "אל_בום" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_שם קובץ" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_משך" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_דלוג לשיר המושמע באופן אוטומטי" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "כאשר מתחלף שיר מושמע, להציג אותו ברשימת השירים" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_אחרים:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_עריכה…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "הוספה או הסרה של עמודות" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "עמודות מוצגות" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "כותרת כלולת _גרסה" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "אלבום כולל כתוביות _תקליטור" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "אמן כולל את כל _האנשים" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "שם קובץ כולל _תקיה" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "העדפות עמודות" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "עריכת עמודות" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "החלת התצורה הנוכחית על רשימת שירים, הוספת עמודות חדשות לסוף" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "רשימת שירים" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "עריכת עמודות" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "סך כל משך" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_מסנן כללי:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "החלת שאילתה זו בנוסף לכל האחרות" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "חיפוש" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "דפדפנים" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "אישור דֵּרוּג _מרובה" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "בקשת אישור לפני שינוי הדֵּרוּג של שירים מרובים בו-זמנית" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "אפשור דרוג בהקשה _אחת" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "אפשור דרוג על ידי לחיצה על עמודת הדרוג ברשימת השירים" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "דרוג" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "העדפת _תמונה משובצת" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "בחירה בשימוש בתמונות עטיפה משובצות (ככל שהן זמינות) על פני תמונות אחרות" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_שם קובץ תמונה קבוע:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "עטיפת אלבום" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "השמעה" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "תְּצוּרָת פלט" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "אם אין מידע ריפליי גאיין זמין להשמעה, עוצמת הקול תושווה לערך זה" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_מרווח עצמה מוצא (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "סולם עצמה עבור כל השירים לפי ערך זה, כל עוד התוצאה לא מקוצצת" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_מרווח קדם-מגבר (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_אפשור כיוונון עוצמת ריפליי גאיין" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "כיוונון עוצמת ריפליי גאיין" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_המשך השמעה לאחר אתחול" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "אם מושמעת מוזיקה בעת כיבוי, היא תמשיך להתנגן מיד לאחר האתחול" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_דֵּרוּג ברירת מחדל:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "סרגל _דרוג:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "גורם ממוצע בייסיאני (C) לדֵּרוּגים מצטברים.\n" "0 פירושו ממוצע קונבנציונאלי, ערכים גבוהים יותר פירושם שלאלבומים עם רצועות " "מעטות יהיו דֵּרוּגים פחות קיצוניים. שינוי ערך זה מפעיל חישוב מחדש עבור כל " "האלבומים." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_סכום ממוצע בייסיאני:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_דואר אלקטרוני:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "הדֵּרוּג ומספר ההשמעות ישמרו בתגים עבור כותבת דוא\"ל זו" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "שמירת שינויים אוטומטית בתגים" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "שמירת שינויים בתגים ללא בקשת אישור בעת עריכת מספר קבצים" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "סדרת תווי הפרדה לשימוש בעת פיצול ערכים בעורך התגים. ערכי הרשימה מופרדים " "בפסיקים." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "פיצול _תג עם:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "סדרת תווי הפרדה לשימוש בעת פיצול תגי משנה מתגים בעורך התגים. הרשימה מופרדת " "ברווח, וכל רשומה אמורה להכיל שני תווים בלבד." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "פיצול תג _משנה עם:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "תגים" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "עריכת תגים" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "עדכונים לדרוג חדש" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_סריקת ספריה" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "בדיקת שינויים בספרית השירים" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "בנ_ית הספריה מחדש" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "טעינה חוזרת של כל השירים בספריה. הפעולה עשויה לארוך זמן ממושך." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "שירים מוסתרים" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "סריקת ספריה _באתחול" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "סריקת מחיצות" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s ו %(count)d נוסף" msgstr[1] "%(title)s ו %(count)d נוספים" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "מאפיינים" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_סדר השמעה" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_ניקוי תור" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "נטרול התור - הנגן יתעלם מהתור בזמן ההשמעה" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "בר-חלוף" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "הסרת שירים מהתור לאחר השמעתם" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "התמדה" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "השארת שירים בתור לאחר השמעתם" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "מצב" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "עצירה בסוף" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "שיר %(count)d (%(time)s)" msgstr[1] "%(count)d שירים (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_דפדוף בספריה" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "החלפת מצג תור" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "שגיאת השמעה" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "הגדרת מחיצות בספריה?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "לא הוגדרה ספרית מוזיקה. האם להגדירה כעת?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_לא כעת" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_הגדרות" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "לא ניתן להוסיף שיר או שירים" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s משתמש בפרוטוקול שאינו נתמך." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_דלוג לשיר מושמע" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_קובץ" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_שיר" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_תצוגה" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_דפדוף" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_בקרה" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_עזרה" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_הוספת תיקיה…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_הוספת קובץ…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_הוספת מיקום…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "עריכת סימניות…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_עצירה" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "עצירה לאחר השיר זה" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_קיצורי מקלדת" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "עזרה מקוונת" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "חיפוש עזרה" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "הוספת מיקום" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "הזנת המיקום של קובץ שמע:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "לא ניתן להוסיף את הנתיב שצוין" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s אינו מיקום תָקֵף." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "הוספת מוזיקה" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_הוספת תיקיות" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "קובצי מוזיקה" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_הוספת קבצים" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "האם להסיר את כל השירים?" msgstr[1] "האם להסיר את כל השירים?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_סדר השמעה" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "האם לשנות דרוג לכל %d השירים?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "הדרוג השמור יוסר" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_הסרת דרוג" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "הדרוג לכל השירים שנבחרו ישתנה ל '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "שינוי _דֵּרוּג" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "החלפת _רווחים בקווים תחתיים" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "הסרת _תווים שאינם נתמכים בחלונות" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "הסרת _סִימָים דִּיאָקְרִיטִיים" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "ה_סרת תווים שאינם תווי ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "שימוש _באותיות קטנות בלבד" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "שינוי שמות קבצים" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_תצוגה מקדימה" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "שמות קובצים" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_העברת עטיפות אלבום" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "ראו הזנות תצור של שמות קובץ [albumart] למחרוזות חיפוש תמונה" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_דריסת עטיפת אלבום ביעד" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_הסרת תיקיות ריקות" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "עטיפת אלבום" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "שם חדש" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "לא ניתן לשנות שם קובץ" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "שינוי שם מ <b>%(old-name)s</b> ל <b>%(new-name)s</b> כשל. יתכן ששם היעד קיים " "כבר או שחסרה הרשאה מתאימה ליצור או למחוק קובץ קודם." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "להתעלם _מכל השגיאות" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_עצירה" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_להמשיך" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "הנתיב אינו מלא" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "הדפוס\n" "\t<b>%s</b>\n" "מכיל / אך אינה מתחיל מספרית השורש. על מנת למנוע שמות תיקיה שגויים על הדפוס " "להתחיל מ / או מ /~." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "שירים בתקיות המוצגות יתווספו לספריה בעת רענונה" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "השירים שנבחרו יוסרו מהספריה." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "נתיב ספריה:" msgstr[1] "נתיב ספריה:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_הסרה" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "בחר ספריות" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "בחר ספריות" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "ערכי חיפוש שמורים" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "עריכת חיפושים שמורים…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "חיפוש בספריה תוך שימוש במלל חופשי או שאילתות QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "חיפוש לאחר _הקלדה" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "הצגת תוצאות חיפוש מיד לאחר סיום הקלדה" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_מגבלה:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_משקל" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "הוספת שאילתה" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "הוספת שאילתת קוואדליבט או מלל חופשי &שיחוברו יחד" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "הצגת זמן נותר" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "חלון ראשי" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "הזחה אחורה ב 10 שניות" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "הזחה קדימה ב 10 שניות" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "מיקוד על רשומת החיפוש" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "איפוס מסננים ודלוג לשיר המושמע" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "פתיחת חלון המידע לשירים שנבחרו" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "פתיחת תגי השירים שנבחרו בעורך התגים" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "הוספת השירים שנבחרו לתור" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "מחיקת השירים שנבחרו" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "הצגת ערך החיפוש" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "הקשה שמאלית על כותרת עמודה" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "הוספת עמודה לרשימת העמודות למיון" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "מצג עץ" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "כיווץ רכיב או בחירת רכיב האב" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "הרחבת הרכיב" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "הזנות מלל" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "ביטול שינויים אחרונים" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "אחזור מחודש של שינויים אחרונים" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "בחירת כל השירים בכל החלוניות" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_מיין לפי %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "כל _הכותרות" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_כותרות רצועות" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "כ_ותרות אלבומים" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "כותרות _מבצעים" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "כותרות ת_אריך" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_כותרות קבצים" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "כות_רות הפקה" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_כותרות מותאמת אישית…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_הרחבת עמודה" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "הסרת רצועה: \"%%(title)s\" מהספריה?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "הסרת רצועה: \"%%(title)s\" מהספריה?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "הסרה מהספריה" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "הפעלת מתקע \"%(name)s\" על %(count)d שיר?" msgstr[1] "הפעלת מתקע \"%(name)s\" על %(count)d שירים?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "הפעלת מתקע \"%(name)s\" על %(count)d אלבום?" msgstr[1] "הפעלת מתקע \"%(name)s\" על %(count)d אלבומים?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "תיצור מתקעים…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "הו_ספה לתור השמעה" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_הסרה מהספריה…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "לא ניתן להציג קבצים" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "שגיאה בהצגת קבצים, או שאין תכנית זמינה להציגם." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_הצגת קובץ במנהל הקבצים" msgstr[1] "_הצגת %(total)d קבצים במנהל הקבצים" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "פעולת השמירה כשלה" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "הורדת עטיפות אלבום" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "הורדת עטיפות אלבום" msgstr[1] "הורדת עטיפות אלבום" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "הורדת עטיפות אלבום" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "החלפת _קווים תחתיים ברווחים" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_החלפה לאות גדולה ראשונה בכל מילה" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "פיצול לערכים _מרובים" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "דפוסי תגים" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "תגים יחליפו את הקיים" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "תגים יתווספו לקיים" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "הדפוס\n" "\t<b>%s</b>\n" "שגוי. עשוי להכיל את אותו התג פעמיים או שהוא אינו סגור במירכאות(< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "הדפוס שהוזן שגוי, נא לוודא ש < ו > הוזנו כ \\< ו \\> וכי התגים " "מאוזנים.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "עריכת מַצָּג" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "מספרי רצועות" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "התחל _מ:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_סך כל רצועות:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "השמעה/השהייה" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "הקודם" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "ו %d יותר…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "שמירת שירים ששונו." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d שירים נשמרו\n" "(%(remaining)s remaining)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s מ %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "בדיקת עדכונים" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "חיבור כשל" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "הגרסה העדכנית ביותר ‏ %(version)s כבר מותקנת" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "גרסה חדשה %(new-version)s זמינה\n" "\n" "הגרסה שבשימוש היא %(old-version)s\n" "\n" "בקרו ב <a href='%(url)s'>אתר</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "ייבא רשימת השמעה" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "רשימת ההשמעה חייבת שם" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "רשימת השמעה בשם %s קיימת כבר." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "עטיפות אלבום משובצות" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "שימוש בתמונות עטיפה משובצות בקבצים." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "עטיפת רשימת ספריות" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "שימוש בתמונות בעלות שמות נפוץ שנמצאו בספריות משותפות לצד השירים." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "תמונות עטיפה" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "תחקור ספקי תמונות לעטיפות אלבום" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "הצגת מידע קצר על השימוש" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "מצג גרסה וזכויות יוצרים" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "הדפסת נתוני ניפוי תקלים" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "שימוש: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[אפשרויות]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "אפשרות %r לא זוהתה." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "אפשרות %r צריכה ארגומנט." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r אינה תחילית יִחוּדִית." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d קב/ש" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s שניה" msgstr[1] "%s שניות" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "נתוני זמן חסרים" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d שניה" msgstr[1] "%d שניות" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d דקה" msgstr[1] "%d דקות" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d שעה" msgstr[1] "%d שעות" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d יום" msgstr[1] "%d ימים" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d שנה" msgstr[1] "%d שנים" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "רישיות?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "יש להזין תאריך בתבנית YYYY, YYYY-MM-DD או YYYY-MM-DD HH:MM:SS." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "יש להזין עצמת ריפליי גאיין בתבנית 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "יש להזין עצמה מרבית ריפליי גאיין בתבנית 'x.yy dB'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "רצועות בעלות סימול מוזיקבריינז חייבות להיות בתסדיר UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "סטטוס של מוזיקבריינז יכול להיות 'official' (רשמי), 'promotional' (לצרכי " "קידום) או 'bootleg' (לא רשמי)." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "שפה חייבת להיות קוד ISO 639-2 בן שלושה תווים" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "פעולת השמירה כשלה" msgstr[1] "פעולת השמירה כשלה" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "לא ניתן לערוך שיר" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "שמירת <b>%s</b> כשלה. יתכן שהקובץ מוגדר לקריאה בלבד, פגום, או שחסרות ההרשאות " "המתאימות לעריכה." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[קידוד פגום]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "אלבום" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "אמרגן" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "אמרגנים" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "הסדר" #: quodlibet/util/tags.py:86 msgid "author" msgstr "מחבר" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "מחברים" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "הערה" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "מלחין" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "מלחינים" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "יצירה" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "מנצח" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "מנצחים" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "ניצוח" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "איש קשר" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "זכויות יוצרים" #: quodlibet/util/tags.py:93 msgid "date" msgstr "תאריך" #: quodlibet/util/tags.py:94 msgid "description" msgstr "תיאור" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "סוגה" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "סגנונות" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "מבצע" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "תיפקוד" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "קיבוץ" #: quodlibet/util/tags.py:98 msgid "language" msgstr "שפה" #: quodlibet/util/tags.py:99 msgid "license" msgstr "רישוי" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "מילים" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "מילים" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "תַּמְלִיל" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "חברת הקלטות" #: quodlibet/util/tags.py:104 msgid "title" msgstr "שם" #: quodlibet/util/tags.py:105 msgid "version" msgstr "גרסה" #: quodlibet/util/tags.py:106 msgid "website" msgstr "אתר מרשתת" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "אמן האלבום" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "קצב סיביות לדקה" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "כותרת משנה תקליטור" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "תקליטור" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "רצועה" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "מזהה תג" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "תאריך הפצה מקורי" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "אלבום מקורי" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "אמן מקורי" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "הוקלט" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "ארץ מקור" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "מזהה הקלטה מוזיקבריינז" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "מזהה מהדורת רצועה מוזיקבריינז" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "מזהה רצועה מוזיקבריינז" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "מזהה אמן מוזיקבריינז" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "מזהה מהדורת אמן מוזיקבריינז" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "סימון TRM של מוזיקבריינז" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "סימון PUID של MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "סימון מוזיקבריינז של מצב אלבום" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "סימון סוג אלבום של מוזיקבריינז" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "מזהה קבוצת מהדורה מוזיקבריינז" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "הגברת רצועה" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "עוצמת רצועה מקסימלית" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "הגברת אלבום" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "עוצמת אלבום מקסימלית" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "ייחוס עוצמת קול" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "תקליטורים" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "רצועות" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "הושמעו לאחרונה" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "שם מלא" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "נקודת עגינה" #: quodlibet/util/tags.py:166 msgid "people" msgstr "יוצרים" #: quodlibet/util/tags.py:168 msgid "year" msgstr "שנה" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "תאריך מהדורה מקורי" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "סימניה" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "עומק סיביות" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "תבנית קובץ" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "_רשימות השמעה" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "קצב דגימה" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "מונה ערוצים" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "מיון" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "תפקידים" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "אקס פאלסו" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "עורך תגי שמע" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "עריכת תגים בקובצי השמע" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "קְווֹדְלִיבֵּט" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "נגן מוזיקה" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "האזנה, עיון ועריכה של אוסף השמע" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "אקס פאלסו הוא עורך תגים עם ממשק עריכת תגים זהה לקְווֹדְלִיבֵּט. דבר המאפשר הצגת " "ועריכת כל התגים בקובץ, בכל תבניות הקבצים הנתמכות." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "תבניות קבצים נתמכים כוללים OG Vorbis / Opus / Speex / FLAC, MP3, FLAC, MOD / " "XM / IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "קְווֹדְלִיבֵּט היא תכנה לניהול מוזיקה. המספקת דרכים שונות להצגת ספריית השמע, כמו " "גם תמיכה ברדיו מרשתת והזנות שמע. התכנה בעלת גמישות מרבית לעריכת תגי מטה-דטה " "ויכולות חיפוש." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "יצוא רשימת השמעה לסקוויזבוקס" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "לא ניתן להוסיף <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "תגים שגויים" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "תגים שגויים <b>%s</b>\n" #~ "\n" #~ "הקבצים שנבחרו אינם תומכים בעריכת התגים אלו." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "דרוג שירים אוטומטית במהלך השמעתם או דלוגום. המתקע משתמש באלוגריטם 'האצה' " #~ "מאת vox שנכתב על ידי בריאן נלסון." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f שניות" #~ msgid "Startup" #~ msgstr "אתחול" #~ msgid "Audio Feeds" #~ msgstr "ערוצי שמע" #~ msgid "_Audio Feeds" #~ msgstr "_הזנות שמע" #~ msgid "New" #~ msgstr "חדש" #~ msgid "Automatic Library Update" #~ msgstr "עדכון ספריה אוטומטי" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "שמירה על עדכניות ספרית המוזיקה באמצעות אינוטיפיי. נדרש %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "שליטה בקְווֹדְלִיבֵּט תוך שימוש בהגדרות ממשק 2 MPRIS D-Bus." #~ msgid "Searching for lyrics…" #~ msgstr "חיפוש תַּמְלִילים…" #, fuzzy #~ msgid "broker username" #~ msgstr "שם מתוך מארח" #, fuzzy #~ msgid "broker password" #~ msgstr "פִּתְחָת מתוך" #, fuzzy #~ msgid "<artist>" #~ msgstr "אמן" #, fuzzy #~ msgid "<album>" #~ msgstr "אלבום" #, fuzzy #~ msgid "<title>" #~ msgstr "שם" #, fuzzy #~ msgid "OK" #~ msgstr "_אוקיי" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "יצוא מטה-דטה לשירים שנבחרו לקובץ .tags." #~ msgid "Import Metadata" #~ msgstr "יבוא מטה-דטה" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "יבוא מטה-דטה לשירים שנבחרו מקובץ .tags." #~ msgid "Migrate Metadata" #~ msgstr "מיזוג מטה-דטה" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "העתקת מטא-דטה ייחודיים לקוודליבט בין שירים." #~ msgid "_Copy" #~ msgstr "_העתקה" #~ msgid "_Paste" #~ msgstr "_הדבקה" #~ msgid "Information to copy/paste" #~ msgstr "מידע להעתקה/הדבקה" #~ msgid "Map tracks by disc and track number" #~ msgstr "ממפה רצועות על פי מספר תקליטור ורצועה" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "יש לשפעל כאשר מעונינים להעביר מטא-דטה מאלבום אחד לאחר בעת התאמת התקליטור " #~ "ומספרי הרצועות.\n" #~ "\n" #~ "<b> שים לב: </ b> יש לאפשר זאת בעת העתקת אחסון מטא-דטה לשמירת פרטי רצועה." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "קיימת %d רצועה שמורה." #~ msgstr[1] "קיימות %d רצועות שמורות." #~ msgid "Unsupported file type" #~ msgstr "סוג קובץ אינו נתמך" #~ msgid "Unable to add station" #~ msgstr "לא ניתן להוסיף תחנה" #~ msgid "Search Library" #~ msgstr "חיפוש בספרית השירים" #~ msgid "_Search Library" #~ msgstr "_חיפוש בספריה" #~ msgid "Quit Program" #~ msgstr "יצאה מהתכנית" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "מניעת שומר צג גנום משיפעול בזמן ששיר מושמע." #~ msgid "No lyrics found" #~ msgstr "לא נמצא תַּמְלִיל" #~ msgid "_Zoom level:" #~ msgstr "_רמת מיקוד:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "חיפוש ב URL שלעיל, אם התַּמְלִיל לא נמצא ב LyricsWikia." #~ msgid "Alternate search" #~ msgstr "שינוי חיפוש" #~ msgid "Web Lyrics" #~ msgstr "תַּמְלִיל מרשתת" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "הצגת תַּמְלִיל מקוון של השיר המושמע בחלון צד." #~ msgid "Skip Songs" #~ msgstr "דִּלּוּג על שירים" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "דלוג השמעה על שירים בעלי דֵּרוּג שווה או נמוך לסף הנתון." #~ msgid "Burn CD" #~ msgstr "צריבת תקליטור" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "צריבת תקליטור באמצעות K3b, בראסרו או xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "שם קובץ תמונה היחיד, בו יעשה שימוש, אם נבחר" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "קובץ תמונת עטיפת האלבום, בו יעשה שימוש, אם אולץ (תומך תווים כלליים)" ������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/hu.po����������������������������������������������������������������������������0000644�0001750�0001750�00000631566�14436352625�013630� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2013-07-20 22:35+0100\n" "Last-Translator: SZERVÁC Attila <sas@321.hu>\n" "Language-Team: hu\n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.5.4\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Cím" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "személyek" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Dátum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Dátum fejlécek" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "eredeti művész" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "műfaj" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "É_rték" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Kijelző szerkesztése" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Rendezés dátum szerint" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Jellemzők" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Album lista" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Album lista" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Minden album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Album borítók mutatása" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Dalok albumon kívül" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d szám" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d lemez" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Minden album" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Album lista jellemzők" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Album borítók mutatása" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[lehetőségek]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Album kiírás" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Daltár böngésző" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d dal" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Hibás minta" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Ismeretlen" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Több értékre szedés" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "Egyedi" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "É_rték" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Album lista jellemzők" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Összméret:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Összméret:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Paneles böngésző beállítások" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Album borítók mutatása" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Minden album" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "szervezet" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Fájlrendszer" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Fájlrendszer" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Dalok másolása sikertelen" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "A kijelölt fájlok nem másolhatók más dal listába vagy sorba." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "Daltárhoz _adás" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Az állomás listák csak állomások helyeit tartalmazhatják, más állomás " "listákat vagy lejátszó-listákat nem. Az alábbi helyek nem tölthetők be:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet Rádió" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Új állomás" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Fájlok letöltése" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Új állomás" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Add meg egy Internet rádió állomás helyét:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "érték" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "Új állomás" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internet Rádió" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Új állomás" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Új állomás" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "Új állomás" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nem leltem állomást" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nem leltem Internet rádió állomást itt: %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Már minden kiírt állomás a daltárban van." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "Listához _adás" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "Tö_rlés a listáról" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d állomás" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneles böngésző" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Paneles böngésző" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Mindent kijelöl" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Ismeretlen" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Minden" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Látható oszlopok" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Paneles böngésző beállítások" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listák" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Listák" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Tö_rlés a listáról" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Import" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Lista importálása sikertelen" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "A Quod Libet csak PLS és M3U listákat tud importálni" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Fájlok törlése" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Átnevez" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Lista átnevezése sikertelen" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Listák importálása" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Import" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "Új lista" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Új lista" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Paneles böngésző beállítások" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Listák" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Szám" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Új lista" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Adj nevet az új mappának:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Lista importálása.\n" "\n" "%d/%d dal behozva." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Új forrás" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Add meg a hangforrás helyét:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Fájl hozzá_adása..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Daltár _frissítése" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Új dalok keresése e mappában" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Forrás hozzáadása sikertelen" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> nem tölthető be. Talán a kiszolgáló áll, vagy a hely nem " "hangforrás." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Eredmény kor_lát" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Több értékre _vágás" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Szám lista" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Szám lista" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Paneles böngésző" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Paneles böngésző" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Keres" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "számok" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "hely" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> nincs csatlakoztatva" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "A Quod Libet nem fut." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "egy zenekönyvtár és lejátszó" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[lehetőségek]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Kiírja a most forgó dalt és kilép" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Lejátszás kezdése azonnal" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Ugrás a következő dalra" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Ugrás az előző dalra" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Lejátszás indítása" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Lejátszás szünete" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Lejátszás/szünet váltása" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Lejátszás indítása" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Hang be" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Hang ki" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Lejátszó állapot kiírása" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Főablak rejtése" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Főablak mutatása" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Főablak mutatásának váltása" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fókusz a futó lejátszóra" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Aktív böngésző szűrők törlése" #: quodlibet/cli.py:113 #, fuzzy msgid "Refresh and rescan library" msgstr "Daltár _frissítése" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Böngésző kikapcsolása" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Mostani lista kiírása" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Sor tartalmának kiírása" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Sor tartalmának kiírása" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "A Quod Libet nem fut." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quod Libet bezárása" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Ugrás a forgó dalban" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ÓÓ:]PP:MM" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Lejátszás/szünet váltása" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Lejátszás/szünet váltása" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Ismétlés be/ki/váltás" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Lejátszás/szünet váltása" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Hangerő beállítása" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Daltár keresése" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "lekérés" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Fájl lejátszása" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "fájlnév" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Ugrás a forgó dalban" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "E böngésző beállítása" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "E dal értéke" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Új böngésző megnyitása" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Sor mutatása/rejtése" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Szűrő egy véletlen értéken" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "Tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Szűrő egy tag értéken" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=érték" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Fájl vagy lekérés a lejátszósorba" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "fájlnév" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Fájl vagy lekérés törlése a sorból" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "hely" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Hibás minta" #: quodlibet/cli.py:216 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Rossz argumentum ehhez: '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Próbáld ezt: %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Hibák mutatása" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "leírás" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "egy hang tag szerkesztő" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "könyvtár" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Hang tag szerkesztő" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz track ID" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz track ID" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Hibás kódolás]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Cím" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Hang tag szerkesztő" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Cím szerinti tagok" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Paneles böngésző beállítások" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Összméret:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Kijelző szerkesztése" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "Súly" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Kijelző szerkesztése" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "Előnézet" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Információ" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Támogatott formátumok: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Szűrő a _műfajon" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "könyvtár" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Hangforrások" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Új állomás" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Értékek és lejátszások mentése" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "rögzítési dátum" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Hibák" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "Új állomás" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Jellemzők" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Listák importálása" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Import" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Import" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Tag cserék elvetése?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Tag cserék elvetése?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Lejátszó" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "minta" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "minta" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d mp." #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Szűrő a _szerzőn/előadón" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "Vála_szt" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "Előnézet" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Egyedi" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Dalok törlése meghiúsult" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Hibás minta" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Zenelejátszó" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modell:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Internet Rádió" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "É_rték" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "hely" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Főablak rejtése" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "minta" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "minta" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d dal" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Információ" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "minta" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "hely" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz album típus" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Név:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Cím" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Könyvjelző név" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Eszköz:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "Más_ok:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Művész" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Fájlnév minta:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Véletlen _album" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "albumok" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "Súly" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Véletlen _album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Könyvjelzők" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Könyvjelző név" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Könyvjelző név" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[lehetőségek]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "[Hibás kódolás]" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "rögzítési dátum" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Fájlok törlése" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Szövegek" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Fájlok törlése" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Szövegek" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Nem leltem állomást" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "minta" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Mentett értékek szerkesztése..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Művész" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Előnézet" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Zenelejátszó" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Listák importálása" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "szervezet" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Válassz új állomásokat" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Szövegek" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Az ösvény nem abszolút" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "A minta\n" "\t<b>%s</b>\n" "tartalmaz /-t de nem indul gyökértől. Könyvtárnév-tévesztés ellen, adj " "gyökeret a mintának /-rel vagy ~/-rel kezdéssel." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nincs kijelölt dal" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nincs kijelölt dal" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Dal mentése sikertelen" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Szövegek" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Fájlok megnyitása sikertelen" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Szövegek" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Nem játszik" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d dal" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "minta" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "É_rték" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Nem játszik" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Listák" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Lejátszó" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "Előnézet" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "S_huffle" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "Ismétlés" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Stop e szám után" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Új böngésző megnyitása" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "_Tag szerkesztés" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Információ" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Listák" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Kijelző szerkesztése" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Szövegek" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Nincs szöveg ehhez a dalhoz." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Dal mentése sikertelen" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Hibák" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Fájlok" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "Előnézet" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Szűrő a _szerzőn/előadón" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "Egyedi" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "Egyedi" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Szűrő a _műfajon" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Szűrő a _szerzőn/előadón" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Hangforrások" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Add meg a hangforrás helyét:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Listák importálása" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Import" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Nem leltem állomást" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Fájlnév minta:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Lista importálása sikertelen" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Fájlnév minta:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Listák importálása" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Tö_rlés a listáról" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Új lista" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "utolsó lejátszás" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "utolsó lejátszás" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Lejátszósor" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Lejátszósor" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Lejátszósor" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Soha" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Soha" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "csoport" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Dalok másolása sikertelen" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Szűrő a _műfajon" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Érvénytelen tagok" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Mentett értékek" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Mentett értékek" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "Átnevez" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Daltár" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Főablak rejtése" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Fájlnév" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Dal mentése sikertelen" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Album lista" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Méret" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "Kere_s:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Keres" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Album lista" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "Könyvjelzők sz_erkesztése..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "Könyvjelzők sz_erkesztése..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Könyvjelzők" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz album típus" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Fájlnév" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Lemez" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Szám" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Cím" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Művész" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz album típus" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "lekérés" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Keres" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Beillesztések nem találhatók" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "hely" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Album lista" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Album lista" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Beillesztések nem találhatók" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "Előnézet" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "tag" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "Átnevez" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "tag" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Soha" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Rossz érték" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "Egyedi" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Dalok másolása sikertelen" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Böngésző kikapcsolása" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "É_rték" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "É_rték" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Kijelző szerkesztése" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Több értékre szedés" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "É_rték" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Szűrő egy tag értéken" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Szűrő a _műfajon" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "Lejátszósor" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Ír" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz track ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "könyvtár" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Album fejlécek" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "Új állomás" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Beillesztések nem találhatók" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "%d/%d mozgatása" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Listák importálása" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Listák importálása" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Nincs idő adat" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Album lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Listák importálása" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Import" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Szűrő a _műfajon" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Lemez" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Szám" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Művész" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albumok" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "Tovább" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Fájlnév" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "számok" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Hibák" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "Átnevez" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Listák importálása" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "<b>%s</b> kinyitása sikertelen" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Daltár _frissítése" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Daltár _frissítése" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Szám" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Tag szerkesztés" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Tag szerkesztés" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Minden album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "Előnézet" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Tag" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Dalok törlése meghiúsult" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Keres" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "minta" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Mentett értékek szerkesztése..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Színes kere_ső kifejezések" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Tag szerkesztés" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Keres" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Daltár" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Csatolási pontok ellenőrzése" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Daltár átnézése" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "%s átnézése" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Daltár átnézése" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Aktív böngésző szűrők törlése" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "egy zenekönyvtár és lejátszó" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "_Programozható tagok mutatása" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "leírás" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Érték" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Hang tag szerkesztő" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Nincs kijelölt dal" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Szűrő egy tag értéken" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Szűrő egy tag értéken" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Nincs idő adat" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Fájl átnevezése sikertelen" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fájl" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Kiírja a tömör útmutatót" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nem egy érvényes hely" #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "Ismeretlen" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Sorban" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Sorban" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "Véletlen" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "Véletlen" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "utolsó lejátszás" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "Ismétlés" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Ismétlés" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Egy dal" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Egy dal" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%d mp." #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nem leltem állomást" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "Mappa létrehozása sikertelen" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Név:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Pluginok" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Kezd..." #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Idő" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Könyvjelző név" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "PP:MM" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Könyvjelzők" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "Szűrők" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "Soha _nem játszott" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 legmenőbb" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Új állomás" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Véletlen _műfaj" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Véletlen _szerző/előadó" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Véletlen _album" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "A legtöbbet lejátszott 40 dal (csomókban több is kijelölhető)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Név:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "Érték:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Mentett értékek" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Mentett értékek szerkesztése..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "_Sáv fejlécek" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "_Album fejlécek" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Fájlok átnevezése" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Ismeretlen" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "Fájl hozzá_adása..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "Kijelző sz_erkesztése..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Szűrő egy tag értéken" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Hang tag szerkesztő" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Fájlok" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Fájlok törlése" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mozgatás a kukába" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "%d/%d mozgatása" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "iPod adatbázis mentése sikertelen" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "<b>%s</b> kinyitása sikertelen" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "%d/%d törlése" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Fájl törlése sikertelen" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "<b>%s</b> törlése sikertelen" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Böngészők" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Fájlok letöltése" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "hiányzik %d dalból" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "eltér %d dal közt" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Több értékre szedés" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "_Album és lemez elválasztása" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "_Verzió és cím elválasztása" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "A hangszerelőt és a többi Művészt ne mossuk egybe !" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Az előadót és a többi Művészt ne mossuk egybe !" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Az előadót és a többi Művészt ne mossuk egybe !" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "_Verzió és cím elválasztása" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Tag hozzáadása" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "_Programozható tagok mutatása" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "_Programozható tagok mutatása" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Soha" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "Tovább" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Tag szerkesztés" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "_Album borítók másolása" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Tag hozzáadása sikertelen" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Dalok hozzáadása sikertelen" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "<b>%s</b> hozzáadása sikertelen\n" "\n" "A kijelölt fájlok nem támogatnak többszörös értékeket." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Rossz tag" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Rossz tag <b>%s</b>\n" "\n" "A kijelölt fájlok nem támogatják e tag szerkesztését." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Rossz érték" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Hibás érték: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "A tag pontatlannak hat" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> változott a program futása alatt. A daltár frissítése nélküli " "mentés felülírhatja e dal más változásait.\n" "\n" "Mégis mentes e dalt?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Dal mentése sikertelen" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "<b>%s</b> mentése sikertelen. Lehet, hogy a fájl csak-olvasható, hibás, vagy " "nincs jogod szerkeszteni." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "Több lehetőség..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Pluginok" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s és %(count)d még" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso jellemzők" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mappák" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Új mappa" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Alkönyvtárak kijelölé_se" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Új mappa" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Adj nevet az új mappának:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Mappa létrehozása sikertelen" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Mappa törlése sikertelen" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Dalok" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "by %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "%s lemez" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "%s szám" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Kijelző szerkesztése" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nincs kijelölt dal" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nincs dal" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Információ" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Szövegek" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Készítette: %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "művész" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "művészek" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "előadók" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Soha" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%dx" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "hozzáadva" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "utolsó lejátszás" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "lejátszás" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "kihagyás" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "érték" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "hossz" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Információ" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[Hibás kódolás]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitarány" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "fájlméret" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "módosítva" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d kijelölt" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Elérhetetlen szám" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d dal nem tartozik albumhoz" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Kijelölt diszkográfia" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d dalhoz nincs szerző" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumok" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Összhossz:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Összméret:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Fájlok" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nincs szöveg ehhez a dalhoz." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Tag cserék elvetése?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "A tagok változtak, de nincsenek elmentve. Mented e fájlokat, vagy elveted a " "változtatásokat?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Soha" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "A fájl létezik" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Fájlok átnevezése" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Lejátszás/szünet váltása" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Lejátszás/szünet váltása" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "S_orrend:" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Tag szerkesztés" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "Átnevez" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "lekérés" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Összméret:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plugin hibák" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "Böngésző kikapcsolása" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Beillesztések nem találhatók" #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Pluginok" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Hibák mutatása" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Lemez" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Szám" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "csoport" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Művész" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Album" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Fájlnév" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Hossz" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Automatikus ugrás a forgó dalra" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "A dal váltásakor a lista görgetése" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "Más_ok:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "Kijelző sz_erkesztése..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Látható oszlopok" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "_Verzió a címben" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "_Verzió a címben" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Mappa a _fájlnévben" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Jellemzők" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Látható oszlopok" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dal lista" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Látható oszlopok" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globális szűrő:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Keres" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Böngészők" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "A dal váltásakor a lista görgetése" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 #, fuzzy msgid "Ratings" msgstr "É_rték" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Album lista" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Lejátszás szünete" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "É_rték" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Értékekhez és lejátszásokhoz beállítandó email cím" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Tag cserék elvetése?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Vágás így:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Vágás így:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Tag szerkesztés" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tag szerkesztés" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "Új állomás" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "Daltár kere_sése" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Változások átnézése a daltárban" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Daltár újratö_ltése" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Minden dal újratöltése a daltárban (sokáig tarthat)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Nincs dal" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "Daltár _frissítése" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Könyvtárak átnézése" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, fuzzy, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s és %(count)d még" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Tulajdonságok" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "Lejátszósor" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "Hibák tisztitása" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Minden dal törlése a sorból" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modell:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d dal (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Daltár _böngészése" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Főablak mutatásának váltása" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Lejátszás szünete" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Könyvtárak kijelölése" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Dalok hozzáadása sikertelen" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> nem támogatott protokollt használ" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Ugrás a lejátszásra" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Fájl" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Dalok" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Nézet" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Böngészők" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Vezérlés" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Súgó" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "Mappa hozzá_adása..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "Fájl hozzá_adása..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Hely hozzáadása" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "Könyvjelzők sz_erkesztése..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Stop e szám után" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Keres" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Hely hozzáadása" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Add meg egy hang fájl helyét:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Hely hozzáadása sikertelen" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nem egy érvényes hely" #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Zene hozzáadása" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "Mappa hozzá_adása..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Zenelejátszó" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "Fájl hozzá_adása..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "Lejátszósor" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "É_rték" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "É_rték" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Szóközök helyett aláhúzások !" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "w$-inkompatibilis jeleket mellőz" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Mellékjelek ki" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Nem-_ASCII karakterek ki" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Fájlok átnevezése" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "Előnézet" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Fájlnév" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "album művész" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "Nem használt borítók és mappák törlése" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Album lista" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Új név" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Fájl átnevezése sikertelen" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "<b>%s</b> átnevezése erre: <b>%s</b> sikertelen. A cél fájl talán létezik, " "nincs jogod az új fájl létrehozására vagy a régi törlésére." #: quodlibet/qltk/renamefiles.py:346 #, fuzzy msgid "Ignore _All Errors" msgstr "Hibák mutatása" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "Tovább" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Az ösvény nem abszolút" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "A minta\n" "\t<b>%s</b>\n" "tartalmaz /-t de nem indul gyökértől. Könyvtárnév-tévesztés ellen, adj " "gyökeret a mintának /-rel vagy ~/-rel kezdéssel." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "E mappákban levő dalok (':'-tal elválasztva) a daltárhoz adódnak" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "F: elavult iPod sáv eltávolítása" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Daltár" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "É_rték" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Könyvtárak kijelölése" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Könyvtárak kijelölése" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Mentett értékek" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Mentett értékek szerkesztése..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "Stop e szám után" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "Kor_lát:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "Súly" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "lekérés" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Maradék idő kiírása" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Szövegek" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Fókusz a futó lejátszóra" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Ugrás a forgó dalban" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Dalok törlése meghiúsult" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Dalok törlése meghiúsult" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "Szűrő itt: %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "_Album fejlécek" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Sáv fejlécek" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Album fejlécek" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Személ_y fejlécek" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Dátum fejlécek" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Fájl fejlécek" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Termék fejlécek" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Egyéni fejlécek..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Tö_rlés a listáról" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Tö_rlés a listáról" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "Tö_rlés a listáról" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Színes kere_ső kifejezések" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Sorhoz adás" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "Tö_rlés a listáról" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Fájl törlése sikertelen" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "Letöltés" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Keres" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Fájl letöltése" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Album lista" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Fájl letöltése" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Aláhúzások helyett szóköz" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Cím szerinti tagok" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Több értékre _vágás" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tagok az ösvényből" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Létezőket cserélő tagok" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Létezőkhöz adandó tagok" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "A minta\n" "\t<b>%s</b>\n" "rossz. Talán ugyanaz a tag 2x vagy páratlan zárójelek vannak benne (< / " ">)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "A minta rossz. A < és > legyen \\< és \\> és legyenek párban.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Kijelző szerkesztése" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Számok száma" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Indítás innen:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Összes szám:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Lejátszó" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "Előnézet" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "és még %d..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Módosított dalok mentése" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "%d/%d mozgatása" #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Csatolási pontok ellenőrzése" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "hely" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Listák importálása" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Már van egy %s nevű lista" #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Album borítók mutatása" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Fájlrendszer" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Összméret:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Kiírja a tömör útmutatót" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Kiírja a verziót és a szerzői jogokat" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Nincs idő adat" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[lehetőségek]" #: quodlibet/util/__init__.py:167 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: '%s' nem ismert lehetőség." #: quodlibet/util/__init__.py:170 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: '%s' egy argumentumot vár." #: quodlibet/util/__init__.py:173 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' nem egyedi előtag." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d mp." #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Nincs idő adat" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d mp." #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d perc" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d óra" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d nap" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d év" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "cím-nagybetű" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "A dátumot 'ÉÉÉÉ', 'ÉÉÉÉ-HH-NN' vagy 'ÉÉÉÉ-HH-NN ÓÓ:PP:MM' formában kell " "bevinni." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "A MusicBrainz ID-knek UUID formátumúaknak kell lenniük" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "A MusicBrainz kiadási állapot 'official', 'promotional' vagy 'bootleg' kell " "legyen" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "<b>%s</b> kinyitása sikertelen" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "A dal szerkesztése sikertelen" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "<b>%s</b> mentése sikertelen. Lehet, hogy a fájl csak-olvasható, hibás, vagy " "nincs jogod szerkeszteni." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Hibás kódolás]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "hangszerelő" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "hangszerelők" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "hangszerelő" #: quodlibet/util/tags.py:86 msgid "author" msgstr "szerző" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "szerzők" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "tag" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "zeneszerző" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "zeneszerzők" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "zeneszerző" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "karmester" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "karmesterek" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "karmester" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kapcsolat" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "dátum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "leírás" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "műfaj" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "műfaj" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "előadó" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "előadó" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "csoport" #: quodlibet/util/tags.py:98 msgid "language" msgstr "nyelv" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licenc" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "szövegíró" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "szövegírók" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "szövegíró" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "szervezet" #: quodlibet/util/tags.py:104 msgid "title" msgstr "cím" #: quodlibet/util/tags.py:105 msgid "version" msgstr "verzió" #: quodlibet/util/tags.py:106 msgid "website" msgstr "weblap" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "album művész" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "lemez" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "szám" # label ID #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "címke ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "eredeti kiadási dátum" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "eredeti album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "eredeti művész" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "rögzítési dátum" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "megjelenés országa" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz album állapot" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz album típus" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "szám csúcs" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album csúcs" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Jellemzők" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "lemezek" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "számok" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "utolsó indítás" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "pontos elérés" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "csatolási pont" #: quodlibet/util/tags.py:166 msgid "people" msgstr "személyek" #: quodlibet/util/tags.py:168 msgid "year" msgstr "év" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "eredeti kiadási dátum" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "Könyvjelzők" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "formátum" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Listák" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Hang tag szerkesztő" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Tagok szerkesztése hangfájljaidban" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Quod Libet bezárása" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Zenelejátszó" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Hallgasd, böngészd vagy szerkeszd zenéidet" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Listák importálása" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Dal hozzáadása sikertelen" #~ msgid "Invalid tags" #~ msgstr "Érvénytelen tagok" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Érvénytelen tagok <b>%s</b>\n" #~ "\n" #~ "A kijelölt fájlok nem támogatják e tagok szerkesztését." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d mp." #, fuzzy #~ msgid "Startup" #~ msgstr "_Import" #~ msgid "Audio Feeds" #~ msgstr "Hangforrások" #~ msgid "_Audio Feeds" #~ msgstr "H_angforrások" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Szöveg keresése..." #, fuzzy #~ msgid "<artist>" #~ msgstr "művész" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "cím" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Listák importálása" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Listák importálása" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Információ" #~ msgid "Unsupported file type" #~ msgstr "Nem támogatott fájl típus" #~ msgid "Unable to add station" #~ msgstr "Állomás hozzáadása sikertelen" #~ msgid "Device Properties" #~ msgstr "Eszköz Tulajdonságok" #~ msgid "Device:" #~ msgstr "Eszköz:" #~ msgid "Not mounted" #~ msgstr "Nincs csatolva" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Csatolási pont:" #~ msgid "Media Devices" #~ msgstr "Média eszközök" #~ msgid "_Media Devices" #~ msgstr "_Média eszközök" #~ msgid "_Eject" #~ msgstr "Kiad" #, fuzzy #~ msgid "_Properties" #~ msgstr "Tulajdonságok" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> használt, <b>%s</b> elérhető" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "<b>%s</b> másolása" #~ msgid "Unable to copy song" #~ msgstr "Dal másolása sikertelen" #~ msgid "There is not enough free space for this song." #~ msgstr "Nincs elég hely e dalhoz" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> másolása sikertelen" #~ msgid "Unable to delete songs" #~ msgstr "Dalok törlése meghiúsult" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "<b>%s</b> törlése" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> törlése sikertelen" #~ msgid "Unable to delete song" #~ msgstr "A dal törlése sikertelen" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "<b>%s</b> kinyitása sikertelen" #~ msgid "Unable to eject device" #~ msgstr "Nem tudom kinyitni az eszközt" #~ msgid "Search Library" #~ msgstr "Daltár keresése" #~ msgid "_Search Library" #~ msgstr "Daltár kere_sése" #~ msgid "Rate the playing song" #~ msgstr "E dal értéke" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Fő dal lista mutatása/rejtése" #~ msgid "Unknown Device" #~ msgstr "Ismeretlen eszköz" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: '%s' nem egyedi előtag." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Rossz érték" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Fájlnév minta:" #, fuzzy #~ msgid "_Clear" #~ msgstr "Hibák tisztitása" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Szövegek" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Keresés törlése" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Szövegek" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Szövegek" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Nincs dal" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Böngészők" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Mappa létrehozása sikertelen" #~ msgid "Audio device: %s" #~ msgstr "Hang eszköz: %s" #~ msgid "Downloads" #~ msgstr "Letöltések" #~ msgid "Size" #~ msgstr "Méret" #~ msgid "_Download" #~ msgstr "Letöltés" #~ msgid "_Copy to Device" #~ msgstr "Eszközre másolás" #, fuzzy #~ msgid "browsers" #~ msgstr "Böngészők" #~ msgid "Unable to download lyrics." #~ msgstr "Szöveg letöltése sikertelen" #~ msgid "Set or toggle the playback order" #~ msgstr "Sorrend beállítása/váltása" #~ msgid "Uninitialized iPod" #~ msgstr "Iniciálatlan iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Készítesz egy üres adatbázist ezen az iPod-on?" #~ msgid "Combine tags with _multiple values" #~ msgstr "Tagok egyesítése több értékkel" #~ msgid "Capacity:" #~ msgstr "Kapacitás:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "iPod adatbázis mentése sikertelen" #~ msgid "Unable to save iPod database" #~ msgstr "iPod adatbázis mentése sikertelen" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "szám csúcs" #~ msgid "Shuffle" #~ msgstr "Shuffle" #~ msgid "Weighted" #~ msgstr "Weighted" #~ msgid "_Weighted" #~ msgstr "Súlyozott" #~ msgid "_One Song" #~ msgstr "_Egy dal" #~ msgid "Restart the playlist when finished" #~ msgstr "Lista újraindítása befejezéskor" #~ msgid "Disable Browser" #~ msgstr "Böngésző kikapcsolása" #~ msgid "_Disable Browser" #~ msgstr "Böngésző kikapcsolása" #, fuzzy #~ msgid "Force Write" #~ msgstr "Ír" #~ msgid "Filter on _Genre" #~ msgstr "Szűrő a _műfajon" #~ msgid "Filter on _Artist" #~ msgstr "Szűrő a _szerzőn/előadón" #~ msgid "Filter on Al_bum" #~ msgstr "Szűrő az _albumon" #~ msgid "_Music" #~ msgstr "_Zene" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Könyvjelzők" #~ msgid "Song _List" #~ msgstr "Dal _lista" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Stop e szám után" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "és még %d..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "_Album és lemez elválasztása" #, fuzzy #~ msgid "Timeout" #~ msgstr "Idő" #, fuzzy #~ msgid "Select an album" #~ msgstr "Mindent kijelöl" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s és %(count)d még" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Listák" #~ msgid "Re_fresh Library" #~ msgstr "Daltár _frissítése" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "É_rték" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Rossz érték" #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "fájlnév" #~ msgid "command|tag" #~ msgstr "tag" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Keres" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Használat: %s %s" #~ msgid "_Download..." #~ msgstr "Letöltés..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "Új állomás" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Felülírod: <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "A Quod Libet már fut." #~ msgid "No song is currently playing." #~ msgstr "Nem fut dal." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "%s írása sikertelen. Eltávolítom." #~ msgid "_Edit Bookmarks..." #~ msgstr "Könyvjelzők sz_erkesztése..." #~ msgid "_New Folder..." #~ msgstr "Ú_j mappa..." #~ msgid "_Add to Playlist" #~ msgstr "Listához _adás" #~ msgid "_Edit Display..." #~ msgstr "Kijelző sz_erkesztése..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d állomás" #~ msgid "_Add a Location..." #~ msgstr "Hely hozzá_adása..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Egyéni fejlécek..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Sáv fejlécek" #, fuzzy #~ msgid "People Headers" #~ msgstr "Személ_y fejlécek" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Album fejlécek" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Dátum fejlécek" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Fájl fejlécek" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Termék fejlécek" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tag:" #, fuzzy #~ msgid "Warnings" #~ msgstr "É_rték" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "album művész" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "művészek" #, fuzzy #~ msgid "album (sort)" #~ msgstr "album művész" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "előadók" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "előadók" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album művész ID" #~ msgid "errors" #~ msgstr "hibák" #~ msgid "Permanently delete this file?" #~ msgstr "Végleg törlöd e fájlt?" #~ msgid "Permanently delete these files?" #~ msgstr "Végleg törlöd e fájlokat?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s és %(count)d még..." #, fuzzy #~ msgid "Version:" #~ msgstr "verzió" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "Hibák tisztitása" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s-t nem tudtam hozzáadni a daltárhoz.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Nem találtam 'eject' parancsot" #~ msgid "Unable to start web browser" #~ msgstr "Web böngésző indítása sikertelen" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Nem lelek web böngészőt. Állítsd be a $BROWSER változót, vagy nézd meg, " #~ "létezik-e /usr/bin/sensible-browser." #, fuzzy #~ msgid "Library Error" #~ msgstr "Daltár böngésző" #, fuzzy #~ msgid "_Output device:" #~ msgstr "Eszközre másolás" #~ msgid "translator-credits" #~ msgstr "sas," #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Más látható oszlopok szóközökkel elválasztva" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "Tovább" #~ msgid "Search your library" #~ msgstr "Daltár keresése" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, és mások\n" #~ "\n" #~ "Ez szbaf szoftver; lásd a forrást a másolási feltételekért. NINCS\n" #~ "garancia; sem az ELADHATÓSÁGRA sem az EGYES CÉLRA VALÓ MEGFELELÉSRE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Összméret:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet Pluginok" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "Egyszerű keresések kékkel, haladók zölddel, érvénytelenek pirossal" #~ msgid "Separators for splitting tags" #~ msgstr "Tagok elválasztói" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet beállítások" #~ msgid "Not Played To_day" #~ msgstr "_Ma még nem játszott" #~ msgid "Not Played in a _Week" #~ msgstr "1 hé_ten belül nem játszott" #~ msgid "Not Played in a _Month" #~ msgstr "1 _hónapon belül nem játszott" #~ msgid "B_ottom 40" #~ msgstr "40 legritkább" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "A legutóbb lejátszott 40 dal (csomókban több is kijelölhető)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | vezérlő ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Dátum" #~ msgid "Add" #~ msgstr "Hozzáad" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitarány" #~ msgid "_Stations..." #~ msgstr "Állomá_sok..." #~ msgid "Unable to save library" #~ msgstr "Daltár mentése sikertelen" #~ msgid "Sort by title" #~ msgstr "Rendezés cím szerint" #~ msgid "Sort by artist" #~ msgstr "Rendezés művész szerint" #~ msgid "Lyrics provided by %s." #~ msgstr "A szöveg forrása: %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Nincs szöveg ehhez a hangfájlhoz.\n" #~ "\n" #~ "A Letöltés gombbal a Quod Libet rákereshet a hálózaton. Kézzel is be " #~ "lehet vinni, majd a mentés gombra kattintani." #~ msgid "part" #~ msgstr "rész" #~ msgid "Opening audio device." #~ msgstr "Hang eszköz megnyitása." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d dal elmentve" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album ID" #~ msgid "Loaded song library." #~ msgstr "Daltár betöltve." #~ msgid "Unable to open audio device" #~ msgstr "Hang eszköz megnyitása sikertelen" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "A Quod Libet megpróbálta elérni az 'autosink' és '%(sink)s' meghajtókat, " #~ "de nem tudta megnyitni. Állítsd be a GStreamer pipát a\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "sor cseréjével a ~/.quodlibet/config-ban." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "A Quod Libet nem leli a 'filesrc' GStreamer elemet. Ellenőrizd a " #~ "GStreamer telepítést." ������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/id.po����������������������������������������������������������������������������0000644�0001750�0001750�00000577636�14436352625�013617� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "PO-Revision-Date: 2022-11-15 13:48+0000\n" "Last-Translator: Neko Nekowazarashi <kodra@nekoweb.my.id>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/id/>\n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Weblate 4.15-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Judul" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Tanggal" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Tanggal Ditambahkan" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Tanggal Asli" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Peringkat" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Jumlah Pemutaran" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Urut _berdasarkan…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Preferensi" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Daftar Album" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Daftar Album" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Semua Album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Muat ulang _sampul album" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Lagu tidak di album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d trek lagu" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d cakram" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Sebuah Album Contoh" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferensi Daftar Album" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Tampilkan _sampul album" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Inline _search termasuk orang" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opsi" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Display Album" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Tutup" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Peramban Perpustakaan" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d lagu" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Pola tidak valid" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Koleksi Album" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Koleksi _Album" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Tidak diketahui %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Beberapa Nilai %s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Kustom" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Tambah" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Hapus" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tanda" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Gabung" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Preferensi Koleksi Album" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Terapkan" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Batal" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Grid Cover" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Grid Cover" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Preferensi Grid Cover" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Tampilkan teks _album" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Tampilkan \"Semua Album\" Item" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Mode Lebar" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Pembesaran Cover" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "File Sistem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_File Sistem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Tidak dapat menyalin lagu" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "File yang dipilih tidak dapat disalin ke daftar lagu lain atau antrean." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Tambahkan ke Perpustakaan" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Tambahkan stasiun" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Mengunduh daftar stasiun" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Stasiun Baru" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Masukkan lokasi stasiun radio internet:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronik" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 #, fuzzy msgid "Oldies" msgstr "Jadul" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Jepang" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "India" #: quodlibet/browsers/iradio.py:394 #, fuzzy msgid "Religious" msgstr "Agamis" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turki" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Radio Kampus" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Percakapan/Berita" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasik" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 #, fuzzy msgid "Alternative" msgstr "Alternatif" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Berita" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavik" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Apakah Anda mau untuk memuat daftar stasiun radio yang populer?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Muat Stasiun" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Radio _Internet" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Semua Stasiun" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favorit" #: quodlibet/browsers/iradio.py:598 #, fuzzy msgid "No Category" msgstr "Tidak Ada Kategori" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Tambah Stasiun…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Perbarui Stasiun" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Tidak ada stasiun yang ditemukan" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Tidak ada stasiun radio internet yang ditemukan di %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Semua stasiun yang didaftar sudah ada di pustaka Anda." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Tambahkan ke Favorit" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Hapus dari Favorit" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stasiun" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Pilih _Semua" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Tidak diketahui" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Semua" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Kecil" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Lebar" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Tata letak kolom" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Konten kolom" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Daftar putar" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Daftar putar" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Hapus dari Daftar Putar" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Baru" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Impor…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Tidak bisa mengimpor daftar putar" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet hanya bisa mengimpor daftar putar dalam format M3U/M3U8 dan PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Hapus" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Ubah Nama" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Tidak bisa mengubah nama daftar putar" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Impor Daftar Putar" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Impor" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "Daftar Putar _Baru…" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Apa yang Anda ingin lakukan pada lagu %d tersebut?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Konfirmasi tindakan untuk daftar putar \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "kosong" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Daftar Putar Contoh" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Tampilan daftar putar" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Apakah Anda yakin ingin menghapus daftar putar '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Semua informasi tentang daftar putar yang dipilih akan dihapus dan tidak " "bisa dipulihkan." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Trek Lagu" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Daftar Putar Baru" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Masukkan nama untuk daftar putar baru:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Buat" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Mengimpor daftar putar.\n" "\n" "%(current)d/%(total)d lagu ditambahkan." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Feed Baru" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Masukkan lokasi umpan audio:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Tambah Berkas…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Segarkan" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Tidak dapat menambahkan umpan" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s tidak dapat ditambahkan. Server mungkin sedang down, atau lokasi mungkin " "bukan merupakan audio feed." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Backend audio saat ini tidak mendukung URL, browser Audio Feeds " "dinonaktifkan." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Batasi Hasil" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Daftar Trek Lagu" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "Daftar _Trek Lagu" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Peramban Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Cari" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Trek Lagu Saya" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Pergi ke %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Terhubung" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet sekarang terhubung, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Keluar dari %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Masukkan kode…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Masuk ke %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Otorisasi Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Masukkan kode autentikasi Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "sebuah pemutar dan pustaka musik" #: quodlibet/cli.py:88 msgid "[option]" msgstr "" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Langsung putar segera" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Jangan tampilkan jendela apa pun pada pemulaian" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Mulai pemutaran" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Jeda pemutaran" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Setop pemutaran" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Besarkan volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Kecilkan volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Cetak status pemutaran" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Sembunyikan jendela utama" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Tampilkan jendela utama" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:113 #, fuzzy msgid "Refresh and rescan library" msgstr "Segarkan dan pindai ulang pustaka" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Daftar peramban yang tersedia" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Cetak daftar putar saat ini" #: quodlibet/cli.py:116 #, fuzzy msgid "Print the contents of the queue" msgstr "Cetak konten antrian" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "" #: quodlibet/cli.py:118 #, fuzzy msgid "Start without plugins" msgstr "Mulai tanpa plugin" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Mulai Quod Libet jika belum dimulai" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Keluar Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Atur volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Cari pustaka audio Anda" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "kueri" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Putar sebuah berkas" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "nama berkas" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Atur peramban saat ini" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Berhenti setelah lagu yang sedang diputar" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Buka peramban baru" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tanda" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nama berkas" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Tambahkan berkas atau direktori ke pustaka" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "lokasi" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "pola" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Coba %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Sebuah Galat Terjadi" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Anda bisa mengabaikan galat ini, tetapi aplikasi mungkin tidak stabil hingga " "dimulai ulang. Mengirimkan laporan galat hanya memakan sedikit waktu dan " "akan membantu banyak kami." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Kirim Laporan Galat" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Mulai Ulang" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Abaikan Galat" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Detail galat:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(opsional) Mohon berikan deskripsi singkat tentang apa yang terjadi saat " "galat terjadi:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Kirim" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Deskripsi singkat…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Data yang akan dikirim:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "penyunting tanda audio" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "direktori" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Penyunting metadata audio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL Sumber Sampul" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Sumber Sampul Discogz" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Unduh sampul dari Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Sumber Sampul Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Unduh sampul dari arsip sampul Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Sumber Sampul MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Unduh sampul dari arsip sampul MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Konversi Enkode" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Tidak bisa menemukan 'Kanji Kana Simple Inverter' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Pengganti Ekspresi Reguler" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Preferensi Lanjutan" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Perbolehkan penyuntingan pengaturan konfigurasi lanjutan." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Saya tahu apa yang saya lakukan" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Tampilkan informasi lagu di layar Anda ketika berubah." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Posisi:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Ukuran _Sampul:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Tampilan" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Fonta:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Kiri" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Tengah" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Kanan" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Teks" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Teks:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Warna" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "Ba_yangan" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Jeda:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efek" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Pratinjau" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informasi aplikasi" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Berbagai informasi tentang aplikasi dan lingkungannya." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Format yang Didukung" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Direktori Konfigurasi" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Direktori Tembolok" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Setiap setelah pemutaran (baku)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Setiap setelah pemutaran atau lanjutan" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Sekali, ketika album telah diperingkatkan semua" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Tidak bisa menulis '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Otomatis Perbarui Tanda di Berkas" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Ketika lagu sedang diputar, perbarui tandanya di berkas. Ini menjamin jumlah " "pemutaran dan peringkat terbaru." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Pengaturan diperbarui" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Galat di %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "Strategi _pembaruan:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Preferensi" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Peringkat Otomatis" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Impor Gagal" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Berhasil mengimpor peringkat dan statistik untuk %d lagu" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Impor Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Impor rating dan statistik lagu dari Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Jalur basis data:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Mulai Impor" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Jam Alarm" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Bangunkan Anda dengan musik keras." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Pesan status Discord" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Pesan Status Discord" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Ubah pesan status Discord Anda tergantung apa yang Anda sedang dengar." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Dijeda" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Baris Status #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Baris Status #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Datar" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Langsung" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Pesta" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Lembut" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 #, fuzzy msgid "Soft Rock" msgstr "Rock Pelan" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dansa" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Tekno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Pilih…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Hapus yang dipilih" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Simpan" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "daring" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "luring" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "obrolan" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "pergi" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "tak terlihat" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Pesan Status Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Ubah pesan status Gajim tergantung apa yang Anda sedang dengar." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "dijeda" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Pola:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Daftar akun, dipisahkan oleh spasi, untuk mengganti pesan status. Jika tidak " "ada yang disebutkan, pesan status untuk semua akun akan diubah." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Akun:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Tambah '[dijeda]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Jika dicentang, '[dijeda]' akan ditambahkan ke pesan status ketika sedang " "jeda" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Status di mana pesan akan diubah" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Pada desktop GNOME, ketika lagu diputar, mencegah antara screensaver aktif " "atau mencegah komputer mati." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musik sedang diputar" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Mode:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Log Radio Internet" #: quodlibet/ext/events/iradiolog.py:18 #, fuzzy msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Rekam 10 lagu terakhir yang diputar di stasiun radio, dan cantumkan mereka " "di menu konteks pencarian" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Ubah Bahasa" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Ubah bahasa tampilan antarmuka." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Bawaan Sistem" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Pemulaian ulang diperlukan untuk perubahan berefek" #: quodlibet/ext/events/mediaserver.py:36 #, fuzzy msgid "UPnP AV Media Server" msgstr "Peladen Media UPnP AV" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Pastikan baris berikut ada di berkas konfigurasi rygel Anda (~/.config/rygel." "conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Peladen MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Porta:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "IP _Lokal:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "Ka_ta Sandi:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Koneksi" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Klien Telah Dites" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Dukungan D-Bus MPRIS" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Sembunyikan jendela utama pada penutupan" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Baku ke localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Baku ke 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Topik" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Pola Pemutaran" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Teks status ketika lagu dimulai." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Pola Penjedaan" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Teks ketika lagu dijeda." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Teks saat tidak ada lagu" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Teks polos ketika tidak ada lagu yang diputar" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Konfigurasi MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Teks Status" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Koneksi gagal" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "Sinkronisasi MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Nama _pengguna:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Kata sandi:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Akun" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Teks notifikasi" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Judul:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Badan:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Tampilkan notifikasi" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Tampilkan notifikasi" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Tampilkan tombol \"_Selanjutnya\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Koneksi gagal" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Tidak bisa menyambung ke daemon notifikasi." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Pemberitahuan Lagu" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Tampilkan pemberitahuan ketika lagu berubah." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Selanjutnya" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Nama Markah" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Tidak dapat menghubungi layanan '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Layanan:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Lain-lain…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Mode _Luring (jangan mengirim apa pun)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Bisukan Iklan Radio" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Diputar lebih sering" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Dilanjutkan lebih sering" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Diputar baru-baru ini" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Dimulai baru-baru ini" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Ditambahkan baru-baru ini" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Album lebih panjang" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "detik sebelum memulai album selanjutnya" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "Berat" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Putar beberapa album lebih dari yang lainnya" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "hindari" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Album Acak" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Menunggu untuk memulai %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Impor Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Impor peringkat dan statistik lagu dari Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nama markah untuk poin A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nama markah untuk poin B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Sinkronisasi Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Berhenti pada Jeda" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Penyalinan tertunda" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Penghapusan tertunda" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "hapus" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Lanjut" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLIKAT" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Menyinkronisasi" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Menghapus" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Sukses" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "GAGAL" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Lanjut berkas yang telah ada" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Tidak dapat mengatur nama berkas lagu." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Sinkronisasi ke Perangkat" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Sinkronisasi semua lagu dari pencarian tersimpan yang dipilih dalam folder " "tertentu." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Jalur tujuan:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Pola Jalur" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Sunting pola tersimpan…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Ekspor pola:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Berkas Sumber" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Ekspor Jalur" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Mulai sinkronisasi" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Berhenti sinkronisasi" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Pilih jalur tujuan" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "hapus {count} berkas" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Tidak ada jalur tujuan yang diberikan" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 #, fuzzy msgid "No export pattern provided" msgstr "Tidak ada pola ekspor yang diberikan" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Pola\n" " <b>%s</b>\n" "mengandung / tapi tidak dimulai dari root. Untuk menghindarai salah " "menamakan folder, root-kan pola Anda dengan memulainya dengan / atau ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Ditemukan {} lagu untuk disinkronisasi" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Tidak bisa menyinkronisasi" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Memulai sinkronisasi lagu" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Sinkronisasi sedang dalam progres." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Sinkronisasi lagu selesai" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Memberhentikan sinkronisasi lagu" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Sinkronisasi diberhentikan." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Sinkronisasi telah selesai." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Berhentikan sinkronisasi lagu" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Menghapus \"{}\"" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Sinkronisasi telah:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "menulis {count}/{total} berkas" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(melewati {count} berkas yang telah ada)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "menghapus {count}/{total} berkas" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "gagal menyinkronkan {count} berkas" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Lirik Tersinkronisasi" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Teks:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Latar belakang:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Fonta" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Ukuran (piksel):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Diputar:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Dijeda:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Teks polos ketika tidak ada lagu yang diputar" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Tidak ada lagu:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "Pola Status" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Pengganti Tema" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Ubah tema GTK+" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Tema Baku" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Lebih sukai tema gelap" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 #, fuzzy msgid "Not playing" msgstr "Tidak ada pemutaran" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Tampilkan %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Putar" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "Je_da" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Se_belumnya" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Selanjutnya" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Acak" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Ulang" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Berhenti Setelah _Lagu Ini" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Buka _Peramban" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Sunting _Tanda" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informasi" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Daftar _Putar" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Keluar" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Lihat Lirik" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Tidak ada lirik yang ditemukan untuk\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Tidak ada lagu yang diputar" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Galat" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Memuat ulang" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Timpa warna depan:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Tampilkan posisi saat ini" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Penyimpan Gambar" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Berkas:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Batas:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Batas hingga filter diaktifkan" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "R_asio:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Rasio kompresi" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Baku" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Kustom" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Pengaturan kostum" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Hapus vokal utama dari audio." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Ekspor Daftar Putar ke Folder" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Ekspor" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Folder tujuan:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Pola nama berkas:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Tidak bisa mengekspor daftar putar" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Pastikan Anda memiliki akses tulis ke tujuan." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Pola nama berkas baku:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Ekspor ke Daftar Putar Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Galat mencari perangkat Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Galat mencari Sonos. Mohon periksa pengaturan" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Ekspor ke Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Ekspor daftar putar ke Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Nama daftar putar (akan menimpa yang ada)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Ekspor ke daftar putar Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Hapus Daftar Putar Duplikat" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Hapus entri duplikat di daftar putar." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Acak Daftar Putar" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Secara acak, acak daftar putar." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Ikuti Kursor" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Ikuti kursor" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Ikuti kursor" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Menunggu untuk memulai kelompok baru…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Pengelompokan tanda:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Jeda:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Jeda waktu dalam detik sebelum memulai grup berikutnya" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Atur ulang ke yang baku" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Kueri Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍️Gunakan ekspresi Python di kueri." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unik" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Tidak bisa menyambung ke %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nama hos:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Porta:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nama pengguna:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Kata sandi:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Jalur pustaka:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Peladen Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Debug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Peladen Squeezebox di {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Pilih pemutar Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Sunting gambar setelah menyimpan" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Nama _Berkas:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Gagal menyimpan" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Tidak bisa menyimpan \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Resolusi: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Ukuran: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Cari" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Mencari…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Selesai" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Unduh Sampul" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Unduh sampul album dari berbagai situs." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Sumber" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 ke ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Konversi tanda APEv2 Anda ke tanda ID3v2. Ini akan menghapus tanda APEv2 " "setelah pengonversian." #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "Ke Markah" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Kelola markah di berkas yang dipilih." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Sunting Markah…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Tidak Ada Markah" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nama Berkas" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Trek Lagu" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Judul" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artis" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "Ca_ri" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Hasil <i>(seret untuk menyusun ulang)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Terjadi galat. Mohon coba kembali." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Memuat hasil…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Tidak ada hasil yang ditemukan." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Konsol Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Konsol Python interaktif. Membuka jendela baru." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} untuk {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Unduh Sampul" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klasik" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Besar" #: quodlibet/ext/songsmenu/cover_download.py:161 #, fuzzy msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "HD Penuh" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 #, fuzzy msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Unduhan Sampul" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Tidak ada sampul yang ditemukan" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} piksel" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Ukuran pratinjau" #: quodlibet/ext/songsmenu/cover_download.py:344 #, fuzzy msgid "Save destination" msgstr "Tujuan penyimpanan" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Jika belum JPEG, konversi gambar ke JPEG kualitas tinggi dengan ukuran yang " "sama" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Simpan sebagai JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Perintah" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nama" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Nama dari perintah ini" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "perintah" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unik" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Perintah Kostum" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Sunting Perintah Kostum" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Tidak bisa menjalankan perintah kostum %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Kunci Duplikat" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Jumlah Pemutaran" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Loncat Penghitungan" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Beberapa Nilai %s" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Hapus semua gambar" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Pilih Gambar…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Atur Peringkat Pasti" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Kunci API Tidak Ada" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Minta kunci API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "Kun_ci API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Menganalisis" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Cari" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Tulis" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Rilis" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Tulis tanda MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Mode Album" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Membuat sidik jari:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detail" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Kirim" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Sidik jari:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Lagu untuk dikirimkan:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Mengirimkan sidik jari:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Mengirimkan…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Ekspor ke HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Ekspor daftar lagu yang dipilih ke HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Kirim ke iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Unggah lagu ke perangkat iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Tidak ada perangkat iFP yang ditemukan" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Tidak bisa menghubungi perangkat iFP Anda. Periksa bahwa perangkat tersebut " "nyala dan tercolok dan Anda memiliki ifp-line (http://ifp-driver.sf.net) " "terpasang." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Mengunggah %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Galat mengunggah" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Ekspor Data Pengguna" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Ekspor Tanda" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Impor/Ekspor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Informasi lebih lanjut" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Kesamaan trek lagu:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Kesamaan album:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Ekspor berkas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Hapus berkas ekspor setelah itu diimpor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Impor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Buka Direktori Ekspor" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Diska" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Trek Lagu" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artis" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 #, fuzzy msgid "End of path" msgstr "Akhir jalur" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Lanjut" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Tidak ada yang diimpor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Anda harus mengekspor sesuatu sebelum Anda bisa mengimpor." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Tidak bisa membaca %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Nama berkas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Telah terbaru." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Sinkronisasi selesai." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Sinkronisasi Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Nama pengguna:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Ekspor sebagai Berkas Daftar Putar M3U/PLS" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Ekspor lagu ke daftar putar M3U atau PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Pindai Ulang Lagu" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Pindai ulang lagu" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Trek Lagu" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Progres" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "selalu" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Atur Ulang" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Pencarian Web" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Cari Tanda di Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Cari di %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Sunting Tanda" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Pencarian gagal" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Tanda \"%s\" tidak ditemukan." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Pustaka" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Memindai pustaka" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Memindai %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Memuat berkas" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Deskripsi" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Sunting tanda di penyunting teks" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Hapus tanda" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Hapus semua tanda" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Daftar informasi berkas" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Gagal memuat berkas gambar: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Ubah nama berkas berdasarkan pada tanda" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Berkas" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Tampilkan informasi bantuan" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "Tidak _diketahui" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Acak" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Acak" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Ulangi trek lagu ini" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Ulangi _trek lagu ini" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Ulang semua" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Ulang _semua" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Satu _lagu" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Siarkan" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Tidak ditemukan elemen GStreamer untuk menangani format media" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Format media: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Plugin GStreamer '%(name)s' tidak dapat diinisialisasi" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Gunakan JACK untuk pemutaran jika tersedia" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Token _pengguna:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "Ta_nda:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Jalankan Plugin" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Penggunaan" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Waktu" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nama Markah" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Markah" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Semua _Lagu" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nama:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Oto_matis" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Mode _Trek Lagu" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Bisu" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "%s baru" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(tidak diketahui)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Tambah…" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Sunting…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "_Sunting gambar setelah menyimpan" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Berkas:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Hapus Berkas" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Pindahkan ke Tong Sampah" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Memindahkan %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Tidak bisa memindahkan ke tong sampah" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Gagal memindahkan satu atau lebih berkas ke tong sampah." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Menghapus %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Tidak bisa menghapus berkas" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Gagal menghapus satu atau lebih berkas." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Peramban" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Mengunduh berkas" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Tambahkan tanda" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tanda:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Simpan" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Konfigurasi" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Tidak bisa menambahkan tanda" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Tidak bisa menambahkan tanda" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Tanda tidak valid" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Tidak bisa menyimpan lagu" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Urung" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Tentang" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Periksa Pembaruan.…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Folder" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Folder Baru…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Pilih semua sub-folder" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Folder Baru" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Tidak bisa membuat folder" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Tidak bisa menghapus folder" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Lagu" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, fuzzy, python-format msgid "by %s" msgstr "oleh %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Trek lagu %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Lagu _Saat Ini" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Tidak ada lagu yang dipilih." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Tidak Ada Lagu" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informasi" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Lirik" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artis" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Tidak Pernah" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "ditambahkan" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "terakhir diputar" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "putar" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "lanjut" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "peringkat" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "jalur" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "panjang" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "enkode" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "ukuran berkas" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d dipilih" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Trek lagu tidak tersedia" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Total panjang:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Total ukuran:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Berkas" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Lihat secara daring" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Tidak ditemukan lirik untuk lagu ini." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Apakah Anda yakin ingin menghapus semua lagu?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Urung" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Berkas telah ada" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Ganti Berkas" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Menyunting" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Sampul" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Tidak ada kategori" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Kategori Apa Pun" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Tampilkan _Galat" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Diska" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "T_rek Lagu" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artis" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Nama Berkas" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Panjang" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Lain-lain:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Sunting…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "_Perbarui Stasiun" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Daftar Lagu" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Sunting Kolom" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Cari" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Peramban" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Peringkat" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Pemutaran" #: quodlibet/qltk/prefs.py:400 #, fuzzy msgid "Output Configuration" msgstr "Konfigurasi Keluaran" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Surel:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tanda" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Penyunting Tanda" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Pindai Pustaka" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Periksa perubahan pada pustaka Anda" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Lagu Tersembunyi" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Pindai pustaka _pada pemulaian" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Pindai Direktori" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Properti" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Mode" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Berhenti pada Akhir" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Jelajah Pustaka" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "Jangan _Sekarang" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Atur" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Loncat ke Lagu yang sedang Diputar" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Berkas" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Lagu" #: quodlibet/qltk/quodlibetwindow.py:893 #, fuzzy msgid "_View" msgstr "_Tampilan" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Jelajah" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Kontrol" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Bantuan" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Tambah Folder…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Tambah Berkas…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Tambah Lokasi…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Sunting Markah…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Berhenti" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Berhenti Setelah Lagu Ini" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Pintasan _Papan Tik" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Bantuan Daring" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Bantuan Pencarian" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Tambah Lokasi" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Masukkan lokasi dari berkas audio:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Tidak bisa menambahkan lokasi" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s bukan lokasi yang valid." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Tambah Musik" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Tambah Folder" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Berkas Musik" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Tambah Berkas" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Apakah Anda yakin ingin menghapus semua lagu?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "" #: quodlibet/qltk/ratingsmenu.py:26 #, fuzzy, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Apakah Anda yakin ingin mengganti peringkat untuk semua lagu %d?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Peringkat yang disimpan akan dihapus" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Hapus Peringkat" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Peringkat semua lagu yang dipilih akan diganti menjadi %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Ubah _Peringkat" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Gunakan hanya karakter huruf _kecil" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Ubah Nama Berkas" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Pratinjau" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Nama berkas" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nama Baru" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Tidak bisa mengubah nama berkas" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Abaikan _Semua Galat" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Berhenti" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Lanjut" #: quodlibet/qltk/renamefiles.py:463 #, fuzzy msgid "Path is not absolute" msgstr "Jalur tidak pasti" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Pola\n" " <b>%s</b>\n" "mengandung / tapi tidak dimulai dari root. Untuk menghindarai salah " "menamakan folder, root-kan pola Anda dengan memulainya dengan / atau ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Lagu di folder yang didaftar akan ditambahkan ke pustaka ketika penyegaran " "pustaka" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Direktori baru akan dipindai setelah ditambahkan" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Semua lagu di direktori yang dipilih akan dihapus juga dari pustaka" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Pindah" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Hapus {dir!r} dan seluruh jejaknya?" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Hapus jalur pustaka {n} dan jejaknya?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Hapus jalur pustaka?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Hapus" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Pilih Direktori" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Pilih Direktori Ini" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Ini akan memindahkan metadata QL:\n" "\n" "{old!r} → {new!r}\n" "\n" "Berkas audio tidak akan dipindah dengan ini.\n" "Meskipun begitu, cadangan disarankan (termasuk berkas 'songs' Quod Libet)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "OK, pindahkan!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Pencarian Tersimpan" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Sunting pencarian tersimpan…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Cari pustaka Anda, menggunakan teks bebas atau kueri QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Cari setelah _mengetik" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Tampilkan hasil pencarian setelah pengguna berhenti mengetik" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Batas:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Beban" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Tambahkan kueri" #: quodlibet/qltk/searchbar.py:357 #, fuzzy msgid "Add a QL query or free text to be &ed together" msgstr "Tambahkan kueri QL atau teks bebas untuk menjadi &ed bersama-sama" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Tampilkan waktu yang tersisa" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Jendela Utama" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Fokuskan entri pencarian" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Atur ulang filter dan loncat ke lagu yang sedang diputar" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Buka jendela informasi untuk lagu yang dipilih" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Buka penyunting tanda untuk lagu yang dipilih" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Antrikan lagu yang dipilih" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Hapus lagu yang dipilih" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Tampilan Pohon" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Hapus dari Pustaka" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Hapus dari Pustaka…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Tidak bisa menampilkan berkas" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Unduh %(total)d berkas…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "berhasil" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "gagal" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Selesai mengunduh" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Unduh di sini" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Putar/Jeda" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Sebelumnya" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "dan %d lebih lagi…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Menyimpan lagu yang Anda ubah." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Memeriksa Pembaruan" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Koneksi gagal" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Anda telah menggunakan versi terbaru %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Daftar Putar Kosong" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Daftar putar harus memiliki nama" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Daftar putar dengan nama %(name)s sudah ada pada %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Sampul" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Tampilkan versi dan hak cipta" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Cetak informasi pengawakutuan" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "" #: quodlibet/util/__init__.py:353 #, fuzzy, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s detik" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Tidak ada informasi jam" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d detik" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d menit" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d jam" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d hari" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d tahun" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Gagal menyimpan" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Tidak bisa menyunting lagu" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "" #: quodlibet/util/tags.py:86 msgid "author" msgstr "pembuat" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "pembuat" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "komentar" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "konduktor" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "konduktor" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontak" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "hak cipta" #: quodlibet/util/tags.py:93 msgid "date" msgstr "tanggal" #: quodlibet/util/tags.py:94 msgid "description" msgstr "deskripsi" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "genre" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "pengelompokan" #: quodlibet/util/tags.py:98 msgid "language" msgstr "bahasa" #: quodlibet/util/tags.py:99 msgid "license" msgstr "lisensi" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "penulis lirik" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "penulis lirik" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "lirik" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "penerbit" #: quodlibet/util/tags.py:104 msgid "title" msgstr "judul" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versi" #: quodlibet/util/tags.py:106 msgid "website" msgstr "situs web" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "album artis" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "trek lagu" #: quodlibet/util/tags.py:116 #, fuzzy msgid "label ID" msgstr "ID label" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "tanggal rilis orisinal" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "album asli" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artis asli" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "tanggal perekaman" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "negara perilisan" #: quodlibet/util/tags.py:122 #, fuzzy msgid "initial key" msgstr "kunci awal" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "ID rilis trek lagu MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Status album MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Jenis album MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "trek lagu" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "" #: quodlibet/util/tags.py:157 #, fuzzy msgid "full name" msgstr "nama penuh" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "" #: quodlibet/util/tags.py:166 msgid "people" msgstr "" #: quodlibet/util/tags.py:168 msgid "year" msgstr "tahun" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "tahun rilis orisinal" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "markah" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "format berkas" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "daftar putar" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "urut" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Penyunting tanda audio" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Sunting tanda di berkas audio Anda" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Pemutar Musik" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Dengar, jelajah, atau sunting koleksi audio Anda" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Format berkas yang didukung termasuk Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, " "MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet adalah program pengelola musik. Program ini memberikan beberapa " "cara untuk melihat pustaka audio Anda, serta dukungan untuk radio internet " "dan umpan audio. Memiliki kemampuan mencari dan menyunting tanda metadata " "yang fleksibel." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Ekspor sebuah daftar putar ke daftar putar Sonos, asalkan keduanya " #~ "memiliki struktur direktori yang sama." #~ msgid "Export to Sonos playlist" #~ msgstr "Ekspor ke daftar putar Sonos" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Tidak bisa menambahkan <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Tanda tidak valid" #~ msgid "Audio Feeds" #~ msgstr "Umpan Audio" #~ msgid "_Audio Feeds" #~ msgstr "_Umpan Audio" #~ msgid "New" #~ msgstr "Baru" ��������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/it.po����������������������������������������������������������������������������0000644�0001750�0001750�00000764320�14436352625�013623� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# ITALIAN TRANSLATION FOR QUODLIBET. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # felipe <filippo@email.it>, 2005. # Albano Battistella <albano_battistella@hotmail.com>, 2021. msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.22\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/it/>\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.9-dev\n" "X-Poedit-Bookmarks: 251,253,873,851,-1,-1,-1,-1,-1,1260\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titolo" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "persone" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Intestazione della _data" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "artista originale" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genere" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Giudizio" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Conteggio ri_produzioni" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Ordina _per…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Preferenze" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista degli album" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Lista degli album" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Tutti gli album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Ricarica le _copertine dell'album" msgstr[1] "Ricarica le _copertine degli album" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Brani non in un album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d traccia" msgstr[1] "%d tracce" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disco" msgstr[1] "%d dischi" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Un album di esempio" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferenze lista album" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Mostra le _copertine degli album" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "La ricerca in linea include le persone" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opzioni" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Visualizzazione album" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Chiudi" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navigatore libreria" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d brano" msgstr[1] "%d brani" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Modello non valido" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Collezione album" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Colle_zione album" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "%s sconosciuto/i" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Valori %s multipli" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizzato" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Aggiungi" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Rimuovi" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Unisci" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Preferenze della collezione di album" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Applica" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Annulla" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Griglia copertine" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Griglia copertine" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Preferenze della griglia copertine" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Mostra _testo album" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Mostra voce \"Tutti gli album\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Modalità ampia" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Ingrandimento copertina" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "File system" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "File s_ystem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Impossibile copiare i brani" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "I file selezionati non possono essere copiati ad altre liste o alla coda" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Aggiungi alla libreria" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Le liste di stazioni possono contenere solo indirizzi di stazioni, non altre " "liste di stazioni o scalette. I seguenti indirizzi non sono stati aggiunti:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Tutte le stazioni" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Scarica lista stazioni" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nuova stazione" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Inserire l'indirizzo di una stazione radio Internet" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elettronica" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Vecchie glorie" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Giapponese" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indiana" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religioso" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Classifiche" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latino americana" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Conversazione / Notizie" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambiente" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Classica" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Notizie" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slava" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Greca" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotica" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Vuoi caricare una lista di stazioni radio popolare?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Carica stazioni" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Radio _Internet" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Tutte le stazioni" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Preferiti" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Nessuna categoria" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nuova stazione…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Aggiorna stazioni" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nessuna stazione trovata" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nessuna stazione radio Internet trovata su %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Tutte le stazioni elencate sono già nella tua libreria." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Aggiungi ai pre_feriti" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Rimuovi dai pre_feriti" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stazione" msgstr[1] "%(count)d stazioni" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Navigatore a pannelli" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Navigatore a _pannelli" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Selezion_a tutto" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Sconosciuto" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Tutti" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Piccolo" #: quodlibet/browsers/paned/prefs.py:42 #, fuzzy msgid "Wide" msgstr "Modalità ampia" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Layout colonne" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Modello di tag con markup opzionale es. <tt>composer</tt> o \n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferenze del navigatore a pannelli" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Layout colonne" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Contenuto colonne" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Larghezza uguale del pannello" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Scalette" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Scalette" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Rimuovi dalla scaletta" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nuovo" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importa" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Impossibile importare la scaletta" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet può importare solo scalette nei formati M3U/M3U8 e PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Elimina" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Rinomina" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Impossibile rinominare la scaletta" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importa una scaletta" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importa" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nuova scaletta…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Cosa vuoi fare con questo %d brano?" msgstr[1] "Cosa vuoi fare con questi %d brani?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Conferma azione per la scaletta \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "vuota" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Scaletta di esempio" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Preferenze del navigatore delle scalette" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Visualizzazione scalette" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Sei sicuro che vuoi eliminare la scaletta '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Tutte le informazioni sulla scaletta selezionata saranno eliminate e non " "potranno essere ripristinate." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Traccia" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nuova scaletta" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Inserisci un nome per la nuova scaletta:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Sto importando la scaletta.\n" "\n" "%(current)d/%(total)d brani aggiunti." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nuovo Feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Inserire la posizione di un feed audio:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Aggiungi un _file…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Aggiorna" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Controlla la presenza di nuovi brani in questa cartella" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Impossibile aggiungere il feed" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s non è stato aggiunto. Il server potrebbe essere irraggiungibile, o " "potrebbe non contenere un feed audio." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "L'attuale backend audio non supporta gli URL, il navigatore dei feed audio è " "disabilitato." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limita i risultati" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Separa in _valori multipli" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Elenco tracce" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Elenco tracce" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Soundc_loud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Navigatore Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Soundc_loud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Cerca" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Le mie tracce" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Vai a %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Connesso" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet adesso è connesso, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Uscita di %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Inserisci il codice…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Ingresso in %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Autorizzazione di Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Inserisci il codice di autenticazione di Soundcloud" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet non è in esecuzione (aggiungi '--run' per avviarlo)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "una libreria musicale e riproduttore" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[opzione]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Stampa il brano in riproduzione ed esci" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Comincia a riprodurre immediatamente" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Non mostrare alcuna finestra all'avvio" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Salta al prossimo brano" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Salta al brano precedente o riavvia se vicino all'inizio" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Salta al brano precedente" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Avvia la riproduzione" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Metti in pausa" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Commuta riproduzione/pausa" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Ferma la riproduzione" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Aumenta il volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Abbassa il volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Mostra lo stato attuale" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Nascondi la finestra principale" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Mostra la finestra principale" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Commuta la visibilità della finestra principale" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Dai il fuoco al riproduttore in esecuzione" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Rimuovi i filtri attivi del navigatore" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Aggiorna e riscansiona la libreria" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Mostra navigatori disponibili" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Stampa la scaletta attuale" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Stampa il contenuto della coda" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Stampa l'interrogazione di testo attiva" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Avvia senza plugin" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Avvia Quod Libet se non è in esecuzione" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Esci da Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Posiziona nel brano in riproduzione" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Imposta o commuta la modalità casuale" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Imposta il tipo di modalità casuale" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Attiva, disattiva o commuta la ripetizione" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Imposta il tipo di modalità di ripetizione" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Imposta il volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Cerca nella tua libreria audio" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "interrogazione" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Riproduci un file" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "nome del file" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Posiziona nel brano in riproduzione" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Imposta il navigatore attuale" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "_Ferma dopo il brano in riproduzione" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Apri un nuovo navigatore" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Mostra o nascondi la coda" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtro su un valore casuale" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtro su un tag" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=valore" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Accoda un file o interrogazione" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Accoda i file separati dalla virgola" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nome del file" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" "Stampa i nomi dei file ottenuti dall'interrogazione sullo standard output" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Rimuovi un file o una ricerca dalla coda" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Aggiungi un file o una directory alla libreria" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "posizione" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "modello" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argomento non valido per '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Prova %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "È avvenuto un errore" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Puoi ignorare questo errore, ma l'applicazione potrebbe essere instabile " "finché non viene riavviata. L'invio di un rapporto di errore richiederà solo " "pochi secondi e ci aiuterebbe molto." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Invia rapporto di errore" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignora l'errore" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Dettagli errore:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Dettagli vari riguardanti l'errore e il tuo sistema saranno inviati ad un " "servizio online di terze parti (<a href='https://www.sentry.io'>www.sentry." "io</a>). Qui sotto puoi rivedere i dati prima di inviarli." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(opzionale) Per favore fornisci una breve descrizione di cosa è accaduto " "quando è avvenuto l'errore:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Invia" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Breve descrizione…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Dati da inviare:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "un editor di tag audio" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "directory" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Editor di metadati audio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL Opera d'arte sorgente copertina " #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Scarica copertine collegate dal tag artwork_url dell'opera d'arte. Questo " "funziona con il navigatore Soundcloud." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Sorgente copertina Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Scarica le copertine da Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Sorgente Last.fm della copertina" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Scarica copertine dall'archivio di copertine di Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Sorgente copertina di MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Scarica copertine dall'archivio di copertine di MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Converti codifiche" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Corregge codifiche errate dei valori dei tag nell'editor dei tag." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Converti codifica…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Semplice inverter Kana/Kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Converte kana/kanji a romaji prima di rinominare" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanizza il testo giapponese" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Impossibile trovare 'Semplice inverter Kanji Kana' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Sostituzione con espressione regolare" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Permetti sostituzioni arbitrarie con espressioni regolari (s///) durante il " "tagging o la rinomina di files." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Maiuscole nel titolo" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Valori dei tag con le prime lettere maiuscole nell'editor dei tag." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Prime lettere maiuscole del valore" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "_Consenti tutte maiuscole nel titolo" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Maiuscole nel titolo _umano" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Usa le comuni regole Inglesi per le maiuscole nel titolo, come in \"Dark " "Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Preferenze avanzate" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Consenti la modifica delle impostazioni di configurazione avanzate." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "_So quello che sto facendo" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "On-Screen Display animato" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Mostra informazioni brano sul tuo schermo quando cambia." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Posizione:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Dimensioni _copertina:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Visualizzazione" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "Caratt_ere:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Sinistra" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centro" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Destra" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Allinea testo:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Testo" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Testo:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Riempimento:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Colori" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Ombre" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Contorno" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "A_ngoli arrotondati" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Ritardo:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effetti" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Modifica modello _visualizzazione…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Anteprima" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informazioni applicazione" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Informazioni varie sull'applicazione e il suo ambiente." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Formati supportati" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Directory configurazione" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Directory cache" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Backend audio" # da controllare #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Ripristina il predefinito" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Impossibile trovare '%s'." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Aggiorna tag nei file" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Aggiorna tag modificati nei file. Questo assicurerà che i conteggi di " "riproduzione e i voti siano aggiornati." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Salva i giudizi e il _numero di riproduzioni nei tag" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "data di registrazione" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Errore durante la sincronizzazione" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Aggiorna stazioni" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Preferenze" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Mascheramento automatico" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Maschera e smaschera automaticamente le unità quando sono montate o smontate." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Giudizio automatico" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Giudica automaticamente i brani quando sono riprodotti o saltati. Questo usa " "l'algoritmo 'accelerated' da vux di Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importazione fallita" #: quodlibet/ext/events/bansheeimport.py:118 #, fuzzy, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Importazione riuscita di giudizi e statistiche per %d brani" msgstr[1] "Importazione riuscita di giudizi e statistiche per %d brani" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "Avvia importazione" #: quodlibet/ext/events/bansheeimport.py:128 #, fuzzy msgid "Imports ratings and song statistics from Banshee." msgstr "Importa giudizi brani e statistiche da Rythmbox." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Avvia importazione" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Sveglia" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Ti sveglia con musica ad alto volume." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Ninna nanna" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Sfuma e mette in pausa la tua musica." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Messaggio di stato di Gajim" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Messaggio di stato di Gajim" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" "Cambia il messaggio di stato di Gajim in accordo con quello che stai " "ascoltando." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "In pausa:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Testo di stato" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Testo di stato" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Cuffie" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Portatile" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizzatore" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Controlla il tono della tua musica con un equalizzatore.\n" "Clicca o usa i tasti per personalizzare i livelli (il clic destro reimposta " "la banda)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "L'attuale backend non supporta l'equalizzazione." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Preset predefiniti" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Seleziona…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Reimposta EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Preset personalizzati" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Elimina selezionati" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Nome del preset per il salvataggio:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Salva" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "connesso" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "disconnesso" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "lontano" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "invisibile" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Messaggio di stato di Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" "Cambia il messaggio di stato di Gajim in accordo con quello che stai " "ascoltando." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "in pausa" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Modello:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Elenca gli account, separati da spazi, per cambiare il messaggio di stato. " "Se nessuno è specificato, verrà cambiato il messaggio di stato di tutti gli " "account." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Account:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Aggiungi '[in pausa]'" #: quodlibet/ext/events/gajim_status.py:164 #, fuzzy msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Se selezionato, ['in pausa'] verrà aggiunto al messaggio di stato durante la " "pausa." #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Stati per i quali il messaggio verrà cambiato" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pausa allo scollegamento cuffie" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Mette in pausa nel caso le cuffie vengano scollegate e riprende in caso " "vengano ricollegate nuovamente." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Inibisce salvaschermo" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musica in riproduzione" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modello:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Inibisce salvaschermo" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Inibisce salvaschermo" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Registro radio Internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Registra gli ultimi 10 brani riprodotti su stazioni radio, ed elencali nel " "menu contestuale di ricerca." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Emette un file di Jabber User Tunes in ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Cambia lingua" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Cambia la lingua dell'interfaccia utente." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Predefinito di sistema" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "È richiesto un riavvio per essere effettivo ogni cambiamento" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Server Media UPnP AV" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Espone tutti gli album al Server Media UPnP Rygel attraverso l'interfaccia D-" "Bus MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Assicurati che il seguente sia nel tuo file di configurazione rygel (~/." "config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Server MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Consente il controllo remoto di Quod Libet usando un client MPD. La gestione " "dello streaming, scalette e libreria non sono supportati." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Porta:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_IP locale:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Connessione" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Client testati" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Supporto D-Bus MPRIS" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "_Nascondi la finestra principale alla chiusura" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Accetta Modelli QL ad es. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Editore MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Pubblica messaggi di stato su un argomento MQTT" #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Nome dell'host del mediatore" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "nome dell'host mediatore / IP" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Porta del mediatore" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Predefinito" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Nome dell'host del mediatore" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Porta del mediatore" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Argomento" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Modello di riproduzione" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Testo di stato quando il brano è avviato." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Modello in pausa" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Testo quando un brano è in pausa." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Testo su nessun brano" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Testo semplice per quando non è presente una canzone corrente" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Configurazione MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Testo di stato" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Connesso al mediatore presso %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Impossibile connettersi a %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Errore di connessione" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Ricerca MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Consente l'impostazione del giudizio dei brani con un numero." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Nome utente:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Testo di notifica" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Titolo:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Ripristina il modello predefinito" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Corpo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "Mo_stra notifica" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Mo_stra notifiche" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Solo su cambi di brano <i>_manuali</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Solo su cambi di brano <i>_automatici</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Su <i>t_utti</i> i cambi di brano" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Solo quando la _finestra principale non ha il fuoco" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Mostra il pulsante \"_Prossimo\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Errore di connessione" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Impossibile connettersi al demone di notifica." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Notifiche brani" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Mostra una notifica quando cambia il brano." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Prossimo" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Notifiche brani" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Per favore visita la finestra Plugins per impostare QLScrobbler. Fino ad " "allora, i brani non verranno inviati." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Impossibile contattare il servizio '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Autenticazione fallita: URL non valido." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Autenticazione fallita: Nome utente '%s' non valido o password errata." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Il client è stato bannato. Contatta l'autore." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Orario di sistema sbagliato. Gli invii potrebbero fallire finché non è " "corretto." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Invio AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Client AudioScrobbler per Last.fm, Libre.fm e altri servizi Audioscrobbler." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Autenticazione riuscita." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Servizio:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Altro…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Verifica dati account" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Modello _artista:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Modello per il _titolo:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_Filtro di esclusione:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "Autenticazione riuscita." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Il modello usato per formattare il titolo per l'invio. Lascia vuoto per il " "predefinito." #: quodlibet/ext/events/qlscrobbler.py:593 #, fuzzy msgid "Songs matching this filter will not be submitted" msgstr "I brani corrispondenti a questo filtro non saranno inviati." #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Modalità disc_onnessa (non invia niente)." #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Invio" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Pubblicità radio mute" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Disattiva l'audio durante la riproduzione di annunci radio.\n" "Stazioni: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Riproduzione album casuale" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Avvia un album casuale quando la tua scaletta raggiunge la sua fine. " "Richiede che il tuo navigatore attivo supporti il filtraggio per album." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Giudicati più alti" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Riprodotti più spesso" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Saltati più spesso" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Riprodotti più recentemente" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Avviati più recentemente" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Aggiunti più recentemente" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Album più lunghi" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "_secondi prima di avviare il prossimo album" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Pesi" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Riproduci certi album più di altri" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "evita" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "preferisci" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Album casuale" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "In attesa di avviare %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Importazione riuscita di giudizi e statistiche per %d brani" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Importazione di Rythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importa giudizi brani e statistiche da Rythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pausa durante salvaschermo" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Mette in pausa la riproduzione mentre il salvaschermo GNOME è attivo." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Nessun fornitore di ricerca GNOME Shell per QuodLibet installato." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Fornitore di ricerca GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Consente a GNOME Shell di cercare nella libreria" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Barra di posizionamento alternativa" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Barra di posizionamento alternativa sempre visibile e che si estende " "all'intera larghezza della finestra." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Segnalibri punti di posizionamento" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Imposta punti di posizionamento A e/o B per le tracce. Salta al tempo A e " "ferma dopo il tempo B quando la traccia è riprodotta.\n" "Nota che cambiando i nomi dei punti qui sotto non si aggiornano i nomi " "effettivi nei segnalibri, esso cambia solo a quali nomi di segnalibri il " "plugin guarda alla decisione se posizionare o meno." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nome del segnalibro per il punto A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Nome del segnalibro da controllare quando un brano è avviato, e se trovato, " "il riproduttore si posiziona a tale tempo" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nome del segnalibro per il punto B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Segnalibro a usare ad ogni tick durante la riproduzione di un brano se " "esiste. Se la posizione corrente eccede il tempo, posiziona alla fine del " "brano." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Sincronizzazione Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Fa si che Squeezebox di Logitech rispecchi l'uscita di Quod Libet, " "presupponendo che entrambi leggano da una libreria identica." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Errore trovando il server Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Errore trovando %s. Per favore controlla le impostazioni" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Opzioni" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "codifica" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "data di registrazione" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Elimina" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Elimina" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Saltati più spesso" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Cartella destinazione:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Modelli del percorso" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Modifica modelli salvati…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "Modello _artista:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Anteprima" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Stato" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Sorgenti" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Esporta metadati" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "etichetta discografica" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Salva destinazione" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Il percorso non è assoluto" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Il modello\n" "\t<b>%s</b>\n" "contiene / ma non parte dalla directory root. Per evitare cartelle mal " "nominate, bisogna far partire i modelli con / o con ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nessun brano selezionato." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nessun brano selezionato." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Impossibile salvare il brano" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Saltati più spesso" msgstr[1] "Saltati più spesso" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Impossibile aprire i file di input" msgstr[1] "Impossibile aprire i file di input" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "Mostra testi sincronizzati da file .lrc con lo stesso nome del brano." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "_Testo:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "_Sfondo:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Carattere" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "_Dimensione (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Messaggi di stato di Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Aggiorna tutti gli account basati su Telepathy (così come configurati in " "Empathy, ecc.) con un messaggio di stato basato sul brano corrente." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "In riproduzione:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Testo di stato quando un brano è avviato. Accetta modelli QL ad es. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "In pausa:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Testo di stato quando un brano è in pausa. Accetta modelli QL ad es. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Testo semplice per lo stato quando non c'è branno corrente" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Nessun brano:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Modelli di stato" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Commutatore di temi" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Cambia il tema GTK+ attivo." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Tema predefinito" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "_Preferisci la versione scura del tema" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Giudizio automatico" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Commuta barra dei menu" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Commuta la barra dei menu premendo il tasto Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Non in riproduzione" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Icona del cassetto" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Controlla Quod Libet dal cassetto di sistema." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "Mo_stra %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Riproduci" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ausa" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Prece_dente" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Prossimo" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Casuale" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Ripeti" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "_Ferma dopo questo brano" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Apri na_vigatore" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Modifica i _tag" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informazioni" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Sca_lette" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Esci" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Comportamento" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "La rotella di scorrimento cambia il _volume" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "La rotella di scorrimento cambia il _brano" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Rotella di scorrimento" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Visualizzazione _suggerimento" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Vedi i testi" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Mostra automaticamente tag o testi basati su file in una barra laterale." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Nessun testo trovato per\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Nessun brano attivo" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Lancia visualizzazioni" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Lancia visualizzazioni esterne." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Impossibile eseguire visualizzazioni usando '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Errore" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Eseguibile visualizzatore" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "_Ricarica" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Barra di posizionamento a forma d'onda" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "Una barra di posizionamento del brano corrente in forma d'onda " #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Scavalca colore di primo piano:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Scavalca colore svolazzante:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Scavalca colore rimanente:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Mostra la posizione corrente" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Mostra le etichette di tempo" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Quantità di posizionamento allo scorrimento (millisecondi)" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Salva immagine" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Salva l'immagine di copertina del brano corrente in un file." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "File:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Soglia:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Soglia fino alla quale il filtro non viene attivato" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "R_apporto:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Rapporto di compressione" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Compressore audio" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Cambia l'ampiezza di tutti i campioni sopra una specifica soglia con un " "rapporto specifico." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "" # vedere contesto #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Preset filtro" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frequenza di taglio:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Frequenza di taglio filtro passa-basso" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "_Livello di feed:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Livello di feed" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Predefinito" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Più vicino al piazzamento virtuale degli altoparlanti (30°, 3 metri)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Vicino al crossfeeder Chu Moy (popolare)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Vicino agli amplificatori CORDA di Jan Meier (piccolo cambiamento)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Personalizzato" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Impostazioni personalizzate" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mixa i canali sinistro e destro in modo da simulare una disposizione di " "altoparlanti usando le cuffie, o per aggiustare le prime registrazioni " "stereo." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Banda filtro:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "La banda di frequenza del filtro" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Larghezza _filtro:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "La larghezza della frequenza del filtro" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Livello:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Livello dell'effetto" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Rimuove le voci principali dall'audio." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Rimissa i canali audio in mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "V_oto:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Intonazione:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Intonazione audio / Velocità" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Controlla l'intonazione di un flusso audio." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Esporta scaletta nella cartella" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Esporta" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Cartella destinazione:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Modello del nome di file:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Esporta una scaletta copiando i file in una cartella." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Impossibile esportare la scaletta" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Modello del nome di file predefinito:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Esporta come scaletta" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Esporta una scaletta copiando i file in una cartella." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Errore trovando il server Squeezebox" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Errore trovando %s. Per favore controlla le impostazioni" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Esporta a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Esporta dinamicamente una scaletta ad una scaletta Squeezebox di Logitech, " "purché entrambi condividano una struttura di directory. Condivide la " "configurazione con il <a href=\"quodlibet:///prefs/plugins/Squeezebox Output" "\">plugin sincronizzazione Squeezebox</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Esporta scaletta a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Nome della scaletta (sovrascriverà esistente)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Esporta a scaletta Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Rimuovi duplicati scaletta" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Rimuove gli elementi duplicati in una scaletta." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Sei sicuro di voler rimuovere %d brano duplicato?" msgstr[1] "Sei sicuro di voler rimuovere %d brani duplicati?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "I brani duplicati verranno rimossi dalla scaletta '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Playlist casuale" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Mischia casualmente una scaletta." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Segui selezione" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "La riproduzione segue la tua selezione, o il prossimo brano nell'elenco una " "volta esaurito." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Segui selezione" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Segui selezione" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Equalizzatore conteggio riproduzione" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Mescola, preferendo brani con poche riproduzioni totali." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Preferisci i meno riprodotti" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Preferisci i meno riprodotti" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Accoda solamente" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Limita la riproduzione solo ai brani in coda. Seleziona questo ordine di " "riproduzione nella finestra principale, poi il doppio clic su ogni brano lo " "accoderà invece di riprodurlo." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Accoda solamente" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Accoda solamente" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Inverti" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Inverte l'ordine di riproduzione dei brani." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Inverti" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Mischia raggruppando" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Mischia raggruppando i brani definiti da un tag comune invece che per brano, " "similmente al mischiamento album. Questo è utile per mischiare i lavori " "classici multi movimento assicurandosi che tutti i movimenti vengano " "riprodotti in ordine prima di mischiare al prossimo pezzo." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Mischia raggruppando" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Mischia raggruppando" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "In attesa di avviare un nuovo gruppo…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Tag di raggruppamento:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Tagga per ragruppare i brani per" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Tag filtro:" # da controllare #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Il raggruppamento è applicato solo se è definito il tag filtro.\n" "Un brano con un tag filtro non definito verrà trattato come \n" "un gruppo consistente solo in se stesso. Tipicamente il tag filtro\n" "dovrebbe corrispondere o corrispondere parzialmente al tag \n" "di raggruppamento." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Ritardo:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Ritardo di tempo in secondi prima di avviare il prossimo gruppo" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Ripristina i predefiniti" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Ripeti ogni traccia" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Mischia brani, ma ripeti ogni traccia un dato numero di volte." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Ripeti ogni traccia" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Ripeti ogni traccia" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Numero di volte da riprodurre ogni brano:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Interrogazione condizionale" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Sceglie l'interrogazione da effettuare basandosi su un'interrogazione " "condizionale. La sintassi è '@(if: condition, then, else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Interrogazione mancanti" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Corrisponde ai brani senza il tag dato." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "_Include tag vuoti" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Interrogazione Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Espressione tag" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Usa espressioni Python nelle interrogazioni. La sintassi è '@(python: " "expression)'. La variabile 's' (o 'a') è il brano / album da corrispondere. " "'_ts' (numero reale) è un tempo all'avvio dell'interrogazione. I moduli " "'time' e 'random' sono disponibili, e la classe 'Random' (==random.Random) " "pure." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Includi ricerca salvata" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Include i risultati di una ricerca salvata come parte di un'altra " "interrogazione. La sintassi è '@(saved: search name)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Ricerche salvate" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unico" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Uso solo il riproduttore (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Impossibile connettersi a %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nome dell'_host:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "_Porta:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nome _utente:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Pass_word:" #: quodlibet/ext/_shared/squeezebox/base.py:138 #, fuzzy msgid "Library directory the server connects to" msgstr "Directory della libreria alla quale il server si connette." #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Percorso _libreria:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Verifica impostazioni" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Server Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "_Debug" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Server Squeezebox a {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "server Squeezebox non identificato" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "riproduttore Squeezebox non identificato: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Scegli riproduttore Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Trovato server Squeezebox.\n" "Per favore scegli il riproduttore." # controllare #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Adatta i_mmagine alla finestra" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Vedi la voce di configurazione '[plugins] cover_filenames' per le stringhe " "del nome del file dell'immagine" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programma:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "Modifica immagin_e dopo il salvataggio" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Nome del file:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Salvatagggio fallito" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Impossibile salvare \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Errore HTTP : %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Scaricatore grafica album" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "da %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Risoluzione: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Dimensione: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Limite di risultati per motore 'al meglio'" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Cerca" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Ricerca…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Fatto" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Scarica grafica album" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Scarica copertine degli album da vari siti web." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Sorgenti" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "Da APEv2 a ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Converte i tuoi tag APEv2 in tag ID3v2. Questo eliminerà i tag APEv2 dopo la " "conversione." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Vai al segnalibro" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Gestisce i segnalibri nei file selezionati." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "Modifica Segnalibri…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Nessun segnalibro" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Ricerca MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Ritagga un album in base ad una ricerca su MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Usa solo l'anno per il tag \"date\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Scrivi \"_albumartist\" quando neccessario" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Scrivi tag di ordinamento per i nomi di artista" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Scrivi tag MusicBrainz _standard." #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Scrivi tag \"labelid\"" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nome del file" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Traccia" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Titolo" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Ricerca MusicBrainz" # controllare #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Interrogazione:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "C_erca" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Risultati <i>(trascina per riordinare)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Per favore inserisci un'interrogazione." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Incontrato errore. Per favore riprova." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Caricamento risultato…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Nessun risultato trovato." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Console Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Console Python interattiva. Apre una nuova finestra." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} per {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Barra laterale console Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Barra laterale console Python interattiva, questa segue i brani selezionati " "nella finestra principale." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Puoi accedere ai seguenti oggetti in modo predefinito:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "La tua directory di lavoro corrente è:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Connessione" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Scarica grafica copertina" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Scarica copertina di alta qualità usando i plugin copertina." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Classico" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Ampio" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Scaricamento grafica copertina" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Caricamento di %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Non è stato trovato niente per gli album:\n" "<i>%(albums)s</i>.\n" "\n" "Fornitori usati:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Nessuna copertina trovata" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Dimensioni _anteprima" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Salva destinazione" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Comando" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nome" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Il nome di questo comando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "comando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "La sintassi del comando shell da eseguire" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parametro" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Se specificato, un parametro le cui occorrenze nel comando verranno " "sostituite con un valore fornito dell'utente, ad es. usando PARAM tutte le " "istanze di '{PARAM}' nel tuo comando avranno il valore richiesto " "all'esecuzione" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Il modello QL, ad es. <~filename>, da usare per calcolare un valore per il " "comando. Per le scalette, questo supporta i tag virtuali <~playlistname> e " "<~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unico" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Se impostato, questo rimuoverà i duplicati dei valori calcolati del modello" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "massimo argomenti" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Il numero massimo di argomenti da passare alla linea di comando in una volta " "(come xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Inverti" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Valore di ingresso" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Valore per %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Comandi personalizzati" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Esegue comandi personalizzati (in gruppo se richiesto) sui brani usando " "ognuno dei suoi tag." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "_Modifica comandi personalizzati" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Non riesco ad eseguire il comando personalizzato %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d gruppo duplicato" msgstr[1] "%d gruppi duplicati" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Collassa / espandi tutto" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "L'espressione chiave duplicata è '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Duplica il navigatore" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Trova e mostra versioni dei brani taggate similmente." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Accetta espressioni di tag QL come <tt>~artist~title</tt> o " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "Ra_ggruppa duplicati per:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Chiave duplicata" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Rimuovi _spazi bianchi" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Rimuovi segni _diacritici" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Rimuovi _punteggiatura" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "_Insensibile alle maiuscole" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Opzioni di corrispondenza" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Modifica conteggio riproduzioni" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Modifica il ~#playcount e il ~#skipcount di un brano.\n" "Quando sono selezionati brani multipli, i conteggi verranno incrementati, " "piuttosto che impostati.\n" "Impostando il ~#playcount di un brano a 0, le voci ~#lastplayed e " "~#laststarted saranno pulite.\n" "Ad ogni modo, impostando un brano con 0 riproduzioni ad un conteggio di " "riproduzioni positivo, non verranno create le volte di riproduzione." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Conteggio riproduzione" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Conteggio saltati" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Valori %s multipli" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Modifica immagini incorporate" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Rimuove o rimpiazza le immagini incorporate." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Rimuovi tutte le immagini" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "Incorpora immagin_e corrente" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Imposta giudizio esatto" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Consente l'impostazione del giudizio dei brani con un numero." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Per favore dai il tuo giudizio desiderato su una scala da 0.0 a 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtro per qualsiasi tag" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Crea un'interrogazione di ricerca basata sui tag dei brani selezionati." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtro per directory" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtro per directory in una nuova finestra del navigatore." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Ricerca impronta acustica" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Ricerca metadati del brano tramite l'impronta acustica." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Invia impronte acustiche" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Genera impronte acustiche usando chromaprint e le invia a acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Chiave API mancante" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Devi specificare una chiave APE di acoustid.org nelle preferenze del plugin " "prima di poter inviare impronte." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "_Richiedi chiave API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Chiave API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Web Service AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Accodato" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analisi" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Ricerca" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Scrivi" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "ID rilascio" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Scrivi tag MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Raggruppa per directory" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Modalità Album" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Scrivi tag relativi all'album e prova a ridurre il numero di rilasci " "dell'album differenti" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generazione impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Dettagli" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Invia" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "I brani hanno bisogno di tag o <i><b>musicbrainz_trackid</b></i>, o " "<i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i> per essere " "inviati." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Brani con MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Brani con tag sufficienti:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Brani da inviare:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Fatto.%(to-send)d/%(all)d brani da inviare." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Invio impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Invio…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Aggiorna tag nei file" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Aggiorna tag modificati nei file. Questo assicurerà che i conteggi di " "riproduzione e i voti siano aggiornati." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Esporta HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Esporta l'elenco di brani selezionati in HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Invia a iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Carica brani su un dispositivo iFP iRiver." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Nessun dispositivo iFP trovato" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Impossibile contattare il tuo dispositivo iFP. Controlla che il dispositivo " "sia alimentato e collegato, e che tu abbia ifp-line (http://ifp-driver.sf." "net) installato." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Sto caricando %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Impossibile caricare <b>%s</b>. Il dispositivo potrebbe avere esaurito lo " "spazio, o essere spento." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Errore mentre carico" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Esporta metadati" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Esporta metadati" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Esporta metadati" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Esporta metadati" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Nessuna informazione sulla durata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Grafica album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importazione fallita" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtro per directory" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Disco" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Traccia" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Artista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Continua" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Impossibile trovare '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Impossibile trovare '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Nomi dei file" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Ripeti ogni traccia" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Aggiornamento elenco classifica." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Già aggiornato." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Ottenimento classifica per la settimana di %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Sincronizzazione completa." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Errore durante la sincronizzazione" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Sincronizzazione Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Aggiorna le tue statistiche di libreria dal tuo profilo Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Nome _utente:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Crea tag di ordinamento" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Converte nomi di album e artista in nomi di ordinamento, poveramente." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Esporta come scaletta" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Esporta brani su una scaletta M3U o PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Usa percorsi relativi" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Usa percorsi assoluti" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Scrittura su <b>%s</b> fallita." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Riscansiona brani" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Controlla per cambiamenti del file e ricarica / rimuove i brani se " "necessario." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Riscansiona brani" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Analizzatore Replay Gain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Traccia" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Progresso" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Guadagno" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Picco" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "C'è <b>%(to-process)s</b> album da aggiornare (di %(all)s)" msgstr[1] "Ci sono <b>%(to-process)s</b> album da aggiornare (di %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analizza ed aggiorna informazioni <a href=\"%(rg_link)s\">ReplayGain</a>, " "usando GStreamer. I risultati sono raggruppati per album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "sempre" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "se <b>qualunque</b> tag RG è mancante" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "se tag RG <b>album</b> sono mancanti" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Elabora album:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Tag esistenti" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Separa tag" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Separa il numero del disco dall'album e la versione dal titolo allo stesso " "tempo." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Separa album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Separa il numero del disco." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/d" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Reimposta" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Tap dei BPM per i brani selezionati." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Cerca nel sito" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Cerca il tuo sito scelto usando qualunque tag del brano.\n" "Supporta modelli es. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Cerca modelli URL" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Modifica _URL di ricerca" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Configura ricerche…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Cerca tag su Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Apre una finestra del browser con l'articolo di Wikipedia sul tag " "corrispondente al brano selezionato." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "_Cerca su %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Modifica i tag" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Ricerca fallita" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Tag \"%s\" non trovato." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Libreria" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Controllo dei punti di mount" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Scansione della libreria" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Scansione di %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Caricamento files" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Scansione della libreria" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Rimuovi i filtri attivi del navigatore" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Riproduttore musicale e gestore libreria musicale" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Fallito caricamento file: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Elenca tag" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Stampa uscita breve" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Colonne da mostrare e ordine in modalità breve (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Elenca anche i tag programmatici" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Argomenti insufficienti" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Troppi argomenti" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Descrizione" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valore" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Elenca tutti i tag comuni" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Copia tag da un file all'altro" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Mostra cambiamenti, non applicarli" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Salta i tag che non possono essere scritti" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Impossibile copiare il tag {tagname} al file: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Modifica i tag in un editor di testo" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Modifica annullata" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Avvio dell'editor di testo '%(editor-name)s' fallito." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Nessun cambiamento rilevato" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Imposta un tag e rimuovi i valori esistenti" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Impossibile impostare %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Rimuovi tag" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Il valore è un'espressione regolare" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Rimuovi tutti i tag" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Impossibile combinare '-all' con '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Impossibile rimuovere {tagname} da {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Rimuovi il valore di un tag" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Aggiungi il valore di un tag" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Impossibile impostare %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Elenca informazioni sul file" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Imposta l'immagine fornita come immagine incorporata primaria e rimuovi " "tutte le altre immagini incorporate" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Fallito caricamento file immagine: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Modifica dell'immagine non supportata per %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Rimuovi tutte le immagini incorporate" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Estrai le immagini incorporate su %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Percorso sul quale verranno salvate le immagini (la directory di lavoro è la " "predefinita)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Rinomina file basandosi sui tag" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Riempi i tag basandosi sul percorso del file" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "File" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Riempi i numeri di traccia per tutti i file" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Stampa tag basandosi su un dato modello" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Mostra informazioni di aiuto" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' non è un nome di colonna valido (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Sconosciuto" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "In ordine" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_In ordine" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Casuale" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Casuale" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Preferisci i _giudicati più alti" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Preferisci i _giudicati più alti" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "_Ripeti questa traccia" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "_Ripeti questa traccia" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Ripeti tutti" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Ripeti tutti" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Un brano" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Un brano" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Flusso" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Impossibile creare pipeline GStreamer" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Nessun elemento GStreamer trovato per gestire il formato del media" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Formato media: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Il plugin GStreamer '%(name)s' non può essere inizializzato" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Pipeline GStreamer di uscita utilizzata per la riproduzione. Lascia vuoto la " "pipeline predefinita. Nel caso in cui la pipeline contenga un sink, questo " "verrà usato al posto di quello predefinito." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Pipeline di _output:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f secondi" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Durata _buffer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Disabilita riproduzione _senza pause" #: quodlibet/player/gstbe/prefs.py:71 #, fuzzy msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Disabilitare la riproduzione senza pause può evitare problemi di cambiamento " "traccia con alcune versioni di GStreamer." #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nessun sink audio GStreamer trovato" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Pipeline di output di GStreamer non valida" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Impossibile creare l'uscita audio" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Il dispositivo audio %r non è stato trovato. Controlla le tue configurazioni " "di Xine in ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Impossibile trovare il modulo '{module}'. Hai forse bisogno di installare il " "pacchetto?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Impossibile trovare l'elemento di GStreamer '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Per favore visita la finestra Plugins per impostare QLScrobbler. Fino ad " "allora, i brani non verranno inviati." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Per favore visita la finestra Plugins per impostare QLScrobbler. Fino ad " "allora, i brani non verranno inviati." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Invio" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nome utente:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "I brani corrispondenti a questo filtro non saranno inviati." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Eseguire il plugin \"%(name)s\" su %(count)s scaletta?" msgstr[1] "Eseguire il plugin \"%(name)s\" su %(count)s scalette?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Esegui plugin" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Inizio" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tempo" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nome del segnalibro" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Segnalibri" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtri" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "_Riprodotti di recente" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Agg_iunti di recente" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "Pri_mi 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "_Tutti i brani" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Sul ge_nere/i corrente" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "_Sull'artista/i corrente" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Su_ll'album corrente" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "_Genere casuale" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "_Artista casuale" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Al_bum casuale" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "I 40 brani più ascoltati (possono essere più di 40 se ci sono dei pari " "merito)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nome:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valore:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Valori salvati" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Modifica i valori salvati…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matico" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Modalità _Traccia" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Modalità _Album" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Muto" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "Modalità Replay _Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nuovo %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(sconosciuto)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Aggiungi" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Modifica" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Espressione tag" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 #, fuzzy msgid "Tag expression e.g. people:real or ~album~year" msgstr "Espressione tag es people:real o ~album~year." #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Inserisci nuovo tag" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Espressione tag" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "File:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "I brani selezionati verranno rimossi dalla libreria e i loro file eliminati " "dal disco." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "I file selezionati verranno eliminati dal disco." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Eliminare %(file_count)d file definitivamente?" msgstr[1] "Eliminare %(file_count)d file definitivamente?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Elimina i file" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "I brani selezionati verranno rimossi dalla libreria e i loro file spostati " "nel cestino." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "I file selezionati verranno spostati nel cestino." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Spostare %(file_count)d file nel cestino?" msgstr[1] "Spostare %(file_count)d file nel cestino?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Sposta nel cestino" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Spostamento di %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Impossibile spostare nel cestino" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Spostamento di uno o più file nel cestino fallito." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Cancellazione di %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Impossibile eliminare i file" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Non è stato possibile eliminare uno o più file." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Navigatori" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Scarica i file" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "mancante da %d brano" msgstr[1] "mancante da %d brani" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "differente in %d brano" msgstr[1] "differente in %d brani" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Separa in valori _multipli" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Separa i dischi dall'_album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Separa la _versione dal titolo" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Separa l'arrangiatore dall'ar_tista" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Separa l'e_secutore dall'artista" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Separa l'e_secutore dal titolo" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Separa l'artista originale dal titolo" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Aggiungi un tag" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Mostra tag programmatici" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Accedi a tutti i tag, inclusi quelli generati da macchine ad es. tag " "MusicBrainz o Replay Gain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Mostra tag programmatici" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Ripristina" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Salva" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Continua" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Separa tag" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "Copia valore/i" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Impossibile aggiungere tag" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Impossibile aggiungere i brani" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "I file attualmente selezionati non supportano valori multipli per <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Tag non valido" msgstr[1] "Tag non valido" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Tag <b>%s</b> non valido\n" "\n" "I file attualmente selezionati non supportano la modifica di questo tag." msgstr[1] "" "Tag <b>%s</b> non valido\n" "\n" "I file attualmente selezionati non supportano la modifica di questo tag." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Valore non valido" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Valore non valido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Il tag potrebbe non essere accurato" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s è cambiato mentre il programma era in esecuzione. Salvare " "senza aggiornare la tua libreria potrebbe sovrascrivere gli altri " "cambiamenti al brano." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Impossibile salvare il brano" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Salvataggio di %(file-name)s fallito. Il file potrebbe essere di sola " "lettura, corrotto, oppure non si hanno permessi sufficienti per modificarlo." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Più opzioni…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Annulla" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Ripeti" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_A proposito" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Controlla per aggiornamenti…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "P_lugin" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s e %(count)s altro" msgstr[1] "%(title)s e altri %(count)s" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferenze di Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Cartelle" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nuova cartella…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Seleziona tutte le sottocartelle" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nuova cartella" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Inserire un nome per la nuova cartella:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Impossibile creare la cartella" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Impossibile eliminare la cartella" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Brani" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "di %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Traccia %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Brano cor_rente" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "Mod_ifica visualizzazione…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nessun brano selezionato." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nessun brano" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informazioni" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Testi" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Prodotto da %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artisti" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "esecutori" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Mai" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d volta" msgstr[1] "%(n)d volte" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "aggiunto" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "ultimo passaggio" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "riproduzioni" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "saltati" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "giudizio" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "percorso" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "lunghezza" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formato" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codifica" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "dimensioni file" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificato" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Addizionale" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selezionato" msgstr[1] "%d selezionati" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Traccia non disponibile" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d brano senza album" msgstr[1] "%d brani senza album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discografia selezionata" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d brano senza artista" msgstr[1] "%d brani senza artista" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Lunghezza totale:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Dimensioni totali:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "File" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Visualizza online" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nessun testo trovato per questo brano." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Sei sicuro di voler rimuovere tutti i brani?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "I brani selezionati saranno rimossi dalla libreria." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Mostra" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Non nostrare" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Tralasciare le modifiche ai tag?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "I tag modificati non sono stati salvati. Salvare i file, o tralasciare i " "cambiamenti?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Ripristina" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Il file esiste" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Sostituire %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "Sostituisci file" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Operazioni attive" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d operazioni in esecuzione" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Commuta modalità casuale" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Commuta modalità ripetizione" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Eventi" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Ordine di riproduzione" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Modifica" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Rinomina" # controllare #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Interrogazione:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Copertine" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Errori dei plugin" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Attivo" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Disattivato" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Nessuna categoria" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Nessuna categoria" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nessun plugin trovato." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Plugin" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtra per stato plugin / tag" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtra per tipo plugin" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtra per nome plugin o descrizione" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Mostra _errori" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Traccia" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Raggru_ppamento" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artista" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Nome del _file" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Lunghezza" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Salta automaticamente al brano in _riproduzione" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Quando cambia il brano in riproduzione, scorri fino ad esso nell'elenco brani" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Altri:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Modifica…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Aggiungi o rimuovi intestazioni di colonna addizionali" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Colonne visibili" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Il titolo include la _versione" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "L'album includ_e il sottotitolo del disco" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "L'artista incl_ude tutte le persone" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Il nome del file include la _cartella" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Preferenze colonna" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Modifica colonne" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Applica la configurazione corrente all'elenco dei brani, aggiungendo le " "nuove colonne alla fine" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Elenco Brani" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Modifica colonne" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "_Totali durata" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Filtro _globale:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Applica questa interrogazione in aggiunta alle altre" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Cerca" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navigatori" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Conferma giudizi _multipli" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Chiedi conferma prima di cambiare il giudizio di più canzoni assieme" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Abilita giudizi con un _click" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Abilita il giudizio cliccando sulla colonna del voto della lista dei brani" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Giudizi" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Pr_eferisci grafica incorporata" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Scegli di usare l'opera d'arte incorporata nell'audio (quando disponibile) " "al posto di altre sorgenti" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "Nome _fisso del file dell'immagine:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Grafica album" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Riproduzione" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Configurazione uscita" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Se non è disponibile l'informazione Replay Gain per un brano, scala il " "volume a questo valore " #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Guadagno di _fall-back (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Scala il volume di tutti i brani a questo valore, fintanto che il risultato " "non distorga" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Guadagno _pre-amp (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Abilita l'aggiustamento del volume _Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Aggiustamento Replay Gain del volume " #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Giudizio pre_definito:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Scala giudizio" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Fattore di media Bayesiana per giudizi accorpat.i.\n" "0 significa una media convenzionale, valori alti significano che gli album " "con poche tracce avranno voti meno estremi. Il cambiamento di questo valore " "avvia il ricalcolo per tutti gli album." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Quantità media _Bayesiana" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Giudizi e numero dei passaggi saranno salvati nei tag per questo indirizzo " "email" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Salvataggio automatico _modifiche dei tag" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Salvataggio delle modifiche ai tag senza conferma durante la modifica di " "file multipli" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Insieme di separatori da usare durante la separazione di valori dei tag " "nell'editor dei tag. L'elenco è separato da spazi" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Dividi s_u:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Insieme di separatori da usare durante la separazione di valori dei tag " "nell'editor dei tag. L'elenco è separato da spazi" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Dividi s_u:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tag" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Modifica dei tag" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Aggiornamento per nuovi giudizi" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Scansiona libreria" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Controlla cambiamenti nella tua libreria" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Ri_costruisci libreria" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Ricarica tutti i brani nella tua libreria (può richiedere molto tempo)." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Brani nascosti" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Scansi_ona la libreria all'avvio" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Scansiona directory" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s e %(count)d altro" msgstr[1] "%(title)s e altri %(count)d" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Proprietà" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "Co_da" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Pulisci coda" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Generale" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Tieni i brani in coda dopo averli riprodotti." #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Tieni i brani in coda dopo averli riprodotti." #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modello:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "_Ferma alla fine" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d brano (%(time)s)" msgstr[1] "%(count)d brani (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Esplora libreria" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Commuta visibilità coda" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Errore di riproduzione" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Impostare le directory della libreria?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Non hai nessuna libreria musicale impostata. Vuoi farlo ora?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Non ora" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "Impo_sta" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Impossibile aggiungere i brani" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s usa un protocollo non supportato." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Salta al brano in riproduzione" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_File" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Brano" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Visualizza" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Esplora" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Controllo" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Aiuto" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Aggiungi una cartella…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Aggiungi un _file…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Aggiungi una _posizione…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Modifica segnali_bri…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Ferma" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "_Ferma dopo questo brano" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Scorciatoie da _tastiera" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Aiuto in _linea" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "C_erca nell'aiuto" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Aggiungi una posizione" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Inserire la posizione di un file audio:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Impossibile aggiungere la posizione" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s non è una posizione valida." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Aggiungi musica" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "Aggiungi _cartelle" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "File musicali" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "Aggiungi _file" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Sei sicuro di voler rimuovere tutti i brani?" msgstr[1] "Sei sicuro di voler rimuovere tutti i brani?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "Co_da" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Stai per modificare il voto di %d tracce.\n" "Desideri proseguire?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "I giudizi salvati verranno rimossi" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Rimuovi giudizio" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Il giudizio di tutti i brani selezionati sarà cambiato in '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Cambia _giudizio" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Sostituisci spazi con _underscore" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Elimina i caratteri incompatibili con _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Elimina i segni _diacritici" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Elimina i caratteri non-_ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Usa solo caratteri _minuscoli" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Rinomina i file" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "Ante_prima" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Nomi dei file" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "Sposta grafica dell'albu_m" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Vedi la voce di configurazione '[albumart] filenames' per le stringhe di " "ricerca immagine" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "S_ovrascrivi grafica album alla destinazione" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Rimuovi directory vuote" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Grafica album" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nuovo nome" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Impossibile rinominare il file" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "La rinomina di <b>%(old-name)s</b> in <b>%(new-name)s</b> è fallita. " "Probabilmente il file esiste già, o non si hanno sufficienti permessi per " "creare un nuovo file o eliminare quello vecchio." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignora _tutti gli errori" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Ferma" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continua" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Il percorso non è assoluto" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Il modello\n" "\t<b>%s</b>\n" "contiene / ma non parte dalla directory root. Per evitare cartelle mal " "nominate, bisogna far partire i modelli con / o con ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "I brani nelle cartelle elencate saranno aggiunti alla libreria durante un " "aggiornamento della stessa" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "I brani selezionati saranno rimossi dalla libreria." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Sto rimuovendo le tracce iPod orfane" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Percorso _libreria:" msgstr[1] "Percorso _libreria:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Rimuovi" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Selezionare le directory" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Selezionare le directory" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Ricerche salvate" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Modifica ricerche salvate…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Cerca nella tua libreria, usando testo libero o interrogazioni QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Cerca _dopo aver digitato" #: quodlibet/qltk/searchbar.py:148 #, fuzzy msgid "Show search results after the user stops typing" msgstr "Mostra i risultati della ricerca dopo che l'utente smette di digitare." #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limite:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Peso" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "interrogazione" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "_Mostra il tempo rimanente" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Finestra principale" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Posiziona all'indietro di 10 secondi" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Posiziona in avanti di 10 secondi" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Dai il fuoco al campo di ricerca" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Reimposta filtri e salta al brano in riproduzione" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Apri la finestra di informazioni per i brani selezionati" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Apri l'editor di tag per i brani selezionati" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Accoda i brani selezionati" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Elimina i brani selezionati" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Mostra la ricerca in linea" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Clic sinistro su un'intestazione di colonna" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Aggiungi la colonna alla lista di colonne sulle quali ordinare" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Vista ad albero" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Collassa l'elemento o seleziona l'elemento padre" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Espande l'elemento" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Voci di testo" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Annulla l'ultimo cambiamento" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Ripeti l'ultimo cambiamento annullato" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Seleziona tutti i brani in tutti i pannelli" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtro su %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Tutte le _intestazioni" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Intestazioni delle _tracce" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Intestazioni degli _album" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Intestazioni delle pe_rsone" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Intestazione della _data" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Intestazioni dei _file" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Intestazioni della _produzione " #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "Personali_zza intestazioni…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Espandi colonna" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Eliminare traccia : \"%%(title)s\" dalla libreria?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Eliminare traccia : \"%%(title)s\" dalla libreria?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "_Rimuovi dalla libreria" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Eseguire il plugin \"%(name)s\" su %(count)d brano?" msgstr[1] "Eseguire il plugin \"%(name)s\" su %(count)d brani?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Eseguire il plugin \"%(name)s\" su %(count)d album?" msgstr[1] "Eseguire il plugin \"%(name)s\" su %(count)d album?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "_Configura i plugin…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Metti in _coda" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Rimuovi dalla libreria…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Impossibile mostrare i file" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Errore nel mostrare i file, o nessun programma disponibile per mostrarli." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "M_ostra nel gestore file" msgstr[1] "M_ostra %(total)d file nel gestore file" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Scaricamento…" msgstr[1] "_Scaricamento…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Salvatagggio fallito" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Scarica il file" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Scarica grafica copertina" msgstr[1] "Scarica grafica copertina" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Scarica il file" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Sostituisci _underscore con spazi" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Prime lettere maiuscole dei tag" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Separa in _valori multipli" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tag dal percorso" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "I tag rimpiazzano quelli esistenti" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "I tag sono aggiunti a quelli esistenti" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Il modello\n" "\t<b>%s</b>\n" "non è valido. Probabilmente contiene lo stesso tag due volte o ha parentesi " "non valide (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Il modello inserito non è valido. Fare attenzione ad inserire < e > " "come \\< e \\> e che i tuoi tag siano bilanciati.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Modifica visualizzazione" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Numeri delle tracce" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Parti _da:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Tracce totali:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Riproduci/Pausa" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Precedente" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "e altri %d…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Salvataggio dei brani che hai modificati." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d brani salvati\n" "(%(remaining)s rimanenti)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s di %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Controllo aggiornamenti" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Connessione fallita" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Stai già usando la versione %(version)s più recente " #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Una nuova versione %(new-version)s è disponibile\n" "\n" "Stai attualmente usando la versione %(old-version)s\n" "\n" "Visita il <a href='%(url)s'>sito web</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importa una scaletta" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Le scalette devono avere un nome" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Esiste già una scaletta chiamata %s." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Copertine dell'album incorporate" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Usa le copertine incorporate nei file audio." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Copertina filesystem" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Usa immagini nominate comunemente trovare in directory comuni insieme al " "brano." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Grafica copertina" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Interrogazione dei fornitori di grafiche degli album" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Mostra brevi informazioni sull'utilizzo" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Mostra versione e copyright" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Stampa informazioni di debug" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Uso: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opzioni]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Opzione %r non riconosciuta." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "L'opzione %r richiede un argomento." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r non è un prefisso unico." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s secondo" msgstr[1] "%s secondi" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Nessuna informazione sulla durata" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d secondo" msgstr[1] "%d secondi" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minuti" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d ora" msgstr[1] "%d ore" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d giorno" msgstr[1] "%d giorni" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d anno" msgstr[1] "%d anni" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "Prime lettere maiuscole nei tag" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "I formati di data corretti sono: 'AAAA', 'AAAA-MM-GG' oppuure 'AAAA-MM-GG HH:" "MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "I guadagni di Replay Gain devono essere nel formato 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "I valori di picco di Replay Gain devono essere nel formato 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "L'ID MusicBrainz deve essere nel formato UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Lo stato del rilascio di MusicBrainz deve essere 'ufficiale', " "'promozionale', o 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "La lingua dev'essere un codice ISO 639-2 di tre lettere" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Salvatagggio fallito" msgstr[1] "Salvatagggio fallito" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Impossibile modificare il brano" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Salvataggio di <b>%s</b> fallito. Il file potrebbe essere in sola lettura, " "corrotto, oppure non si hanno permessi sufficienti per modificarlo." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codifica non valida]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangiatore" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangiatori" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arrangiamento" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autore" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "commento" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compositore" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compositori" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "composizione" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "direttore" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "direttori" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "direzione" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contatto" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "descrizione" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genere" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "generi" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "esecutore" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "esecuzione" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "raggruppamento" #: quodlibet/util/tags.py:98 msgid "language" msgstr "lingua" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licenza" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "paroliere" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "parolieri" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "testi" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "etichetta discografica" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titolo" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versione" #: quodlibet/util/tags.py:106 msgid "website" msgstr "sito web" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "artista dell'album" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "Sottotitolo disco" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "traccia" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "ID etichetta" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "data d'uscita originale" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "album originale" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artista originale" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "data di registrazione" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "Stato di rilascio" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "ID MusicBrainz della registrazione" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "ID MusicBrainz della traccia del rilascio" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID MusicBrainz del rilascio" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "ID MusicBrainz dell'artista" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "ID MusicBrainz dell'artista del rilascio" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "ID MusicBrainz TRM" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Stato dell'album MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Tipo di album MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "" "ID MusicBrainz del \n" " del rilascio" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "guadagno della traccia" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "picco della traccia" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "guadagno dell'album" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "picco dell'album" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "volume di riferimento" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "dischi" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "tracce" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "ultimo avvio" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nome completo" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "punto di mount" #: quodlibet/util/tags.py:166 msgid "people" msgstr "persone" #: quodlibet/util/tags.py:168 msgid "year" msgstr "anno" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "anno d'uscita originale" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "segnalibro" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "profondità di bit" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "formato file" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "scalette" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "frequenza di campionamento" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "Numero del canale" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "ordina" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "ruoli" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor di tag audio" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Modifica i tag dei tuoi file audio." #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Riproduttore musicale" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Ascolta, esplora o modifica la tua collezione audio" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso è un editor di tag con la stessa interfaccia di modifica di tag di " "Quod Libet. Ti permette di mostrare e modificare qualunque tag tu voglia nel " "file, per tutti i formati di file che supporta." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "I formati di file supportati includono Ogg Vorbis/Opus/Speex/FLAC, MP3, " "FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC e " "MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet è un programma di gestione della musica. Fornisce diversi modi di " "visualizzare la tua libreria audio, come anche il supporto per radio " "Internet e feed audio. Ha capacità di ricerca e modifica estremamente " "flessibile di metadati tag." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Esporta a scaletta Squeezebox" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Impossibile aggiungere <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Tag non validi" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Tags <b>%s</b> non validi\n" #~ "\n" #~ "I file attualmente selezionati non supportano la modifica di questi tag." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Giudica automaticamente i brani quando sono riprodotti o saltati. Questo " #~ "usa l'algoritmo 'accelerated' da vux di Brian Nelson." #, fuzzy #~ msgid "Startup" #~ msgstr "Avvia importazione" #~ msgid "Audio Feeds" #~ msgstr "Feed audio" #~ msgid "_Audio Feeds" #~ msgstr "Feed a_udio" #~ msgid "New" #~ msgstr "Nuovo" #~ msgid "Automatic Library Update" #~ msgstr "Aggiornamento automatico libreria" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Mantiene la tua libreria aggiornata con inotify. Richiede %s." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Consente il controllo di Quod Libet usando la specifica d'interfaccia " #~ "DBUS MPRIS 1.0/2.0" #~ msgid "Searching for lyrics…" #~ msgstr "Ricerca di testi…" #, fuzzy #~ msgid "broker username" #~ msgstr "Nome dell'host del mediatore" #, fuzzy #~ msgid "broker password" #~ msgstr "porta del mediatore" #, fuzzy #~ msgid "<artist>" #~ msgstr "artista" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "titolo" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Esporta metadati dei brani selezionati come file .tags." #~ msgid "Import Metadata" #~ msgstr "Importa metadati" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Importa metadati per i brani selezionati da un file .tags." #~ msgid "Migrate Metadata" #~ msgstr "Migra metadati" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Copia metadati specifici di Quod Libet tra i brani." #~ msgid "_Copy" #~ msgstr "_Copia" #~ msgid "_Paste" #~ msgstr "_Incolla" #~ msgid "Information to copy/paste" #~ msgstr "Informazioni da copiare/incollare" #~ msgid "Map tracks by disc and track number" #~ msgstr "Mappa tracce per disco e numero traccia" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Abilita questo se vuoi migrare i metadati da un album ad un altro facendo " #~ "corrispondere i numeri di traccia e disco.\n" #~ "\n" #~ "<b>Nota:</b> questo deve essere abilitato quando i metadati sono copiati " #~ "perché le informazioni di traccia siano memorizzate." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "C'è %d traccia memorizzata." #~ msgstr[1] "Ci sono %d tracce memorizzate." #~ msgid "Unsupported file type" #~ msgstr "Tipo di file non supportato" #~ msgid "Unable to add station" #~ msgstr "Impossibile aggiungere la stazione" #~ msgid "Search Library" #~ msgstr "Cerca nella libreria" #~ msgid "_Search Library" #~ msgstr "_Cerca nella libreria" #~ msgid "Rate the playing song" #~ msgstr "Dai un giudizio al brano in riproduzione" #~ msgid "Quit Program" #~ msgstr "Esci dal programma" #~ msgid "ID3 encodings:" #~ msgstr "Codifiche _ID3:" #~ msgid "" #~ "ID3 encodings separated by spaces. UTF-8 is always tried first, and " #~ "Latin-1 is always tried last." #~ msgstr "" #~ "Codifiche ID3 separate da spazi. UTF-8 è provata sempre per prima, e " #~ "Latin-1 è provata sempre per ultima." #~ msgid "Search tags:" #~ msgstr "Ricerca di _tag:" #~ msgid "" #~ "Tags which get searched in addition to the ones present in the song list. " #~ "Separate with \",\"" #~ msgstr "" #~ "Tag che vengono cercati in aggiunta a quelli presenti nell'elenco brani. " #~ "Separali con \",\"." #~ msgid "Rating symbol (full):" #~ msgstr "Simbolo di giudizio (_pieno):" #~ msgid "Rating symbol (blank):" #~ msgstr "Simbolo di giudizio (_vuoto):" #~ msgid "Backend:" #~ msgstr "_Backend:" #~ msgid "Identifier of the playback backend to use" #~ msgstr "Identificatore del backend di riproduzione da usare" #~ msgid "Disable hints:" #~ msgstr "Disattiva _suggerimenti:" #~ msgid "Disable popup windows (treeview hints)" #~ msgstr "Disattiva finestre popup (suggerimenti della vista ad albero)" #~ msgid "Album cover size:" #~ msgstr "Dimensioni _copertina album:" #~ msgid "" #~ "Size of the album cover images in the album list browser (restart " #~ "required)" #~ msgstr "" #~ "Dimensioni delle immagini di copertina dell'album nel navigatore lista " #~ "degli album (richiede il riavvio)" #~ msgid "Disable multimedia keys:" #~ msgstr "Disattiva tasti _multimediali" #~ msgid "(restart required)" #~ msgstr "(richiede il riavvio)" #~ msgid "Main window title:" #~ msgstr "Titolo della _finestra principale:" #~ msgid "" #~ "A (tied) tag for the main window title, e.g. ~title~~people (restart " #~ "required)" #~ msgstr "" #~ "Un tag (legato) per il titolo della finestra principale, ad es. " #~ "~title~~people (richiede il riavvio)" #~ msgid "DateColumn timestamp format" #~ msgstr "Formato data/ora della _DateColumn" #~ msgid "A timestamp format, e.g. %Y%m%d %X " #~ msgstr "Un formato data/ora, ad es. %Y%m%d %X " #~ msgid "Scrollbars always visible:" #~ msgstr "Barre di sc_orrimento sempre visibili:" #~ msgid "" #~ "Toggles whether the scrollbars on the bottom and side of the window " #~ "always are visible or get hidden when not in use (restart required)" #~ msgstr "" #~ "Commuta la visibilità perenne delle barre di scorrimento al fondo e a " #~ "lato della finestra oppure le nasconde quando non in uso (richiede il " #~ "riavvio)" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Previene l'attivazione del salvaschermo di GNOME mentre è in riproduzione " #~ "un brano." #~ msgid "No lyrics found" #~ msgstr "Testi non trovati" #~ msgid "_Zoom level:" #~ msgstr "Livello di _zoom:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "_Cerca tramite l'URL sopra sei testi non possono essere trovati su " #~ "LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Ricerca alternativa" # controllare contesto #~ msgid "Web Lyrics" #~ msgstr "Testi Web" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Mostra una barra laterale contenente i testi online del brano corrente." #~ msgid "Skip Songs" #~ msgstr "Salta brani" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "La riproduzione salta i brani con un giudizio uguale o inferiore ad una " #~ "soglia data." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Supporta i modelli QL\n" #~ "ad es. <tt><~artist~title></tt>" #~ msgid "Burn CD" #~ msgstr "Scrivi CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Masterizza CD con K3b, Brasero o xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "Il nome di file di immagine singola da usare se selezionato" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "" #~ "Il file di immagine della grafica dell'album da usare quando forzato " #~ "(supporta caratteri jolly)" #~ msgid "Ignore" #~ msgstr "_Ignora" #~ msgid "Keep Songs" #~ msgstr "_Tieni i brani" #~ msgid "Device Properties" #~ msgstr "Proprietà del dispositivo" #~ msgid "Device:" #~ msgstr "Dispositivo:" #~ msgid "Not mounted" #~ msgstr "Non montato" #~ msgid "Mount point:" #~ msgstr "Punto di mount:" #~ msgid "Media Devices" #~ msgstr "Dispositivo multimediale" #~ msgid "_Media Devices" #~ msgstr "Dispositivo_Multimediale" #~ msgid "_Eject" #~ msgstr "_Espelli" #~ msgid "_Properties" #~ msgstr "Proprietà" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s usato, %(free-size)s disponibile" #~ msgid "%s is not connected." #~ msgstr "%s non è connesso." #~ msgid "Copying %(song)s" #~ msgstr "Sto copiando %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Impossibile copiare il brano" #~ msgid "There is not enough free space for this song." #~ msgstr "Non c'è abbastanza spazio libero per questa canzone." #~ msgid "%s could not be copied." #~ msgstr "%s non può essere copiato." #~ msgid "Unable to delete songs" #~ msgstr "Impossibile eliminare i brani" #~ msgid "Deleting %(song)s" #~ msgstr "Eliminazione %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s non può essere eliminato." #~ msgid "Unable to delete song" #~ msgstr "Impossibile eliminare il brano" #~ msgid "Ejecting %s failed." #~ msgstr "Esplusione %s fallita." #~ msgid "Unable to eject device" #~ msgstr "Impossibile espellere il dispositivo" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Nessun dispositivo di backend, il navigatore dei dispositivi multimediali " #~ "è disabilitato." #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Mostra o nascondi l'elenco dei brani principali (deprecated)" #~ msgid "Unknown Device" #~ msgstr "Dispositivo sconosciuto" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Impossibile importare %s, necessario per il supporto del dispositivo." #~ msgid "%r is not a supported device." #~ msgstr "'%r' non è un dispositivo supportato." #~ msgid "Initializing device backend." #~ msgstr "Annullo l'inizializzazione del dispositivo di backend." #~ msgid "Trying '%s'" #~ msgstr "Provo '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Non riesco a connettermi al backend del dispositivo" #~ msgid "Device backend initialized." #~ msgstr "Backend del dispositivo inizializzato" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "Schema per il nome del file" #~ msgid "_Clear" #~ msgstr "_Pulisci" #~ msgid "Lyrics:" #~ msgstr "Testi:" #~ msgid "Lyrics Window" #~ msgstr "Finestra dei Testi" #~ msgid "_Lyrics" #~ msgstr "_Testi" #~ msgid "Browse Folders" #~ msgstr "Sfoglia Cartelle" #~ msgid "Unable to open folders" #~ msgstr "Impossibile aprire le cartelle" #~ msgid "Audio device: %s" #~ msgstr "Dispositivo audio: %s" #~ msgid "Downloads" #~ msgstr "Scaricati" #~ msgid "Size" #~ msgstr "Dimensioni" #~ msgid "_Download" #~ msgstr "S_carica" #~ msgid "_Copy to Device" #~ msgstr "Copia sul dispositivo" #~ msgid "browsers" #~ msgstr "browser" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Impossibile importare% s. Browser dei feed audio disabilitato." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Un eccezione è occorsa in Quod Libet. E' stato salvato un file di dump in " #~ "<b>%s</b> che ci potrebbe aiutare a debuggare il crash. Per cortesia apri " #~ "un nuovo problema su http://code.google.com/p/quodlibet/issues/list ed " #~ "allega questo file o includi il suo contenuto. Questo file può contenere " #~ "alcune informazioni di identificazione circa te o il tuo sistema, come la " #~ "lista dei file recentemente ascoltati. Se questo è inaccettabile, invia " #~ "<b>%s</b> con una descrizione di quello che stavi facendo.\n" #~ "\n" #~ "Quod Libet può ora essere instabile. Si raccomanda di chiuderlo e " #~ "riavviarlo. La tua libreria sarà salvata." #~ msgid "Unable to download lyrics." #~ msgstr "Impossibile scaricare i testi" #~ msgid "Remove all songs from the queue" #~ msgstr "Rimuovi tutti i brani dalla coda" #~ msgid "Set or toggle the playback order" #~ msgstr "Imposta o commuta l'ordine d'esecuzione" #~ msgid "Uninitialized iPod" #~ msgstr "Inizializzazione di iPod annullata" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Vuoi creare un database vuoto su questo iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volume (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combina i tag con valori _multipli" #~ msgid "Capacity:" #~ msgstr "Capienza:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Non riesco a salvare il database iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Non riesco a salvare il database iPod" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Impossibile trovare libgpod, supporto per iPod disabilitato." #~ msgid "Track Repeat" #~ msgstr "Ripeti Traccia" #~ msgid "Shuffle" #~ msgstr "Casuale" #~ msgid "Weighted" #~ msgstr "In base al Giudizio" #~ msgid "_Weighted" #~ msgstr "In base al _Giudizio" #~ msgid "_One Song" #~ msgstr "_Un Brano" #~ msgid "Restart the playlist when finished" #~ msgstr "Ricomincia la scaletta una volta finito" #~ msgid "Disable Browser" #~ msgstr "Disattiva il Catalogo" #~ msgid "_Disable Browser" #~ msgstr "_Disattiva il Catalogo" #~ msgid "Force Write" #~ msgstr "FOrza Scrittura" #~ msgid "Filter on _Genre" #~ msgstr "Filtro sul _genere" #~ msgid "Filter on _Artist" #~ msgstr "Filtro sull'_artista" #~ msgid "Filter on Al_bum" #~ msgstr "Filtro sull'al_bum" #~ msgid "_Music" #~ msgstr "_Musica" #~ msgid "Add Bookmark" #~ msgstr "Aggiungi Segnalibri" #~ msgid "Song _List" #~ msgstr "_Lista dei Brani" #~ msgid "D:" #~ msgstr "D:" #~ msgid "W:" #~ msgstr "W:" #~ msgid "E:" #~ msgstr "E:" #~ msgid "Stop _after this song" #~ msgstr "Ferma _dopo questo brano" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "e altri %d ..." #~ msgstr[1] "e altri %d ..." #~ msgid "Split _disc from album" #~ msgstr "Dividi i dischi dell'album" #~ msgid "Timeout" #~ msgstr "Timeout" #~ msgid "Select an album" #~ msgstr "Seleziona un album" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s e %(count)d altro" #~ msgstr[1] "%(title)s e %(count)d altro..." #~ msgid "Playlist Export" #~ msgstr "Esporta Playlist" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Usa angoli arrotondati nelle anteprime" #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Arrotondare gli angoli delle immagini in miniatura delle copertine degli " #~ "album." #~ msgid "Re_fresh Library" #~ msgstr "A_ggiorna la Libreria" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Rimuovi Stazione" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer non ha l'elemento per gestire i file in lettura. Controlla i " #~ "settaggi della tua installazione di GStreamer." #~ msgid "Invalid audio backend" #~ msgstr "Audio backend invalido" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "L'audio backend %r non è installato." #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "nome del file" #~ msgid "command|tag" #~ msgstr "tag" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Non trovo libudev." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Cerca" #~ msgid "%d of %d" #~ msgstr "%d di %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Utilizzo: %s %s" #~ msgid "_Download..." #~ msgstr "_Scarica..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nuova Stazione" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Sovrascrivere <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Output Error" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Il GStreamer output pipeline non può essere inizializzato. Il pipeline " #~ "può essere invalido, o il dispositivo può essere in uso. Controlla le " #~ "preferenze del lettore multimediale." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet è già in esecuzione." #~ msgid "No song is currently playing." #~ msgstr "Nessun brano è attualmente in esecuzione" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Impossibile scrivere su %s. Rimosso." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Modifica Segnalibri..." #~ msgid "_New Folder..." #~ msgstr "_Nuova Cartella..." #~ msgid "_Add to Playlist" #~ msgstr "Metti in _Scaletta" #~ msgid "_Edit Display..." #~ msgstr "_Modifica Display..." #~ msgid "Output Log" #~ msgstr "Output Log" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stazione" #~ msgid "_Add a Location..." #~ msgstr "_Aggiungi una Posizione..." #~ msgid "_Output Log" #~ msgstr "_Output Log" #~ msgid "Invalid command %r received." #~ msgstr "Ricevuto il commando invalido %r." #~ msgid "Unknown browser %r." #~ msgstr "Browser sconosciuto %r." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Personalizza gli Headers..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #~ msgstr[1] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #~ msgstr[1] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #~ msgid "Track Headers" #~ msgstr "Headers delle Tracce" #~ msgid "People Headers" #~ msgstr "Headers della Gente" #~ msgid "Album Headers" #~ msgstr "Headers degli Album" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Headers della _Data" #, fuzzy #~ msgid "File Headers" #~ msgstr "Headers dei _File" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Headers della _Produzione " #~ msgid "Tag:" #~ msgstr "Tag:" #~ msgid "Too Many Errors" #~ msgstr "Troppo errori" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Riproduzione arrestata poiché vi sono stati %d errori consecutivi." #~ msgid "Warnings" #~ msgstr "Avvertimenti" #~ msgid "No log available." #~ msgstr "Nessun log disponibile." #~ msgid "album artist (sort)" #~ msgstr "artista dell'album" #~ msgid "artist (sort)" #~ msgstr "artista" #~ msgid "album (sort)" #~ msgstr "album" #~ msgid "performer (sort)" #~ msgstr "esecutore" #~ msgid "performers (sort)" #~ msgstr "esecutori" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID MusicBrainz dell'artista dell'album" #~ msgid "errors" #~ msgstr "errori" #~ msgid "Permanently delete this file?" #~ msgstr "Eliminare permanentemente questo file?" #~ msgid "Permanently delete these files?" #~ msgstr "Eliminare permanentemente questi file?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s e altri %(count)d..." #~ msgstr[1] "%(title)s e altri %(count)d..." #~ msgid "Version:" #~ msgstr "Versione:" #~ msgid "_Cause an Error" #~ msgstr "_Causa un Errore" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "Non è stato possibile aggiungere %s alla libreria\n" #, fuzzy #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Errore mentre eseguo il comando %r, causato da: %r)." #~ msgid "No eject command found." #~ msgstr "Nessun comando di espulsione trovato" #~ msgid "Unable to start web browser" #~ msgstr "Impossibile avviare un browser web" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Non è stato trovato alcun browser web. Impostare la variabile $BROWSER, o " #~ "verificare l'esistenza di /usr/bin/sensible-browser." #, fuzzy #~ msgid "Library Error" #~ msgstr "Esplora la Libreria" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Output pipeline:" #~ msgid "translator-credits" #~ msgstr "Filippo Pappalardo <filippo@email.it>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Altre intestazioni da mostrare, separate da spazi" #~ msgid "_Edit and Continue" #~ msgstr "_Modifica e Continua" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #~ msgstr[1] "" #~ "Stai per modificare il voto di %d tracce.\n" #~ "Desideri proseguire?" #~ msgid "Confirm rating" #~ msgstr "Chiedi conferma del voto" #~ msgid "Search your library" #~ msgstr "Cerca nella libreria audio" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, e altri\n" #~ "\n" #~ "Questo è software libero; vedi il codice sorgente per le condizioni di " #~ "copia. Non c'è\n" #~ "garanzia; neppure per la COMMERCIALIZZAZIONE o per L'ADEGUATEZZA AD UNO " #~ "SCOPO PARTICOLARE.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r non contiene alcun browser." #~ msgid "Total size unknown" #~ msgstr "Dimensione totale sconosciuta" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r non contiene alcun dispositivo." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: Non riesco a importare i ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Non trovo le informazioni di media-player." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: Non trovo libudev." #~ msgid "Quod Libet Plugins" #~ msgstr "Plugin di Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Colora le stringhe di ricerca semplici in blu, avanzate in verde, non " #~ "valide in rosso" #~ msgid "Separators for splitting tags" #~ msgstr "Separatori per dividere i tag" #~ msgid "Quod Libet Preferences" #~ msgstr "Preferenze di Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Non ascoltati o_ggi" #~ msgid "Not Played in a _Week" #~ msgstr "Non ascoltati da una _settimana" #~ msgid "Not Played in a _Month" #~ msgstr "Non ascoltati da un _mese" #~ msgid "B_ottom 40" #~ msgstr "_Ultimi 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "I 40 brani meno ascoltati" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "Date" #~ msgstr "Data" #~ msgid "Choose New Stations" #~ msgstr "Scegli Nuove Stazioni" #~ msgid "Add" #~ msgstr "Aggiungi" #~ msgid "Bitrate" #~ msgstr "Bitrate" #~ msgid "_Stations..." #~ msgstr "_Stazioni..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Sto inizializzando l'audio backend (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Sto inizializzando la libreria principale (%s)" #~ msgid "Unable to save library" #~ msgstr "Impossibile salvare la libreria" #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Impossibile esportare i log, sei bloccato." #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "L'audio output pipeline %r non può essere creato. Controlla le tue " #~ "impostazioni di GStreamer in ~/.quodlibet/config." #~ msgid "Sort by title" #~ msgstr "Ordina per titolo" #~ msgid "Sort by artist" #~ msgstr "Ordina per artista" #~ msgid "Lyrics provided by %s." #~ msgstr "Testi forniti da %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Nessun testo trovato.\n" #~ "\n" #~ "Si può cliccare sul pulsante Scarica per cercare testi online.E' " #~ "possibile anche inserire manualmente il testo e salvarlo." #~ msgid "part" #~ msgstr "parte" #~ msgid "Opening audio device." #~ msgstr "Apertura del dispositivo audio." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d brani modificati" #~ msgid "MusicBrainz album ID" #~ msgstr "ID MusicBrainz dell'album" #~ msgid "Loaded song library." #~ msgstr "Libreria audio caricata." #~ msgid "Unable to open audio device" #~ msgstr "Impossibile accedere al dispositivo audio" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet ha cercato di accedere ai driver 'autosink' e '%(sink)s' ma " #~ "senza successo. Imposta le preferenze di GStreamer cambiando il valore\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet non è riuscito a trovare l'elemento GStreamer " #~ "'filesrc.'Controlla l'installazione di GStreamer." #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "Mostra le _Cover degli album" #~ msgid "Unable to retag multiple values" #~ msgstr "Impossibile rietichettare valori multipli" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Cambiare il nome di un tag con valori multipli non è supportato." #~ msgid "W: %s is not a QL song database." #~ msgstr "W. %s non è un database di QL" #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Per brano (\"Radio\")" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Per album (\"Audiofilo\")" #~ msgid "_Volume Normalization" #~ msgstr "Normalizzazione del _Volume" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Quod Libet sta aggiornando la libreria. Possono volerci alcuni minuti.\n" #~ "\n" #~ "%d brani ricaricati\n" #~ "%d brani rimossi" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Quod Libet sta rilevando nuovi brani da aggiungere alla libreria.\n" #~ "\n" #~ "%d brani aggiunti" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "Le scalette M3U non possono essere caricate." #~ msgid "This station is already in your library." #~ msgstr "Questa stazione è già nella libreria" #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "di <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disco <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Traccia <tracknumber>>>" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/ja.po����������������������������������������������������������������������������0000644�0001750�0001750�00001014561�14436352625�013575� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Japanese translations for PACKAGE package. # Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Yasushi Iwata <yasusii@lowlife.jp>, 2006. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.23\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-05-20 14:48+0000\n" "Last-Translator: Takashi Ueda <samus39@gmail.com>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/ja/>\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Weblate 4.18-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "タイトル(_T)" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "ピープル(_P)" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "日付(_D)" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "登録日時(_D)" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "オリジナルリリース日時(_O)" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "ジャンル(_G)" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "評価(_R)" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "再生回数(_C)" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "ソート(_B)…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "設定(_P)" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "アルバムリスト" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "アルバムリスト(_A)" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "全てのアルバム" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%dアルバム" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "アルバムカバーを再読込(_C)" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "どのアルバムにも属さない曲" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%dトラック" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%dディスク" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "サンプルアルバム" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "アルバムリストの設定" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "アルバムカバーを表示する(_C)" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "インライン検索対象にピープルタグを含める(_S)" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "オプション" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "アルバムの表示" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "閉じる(_C)" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "ライブラリブラウザ" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d曲" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "不正なパターン" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "アルバムコレクション" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "アルバムコレクション(_C)" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "不明な%s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "複数の%s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "カスタム(_C)" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "追加(_A)" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "削除(_R)" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "タグ" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "マージ" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "アルバムコレクションの設定" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "適用(_A)" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "キャンセル(_C)" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "カバーグリッド" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "カバーグリッド(_C)" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "カバーグリッドの設定" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "アルバムのテキストを表示する(_T)" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "「全てのアルバム」を表示する" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "ワイドモード" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "カバーの表示倍率" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "ファイルシステム" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "ファイルシステム(_F)" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "曲のコピーができません" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "選択されたファイルのソングリストまたはキューへのコピーに失敗しました。" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "ライブラリに追加(_A)" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "ステーションリストに含められるのはそのラジオ局のプレイリストだけで、他局のリ" "ストや他局のプレイリストを含めることはできません。以下の場所は読み込みできま" "せんでした:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "インターネットラジオ" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "ラジオ局の追加" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "ラジオ局リストをダウンロード中" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "新規ラジオ局" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "インターネットラジオ局の場所を入力してください:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "エレクトロニック" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "ヒップホップ/ラップ" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "オールディーズ" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "日本" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "インド" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "宗教音楽" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "チャート" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "トルコ" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "レゲエ/ダンスホール" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "ラテン" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "カレッジラジオ" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "トーク/ニュース" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "アンビエント" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "ジャズ" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "クラシック" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "ポップ" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "オルタナティブ" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "メタル" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "カントリー" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "ニュース" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "シュラーガー" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "ファンク" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "インディーズ" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "ブルース" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "ソウル" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "ラウンジ" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "パンク" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "レゲトン" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "スラブ" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "ギリシャ" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "ゴシック" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "ロック" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "人気ラジオ局のリストをロードしますか?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "ラジオ局のロード(_L)" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "インターネットラジオ(_I)" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "全てのラジオ局" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "お気に入り" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "カテゴリなし" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "ラジオ局の追加(_A)…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "ラジオ局の更新(_U)" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "ラジオ局が見つかりません" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s にインターネットラジオ局が見つかりません。" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "追加するものはありません" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "一覧にあるラジオ局は全てライブラリに登録されています。" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "お気に入りに追加" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "お気に入りから削除" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d局" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "ペインブラウザ" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "ペインブラウザ(_P)" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "全て選択(_A)" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "不明" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "全て" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "スモール" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "ワイド" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "カラムナー" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "任意にマークアップ可能なタグパターン。例: <tt>composer</tt> や\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "ペインブラウザの設定" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "カラムレイアウト" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "カラム内容" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "ペインの幅を揃える" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "プレイリスト" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "プレイリスト(_P)" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "プレイリストから削除(_R)" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "新規(_N)" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "インポート(_I)…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "プレイリストをインポートできません" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet は M3U/M3U8 と PLS 形式のプレイリストのみインポートできます。" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "削除(_D)" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "名前の変更(_R)" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "プレイリストの名前を変更できません" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "プレイリストのインポート" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "インポート(_I)" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "新規プレイリスト(_N)…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "それらの%d曲をどうしますか?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "プレイリスト「%s」へのアクションの確認" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "空" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "サンプルプレイリスト" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "プレイリストブラウザの設定" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "プレイリストの表示" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "プレイリスト「%s」を削除してもよろしいですか?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "選択したプレイリストに関する全ての情報が削除され、復元できなくなります。" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "「{pl_name}」に{num}個のトラックを追加しますか?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "トラックの追加(_A)" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "新規プレイリスト" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "プレイリスト名を入力してください:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "作成(_C)" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "プレイリストをインポートしています。\n" "\n" "%(current)d/%(total)d曲を追加しました。" #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "新規フィード" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "ポッドキャスト/オーディオフィードの場所を入力してください:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "ポッドキャスト" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "ポッドキャスト(_P)" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "フィードの追加(_A)…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "再表示(_R)" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "新着エピソードを検索します" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "再構築(_R)" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "既存のエピソードを全て削除してから再読込します" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "このポッドキャストとエピソードを削除します" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "フィードを追加できません" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s を追加できませんでした。サーバがダウンしているか、もしくはポッドキャスト/" "オーディオフィードの場所を間違えている可能性があります。" #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "現在のオーディオバックエンドはURLに対応していないため、ポッドキャストブラウザ" "は無効になっています。" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "検索結果の上限を設定(_L)" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "複数クエリを可能にする(_A)" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "トラックリスト" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "トラックリスト(_T)" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "SoundCloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "SoundCloudブラウザ" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "SoundCloud(_C)" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "検索" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "マイトラック" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "%s を開く" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "接続完了" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet が接続されました、%s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "%s からログアウト" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "コードを入力…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "%s にログイン" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "SoundCloud 認証" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "SoundCloud 認証コードを入力してください:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libetは実行中ではありません (オプション「--run」を追加すると起動)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "ミュージックライブラリ/プレイヤー" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[オプション]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "再生中の曲名を表示" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "直ちに再生開始" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "ウィンドウを表示せずに起動" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "次の曲にジャンプ" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "前の曲にジャンプ、または最初から再生(冒頭付近を再生中の場合)" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "前の曲にジャンプ" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "再生開始" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "一時停止" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "再生/一時停止をトグル" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "再生停止" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "音量を上げる" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "音量を下げる" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "再生中の曲の評価を1つ上げる" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "再生中の曲の評価を1つ下げる" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "プレイヤーの状態を表示" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "メインウィンドウを非表示" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "メインウィンドウを表示" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "メインウィンドウの表示状態をトグル" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "実行中のプレイヤーをフォーカス" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "ブラウザからフィルターを削除" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "ライブラリをリフレッシュおよび再スキャン" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "利用可能なブラウザの一覧を表示" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "現在のソングリストを表示" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "キューの内容を表示" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "アクティブなテキストクエリを表示" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "プラグインなしで起動" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Quod Libetが実行中でなければ起動" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quod Libetを終了" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "再生中の曲をシーク" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "シャッフルモードをオフ/オンまたはトグル" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "シャッフルモードのタイプを設定" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "リピートモードをオフ/オンまたはトグル" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "リピートモードのタイプを設定" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "音量を設定" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "オーディオライブラリを検索" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "クエリ" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "ファイルを再生" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "ファイル名" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "再生中の曲の評価を設定" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "現在のブラウザを変更" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "再生中の曲の後で停止" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "新しいブラウザウィンドウを開く" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "キューを表示/非表示" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "ランダムな値でフィルタリング" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "タグ" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "タグの値でフィルタリング" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "タグ=値" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "ファイルまたはクエリ結果をキューに追加" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "カンマ区切りで指定したファイルをキューに追加" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "ファイル名" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "クエリ結果のファイル名を標準出力に出力" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "ファイルまたはクエリ結果をキューから削除" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "ファイルまたはディレクトリをライブラリに追加" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "場所" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "「--print-*」コマンド用のテンプレートを設定" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "パターン" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "「%s」の引数が不正です。" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "「%s --help」を試してみてください。" #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "エラーが発生しました" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "このエラーは無視してもかまいませんが、アプリケーションを再起動するまで不安定" "になる可能性があります。エラー報告の提出は数秒しかかかりませんが、大変助かり" "ます。" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "エラー報告の提出" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "再起動" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "エラーを無視" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "エラー詳細:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "エラーやシステムに関するさまざまな詳細が、サードパーティのオンラインサービス " "(<a href='https://www.sentry.io'>www.sentry.io</a>) に送信されます。送信前に" "データを確認することができます。" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(省略可能) エラーが発生したときの状況を簡単に説明してください:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "送信(_S)" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "短い説明…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "送信するデータ:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "オーディオタグエディタ" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "ディレクトリ" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "オーディオメタデータエディタ" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "アートワークURLカバーソース" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "<tt>artwork_url</tt> タグでリンクされたカバーアートをダウンロードします。これ" "は SoundCloud ブラウザとポッドキャストブラウザで動作します。" #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogsカバーソース" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Discogs からカバーアートをダウンロードします。" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fmカバーソース" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Last.fm のカバーアートアーカイブからカバーアートをダウンロードします。" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainzカバーソース" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" "MusicBrainz のカバーアートアーカイブからカバーアートをダウンロードします。" #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "エンコーディングの変換" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "タグエディタで誤って解釈されたタグ値のエンコーディングを修正します。" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "エンコーディングの変換(_C)…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "漢字→かな(ローマ字)変換" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "名前を変更する前に、かな/漢字をローマ字に変換します。" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "日本語のテキストをローマ字化する(_J)" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "「Kanji Kana Simple Inverter」(KAKASI) が見つかりませんでした。" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "正規表現置換" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "ファイルのタグ付けまたは名前変更時に、任意の正規表現置換 (<tt>s/from/to/</" "tt>) を許可します。" #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "タイトルケース" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "タグエディタでタグの値をタイトルケースにします。" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "タイトルケース(_C)" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "タグで全大文字の単語を使えるようにする(_A)" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "人間的なタイトルケース(_H)" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "タイトルケースとして一般的な英語のルールを使用します (「Dark Night of the " "Soul」のように)" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "高度な設定" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "高度な設定の編集を可能にします。" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "理解した上で編集" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "アニメート・オンスクリーンディスプレイ" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "曲が変わったときに画面に曲情報を表示します。" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "位置(_P):" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "カバーのサイズ(_C):" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "表示" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "フォント(_F):" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "左" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "中央" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "右" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "位置揃え(_A):" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "テキスト" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "テキスト(_T):" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "背景(_F):" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "色" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "影付き(_S)" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "輪郭線(_O)" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "丸い角(_N)" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "遅延時間(_D):" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "エフェクト" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "ディスプレイの編集(_I)…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "プレビュー" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "アプリケーション情報" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "アプリケーションやその環境に関するさまざまな情報を提供します。" #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "対応している形式" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "設定ディレクトリ" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "キャッシュディレクトリ" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "オーディオバックエンド" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "再生された後 (デフォルト)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "曲が再生されたがスキップもされなかった場合に、ファイルにタグを書き込みます。" "スキップ回数はファイルには一切保存されないので、不必要な書き込みを避けること" "ができます。" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "再生またはスキップされた後" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "曲が再生またはスキップされるたびに、ファイルにタグを書き込みます。嫌いな曲、" "つまりスキップした曲の評価が確実にファイルに書き込まれるようにしたい場合に便" "利です。" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "一度だけ、アルバム全体が評価されたとき" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "曲が再生またはスキップされたとき、その曲のアルバムがチェックされます。アルバ" "ム内の全ての曲が評価済みで、少なくとも1曲について評価や再生回数がファイルに保" "存されていない場合に、その曲のファイルにタグを書き込みます。\n" "\n" "ファイルが更新されないようにするために使いますが、一度アルバムが更新された後" "は、修正された評価や再生回数をファイルに書き込みたいときには「ファイルタグの" "更新」プラグインを使わなければならないことに注意してください。" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "アルバムのタグを書き込むとき、まず再生回数が0の曲を1に変更します。\n" "嫌いな曲がすでに分かっている場合もあるので、保存時に1にしておくと、聴き終わっ" "たアルバム (%s) を検索するときに便利です。" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "「%s」を書き込めませんでした" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "ファイルタグの自動更新" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "曲が再生されたら、そのファイルのタグを更新します。これにより再生回数と評価が" "最新になります。" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "このプラグインが動作するために必要な、以下の設定を有効にしました:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "評価と再生回数をタグに保存する(_C)" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "設定更新" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "%s でエラーが発生しました" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "保存時に再生回数が0回より多くなるようにする" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "更新方法(_U):" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "設定" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "自動マスキング" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "ドライブがアンマウントまたはマウントされたときに、自動的にドライブをマスクお" "よびマスク解除します。" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "自動評価" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "曲の再生やスキップ時に自動的に評価を設定します。これは Brian Nelson による " "vux (Vacillating Utilitarian eXtemporizer) の「加速」アルゴリズムを使用してい" "ます。" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "指定された Banshee データベースが不正であるか、または見つかりません" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "インポート失敗" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "%d曲の評価と統計情報を正常にインポートしました" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Bansheeインポート" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Banshee から評価と曲の統計情報をインポートします。" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "データベースのパス(_D):" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "インポート開始" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "アラームクロック" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "大音量の音楽で目を覚まさせます。" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "ララバイ" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "音楽をフェードアウトして一時停止します。" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discordステータスメッセージ" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discordステータスメッセージ" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "現在聴いている曲に従って、Discord のステータスメッセージを変更します。" #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "一時停止" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "ステータスライン#1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "ステータスライン#2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "フラット" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "ライブ" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "フル・ベース&トレブル" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "クラブ" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "ラージホール" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "パーティ" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "ソフト" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "フル・ベース" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "レゲエ" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "ヘッドフォン" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "ソフトロック" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "フル・トレブル" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "ダンス" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "テクノ" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "スカ" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "ラップトップ" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "イコライザー" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "イコライザーで音楽のトーンを制御します。\n" "クリックまたはキー操作でレベルをカスタマイズできます (帯域を右クリックすると" "リセットされます)。" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "現在のバックエンドはイコライザーに対応していません。" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "デフォルトプリセット" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "選択…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "EQをリセット(_R)" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "カスタムプリセット" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "選択項目を削除(_D)" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "保存するプリセット名:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "保存(_S)" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "オンライン" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "オフライン" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "チャット可" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "離席中" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "不在" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "隠れ中" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajimステータスメッセージ" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "現在聴いている曲に従って、Gajim のステータスメッセージを変更します。" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "一時停止" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "パターン:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "ステータスメッセージを変更するアカウントを、スペースで区切って指定してくださ" "い。何も指定しない場合は、全てのアカウントのステータスメッセージを変更しま" "す。" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "アカウント:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "「[一時停止]」を追加する" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "チェックした場合、一時停止時にステータスメッセージに「[一時停止]」が追加され" "ます" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "メッセージが変更されるステータス" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "ヘッドフォンが抜かれたら一時停止" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "ヘッドフォンが抜かれたときに一時停止し、再び接続されたときに一時停止を解除し" "ます。" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "スクリーンセーバー/サスペンドの禁止" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "GNOME デスクトップでの曲の再生中に、スクリーンセーバーのアクティブ化やコン" "ピューターのサスペンドを防止します。" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "音楽再生中" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "モード:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "スクリーンセーバーを禁止する" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "サスペンドを禁止する" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "インターネットラジオログ" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "インターネットラジオ局で再生された直近の10曲を記録し、シークのコンテキストメ" "ニューに一覧表示します。" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Jabber User Tunes ファイルを「%(path)s」に出力します。" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "言語の変更" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "ユーザーインターフェースの言語を変更します。" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "システムのデフォルト" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "変更を有効にするには再起動が必要です" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AVメディアサーバー" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "MediaServer2 D-Bus インターフェースを介して、Rygel UPnP メディアサーバーで全" "アルバムを公開します。" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Rygel の設定ファイル (~/.config/rygel.conf) に以下が記述されていることを確認" "してください:" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPDサーバー" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "MPD クライアントを使用した Quod Libet のリモートコントロールを可能にします。" "ストリーミング、プレイリスト、ライブラリ管理には対応していません。" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "ポート(_P):" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "ローカルIP(_I):" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "パスワード(_A):" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "接続情報" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "テスト済みのクライアント" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Busサポート" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "<a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a> D-Bus イン" "ターフェース仕様を使用した Quod Libet の制御を可能にします。これにより様々な " "Linux デスクトップ統合 (マルチメディアキーなど) が可能になります。" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "メインウィンドウが閉じられる代わりに非表示" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "QLパターンを受け付けます。例: %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTTパブリッシャー" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "MQTT トピックにステータスメッセージを発行します。" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "ブローカーのホスト名 / IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "デフォルトは localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "ブローカーのポート" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "デフォルトは 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "ブローカーのユーザー名" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "ブローカーのパスワード" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "トピック" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "再生パターン" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "再生開始したときのステータステキスト。" #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "一時停止パターン" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "一時停止したときのステータステキスト。" #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "曲なしテキスト" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "曲を再生していないときのプレーンなステータステキスト" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTTの設定" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "ステータステキスト" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "%(host)s:%(port)d のブローカーに接続しました" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "%(host)s:%(port)d に接続できません (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "接続エラー" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainzと同期" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "曲の評価を MusicBrainz と同期します。" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "ユーザー名(_N):" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "パスワード(_P):" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "アカウント" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "通知テキスト" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "タイトル(_T):" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "デフォルトのパターンに戻す" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "本文(_B):" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "通知の表示(_S)" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "通知の表示" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "<i>手動</i>での曲変更時のみ(_M)" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "<i>自動</i>での曲変更時のみ(_A)" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "曲変更時は<i>常に</i>(_L)" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "メインウィンドウがフォーカスされていない時のみ(_F)" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "「次へ」ボタンを表示する(_N)" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "接続エラー" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "通知デーモンに接続できません。" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "曲の通知" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "曲が変わったときに通知を表示します。" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "次へ" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "ブックマーク通知" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "通知を使用して、ブックマーク/コメントをリアルタイムで表示します。SoundCloud " "ブラウザでうまく機能します。" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "プラグインウインドウで QLScrobbler の設定を行ってください。それまでは、曲情報" "の送信はできません。" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "サービス「%s」に接続できません。" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "認証失敗: 不正なURLです。" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "認証失敗: 不正なユーザー名「%s」か、不正なパスワードです。" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "クライアントは禁止されています。作者に連絡してください。" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "システム時刻が間違っています。 修正されるまで、送信は失敗する可能性がありま" "す。" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Audioscrobblerの送信" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Last.fm、Libre.fm およびその他の Audioscrobbler サービス用の Audioscrobbler " "クライアントです。" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "認証成功しました。" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "サービス(_S):" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "URL(_U):" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "その他…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "アカウントデータの確認(_V)" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "アーティストパターン(_A):" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "タイトルパターン(_T):" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "除外フィルター(_F):" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "送信用にアーティスト名をフォーマットするためのパターン。通常は空白のままにし" "ます。" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "送信用にタイトルをフォーマットするためのパターン。通常は空白のままにします。" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "このフィルターに一致する曲は送信されません" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "オフラインモード(何も送信されない)(_O)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "送信" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "ラジオ広告のミュート" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "インターネットラジオ広告の再生中に出力をミュートします。\n" "インターネットラジオ局: di.fm。" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "ランダムアルバム再生" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "プレイリストが最後まで達すると、ランダムなアルバムの再生を開始します。アク" "ティブなブラウザがアルバムによるフィルタリングに対応している必要があります。" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "評価が高い" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "再生回数が多い" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "スキップ回数が多い" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "最近再生された" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "最近再生開始された" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "最近追加された" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "長いアルバム" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "秒後に次のアルバムを開始する" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "ウェイト" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "一部のアルバムを他のアルバムより多く再生する" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "避ける" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "好む" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "ランダムアルバム" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "%s の開始を待機中" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "%d曲の評価と統計情報を正常にインポートしました" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmboxインポート" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Rhythmbox から評価と曲の統計情報をインポートします。" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "スクリーンセーバー中に一時停止" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "GNOME スクリーンセーバーがアクティブな間、再生を一時停止します。" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Quod Libet 用の GNOME シェル検索プロバイダがインストールされていません。" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "iniファイルを %s (または同様の場所) にコピーしましたか?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME検索プロバイダ" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "GNOME シェルによるライブラリの検索を許可します。" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "オルタナティブ・シークバー" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "常に表示され、ウィンドウの幅全体に広がる代替シークバーです。" #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "シークポイント・ブックマーク" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "トラックのシークポイント A や B を保存しておくと、トラックが再生されたとき、" "時間 A にスキップし、時間 B の後に停止します。\n" "\n" "ℹ 以下のポイントの名前を変更しても、実際のブックマーク名は更新されず、シーク" "するかどうかを決める際にどのブックマーク名を見るかが変更されるということに注" "意してください。" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "ポイント A のブックマーク名" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "トラックが開始されたときにチェックするブックマーク名。見つかった場合はそのタ" "イムスタンプにシークします" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "ポイント B のブックマーク名" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "トラックの再生中に使用するブックマーク名。現在位置がタイムスタンプを越えた場" "合、トラックの終端までシークします。" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezeboxと同期" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Logitech Squeezebox が Quod Libet の出力をミラーリングするようにします (両方" "が同一のライブラリから読み込まれる場合)。" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "「<a href=\"%(plugin_link)s\">Squeezeboxにエクスポート</a>」プラグインと設定" "を共有します。" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Squeezebox サーバ検索エラー" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "「%s」の検索エラーです。設定を確認してください" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "一時停止時に停止" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "このプラグインは、一時停止を停止/再生/シークに変更します。\n" "\n" "新しいデバイス (Bluetoothスピーカー、USB DACなど) がシステムに追加されたとき" "に Quod Libet がオーディオデバイスを切り替えることができない場合に便利で" "す。\n" "\n" "「シーク可能なソースのみ」がオフになっている限り、現在のソース内の位置が維持" "されるようにします。それ以外の場合、再生は停止したままになり、最初から再開す" "る必要があります。" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "シーク可能なソースのみ" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "プラグインオプション" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "コピー保留中" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "削除保留中" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "削除" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "スキップ" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "重複" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "同期中" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "削除中" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "成功" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "失敗" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "既存ファイルをスキップ" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "曲のファイル名を設定できません。" #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "デバイスと同期" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "選択した保存済み検索の全ての曲を、指定したフォルダと同期します。" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "以下の保存済み検索を同期:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "エクスポート先の絶対パス" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "保存された検索に含まれない、保存先フォルダ内の既存のファイルは全て削除されま" "す。" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "MTP でマウントされているデバイスの場合は、ローカルの保存先フォルダにエクス" "ポートしてから、rsync を使用してデバイスに転送します。または、多くのファイル" "を Android デバイスに同期する場合は、はるかに高速な adb-sync を使用します。" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "保存先パス:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "パスのパターン" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "保存済みのパターンの編集…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "エクスポートされるファイルのタグに基づいた、ファイル名の構造" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "エクスポートパターン:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "プレビューを中止" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "状態" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "ソースファイル" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "エクスポートパス" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "重複したエクスポートパスが検出されました! 上記のエクスポートパスは、同期を開" "始する前に編集することができます。" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "保存先パスにある既存のファイルは削除されます (ただし「cover.jpg」は除く) !" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "同期の開始" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "同期の中止" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "保存済み検索はまだありません。作成して戻ってきてください!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "保存先パスを選択" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "ファイル [{filename}] のエクスポートパスを [{old_path}] から [{new_path}] に" "変更" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "同期プレビュー開始" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "同期プレビューが進行中です。" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "同期プレビュー完了" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "同期プレビュー停止中" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "同期プレビューを中止しました。" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "同期プレビューが完了しました。" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "同期プレビュー中止" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "別のプラグインが選択されたためプレビュー中止" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "同期の想定結果:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "{count}個のファイルをコピー" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "{count}個の重複ファイルをスキップ" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "{count}個のファイルを削除" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "保存先パスが指定されていません" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "曲をエクスポートするディレクトリを指定してください。" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "エクスポートパターンが指定されていません" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" "エクスポートされる曲のファイル名のエクスポートパターンを指定してください。" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "エクスポートパスが絶対パスになっていません" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "パターン\n" "\n" "{}\n" "\n" "に「/」が含まれていますが、ルートとなる位置を示していません。「/」または" "「~/」で始まることを確認して、保存先の絶対パスを指定してください。" #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "保存済み検索が選択されていません" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "保存済み検索を1つ以上選択してください。" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "選択された保存済み検索には曲がありません" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "選択された保存済み検索の結果は全て空です。" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "{}曲の同期対象を検出" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "保存先パスとエクスポートパターンが不整合です" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "エクスポートパターンが、保存先パスとは異なるパスで始まっています。 パターンを" "修正してください。\n" "\n" "エラー:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "同期できません" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "<b>状態</b>でソートされている間は同期を開始できません。" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "曲の同期開始" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "同期が進行中です。" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "曲の同期完了" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "曲の同期停止中" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "曲の同期を中止しました。" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "曲の同期が完了しました。" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "曲の同期中止" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "別のプラグインが選択されたため同期中止" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "「{}」を削除中" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "同期の結果:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "{count}/{total}個のファイルをコピー" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "({count}個の既存ファイルをスキップ)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "{count}/{total}個の重複ファイルをスキップ" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "{count}/{total}個のファイルを削除" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "{count}個のファイルの同期に失敗" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "{count}個の同期済みファイルをスキップ" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "同期歌詞" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "トラックと同じ (または同様の) 名前の .lrc ファイルから同期歌詞を表示します。" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "テキスト:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "背景:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "フォント" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "サイズ(px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathyステータスメッセージ" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "全ての Telepathy ベースのインスタントメッセンジャーアカウント (Empathy などで" "設定されたもの) を、再生中の曲に基づくステータスメッセージで更新します。" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "再生:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "再生開始したときのステータステキスト。QLパターンを受け付けます。例: %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "一時停止:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "一時停止したときのステータステキスト。QLパターンを受け付けます。例: %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "曲を再生していないときのプレーンなステータステキスト" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "曲なし:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "ステータスパターン" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "テーマスイッチャー" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "有効な GTK+ テーマに変更します。" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "テーマ(_T):" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "デフォルトテーマ" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "ダークテーマを優先する" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "サムズアップ評価" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "評価値に変換されるサムズアップ/ダウン・スコアリングシステムを追加します。投票" "総数を維持し、<b><tt>~#score</tt></b> でソートするのに便利です。" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "トグルメニューバー" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Altキーを押すとメニューバー表示をトグルします。" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "再生中の曲はありません" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "トレイアイコン" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "システムトレイから Quod Libet を制御します。" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "%(application-name)sの表示(_S)" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "再生(_P)" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "一時停止(_A)" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "前へ(_V)" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "次へ(_N)" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "シャッフル(_S)" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "リピート(_R)" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "この曲の後で停止(_A)" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "ブラウザウィンドウを開く(_B)" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "タグの編集(_T)" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "情報(_I)" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "プレイリスト(_L)" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "終了(_Q)" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "挙動" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "スクロールホイールで音量を調節する" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "スクロールホイールで曲を変える" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "スクロールホイール(_W)" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "ツールチップ表示" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "歌詞表示" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "タグやファイルベースの歌詞を自動的にサイドバーに表示します。" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "以下の歌詞は見つかりませんでした\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "アクティブな曲はありません" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "ビジュアライザーの起動" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "外部のビジュアライザーを起動します。" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "「%s」を使用してビジュアライザーを実行できませんでした" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "エラー" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "ビジュアライザーの実行ファイル:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "再実行" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "波形シークバー" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ 再生中の曲の波形の形をしたシークバーです。" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "前景色を上書きする:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "マウスホバー時の色を上書きする:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "残り時間の色を上書きする:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "現在位置を表示する" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "時間ラベルを表示する" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "スクロール時のシーク量(ミリ秒):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "画像保存" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "再生中の曲のカバー画像をファイルに保存します。" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "ファイル:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "しきい値(_T):" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "フィルターが作動するまでのしきい値" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "比率(_A):" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "圧縮率" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "オーディオコンプレッサー" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "特定のしきい値を超える全ての標本値の振幅を特定の比率で変更します。" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "プリセット(_P):" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "フィルターのプリセット" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "周波数カット(_F):" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "ローパスフィルターのカット周波数" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "フィードレベル(_L):" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "フィードレベル" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "デフォルト" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "仮想スピーカー配置 (30°、3メートル) に一番近い" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Chu Moy のクロスフィーダーに近い (一般的)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Jan Meier の CORDA アンプに近い (ほとんど変化しない)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "カスタム" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "カスタム設定" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "クロスフィード" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "ヘッドフォン聴取時において、スピーカーでの聴取をシミュレートする方法で、ある" "いは古いステレオ音源を調整するために、左右のチャンネルをミックスします。" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "周波数帯域(_B):" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "フィルターの周波数帯域" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "周波数幅(_W):" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "フィルターの周波数幅" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "レベル(_L):" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "効果のレベル" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "カラオケ" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "音声からメインボーカルを除去します。" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "モノラル・ダウンミックス" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "オーディオチャンネルをモノラルにダウンミックスします。" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "レート(_A):" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "テンポ(_T):" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "ピッチ(_P):" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "オーディオピッチ/スピード" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "オーディオストリームのピッチを制御します。" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "フォルダにプレイリストをエクスポート" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "エクスポート(_E)" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "保存先フォルダ:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "ファイル名のパターン:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "ファイルをフォルダにコピーする形でプレイリストをエクスポートします。" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "プレイリストをエクスポートできません" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "保存先への書き込み権限があることを確認してください。" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "デフォルトのファイル名のパターン:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "OK(_O)" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "新しいプレイリスト名を入力、\n" "または既存の Sonos プレイリストを選択して上書きしてください" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Sonos プレイリストにエクスポート" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "マッチングしたトラックを Sonos プレイリストにエクスポートします。" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Sonos デバイスの検索エラー" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Sonos の検索中にエラーが発生しました。設定を確認してください" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "既存の Sonos プレイリスト「%s」の削除に失敗しました:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "プレイリスト「%(playlist)r」(%(total)dトラック) にエクスポート" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Squeezeboxにエクスポート" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Quod Libet プレイリストを Logicool Squeezebox プレイリストに動的にエクスポー" "トします (両方がディレクトリ構造を共有している場合)。" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "「<a href=\"%(plugin_link)s\">Squeezeboxと同期</a>」プラグインと設定を共有し" "ます。" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Squeezeboxにプレイリストをエクスポート" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "プレイリスト名 (既存のものを上書きします)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Squeezeboxプレイリストにエクスポート" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "プレイリストの重複を削除" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "プレイリスト内の重複している項目を削除します。" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "重複する%d曲を削除してもよろしいですか?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "重複している曲はプレイリスト「%s」から削除されます。" #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "シャッフルプレイリスト" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "プレイリストをランダムにシャッフルします。" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "カーソルに追従" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "選択した曲に追従し、聴き終わったらリストの次の曲に進む再生順序モードを追加し" "ます。" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "カーソルに追従" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "カーソルに追従(_F)" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "再生回数イコライザー" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "総再生回数が少ない曲を優先するシャッフルモードを追加します。" #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "再生回数が少ない曲を優先" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "再生回数が少ない曲を優先(_L)" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "キューのみ再生" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "曲の再生をキューに限定します。\n" "\n" "メインウィンドウでこの再生順序を選択し、曲をダブルクリックすると、再生する代" "わりにキューに追加されます。" #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "キューのみ再生" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "キューのみ再生(_Q)" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "ダブルクリックした曲を自動的に再生開始" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "逆順再生" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "曲の再生順序を逆にするシャッフルモードを追加します。" #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "逆順(_V)" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "グルーピングシャッフル" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "アルバムシャッフルに似た、共通のタグで曲をグルーピングするシャッフルモードを" "追加します。\n" "\n" "この機能は、複数の楽章から成るクラシック曲をシャッフルする際、次の曲に移る前" "にすべての楽章が順番に再生されるようにするのに便利です。" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "グルーピングシャッフル" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "グルーピングシャッフル(_G)" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "新しいグループの開始を待機中…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "グルーピングタグ:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "曲をグルーピングするためのタグ" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "フィルタータグ:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "グルーピングは、フィルタータグが定義されている場合のみ適用されます。\n" "フィルタータグが定義されていない曲は、その曲だけで構成されるグループ\n" "として扱われます。通常、フィルタータグはグルーピングタグと完全一致か\n" "部分一致している必要があります。" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "遅延時間:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "次のグループを開始するまでの遅延時間(秒)" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "デフォルト値にリセット" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "嫌いなトラックをスキップ" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "指定されたしきい値より低い (または等しい) 評価のトラックをスキップして順番に" "再生する再生順序 (シャッフル) モードを追加します。" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "嫌いなトラックをスキップ" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "嫌いなトラックをスキップ(_D)" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "トラック毎のリピート" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "トラックを順番に再生するが、各トラックは設定された回数だけリピートしていく" "シャッフルモードを追加します。" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "トラック毎のリピート" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "トラック毎のリピート(_E)" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "各曲を再生する回数:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "条件付きクエリ" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "条件クエリに基づいて、マッチするクエリを選択します。" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: 条件クエリ, thenクエリ, elseクエリ)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "欠落クエリ" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "指定されたタグが無い曲とマッチします。" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "空のタグを含める" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Pythonクエリ" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍クエリで Python の式を使用します。" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: 式)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "変数 <tt>s</tt> (または <tt>a</tt>) は、一致する曲/アルバムです。\n" "\n" "<tt>_ts</tt> は、クエリ開始時の (実数の) タイムスタンプです。\n" "\n" "モジュール <tt>time</tt> および <tt>random</tt> も使用でき、クラス " "<tt>Random</tt> (== <tt>random.Random</tt>) も使用できます。" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "保存済み検索を含める" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 保存済み検索の結果を別のクエリの一部として含めます。" #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: 検索の名前)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "ユニーククエリ" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "タグが一意となるように検索結果をフィルタリングします。" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: タグ)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK。プレイヤー %s だけを使用しています。" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "%s に接続できません" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "ホスト名:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "ポート:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "ユーザー名:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "パスワード:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "サーバーが接続するライブラリディレクトリ" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "ライブラリパス:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "設定の確認(_V)" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezeboxサーバー" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "デバッグ" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox server at {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "不明な Squeezebox プレイヤー" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "不明な Squeezebox プレイヤー: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Squeezeboxプレイヤーを選択" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Squeezebox サーバーが見つかりました。\n" "プレイヤーを選択してください" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "画像表示をウィンドウサイズに合わせる(_W)" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "画像ファイル名の文字列については「[plugins] cover_filenames」設定項目を参照し" "てください" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "プログラム(_P):" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "保存後に画像を編集する(_E)" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "ファイル名(_N):" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "保存失敗" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "「%s」を保存できません。" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP エラー: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "アルバムアートダウンローダー" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "%(source)s から" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "解像度: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "サイズ: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "1エンジンあたりのベストな結果の上限" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "検索(_S)" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "検索中…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "完了" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "アルバムアートのダウンロード" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "さまざまなウェブサイトからアルバムカバーをダウンロードします。" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "ソース" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2をID3v2に変換" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "APEv2 タグを ID3v2 タグに変換します。これにより、変換後に APEv2 タグが削除さ" "れます。" #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "ブックマークに移動" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "選択したファイルのブックマークを管理します。" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "ブックマークの編集(_E)…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "ブックマークがありません" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainzで検索" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "MusicBrainz での検索結果に基づいてアルバムにタグを付け直します。" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "「date」タグには年のみを使用する" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "必要な場合は「albumartist」タグを書き込む(_A)" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "アーティスト名のソートタグを書き込む" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "標準のMusicBrainzタグを書き込む(_S)" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "「labelid」タグを書き込む" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "ファイル名" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "ディスク" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "トラック" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "タイトル" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "アーティスト" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainzで検索" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "クエリ(_Q):" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "検索(_E)" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "結果 <i>(ドラッグで並べ替え)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "クエリを入力してください。" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "エラーが発生しました。再試行してください。" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "結果をロード中…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "該当する結果はありません。" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Pythonコンソール" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "対話型 Python コンソール。新しいウィンドウを開きます。" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} {songs}用 ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Pythonコンソールサイドバー" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "対話型 Python コンソールのサイドバーで、メインウィンドウで選択された曲に追随" "します。" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "以下のオブジェクトにアクセスできます:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "カレントディレクトリ:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "補完" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "カバーアートのダウンロード" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Quod Libet カバープラグインを使用して高画質なアルバムカバーをダウンロードしま" "す。" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "クラシック" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "ラージ" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "フルHD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "カバーアートダウンロード" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "%(source)s - %(dimensions)s をロード中…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "以下のアルバムに関する情報が見つかりませんでした:\n" "%(albums)s\n" "\n" "使用したプロバイダー:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "カバーが見つかりません" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "プレビューサイズ" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "保存先" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "JPEG でない場合は、同じサイズの高品質 JPEG に変換します" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "JPEGとして保存" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "コマンド" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "名前" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "このコマンドの名前" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "コマンド" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "実行するシェルコマンドの構文" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "パラメータ" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "指定した場合、コマンド内で出現するパラメータがユーザー指定の値に置き換えられ" "ます。例えば、「PARAM」を使用すると、コマンド内の全ての「{PARAM}」を置換する" "ための入力プロンプトが実行時に表示されます" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "コマンドの値を計算するために使用するQLパターン (例: <~filename>)。プレイリス" "トの場合、仮想タグ <~playlistname> および <~#playlistindex> も対応していま" "す。" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "ユニーク" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "設定された場合、パターンの計算値から重複した値を削除します" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "最大引数" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "一度にコマンドに渡す引数の最大数 (xargs のようなもの)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "逆順" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "設定すると、引数リストが逆順になります" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "値の入力" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "%s の値は?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "カスタムコマンド" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "曲のタグを使って (必要ならバッチ処理で) カスタムコマンドを実行します。" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "カスタムコマンドの編集" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "カスタムコマンド %s を実行できません" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d個の重複グループ" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "全て折りたたむ/展開する" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "重複キーを表すタグ式は「%s」" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "重複した曲の表示" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "類似のタグが付けられた曲を検索して表示します。" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "<tt>~artist~title</tt> や <tt>musicbrainz_track_id</tt> などのQLタグ式を受け" "付けます" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "重複グループ(_G):" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "重複キー" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "空白を削除する(_W)" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "発音区別符号を削除する(_D)" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "約物を削除する(_P)" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "大文字小文字を区別しない(_I)" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "マッチングオプション" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "再生回数の編集" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "曲の <tt>~#playcount</tt> および <tt>~#skipcount</tt> を編集します。\n" "\n" "複数の曲を選択すると、それぞれのカウントは指定した回数に設定されるのではな" "く、指定回数分増加されます。\n" "\n" "曲の <tt>~#playcount</tt> を0に設定した場合、<tt>~#lastplayed</tt> および " "<tt>~#laststarted</tt> がクリアされます。ただし、再生回数0の曲に1以上の再生回" "数を設定しても、再生時間は作成されません。" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "再生回数" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "スキップ回数" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "複数ファイルが選択されました。" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "各カウントは指定回数分増加します。" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "埋め込み画像の編集" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "埋め込み画像を追加、削除または置換します。" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "埋め込む(_E)" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "%d個のトラックに埋め込む画像の選択" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "全ての画像を削除する(_R)" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "現在の画像を埋め込む(_E)" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "画像の選択(_C)…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "正確な評価の設定" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "曲の評価を数字で設定できるようにします。" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "0.0から1.0の範囲でご希望の評価を付けてください" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "任意のタグでフィルタリング" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "選択した曲のタグに基づいて検索クエリを作成します。" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "ディレクトリでフィルタリング" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "新しいブラウザウィンドウを開き、ディレクトリでフィルタリングします。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "音響指紋で検索" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "音響指紋を使用して曲のメタデータを検索します。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "音響指紋の送信" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "chromaprint を使用して音響指紋を生成し、acoustid.org に送信します。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "APIキーが見つかりません" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "音響指紋を送信する前に、プラグインの設定で acoustid.org のAPIキーを指定する必" "要があります。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "APIキーのリクエスト" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "APIキー(_K):" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustIDウェブサービス" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "キュー" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "解析中" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "検索中" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "書き込み" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "リリース" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "MusicBrainzタグを書き込む" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "ディレクトリでグルーピング" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "アルバムモード" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "アルバム関連のタグを書くことで、異なるアルバムリリースを減らすようにします" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "音響指紋の生成中:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "詳細(_D)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "送信(_S)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "曲の送信には、<i><b>musicbrainz_trackid</b></i> タグ、または <i><b>artist</" "b></i> / <i><b>title</b></i> / <i><b>album</b></i> タグのどちらか一方が必要で" "す。" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "音響指紋:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "MBIDが付いた曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "十分なタグが付いた曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "送信する曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "完了しました。%(to-send)d/%(all)d曲を送信します。" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "音響指紋の送信:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "送信中…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "ファイルタグの更新" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "修正されたタグをファイルに反映します。これにより再生回数と評価が最新になりま" "す。" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "HTMLにエクスポート" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "選択した曲のリストを HTML にエクスポートします。" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "iFPに送信" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "iRiver iFP デバイスに曲をアップロードします。" #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "iFP デバイスが見つかりません" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "iFP デバイスに接続できません。デバイスの電源がオンになっていて接続されている" "こと、および ifp-line (http://ifp-driver.sf.net) がインストールされていること" "を確認してください。" #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "%(current)d/%(total)d アップロード中" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "「%s」をアップロードできません。デバイスの容量が不足しているか、電源がオフに" "なっている可能性があります。" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "アップロードエラー" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "ユーザーデータのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "タグのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "タグとユーザーデータのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "ファイルステムとユーザーデータのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "ファイルステムとタグのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "ファイルステム、タグとユーザーデータのエクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "インポート/エクスポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "タグやトラックのユーザーデータをインポートまたはエクスポートします。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "詳細情報" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "「トラックのユーザーデータ」という用語には、選択したトラックが含まれるプレイ" "リストと次のメタデータが含まれます:\n" "\n" "%s\n" "\n" "エクスポートを選択したものは、すべてインポートされることに注意してください。" "ファイルのステム (拡張子なしのファイル名) をエクスポートした場合、インポート" "時に、選択したファイルの名前が変更されます。\n" "\n" "アルバムをエクスポートした後、そのデータを別のバージョンのアルバムにインポー" "トすることができます。トラックの順番や数は異なってもかまいません。プラグイン" "は、トラックの名前が多少異なっていても、エクスポートされたデータを新しいト" "ラックに合わせます。自動マッチングが常に正しいとは限らないので、以下の類似度" "の値をあまり下げない方がよいでしょう。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "インポート時のユーザー操作" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "トラック数が異なる場合は確認を求める" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "アルバム数が異なる場合は確認を求める" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "この割合以下の場合、ユーザーはどのトラックがどのトラックとマッチングしている" "かを手動で確認し、変更する必要があります。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "トラックの類似度:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "アルバムの類似度:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "エクスポートファイル" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "きれいに整形された JSON を出力する (遅い)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "インポート後にエクスポートファイルを削除する" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "インポート" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "エクスポートディレクトリを開く" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "ディスク数" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "トラック数" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "アーティスト" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "パスの末端" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "アルバムのマッチング" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "続行する" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "インポートするものはありません" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "インポートする前に、何かをエクスポートする必要があります。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "インデックスが破損していました。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "%s を JSON として解析できません" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "%s を読み込めません" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "ファイル名" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "トラックのマッチング" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "チャートリストを更新中。" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "すでに最新です。" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "%sの週のチャートを取得中。" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "同期完了しました。" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "同期中にエラーが発生しました (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fmと同期" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Last.fm のプロフィールからライブラリの統計情報を更新します。" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "ユーザー名(_U):" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "ソートタグの生成" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "アルバム名やアーティスト名をソート名に変換します(不十分)。" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "M3U/PLSプレイリストとしてエクスポート" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "曲を M3U または PLS プレイリストにエクスポートします。" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "相対パスを使う" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "絶対パスを使う" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "「%s」への書き込みに失敗しました。" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "曲の再スキャン" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "ファイルの変更をチェックし、必要に応じて曲を再読込/削除します。" #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "曲の再スキャン" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGainアナライザー" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "トラック" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "進捗" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "ゲイン" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "ピーク" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "更新するアルバムは%(to-process)s枚あります(%(all)s枚中)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGainの解析" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "GStreamer を使用して <a href=\"%(rg_link)s\">ReplayGain</a> 情報を解析し更新" "します。結果はアルバム単位でグルーピングされます。" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "常に" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "<b>いくつかの</b>RGタグが欠落している場合" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "<b>アルバム</b>RGタグが欠落している場合" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "アルバムの更新処理(_P):" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "既存のタグ" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "タグの分離" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "アルバムからディスク番号、タイトルからバージョンを同時に分離します。" #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "アルバムタグの分離" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "ディスク番号を分離します。" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "なし" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "リセット" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "タップ" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "BPMのタップ" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 選択した曲の BPM をタップします。" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "ウェブサイトで検索" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "曲のタグを使用して、選択したウェブサイトで検索します。\n" "「%(pattern)s」のようなパターンに対応しています。" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "検索URLパターン" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "検索URLの編集" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "検索の設定…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Wikipediaでタグを検索" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "選択した曲の対応するタグに関する Wikipedia の記事をウェブブラウザで表示しま" "す。" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "検索先 %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "タグの編集" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "検索失敗" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "タグ「%s」が見つかりません。" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "ライブラリ" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "マウントポイントを確認中" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "ライブラリスキャン中" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "%s をスキャン中" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "ファイルをロード中" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "ライブラリ移動中" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "ライブラリ削除中" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "%s の監視を追加" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "レガシープレイリスト「%(filename)r」(サイズ %(size).1f kB) にはライブラリ登録" "曲が見つかりません。" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" "ライブラリのルートディレクトリを変更したのに、このプレイリストは変更していな" "いということはないですか?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d個のプレイリストの変換に失敗しました" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "ミュージックプレイヤー/ミュージックライブラリマネージャ" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "ファイルの読み込みに失敗しました: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "タグの一覧表示" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "簡潔な出力を表示" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "簡潔モードでの表示するカラムおよび表示順 (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "プログラマチックタグも表示する" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "引数が不足しています" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "引数が多すぎます" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "説明" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "値" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "全共通タグの一覧表示" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "あるファイルから別のファイルにタグをコピーする" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "変更の表示のみで、適用はしない" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "書き込めないタグはスキップする" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "タグ「{tagname}」をファイル「{filename}」にコピーできません" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "テキストエディタでタグを編集する" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "編集を中止しました" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "テキストエディタ「%(editor-name)s」の実行が失敗しました。" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "変更は検出されませんでした" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "タグを設定して既存の値を削除" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "%(format)s ファイル「%(file)r」に「%(tag)r」を設定できません" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "タグの削除" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "正規表現で指定" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "全てのタグの削除" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "「--all」と「--regexp」を組み合わせることはできません" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "「{filename}」から「{tagname}」を削除できません" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "タグの値の削除" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "タグの値の追加" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "「%r」を設定できません" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "ファイル情報の一覧表示" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "提供された画像を主埋め込み画像として設定し、他の全ての埋め込み画像を削除する" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "画像ファイルの読み込みに失敗しました: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "「%(file_name)s」(%(file_format)s) の画像編集には対応していません" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "全ての埋め込み画像の削除" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "埋め込み画像を「%(filepath)s」に抽出" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "画像の保存先パス (デフォルトはカレントディレクトリ)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "タグに基づいてファイル名を変更" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "ファイルパスに基づいてタグを埋める" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "ファイル" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "全てのファイルのトラック番号を埋める" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "指定されたパターンに基づいてタグを表示" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "ヘルプ情報の表示" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "「%(column-id)s」は有効なカラム名ではありません (%(all-column-ids)s)。" #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "不明(_U)" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "並び順" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "並び順(_I)" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "ランダム" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "ランダム(_R)" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "高評価の曲を優先" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "高評価の曲を優先(_H)" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "このトラックをリピート" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "このトラックをリピート(_T)" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "全体をリピート" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "全体をリピート(_A)" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "1曲のみ" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "1曲のみ(_S)" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "ストリーム" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "バッファリング中" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "GStreamer パイプラインを作成できません (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "メディア形式を処理する GStreamer エレメントが見つかりません" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "メディア形式: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer プラグイン「%(name)s」を初期化できませんでした" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "再生に使用される GStreamer 出力パイプライン。空白の場合はデフォルトのパイプラ" "インが使用されます。パイプラインにシンクが含まれる場合、デフォルトの代わりに" "使用されます。" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "出力パイプライン(_O):" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f秒" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "バッファ時間(_B):" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "ギャップレス再生を無効にする(_G)" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "ギャップレス再生を無効にすると、一部の GStreamer バージョンでトラック変更の問" "題を回避できます" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "可能であれば再生にJACKを使用する" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "検出できる場合は、playbin シンクに「jackaudiosink」を使用します" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "JACK出力デバイスに自動接続する" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "「jackaudiosink」に自動接続するように指示します" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "GStreamer オーディオシンクが見つかりません。試行した設定: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "不正な Gstreamer 出力パイプライン" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "オーディオ出力を作成できません" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "オーディオ デバイス「%r」が見つかりませんでした。「~/.quodlibet/config」で " "Xine の設定を確認してください。" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "モジュール「{module}」が見つかりませんでした。おそらくパッケージのインストー" "ルが必要ではないでしょうか?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "GStreamer エレメント「{element}」が見つかりませんでした。" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "プラグインウィンドウで ListenBrainz の設定を行ってください。それまでは、聴取" "情報は送信されません。" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "連続して送信失敗しすぎています (%d回)。オフラインモードに設定しています。プラ" "グインウィンドウで ListenBrainz の再設定を行ってください。それまでは、聴取情" "報は送信されません。" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainzの送信" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "ListenBrainz に聴取情報を送信します。" #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "ユーザートークン(_T):" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "タグ(_A):" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "送信に含めるタグのリスト。カンマで区切り、必要に応じてダブルクォートを使用し" "てください。" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "このフィルターに一致する曲は送信されません。" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "プラグイン「%(name)s」を%(count)s個のプレイリストで実行しますか?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "プラグインの実行(_R)" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "使用法" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "曲の頭から再生" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "なし" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "時間" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "ブックマーク名" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "分:秒" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "ブックマーク" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "フィルター(_F)" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "最近再生された曲(_P)" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "最近追加された曲(_A)" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "上位40曲(_T)" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "全ての曲(_S)" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "再生中の曲のジャンル(_G)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "再生中の曲のアーティスト(_A)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "再生中の曲のアルバム(_B)" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "ジャンルでランダム選択(_G)" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "アーティストでランダム選択(_A)" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "アルバムでランダム選択(_B)" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "再生回数の上位40曲(組になっているものがある場合40曲以上が選択される場合もあり" "ます)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "名前(_N):" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "値(_V):" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "保存済みの値" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "保存済みの値の編集…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "自動(_M)" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "トラックモード(_T)" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "アルバムモード(_A)" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "ミュート(_M)" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "ReplayGainモード(_R)" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "新規%s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(不明)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "追加(_A)…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "編集(_E)" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "タグ式" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "タグ式 (例: people:real、~album~year)" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "タグの入力" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "タグ式の編集" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "ファイル:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "選択された曲はライブラリから削除され、そのファイルはディスクから削除されま" "す。" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "選択されたファイルがディスクから削除されます。" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "%(file_count)d個のファイルを完全に削除しますか?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "ファイルの削除(_D)" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "選択された曲はライブラリから削除され、ファイルはゴミ箱に移動されます。" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "選択されたファイルはゴミ箱に移動されます。" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "%(file_count)d個のファイルをゴミ箱に移動しますか?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "ゴミ箱に移動(_M)" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "%(current)d/%(total)d個を移動中。" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "ゴミ箱に移動できません" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "1個以上のファイルのゴミ箱への移動に失敗しました。" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "%(current)d/%(total)d個を削除中。" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "ファイルを削除できません" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "1個以上のファイルの削除に失敗しました。" #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "ブラウザ" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "ファイルをダウンロード中" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "%d曲が欠落しています" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d曲の内容がそれぞれ異なっています" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "複数の値に分割(_M)" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "albumからdiscを分離(_A)" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "titleからversionを分離(_V)" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "artistからarrangerを分離(_T)" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "artistからperformerを分離(_P)" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "titleからperformerを分離(_P)" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "titleからoriginalartistを分離(_O)" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "タグの追加" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "タグ(_T):" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "プログラマチックタグの表示(_P)" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "MusicBrainz タグや ReplayGain タグなどの機械生成されたものを含む全てのタグに" "アクセスします" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "複数行タグの表示(_M)" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "複数行になる可能性のあるタグ(「lyrics」など)もここに表示します" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "元に戻す(_R)" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "保存(_S)" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "設定(_C)" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "タグの分割(_S)" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "値のコピー(_C)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "タグを追加できません" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "「%s」を追加できません" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "選択されているファイルには「%s」タグに複数の値を設定することができません。" #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "不正なタグ" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "不正なタグ: %s\n" "\n" "選択されているファイルはこのタグの編集に対応していません。" #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "不正な値" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "不正な値: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "タグが正しくない可能性があります" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "プログラム動作中に「%(file-name)s」の内容が変更されました。ライブラリをリフ" "レッシュせずに保存すると、この曲に対する他の修正内容を上書きしてしまう可能性" "があります。" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "曲を保存できません" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "「%(file-name)s」の保存に失敗しました。ファイルが読み取り専用になっている、あ" "るいは破損している、またはあなたにファイル編集の権限が与えられていない可能性" "があります。" #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "他のオプション(_M)…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "取り消す(_U)" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "やり直す(_R)" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "バージョン情報(_A)" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "アップデートの確認(_C)…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "プラグイン(_P)" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s、他%(count)s曲" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falsoの設定" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "フォルダ" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "新しいフォルダ(_N)…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "サブフォルダを全て選択(_S)" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "新しいフォルダ" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "フォルダ名を入力してください:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "フォルダを作成できません" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "フォルダを削除できません" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "曲" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "by %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "ディスク %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "トラック %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "再生中の曲(_S)" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "ディスプレイの編集(_E)…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "曲が選択されていません。" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "曲がありません" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "情報" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "歌詞" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "プロデュース %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "アーティスト" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "アーティスト" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "演奏者" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "なし" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d回" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "登録日時" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "再生完了日時" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "再生回数" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "スキップ回数" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "評価" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "パス" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "時間" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "フォーマット" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "コーデック" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "エンコーディング" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "ビットレート" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "サイズ" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "修正日時" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "付加情報" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d曲選択済み" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "トラック情報が取得できません" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d曲にアルバム情報がありません" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "選択済みディスコグラフィ" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d曲にアーティスト情報がありません" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "アルバム" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "合計時間:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "合計サイズ:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "ファイル" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "オンラインで表示(_V)" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "この曲の歌詞は見つかりませんでした。" #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "全ての曲を削除してもよろしいですか?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "選択された曲はライブラリから削除されます。" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "再表示" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "再表示(_U)" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "左側のカラムが右側のカラムとほぼ一致しているかどうかを確認してください。一致" "しない場合は、ここで順序を変更することができます (一致させるべきではない行に" "は「_」を使用します):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "右側の順序:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "タグの変更を破棄しますか?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "タグが変更されましたが、まだ保存されていません。保存しますか? それとも元に戻" "して変更を破棄しますか?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "元に戻す(_R)" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "同名のファイルが存在します" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "「%(file-name)s」を置換しますか?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "ファイルを置換(_R)" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "アクティブタスク" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d個のタスクを実行中" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "シャッフルモードをトグル" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "リピートモードをトグル" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "イベント" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "再生順序" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "編集" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "名前変更" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "クエリ" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "カバー" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "プラグインのエラー" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "全ての状態" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "有効" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "無効" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "カテゴリなし" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "全てのカテゴリ" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "プラグインが見つかりません。" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "プラグイン" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "プラグイン状態/タグでフィルタリングします" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "プラグインタイプでフィルタリングします" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "プラグイン名や説明でフィルタリングします" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "エラーの表示(_E)" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "ディスク(_D)" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "トラック(_T)" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "グループ(_P)" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "アーティスト(_A)" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "アルバム(_B)" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "ファイル名(_F)" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "時間(_L)" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "再生中の曲へ自動的にジャンプする(_J)" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "再生する曲が変わったときにソングリストをスクロールさせます" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "タグが変更されたときに曲をソートする(_S)" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "タグが変更されると、ソングリスト内の曲を自動的に再ソートします" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "常にソートを可能にする" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "プレイリストなどでも、カラムヘッダでソートできるようにします" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "その他(_O):" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "編集(_E)…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "追加表示するカラムヘッダを追加または削除します" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "表示するカラム" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "タイトルにバージョンを含める(_V)" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "アルバムにディスクサブタイトルを含める(_D)" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "アーティストに全てのピープルを含める(_P)" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "ファイル名にフォルダ名を含める(_F)" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "カラム設定" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "カラムの更新(_U)" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "現在の設定をソングリストに適用し、新しいカラムは最後に追加します" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "ソングリスト" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "カラムの編集" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "総再生時間" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "グローバルに適用するフィルター(_G):" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "他の全ての検索条件に加えてこのクエリを適用します" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "検索" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "ブラウザ" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "複数の評価時に確認する(_M)" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "複数の曲の評価を一度に変更する前に確認を求めます" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "ワンクリック評価を有効にする(_O)" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "ソングリストで「評価」カラムをクリックすることで評価できるようにします" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "評価" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "埋め込み画像を優先する(_E)" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "他のソースより、オーディオファイルに埋め込まれたアートワーク(利用可能な場合)" "を選択します" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "利用可能な場合に使用するアルバムアート画像ファイル(ワイルドカードに対応)。複" "数指定する場合は、カンマで区切ってください。" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "固定の画像ファイル名を優先する(_P)" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "アルバムアート" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "再生" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "出力設定" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "曲に ReplayGain 情報が無い場合、この値で音量を調整します" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "フォールバックゲイン(_F):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "結果がクリップしない限り、この値で全ての曲の音量を調整します" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "プリアンプゲイン(_P):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "ReplayGain音量調整を有効にする(_E)" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "ReplayGain音量調整" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "起動時に再生を再開する(_C)" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "シャットダウン時に音楽が再生されていた場合は、次回の起動時に自動的に再生を開" "始します" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "デフォルトの評価(_D):" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "評価尺度(_S):" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "集計された評価のベイジアン平均係数(C)。\n" "0は従来の平均を意味し、値が高いほど、トラックの少ないアルバムの極端な評価が低" "くなります。この値を変更すると全てのアルバムが再計算されます。" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "ベイジアン平均量(_B):" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "メールアドレス(_E):" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "評価と再生回数はこのメールアドレスのタグに保存されます" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "タグの変更を自動保存する(_A)" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "複数ファイルの編集時に確認なしでタグの変更を保存します" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "タグエディタでタグの値を分割するときに使用する区切り文字のセット。このリスト" "はスペースで区切られます。" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "タグの分割に用いる文字(_T):" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "タグエディタでタグからサブタグを抽出するときに使用する区切り文字のセット。こ" "のリストはスペースで区切られ、各エントリには2文字のみを含める必要があります。" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "サブタグの分離に用いる文字(_S):" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "タグ" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "タグの編集" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "新しい評価に更新中" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "ライブラリのスキャン(_S)" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "ライブラリの変更内容をチェックします" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "ライブラリの再構築(_B)" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "ライブラリの全曲を再読込します。この処理はやや時間がかかるかもしれません。" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "非表示の曲" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "起動時にライブラリをスキャンする(_O)" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "ディレクトリの変更を監視する(_W)" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "外部ファイルの追加、削除、名前の変更についてライブラリディレクトリを監視しま" "す。" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "スキャンするディレクトリ" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s、他%(count)d曲" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "プロパティ" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "キュー(_Q)" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "キューを全て消去" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "キューを無効化 - 再生時にキューは無視されます" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "一時的" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "再生後、キューから曲を削除します" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "永続的" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "再生後、キューに入っている曲を保持します" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "モード" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "最後の曲で停止" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d曲(%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "ライブラリの参照(_B)" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "キューの表示状態をトグル" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "再生エラー" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "ライブラリディレクトリを設定しますか?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "ライブラリが設定されていません。これから設定しますか?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "今はまだ(_N)" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "設定する(_S)" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "曲を追加できません" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s で使われているプロトコルに対応していません。" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "再生中の曲にジャンプ(_J)" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "ファイル(_F)" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "曲(_S)" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "表示(_V)" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "ブラウザ(_B)" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "操作(_C)" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "ヘルプ(_H)" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "フォルダの追加(_A)…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "ファイルの追加(_A)…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "場所の追加(_A)…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "ブックマークの編集…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "停止" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "この曲の後で停止" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "キーボードショートカット(_K)" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "オンラインヘルプ" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "検索のヘルプ" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "場所の追加" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "オーディオファイルのある場所を入力してください:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "場所の追加ができません" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "指定された場所 %s にアクセスできません。" #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "ミュージックの追加" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "フォルダの追加(_A)" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "ミュージックファイル" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "ファイルの追加(_A)" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "%d曲をキューに追加してもよろしいですか?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "キューに追加(_E)" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "%d曲全ての評価を変更してもよろしいですか?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "保存されている評価は削除されます" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "評価の削除(_R)" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "選択された全ての曲の評価が %s に変更されます" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "評価の変更(_R)" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "スペースをアンダースコアに置き換える(_U)" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "(セミ)コロン区切りをハイフンに置き換える" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "例:「iv: allegro.flac」→「iv - allegro.flac」" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Windowsと互換性のない文字を削除する(_W)" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "発音区別符号を削除する(_D)" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "非ASCII文字を削除する(_A)" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "大文字を小文字に変換する(_L)" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "ファイル名の変更" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "プレビュー(_P)" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "ファイル名" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "アルバムアートを移動する(_M)" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "画像検索文字列については「[albumart] filenames」設定項目を参照してください" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "移動先のアルバムアートを上書きする(_O)" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "空になったディレクトリを削除する(_R)" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "アルバムアート" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "新しい名前" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "ファイル名を変更できません" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "「%(old-name)s」から「%(new-name)s」への名前変更に失敗しました。変更先のファ" "イルが既に存在する、新規ファイルを作成する権限が無い、旧ファイルを削除する権" "限が無い、などの可能性があります。" #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "全てのエラーを無視(_A)" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "停止(_S)" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "続行する(_C)" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "パス名が絶対パスになっていません" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "パターン\n" "\t%s\n" "に「/」が含まれていますが、ルートとなる位置を示していません。誤ったフォルダ名" "とならないよう、パターンを「/」または「~/」で始め、ルート位置を特定してくださ" "い。" #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "リストされたフォルダ内の曲は、ライブラリのリフレッシュ時にライブラリに追加さ" "れます" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "新しいディレクトリは、追加後にスキャンされます" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "選択したディレクトリにある全ての曲もライブラリから削除されます" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "移動(_M)" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "スキャンルートを移動し(ファイルは移動しません)、含まれている全てのトラックの" "メタデータを移行します。" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "{dir!r} とその全てのトラックを削除しますか?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "{n}個のライブラリパスとそのトラックを削除しますか?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "ライブラリパスを削除しますか?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "削除" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "ディレクトリの選択" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "このディレクトリを選択" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "{dir!r} の実際のディレクトリまたは新しいディレクトリを選択" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "これにより、QLメタデータを移動します:\n" "\n" "{old!r} → {new!r}\n" "\n" "オーディオファイル自体はこれによって移動することはありません。\n" "それでも、バックアップを取ることをお勧めします (Quod Libet の「songs」ファイ" "ルを含む)。" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "{dir!r} のスキャンルートを移動しますか?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "OK、移動して!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "保存済みの検索文字列" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "保存済みの検索文字列の編集…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "フリーテキストまたはQLクエリを使用してライブラリを検索します" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "タイピング後に検索(_T)" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "タイピングが終わった後に検索結果を表示する" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "検索結果の上限(_L):" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "ウェイト(_W)" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "クエリを追加" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "一緒に使用するQLクエリまたはフリーテキストを追加します" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "残り時間を表示" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "メインウィンドウ" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "10秒前に戻す" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "10秒先に進める" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "検索ボックスをフォーカス" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "フィルターをリセットして、再生中の曲にジャンプ" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "選択した曲の情報ウィンドウを開く" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "選択した曲のタグエディタを開く" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "選択した曲をキューに追加する" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "選択した曲を削除する" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "インライン検索ボックスを表示する" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "カラムヘッダを左クリック" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "ソート対象カラムのリストに追加する" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "ツリービュー" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "要素を折りたたむ、または親要素を選択する" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "要素を展開する" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "テキストボックス" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "直前の変更を取り消す" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "直前に取り消した変更をやり直す" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "全てのペインで全ての曲を選択する" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "%sでフィルタリング(_F)" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "全てのヘッダ(_H)" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "トラックヘッダ(_T)" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "アルバムヘッダ(_A)" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "ピープルヘッダ(_P)" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "日付ヘッダ(_D)" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "ファイルヘッダ(_F)" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "プロダクションヘッダ(_P)" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "ヘッダのカスタマイズ(_C)…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "カラム幅の自動伸縮(_E)" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "ライブラリからトラック「%(title)s」を削除しますか?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "ライブラリから%(count)d個のトラックを削除しますか?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "ライブラリから削除" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "プラグイン「%(name)s」を%(count)d曲で実行しますか?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "プラグイン「%(name)s」を%(count)d個のアルバムで実行しますか?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "プラグインの設定…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "キューに追加(_Q)" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "ライブラリから削除(_R)…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "ファイルを表示できません" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "ファイル表示のエラー、または表示できるプログラムがありません。" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "ファイルマネージャで%(total)d個のファイルを表示(_S)" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "%(total)d個のファイルをダウンロード(_D)…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "成功" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "失敗" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "ダウンロード完了" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "{total}個のファイルのダウンロード先" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "ここにダウンロード" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "アンダースコアをスペースに置き換える(_U)" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "タイトルの単語をキャピタライズする(_T)" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "複数の値に分割する(_V)" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "パス名からタグへの変換" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "既存のタグを置き換える" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "既存のタグに追加する" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "パターン\n" "\t%s\n" "は不正です。同じタグが二度使われているか、ブラケット (< / >) の開始、終" "了の対応が取れていない可能性があります。" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "入力されたパターンが不正です。「<」と「>」はそれぞれ「\\<」や" "「\\>」のように入力し、タグの開始と終了関係を保つように入力してくださ" "い。\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "ディスプレイの編集" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "トラック番号" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "開始番号(_M):" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "合計トラック数(_T):" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "再生/一時停止" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "前へ" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "他%d項目…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "変更した曲を保存しています。" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d曲を保存済み\n" "(残り%(remaining)s曲)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s / %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "アップデートの確認中" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "接続に失敗しました" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "既に最新バージョン %(version)s を使用しています" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "新しいバージョン %(new-version)s が利用可能です\n" "\n" "現在はバージョン %(old-version)s を使用しています\n" "\n" "<a href='%(url)s'>ウェブサイト</a>も参照してください" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "空のプレイリスト" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "プレイリストには名前が必要です" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "「%(name)s」という名前のプレイリストは既に「%(path)s」に存在します" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "埋め込みアルバムカバー" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "オーディオファイルに埋め込まれたカバーを使用します。" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "ファイルシステムカバー" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "曲と一緒のディレクトリにある一般的な名前の画像を使用します。" #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "カバーアート" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "アルバムアートプロバイダへの問い合わせ中" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "基本的な使い方を表示" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "バージョンと著作権情報を表示" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "デバッグ情報を表示" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "使用法: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[オプション]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "オプション「%r」は認識できません。" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "オプション「%r」には引数が必要です。" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "「%r」はユニークなプリフィックスではありません。" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s秒" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "時間情報なし" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d秒" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d分" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d時間" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d日" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d年" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "titlecase?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "日付は「YYYY」「YYYY-MM-DD」「YYYY-MM-DD HH:MM:SS」のいずれかの形式で入力して" "ください。" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "ReplayGain のゲイン値は「x.yy dB」の形式で入力してください。" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "ReplayGain のピーク値は「x.yy」の形式で入力してください。" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID は UUID 形式でなくてはなりません。" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz リリースステータスは「official」「promotional」「bootleg」のいず" "れかでなくてはなりません。" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "language は ISO 639-2 の3文字コードでなければなりません" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "%d個のファイルを保存中" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "自動保存" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "曲の編集に失敗しました" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "「%s」の保存に失敗しました。ファイルが読み取り専用になっている、あるいは破損" "している、またはあなたにファイル編集の権限が与えられていない可能性がありま" "す。" #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[不正なエンコーディング]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "アルバム" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "編曲者" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "編曲者" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "編曲" #: quodlibet/util/tags.py:86 msgid "author" msgstr "原作者" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "原作者" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "コメント" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "作曲者" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "作曲者" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "作曲" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "指揮者" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "指揮者" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "指揮" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "連絡先" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "著作権" #: quodlibet/util/tags.py:93 msgid "date" msgstr "日時" #: quodlibet/util/tags.py:94 msgid "description" msgstr "説明" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "ジャンル" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "ジャンル" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "演奏者" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "演奏" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "グルーピング" #: quodlibet/util/tags.py:98 msgid "language" msgstr "言語" #: quodlibet/util/tags.py:99 msgid "license" msgstr "ライセンス" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "作詞者" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "作詞者" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "作詞" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "組織" #: quodlibet/util/tags.py:104 msgid "title" msgstr "タイトル" #: quodlibet/util/tags.py:105 msgid "version" msgstr "バージョン" #: quodlibet/util/tags.py:106 msgid "website" msgstr "ウェブサイト" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "アルバムアーティスト" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "ディスクサブタイトル" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "ディスク" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "トラック" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "レーベルID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "オリジナルリリース日時" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "オリジナルアルバム" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "オリジナルアーティスト" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "録音日時" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "リリース国" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "最初の調" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainzレコーディングID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainzリリーストラックID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainzリリースID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainzアーティストID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainzリリースアーティストID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainzアルバムステータス" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainzアルバムタイプ" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainzリリースグループID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "トラックゲイン" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "トラックピーク" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "アルバムゲイン" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "アルバムピーク" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "リファレンスラウドネス" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "ディスク数" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "トラック数" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "再生開始日時" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "フルパス" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "マウントポイント" #: quodlibet/util/tags.py:166 msgid "people" msgstr "ピープル" #: quodlibet/util/tags.py:168 msgid "year" msgstr "年" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "オリジナルリリース年" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "ブックマーク" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "ビット深度" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "ファイル形式" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "プレイリスト" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "サンプリングレート" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "チャンネル数" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "ソート" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "担当" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "オーディオタグエディタ" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "オーディオファイルのタグ編集" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "ミュージックプレイヤー" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "オーディオファイルの再生、内容表示、編集ができます" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso は、Quod Libet と同じタグ編集インターフェイスを備えたタグエディタで" "す。対応している全てのファイル形式について、任意のタグを表示および編集できま" "す。" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "対応しているファイル形式は、Ogg Vorbis/Opus/Speex/FLAC、MP3、FLAC、MOD/XM/" "IT、Musepack、Wavpack、MPEG-4 AAC、Monkeys Audio、WMA、SPC、MIDI です。" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet は音楽管理プログラムです。 オーディオライブラリを表示するさまざま" "な方法を提供するのみならず、インターネットラジオやオーディオフィードにも対応" "しています。また、非常に柔軟なメタデータタグの編集および検索機能を備えていま" "す。" #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Quod Libet プレイリストを Sonos プレイリストにエクスポートします (両方が" #~ "ディレクトリ構造を共有している場合)。" #~ msgid "Export to Sonos playlist" #~ msgstr "Sonosプレイリストにエクスポート" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "<b>%s</b> タグを追加できません" #~ msgid "Invalid tags" #~ msgstr "不正なタグ" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "不正なタグ <b>%s</b>\n" #~ "\n" #~ "選択されたファイルは上記のタグに対応していません。" #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "曲の再生やスキップ時に自動的に評価を設定します。これは Brian Nelson によ" #~ "る vux の「加速」アルゴリズムを使用しています。" #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f秒" #~ msgid "Startup" #~ msgstr "起動" #~ msgid "Audio Feeds" #~ msgstr "オーディオフィード" #~ msgid "_Audio Feeds" #~ msgstr "オーディオフィード(_A)" #~ msgid "New" #~ msgstr "新規" #~ msgid "Removes or replaces embedded images." #~ msgstr "埋め込まれた画像を削除または置換します。" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "歌詞を検索中..." #, fuzzy #~ msgid "<artist>" #~ msgstr "アーティスト" #, fuzzy #~ msgid "<album>" #~ msgstr "アルバム" #, fuzzy #~ msgid "<title>" #~ msgstr "タイトル" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "プレイリストのインポート" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "プレイリストのインポート" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "情報" #~ msgid "Unsupported file type" #~ msgstr "サポートしていないファイル形式です" #~ msgid "Unable to add station" #~ msgstr "ラジオ局を追加できません" #, fuzzy #~ msgid "Device Properties" #~ msgstr "プロパティ" #~ msgid "Device:" #~ msgstr "デバイス:" #~ msgid "Not mounted" #~ msgstr "マウントされていません" #, fuzzy #~ msgid "Mount point:" #~ msgstr "マウントポイント" #, fuzzy #~ msgid "Media Devices" #~ msgstr "オーディオデバイス: %s" #, fuzzy #~ msgid "_Media Devices" #~ msgstr "オーディオデバイス: %s" #, fuzzy #~ msgid "_Eject" #~ msgstr "イジェクト(_E)" #, fuzzy #~ msgid "_Properties" #~ msgstr "プロパティ" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "使用中<b>%s</b>、利用可能<b>%s</b>" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "<b>%s</b>の削除失敗。" #, fuzzy #~ msgid "Unable to copy song" #~ msgstr "曲のコピーができません" #~ msgid "There is not enough free space for this song." #~ msgstr "この曲を保存するための空き領域が不足しています" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b>のコピーに失敗しました。" #, fuzzy #~ msgid "Unable to delete songs" #~ msgstr "曲を追加できません" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "<b>%s</b>の削除失敗。" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "指定された場所 <b>%s</b> にアクセスできません。" #, fuzzy #~ msgid "Unable to delete song" #~ msgstr "曲の編集に失敗しました" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "<b>%s</b>のイジェクト失敗。" #, fuzzy #~ msgid "Unable to eject device" #~ msgstr "ファイルを削除できませんでした。" #~ msgid "Search Library" #~ msgstr "ライブラリの検索" #~ msgid "_Search Library" #~ msgstr "ライブラリの検索(_S)" #~ msgid "Rate the playing song" #~ msgstr "再生中の曲をレイティング" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "メインソングリストの表示/非表示" #, fuzzy #~ msgid "Unknown Device" #~ msgstr "不明なデバイス" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: '%s'はユニークなプリフィックスではありません。" #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "不正な値" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "ファイル名のパターン(_F)" #, fuzzy #~ msgid "_Clear" #~ msgstr "プラグインのエラー" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "歌詞" #, fuzzy #~ msgid "Alternate search" #~ msgstr "検索条件をクリア" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "歌詞" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "歌詞" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "曲がありません" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "ブラウザ" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "フォルダを作成できません" #~ msgid "Audio device: %s" #~ msgstr "オーディオデバイス: %s" #~ msgid "Downloads" #~ msgstr "ダウンロード" #~ msgid "Size" #~ msgstr "サイズ" #~ msgid "_Download" #~ msgstr "ダウンロード(_D)" #~ msgid "_Copy to Device" #~ msgstr "デバイスへコピー(_C)" #, fuzzy #~ msgid "browsers" #~ msgstr "ブラウザ" #~ msgid "Unable to download lyrics." #~ msgstr "歌詞のダウンロードに失敗しました。" #~ msgid "Set or toggle the playback order" #~ msgstr "再生順のセットまたは切替" #~ msgid "Uninitialized iPod" #~ msgstr "初期化されていない iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "iPodに空のデータベースを新規作成しますか?" #~ msgid "_Volume Gain (dB):" #~ msgstr "ボリュームゲイン(dB)" #, fuzzy #~ msgid "Combine tags with _multiple values" #~ msgstr "複数の値に分割する(_v)" #~ msgid "Capacity:" #~ msgstr "容量" #~ msgid "Firmware:" #~ msgstr "ファームウェア" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "ライブラリの保存に失敗しました" #, fuzzy #~ msgid "Unable to save iPod database" #~ msgstr "ライブラリの保存に失敗しました" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "トラックのピーク" #~ msgid "Shuffle" #~ msgstr "シャッフル" #~ msgid "Weighted" #~ msgstr "ウェイト順" #~ msgid "_Weighted" #~ msgstr "ウェイト順(_W)" #~ msgid "_One Song" #~ msgstr "1曲のみ(_O)" #~ msgid "Restart the playlist when finished" #~ msgstr "終了したときにプレイリストをリスタートする" #~ msgid "Disable Browser" #~ msgstr "ブラウザの無効化" #~ msgid "_Disable Browser" #~ msgstr "ブラウザの無効化(_D)" #, fuzzy #~ msgid "Force Write" #~ msgstr "書き込み" #~ msgid "Filter on _Genre" #~ msgstr "ジャンルでフィルタリング(_G)" #~ msgid "Filter on _Artist" #~ msgstr "アーティストでフィルタリング(_A)" #~ msgid "Filter on Al_bum" #~ msgstr "アルバムでフィルタリング(_b)" #~ msgid "_Music" #~ msgstr "ミュージック(_M)" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "ブックマーク" #~ msgid "Song _List" #~ msgstr "ソングリスト(_L)" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "この曲の後で停止" #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "albumからdiscを分離(_A)" #, fuzzy #~ msgid "Timeout" #~ msgstr "時間" #, fuzzy #~ msgid "Select an album" #~ msgstr "全て選択(_A)" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "プレイリスト" #~ msgid "Re_fresh Library" #~ msgstr "ライブラリの再表示(_f)" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "ラジオ局の削除(_R)" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "不正な値" #, fuzzy #~ msgid "heading|Search" #~ msgstr "検索" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "使い方: %s %s" #~ msgid "_Download..." #~ msgstr "ダウンロード(_D)" #, fuzzy #~ msgid "_New Station..." #~ msgstr "新規ラジオ局(_N)" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "<b>%s</b>を上書きしますか?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet は既に起動しています。" #~ msgid "No song is currently playing." #~ msgstr "現在再生中の曲はありません。" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "%sに書き込みできないため、削除します。" #~ msgid "_Edit Bookmarks..." #~ msgstr "ブックマークの編集(_E)" #, fuzzy #~ msgid "_New Folder..." #~ msgstr "新規フォルダ(_N)" #~ msgid "_Add to Playlist" #~ msgstr "プレイリストへ追加(_A)" #~ msgid "_Edit Display..." #~ msgstr "ディスプレイの編集(_E)" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d局" #~ msgid "_Add a Location..." #~ msgstr "場所の追加(_A)" #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Customizeヘッダ" #, fuzzy #~ msgid "Track Headers" #~ msgstr "トラック番号ヘッダ(_T)" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Peopleヘッダ" #, fuzzy #~ msgid "Album Headers" #~ msgstr "アルバムヘッダ(_A)" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Dateヘッダ" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Fileヘッダ" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Productionヘッダ" #, fuzzy #~ msgid "Tag:" #~ msgstr "タグ(_T)" #, fuzzy #~ msgid "Warnings" #~ msgstr "レイティング(_R)" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "アルバムアーティスト" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "アーティスト" #, fuzzy #~ msgid "album (sort)" #~ msgstr "アルバムアーティスト" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "演奏者" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "演奏者" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainzアルバムアーティストID" #, fuzzy #~ msgid "errors" #~ msgstr "エラー" #~ msgid "Permanently delete this file?" #~ msgstr "このファイルを完全に削除しますか?" #~ msgid "Permanently delete these files?" #~ msgstr "これらのファイルを完全に削除しますか?" #, fuzzy #~ msgid "Version:" #~ msgstr "バージョン" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "プラグインのエラー" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s をライブラリに追加できませんでした。\n" #~ "\n" #, fuzzy #~ msgid "No eject command found." #~ msgstr "ラジオ局が見つかりません" #~ msgid "Unable to start web browser" #~ msgstr "webブラウザを起動できません" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "webブラウザが見つかりません。環境変数$BOWSERを設定するか、/usr/sbin/" #~ "sensible-browserが存在することを確認してください。" #, fuzzy #~ msgid "Library Error" #~ msgstr "ライブラリブラウザ" #, fuzzy #~ msgid "_Output device:" #~ msgstr "デバイスへコピー(_C)" #~ msgid "translator-credits" #~ msgstr "Yasushi Iwata <yasusii@lowlife.jp>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "表示したいカラム名をスペースで区切って入力します" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "続行する(_C)" #~ msgid "Search your library" #~ msgstr "ライブラリを検索します" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "合計サイズ" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet プラグイン" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "単純な検索は青、詳細な検索は緑、間違った入力内容は赤で表示します" #~ msgid "Separators for splitting tags" #~ msgstr "タグを分割するときの区切り文字" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libetの設定" #~ msgid "Not Played To_day" #~ msgstr "この1日再生していない曲(_d)" #~ msgid "Not Played in a _Week" #~ msgstr "この1週間再生していない曲(_W)" #~ msgid "Not Played in a _Month" #~ msgstr "この1ヶ月再生していない曲(_M)" #~ msgid "B_ottom 40" #~ msgstr "下位40曲(_B)" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "再生回数の下位40曲(組になっているものがある場合40曲以上が選択される場合も" #~ "あります)" #, fuzzy #~ msgid "Date" #~ msgstr "日付(_D)" #~ msgid "Add" #~ msgstr "追加" #, fuzzy #~ msgid "Bitrate" #~ msgstr "ビットレート" #~ msgid "_Stations..." #~ msgstr "ラジオ局(_S)" #~ msgid "Unable to save library" #~ msgstr "ライブラリの保存に失敗しました" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "曲の再生ができません" #~ msgid "Sort by title" #~ msgstr "タイトルで並び換え" #~ msgid "Sort by artist" #~ msgstr "アーティストで並び換え" #~ msgid "Lyrics provided by %s." #~ msgstr "歌詞の提供元 %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "歌詞が見つかりません。\n" #~ "\n" #~ "ダウンロードボタンをクリックすると歌詞のオンライン検索を実行します。また、" #~ "自分で歌詞を入力して保存することもできます。" #~ msgid "part" #~ msgstr "パート" #~ msgid "Opening audio device." #~ msgstr "オーディオデバイスのオープン中です。" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d 曲を保存しました" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainzアルバムID" #~ msgid "Loaded song library." #~ msgstr "ソングライブラリの読み込み" #~ msgid "Unable to open audio device" #~ msgstr "オーディオデバイスのオープンに失敗しました" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libetは'autosink'と'%(sink)s' ドライバへのアクセスに失敗しました。~/." #~ "quodlibet/configの\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "を編集してGStreamerのパイプラインを変更してください。" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod LibetはGStreamerの'filesrc'要素を見つけられませんでした。GStreamerの" #~ "インストール状態を確認してください。" #~ msgid "Unable to retag multiple values" #~ msgstr "複数の値によるタグの付け直しはできません" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "複数の値を持つタグ名の変更はサポートされていません。" #~ msgid "W: %s is not a QL song database." #~ msgstr "警告: %sはQuod Libetのデータベースではありません" #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "曲単位の(\"Radio\")音量調整" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "アルバム単位の(\"Audiophile\")音量調整" #~ msgid "_Volume Normalization" #~ msgstr "音量の均一化" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "ライブラリをスキャンしています。この処理には数分かかるかもしれません。\n" #~ "\n" #~ "%d曲を再読込\n" #~ "%d曲を削除" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "新しい曲をスキャンしてライブラリに追加しています。\n" #~ "\n" #~ "%d曲を追加しました" #, fuzzy #~ msgid "Add Custom Header" #~ msgstr "カスタムヘッダの追加" #, fuzzy #~ msgid "_Header:" #~ msgstr "ヘッダ(_H)" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3Uプレイリストを読み込めません。" #~ msgid "This station is already in your library." #~ msgstr "このラジオ局は既にライブラリに登録されています。" �����������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/ko.po����������������������������������������������������������������������������0000644�0001750�0001750�00000672542�14436352625�013624� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Korean translation of Quod Libet # ChangBom Yoon <changbom.yoon@gmail.com>, 2006 # Byung-Hee HWANG <bh@izb.knu.ac.kr>, 2006 # $LUG: projects/quodlibet/ql_0_23_ko.po,v 1.2 2006/08/09 08:35:52 bh Exp $ # msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.23\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2022-11-09 13:47+0000\n" "Last-Translator: 이정희 <daemul72@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/ko/>\n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Weblate 4.15-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "제목(_T)" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "피플(_P)" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "날짜(_D)" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "추가된 날짜(_D)" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "원본 날짜(_O)" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "장르(_G)" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "별점(_R)" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "재생 횟수(_C)" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "정렬 기준(_B)…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "환경설정(_P)" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "앨범 목록" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "앨범 목록(_A)" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "모든 앨범" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d 앨범" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "앨범 표지 다시 불러오기(_C)" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "앨범에 없는 노래" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d 트랙" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d 디스크" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "예시 앨범" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "앨범 목록 설정" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "앨범 표지 표시하기(_C)" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "피플을 포함하여 인라인 검색하기(_S)" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "옵션" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "앨범 표시" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "닫기(_C)" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "라이브러리 탐색기" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d 곡" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "유효하지 않은 양식" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "앨범 컬렉션" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "앨범 컬렉션(_C)" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "알 수 없음 %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "다중 %s 값" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "사용자 지정(_C)" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "추가하기(_A)" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "제거하기(_R)" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "태그" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "합치기" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "앨범 목록 설정" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "적용하기(_A)" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "취소하기(_C)" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "커버 그리드" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "표지 격자(_C)" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "커버 그리드 설정" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "앨범_텍스트 표시" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "\"모든 앨범\" 항목 표시" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "와이드 모드" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "커버 확대" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "파일 시스템" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_파일 시스템" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "노래를 복사할 수 없습니다" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "선택한 파일은 다른 노래 목록이나 대기열로 복사 할 수 없습니다." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "라이브러리에 추가하기(_A)" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "방송국 목록은 방송국의 주소만 포함되어야 합니다. 다음 주소는 추가할수 없습니" "다:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "인터넷 라디오" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "방송국 추가" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "방송국 목록 다운로드" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "새 방송국" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "인터넷 라디오 방송국의 주소를 입력하세요:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "일렉트로닉" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "힙합/랩" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "고전 명곡" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "일본어" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "인도어" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "종교" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "차트" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "터키어" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "레게 / 댄스 홀" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "라틴" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "대학 라디오" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "토크 / 뉴스" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "주변 음악" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "재즈" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "클래식" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "팝" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "얼터너티브" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "메탈" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "컨트리" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "뉴스" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "슐라거" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "펑크" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "인디" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "블루스" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "소울" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "라운지" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "펑크" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "레게톤" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "슬라브" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "그리스" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "고딕" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "락" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "인기있는 라디오 방송국 목록을 불러올까요?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_방송국 불러오기" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_인터넷 라디오" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "모든 방송국" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "즐겨찾기" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "카테고리 없음" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "방송국 추가하기(_A)…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_방송국 새로 고침" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "발견된 방송국이 없습니다" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s 에서 발견된 인터넷 라디오 방송국이 없습니다." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "추가할 항목이 없습니다" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "목록에 있는 모든 방송국은 이미 라이브러리에 존재합니다." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "즐겨찾기에 추가" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "즐겨찾기에서 제거" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d 방송국" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "창 탐색기" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_창 탐색기" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "모두 선택하기(_A)" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "알 수 없음" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "모두" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "작게" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "넓게" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "일렬로" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "선택적 마크업이 있는 태그 패턴(예: <tt>작곡가</tt> 또는\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "창 탐색기 설정" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "열 형식" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "열 내용" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "창 너비를 같게" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "재생 목록" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_재생 목록" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_재생 목록에서 제거" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_추가" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "가져오기(_I)…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "재생 목록을 가져올 수 없습니다" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet 은 M3U 와 PLS 포맷에서만 재생 목록을 가져올 수 있습니다." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "삭제하기(_D)" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_이름 바꾸기" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "재생 목록 이름을 바꿀 수 없습니다" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "재생 목록 가져오기" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_가져오기" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_새 재생목록…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "%d 들로 무엇을 하시겠나요?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "재생 목록 \"%s\"에 대한 작업 확인" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "공백" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "예시 재생목록" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "재생 목록 탐색기 설정" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "재생 목록 화면" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "재생 목록 '%s'을 삭제하시겠습니까?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "선택된 재생 목록에 대한 모든 정보가 제거되며 복구할 수 없습니다." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "트랙 추가하기(_A)" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "새 재생목록" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "새 재생 목록 명을 입력하십시오:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "만들기(_C)" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "재생목록을 가져옵니다.\n" "\n" "%(current)d/%(total)d 곡을 추가했습니다." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "새 피드" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "오디오 피드의 주소를 입력하십시오:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "피드 추가하기(_A)…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_ 새로 고침" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "새 노래를 위해 이 폴더 감시" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "피드를 추가할 수 없습니다" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s (을)를 추가할 수 없습니다. 서버가 다운되었거나, 입력한 주소가 오디오 피드" "가 아닐 수 있습니다." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "현재 오디오 백엔드가 URL을 지원하지 않으며, 오디오 피드 탐색기가 비활성화되" "어 있습니다." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "결과 제한" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "여러 쿼리 허용하기(_A)" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "트랙 목록" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_트랙 목록" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "사운드클라우드" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "사운드클라우드(Souncloud) 탐색기" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "사운드 클라우드(_C)" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "검색" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "내 트랙" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "%s로 이동" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "연결 완료" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet이 %s에 연결되었습니다!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "%s에서 로그아웃" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "코드를 입력하세요…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "%s (으)로 로그인" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "사운드클라우드 인증" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "사운드클라우드 인증 코드를 입력하세요:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 이 실행 중이 아닙니다( '--run'을 시작하기 위해 추가하세요)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "음악 라이브러리 및 재생기" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[옵션]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "재생중인 노래 표시 후 마침" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "곧 노래 시작" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "시작 시 창을 보이지 않기" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "다음 노래로 가기" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "이전 곡으로 이동하거나 시작에 가까우면 다시 시작" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "이전 노래로 가기" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "연주 시작" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "연주 일시정지" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "재생 멈춤" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "음량 증가" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "음량 감소" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "재생중인 곡의 별점 별 1개 올리기" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "재생중인 곡의 별점 별 1개 내리기" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "재생기 상태 표시" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "메인 창 숨기기" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "메인 창 보이기" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "메인 창 표시 토글(Toggle)" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "실행중인 재생기 강조" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "활성화된 탐색 필터 제거" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "라이브러리 새로 고침 및 재검색" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "가능한 탐색 목록" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "현재 재생목록 표시" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "대기열 내용 표시" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "대기열 내용 표시" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "플러그인 없이 시작" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet 이 실행 중이 아니면 실행하기" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quod Libet 마침" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "재생중인 노래에서 탐색" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "셔플 모드 설정 또는 전환" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "셔플 모드 종류 설정" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "반복 끄기, 켜기, 토글(Toggle)" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "반복 모드 종류 설정" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "음량 설정" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "오디오 라이브러리 검색" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "쿼리" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "파일 재생" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "파일명" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "재생중인 곡의 별점 설정하기" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "현재 브라우저 지정" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "노래 재생 후 멈춤" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "새 브라우저 열기" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "대기열 보이기 및 숨기기" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "임의의 값으로 필터" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "태그" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "태그 값으로 필터" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=value" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "파일 또는 쿼리를 큐에 넣기" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "쉼표로 구분된 파일을 대기열에 추가" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "파일이름" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "쿼리 결과의 파일이름을 stdout에 출력하기" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "파일 또는 쿼리의 대기열 해제" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "라이브러리에 파일 또는 경로 추가" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "주소" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "유효하지 않은 양식" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "'%s' 에 잘못된 인자입니다." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "%s --help 를 시도해 보세요." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "오류 발생" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "이 오류를 무시할 수 있지만 응용 프로그램이 재시작하기 전까지 불안정할 수 있습" "니다. 오류를 보고하는 데는 얼마 걸리지 않으며, 이는 많은 도움이 됩니다." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "오류를 보고하였습니다" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "재시작" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "오류 무시하기" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "오류 사항:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "오류 및 시스템에 대한 여러 세부 데이터가 제 3자인 온라인 서비스(<a " "href='https://www.sentry.io'>www.sentry.io</a>)로 전송됩니다. 아래에서 전송되" "기 전 데이터를 검토할 수 있습니다." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(선택 사항) 오류가 났을 때 어떤 일이 일어났는지 짧은 설명을 써주세요:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_전송" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "설명…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "전송될 데이터:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "오디오 태그 편집기" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "디렉토리" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "오디오 태그 편집기" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "작품 URL 표지 출처" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "<tt>artwork_url</tt>에 태그된 링크에서 커버를 다운로드 하세요. 이 작업은 사운" "드클라우드 탐색기에서 이루어집니다." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs 커버 표지" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Discogs에서 커버 다운로드하기." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm 커버 출처" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Last.fm의 커버 아트 저장소에서 커버를 다운로드 하세요." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz 커버 출처" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "MusicBrainz의 커버 아트 저장소에서 커버를 다운로드 하세요." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "인코딩 변환" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "태그 편집기에서 잘못 해석된 태그 값 인코딩을 수정하세요." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "인코딩 변환하기(_C)…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "가나/한자 간편 변환기" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "이름을 바꾸기 전에 가나/한자를 로마자로 변환합니다." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "로마자 _일본어 텍스트" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "'가나/한자 간편 변환기'(kakasi)를 찾을 수 없습니다." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "정규식 대체" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "제목" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "태그 편집기에서 태그를 대문자로 표시합니다." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "각 단어의 첫 글자를 대문자로(_C)" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "태그에 전체 대문자 허용하기(_A)" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Paned Browser 설정" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "표지 크기(_C):" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Edit Display" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "무게" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "텍스트 정렬하기(_A):" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "지연(_D):" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "디스플레이 패턴 편집하기(_I)…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "미리보기" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "정보" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "지원 포맷: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "장르 필터" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "디렉토리" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "오디오 백엔드" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "곡이 재생되거나 건너뛸 때마다 플러그인이 파일에 태그를 씁니다. 싫어해서 건너" "뛴 노래의 별점이 파일에 기록되도록 하려는 경우에 유용할 수 있습니다." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "곡을 재생하거나 건너뛸 때 해당 노래의 앨범이 확인됩니다. 앨범의 모든 곡에 별" "점이 지정되었고 파일에 별점이나 재생 횟수가 저장된 노래 중 하나 이상이 없는 " "경우 플러그인은 노래 파일에 태그를 기록합니다.\n" "\n" "이 기능을 사용하여 지속적인 파일 업데이트를 방지하지만 앨범이 업데이트되면 수" "정된 별점 및 재생 횟수를 파일에 기록할 때마다 '파일의 태그 업데이트' 플러그인" "을 사용해야 합니다." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "새 방송국" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "곡이 재생되면 파일의 태그를 업데이트합니다. 이렇게 하면 재생 횟수와 별점이 최" "신 상태로 유지됩니다." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "태그에 별점 및 재생 횟수 저장하기(_C)" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "녹음 날짜" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "%s의 오류" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "업데이트 방법(_U):" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "설정" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "자동 별점" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "불러오는데 실패하였습니다" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "%d에 대한 별점과 통계를 성공적으로 불러왔습니다" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee 불러오기" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Banshee에서 별점 및 곡 통계를 가져옵니다." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "데이터베이스 경로(_D):" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "불러오기 시작" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "알람 시계" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "큰 소리로 음악과 함께 당신을 깨워줍니다." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "자장가 모드" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "페이드 아웃하고 음악 재생을 중지합니다." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim 상태 메세지" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim 상태 메세지" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Gajim 상태 메시지를 최근 들은 곡에 따라 변경합니다." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "멈춤" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "양식" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "양식" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "플랫(Flat)" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "라이브(Live)" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "풀 베이스 & 트레블(Full Bass & Treble)" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "클럽(Club)" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "라지 홀(Large Hall)" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "파티(Party)" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "소프트(Soft)" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "풀 베이스(Full Bass)" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "레게" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "헤드폰(Headphones)" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "소프트 락" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "풀 트레블(Full Treble)" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "댄스" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "테크노" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "스카(Ska)" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "노트북" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "이퀄라이저" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "이퀄라이저로 노래의 톤을 조절하세요.\n" "클릭 혹은 키보드로 단계를 조절하면 됩니다(우클릭으로 음역대를 초기화할 수 있" "습니다)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "현재 백엔드가 이퀄라이저를 지원하지 않습니다." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "기본 사전 설정" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "선택…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_EQ(이퀄라이저) 재설정" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "_사용자 지정 사전 설정" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "선택된 항목 삭제하기(_D)" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "저장할 사전 설정명:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_저장" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "온라인" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "오프라인" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "채팅" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "자리 비움" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "부재중" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "숨김" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim 상태 메세지" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Gajim 상태 메시지를 최근 들은 곡에 따라 변경합니다." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "멈춤" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "양식:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "상태 메시지 변경을 위해 공백으로 구분된 계정을 나열합니다. 아무 것도 지정하" "지 않으면 모든 계정의 상태 메시지가 변경됩니다." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "계정:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "'[일시 정지]' 추가" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "체크하면, '[paused]'가 일시 정지 상태 메세지에 추가됩니다" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "변경될 메세지의 상태입니다" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "헤드폰 제거 시 재생 정지" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "헤드폰을 뽑으면 재생을 멈추고, 다시 꼽으면 음악이 재생됩니다." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "화면 보호기 금지/중지" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "그놈(GNOME) 데스크탑에서 음악이 재생되는 중일 때, 화면 보호기가 활성화되지 않" "거나 컴퓨터가 일시 정지되지 않습니다." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "음악이 재생 중입니다" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "금지 모드:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "인터넷 라디오 기록" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "재생율" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "암호(_A):" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "주소" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "메인 창 숨기기" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "양식" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "양식" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d 곡" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "정보" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "양식" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "주소" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz album type" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "MusicBrainz와 곡의 별점을 동기화합니다." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "이름:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "제목(_T):" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "본문(_B):" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "<i>자동</i> 곡 변경 시에만(_A)" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Notification daemon에 연결할 수 없습니다." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "노래 알림" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "노래가 바뀌면 알림을 띄웁니다." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "다음" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "노래 알림" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "플러그인 창에서 QLScrobbler를 설정하세요. 그때까지는 노래가 제출되지 않습니" "다." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "'%s'에 연결할 수가 없습니다." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "인증 실패: 유효하지 않은 URL입니다." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "인증 실패: 유효하지 않은 사용자명:'%s'이거나 잘못된 비밀번호입니다." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "클라이언트가 금지되었습니다. 관리자에게 문의하세요." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "시스템 시간이 잘못되었습니다. 수정 전까지 제출이 안 될 수 있습니다." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler 제출" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Last.fm, Libre.fm 그리고 그 외 다른 Audioscrobbler 서비스를 위한 " "Audioscrobbler 클라이언트." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "인증에 성공했습니다." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_서비스:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "그 외…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_계정 데이터 확인" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "아티스트 패턴(_A):" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_제목 형식:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "제외_필터:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "제출할 아티스트 명을 지정하는 형식입니다. 기본값은 공백입니다." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "제출할 제목을 지정하는 형식입니다. 기본값은 공백입니다." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "필터와 일치하는 노래가 없습니다" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_오프라인 모드(아무것도 제출하지 않음)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "제출" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "라디오 광고 음소거" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "라디오 광고가 재생되는 동안 출력을 음소거합니다.\n" "방송국: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "임의의 앨범 재생" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "재생 목록 끝에 도달하면 임의의 앨범을 재생합니다. 이를 위해서 활성 탐색기가 " "앨범별 필터를 지원해야 합니다." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "높은 평가를 받은 순으로" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "자주 재생된 순으로" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "자주 건너뛴 순으로" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "최근 재생된 순으로" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "최근 재생된 순으로" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "최근에 추가된 순으로" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "긴 앨범 순으로" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "다음 앨범을 시작하기 몇 초 전에" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "무게" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "다른 앨범보다 더 많이 재생한 순으로" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "피함" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "선호하는 순으로" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "임의의 앨범" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "%s 시작을 기다리는 중" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "%d개 곡에 대한 별점 및 통계를 성공적으로 가져왔습니다" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "리듬박스 불러오기" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Rhythmbox에서 별점 및 노래 통계를 가져옵니다." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "화면보호기 멈춤" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "그놈 화면보호기가 활성화될 때 재생을 멈춥니다." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Quod Libet를 위한 GNOME Shell의 검색 제공자가 설치되어 있지 않습니다." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "그놈 검색 제공" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "그놈 쉘에서 라이브러리를 검색하는 것을 허용합니다." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "대체 탐색 바" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "대체 탐색 바가 항상 보이며, 모든 창의 폭에 걸쳐집니다." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "탐색 포인트 북마크" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "트랙에 대한 탐색 포인트 A 및/또는 B를 저장합니다. 트랙이 재생되면 지정한 A 시" "간으로 건너뛰고 B 시간 이후에 멈춥니다.\n" "\n" "ℹ 아래 포인트의 이름을 변경해도 실제 책갈피 이름은 업데이트되지 않으며 검색 " "여부를 결정할 때 플러그인이 찾는 책갈피 이름만 변경됩니다." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "A 포인트를 위한 북마크 명" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "트랙이 시작될 때 확인할 북마크 명과 발견된 경우 플레이어가 해당 타임스탬프를 " "검색합니다" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "B 포인트를 위한 북마크 명" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "트랙이 있는 경우 트랙 재생 중에 각 체크 포인트를 사용할 북마크 명입니다. 현" "재 위치가 타임스탬프를 초과하면 트랙의 끝을 검색합니다." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeexebox 동기화" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "로지텍 Squeezebox가 Quod :Libet의 출력을 미러링하도록 합니다. 둘 다 동일한 라" "이브러리에서 읽을 수 있습니다." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "<a href=\"%(plugin_link)s\">Squeezebox 플러그인으로 내보내기</a>와 함께 구성" "을 공유합니다." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Squeezebox 서버를 찾는 중 오류가 발생했습니다" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "%s를 찾는 데 오류가 생겼습니다. 설정을 확인해 주세요" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "일시 정지" #: quodlibet/ext/events/stop_on_pause.py:24 #, fuzzy msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "이 플러그인은 일시 정지/재생/탐색을 변경합니다.\n" "\n" "이 동작은 시스템에 새 오디오 장치(Bluetooth 스피커, USB DAC 등)가 추가될 때 " "Quod Libet이 오디오 장치를 전환하지 못하는 경우에 유용합니다.\n" "\n" "'검색 가능한 소스만' 옵션이 선택되지 않은 경우 이 플러그인은 현재 소스의 위치" "가 유지되도록 합니다. 그렇지 않으면 재생이 중지된 상태로 남아 처음부터 다시 " "시작해야 합니다." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "검색 가능한 소스들만" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "플러그인 옵션" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "보류 중인 사본" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "대기 중인 목록 삭제" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "삭제" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "건너뛰기" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "복제하기" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "동기화 중" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "삭제하기" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "성공" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "실패" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "기존 파일 건너뛰기" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "노래의 파일명을 설정할 수 없습니다." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "기기 동기화" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "선택한 저장된 검색어의 모든 노래를 지정된 폴더와 동기화합니다." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "다음 저장된 검색어를 동기화합니다:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "내보내기 위치의 절대 경로" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "저장된 검색어에 없는 대상 폴더의 모든 기존 파일이 삭제됩니다." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "MTP로 마운트된 장치의 경우 로컬 대상 폴더로 내보낸 다음 rsync를 사용하여 장치" "로 전송합니다. 또는 많은 파일을 안드로이드 기기에 동기화할 때 훨씬 더 빠른 " "adb-sync를 사용합니다." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "대상 경로:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "경로 양식" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "저장된 형식 편집…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "태그를 기반으로 내보낸 파일 이름의 구조" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "내보낼 형식:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "미리 듣기 멈춤" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "상태" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "소스 파일" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "내보내기 경로" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "조직" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "아직 저장된 검색어가 없으면, 몇 개를 만들고 다시 오십시오!" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "새 방송국을 선택하십시오" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "동기화의 예상 결과:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "절대경로가 아닙니다" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "아래 양식\n" "\n" "<b>{}</b>\n" "\n" "는 \"/\"를 포함하지만, root 에서 시작하지 않고 있습니다. 올바르게 지정하려" "면, \"/\" 또는 \"~/\" 으로 시작하십시오." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "저장된 검색어가 선택되지 않음" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "선택한 저장된 검색어에 곡이 없음" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "선택한 모든 저장된 검색어가 비어 있습니다." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "노래를 저장할 수 없습니다" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "동기화의 결과:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "{count} 파일을 열 수 없습니다" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "가사" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "재생 중:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "곡 없음:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "양식" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Thumb 별점" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "별점 값으로 변환되는 thumb-up / thumb-down 채점 시스템을 추가합니다. 총 투표" "수를 유지하고 <b><tt>~#score</tt></b>별로 정렬하는 데 유용합니다." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "재생중인 곡 없음" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "재생목록" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "일시정지(_A)" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "미리보기" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "섞어서" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "반복" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "이 곡 재생 후 정지하기(_A)" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "브라우저 열기(_B)" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "태그 편집" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "정보" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "재생목록" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Edit Display" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "가사" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "이 노래에 해당하는 가사가 없습니다\n" "%s" #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "노래를 저장할 수 없습니다" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "비주얼리제이션 시작하기" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "외부 비주얼리제이션을 시작합니다." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "'%s'을(를) 사용하여 비주얼리제이션을 실행할 수 없습니다" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "에러 보이기" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "파일:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "비율(_A):" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "프리셋(_P):" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "아티스트 필터" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "사용자 지정" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "사용자 지정 설정" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "밴드 필터링(_B):" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "필터 폭(_W):" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "속도(_A):" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "오디오 피치/속도" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "오디오 스트림의 피치를 제어합니다." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "재생목록 가져오기" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "가져오기" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "대상 폴더:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "파일이름 패턴:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "재생목록을 가져올 수 없습니다" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "기본 파일이름 패턴:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "재생목록 가져오기" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "재생목록으로부터 제거" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "새 재생목록" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "마지막 재생" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "마지막 재생" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "대기열" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "대기열" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "대기열" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Never" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Never" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "그룹화 태그:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "노래를 복사할 수 없습니다" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "필터 태그:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "순서대로 재생되는 재생 순서(순서섞기) 모드를 추가하지만 별점이 지정된 임계값" "보다 낮거나 같은 트랙은 건너뜁니다." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "싫어요 트랙 건너뛰기(_D)" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "유효하지 않은 태그" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "저장된 값" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "저장된 값" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "사용자이름:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "라이브러리 경로:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "메인 창 숨기기" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "파일이름(_N):" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "\"%s\"을(를) 저장할 수 없습니다." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "앨범 목록" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "크기: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "검색(_S)" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "검색하는 중…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "앨범 목록" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "북마크 편집" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "북마크 편집하기(_E)…" #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "북마크" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz album type" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "필요할 때 \"앨범아티스트\" 쓰기(_A)" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "파일이름" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "디스크" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "트랙" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "제목" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "아티스트" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz album type" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "쿼리(_Q):" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "검색" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "검색 결과가 없습니다." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "주소" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "앨범 목록" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "앨범 목록" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "발견된 플러그인이 없습니다" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "미리보기" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "command|tag" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "이름 바꾸기" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "command|tag" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Never" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "유효하지 않은 값" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "사용자 지정 명령" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "사용자 지정 명령 %s을(를) 실행할 수 없습니다" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "브라우저 비활성" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "분음 부호 제거하기(_D)" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "재생율" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Edit Display" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "여러 파일이 선택되었습니다." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "재생율" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "이미지 고르기(_C)…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "정확한 별점 설정하기" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "숫자로 노래의 별점을 설정할 수 있습니다." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "0.0에서 1.0까지의 척도로 원하는 별점을 부여하십시오" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "태그 값으로 필터" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer 는 선택한 노래를 불러올 수 없습니다." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "장르 필터" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "대기열" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "쓰기" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz track ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "디렉토리" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "앨범 모드" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "지문 생성:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "세부 정보(_D)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "새 방송국" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "파일에서 수정된 태그를 업데이트합니다. 이렇게 하면 플레이 횟수와 별점이 최신 " "상태로 유지됩니다." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "발견된 플러그인이 없습니다" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "%(current)d/%(total)d곡 올리는 중" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "%s을(를) 업로드할 수 없습니다. 장치의 공간이 부족하거나 꺼져 있을 수 있습니" "다." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "재생목록 가져오기" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "재생목록 가져오기" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "더 많은 정보" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "'트랙 사용자 데이터'라는 용어에는 선택한 트랙이 있는 재생 목록과 다음 메타데" "이터가 포함됩니다:\n" "\n" "%s\n" "\n" "내보내기로 선택한 모든 항목을 가져옵니다. 파일 스템(확장자가 없는 파일 이름)" "을 내보낸 경우 가져올 때 선택한 파일의 이름이 바뀝니다.\n" "\n" "앨범을 내보낸 후 데이터를 앨범의 다른 버전으로 가져올 수 있습니다. 트랙의 순" "서와 수는 다를 수 있습니다. 플러그인은 트랙 이름이 약간 다르더라도 내보낸 데" "이터를 새 트랙과 일치시킵니다. 자동 매칭이 항상 정확한 것은 아니므로 다음 유" "사도 값을 너무 많이 줄이지 않는 것이 좋습니다." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "앨범 유사성:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "재생목록 가져오기" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "가져오기" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "장르 필터" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "디스크" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "트랙" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "아티스트" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "앨범 일치" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "계속하기" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "파일이름" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "트랙" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "동기화 중 오류 발생(%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "사용자이름(_U):" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "재생목록 가져오기" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "<b>%s</b> 삭제 실패." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "라이브러리 새로고침" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "라이브러리 새로고침" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "트랙" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "기존 태그" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "태그 분할하기" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "앨범의 디스크 번호와 제목의 버전을 동시에 분할합니다." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "앨범 분할하기" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "디스크 번호를 분할합니다." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "미리보기" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "태그" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 선택한 노래의 BPM을 탭합니다." #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "검색" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "임의의 노래 태그를 사용하여 웹사이트의 사용자 선택을 검색합니다.\n" "패턴을 지원합니다. %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "양식" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "검색 URL 편집하기" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "검색어 구성하기…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "태그 편집하기" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "검색" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "라이브러리" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "마운트 지점 확인" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "라이브러리 스캐닝" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "스캐닝 %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "라이브러리 스캐닝" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "음악 라이브러리 및 재생기" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Show _programmatic tags" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "설명" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "값" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "오디오 태그 편집기" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "감지된 변경사항 없음" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "태그 값으로 필터" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "태그 값으로 필터" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "정보에 시간이 없습니다" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "이미지 파일을 불러오지 못했습니다 : %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "파일" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "사용 정보 개요 표시" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s'은(는) 올바른 열 이름(%(all-column-ids)s)이 아닙니다." #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "Unknown" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "순서대로" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "순서대로" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "임의로" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "임의로" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "마지막 재생" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "반복" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "모두 반복하기(_A)" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "선택한 노래를 1회 재생" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "선택한 노래를 한 번만 재생" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "재생에 사용되는 GStreamer 출력 파이프라인입니다. 기본 파이프라인에 대해서는 " "비워 둡니다. 파이프라인에 싱크가 포함되어 있으면 기본 싱크 대신 싱크가 사용됩" "니다." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "버퍼 지속시간(_B):" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "GStreamer 오디오 싱크를 찾을 수 없습니다. 시도됨: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "폴더를 생성할 수 없습니다" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "이름:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "태그(_A):" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "플러그인" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "시작" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "시간" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "북마크 이름" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "북마크" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "필터" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Never Played" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "최근에 추가됨(_A)" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "새방송국" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "현재 아티스트에서(_A)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "현재 앨범에서(_B)" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "랜덤 장르" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "무작위 아티스트(_A)" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "무작위 앨범(_B)" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "최대 40 곡이 재생되었습니다" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "이름:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "값:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "저장된 값" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "저장된 값 편집하기…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "_Track Headers" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "앨범 모드(_A)" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "_Replay Gain volume adjustment" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Unknown" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "추가하기(_A)…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "편집(_E)" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "태그 표현식(예: 피플:이름 또는 ~앨범~연도)" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "태그 값으로 필터" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "오디오 태그 편집기" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "파일:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "%(file_count)d개 파일을 영구적으로 삭제 하시겠습니까?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "파일 삭제하기(_D)" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "%(file_count)d개 파일을 휴지통으로 이동하시겠습니까?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "휴지통으로 이동" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "%(current)d/%(total)d곡을 이동하는 중입니다." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "라이브러리를 저장할 수 없습니다" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "<b>%s</b> 삭제 실패." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "%(current)d/%(total)d곡을 삭제하는 중입니다." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "파일 삭제에 실패했습니다" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "<b>%s</b> 삭제 실패." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "브라우저" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "파일 내려받기" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "%d개의 곡에서 누락됨" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d개의 곡에서 다름" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "여러 값으로 분할하기(_M)" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "앨범없이 디스크 분할하기(_A)" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "제목없이 버전 분할하기(_V)" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "아티스트없이 편곡자 분할하기(_T)" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "아티스트없이 연주자 분할하기(_P)" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "제목없이 연주자 분할하기(_P)" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "제목없이 원곡아티스트 분할하기(_O)" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "태그 추가" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "태그:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "프로그래밍 방식으로 태그 표시하기(_P)" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Show _programmatic tags" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Never" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "구성하기(_C)" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "태그 분할하기(_S)" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "값 복사하기(_C)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "태그를 추가할 수 없습니다" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "%s을(를) 추가할 수 없습니다" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "선택한 파일은 <b>%s</b>에 대해 여러 값을 추가할 수 없습니다." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "잘못된 태그" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "잘못된 태그 %s\n" "\n" "현재 선택한 파일은 이 태그 편집을 지원하지 않습니다." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "유효하지 않은 값" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "태그에 결함이 있습니다" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s (이)가 프로그램이 실행되는 동안 변경 되었습니다. 새로 고침이 없" "이라이브러리를 저장하면 그 노래에 다른 변경 사항이 덮혀 쓰이게 됩니다." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "노래를 저장할 수 없습니다" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "%(file-name)s을(를) 저장하지 못했습니다. 파일이 읽기 전용이거나, 손상되었거" "나, 편집할 수 있는 권한이 없을 수 있습니다." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "더 많은 옵션…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "정보(_A)" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "업데이트 확인하기(_C)…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "플러그인" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s 및 %(count)s회 이상" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso 설정" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "폴더" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "새 폴더(_N)…" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "하위폴더 모두 선택" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "새 폴더" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "새 폴더 이름을 입력하십시오:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "폴더를 생성할 수 없습니다" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "폴더를 지울 수 없습니다" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "노래" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "아티스트: %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "%s 디스크" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "%s 트랙" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "디스플레이 편집하기(_E)…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "선택한 노래가 없습니다." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "곡 없음" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "정보" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "가사" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "기획: %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "아티스트" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "아티스트" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "연주" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "안함" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d 회" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "추가" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "마지막 재생" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "재생" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "통과" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "별점" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "길이" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "정보" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[유효하지 않은 인코딩]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "비트율" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "파일 크기" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "수정" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 선택" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "트랙을 이용할 수 없습니다" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "앨범이 없는 노래 %d 곡" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "선택한 음반" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "아티스트가 없는 노래 %d 곡" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "앨범" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "총 길이:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "총 크기:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "파일" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "온라인으로 보기(_V)" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "이 노래의 가사를 찾을 수 없습니다." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "변경된 태그를 버릴까요?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "태그가 변경되었으나 저장되지 않았습니다. 이 파일을 저장할까요? 아니면 변경사" "항을 무시하고 이전으로 되돌릴까요?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Never" #: quodlibet/qltk/msg.py:108 #, fuzzy msgid "File exists" msgstr "파일 시스템" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "파일이름 바꾸기" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "재생 순서" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "태그 편집" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "이름 바꾸기" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "쿼리" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "표지" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "플러그인 에러" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "브라우저 비활성" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "카테고리 없음" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "플러그인을 찾을 수 없습니다." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "플러그인" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "에러 보이기" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "디스크(_D)" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "트랙" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "그룹" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "아티스트(_A)" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "앨범(_B)" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "파일이름" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "길이" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "자동으로 현재 재생중인 노래로 가기" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "재생중인 곡이 변경되면 곡 목록에서 해당 곡으로 스크롤합니다" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "기타(_O):" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "편집하기(_E)…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "칼럼 표시" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "버전을 포함하는 제목" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "앨범에 디스크 자막 포함(_D)" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "아티스트는 모든 피플을 포함함(_P)" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "폴더를 포함하는 파일이름" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "설정" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "칼럼 표시" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "노래 목록" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "칼럼 표시" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "전역 필터:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "검색" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "브라우저" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "여러 별점 확인하기(_M)" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "한 번에 여러 곡의 별점을 변경하기 전에 확인 묻기" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "원클릭 별점 활성화(_O)" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "곡 목록에서 별점 열을 클릭하여 평가 활성화" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "별점" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "앨범 목록" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "연주 일시정지" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "폴백 게인(_F):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "_Replay Gain volume adjustment" #: quodlibet/qltk/prefs.py:445 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "_Replay Gain volume adjustment" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "시작 시 재생 계속하기(_C)" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "기본 별점(_D):" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "별점 등급(_S):" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "집계된 별점에 대한 베이지안 평균 계수(C)입니다.\n" "0은 일반적인 평균을 의미하고 값이 높을수록 트랙 수가 적은 앨범의 등급이 덜 극" "단적임을 의미합니다. 이 값을 변경하면 모든 앨범에 대한 재계산이 트리거됩니다." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "베이지안 평균 연산량(_B):" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "전자메일:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "별점 및 재생 횟수는 이 이메일 주소의 태그에 저장됩니다" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "태그 변경사항 자동 저장(_A)" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "태그 편집기에서 태그 값을 분할할 때 사용할 구분 기호 집합입니다. 목록은 공백" "으로 구분됩니다." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "태그를 분할하는 데 사용되는 문자(_T):" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "하위 태그 분리에 사용되는 문자(_S):" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "태그" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "태그 편집" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "새로운 별점 업데이트하는 중" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "라이브러리 검색" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "라이브러리 변경 체크" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "라이브러리 다시 빌드(_B)" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "사용자의 라이브러리에 있는 모든 노래를 다시 불러옵니다. 시간이 오래 걸릴 수 " "있습니다." #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "No Songs" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "라이브러리 새로고침" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "디렉토리 스캔" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s 및 %(count)d회 이상" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "등록정보" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "대기열" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "플러그인 에러" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "대기열의 모든 노래 지우기" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d song (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "라이브러리 찾아보기(_B)" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "메인 창 표시 토글(Toggle)" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "연주 일시정지" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "라이브러리 경로를 설정할까요?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "노래를 추가할 수 없습니다" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> 는 지원하지 않는 프로토콜을 사용하고 있습니다." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "현재 재생중인 노래로 가기" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "파일" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "노래" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "보기" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "찾아보기(_B)" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "제어하기(_C)" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "도움말" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "폴더 추가하기(_A)…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "파일 추가하기(_A)…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "위치 추가하기(_A)…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "북마크 편집하기…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "이 노래 후 정지" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "키보드 단축키(_K)" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "온라인 도움말" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "검색" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "주소 추가" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "오디오 파일의 주소를 입력하십시오:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "주소를 추가할 수 없습니다" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "음악 추가" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "폴더 추가하기(_A)" #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "음악 재생기" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "파일 추가하기(_A)" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "%d곡의 노래를 대기열에 넣으시겠습니까?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "대기열" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "모두 %d 곡의 별점을 변경하시겠습니까?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "저장된 별점이 제거됩니다" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "별점 제거하기(_R)" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "선택한 모든 곡의 별점이 %s(으)로 변경됩니다" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "별점 변경하기(_R)" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "공백을 밑줄로 바꾸기(_U)" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Windows와 호환되지 않는 문자 제거(_W)" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "분음 부호 표식 제거(_D)" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "ASCII가 아닌 문자 제거(_A)" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "파일이름 바꾸기" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "미리보기" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "파일이름" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "앨범 아티스트" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "디렉토리 선택" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "앨범 목록" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "새 이름" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "파일이름 변경을 할 수 없습니다" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "%(old-name)s의 이름을 %(new-name)s(으)로 바꾸지 못했습니다. 대상 파일이 이미 " "있거나, 새 파일을 만들거나, 이전 파일을 제거할 수 있는 권한이 없을 수 있습니" "다." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "모든 오류 무시하기(_A)" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "계속하기(_C)" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "절대경로가 아닙니다" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "아래 양식\n" "\t<b>%s</b>\n" "는 root 에서 시작하지않은 / 를포함하고 있습니다.폴더의 잘못된 이름을 피하려" "면, / 또는 ~/ 으로 시작하는 양식을취하십시오." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Songs placed in these folders (separated by ':') will be added to your " "library" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "포함된 모든 트랙의 메타데이터를 마이그레이션하여 스캔 루트(파일 제외)를 이동" "합니다." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "라이브러리 경로를 제거할까요?" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "재생율" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "디렉토리 선택" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "디렉토리 선택" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "저장된 검색어" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "저장된 검색어 편집하기…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "이 노래 후 정지" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "제한:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "무게" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "쿼리" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "남은 시간 표시" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "가사" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "실행중인 재생기 강조" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "재생중인 노래에서 탐색" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "노래를 추가할 수 없습니다" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "노래를 추가할 수 없습니다" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filter on %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "모든 헤더(_A)" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "트랙 헤더(_T)" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "앨범 헤더(_A)" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "피플 헤더(_P)" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "날짜 헤더(_D)" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "파일 헤더(_F)" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "프로덕션 헤더(_P)" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "헤더 사용자 정의(_C)…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "라이브러리에서 \"%(title)s\" 트랙을 제거하시겠습니까?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "%(count)d (을)를 라이브러리에서 제거할까요?" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "재생목록으로부터 제거" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "플러그인 구성하기…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "대기열 추가" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "라이브러리에서 제거하기(_R)…" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "파일 삭제에 실패했습니다" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "%(total)d개 파일 내려받기(_D)…" #: quodlibet/qltk/songsmenu.py:443 #, fuzzy msgid "successful" msgstr "성공" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "검색" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "파일 내려받기" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "{total}개 파일 내려받기" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "파일 내려받기" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "밑줄을 공백으로 바꾸기_U)" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "태그에 있는 각 단어의 첫 글자를 대문자로(_T)" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "여러 값으로 분할하기(_V)" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "경로 이름을 태그로" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "태그가 기존 태그를 대체합니다" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "태그가 기존 태그에 추가됩니다" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Edit Display" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "트랙 번호" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "시작:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "총 트랙:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "재생/일시정지" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "이전" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "및 %d개 이상…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "변경한 노래를 저장합니다." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s / %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "업데이트 확인" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "연결 실패" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "이미 최신 버전 %(version)s을(를) 사용하고 있습니다" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "재생목록 가져오기" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "이름이 %(name)s인 재생 목록이 %(path)s에 이미 있습니다" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "포함된 앨범 표지" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "오디오 파일에 포함된 표지를 사용합니다." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "파일시스템 표지" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "곡과 함께 공통 디렉터리에 있는 일반적으로 이름이 지정된 이미지를 사용합니다." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "표지 그림" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "간단한 사용 정보 화면표시하기" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "버전 및 저작권 화면표시하기" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "디버깅 정보 출력하기" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "사용법 : %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[옵션]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "%r 옵션이 인식되지 않습니다." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "%r 옵션에는 인수가 필요합니다." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r은(는) 고유 접두사가 아닙니다." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s 초" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "정보에 시간이 없습니다" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 초" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 분" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 시간" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 일" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d 년" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "check|titlecase?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "날짜는 반드시 'YYYY', 'YYYY-MM-DD' 또는 'YYYY-MM-DD HH:MM:SS' 형식으로 입력해" "야 합니다." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain gains must be entered in 'x.yy dB' format." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain peaks must be entered in 'x.yy' format." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDs must be in UUID format." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "%d개 파일 저장하는 중" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "노래를 편집할 수 없습니다" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "<b>%s</b> 저장을 할 수 없습니다. 읽기-전용 파일이거나, 변조된파일입니다. 또" "는 파일에 접근 권한이 없습니다." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[유효하지 않은 인코딩]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "앨범" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "편곡" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "편곡" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "편곡" #: quodlibet/util/tags.py:86 msgid "author" msgstr "작가" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "작가" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "command|tag" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "작곡" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "작곡" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "작곡" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "지휘" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "지휘" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "지휘" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "연락" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "저작권" #: quodlibet/util/tags.py:93 msgid "date" msgstr "날짜" #: quodlibet/util/tags.py:94 msgid "description" msgstr "설명" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "장르" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "장르" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "연주" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "연주" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "그룹" #: quodlibet/util/tags.py:98 msgid "language" msgstr "언어" #: quodlibet/util/tags.py:99 msgid "license" msgstr "라이센스" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "작사" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "작사" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "작사" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "조직" #: quodlibet/util/tags.py:104 msgid "title" msgstr "제목" #: quodlibet/util/tags.py:105 msgid "version" msgstr "버전" #: quodlibet/util/tags.py:106 msgid "website" msgstr "웹사이트" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "앨범 아티스트" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "디스크" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "트랙" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "라벨 ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "오리지널 출시 날짜" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "오리지널 앨범" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "오리지널 아티스트" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "녹음 날짜" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "출시 국가" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz album type" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "설정" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "디스크" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "트랙" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "마지막 시작" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "성명(FullName)" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "마운트 지점" #: quodlibet/util/tags.py:166 msgid "people" msgstr "피플" #: quodlibet/util/tags.py:168 msgid "year" msgstr "년" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "오리지널 출시 날짜" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "북마크" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "포맷" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "재생목록" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "오디오 태그 편집기" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "오디오 파일 태그 편집" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Quod Libet 마침" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "음악 재생기" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "듣기, 검색 및 오디오 모음 편집" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "재생목록 가져오기" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "<b>%s</b> (을)를 추가할 수 없습니다" #~ msgid "Invalid tags" #~ msgstr "유효하지 않은 태그" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "유효하지 않은 태그 <b>%s</b>\n" #~ "\n" #~ "지금 선택한 파일은 이러한 태그의 편집을 지원하지 않습니다." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d 초" #, fuzzy #~ msgid "Startup" #~ msgstr "가져오기" #~ msgid "Audio Feeds" #~ msgstr "오디오 피드" #~ msgid "_Audio Feeds" #~ msgstr "_오디오 피드" #~ msgid "New" #~ msgstr "추가" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "가사 검색중..." #, fuzzy #~ msgid "<artist>" #~ msgstr "아티스트" #, fuzzy #~ msgid "<album>" #~ msgstr "앨범" #, fuzzy #~ msgid "<title>" #~ msgstr "제목" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "재생목록 가져오기" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "재생목록 가져오기" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "정보" #~ msgid "Unsupported file type" #~ msgstr "지원하지 않는 파일 형식" #~ msgid "Unable to add station" #~ msgstr "방송국을 추가할 수 없습니다" #, fuzzy #~ msgid "Device Properties" #~ msgstr "등록정보" #, fuzzy #~ msgid "Mount point:" #~ msgstr "마운트 지점" #, fuzzy #~ msgid "Media Devices" #~ msgstr "오디오 장치: %s" #, fuzzy #~ msgid "_Media Devices" #~ msgstr "오디오 장치: %s" #, fuzzy #~ msgid "_Eject" #~ msgstr "선택" #, fuzzy #~ msgid "_Properties" #~ msgstr "등록정보" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "<b>%s</b> 삭제 실패." #, fuzzy #~ msgid "Unable to copy song" #~ msgstr "노래를 복사할 수 없습니다" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #, fuzzy #~ msgid "Unable to delete songs" #~ msgstr "노래를 추가할 수 없습니다" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "<b>%s</b> 삭제 실패." #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #, fuzzy #~ msgid "Unable to delete song" #~ msgstr "노래를 편집할 수 없습니다" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "<b>%s</b> 삭제 실패." #, fuzzy #~ msgid "Unable to eject device" #~ msgstr "파일 삭제에 실패했습니다" #~ msgid "Search Library" #~ msgstr "라이브러리 검색" #~ msgid "_Search Library" #~ msgstr "라이브러리 검색" #~ msgid "Rate the playing song" #~ msgstr "재생율" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "메인 노래 목록 보이기 및 숨기기" #, fuzzy #~ msgid "Unknown Device" #~ msgstr "Unknown" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "에러: '%s' 는 유일한 prefix 가 아닙니다." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "유효하지 않은 값" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "파일이름" #, fuzzy #~ msgid "_Clear" #~ msgstr "플러그인 에러" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "가사" #, fuzzy #~ msgid "Alternate search" #~ msgstr "검색 초기화" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "가사" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "가사" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "No Songs" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "브라우저" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "폴더를 생성할 수 없습니다" #~ msgid "Audio device: %s" #~ msgstr "오디오 장치: %s" #~ msgid "Downloads" #~ msgstr "내려받기" #~ msgid "Size" #~ msgstr "크기" #~ msgid "_Download" #~ msgstr "내려받기" #, fuzzy #~ msgid "browsers" #~ msgstr "브라우저" #~ msgid "Unable to download lyrics." #~ msgstr "가사를 내려받을 수 없습니다" #~ msgid "Set or toggle the playback order" #~ msgstr "연주 순서 지정 또는 토글(Toggle)" #, fuzzy #~ msgid "Combine tags with _multiple values" #~ msgstr "Split into multiple _values" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "라이브러리를 저장할 수 없습니다" #, fuzzy #~ msgid "Unable to save iPod database" #~ msgstr "라이브러리를 저장할 수 없습니다" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "track peak" #~ msgid "Shuffle" #~ msgstr "섞어서" #~ msgid "Weighted" #~ msgstr "무거운거로" #~ msgid "_Weighted" #~ msgstr "무거운거로" #~ msgid "_One Song" #~ msgstr "선택한 노래" #~ msgid "Restart the playlist when finished" #~ msgstr "완료후 재생목록 재시작" #~ msgid "Disable Browser" #~ msgstr "브라우저 비활성" #~ msgid "_Disable Browser" #~ msgstr "브라우저 비활성" #, fuzzy #~ msgid "Force Write" #~ msgstr "쓰기" #~ msgid "Filter on _Genre" #~ msgstr "장르 필터" #~ msgid "Filter on _Artist" #~ msgstr "아티스트 필터" #~ msgid "Filter on Al_bum" #~ msgstr "앨범 필터" #~ msgid "_Music" #~ msgstr "음악" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "북마크" #~ msgid "Song _List" #~ msgstr "노래 목록" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "이 노래 후 정지" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "and %d more..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Split Disc out of _Album" #, fuzzy #~ msgid "Timeout" #~ msgstr "시간" #, fuzzy #~ msgid "Select an album" #~ msgstr "모두 선택" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s and %(count)d more" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "재생목록" #~ msgid "Re_fresh Library" #~ msgstr "라이브러리 새로고침" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "재생율" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "유효하지 않은 값" #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "command|filename" #~ msgid "command|tag" #~ msgstr "command|tag" #, fuzzy #~ msgid "heading|Search" #~ msgstr "검색" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "사용법: %s %s" #~ msgid "_Download..." #~ msgstr "내려받기..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "새 방송국" #, fuzzy #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "<b>%s</b> 삭제 실패." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet 이 이미 실행중입니다." #~ msgid "No song is currently playing." #~ msgstr "현재 재생중인 노래가 없습니다." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "%s 에 쓸 수 없음. 제거합니다." #~ msgid "_Edit Bookmarks..." #~ msgstr "북마크 편집" #~ msgid "_New Folder..." #~ msgstr "새 폴더" #~ msgid "_Add to Playlist" #~ msgstr "재생목록 추가" #~ msgid "_Edit Display..." #~ msgstr "_Edit Display..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d station" #~ msgid "_Add a Location..." #~ msgstr "주소 추가..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Customize Headers..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Track Headers" #, fuzzy #~ msgid "People Headers" #~ msgstr "_People Headers" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Album Headers" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Date Headers" #, fuzzy #~ msgid "File Headers" #~ msgstr "_File Headers" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Production Headers" #, fuzzy #~ msgid "Tag:" #~ msgstr "태그:" #, fuzzy #~ msgid "Warnings" #~ msgstr "재생율" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "앨범 아티스트" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "아티스트" #, fuzzy #~ msgid "album (sort)" #~ msgstr "앨범 아티스트" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "연주" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "연주" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artist ID" #, fuzzy #~ msgid "errors" #~ msgstr "연주" #~ msgid "Permanently delete this file?" #~ msgstr "이 파일을 영구히 지울까요?" #~ msgid "Permanently delete these files?" #~ msgstr "이 파일을 영구히 지울까요?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s and %(count)d more..." #, fuzzy #~ msgid "Version:" #~ msgstr "버전" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "플러그인 에러" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s 는 라이브러리에 추가할 수 없습니다.\n" #~ "\n" #, fuzzy #~ msgid "No eject command found." #~ msgstr "발견된 방송국이 없습니다" #~ msgid "Unable to start web browser" #~ msgstr "웹브라우저를 시작할 수 없습니다" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "웹브라우저를 찾을 수 없습니다. $BROWSER 환경변수를 지정하거나 경로에 웹브" #~ "라우저의 실행파일이 걸려있는지 확인하십시오." #, fuzzy #~ msgid "Library Error" #~ msgstr "라이브러리 브라우저" #~ msgid "translator-credits" #~ msgstr "" #~ "ChangBom Yoon <changbom.yoon@gmail.com>\n" #~ "Byung-Hee HWANG <bh@izb.knu.ac.kr>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Other columns to display, separated by spaces" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "계속" #~ msgid "Search your library" #~ msgstr "라이브러리 검색" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "총 크기:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet 플러그인" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "파랑색은 간단한 검색, 초록색은 복잡한 검색, 빨강색은 유효하지 않은검색" #~ msgid "Separators for splitting tags" #~ msgstr "Separators for splitting tags" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet 설정" #~ msgid "Not Played To_day" #~ msgstr "Not Played To_day" #~ msgid "Not Played in a _Week" #~ msgstr "Not Played in a _Week" #~ msgid "Not Played in a _Month" #~ msgstr "Not Played in a _Month" #~ msgid "B_ottom 40" #~ msgstr "B_ottom 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "최소 40 곡이 재생되었습니다" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "날짜" #~ msgid "Add" #~ msgstr "추가" #, fuzzy #~ msgid "Bitrate" #~ msgstr "비트율" #~ msgid "_Stations..." #~ msgstr "방송국..." #~ msgid "Unable to save library" #~ msgstr "라이브러리를 저장할 수 없습니다" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "노래를 실행할 수 없습니다" #~ msgid "Sort by title" #~ msgstr "제목 순 정렬" #~ msgid "Sort by artist" #~ msgstr "아티스트 순 정렬" #~ msgid "Lyrics provided by %s." #~ msgstr "가사 제공: %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "발견된 가사 없음.\n" #~ "\n" #~ "Quod Libet 검색을 통해 찾은 온라인 가사를 내려받기 버튼을또는 직접 입력하" #~ "셔도 됩니다. 그리고 저장을 클릭하십시오." #~ msgid "part" #~ msgstr "파트(part)" #~ msgid "Opening audio device." #~ msgstr "오디오 장치 열기" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d 곡을 저장했습니다" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album ID" #~ msgid "Loaded song library." #~ msgstr "라이브러리 불러오기" #~ msgid "Unable to open audio device" #~ msgstr "오디오 장치를 열 수 없습니다" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet 이 'alsasink', 'osssink', '%(sink)s' 장치 접근을시도했지만 그것" #~ "들중 어느것도 열 수 없었습니다. ~/.quodlibet/config 파일에서GStreamer " #~ "pipeline 을 찾아 아래처럼 설정을 해주십시오:\n" #~ "\t<b>pipeline = %(sink)s</b>" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet 이 'filesrc' GStreamer 요소를 찾지 못 합니다. GStreamer 가 설치" #~ "되었는지 확인해보십시오." #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "앨범 표지 보이기" #~ msgid "Unable to retag multiple values" #~ msgstr "Unable to retag multiple values" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Changing the name of a tag with multiple values is not supported." ��������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/lt.po����������������������������������������������������������������������������0000644�0001750�0001750�00000671442�14436352625�013630� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Jonas <jonas.slivka@gmail.com>, 2006, Naglis Jonaitis <njonaitis@gmail.com>, 2011. msgid "" msgstr "" "Project-Id-Version: Quod Libet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2012-12-07 17:22+0300\n" "Last-Translator: Naglis Jonaitis <njonaitis@gmail.com>\n" "Language-Team: Lithuanian (http://www.transifex.net/projects/p/quodlibet/" "team/lt/)\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" "%100<10 || n%100>=20) ? 1 : 2)\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "Pa_vadinimas" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "atlikėjai" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Dat_os antraštės" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "originalus atlikėjas" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Žanras" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "Į_vertis" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Redaguoti rodomą informaciją" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Rikiuoti _pagal..." #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Nuostatos" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumų sąrašas" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumų sąrašas" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Visi albumai" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albumas" msgstr[1] "%d albumai" msgstr[2] "%d albumų" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Atnaujinti albumo _viršelį" msgstr[1] "Atnaujinti albumų _viršelius" msgstr[2] "Atnaujinti albumų _viršelius" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Dainos nėra albume" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d takelis" msgstr[1] "%d takeliai" msgstr[2] "%d takelių" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d diskas" msgstr[1] "%d diskai" msgstr[2] "%d diskų" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Visi albumai" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albumų sąrašo nuostatos" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Rodyti albumų _viršelius" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Į paiešką įtraukti atlikėju_s" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[pasirinktys]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albumo vaizdas" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Bibliotekos naršyklė" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d daina" msgstr[1] "%d dainos" msgstr[2] "%d dainų" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Netaisyklingas šablonas" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumų kolekcija" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Albumų _kolekcija" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Nežinoma (-s) %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Kelios lauko %s reikšmės" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Individualus" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Žymė" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Sulieti" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Albumų sąrašo nuostatos" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Visas dydis:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Visas dydis:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Langų naršyklės nuostatos" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Rodyti albumų _viršelius" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Visi albumai" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "organizacija" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Failų sistema" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Failų sistema" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Negalima kopijuoti dainų" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Failai, kuriuos pasirinkote, negali būti nukopijuoti į kitą dainų sąrašą ar " "eilę." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Pridėti į biblioteką" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Stočių sąrašuose gali būti tik stočių vietos, ne kiti stočių sąrašai ar " "grojaraščiai. Šios vietos negali būti įkeltos:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Interneto radijas" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Visos stotys" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Atsiunčiamas stočių sąrašas" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nauja stotis" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Įveskite Interneto radijo stočių adresą:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektroninė" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hiphopas / Repas" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Senesnė muzika" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonų" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indų" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religinė" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Topai" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turkų" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Regis / „Šokių salės“ regis" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Lotynų" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Koledžų radijo stotys" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Pokalbiai / Žinios" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambientinė" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Džiazas" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasikinė" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatyvioji" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metalas" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Kantri" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Žinios" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Šlageriai" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Fank" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Bliuzas" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Pank" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Regetonas" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavų" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Graikų" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotikinė" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rokas" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_Atnaujinti stotis" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Interneto radijas" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Visos stotys" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Mėgstamiausios" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Be kategorijos" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Nauja stotis" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Atnaujinti stotis" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nerasta stočių" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Jokių Interneto radijo stočių nerasta %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Visos šios stotys jau yra Jūsų bibliotekoje." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Pridėti prie Mėgstamiausių" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Pašalinti iš Mėgstamiausių" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stotis" msgstr[1] "%(count)d stotys" msgstr[2] "%(count)d stočių" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Langų naršyklė" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Langų naršyklė" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "P_asirinkti viską" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nežinoma" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Viskas" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Matomi stulpeliai" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Langų naršyklės nuostatos" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Grojaraščiai" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Grojaraščiai" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Pašalinti iš grojaraščio" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importuoti" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Negalima importuoti grojaraščio" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet gali importuoti tik M3U ir PLS formato grojaraščius." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Ištrinti failus" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Per_vadinti" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Negalima pervadinti grojaraščio" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importuoti grojaraštį" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importuoti" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_Naujas grojaraštis" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Ar tikrai norite pakeisti visų %d dainų įvertį?" msgstr[1] "Ar tikrai norite pakeisti visų %d dainų įvertį?" msgstr[2] "Ar tikrai norite pakeisti visų %d dainų įvertį?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Naujas grojaraštis" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Langų naršyklės nuostatos" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Grojaraščiai" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Ar tikrai norite ištrinti grojaraštį '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Visa pažymėto grojaraščio informacija bus ištrinta be atkūrimo galimybės." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Takelis" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Naujas grojaraštis" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Įveskite naujo grojaraščio pavadinimą:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importuojamas grojaraštis.\n" "\n" "%(current)d/%(total)d dainų pridėta." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Naujas kanalas" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Įveskite garso kanalo vietą:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Pridėti failą..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Atnaujinti biblioteką" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Stebėti šį aplanką dėl naujų dainų" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Negalima pridėti kanalo" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> negali būti pridėta. Serveris gali neveikti arba nurodyta vieta " "nėra garso kanalas." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Dabartinė garso posistemė nepalaiko URL adresų. Audio kanalų naršyklė " "išjungta." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Ap_riboti rezultatus" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Išskaidyti į keletą _reikšmių" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Takelių sąrašas" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Takelių sąrašas" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Langų naršyklė" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Langų naršyklė" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Ieškoti" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "takeliai" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "vieta" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> nėra prijungtas." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nėra paleistas." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "muzikos biblioteka ir grotuvas" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[pasirinktis]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Parašyti dabar grojamos dainos pavadinimą ir išeiti" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Iškart pradėti groti" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Peršokti į kitą dainą" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Peršokti į praėjusią dainą arba groti esamą dainą iš naujo, jei netoli " "pradžios" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Peršokti į praėjusią dainą" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Pradėti grojimą" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pristabdyti grojimą" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Sustabdyti grojimą" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Pagarsinti" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Pritildyti" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Parašyti apie grotuvo būseną" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Slėpti pagrindinį langą" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Rodyti pagrindinį langą" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Perjungti pagrindinio lango matomumą" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokusuoti grojantį grotuvą" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Naikinti aktyvius naršyklių filtrus" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Atnaujinti biblioteką" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Išjungti naršyklę" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Parašyti dabartinį grojaraštį" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Parašyti eilės turinį" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Parašyti eilės turinį" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Paleisti be įskiepių" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nėra paleistas." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Išjungti Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Peršokti grojamoje dainoje" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Išjungti/įjungti kartojimo veikseną" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Nustatyti garsumą" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Ieškoti jūsų garsų bibliotekoje" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "užklausa" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Groti failą" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "failo vardas" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Peršokti grojamoje dainoje" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Nustatyti dabartinę naršyklę" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Įvertinti grojamą dainą" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Atverti naują naršyklę" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Rodyti ar slepti eilę" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtruoti pagal atsitiktinę reikšmę" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "Žymė" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "žymė=reikšmė" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Pridėti į eilę failą ar užklausą" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Pridėti į eilę kableliu atskirtus failus" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "failo vardas" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Spausdinti užklausų rezultatų failų vardus į standartinę išvestį" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Pašalinti iš eilės failą ar užklausą" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "vieta" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Netaisyklingas šablonas" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Netaisyklingas „%s“ argumentas." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Pamėginkite „%s“ --help." #: quodlibet/errorreport/ui.py:58 #, fuzzy msgid "An Error Occurred" msgstr "Įvyko klaida" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Ignoruoti vis_as klaidas" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "aprašymas" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "audio žymių redaktorius" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "aplankas" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Garso žymių redaktorius" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "„MusicBrainz“ takelio ID" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "„MusicBrainz“ takelio ID" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Netaisyklinga koduotė]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Pa_vadinimas" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Garso žymių redaktorius" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Žymes pradėti iš _didžiosios raidės" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 #, fuzzy msgid "_Human title case" msgstr "Įjungti žmonėms tinkamą pavadinimų tvarkymą" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Naudoti bendrines anglų kalbos taisykles pavadinimams, pvz. \"Dark Night of " "the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Langų naršyklės nuostatos" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Visas dydis:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Redaguoti rodymą" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Svoris" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 #, fuzzy msgid "_Outline" msgstr "_Išvestis:" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Redaguoti rodomą informaciją" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "Perž_iūra" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informacija" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Palaikomi formatai: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtras _žanrui" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "aplankas" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Audio kanalai" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "%s: Nepavyko rasti %s." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Atnaujinti stotis" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Saugoti įverčius bei grojimo _kartų vertes" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "įrašymo data" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Klaida įkeliant %r" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Atnaujinti stotis" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Nuostatos" #: quodlibet/ext/events/automask.py:22 #, fuzzy msgid "Automatic Masking" msgstr "Auto_matinis" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 #, fuzzy msgid "Automatic Rating" msgstr "Auto_matinis" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Importuoti grojaraštį" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importuoti" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Importuoti" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Atšaukti žymių pakeitimus?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Atšaukti žymių pakeitimus?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Groti/Pristabdyti" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Kelio šablonai" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Kelio šablonai" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 #, fuzzy msgid "Reggae" msgstr "Regetonas" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 #, fuzzy msgid "Soft Rock" msgstr "Rokas" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "Dabartinė garso posistemė nepalaiko URL adresų. Audio kanalų naršyklė " "išjungta." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%.1f sekundė" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Numatytasis" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Pasirinkti" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "Perž_iūra" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Individualizuotas rikiavimas" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Negalima ištrinti dainų" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Netaisyklingas šablonas" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Muzikos grotuvas" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modelis:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Interneto radijas" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "Į_vertis" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Numatytasis" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "vieta" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Slėpti pagrindinį langą" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Numatytasis" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "Kelio šablonai" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "Kelio šablonai" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d daina" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Išvesties sąranka" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "Kelio šablonai" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "vieta" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "„MusicBrainz“ albumo tipas" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Vardas:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Pa_vadinimas" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Kita" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Žymės vardas" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Įrenginys:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Kita:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Atlikėjas" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "Failo _vardo šablonas:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Atsitiktinis a_lbumas" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "albumai" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Svoris" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Atsitiktinis a_lbumas" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 #, fuzzy msgid "Alternative Seek Bar" msgstr "Alternatyvioji" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Žymės" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Žymės vardas" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Žymės vardas" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[pasirinktys]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "Didėjančia tvarka" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "įrašymo data" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Ištrinti failus" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Dainos žodžiai" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Ištrinti failus" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Dainos žodžiai" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Nerasta stočių" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Kelio šablonai" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Redaguoti išsaugotus šablonus..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Atlikėjas" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Perž_iūra" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Muzikos grotuvas" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Importuoti grojaraštį" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organizacija" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Pasirinkite naujas stotis" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Dainos žodžiai" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Kelias neabsoliutus" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Šablone\n" "\t<b>%s</b>\n" "yra „/“, bet jis neprasideda šaknimi. Siekdami išvengti netaisyklingų " "aplankų, nurodykite kelyje šaknį jį pradėdami „/“ arba „~/“." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nepasirinkta jokių dainų." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nepasirinkta jokių dainų." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Negalima išsaugoti dainos" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Dainos žodžiai" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Negalima atverti įvesties failų" msgstr[1] "Negalima atverti įvesties failų" msgstr[2] "Negalima atverti įvesties failų" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Dainos žodžiai" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Negrojama" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d daina" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "Kelio šablonai" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Auto_matinis" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Negrojama" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "_Grojaraščiai" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Groti/Pristabdyti" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "Ankstesnė" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 #, fuzzy msgid "_Next" msgstr "Kita" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Išmaišytai" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Kartoti" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Po šios dainos sustabdyti" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Atverti naują naršyklę" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "_Redaguoti žymes" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Information" msgstr "Informacija" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Grojaraščiai" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Elgsena" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Redaguoti rodomą informaciją" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Dainos žodžiai" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Nerasta dainos žodžių šiai dainai." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Negalima išsaugoti dainos" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Klaidos" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternatyvioji" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Failų" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "Perž_iūra" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtras _atlikėjui" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 #, fuzzy msgid "Default" msgstr "Numatytasis" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Individualus" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "Individualizuotas rikiavimas" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filtras _žanrui" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filtras _atlikėjui" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio kanalai" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Įveskite garso kanalo vietą:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importuoti grojaraštį" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Importuoti" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Nerasta stočių" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "Failo _vardo šablonas:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Negalima importuoti grojaraščio" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "Failo _vardo šablonas:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Importuoti grojaraštį" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, fuzzy, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" msgstr[1] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" msgstr[2] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Naujas grojaraštis" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "paskutinį kartą grota" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "paskutinį kartą grota" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Eilėje" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Eilėje" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Eilėje" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Niekada" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Niekada" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "grupavimas" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Negalima kopijuoti dainų" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtras _žanrui" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Netaisyklingos žymės" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Išsaugotos paieškos reikšmės" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Išsaugotos paieškos reikšmės" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "Per_vadinti" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Biblioteka" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Derinimas" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Slėpti pagrindinį langą" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Failo vardas" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Negalima išsaugoti dainos" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Albumų viršeliai" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Dydis" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Paieška:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Ieškoti" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Albumų viršeliai" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "Redaguoti _žymes..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "Redaguoti _žymes..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Žymės" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "„MusicBrainz“ albumo tipas" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Failo vardas" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Diskas" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Takelis" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Pa_vadinimas" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Atlikėjas" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "„MusicBrainz“ albumo tipas" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "užklausa" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Ieškoti" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Nerasta priedų." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "vieta" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Albumų viršeliai" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Klasikinė" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Albumų viršeliai" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Nerasta priedų." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "Perž_iūra" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "žymė" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "Per_vadinti" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "žymė" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Niekada" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Netaisyklinga reikšmė" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "Individualizuotas rikiavimas" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Negalima kopijuoti dainų" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Išjungti naršyklę" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Redaguoti rodomą informaciją" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Kelios lauko %s reikšmės" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filtruoti pagal žymės reikšmę" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtras _žanrui" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Eilėje" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Įrašyti" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "„MusicBrainz“ takelio ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "aplankas" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Albumo režimas" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Atnaujinti stotis" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Nerasta priedų." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Perkeliama %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Klaida įkeliant %r" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Importuoti grojaraštį" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Importuoti grojaraštį" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Nėra laiko informacijos" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Albumų viršeliai" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importuoti grojaraštį" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importuoti" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtras _žanrui" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Diskas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Takelis" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Atlikėjas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albumai" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Tęsti" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "%s: Nepavyko rasti %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "%s: Nepavyko rasti %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Failo vardas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "takeliai" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Klaida įkeliant %r" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "Per_vadinti" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Importuoti grojaraštį" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Nepavyko atjungti <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Atnaujinti biblioteką" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Atnaujinti biblioteką" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Takelis" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Redaguoti žymes" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Redaguoti žymes" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Visi albumai" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "Perž_iūra" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Žymė" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Negalima ištrinti dainų" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Ieškoti" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "Kelio šablonai" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Redaguoti išsaugotas paieškos reikšmes..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Nus_palvinti paieškos žodžius" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Redaguoti žymes" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Paieškos bibliotekoje pagalba" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Biblioteka" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Tikrinami prijungimo taškai" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Peržvelgiama biblioteka" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Peržvelgiama %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Peržvelgiama biblioteka" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Naikinti aktyvius naršyklių filtrus" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "muzikos biblioteka ir grotuvas" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Rodyti su_generuotas programines žymes" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 #, fuzzy msgid "Too many arguments" msgstr "Per daug klaidų" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "aprašymas" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Reikšmė" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Garso žymių redaktorius" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Nepasirinkta jokių dainų." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 #, fuzzy msgid "Remove tags" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 #, fuzzy msgid "Remove all tags" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Nėra laiko informacijos" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Negalima pervadinti failo" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Failas" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Rodyti bendrą vartojimo informaciją" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nėra tinkama vieta." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "Nežinoma" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Iš eilės" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "Iš _eilės" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Atsitiktine tvarka" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Atsitiktine tvarka" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "paskutinį kartą grota" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Kartoti" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Kartoti" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Viena daina" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Viena daina" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Srautas" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Buferizuojama" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Nepavyko sukurti GStreamer išvesties." #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer išvestis naudojama grojimui, pvz. 'alsasink device=default'. " "Palikie tuščią, jei norite naudoti numatytąją išvestį." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Išvestis:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f sekundė" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buferizavimo trukmė:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nerasta stočių" #: quodlibet/player/gstbe/util.py:167 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Netaisyklinga GStreamer išvestis, bandoma naudoti numatytąją." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Negalima sukurti garso išvesties" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Garso įrenginys %r nerastas. Patikrinkite Xine nuostatas ~/.quodlibet/config " "faile." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nepavyko susieti GStreamer išvesties: '%s'" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Vardas:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Priedai" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Pradžia" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Laikas" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Žymės vardas" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Žymės" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtrai" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "_Neseniai grota" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Neseniai _pridėta" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _geriausių" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Visos stotys" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Atsitiktinis žanras" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Atsitiktinis _atlikėjas" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Atsitiktinis a_lbumas" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 dažniausiai grotų dainų (gali būti parinkta daugiau nei 40, jei kai " "kurios bus grotos tiek pat kartų)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Vardas:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Reikšmė:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Išsaugotos reikšmės" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Redaguoti išsaugotas reikšmes..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matinis" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Takelio režimas" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albumo režimas" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Garsumo derinimas (Replay Gain)" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Nežinoma" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Pridėti failą..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Redaguoti vaizdą..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filtruoti pagal žymės reikšmę" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Garso žymių redaktorius" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Failų" #: quodlibet/qltk/delete.py:63 #, fuzzy msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/delete.py:72 #, fuzzy msgid "The selected files will be deleted from disk." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Ištrinti failus" #: quodlibet/qltk/delete.py:106 #, fuzzy msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/delete.py:115 #, fuzzy msgid "The selected files will be moved to the trash." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Perkelti į šiukšlinę" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Perkeliama %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Nepavyko perkelti į šiukšlinę" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Nepavyko perkelti <b>%s</b> į šiukšlinę." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Ištrinama %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Negalima ištrinti failo" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Nepavyko ištrinti <b>%s</b>." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Naršyklės" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Atsiųsti failus" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "trūksta iš %d dainos" msgstr[1] "trūksta iš %d dainų" msgstr[2] "trūksta iš %d dainų" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "skirtinga tarp %d dainos" msgstr[1] "skirtinga tarp %d dainų" msgstr[2] "skirtinga tarp %d dainų" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Iš_skaidyti į keletą reikšmių" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Išskaidyti diską iš _albumo" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Išskaidyti _versiją iš pavadinimo" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Išskaidyti aranžuotoją iš a_tlikėjo" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Išskaidyti muzikantą iš atlikėjo" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Išskaidyti _Muzikantą iš Pavadinimo žymės" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Išskaidyti _Originalo atlikėją iš Pavadinimo žymės" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Pridėti žymę" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "Žy_mė:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Rodyti su_generuotas programines žymes" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Prieiti prie visų žymių, įskaitant kompiuterio sugeneruotas, pvz. " "MusicBrainz ar ReplayGain žymes" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Rodyti su_generuotas programines žymes" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Niekada" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Tęsti" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Redaguoti žymes" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Kopijuoti albumų _viršelius" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Negalima pridėti žymės" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Negalima pridėti dainų" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Negalima pridėti <b>%s</b>\n" "\n" "Failai, kuriuos pasirinkote, nepalaiko kelių reikšmių redagavimo." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Netaisyklinga žymė" msgstr[1] "Netaisyklinga žymė" msgstr[2] "Netaisyklinga žymė" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Netaisyklinga žymė <b>%s</b>\n" "\n" "Failai, kuriuos pasirinkote, nepalaiko šios žymės redagavimo." msgstr[1] "" "Netaisyklinga žymė <b>%s</b>\n" "\n" "Failai, kuriuos pasirinkote, nepalaiko šios žymės redagavimo." msgstr[2] "" "Netaisyklinga žymė <b>%s</b>\n" "\n" "Failai, kuriuos pasirinkote, nepalaiko šios žymės redagavimo." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Netaisyklinga reikšmė" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Netaisyklinga reikšmė: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Žymė gali būti netiksli" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> buvo pakeista, kol veikė programa. Išsaugojimas neatnaujinus " "bibliotekos gali panaikinti kitus dainos pakeitimus.\n" "\n" "Ar vistiek išsaugoti šią dainą?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Negalima išsaugoti dainos" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Nepavyko išsaugoti <b>%s</b>. Failas gali būti apsaugotas nuo rašymo, " "sugadintas arba neturite teisių jo redaguoti." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Daugiau pasirinkčių..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Priedai" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s bei dar %(count)d" msgstr[1] "%(title)s bei dar %(count)d" msgstr[2] "%(title)s bei dar %(count)d" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso nuostatos" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Aplankai" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Naujas aplankas" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Pasirinkti visus poaplankius" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Naujas aplankas" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Įveskite naujo aplanko vardą:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Negalima sukurti aplanko" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Negalima ištrinti aplanko" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Dainos" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "atliko %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Diskas %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Takelis %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Redaguoti rodomą informaciją" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nepasirinkta jokių dainų." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nėra dainų" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informacija" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Dainos žodžiai" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Prodiusavo %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "atlikėjas" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "atlikėjai" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "muzikantai" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Niekada" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d kartą" msgstr[1] "%(n)d kartus" msgstr[2] "%(n)d kartų" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "pridėta" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "paskutinį kartą grota" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "grota" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "praleista" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "įvertis" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "trukmė" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Informacija" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "Didėjančia tvarka" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitų dažnis" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "failo dydis" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "paskutinį kartą pakeista" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d pasirinkta" msgstr[1] "%d pasirinkta" msgstr[2] "%d pasirinkta" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Takelis neprieinamas" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d daina be jokio albumo" msgstr[1] "%d dainos be jokio albumo" msgstr[2] "%d dainų be jokio albumo" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Pasirinkta diskografija" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d daina be jokio atlikėjo" msgstr[1] "%d dainos be jokio atlikėjo" msgstr[2] "%d dainų be jokio atlikėjo" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumai" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Visa trukmė:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Visas dydis:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Failų" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nerasta dainos žodžių šiai dainai." #: quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "Ar tikrai norite pašalinti %d pasikartojančią dainą?" #: quodlibet/qltk/maskedbox.py:21 #, fuzzy msgid "The selected songs will be removed from the library." msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Atšaukti žymių pakeitimus?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Žymės buvo pakeistos, bet neišsaugotos. Išsaugoti šiuos failus, atkurti " "buvusias reikšmes ar atsisakyti pakeitimų?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Niekada" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Failas egzistuoja" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Pervadinti failus" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktyvios užduotys" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d užduotys vykdomos" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Perjungti grojimo/pauzės režimą" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Tvarka:" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Žymių redagavimas" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "Per_vadinti" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "užklausa" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Visas dydis:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Priedų klaidos" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Įjungta" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Išjungta" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Be kategorijos" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Be kategorijos" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nerasta priedų." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Priedai" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Rodyti klaidas" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Diskas" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Takelio nr." #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "grupavimas" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Atlikėjas" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bumas" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Failo _vardas" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "T_rukmė" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Automatiškai peršokti prie grojamos dainos" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Kai pasikeičia grojama daina, perškoti ties ja dainų sąraše" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Kita:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Redaguoti vaizdą..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Matomi stulpeliai" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Pavadinime yra dainos versija" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albumo pavadinime yra disko _dalis" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Į paiešką įtraukti atlikėju_s" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Failo varde yra _aplanko vardas" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Nuostatos" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Matomi stulpeliai" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dainų sąrašas" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Matomi stulpeliai" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Bendras filtras:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Taikyti šią užklausą kartu su kitomis" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Ieškoti" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Naršyklės" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Patvirtinti su_dėtinius įverčius" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Prašyti patvirtinimo prieš pakeičiant kelių dainų įvertį vienu metu" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Įjungti vien_o paspaudimo įverčius" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Įjungti įverčių keitimą spragtelėjus įverčio stulpelyje dainų sąraše" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Įverčiai" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Pageidautina naudoti į_terptinius albumų viršelius" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Pasirinkite, jei norite, kad pirmenybė būtų teikiama į audio failus " "įterptiems albumų viršeliams (kai prieinama)" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Priverstinai naudotino paveikslėlio failo vardas:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumų viršeliai" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Grojimas" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Išvesties sąranka" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Jei Replay Gain garso derinimo informacija dainai neprieinama, pakoreguoti " "garsumo lygį šia reikšme" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Numatytasis derinimas (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Pakoreguoti garsumo lygį visoms dainoms šia reikšme, kol neatsiras iškraipymų" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Pirminis derinimas (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Įjungti Replay Gain garso d_erinimą" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Garsumo derinimas (Replay Gain)" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 #, fuzzy msgid "_Default rating:" msgstr "Numatytasis" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Įverčiai" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_El. paštas:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Įverčiai bei grojimo kartų vertės bus susietos su šiuo el. pašto adresu" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Automatiškai išsaugoti žymių pakeitimus" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Redaguojant keletą failų išsaugoti žymių pakeitimus be patvirtinimo" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Skyriklių, naudojamų žymių reikšmių išskaidymui, sąrašas. Skyrikliai " "atskirti tarpais" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "At_skirti ties:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Skyriklių, naudojamų žymių reikšmių išskaidymui, sąrašas. Skyrikliai " "atskirti tarpais" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "At_skirti ties:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Žymės" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Žymių redagavimas" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Atnaujinti stotis" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "Pa_ieška bibliotekoje" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Ieškoti pasikeitimų bibliotekoje" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Iš naujo įkelti _biblioteką" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Iš naujo įkelti dainas į biblioteką (tai gali užtrukti)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Nėra dainų" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "At_naujinti biblioteką paleidus programą" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Peržvelgiami aplankai" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s bei dar %(count)d" msgstr[1] "%(title)s bei dar %(count)d" msgstr[2] "%(title)s bei dar %(count)d" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Savybės" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Eilė" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "Valyti _klaidas" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Bendrasis" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Iš eilės pašalinti visas dainas" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modelis:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d daina (%(time)s)" msgstr[1] "%(count)d dainos (%(time)s)" msgstr[2] "%(count)d dainų (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Naršyti bibliotekoje" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Perjungti pagrindinio lango matomumą" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Grojimas" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Pasirinkti aplankus" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Negalima pridėti dainų" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> naudoja nepalaikomą protokolą." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Peršokti ties grojama daina" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Failas" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Dainos" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Rodymas" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Naršyklės" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Valdymas" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Pagalba" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Pridėti aplanką..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Pridėti failą..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Pridėti vietą" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "Redaguoti _žymes..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Po šios dainos sustabdyti" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Pagalba Internete" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Paieškos bibliotekoje pagalba" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Pridėti vietą" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Įveskite garso failo vietą:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Negalima pridėti vietos" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nėra tinkama vieta." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Pridėti muziką" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Pridėti aplanką..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Muzikos grotuvas" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Pridėti failą..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" msgstr[1] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" msgstr[2] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Eilė" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Ar tikrai norite pakeisti visų %d dainų įvertį?" #: quodlibet/qltk/ratingsmenu.py:29 #, fuzzy msgid "The saved ratings will be removed" msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Pažymėtų dainų įvertis bus pakeistas į '%s'" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "Į_vertis" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Pakeisti tarpus „_“ simboliu" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Pašalinti su _Windows nesuderinamus simbolius" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Pašalinti _diakritinius ženklus" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Pašalinti ne _ASCII simbolius" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Naudoti tik _mažąsias raides" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Pervadinti failus" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "Perž_iūra" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Failo vardas" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "albumo atlikėjas" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "Šalinti nenaudojamus vi_ršelius bei aplankus" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Albumų viršeliai" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Naujas vardas" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Negalima pervadinti failo" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Pervadinimas iš <b>%s</b> į <b>%s</b> nepavyko. Greičiausiai paskirties " "failas jau egzistuoja arba neturite teisių sukurti naują ar pašalinti seną." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignoruoti vis_as klaidas" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Tęsti" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Kelias neabsoliutus" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Šablone\n" "\t<b>%s</b>\n" "yra „/“, bet jis neprasideda šaknimi. Siekdami išvengti netaisyklingų " "aplankų, nurodykite kelyje šaknį jį pradėdami „/“ arba „~/“." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Dainos, esančios šiuose aplankuose, bus pridėtos į Jūsų biblioteką jos " "atnaujinimo metu" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Šalinamas vienišas takelis iPod grotuve" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Biblioteka" msgstr[1] "Biblioteka" msgstr[2] "Biblioteka" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "Pašalinti pasikartojančias dainas" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Pasirinkti aplankus" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Pasirinkti aplankus" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Išsaugotos paieškos reikšmės" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Redaguoti išsaugotas paieškos reikšmes..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Ieško_ti bevedant užklausą" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Rodyti paieškos rezultatus vartotojui baigus įvesti užklausą" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Riba:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Svoris" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "užklausa" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Rodyti, kiek liko laiko" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Dainos žodžiai" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Fokusuoti grojantį grotuvą" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Peršokti grojamoje dainoje" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Negalima ištrinti dainų" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Negalima ištrinti dainų" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtras laukui „%s“" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "_Visos antraštės" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Takelio antraštės" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumo antraštės" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "A_tlikėjų antraštės" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Dat_os antraštės" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Failo antraštės" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Produkcijos antraštės" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Individualizuoti antraštes..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Pašalinti iš bibliotekos" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Pašalinti iš bibliotekos" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Pašalinti iš bibliotekos" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Nus_palvinti paieškos žodžius" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Pridėti į _eilę" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Pašalinti iš bibliotekos" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Negalima ištrinti failo" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Atsisiųsti" msgstr[1] "_Atsisiųsti" msgstr[2] "_Atsisiųsti" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Paieškos bibliotekoje pagalba" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Atsiųsti failą" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Albumų viršeliai" msgstr[1] "Albumų viršeliai" msgstr[2] "Albumų viršeliai" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Atsiųsti failą" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Pakeisti simbolius „_“ tarpo simboliais" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Žymes pradėti iš _didžiosios raidės" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Išskaidyti į keletą _reikšmių" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Žymės pagal kelią" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Žymės pakeičia jau esamas" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Žymės pridedamos prie esamų" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Šablonas\n" "\t<b>%s</b>\n" "yra netaisyklingas. Greičiausiai jame yra kelios tos pačios žymės ar " "netvarkingi skliausteliai (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Šablonas, kurį įvedėte, netaisyklingas. Įsitikinkite, kad įvedėte < ir " "> kaip \\< ir \\> ir kad Jūsų žymės suderintos.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Redaguoti rodomą informaciją" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Takelių numeriai" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Pradėti _nuo:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Iš _viso takelių:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Groti/Pristabdyti" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Ankstesnė" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "ir %d daugiau..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Išsaugomos dainos, kurias pakeitėte." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d dainų išsaugota\n" "(%(remaining)s liko)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Perkeliama %(current)d/%(total)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Tikrinami prijungimo taškai" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "vieta" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importuoti grojaraštį" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Grojaraštis vardu %s jau egzistuoja." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Atnaujinti albumo _viršelį" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Failų sistema" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Visas dydis:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Rodyti bendrą vartojimo informaciją" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Rodyti versijos numerį ir autorių teises" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Nėra laiko informacijos" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[pasirinktys]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Pasirinkimas „%r“ neatpažintas." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Pasirinkimas „%r“ reikalauja argumento." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "„%r“ nėra unikalus priešdėlis." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d sekundė" msgstr[1] "%d sekundės" msgstr[2] "%d sekundžių" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Nėra laiko informacijos" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekundė" msgstr[1] "%d sekundės" msgstr[2] "%d sekundžių" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minutė" msgstr[1] "%d minutės" msgstr[2] "%d minučių" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d valanda" msgstr[1] "%d valandos" msgstr[2] "%d valandų" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d diena" msgstr[1] "%d dienos" msgstr[2] "%d dienų" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d metai" msgstr[1] "%d metai" msgstr[2] "%d metų" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "nereikia" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Data turi būti įvesta tokiais formatais: „YYYY“, „YYYY-MM-DD“ arba „YYYY-MM-" "DD HH:MM:SS“." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "ReplayGain garso pokyčiai turi būti įvesti „x.yy dB“ formatu." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "ReplayGain garso maksimumai turi būti įvesti „x.yy“ formatu." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID turi būti UUID formato." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz leidimo statusas privalo būti 'official', 'promotional' arba " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Kalba privalo būti ISO 639-2 trijų raidžių kodas" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Nepavyko atjungti <b>%s</b>." msgstr[1] "Nepavyko atjungti <b>%s</b>." msgstr[2] "Nepavyko atjungti <b>%s</b>." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Negalima redaguoti dainos" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Nepavyko išsaugoti <b>%s</b>. Failas gali būti apsaugotas nuo rašymo, " "sugadintas arba neturite teisių jo redaguoti." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Netaisyklinga koduotė]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "albumas" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranžuotojas" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranžuotojai" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "aranžuotojas" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autorius" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autoriai" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "žymė" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "kompozitorius" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "kompozitoriai" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "kompozitorius" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigentas" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigentai" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "dirigentas" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontaktai" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "autorių teisės" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "aprašymas" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "žanras" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "žanras" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "muzikantas" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "muzikantas" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupavimas" #: quodlibet/util/tags.py:98 msgid "language" msgstr "kalba" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licencija" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "dainos ž. autorius" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "dainos ž. autoriai" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "dainos ž. autorius" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizacija" #: quodlibet/util/tags.py:104 msgid "title" msgstr "pavadinimas" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versija" #: quodlibet/util/tags.py:106 msgid "website" msgstr "tinklalapis" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albumo atlikėjas" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "disko dalis" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "diskas" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "takelio nr." #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "leidinio ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "originalo išleidimo data" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "originalus albumas" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "originalus atlikėjas" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "įrašymo data" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "išleidimo šalis" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "„MusicBrainz“ takelio ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "„MusicBrainz“ leidimo ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "„MusicBrainz“ leidimo ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "„MusicBrainz“ atlikėjo ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "„MusicBrainz“ leidimo ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "„MusicBrainz“ TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "„MusicIP“ PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "„MusicBrainz“ albumo statusas" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "„MusicBrainz“ albumo tipas" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "„MusicBrainz“ leidimo ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "takelio garso lygis" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "takelio maks. garsumo lygis" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albumo garso lygis" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albumo maks. garsumo lygis" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "garsumo etalonas" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diskai" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "takeliai" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "paskutinį kartą grota" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "pilnas vardas" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "prijungimo taškas" #: quodlibet/util/tags.py:166 msgid "people" msgstr "atlikėjai" #: quodlibet/util/tags.py:168 msgid "year" msgstr "metai" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "originalo išleidimo metai" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "žymė" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "failo formatas" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Grojaraščiai" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Garso žymių redaktorius" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Redaguoti Jūsų garso failų žymes" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Muzikos grotuvas" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Klausykite, naršykite ar redaguokite savo muzikos kolekciją" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Importuoti grojaraštį" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Negalima pridėti dainos" #~ msgid "Invalid tags" #~ msgstr "Netaisyklingos žymės" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Netaisyklingos žymės <b>%s</b>\n" #~ "\n" #~ "Failai, kuriuos pasirinkote, nepalaiko šių žymų redagavimo." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekundė" #, fuzzy #~ msgid "Startup" #~ msgstr "_Importuoti" #~ msgid "Audio Feeds" #~ msgstr "Audio kanalai" #~ msgid "_Audio Feeds" #~ msgstr "_Audio kanalai" #, fuzzy #~ msgid "New" #~ msgstr "Žinios" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Ieškoma dainos žodžių..." #, fuzzy #~ msgid "<artist>" #~ msgstr "atlikėjas" #, fuzzy #~ msgid "<album>" #~ msgstr "albumas" #, fuzzy #~ msgid "<title>" #~ msgstr "pavadinimas" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importuoti grojaraštį" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importuoti grojaraštį" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informacija" #~ msgid "Unsupported file type" #~ msgstr "Nepalaikomas failo tipas" #~ msgid "Unable to add station" #~ msgstr "Negalima pridėti stoties" #~ msgid "Device Properties" #~ msgstr "Įrenginio savybės" #~ msgid "Device:" #~ msgstr "Įrenginys:" #~ msgid "Not mounted" #~ msgstr "Neprijungtas" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Prijungimo taškas:" #~ msgid "Media Devices" #~ msgstr "Medijos įrenginiai" #~ msgid "_Media Devices" #~ msgstr "_Medijos įrenginiai" #~ msgid "_Eject" #~ msgstr "At_jungti" #, fuzzy #~ msgid "_Properties" #~ msgstr "Savybės" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> naudojama, <b>%s</b> prieinama" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Kopijuojama <b>%(song)s</b>" #~ msgid "Unable to copy song" #~ msgstr "Negalima kopijuoti dainos" #~ msgid "There is not enough free space for this song." #~ msgstr "Šiai dainai nepakanka laisvos vietos." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> nepavyko nukopijuoti." #~ msgid "Unable to delete songs" #~ msgstr "Negalima ištrinti dainų" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Nepavyko ištrinti <b>%(song)s</b>." #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "Nepavyko ištrinti „<b>%s</b>“." #~ msgid "Unable to delete song" #~ msgstr "Negalima ištrinti dainos" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Nepavyko atjungti <b>%s</b>." #~ msgid "Unable to eject device" #~ msgstr "Negalima atjungti įrenginio" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Nerasta jokių įrenginių posistemių, įvairialypės terpės naršyklė išjungta." #~ msgid "Search Library" #~ msgstr "Paieška bibliotekoje" #~ msgid "_Search Library" #~ msgstr "Pa_ieška bibliotekoje" #~ msgid "Rate the playing song" #~ msgstr "Įvertinti grojamą dainą" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Rodyti ar slėpti pagrindinį dainų sąrašą" #~ msgid "Unknown Device" #~ msgstr "Nežinomas įrenginys" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Nepavyko įkelti %s, kuri yra būtina įrenginio palaikymui." #~ msgid "%r is not a supported device." #~ msgstr "„%r“ nėra palaikomas įrenginys." #~ msgid "Initializing device backend." #~ msgstr "Inicijuojama garso posistemė." #~ msgid "Trying '%s'" #~ msgstr "Bandoma '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Nepavyko prisijungti prie įrenginio posistemės." #~ msgid "Device backend initialized." #~ msgstr "Įrenginio posistemė inicijuota." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "Failo _vardo šablonas:" #, fuzzy #~ msgid "_Clear" #~ msgstr "Valyti _klaidas" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Dainos žodžiai" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Išvalyti paiešką" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Dainos žodžiai" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Dainos žodžiai" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Nėra dainų" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Naršyklės" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Negalima sukurti aplanko" #~ msgid "Audio device: %s" #~ msgstr "Garso įrenginys: %s" #~ msgid "Downloads" #~ msgstr "Atsiuntimai" #~ msgid "Size" #~ msgstr "Dydis" #~ msgid "_Download" #~ msgstr "_Atsisiųsti" #, fuzzy #~ msgid "The single image filename to use if selected" #~ msgstr "" #~ "Naudotino albumo viršelio paveikslėlio failo vardas (esant keliems " #~ "galimiems variantams)" #~ msgid "The album art image file to use when forced" #~ msgstr "" #~ "Naudotino albumo viršelio paveikslėlio failo vardas (esant keliems " #~ "galimiems variantams)" #~ msgid "_Copy to Device" #~ msgstr "_Kopijuoti į įrenginį" #, fuzzy #~ msgid "browsers" #~ msgstr "Naršyklės" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Nepavyko įkelti %s. Audio kanalų naršyklė išjungta." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Quod Libet programoje aptikta nenumatyta išimtis. Išimties informacija " #~ "išsaugota faile <b>%s</b>, kuri padės mums derinti programą. Prašome " #~ "užpildyti pranešimą apie klaidą tinklalapyje http://code.google.com/p/" #~ "quodlibet/issues/list ir prisegti šį failą arba tekste įterptį jo turinį. " #~ "Šiame faile gali būti šiek tiek informacijos apie Jus ar Jūsų kompiuterį, " #~ "pvz. neseniai klausytų dainų sąrašas. Jei Jums tai nepriimtina, vietoje " #~ "to atsiųskite failą <b>%s</b> su veiksmų, kuriuos atlikote prieš " #~ "įvykstant klaidai, aprašymu.\n" #~ "\n" #~ "Quod Libet dabar gali būti nestabilus. Patartina išeiti iš programos ir " #~ "paleisti ją iš naujo. Jūsų biblioteka bus išsaugota." #~ msgid "Unable to download lyrics." #~ msgstr "Negalima atsiųsti dainos žodžių." #~ msgid "Set or toggle the playback order" #~ msgstr "Įjungti ar perjungti grojimo tvarką" #~ msgid "Uninitialized iPod" #~ msgstr "Neinicijuotas iPod grotuvas" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Ar norite sukurti tuščią duomenų bazę šiame iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Ga_rsumo derinimas (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Sujungti žymes su keletu _reikšmių" #~ msgid "Capacity:" #~ msgstr "Talpa:" #~ msgid "Firmware:" #~ msgstr "Programinė įranga:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Negalima išsaugoti iPod duomenų bazės" #~ msgid "Unable to save iPod database" #~ msgstr "Negalima išsaugoti iPod duomenų bazės" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Nepavyko įkelti python-gpod, iPod palaikymas išjungtas." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "takelio maks. garsumo lygis" #~ msgid "Shuffle" #~ msgstr "Išmaišytai" #~ msgid "Weighted" #~ msgstr "Svertinai" #~ msgid "_Weighted" #~ msgstr "_Svertinai" #~ msgid "_One Song" #~ msgstr "_Viena daina" #~ msgid "Restart the playlist when finished" #~ msgstr "Iš naujo pradėti grojaraštį jam pasibaigus" #~ msgid "Disable Browser" #~ msgstr "Išjungti naršyklę" #~ msgid "_Disable Browser" #~ msgstr "_Išjungti naršyklę" #, fuzzy #~ msgid "Force Write" #~ msgstr "Įrašyti" #~ msgid "Filter on _Genre" #~ msgstr "Filtras _žanrui" #~ msgid "Filter on _Artist" #~ msgstr "Filtras _atlikėjui" #~ msgid "Filter on Al_bum" #~ msgstr "FIltras a_lbumui" #~ msgid "_Music" #~ msgstr "_Muzika" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Žymės" #~ msgid "Song _List" #~ msgstr "Dainų _sąrašas" #, fuzzy #~ msgid "D:" #~ msgstr "Der:" #, fuzzy #~ msgid "W:" #~ msgstr "Įsp:" #, fuzzy #~ msgid "E:" #~ msgstr "Kl:" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Po šios dainos sustabdyti" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "ir %d daugiau..." #~ msgstr[1] "ir %d daugiau..." #~ msgstr[2] "ir %d daugiau..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Išskaidyti diską iš _albumo" #, fuzzy #~ msgid "Timeout" #~ msgstr "Laikas" #, fuzzy #~ msgid "Select an album" #~ msgstr "P_asirinkti viską" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s bei dar %(count)d" #~ msgstr[1] "%(title)s bei dar %(count)d" #~ msgstr[2] "%(title)s bei dar %(count)d" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Grojaraščiai" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "Apvalinti miniatiūrų kamp_us" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Apvalinti albumų viršelių miniatiūrų paveikslėlių kampus. Gali tekti " #~ "paleisti programą iš naujo, kad pakeitimai įsigaliotų." #~ msgid "Re_fresh Library" #~ msgstr "At_naujinti biblioteką" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Pašalinti pasikartojančias dainas" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer neturi elemento, skirto failų skaitymui. Patikrinkite GStreamer " #~ "įdiegties nuostatas." #~ msgid "Invalid audio backend" #~ msgstr "Netaisyklinga garso posistemė" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "Garso posistemė „%r“ neįdiegta." #~ msgid "ql-save" #~ msgstr "ql-save" #~ msgid "ql-revert" #~ msgstr "ql-revert" #~ msgid "command|filename" #~ msgstr "failo_vardas" #~ msgid "command|tag" #~ msgstr "žymė" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Nepavyko rasti %s." #~ msgid "heading|Search" #~ msgstr "heading|Paieška" #~ msgid "%d of %d" #~ msgstr "%d iš %d" #~ msgid "Usage: %s %s\n" #~ msgstr "Naudojimas: %s %s\n" #~ msgid "_Download..." #~ msgstr "_Atsiųsti..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nauja stotis" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Perrašyti <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Išvesties klaida" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "GStreamer išvesties inicijuoti nepavyko. Gali būti, jog išvestis " #~ "netaisyklinga arba įrenginys šiuo metu naudojamas. Patikrinkite grotuvo " #~ "nuostatas." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet jau paleistas." #~ msgid "No song is currently playing." #~ msgstr "Negroja jokia daina." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Negalima rašyti į %s. Pašalinama." #~ msgid "_Edit Bookmarks..." #~ msgstr "Redaguoti _žymes..." #~ msgid "_New Folder..." #~ msgstr "_Naujas aplankas..." #~ msgid "_Add to Playlist" #~ msgstr "_Pridėti į grojaraštį" #~ msgid "_Edit Display..." #~ msgstr "_Redaguoti vaizdą..." #~ msgid "Output Log" #~ msgstr "Išvesties žurnalas" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stotis" #~ msgid "_Add a Location..." #~ msgstr "_Pridėti vietą..." #~ msgid "_Output Log" #~ msgstr "Išvesties _žurnalas" #~ msgid "Invalid command %r received." #~ msgstr "Gauta netaisyklinga komanda %r." #~ msgid "Unknown browser %r." #~ msgstr "Nežinoma naršyklė %r." #~ msgid "Custom _Sort..." #~ msgstr "Individualizuotas _rikiavimas..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "Ar tikrai norite pakeisti visų %d dainų įvertį?" #~ msgstr[1] "Ar tikrai norite pakeisti visų %d dainų įvertį?" #~ msgstr[2] "Ar tikrai norite pakeisti visų %d dainų įvertį?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "Ar tikrai norite pašalinti %d pasikartojančią dainą?" #~ msgstr[1] "Ar tikrai norite pašalinti %d pasikartojančias dainas?" #~ msgstr[2] "Ar tikrai norite pašalinti %d pasikartojančių dainų?" #~ msgid "Track Headers" #~ msgstr "_Takelio antraštės" #~ msgid "People Headers" #~ msgstr "Atlikėjų antraštės" #~ msgid "Album Headers" #~ msgstr "Albumo antraštės" #~ msgid "Date Headers" #~ msgstr "Datos antraštės" #~ msgid "File Headers" #~ msgstr "Failo antraštės" #~ msgid "Production Headers" #~ msgstr "Produkcijos antraštės" #~ msgid "Tag:" #~ msgstr "Žymė:" #~ msgid "Descending" #~ msgstr "Mažėjančia tvarka" #~ msgid "Too Many Errors" #~ msgstr "Per daug klaidų" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Stabdomas grojimas, nes įvyko %d klaidos iš eilės." #~ msgid "Warnings" #~ msgstr "Įspėjimai" #~ msgid "No log available." #~ msgstr "Nėra prieinamo vedamo žurnalo." #~ msgid "album artist (sort)" #~ msgstr "albumo atlikėjas (rikiuojamas)" #~ msgid "artist (sort)" #~ msgstr "atlikėjas (rikiuojamas)" #~ msgid "album (sort)" #~ msgstr "albumas (rikiuojamas)" #~ msgid "performer (sort)" #~ msgstr "muzikantas (rikiuojamas)" #~ msgid "performers (sort)" #~ msgstr "muzikantai (rikiuojamas)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "„MusicBrainz“ albumo atlikėjo ID" #~ msgid "errors" #~ msgstr "klaidos" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Nepavyko perskaityti albumo viršelio \"%s\"" #~ msgid "Permanently delete this file?" #~ msgstr "Ar negrįžtamai ištrinti šį failą?" #~ msgid "Permanently delete these files?" #~ msgstr "Ar negrįžtamai ištrinti šiuos failus?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s ir %(count)d daugiau..." #~ msgstr[1] "%(title)s ir %(count)d daugiau..." #~ msgstr[2] "%(title)s ir %(count)d daugiau..." #~ msgid "Version:" #~ msgstr "Versija:" #~ msgid "_Cause an Error" #~ msgstr "Suke_lta klaida" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s negali būti pridėta į Jūsų biblioteką.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Klaida vykdant komandą %r, sukėlėjas: %r." #~ msgid "No eject command found." #~ msgstr "Nerasta atjungimo komanda." #~ msgid "Unable to start web browser" #~ msgstr "Negalima įkelti Interneto naršyklės" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Nerasta Interneto naršyklė. Nustatykite $BROWSER kintamąjį arba " #~ "įsitikinkite, ar /usr/bin/sensible-browser egzistuoja." #~ msgid "" #~ "Cannot save library contents to %s (it's a directory). Please remove it " #~ "and try again." #~ msgstr "" #~ "Negalima išsaugoti bibliotekos turinio į '%s' (tai aplankas). Pašalinkite " #~ "jį ir bandykite dar kartą." #~ msgid "Library Error" #~ msgstr "Bibliotekos klaida" #~ msgid "_Output device:" #~ msgstr "Išvesties įren_ginys:" #~ msgid "translator-credits" #~ msgstr "" #~ "Jonas Slivka <jonas.slivka@gmail.com>,\n" #~ "Naglis Jonaitis <njonaitis@gmail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Rodyti kitus stulpelius, atskirtus tarpais" #~ msgid "_Edit and Continue" #~ msgstr "R_edaguoti ir tęsti" #~ msgid "Search your library" #~ msgstr "Ieškoti bibliotekoje" #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Autorinės teisės {dates}\t{authors}\n" #~ "\n" #~ "Tai nemokama programinė įranga, kopijavimo sąlygų ieškokite išeities " #~ "tekstuose. Nesuteikiama JOKIŲ \n" #~ "garantijų.\n" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Ketinate pakeisti %d dainų reitingą.\n" #~ "Ar norite tęsti?" #~ msgstr[1] "" #~ "Ketinate pakeisti %d dainų reitingą.\n" #~ "Ar norite tęsti?" #~ msgstr[2] "" #~ "Ketinate pakeisti %d dainų reitingą.\n" #~ "Ar norite tęsti?" #~ msgid "Confirm rating" #~ msgstr "Patvirtinti reitingą" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r nėra naršyklių." #~ msgid "Total size unknown" #~ msgstr "Visas dydis nežinomas" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r nėra jokių įrenginių." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: Nepavyko įkelti ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Nepavyko rasti media-player-info." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: Nepavyko rasti libudev." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet priedai" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Rodyti paprastą paiešką mėlynai, sudėtingesnę žaliai ir netaisyklingą - " #~ "raudonai" #~ msgid "Separators for splitting tags" #~ msgstr "Atskyrikliai žymėms atskirti" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet pasirinktys" #~ msgid "Not Played To_day" #~ msgstr "Šiandien ne_grota" #~ msgid "Not Played in a _Week" #~ msgstr "_Savaitę negrota" #~ msgid "Not Played in a _Month" #~ msgstr "_Mėnesį negrota" #~ msgid "B_ottom 40" #~ msgstr "40 _blogiausių" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "40 rečiausiai grotų dainų (gali būti parinkta daugiau nei 40, jei kai " #~ "kurių bus grota tiek pat kartų)" #~ msgid "gtk-media-next" #~ msgstr "Kita" #~ msgid "gtk-media-previous" #~ msgstr "Ankstesnė" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #~ msgid "Date" #~ msgstr "Data" #~ msgid "Add" #~ msgstr "Pridėti" #~ msgid "Bitrate" #~ msgstr "Bitų dažnis" #~ msgid "_Stations..." #~ msgstr "_Stotys..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Inicijuojama garso posistemė (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Inicijuojama pagrindinė biblioteka (%s)" #~ msgid "Unable to save library" #~ msgstr "Negalima išsaugoti bibliotekos" #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Negalima išvesti klaidos žurnalo, Jums labai nepasisekė." ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/lv.po����������������������������������������������������������������������������0000644�0001750�0001750�00000663013�14436352625�013625� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Einars Sprugis <einars8@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2010-03-30 10:12+0300\n" "Last-Translator: Einars Sprugis <einars8@gmail.com>\n" "Language-Team: Latvian <locale@laka.lv>\n" "Language: lv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " "2);\n" "X-Generator: Lokalize 1.0\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Nosaukums" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "cilvēki" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datums" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Datumu galvenes" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "oriģinālais mākslinieks" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "Žanrs" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Vērtējums" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Rediģēt rādāmo" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "_Kārtot pēc:" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Iestatījumi" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumu saraksts" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumu saraksts" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Visi albumi" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albums" msgstr[1] "%d albumi" msgstr[2] "%d albumu" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Rādīt albumu _vākus" msgstr[1] "Rādīt albumu _vākus" msgstr[2] "Rādīt albumu _vākus" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Dziesmas nav albumā" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d celiņš" msgstr[1] "%d celiņi" msgstr[2] "%d celiņu" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disks" msgstr[1] "%d diski" msgstr[2] "%d disku" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Visi albumi" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albumu saraksta iestatījumi" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Rādīt albumu _vākus" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Iegultajā _meklēšanā tiek iekļauti cilvēki" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[opcijas]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albuma attēlojums" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Bibliotēkas pārlūks" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d dziesma" msgstr[1] "%d dziesmas" msgstr[2] "%d dziesmu" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Nederīgs paraugs" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Nezināms" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Sadalīt _vairākās vērtībās" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Pielāgots" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "_Vērtējums" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tags" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Albumu saraksta iestatījumi" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Kopējais izmērs:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Kopējais izmērs:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Rādīt albumu _vākus" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Visi albumi" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "organizācija" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Failu sistēma" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Failu sistēma" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Neizdevās pārkopēt dziesmas" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Izvēlētie faili nevar tikt pārkopēti uz citiem dziesmu sarakstiem vai rindu." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "Pievienot bibliotēk_ai" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Staciju saraksti var saturēt tikai staciju adreses, nevis citus staciju " "sarakstus vai repertuārus. Neizdevās ielādēt šādas stacijas:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Interneta radio" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Jauna stacija" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Lejupielādēt failus" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Jauna stacija" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Ievadiet interneta radiostacijas adresi:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "vērtējums" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "Jau_na stacija" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Interneta radio" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Jauna stacija" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 #, fuzzy msgid "No Category" msgstr "Bez kategorijas" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Jauna stacija" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "Jau_na stacija" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nav atrasta neviena stacija" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Netika atrasta neviena interneta radiostacija ar adresi %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Visas sarakstā esošas stacijas jau ir jūsu bibliotēkā." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "Pievienot repertuār_am" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "Izņemt no _repertuāra" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stacija" msgstr[1] "%(count)d stacijas" msgstr[2] "%(count)d staciju" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Sadalītais pārlūks" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Sadalītais _pārlūks" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Iezīmēt visus" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nezināms" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Visi" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Redzamās kolonnas" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Repertuāri" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Re_pertuāri" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Izņemt no _repertuāra" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importēt" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Neizdevās importēt repertuāru" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet var importēt repertuārus tikai M3U un PLS formātā." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Dzēst failus" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "Pā_rdēvēt" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Neizdevās pārdēvēt repertuāru" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importēt repertuāru" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importēt" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "Jau_ns repertuārs" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[1] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[2] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Jauns repertuārs" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Repertuāri" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Celiņš" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Jauns repertuārs" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Ievadiet jaunās mapes nosaukumu:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importē repertuāru.\n" "\n" "%(current)d/%(total)d dziesmas pievienotas." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Jauna barotne" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Ievadiet audio barotnes adresi:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Pievienot _failu..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "_Atsvaidzināt bibliotēku" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Vērot šo mapi" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Neizdevās pievienot barotni" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> neizdevās pievienot. Iespējams, nedarbojas serveris, vai arī " "ievadītā adrese nav audio barotne." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Pašreizējā audio aizmugure neatbalsta URL, audio barotņu pārlūks tiks " "atslēgts." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limitēt rezultātus" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Sadalīt _vairākās vērtībās" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Celiņu saraksts" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Celiņu saraksts" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sadalītais pārlūks" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Sadalītais pārlūks" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Meklēt" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "celiņi" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "vieta" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> nav pievienots." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nav palaists." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "mūzikas bibliotēka un atskaņotājs" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[opcijas]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Izdrukā pašreiz atskaņoto dziesmu un iziet" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Nekavējoties uzsāk atskaņošanu" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Pāriet uz nākamo dziesmu" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Pāriet uz iepriekšējo dziesmu" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Sākt atskaņošanu" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pauzēt atskaņošanu" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Sākt atskaņošanu" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Palielināt skaļumu" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Samazināt skaļumu" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Izdrukāt atskaņotāja statusu" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Slēpt galveno logu" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Rādīt galveno logu" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Pārslēgt galvenā loga redzamību" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokusēties uz darbojošos atskaņotāju" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Noņemt aktīvos pārlūka filtrus" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Atsvaidzināt un pārskenēt bibliotēku" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Atslēgt pārlūku" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Izdrukāt pašreizējo repertuāru" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Izdrukāt rindas saturu" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Izdrukāt rindas saturu" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nav palaists." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Iziet no Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Meklēt pašreizējā dziesmā" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Izslēgt, ieslēgt vai pārslēgt atkārtošanu" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Iestatīt skaļumu" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Meklēt jūsu audio bibliotēkā" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "vaicājums" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Atskaņot failu" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "faila nosaukums" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Meklēt pašreizējā dziesmā" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Iestatīt pašreizējo pārlūku" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Novērtēt pašreiz atskaņoto dziesmu" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Atvērt jaunu pārlūku" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Rādīt vai slēpt rindu" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrēt pēc nejaušas vērtības" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "Tags" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrēt pēc taga vērtības" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tags=vērtība" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Ierindot failu vai vaicājumu" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "faila nosaukums" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Atrindot failu vai vaicājumu" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "vieta" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Nederīgs paraugs" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Nederīgs arguments priekš '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Mēģiniet %s --help." #: quodlibet/errorreport/ui.py:58 #, fuzzy msgid "An Error Occurred" msgstr "Gadījās kļūda" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Ignorēt vis_as kļūdas" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "apraksts" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "audio tagu redaktors" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "mape" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Audio tagu redaktors" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz celiņa ID" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz celiņa ID" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Nederīgs kodējums]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Nosaukums" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Audio tagu redaktors" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Tagu reģistrs ir tāds pats, kā nosaukuma reģistrs" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Kopējais izmērs:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Rediģēt rādāmo" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "S_vars" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 #, fuzzy msgid "_Outline" msgstr "_Izvades līnija:" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Rediģēt rādāmo" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Priekšskats" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informācija" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Atbalstītie formāti: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtrēt pēc žanra" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "mape" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Audio barotnes" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "%s: neizdevās atrast media-player-info." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Jau_na stacija" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Saglabāt vērtējumus un _atskaņošanu skaitu" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "ierakstīšanas datums" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Kļūda ielādējot %r" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "Jau_na stacija" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Iestatījumi" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Importēt repertuāru" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importēt" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Importēt" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Izmest tagu izmaiņas?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Izmest tagu izmaiņas?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Atskaņotājs" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "paraugs" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "paraugs" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "Pašreizējā audio aizmugure neatbalsta URL, audio barotņu pārlūks tiks " "atslēgts." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d sekunde" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Filtrēt pēc māksliniek_a" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "Izvēlētie_s" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Priekšskats" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Pielāgots" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Neizdevās izdzēst dziesmas" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Nederīgs paraugs" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Mūzikas atskaņotājs" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modelis:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Interneta radio" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Vērtējums" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "vieta" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Slēpt galveno logu" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "paraugs" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "paraugs" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d dziesma" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Izvades žurnāls" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "paraugs" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "vieta" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz albuma tips" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Nosaukums:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Nosaukums" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Grāmatzīmes nosaukums" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Ierīce:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "C_iti:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Mākslinieks" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Faila nosaukuma paraugs:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Nejaušs al_bums" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "albumi" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "S_vars" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Nejaušs al_bums" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Grāmatzīmes" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Grāmatzīmes nosaukums" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Grāmatzīmes nosaukums" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[opcijas]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "[Nederīgs kodējums]" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "ierakstīšanas datums" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Dzēst failus" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Dzēst failus" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Nav atrasta neviena stacija" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "paraugs" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Rediģēt saglabātās vērtības..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Mākslinieks" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Priekšskats" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Mūzikas atskaņotājs" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Importēt repertuāru" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organizācija" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Izvēlieties jaunas stacijas" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Ceļš nav absolūts" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Paraugs\n" "\t<b>%s</b>\n" "satur '/', bet nesākas no saknes mapes. Lai izvairītos no mapju nepareizas " "nosaukšanas, pievienojiet savam paraugam sakni, iesākot to ar '/' vai '~/'." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nav izvēlēta neviena dziesma." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nav izvēlēta neviena dziesma." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Neizdevās saglabāt dziesmu" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Neizdevās atvērt ievades failus" msgstr[1] "Neizdevās atvērt ievades failus" msgstr[2] "Neizdevās atvērt ievades failus" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Pašreiz neatskaņo" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d dziesma" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "paraugs" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "_Vērtējums" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Pašreiz neatskaņo" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Re_pertuāri" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Atskaņotājs" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "_Priekšskats" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Sajaukt" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Atkārtot" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Apstāties pēc šīs dziesmas" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Atvērt jaunu pārlūku" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Rediģēt _tagus" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informācija" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Repertuāri" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Rediģēt rādāmo" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Dziesmas vārdi" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Šajai dziesmai vārdi netika atrasti." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Neizdevās saglabāt dziesmu" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Kļūdas" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Faili" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Priekšskats" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtrēt pēc māksliniek_a" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Pielāgots" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Pielāgots" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filtrēt pēc žanra" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filtrēt pēc māksliniek_a" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio barotnes" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Ievadiet audio barotnes adresi:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importēt repertuāru" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Importēt" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Nav atrasta neviena stacija" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Faila nosaukuma paraugs:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Neizdevās importēt repertuāru" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Faila nosaukuma paraugs:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Importēt repertuāru" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Izņemt no _repertuāra" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, fuzzy, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[1] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[2] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Jauns repertuārs" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "Pēdējo reizi atskaņots" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Pēdējo reizi atskaņots" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Ierindots" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Ierindots" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Ierindots" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Nekad" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Nekad" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "grupēšana" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Neizdevās pārkopēt dziesmas" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtrēt pēc žanra" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Nederīgi tagi" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Saglabātās vērtības" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Saglabātās vērtības" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "Pā_rdēvēt" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Bibliotēka" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Slēpt galveno logu" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Faila nosaukums" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Neizdevās saglabāt dziesmu" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Albumu saraksts" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Izmērs" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Meklēt:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Meklēt" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Albumu saraksts" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "R_ediģēt grāmatzīmes..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "R_ediģēt grāmatzīmes..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Grāmatzīmes" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz albuma tips" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Faila nosaukums" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Disks" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Celiņš" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Nosaukums" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Izpildītājs" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz albuma tips" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "vaicājums" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Meklēt" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Nav atrasts neviens spraudnis." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "vieta" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Albumu saraksts" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Albumu saraksts" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Nav atrasts neviens spraudnis." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Priekšskats" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "tags" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "Pā_rdēvēt" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "tags" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Nekad" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Nederīga vērtība" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Pielāgots" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Neizdevās pārkopēt dziesmas" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Atslēgt pārlūku" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "_Vērtējums" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "_Vērtējums" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Rediģēt rādāmo" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Sadalīt _vairākās vērtībās" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "_Vērtējums" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filtrēt pēc taga vērtības" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtrēt pēc žanra" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Ierindots" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Rakstīt" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz celiņa ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "mape" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Albumu galvenes" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "Jau_na stacija" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Nav atrasts neviens spraudnis." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Pārvieto %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Kļūda ielādējot %r" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Importēt repertuāru" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Importēt repertuāru" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Nav ilguma informācijas" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Albumu saraksts" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importēt repertuāru" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importēt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrēt pēc žanra" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Disks" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Celiņš" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Izpildītājs" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albumi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Turpināt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "%s: neizdevās atrast media-player-info." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "%s: neizdevās atrast media-player-info." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Faila nosaukums" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "celiņi" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Kļūda ielādējot %r" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "Pā_rdēvēt" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Importēt repertuāru" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Neizdevās izgrūzt <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "_Atsvaidzināt bibliotēku" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "_Atsvaidzināt bibliotēku" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Celiņš" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Rediģēt tagus" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Rediģēt tagus" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Visi albumi" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Priekšskats" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Tags" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Neizdevās izdzēst dziesmas" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Meklēt" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "paraugs" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Rediģēt saglabātās vērtības..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Iekrā_sot meklējamos terminus" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Rediģēt tagus" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Meklēt" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliotēka" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Pārbauda montēšanas punktus" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Skenē bibliotēku" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Skenē %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Skenē bibliotēku" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Noņemt aktīvos pārlūka filtrus" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "mūzikas bibliotēka un atskaņotājs" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Rādīt programmatūras _tagus" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 #, fuzzy msgid "Too many arguments" msgstr "Par daudz kļūdu" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "apraksts" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Vērtība" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Audio tagu redaktors" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Nav izvēlēta neviena dziesma." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Filtrēt pēc taga vērtības" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Filtrēt pēc taga vērtības" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Nav ilguma informācijas" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Neizdevās pārdēvēt failu" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fails" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Parādīt īsu lietošanas informāciju" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nav derīga vieta." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Nezināms" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Pēc kārtības" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "Pē_c kārtības" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Nejauši" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Nejauši" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Pēdējo reizi atskaņots" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Atkārtot" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Atkārtot" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Viena dziesma" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Viena dziesma" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer izvades līnija, kas tiks izmantota atskaņošanai, piemēram, " "'alsasink device=default'. Atstājiet tukšu, lai izmantotu noklusēto līniju." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Izvades līnija:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%d sekunde" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nav atrasta neviena stacija" #: quodlibet/player/gstbe/util.py:167 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Nederīga GStreamer izvades līnija, mēģina noklusēto." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Neizdevās izveidot audio izvadi" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Audio ierīce %r netika atrasta. Pārbaudiet jūsu Xine iestatījumus failā ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nosaukums:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "S_praudņi" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Sākums" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/P" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Laiks" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Grāmatzīmes nosaukums" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Grāmatzīmes" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtri" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Nekad nav atskaņots" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "Augšējās _40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Jauna stacija" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Nejauš_s žanrs" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Nej_aušs mākslinieks" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Nejaušs al_bums" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 dziesmas, ko esi atskaņojis visbiežāk (var tikt atlasītas vairāk nekā 40, " "ja ir 'neizšķirti' gadījumi)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nosaukums:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Vērtība:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Saglabātās vērtības" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Rediģēt saglabātās vērtības..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "_Celiņu galvenes" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "_Albumu galvenes" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Replay Gain skaļuma regulācija" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Nezināms" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "Pievienot _failu..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "R_ediģēt rādāmo..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filtrēt pēc taga vērtības" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Audio tagu redaktors" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Faili" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Dzēst failus" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "Pārvietot uz _miskasti" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Pārvieto %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Neizdevās saglabāt iPod datubāzi" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Neizdevās izgrūzt <b>%s</b>." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Dzēš %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Neizdevās izdzēst failu" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Neizdevās izdzēst <b>%s</b>." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Pārlūki" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Lejupielādēt failus" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "trūkst no %d dziesmas" msgstr[1] "trūkst no %d dziesmām" msgstr[2] "trūkst no %d dziesmām" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "atšķirīgs %d dziesmā" msgstr[1] "atšķirīgs %d dziesmās" msgstr[2] "atšķirīgs %d dziesmās" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Sadalīt _vairākās vērtībās" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Izdalīt disku no _albuma" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Izdalīt _versiju no nosaukuma" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Izdalīt aranžētāju no izpildī_tāja" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Izdalīt iz_pildītāju no mākslinieka" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Izdalīt iz_pildītāju no mākslinieka" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Izdalīt _versiju no nosaukuma" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Pievienot tagu" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tags:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Rādīt programmatūras _tagus" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Rādīt programmatūras _tagus" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nekad" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Turpināt" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Rediģēt tagus" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Kopēt _albumu vākus" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Neizdevās pievienot tagu" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Neizdevās pievienot dziesmas" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Neizdevās pievienot <b>%s</b>\n" "\n" "Pašlaik izvēlētie faili neatbalsta vairākas vērtības." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Nederīgs tags" msgstr[1] "Nederīgs tags" msgstr[2] "Nederīgs tags" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Neatļauts tags <b>%s</b>\n" "\n" "Pašlaik izvēlētie faili neatbalsta šī taga rediģēšanu." msgstr[1] "" "Neatļauts tags <b>%s</b>\n" "\n" "Pašlaik izvēlētie faili neatbalsta šī taga rediģēšanu." msgstr[2] "" "Neatļauts tags <b>%s</b>\n" "\n" "Pašlaik izvēlētie faili neatbalsta šī taga rediģēšanu." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Nederīga vērtība" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Nederīga vērtība: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tags var nebūt precīzs" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> tika izmainīts, programmai darbojoties. Saglabāšana, " "neatsvaidzinot jūsu bibliotēku, var pārrakstīt citas izmaiņas dziesmā.\n" "\n" "Tomēr saglabāt šo dziesmu?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Neizdevās saglabāt dziesmu" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Neizdevās saglabāt <b>%s</b>. Fails var būt tikai lasāms, bojāts vai arī " "jums nav atļauju to rediģēt." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Vairāk opciju..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "S_praudņi" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s un vēl %(count)d" msgstr[1] "%(title)s un vēl %(count)d" msgstr[2] "%(title)s un vēl %(count)d" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso iestatījumi" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mapes" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Jauna mape" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Izvēlēties vi_sas apakšmapes" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Jauna mape" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Ievadiet jaunās mapes nosaukumu:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Neizdevās izveidot mapi" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Neizdevās izdzēst mapi" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Dziesmas" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "no %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "%s. disks" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "%s. celiņš" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Rediģēt rādāmo" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nav izvēlēta neviena dziesma." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nav dziesmu" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informācija" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Dziesmas vārdi" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Producējis %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "mākslinieks" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "mākslinieki" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "izpildītāji" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nekad" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d reizi" msgstr[1] "%d reizes" msgstr[2] "%d reižu" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "pievienots" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "Pēdējo reizi atskaņots" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "atskaņojumi" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "izlaidumi" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "vērtējums" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "ilgums" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Informācija" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[Nederīgs kodējums]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitātrums" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "faila izmērs" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "mainīts" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d izvēlēti" msgstr[1] "%d izvēlēti" msgstr[2] "%d izvēlēti" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Celiņš nav pieejams" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d dziesma bez albuma" msgstr[1] "%d dziesmas bez albuma" msgstr[2] "%d dziesmu bez albuma" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Izvēlētā diskogrāfija" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d dziesma bez mākslinieka" msgstr[1] "%d dziesmas bez mākslinieka" msgstr[2] "%d dziesmas bez mākslinieka" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumi" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Kopējais ilgums:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Kopējais izmērs:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Faili" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Šajai dziesmai vārdi netika atrasti." #: quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Izmest tagu izmaiņas?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tagi tika izmainīti, bet netika saglabāti. Saglabāt šos failus, vai " "atgriezties un izmest izmaiņas?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Nekad" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Fails pastāv" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Pārdēvēt failus" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Kārtība" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Tagu rediģēšana" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "Pā_rdēvēt" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "vaicājums" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Kopējais izmērs:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Spraudņu kļūdas" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Ieslēgts" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Izslēgts" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Bez kategorijas" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Bez kategorijas" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nav atrasts neviens spraudnis." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "S_praudņi" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Rādīt _kļūdas" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disks" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Celiņš" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "grupēšana" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Mākslinieks" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bums" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Faila nosaukums" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Ilgums" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Pārlēkt uz atskaņoto dziesmu automātiski" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Kad atskaņotā dziesma izmainās, pāriet uz to arī dziesmu sarakstā" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "C_iti:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "R_ediģēt rādāmo..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Redzamās kolonnas" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Nosaukums iekļauj _versiju" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albums iekļauj _diska apakšnosaukumu" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Iegultajā _meklēšanā tiek iekļauti cilvēki" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "_Faila nosaukums iekļauj mapi" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Iestatījumi" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Redzamās kolonnas" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dziesmu saraksts" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Redzamās kolonnas" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globālais filtrs:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Meklēt" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Pārlūki" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Apstiprināt vairākus vērtēju_mus" #: quodlibet/qltk/prefs.py:314 #, fuzzy msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Vaicāt pēc apstiprinājuma, pirms mainīt vērtējumu vairākām dziesmām uzreiz" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Ieslēgt viena klikšķa vērtējumus" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Ieslēgt novērtējumu, noklikšķinot uz vērtējumu kolonnas dziesmu sarakstā" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Vērtējumi" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Albumu saraksts" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Pauzēt atskaņošanu" #: quodlibet/qltk/prefs.py:400 #, fuzzy msgid "Output Configuration" msgstr "Izvades žurnāls" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ja dziesmai nav pieejama Replay Gain informācija, mērogot skaļumu par šo " "vērtību" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Atkāpšanās pastiprinājums (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Mērogot skaļumu visām dziesmām par šo vērtību, ja vien neparādās apgriešana" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Priekšpastiprinājuma pastiprinājums (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "I_eslēgt Replay Gain skaļuma regulāciju" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain skaļuma regulācija" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Vērtējumi" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-pasts:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Vērtējumi un atskaņošanu skaits tiks iestatīts šajai e-pasta adresei" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Izmest tagu izmaiņas?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Sadalīt _pie:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Sadalīt _pie:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Rediģēt tagus" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tagu rediģēšana" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "Jau_na stacija" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Meklēt bibliotēkā" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Pārbaudīt izmaiņas jūsu bibliotēkā" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Pār_lādēt bibliotēku" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Pārlādēt visas dziesmas jūsu bibliotēkā (tas var aizņemt ilgu laiku)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Nav dziesmu" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "A_tsvaidzināt bibliotēku, palaižot programmu" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "Skenēt _mapes" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s un vēl %(count)d" msgstr[1] "%(title)s un vēl %(count)d" msgstr[2] "%(title)s un vēl %(count)d" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Īpašības" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Rinda" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Notīrīt kļūdas" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Izņemt no rindas visas dziesmas" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modelis:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d dziesma (%(time)s)" msgstr[1] "%(count)d dziesmas (%(time)s)" msgstr[2] "(count)d dziesmas (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Pārlūkot _bibliotēku" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Pārslēgt galvenā loga redzamību" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Pauzēt atskaņošanu" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Izvēlieties mapes" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Neizdevās pievienot dziesmas" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> izmanto neatbalstītu protokolu." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Pārlēkt uz atskaņoto dziesmu" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Fails" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Dziesmas" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Skats" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Pārlūki" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Vadība" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Palīdzība" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Pievienot mapi..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "Pievienot _failu..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Pievienot vietu" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "R_ediģēt grāmatzīmes..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Apstāties pēc šīs dziesmas" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Meklēt" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Pievienot vietu" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Ievadiet audio faila atrašanās vietu:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Neizdevās pievienot vietu" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nav derīga vieta." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Pievienot mūziku" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Pievienot mapi..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Mūzikas atskaņotājs" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "Pievienot _failu..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[1] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" msgstr[2] "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Rinda" #: quodlibet/qltk/ratingsmenu.py:26 #, fuzzy, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" "Vai vēlaties turpināt?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "_Vērtējums" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Vērtējums" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Aizvietot atstarpes ar pa_svītrām" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Izņemt ar Windows nesavietojamas rakstzīmes" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Izņemt _diakritiskās zīmes" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Izņemt ne-ASCII rakstzīmes" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Pārdēvēt failus" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Priekšskats" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Faila nosaukums" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "albuma mākslinieks" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Dzēst nevajadzīgos vākus un mapes" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Albumu saraksts" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Jauns nosaukums" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Neizdevās pārdēvēt failu" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Neizdevās pārdēvēt <b>%s</b> par <b>%s</b>. Mērķa fails, iespējams, jau " "eksistē, vai arī jums nav atļauju izveidot jaunu vai dzēst veco failu." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorēt vis_as kļūdas" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Turpināt" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Ceļš nav absolūts" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Paraugs\n" "\t<b>%s</b>\n" "satur '/', bet nesākas no saknes mapes. Lai izvairītos no mapju nepareizas " "nosaukšanas, pievienojiet savam paraugam sakni, iesākot to ar '/' vai '~/'." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Šajās mapēs (jāatdala ar ':') esošās dziesmas tiks pievienotas jūsu " "bibliotēkai" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Dzēš nevajadzīgu iPod celiņu" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Bibliotēka" msgstr[1] "Bibliotēka" msgstr[2] "Bibliotēka" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Vērtējums" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Izvēlieties mapes" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Izvēlieties mapes" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Saglabātās vērtības" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Rediģēt saglabātās vērtības..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Meklēt pēc ieraks_tīšanas" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" "Parāda meklējuma rezultātus pēc tam, kad lietotājs ir pārtraucis rakstīt" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limits:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "S_vars" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "vaicājums" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Rādīt atlikušo laiku" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Dziesmas vārdi" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Fokusēties uz darbojošos atskaņotāju" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Meklēt pašreizējā dziesmā" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Neizdevās izdzēst dziesmas" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Neizdevās izdzēst dziesmas" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrēt pēc %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "_Albumu galvenes" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Celiņu galvenes" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumu galvenes" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "C_ilvēku galvenes" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Datumu galvenes" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Failu galvenes" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Producēšanas galvenes" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "Pielāg_ot galvenes..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Izņemt no _repertuāra" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Izņemt no _repertuāra" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "Izņemt no _repertuāra" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Iekrā_sot meklējamos terminus" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Pie_vienot rindai" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "Izņemt no _repertuāra" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Neizdevās izdzēst failu" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "Lejupielā_dēt" msgstr[1] "Lejupielā_dēt" msgstr[2] "Lejupielā_dēt" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Meklēt" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Lejupielādēt failu" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Albumu saraksts" msgstr[1] "Albumu saraksts" msgstr[2] "Albumu saraksts" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Lejupielādēt failu" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Aizvietot pasvīt_ras ar atstarpēm" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Tagu reģistrs ir tāds pats, kā nosaukuma reģistrs" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Sadalīt _vairākās vērtībās" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tagi no ceļa" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tagi aizvieto pastāvošos tagus" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tagi tiek pievienoti pastāvošajiem tagiem" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Paraugs\n" "\t<b>%s</b>\n" "ir nederīgs. Iespējams, tas satur vienu un to pašu tagu divreiz, vai arī " "tajā ir nenobalancētas zīmes (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Jūsu ievadītais paraugs nav derīgs. Pārliecinieties, ka ievadiet < un " "> kā \\< un \\> un ka jūsu tagi ir nobalancēti.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Rediģēt rādāmo" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Celiņu numuri" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Sākt _no:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Celiņi kopā:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Atskaņotājs" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "_Priekšskats" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "un vēl %d..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Saglabā jūsu izmainītās dziesmas." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d dziesmas saglabātas\n" "(%(remaining)s atlikušas)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Pārvieto %(current)d/%(total)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Pārbauda montēšanas punktus" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "vieta" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importēt repertuāru" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Repertuārs ar nosaukumu %s jau pastāv." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Rādīt albumu _vākus" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Failu sistēma" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Kopējais izmērs:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Parādīt īsu lietošanas informāciju" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Parādīt versiju un autortiesības" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Nav ilguma informācijas" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opcijas]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Opcija %r nav atpazīta." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Opcijai %r nepieciešams arguments." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r nav unikāls prefikss." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d sekunde" msgstr[1] "%d sekundes" msgstr[2] "%d sekunžu" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Nav ilguma informācijas" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunde" msgstr[1] "%d sekundes" msgstr[2] "%d sekunžu" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minūte" msgstr[1] "%d minūtes" msgstr[2] "%d minūšu" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d stunda" msgstr[1] "%d stundas" msgstr[2] "%d stundu" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d diena" msgstr[1] "%d dienas" msgstr[2] "%d dienu" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d gads" msgstr[1] "%d gadi" msgstr[2] "%d gadu" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "nē" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datumam jābūt ievadītam 'GGGG', 'GGGG-MM-DD' vai 'GGGG-MM-DD HH:MM:SS' " "formātā." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain pastiprinājumi jāievada 'x.yy dB' formātā." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain maksimumi jāievada 'x.yy' formātā." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID-iem jābūt UUID formātā." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz izlaiduma statusam jābūt 'official', 'promotional' vai 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Neizdevās izgrūzt <b>%s</b>." msgstr[1] "Neizdevās izgrūzt <b>%s</b>." msgstr[2] "Neizdevās izgrūzt <b>%s</b>." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Neizdevās rediģēt dziesmu" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Neizdevās saglabāt <b>%s</b>. Fails var būt tikai lasāms, bojāts vai arī " "jums nav atļauju to rediģēt." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Nederīgs kodējums]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "albums" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranžētājs" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranžētāji" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "aranžētājs" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autors" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "tags" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "komponists" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "komponisti" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "komponists" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "diriģents" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "diriģenti" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "diriģents" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakts" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "autortiesības" #: quodlibet/util/tags.py:93 msgid "date" msgstr "datums" #: quodlibet/util/tags.py:94 msgid "description" msgstr "apraksts" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "žanrs" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "žanrs" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "izpildītājs" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "izpildītājs" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupēšana" #: quodlibet/util/tags.py:98 msgid "language" msgstr "valoda" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licence" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "dziesmu vārdu autors" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "vārdu autori" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "dziesmu vārdu autors" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizācija" #: quodlibet/util/tags.py:104 msgid "title" msgstr "nosaukums" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versija" #: quodlibet/util/tags.py:106 msgid "website" msgstr "tīmekļa vietne" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albuma mākslinieks" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "sit./min." #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "diska apakšnosaukums" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disks" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "celiņš" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "izdevēja ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "oriģinālais izlaiduma datums" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "oriģinālais albums" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "oriģinālais mākslinieks" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "ierakstīšanas datums" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "izlaiduma valsts" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz celiņa ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz izlaiduma ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz izlaiduma ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz mākslinieka ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz izlaiduma ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz albuma statuss" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz albuma tips" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz izlaiduma ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "celiņa pastiprinājums" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "celiņa maksimums" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albuma pastiprinājums" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albuma maksimums" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Iestatījumi" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diski" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "celiņi" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "pēdējo reizi sākts" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "pilns vārds" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "montēšanas punkts" #: quodlibet/util/tags.py:166 msgid "people" msgstr "cilvēki" #: quodlibet/util/tags.py:168 msgid "year" msgstr "gads" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "oriģinālais izlaiduma datums" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "grāmatzīme" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "Nav ilguma informācijas" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Repertuāri" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Audio tagu redaktors" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Rediģē tagus jūsu audio failos" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Mūzikas atskaņotājs" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Atskaņo, pārlūko vai rediģē jūsu audio kolekciju" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Importēt repertuāru" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Neizdevās pievienot dziesmu" #~ msgid "Invalid tags" #~ msgstr "Nederīgi tagi" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Nederīgi tagi <b>%s</b>\n" #~ "\n" #~ "Pašreiz izvēlētie faili neatbalsta šo tagu rediģēšanu." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d sekunde" #, fuzzy #~ msgid "Startup" #~ msgstr "_Importēt" #~ msgid "Audio Feeds" #~ msgstr "Audio barotnes" #~ msgid "_Audio Feeds" #~ msgstr "_Audio barotnes" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Meklē dziesmas vārdus..." #, fuzzy #~ msgid "<artist>" #~ msgstr "mākslinieks" #, fuzzy #~ msgid "<album>" #~ msgstr "albums" #, fuzzy #~ msgid "<title>" #~ msgstr "nosaukums" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importēt repertuāru" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importēt repertuāru" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informācija" #~ msgid "Unsupported file type" #~ msgstr "Neatbalstīts faila tips" #~ msgid "Unable to add station" #~ msgstr "Neizdevās pievienot staciju" #~ msgid "Device Properties" #~ msgstr "Ierīces īpašības" #~ msgid "Device:" #~ msgstr "Ierīce:" #~ msgid "Not mounted" #~ msgstr "Nav piemontēta" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Montēšanas punkts:" #~ msgid "Media Devices" #~ msgstr "Multivides ierīces" #~ msgid "_Media Devices" #~ msgstr "_Multivides ierīces" #~ msgid "_Eject" #~ msgstr "Izgrūz_t" #, fuzzy #~ msgid "_Properties" #~ msgstr "Īpašības" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> izmantoti, <b>%s</b> pieejami" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Kopē <b>%(song)s</b>" #~ msgid "Unable to copy song" #~ msgstr "Neizdevās pārkopēt dziesmu" #~ msgid "There is not enough free space for this song." #~ msgstr "Nav pietiekami daudz brīvas vietas šajai dziesmai." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> nevarēja tikt pārkopēta." #~ msgid "Unable to delete songs" #~ msgstr "Neizdevās izdzēst dziesmas" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Dzēš <b>%(song)s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> nevarēja tikt izdzēsta." #~ msgid "Unable to delete song" #~ msgstr "Neizdevās izdzēst dziesmu" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Neizdevās izgrūzt <b>%s</b>." #~ msgid "Unable to eject device" #~ msgstr "Neizdevās izgrūzt ierīci" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "Nav ierīču aizmugures, multivides ierīču pārlūks atslēgts." #~ msgid "Search Library" #~ msgstr "Meklēt bibliotēkā" #~ msgid "_Search Library" #~ msgstr "_Meklēt bibliotēkā" #~ msgid "Rate the playing song" #~ msgstr "Novērtēt pašreiz atskaņoto dziesmu" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Rādīt vai slēpt galveno dziesmu sarakstu" #~ msgid "Unknown Device" #~ msgstr "Nezināma ierīce" #, fuzzy #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Neizdevās importēt dbus-python, kas ir nepieciešams ierīču atbalstam." #~ msgid "%r is not a supported device." #~ msgstr "%r nav atbalstīta ierīce." #~ msgid "Initializing device backend." #~ msgstr "Inicializē ierīces aizmuguri." #~ msgid "Trying '%s'" #~ msgstr "Mēģina '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Neizdevās pieslēgties ierīces aizmugurei." #~ msgid "Device backend initialized." #~ msgstr "Ierīces aizmugure inicializēta." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Faila nosaukuma paraugs:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Notīrīt kļūdas" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Dziesmas vārdi" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Notīrīt meklējumu lauku" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Dziesmas vārdi" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Dziesmas vārdi" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Nav dziesmu" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Pārlūki" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Neizdevās izveidot mapi" #~ msgid "Audio device: %s" #~ msgstr "Audio ierīce: %s" #~ msgid "Downloads" #~ msgstr "Lejupielādes" #~ msgid "Size" #~ msgstr "Izmērs" #~ msgid "_Download" #~ msgstr "Lejupielā_dēt" #~ msgid "_Copy to Device" #~ msgstr "Kopēt uz ierī_ci" #, fuzzy #~ msgid "browsers" #~ msgstr "Pārlūki" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Neizdevās importēt python-feedparser, audio barotņu pārlūks tiks atslēgts." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Quod Libet nonāca izņēmumsituācijā. Dump fails, kas mums palīdzēs " #~ "atkļūdot avāriju, tika saglabāts <b>%s</b>. Lūdzu, aizpildiet jaunu " #~ "problēmas ziņojumu vietnē http://code.google.com/p/quodlibet/issues/" #~ "list , un pievienojiet šo failu vai arī iekļaujiet tā saturu. Šis fails " #~ "var saturēt identificējošu situāciju par jums vai jūsu sistēmu, piemēram, " #~ "nesen atskaņoto failu sarakstu. Ja tas nav pieņemami, tā vietā sūtiet <b>" #~ "%s</b> kopā ar aprakstu par jūsu darbībām avārijas brīdī.\n" #~ "\n" #~ "Quod Libet tagad var būt nestabils. Vēlams to aizvērt un pārstartēt. Jūsu " #~ "bibliotēka tiks saglabāta." #~ msgid "Unable to download lyrics." #~ msgstr "Neizdevās lejupielādēt dziesmas vārdus." #~ msgid "Set or toggle the playback order" #~ msgstr "Iestatīt vai pārslēgt atskaņošanas kārtību" #~ msgid "Uninitialized iPod" #~ msgstr "Neinicializēts iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Vai vēlaties izveidot tukšu datubāzi uz šī iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "S_kaļuma pastiprinājums (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Ko_mbinēt tagus ar vairākām vērtībām" #~ msgid "Capacity:" #~ msgstr "Ietilpība:" #~ msgid "Firmware:" #~ msgstr "Programmatūra:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Neizdevās saglabāt iPod datubāzi" #~ msgid "Unable to save iPod database" #~ msgstr "Neizdevās saglabāt iPod datubāzi" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Neizdevās importēt python-gpod, iPod atbalsts tiks atslēgts." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "celiņa maksimums" #~ msgid "Shuffle" #~ msgstr "Sajaukt" #~ msgid "Weighted" #~ msgstr "Svērti" #~ msgid "_Weighted" #~ msgstr "S_vērti" #~ msgid "_One Song" #~ msgstr "V_iena dziesma" #~ msgid "Restart the playlist when finished" #~ msgstr "Pārstartēt repertuāru, kad pabeigts" #~ msgid "Disable Browser" #~ msgstr "Atslēgt pārlūku" #~ msgid "_Disable Browser" #~ msgstr "A_tslēgt pārlūku" #, fuzzy #~ msgid "Force Write" #~ msgstr "Rakstīt" #~ msgid "Filter on _Genre" #~ msgstr "Filtrēt pēc žanra" #~ msgid "Filter on _Artist" #~ msgstr "Filtrēt pēc māksliniek_a" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrēt pēc al_buma" #~ msgid "_Music" #~ msgstr "_Mūzika" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Grāmatzīmes" #~ msgid "Song _List" #~ msgstr "_Dziesmu saraksts" #, fuzzy #~ msgid "D:" #~ msgstr "B: " #, fuzzy #~ msgid "W:" #~ msgstr "B: " #, fuzzy #~ msgid "E:" #~ msgstr "E: " #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Apstāties pēc šīs dziesmas" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "un vēl %d..." #~ msgstr[1] "un vēl %d..." #~ msgstr[2] "un vēl %d..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Izdalīt disku no _albuma" #, fuzzy #~ msgid "Timeout" #~ msgstr "Laiks" #, fuzzy #~ msgid "Select an album" #~ msgstr "Iezīmēt visus" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s un vēl %(count)d" #~ msgstr[1] "%(title)s un vēl %(count)d" #~ msgstr[2] "%(title)s un vēl %(count)d" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Repertuāri" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "Izmantot noapaļot_us stūrus sīktēliem" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Noapaļot albumu vāciņu sīktēlus. Iespējams, būs jāpārstartē programma, " #~ "lai izmaiņas stātos spēkā." #~ msgid "Re_fresh Library" #~ msgstr "_Atsvaidzināt bibliotēku" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Vērtējums" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer nav elementa failu nolasīšanai. Pārbaudiet jūsu GStreamer " #~ "instalācijas iestatījumus." #~ msgid "Invalid audio backend" #~ msgstr "Nederīga audio aizmugure" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "Audio aizmugure %r nav instalēta." #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "faila_nosaukums" #~ msgid "command|tag" #~ msgstr "tags" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: neizdevās atrast media-player-info." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Meklēt" #~ msgid "%d of %d" #~ msgstr "%d no %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Lietošana: %s %s" #~ msgid "_Download..." #~ msgstr "Lejupielā_dēt..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "Jau_na stacija" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Pārrakstīt <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Izvades kļūda" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "Neizdevās inicializēt GStreamer izvades līniju. Līnija var nebūt derīga, " #~ "vai arī ierīce jau tiek izmantota. Pārbaudiet jūsu atskaņotāja " #~ "iestatījumus." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet jau ir palaists." #~ msgid "No song is currently playing." #~ msgstr "Pašreiz netiek atskaņota neviena dziesma." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Neizdevās uz %s. Dzēš to." #~ msgid "_Edit Bookmarks..." #~ msgstr "R_ediģēt grāmatzīmes..." #~ msgid "_New Folder..." #~ msgstr "Jau_na mape..." #~ msgid "_Add to Playlist" #~ msgstr "Pievienot repertuār_am" #~ msgid "_Edit Display..." #~ msgstr "R_ediģēt rādāmo..." #~ msgid "Output Log" #~ msgstr "Izvades žurnāls" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stacija" #~ msgid "_Add a Location..." #~ msgstr "Pievienot _vietu..." #~ msgid "_Output Log" #~ msgstr "Izvades ž_urnāls" #~ msgid "Invalid command %r received." #~ msgstr "Saņemta nederīga komanda %r." #~ msgid "Unknown browser %r." #~ msgstr "Nezināms pārlūks %r." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "Pielāg_ot galvenes..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[1] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[2] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[1] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[2] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Celiņu galvenes" #, fuzzy #~ msgid "People Headers" #~ msgstr "C_ilvēku galvenes" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Albumu galvenes" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Datumu galvenes" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Failu galvenes" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Producēšanas galvenes" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tags:" #~ msgid "Too Many Errors" #~ msgstr "Par daudz kļūdu" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Aptur atskaņošanu, jo tika novērotas %d kļūdas pēc kārtas." #~ msgid "Warnings" #~ msgstr "Brīdinājumi" #~ msgid "album artist (sort)" #~ msgstr "albuma mākslinieks (kārtot)" #~ msgid "artist (sort)" #~ msgstr "mākslinieks (kārtot)" #~ msgid "album (sort)" #~ msgstr "albums (kārtot)" #~ msgid "performer (sort)" #~ msgstr "izpildītājs (kārtot)" #~ msgid "performers (sort)" #~ msgstr "izpildītāji (kārtot)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz albuma mākslinieka ID" #~ msgid "errors" #~ msgstr "kļūdas" #~ msgid "Permanently delete this file?" #~ msgstr "Neatgriezeniski dzēst šo failu?" #~ msgid "Permanently delete these files?" #~ msgstr "Neatgriezeniski dzēst šos failus?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s un vēl %(count)d..." #~ msgstr[1] "%(title)s un vēl %(count)d..." #~ msgstr[2] "%(title)s un vēl %(count)d..." #, fuzzy #~ msgid "Version:" #~ msgstr "versija" #~ msgid "_Cause an Error" #~ msgstr "Izraisīt _kļūdu" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s nevarēja tikt pievienota jūsu bibliotēkai.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Komanda 'eject' nav atrasta." #~ msgid "Unable to start web browser" #~ msgstr "Neizdevās palaist tīmekļa pārlūku" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Neizdevās atrast tīmekļa pārlūku. Lūdzu, iestatiet mainīgo '$BROWSER', " #~ "vai arī pārliecinieties, ka /usr/bin/sensible-browser eksistē." #, fuzzy #~ msgid "Library Error" #~ msgstr "Bibliotēkas pārlūks" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Izvades līnija:" #~ msgid "translator-credits" #~ msgstr "Einārs Sprūģis <einars8@gmail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Citas kolonnas, ko attēlot, atdalītas ar atstarpēm" #~ msgid "_Edit and Continue" #~ msgstr "R_ediģēt un turpināt" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[1] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgstr[2] "" #~ "Jūs grasāties mainīt vērtējumu %d dziesmām.\n" #~ "Vai vēlaties turpināt?" #~ msgid "Confirm rating" #~ msgstr "Apstiprināt vērtējumu" #~ msgid "Search your library" #~ msgstr "Meklēt jūsu bibliotēkā" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Autortiesības 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "Šī ir brīvā programmatūra; kopēšanas nosacījumiem skatiet pirmkodu.\n" #~ "Netiek dota NEKĀDA garantija, pat PIEPRASĪJUMA vai NODERĪBAS ĪPAŠAM\n" #~ "MĒRĶIM garantija.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r nesatur nekādus pārlūkus." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Kopējais izmērs:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r nesatur nekādas ierīces." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: neizdevās importēt ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: neizdevās atrast media-player-info." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: neizdevās atrast media-player-info." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet spraudņi" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Attēlot vienkāršos meklējumus zilā krāsā, paplašinātos - zaļā, bet " #~ "nederīgos - sarkanā krāsā" #~ msgid "Separators for splitting tags" #~ msgstr "Atdalītāji tagu sadalīšanai" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet iestatījumi" #~ msgid "Not Played To_day" #~ msgstr "Nav atskaņots šo_dien" #~ msgid "Not Played in a _Week" #~ msgstr "Nav atskaņots š_onedēļ" #~ msgid "Not Played in a _Month" #~ msgstr "Nav atskaņots šo_mēness" #~ msgid "B_ottom 40" #~ msgstr "Apakšējās 4_0" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "40 dziesmas, ko esi atskaņojis visretāk (var tikt atlasītas vairāk nekā " #~ "40, ja ir 'neizšķirti' gadījumi)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | vadīkla ]" #~ msgid "Date" #~ msgstr "Datums" #~ msgid "Add" #~ msgstr "Pievienot" #~ msgid "Bitrate" #~ msgstr "Bitātrums" #~ msgid "_Stations..." #~ msgstr "_Stacijas..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Inicializē audio aizmuguri (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Inicializē galveno bibliotēku (%s)" #~ msgid "Unable to save library" #~ msgstr "Neizdevās saglabāt bibliotēku" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "Audio izvades līnija %r nevarēja tikt izveidota. Pārbaudiet jūsu " #~ "GStreamer iestatījumus failā ~/.quodlibet/config." ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/nb.po����������������������������������������������������������������������������0000644�0001750�0001750�00000761612�14436352625�013607� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Norwegian bokmål translation of Quod Libet # Copyright (C) 2004-2022 Joe Wreschnig and other Quod Libet authors # This file is distributed under the same license as the Quod Libet package. # # Eirik Haatveit <haatveit@gmail.com>, 2007. # Åka Sikrom <a4 ætt hush dått com>, 2016-2018. # Allan Nordhøy <epost@anotheragency.no>, 2021-2022. # Pho Korat <post -at- phokorat -dot- com>, 2022. # msgid "" msgstr "" "Project-Id-Version: quodlibet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-20 11:19+0100\n" "PO-Revision-Date: 2022-12-20 11:20+0100\n" "Last-Translator: Pho Korat <post -at- phokorat -dot- com>\n" "Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/" "quodlibet/quodlibet/nb_NO/>\n" "Language: nb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 3.0.1\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Tittel" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Personer" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Dato" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Dato lagt til" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Opprinnelig dato" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "Sjan_ger" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Vurdering" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "_Antall avspillinger" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Sorter _etter …" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Innstillinger" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumliste" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumliste" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Alle album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Last inn album_omslag på nytt" msgstr[1] "Last inn album_omslag på nytt" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Låter uten album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d spor" msgstr[1] "%d spor" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d plate" msgstr[1] "%d plater" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Et eksempelalbum" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Innstillinger for albumliste" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Vis album_omslag" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_Søk inkluderer personer" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Valg" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albumvisning" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Lukk" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Bibliotekutforsker" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d låt" msgstr[1] "%d låter" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Ugyldig mønster" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumsamling" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Album_samling" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Ukjent %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Flere %s verdier" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Selvvalgt" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "L_egg til" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Fjern" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tagg" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Slå sammen" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Innstillinger for albumsamling" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Bruk" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "Avbr_yt" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Omslagsnett" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Omslagsnett" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Omslagsnett-innstillinger" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Vis album_tekst" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Vis elementet «alle album»" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Bred modus" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Omslagsforstørrelse" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Filsystem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Filsystem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Klarte ikke å legge til låter" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "Klarte ikke å kopiere eller legge valgte filer i kø." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Legg til i bibliotek" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Stasjonslister skal bare inneholde adresser til stasjoner, og ikke andre " "stasjons- eller spillelister. Klarte ikke å laste inn følgende " "plasseringer: \n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Nettradio" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Legg til stasjoner" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Laster ned stasjonsliste" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Ny stasjon" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Skriv inn adressen til en nettradio-stasjon:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronisk" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip-Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Gamleviser" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japansk" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indisk" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religiøst" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Lister" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Tyrkisk" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Studentradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Prat / Nyheter" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassisk" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativt" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Nyheter" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavisk" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Gresk" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotisk" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Vil du laste inn en liste over populære radiokanaler?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "Last inn stasjoner" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Nettradio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Alle stasjoner" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoritter" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Ingen kategori" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Ny stasjon …" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Oppdater stasjoner" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Fant ingen stasjoner" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Fant ingen nettradio-stasjoner på %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Ingenting å legge til" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Alle oppførte stasjoner ligger i biblioteket allerede." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Legg til i favoritter" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Fjern fra favoritter" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stasjon" msgstr[1] "%(count)d stasjoner" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Rutevisning" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Rutevisning" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Velg alle" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Ukjent" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Alle" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Liten" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Bred" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Kolonneformet" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Taggmønster med valgfri markering som f.eks. <tt>komponist</tt> eller\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Innstillinger for rutevisning" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Kolonneoppsett" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Kolonneinnhold" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Lik rutebredde" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Spillelister" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Spillelister" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Fjern fra spilleliste" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Ny" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Importer …" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Klarte ikke å importere spilleliste" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet kan bare importere spillelister i formatene M3U/M3U8 og PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "Sle_tt" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Gi nytt navn" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Klarte ikke å gi nytt navn til spilleliste" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importer spilleliste" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importer" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Ny spilleliste …" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Hva vil du gjøre med %d låt?" msgstr[1] "Hva vil du gjøre med disse %d låtene?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Bekreft handling for spilleliste «%s»" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "tom" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Eksempelliste" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Innstillinger for spilleliste-utforsker" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Spillelistevisning" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Er du sikker på at du vil slette spillelista «%s»?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "All informasjon om valgt spilleliste blir slettet, og du kan ikke " "gjenopprette den." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "Utvid «{pl_name}» med {num} ytterligere spor?" msgstr[1] "Utvid «{pl_name}» med {num} ytterligere spor?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Legg til spor" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Ny spilleliste" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Skriv inn navn på ny spilleliste:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Lag" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importerer spilleliste.\n" "\n" "%(current)d/%(total)d låter lagt til." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Ny kilde" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Skriv inn adresse til podkast-/lydstrøm:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Nettradioopptak" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Nettradioopptak" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "_Legg til kilde …" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Oppdate_r" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Se etter nye nye episoder i denne kilden" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Bygg igjen" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "Fjern alle eksisterende episoder og last inn på nytt fra kilde" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Fjern dette nettradioopptaket og dets episoder" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Klarte ikke å legge til kilde" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Klarte ikke å legge til %s. Tjeneren kan være utilgjengelig, eller " "plasseringa er ikke en podkast-/lydkilde." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Gjeldende lyd-bakstykke støtter ikke nettadresser. Podkast-utforsker slått " "av." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Begrens resultater" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Tillat flere spørringer" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Sporliste" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Sporliste" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud-utforsker" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Søk" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Spor" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Gå til %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Tilkoblet" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet er tilkoblet. %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Logg ut av %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Skriv inn kode …" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Logg inn på %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud-autorisering" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Skriv inn Soundcloud-autoriseringskode:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet kjører ikke (bruk valget «--run» for å kjøre)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "musikkbibliotek og -spiller" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[valg]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Skriv ut spillende låt og avslutt" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Begynn avspilling med en gang" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Ikke vis noen vinduer ved oppstart" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Hopp til neste låt" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Hopp til forrige låt eller start på nytt hvis nettopp begynt" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Hopp til forrige låt" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Start avspilling" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pause avspilling" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Skift mellom avspilling/pause-modus" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Stopp avspilling" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Øk volum" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Demp volum" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Øk vurdering av spillende spor med én stjerne" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Mink vurdering av spillende spor med én stjerne" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Skriv ut spillerstatus" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Skjul hovedvindu" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Vis hovedvindu" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Vis/skjul hovedvindu" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokuser på kjørende spiller" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Fjern gjeldende visningsfiltre" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Oppdater bibliotek og skann på nytt" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Vis tilgjengelige utforskere" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Skriv ut gjeldende spilleliste" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Skriv ut innhold i kø" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Skriv ut gjeldende tekstspørring" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Start uten tillegg" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet hvis det ikke kjører" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Avslutt Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Søk i spillende låt" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Slå av/på omstokket rekkefølge" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Endre omstokkingsmodus" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Bytt eller slå gjentakelsesmodus av/på" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Endre gjentakelsesmodus" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Juster volum" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Søk i musikkbibliotek" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "spørring" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Spill av en fil" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "filnavn" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Sett vurdering for spillende spor" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Velg visningsmodus for gjeldende vindu" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Stopp etter spillende låt" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Åpne nytt visningsvindu" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Vis eller skjul kø" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrer på tilfeldig verdi" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tagg" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrer på taggverdi" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tagg=verdi" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Legg fil eller spørring i kø" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Legg komma-adskilte filnavn i kø" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "filnavn" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Skriv ut filnavn fra søketreff til standardutdata" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Fjern fil eller spørring fra kø" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Legg til en fil eller mappe i biblioteket" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "sted" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Velg mal for «--print-*»-kommandoer" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "mønster" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Ugyldig argument for «%s»." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Prøv %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Det oppstod en feil" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Du kan se bort fra denne feilmeldinga, men programmet kan oppføre seg " "ustabilt frem til du starter det på nytt. Hjelp oss gjerne med å rette " "feilen ved å sende inn en feilrapport." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Send feilrapport" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Start på nytt" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorer feil" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Feildetaljer:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Detaljer om programfeilen og systemet ditt blir sendt til en " "tredjepartstjeneste på nett (<a href='https://www.sentry.io'>www.sentry.io</" "a>). Du kan se gjennom dataene nedenfor før du evt. velger å sende dem." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(valgfritt) Kort beskrivelse av hva du gjorde da feilen oppstod:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Send" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Kort beskrivelse …" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Data som blir sendt:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "lydtagg-behandler" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "mappe" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Metadata-behandler for lydfiler" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Nettadresse til omslagsbilde" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Laster ned omslagsbilder fra adresse i taggen <tt>artwork_url</tt>. Dette " "fungerer med Soundcloud- og podkast-utforskere." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs-omslagskilde" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Last ned omslagsbilder fra Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm-omslagskilde" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Laster ned omslagsbilder fra Last.fm-arkivet." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-omslagskilde" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Laster ned omslagsbilder fra MusicBrainz-arkivet." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Konverter kodinger" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Retter opp feiltolkede kodinger av taggverdier i taggbehandleren." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Konverter koding …" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Enkel Kana/Kanji-omformer" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Konverterer kana/kanji til romaji før navnebytte." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romaniser _japansk tekst" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Fant ikke «Kanji Kana Simple Inverter» (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Bruk reg.uttrykk" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Tillater arbitrær bruk av regulære uttrykk (<tt>s/fra/til/</tt>) ved tagging " "eller endring av filnavn." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Tittelversaler" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Tittelversaliser tagger i taggbehandler." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Tittelversaliser verdi" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Tillat tagger med _BARE STORE BOKSTAVER" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Tittelversalisering" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Bruker vanlig engelsk modell for tittelversalisering, som f.eks. «Dark Night " "of the Soul»" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Avanserte innstillinger" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Tillat endring av avanserte oppsettsvalg." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Jeg vet hva jeg gjør" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animert skjermvisning" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Viser info om låt ved låtbytte." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Posisjon:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Omslagsstørrelse:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Visning" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "Skri_ft:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Venstre" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Sentrum" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Høyre" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Juster tekst:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Tekst" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Tekst:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Fyll:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Farger" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Skygger" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "K_ontur" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Avru_ndede hjørner" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Forsinkelse:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effekter" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Rediger visningsmønster …" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Forhåndsvis" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Programinformasjon" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Diverse informasjon om programmet og miljøet." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Støttede formater" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Oppsettsmappe" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Hurtiglagringsmappe" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Lyd-bakstykke" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Etter hver avspilling (forvalg)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Når du spiller av en låt uten å hoppe over den, skriver tillegget taggene " "til fila. Antall ganger du hopper over låter blir ikke lagret, så du unngår " "unødvendig skriving." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Etter hver avspilling eller hopp" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Når du spiller av eller hopper over en låt, skriver tillegget tagger til " "fila. Nyttig hvis du vil forsikre deg om at vurderinger av spor du misliker " "(og altså hopper over) blir lagret." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Én gang, når albumet er vurdert i sin helhet" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Når du spiller av heller hopper over en låt, blir albumet for sporet " "kontrollert. Hvis hvert spor på albumet er blitt vurdert, og minst ett av " "dem mangler vurdering eller avspillingsantall i fila si, skriver tillegget " "tagger til filene.\n" "\n" "Bruk dette for å unngå gjentatte filoppdateringer, men vær klar over at så " "snart et album er blitt oppdatert, må du bruke «Oppdater tagger i filer»-" "programtillegget når du vil at endrede avspillingsantall og vurderinger skal " "lagres i filene." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Når tillegget lagrer tagger for et album, endrer det først avspillingsantall " "for låter som har ingen eller én avspilling.\n" "Noen ganger vet du allerede at du ikke liker en låt. Derfor kan det være " "nyttig å endre verdien til 1 ved lagring, med tanke på senere anledninger " "når du søker etter album som du har lyttet helt gjennom (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Klarte ikke å skrive «%s»." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Oppdater tagger i filer automatisk" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Oppdater tagger i filer når du har spilt dem av. Dette holder " "avspillingsstatistikk og vurderinger oppdatert." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Følgende innstilling ble slått på for at tillegget skal virke:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Lagre vurderinger og avspillings_antall i tagger" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Oppsett oppdatert" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Feil i %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Sørg for at avspillingsantall er over null ved lagring" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Oppdater strategi:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Innstillinger" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatisk maskering" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Viser og skjuler lagringsenheter automatisk når de monteres og avmonteres." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatisk vurdering" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Gir låter automatisk vurdering basert på om du spiller gjennom eller hopper " "over dem. Denne funksjonen bruker vux-algoritmen «accelerated» av Brian " "Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Valgt Banshee-database er skadet eller mangler" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importering mislyktes" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Importerte vurderinger og statistikk for %d låt" msgstr[1] "Importerte vurderinger og statistikk for %d låter" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee-importering" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Importerer vurderinger og sporstatistikk fra Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Databasesti:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Start importering" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Vekkerklokke" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Vekkefunksjon med høy musikk." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Nattasang" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Toner ut og setter musikk på pause." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord-statusmelding" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discord-statusmelding" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Legg det du hører på nå i en Discord-statusmelding." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "På pause" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Statuslinje #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Statuslinje #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Flat" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Levende" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Full bass og diskant" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klubb" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Stor hall" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Fest" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Myk" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Full bass" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Hodetelefoner" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Soft rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Full diskant" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizer" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Kontrollerer overtonenivåer i lydfiler.\n" "Klikk eller bruk knapper for å tilpasse nivåer (høyreklikk for å " "tilbakestille)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Gjeldende bakstykke støtter ikke overtone-kontroll." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Forvalgte oppsett" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Velg …" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Tilbakestill tonekontroll" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Egendefinerte forvalg" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Slett valgte" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Forvalgt navn for lagring:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "La_gre" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "tilkoblet" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "frakoblet" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "prat" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "borte" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "usynlig" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim-statusmelding" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Endrer Gajim-statusmelding basert på hva du spiller av." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "pauset" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Mønster:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Viser kontoer - adskilt med komma - for endring av statusmelding. Hvis ingen " "er valgt, blir statusmeldinger for alle kontoer endret." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Kontoer:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Legg til «[på pause]»" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Hvis dette er valgt, blir «[paused]» lagt til statusmeldinger ved pause" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statuser som statusmelding skal endres for" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pause ved frakobling av hodetelefoner" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Setter musikk på pause når du kobler fra hodetelefoner, og fortsetter " "avspilling når du kobler dem til igjen." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Hindre skjermsparer/dvalgang" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Forhindrer skjermsparer og dvalemodus under avspilling på GNOME-skrivebord." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Musikk under avspilling" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Modus:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Hindre skjermsparer" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Hindre hvilemodus" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Internettradio-logg" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Husker de 10 siste låtene som ble spilt på radiokanaler, og viser dem i " "søkemenyen." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Skriver ut Jabber User Tunes-fil til %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Bytt språk" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Endre grensesnitt-språk." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Forvalgt av system" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Programmet må startes på nytt for å ta i bruk endringer" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV-medietjener" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Viser alle album til Rygel UPnP-medietjener via D-Bus-grensesnittet " "MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Forsikre deg om at dette finnes i rygel-oppsettsfila (~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD-tjener" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Tillater fjernstyring av Quod Libet ved bruk av MPD-klient. Strømming, " "spillelister og bibliotekbehandling støttes ikke." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokal _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "P_assord:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Tilkobling" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Testede klienter" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus-støtte" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Tillater kontroll av Quod Libet ved bruk av <a href=\"https://mpris2." "readthedocs.io/en/latest/\">MPRIS 2</a>-D-Bus-grensesnittsspesifikasjonen. " "Dette tillater forskjellig integrasjon i Linux-skrivebord (f.eks. " "multimediataster)." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Skjul hovedvindu ved lukking" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Tillater QL-mønstre som f.eks. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT-utgiver" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Sender statusmeldinger til et MQTT-emne." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Mellomtjener-vertsnavn / -IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Forvalg er lokal maskin" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Mellomtjener-port" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Forvalg er 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Magler-brukernavn" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Megler-passord" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Emne" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Avspillingsmønster" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Statustekst når du spiller av en låt." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Pausemønster" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Tekst når du setter en låt på pause." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "«Ingen låt»-tekst" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Ren tekst når du ikke spiller av en låt" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT-oppsett" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Statustekst" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Tilkoblet mellomtjener på %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Klarte ikke å koble til %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Tilkoblingsfeil" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz-synkronisering" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synkroniserer låtvurderinger med MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Bruker_navn:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Passord:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Varslingstekst" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Tittel:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Tilbakestill til standardmønster" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Brødtekst:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "Vi_s varsling" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Vis varslinger" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Bare ved <i>_manuelt</i> låtbytte" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Bare ved <i>_automatisk</i> låtbytte" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Ved <i>a_lle</i> typer låtbytte" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Bare når hovedvindu ikke er i _fokus" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Vis «_Neste»-knapp" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Tilkoblingsfeil" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Klarte ikke å koble til bakgrunnsprosess for varslinger." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Låtvarslinger" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Viser et varsel ved låtbytte." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Neste" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Bokmerkevarslinger" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Bruker varslinger for å vise bokmerker og kommentarer i sanntid. Fungerer " "godt med Soundcloud-utforskeren." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Besøk Tillegg-vinduet for å sette opp QLScrobbler. Ingen låter blir sendt " "inn før du gjør dette." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Klarte ikke å koble til tjenesten «%s»." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Autentisering mislyktes. Ugyldig nettadresse." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Autentisering mislyktes. Brukernavnet «%s» eller oppgitt passord er feil." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Klienten er utestengt. Kontakt forfatteren." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Systemet har feil dato/klokkeslett. Innsending av låter kan mislykkes inntil " "du retter opp dette." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-innsending" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler-klient for Last.fm, Libre.fm og andre Audioscrobbler-" "tjenester." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Du er nå autentisert." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Tjeneste:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_Adresse:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Annet …" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Bekreft kontoinformasjon" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Artistmønster:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Tittelmønster:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Utelat _filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Mønster til formatering av artistnavn for innsending. La feltet stå tomt for " "å bruke standardmønster." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Mønster til formatering av tittel for innsending. La feltet stå tomt for å " "bruke standardmønster." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Låter som samsvarer med dette filteret blir ikke sendt inn" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Frakoblet modus (ikke send inn noe)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Innsending" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Demp radioreklame" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Slår av lyden når radiokanaler spiller reklame.\n" "Kanaler: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Omstokket albumavspilling" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Spiller av et tilfeldig album når du har spilt gjennom en spilleliste. Dette " "krever at gjeldende utforsker støtter filtrering på album." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Høyere vurdering" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Oftere spilt" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Oftere hoppet over" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Nyligere spilt" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Nyligere startet" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Nyligere lagt til" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Lengre album" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekunder før neste album begynner" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Vektinger" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Spill noen album oftere enn andre" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "unngå" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "foretrekk" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Tilfeldig album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Venter på å starte %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Vurderinger og statistikk for %d låter er nå importert" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox-importering" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importerer vurderinger og låtstatistikk fra Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pause ved skjermsparer" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Setter spilleren på pause når GNOME-skjermspareren er slått på." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Ingen GNOME Shell-søketilbyder for Quod Libet er installert." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME-søketilbyder" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Lar GNOME Shell søke i biblioteket." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternativ søkelinje" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "En alternativ søkelinje som alltid er synlig og fyller ut hele vinduets " "bredde." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Punkt-bokmerker" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Lagre søkepunkt A og/eller B per spor. Hopp til tidspunkt A og stopp etter B " "når du spiller av sporet.\n" "ℹ Ved å endre navn på punktene nedenfor endrer du bare hvilke bokmerkenavn " "tillegget søker etter. Faktiske bokmerkenavn blir ikke endret." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Bokmerkenavn på punkt A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Bokmerkenavn å søke etter (og hoppe til hvis det finnes) når et spor starter" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Bokmerkenavn på punkt B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Bokmerkenavn å bruke under avspilling hvis det finnes. Hvis gjeldende " "posisjon er etter tidsstempelet, hopper spilleren til slutten av sporet." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox-synk" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Speiler Quod Libet-utdata til Logitech Squeezebox, gitt at begge leser fra " "samme bibliotek." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Deler oppsett med <a href=\"%(plugin_link)s\">Squeezebox-eksporttillegg</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Fant ikke Squeezebox-tjener" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fant ikke %s. Kontroller oppsett" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Stopp ved pause" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Dette tillegget endrer «Pause» til «Stopp/Spill av/Søk».\n" "\n" "Nyttig hvis Quod Libet ikke klarer å reagere riktig når du kobler en ny " "lydenhet til systemet (Bluetooth-høyttaler, USB-DAC, e.l.).\n" "\n" "Hvis «Bare søkbare kilder» ikke er valgt, husker dette programtillegget " "posisjon i gjeldende kilde. Ellers stoppes avspilling, og du må starte på " "nytt fra begynnelsen." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Bare søkbare kilder" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Tilleggsvalg" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Kopiering venter" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Avventer sletting" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "slett" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Hopp over" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLIKAT" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Synkroniserer" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Sletter" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Vellykket" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "MISLYKKET" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Hoppet over eksisterende fil" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Klarte ikke å endre låt-filnavn." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Synkroniser til enhet" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "Synkroniserer alle låter fra valgte lagrede søk med valgt mappe." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synkroniser følgende lagrede søk:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Absolutt sti til eksportmappe" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Filer som allerede finnes i målmappa, men ikke i lagrede søk, blir slettet." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "For enheter montert med MTP eksporterer du til en lokal målmappe, og " "overfører den til enheten med rsync. Hvis du har mange filer å synkronisere " "til en Android enhet, kan du bruke adb-sync som går mye raskere." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Målsti:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Sti-mønstre" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Rediger lagrede mønstre …" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Struktur for eksporterte filnavn, basert på tagger" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Eksporteringsmønster:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Stopp forhåndsvisning" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Kildefil" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Eksportsti" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Oppdaget dupliserte eksporteringsstier. Du kan endre stiene overfor før du " "starter synkronisering." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Eksisterende filer i målmappa blir slettet, unntatt filer som heter 'cover." "jpg'!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Start synkronisering" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Stopp synkronisering" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "Ingen lagrede søk enda. Lag noen og kom tilbake!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Velg målsti" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Eksportsti endret fra [{old_path}] til [{new_path}] for fil [{filename}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Starter forhåndsvisning av synkronisering" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Synkroniseringsforhåndsvisning pågår." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Fullførte synkroniseringsforhåndsvisning" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Stopper synkroniseringsforhåndsvisning" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Synkroniseringsforhåndsvisning ble stoppet." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Synkroniseringsforhåndsvisning er ferdig." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Stoppet Synkroniseringsforhåndsvisning" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Et annet programtilleg ble oppdaget - stopp forhåndsvisning" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Synkroniseringsplan:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "forsøk å skrive {count} fil" msgstr[1] "forsøk å skrive {count} filer" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "hopp over {count} duplisert fil" msgstr[1] "hopp over {count} dupliserte filer" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "slett {count} fil" msgstr[1] "slett {count} filer" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Målsti ikke valgt" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Velg mappe som du vil eksportere låter til." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Eksportmønster ikke valgt" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Velg eksporteringsmønster for navn på eksporterte låter." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Eksportstien er ikke absolutt" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Mønsteret\n" "\n" "{}\n" "\n" "inneholder «/», men begynner ikke i rotmappe. For å unngå feilutformede " "mappenavn, må mønsteret begynne med «/» eller «~/»." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Ingen lagrede søk valgt" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Velg minst ett lagret søk." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Ingen spor i valgte lagrede søk" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Alle valgte lagrede søk er tomme." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Fant {} spor å synkronisere" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Målsti og eksportmønster er ikke i overensstemmelse" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Eksportmønsteret starter med en sti som er forskjellig fra målstien. Fiks " "mønsteret.\n" "\n" "Feil:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Synkronisering mislyktes" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Kan ikke starte synkronisering under <b>Status</b>-sortering." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Starter låtsynkronisering" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Synkronisering pågår." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Låtsynkronisering fullført" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Stopper låtsynkronisering" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Synkroniseringen ble stoppet." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Synkronisering fullført." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Låtsynkronisering stoppet" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Et annet tillegg ble valgt - stopp synkronisering" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - «{filename}»" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Fjerner «{}»" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Synkronisering har:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "skrev {count}/{total} fil" msgstr[1] "skrev {count}/{total} filer" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(hoppet over {count} eksisterende fil)" msgstr[1] "(hoppet over {count} eksisterende filer)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "hoppet over {count}/{total} duplisert fil" msgstr[1] "hoppet over {count}/{total} dupliserte filer" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "slettet {count}/{total} fil" msgstr[1] "slettet {count}/{total} filer" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "klarte ikke å synkronisere {count} fil" msgstr[1] "klarte ikke å synkronisere {count} filer" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "hoppet over {count} tidligere synkronisert fil" msgstr[1] "hoppet over {count} tidligere synkroniserte filer" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synkronisert sangtekst" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Viser synkronisert sangtekst fra en «.lrc»-fil som har samme navn som et " "spor (eller lignende)." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Bakgrunn:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Skrifttype" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Størrelse (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy-statusmeldinger" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Oppdaterer alle Telepathy-baserte direktemeldingskontoer (som er satt opp i " "Empathy o.l.) med statusmelding basert på låta du spiller av." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Spiller:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Statustekst når du starter en låt. Godtar QL-mønstre som f.eks. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Pauset:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Statustekst når du setter en låt på pause. Godtar QL-mønstre som f.eks. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Ren tekst når du ikke spiller av en låt" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Ingen låt:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Statusmønstre" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Temaveksler" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Endrer gjeldende GTK+-tema." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Forvalgt tema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Foretrekk mørk temaversjon" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Tommelvurdering" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Legger til poengsystem med tommel opp eller ned, som så konverteres til en " "vurdering. Nyttig for å holde rede på stemmeantall og sortering med " "<b><tt>~#score</tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Slå på/av menylinje" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Slå på/av menylinja ved å trykke Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Spiller ikke av" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Systemkurv-ikon" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Kontrollerer Quod Libet fra systemkurven." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Vis %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "S_pill av" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Forrige" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Neste" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Stokk om" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Gjenta" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Stopp _etter denne låta" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Åpne _utforsker" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Rediger _tagger" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informasjon" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Spille_lister" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Avslutt" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Oppførsel" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Rullehjul stiller inn volum" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Rullehjul bytter låt" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Rulle_hjul" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Vis hjelpebobler" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Vis sangtekst" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Viser sangtekster på en sidelinje basert på tagg eller fil." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Fant ingen sangtekst for\n" "%s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Ingen spillende låt" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Start visualisering" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Start ekstern visualisering." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Klarte ikke å kjøre visualisering med «%s»" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Feil" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Kjørbart visualiseringsprogram:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Last inn på nytt" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Lydbølge-søkelinje" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ Søkelinje som former seg etter lydbølger av spillende låt." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Overstyr forgrunnsfarge:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Overstyr farge ved peking:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Overstyr farge for gjenstående tid:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Vis gjeldende posisjon" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Vis tidstagger" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Blafringsmengde under rulling (millisekunder):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Bildelagring" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Lagrer omslagsbilde for gjeldende låt i en fil." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Fil:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Terskel:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Terskel for når filteret slår seg på" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "For_hold:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Komprimeringsforhold" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Lydkompressor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Endrer lydstyrke på alle lyder med styrke over en gitt terskel men et gitt " "komprimeringsforhold." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Forvalg:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filteroppsett" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frekvensterskel:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Kappefrekvens for lavpass-filter" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Innmatings_nivå:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Innmatingsnivå" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Standard" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Nærmest virtuell høyttalerplassering (30°, 3 meter)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Nærme Chu Moys «crossfeeder» (populært)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Nærme Jan Meiers CORDA-forsterkere (liten endring)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Selvvalgt" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Selvvalgte innstillinger" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Kryssmating" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Blander lyd fra venstre og høyre kanal for f.eks. å simulere et " "høyttaleroppsett ved bruk av hodetelefoner, eller for å kompensere for " "tidlige stereo-innspillinger." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filtrer _band:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Filterets frekvensbånd" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filtrer _bredde:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Filterets frekvensvidde" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "Ni_vå:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Effektnivå" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Fjerner hovedvokal fra lyd." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono-nedmiks" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Mikser ned flere lydkanaler til mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "Fr_ekvens:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Tonehøyde:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Tonehøyde / hastighet" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Styrer tonehøyde på lydstrøm." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Eksporter spilleliste til mappe" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Eksporter" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Målmappe:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "_Filnavn-mønster:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Eksporterer en spilleliste ved å kopiere filer til en mappe." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Klarte ikke å eksportere spilleliste" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Sjekk at du har skrivetilgang til målet." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "_Forvalgt filnavn-mønster:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Skriv et nytt spillelistenavn,\n" "eller velg en eksisterende Sonos-spilleliste å overskrive" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Eksporter som Sonos-spilleliste" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Eksporterer en spilleliste ved å kopiere filer til en mappe." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Finner ikke Sonos-enhet(er)" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Finner ikke Sonos. Sjekk oppsettet ditt" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Eksporter til Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Eksporterer en spilleliste til Sonos-format, gitt at både deling og " "mappestruktur finnes." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Deler oppsett med <a href=\"%(plugin_link)s\">Sqeezebox Sync-tillegg</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Eksporter spilleliste til Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Spillelistenavn (overskriver gjeldende navn)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Eksporter til Squeezebox-spilleliste" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Fjern duplikater fra spilleliste" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Fjerner duplikater fra spillelister." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Er du sikker på at du hvis fjerne %d duplikat?" msgstr[1] "Er du sikker på at du hvis fjerne %d duplikater?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplikatlåter blir fjernet fra spillelista «%s»." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Stokk om spilleliste" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Stokker om låter i en spilleliste." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Følg peker" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Legger til en rekkefølgemodus som følger utvalget ditt, og deretter neste " "låt på lista." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Følg peker" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Følg peker" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Avspillingsutjevner" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Legger til en omstokkingsmodus som foretrekker låter som er blitt spilt av " "færrest antall ganger." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Foretrekk låter med færre avspillinger" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Foretrekk _færre avspillinger" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Bare kø" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Begrenser avspilling til låter som ligger i kø.\n" "\n" "Når denne avspillingsrekkefølgen er valgt i hovedvinduet blir låter lagt i " "kø ved dobbeltklikk i stedet for å bli spilt av direkte." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Bare kø" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "_Bare kø" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Begynn avspilling automatisk når spor dobbeltklikkes" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Omvendt" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Legger til en omstokkingsmodus som spiller av album og lister i motsatt " "rekkefølge." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Omvendt rekkefølge" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Stokk om per gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Stokker om per gruppering, definert av en felles tagg, i stedet for å stokke " "om per låt. Dette minner om album-stokking.\n" "\n" "Dette kan være nyttig når du vil stokke om f.eks. klassiske stykker og " "samtidig være sikker på at du spiller av alle partiene i korrekt rekkefølge " "før neste stykke." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Stokk om per gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "Stokk om etter gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Venter på å starte ny gruppe …" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Grupperingstagg:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Tagg som låter skal grupperes på" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filtertagg:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Gruppering blir bare brukt hvis filter-taggen er utfylt.\n" "Låter med tomme filtertagger blir behandlet\n" "separat. Filter-taggen bør typisk samsvare med\n" "grupperingstaggen." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Forsinkelse:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Forsinkelse (i sekunder) før neste gruppe skal startes" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Tilbakestill til forvalg" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Hopp over mislikte spor" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Legger til en omstokkingsmodus som spiller av låter i riktig rekkefølge, men " "som hopper over spor med vurdering som er lik eller lavere enn valgt terskel." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Hopp over mislikte spor" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Hopp over _mislikte spor" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Gjenta hvert spor" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Legger til en omstokkingsmodus som spiller av spor i riktig rekkefølge, men " "som gjentar hvert spor valgt antall ganger." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Gjenta hvert spor" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "Gjenta _hvert spor" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Antall avspillinger per låt:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Betinget spørring" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Velger spørring å samsvare med basert på en betingelsesspørring." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: betingelses-spørring, deretter-spørring, ellers-spørring)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Spørring mangler" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Finner låter som ikke inneholder valgt tagg." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Inkluder tomme tagger" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python-spørring" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Bruk Python-uttrykk i spørringer." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: uttrykk)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Variabelen <tt>s</tt> eller <tt>a</tt> er låt / album som skal samsvare.\n" "\n" "<tt>_ts</tt> er et (ekte numerisk) tidsstempel i begynnelsen av en " "spørring.\n" "\n" "Modulene <tt>time</tt> (tid) og <tt>random</tt> (vilkårlig) er også " "tilgjengelige, i tillegg til klassen <tt>Random</tt> (==<tt>random.Random</" "tt>)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Ta med lagret søk" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 Ta med søketreff fra lagret søk som del av en annen spørring." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(lagret: søkenavn)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unik" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Bruker eneste spiller (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Klarte ikke å koble til %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Vertsnavn:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Brukernavn:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Passord:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Bibliotekmappe som tjener kobler til" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Bibliotek-sti:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Kontroller oppsett" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox-tjener" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Feilsøk" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-tjener på {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "ukjent Squeezebox-tjener" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "ukjent Squeezebox-spiller: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Velg Squeezebox-spiller" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Fant Squeezebox-tjener.\n" "Velg spiller" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Tilpass bilde til _vindu" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "Se oppsettsvalg «[plugins] cover_filenames» for bildenavn-strenger" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Rediger bilde etter lagring" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Fil_navn:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Lagring mislyktes" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Klarte ikke å lagre «%s»." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-feil: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Nedlastingsverktøy for omslag" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "fra %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Oppløsning: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Størrelse: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Grense for antall «at best» (i beste fall)-resultater" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Søk" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Søker …" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Ferdig" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Last ned album-omslag" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Last ned omslagsbilder fra diverse nettsteder." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Kilder" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 til ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Konverterer APEv2-tagger til ID3v2. APEv2-tagger blir slettet etter " "konvertering." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Gå til bokmerke" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Håndterer bokmerker i valgte filer." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "R_ediger bokmerker …" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Ingen bokmerker" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-oppslag" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Tagger album på nytt basert på MusicBrainz-oppslag." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Bare bruk år i «date»-tagg" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Skriv «_albumartist» hvis nødvendig" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Skriv sorteringstagger for artistnavn" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Skriv _standard MusicBrainz-tagger" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Skriv «labelid»-tagg" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Filnavn" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Plate" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Spor" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Tittel" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artist" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz-oppslag" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Spørring:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "S_øk" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Treff <i>(dra for å endre rekkefølge)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Skriv inn en spørring." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Det oppstod en feil. Prøv på nytt." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Laster inn treff …" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Søket ga ingen treff." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python-konsoll" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktiv Python-konsoll. Åpner et nytt vindu." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} for {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python-konsollsidelinje" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Interaktiv Python-konsollsidelinje som følger valgte låter i hovedvindu." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Du kan bruke følgende objekter som standard:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Gjeldende arbeidsmappe er:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Fullføring" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Last ned omslag" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Laster ned album-omslag i høy kvalitet ved hjelp av Quod Libet-tillegg for " "omslagsbilder." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klassisk" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Stor" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Last ned omslagsbilde" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Laster inn %(source)s - %(dimensions)s …" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Fant ingenting om:\n" "%(albums)s.\n" "\n" "Søket ble utført med:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Fant ingen omslag" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Forhåndsvis størrelse" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Lagre mål" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Hvis bildet ikke allerede er i JPEG-format, konverter ttil høykvalitets-JPEG " "av samme størrelse" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Lagre som JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Kommando" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "navn" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Navn på denne kommandoen" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "kommando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Skallkommando-syntaks som skal kjøres" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parameter" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Hvis dette er valgt, blir en parameter i kommandoen erstattet med selvvalgt " "verdi. For eksempel: bruk «PARAM» for å bli bedt om verdier for alle " "forekomster av «{PARAM}» i en kommando" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL-mønster - f.eks. <~filnavn> - som skal brukes til å beregne en verdi for " "kommandoen. Dette støtter også bruk av taggene <~playlistname> og " "<~#playlistindex> for spillelister." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unik" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Hvis dette er valgt, blir duplikatverdier som mønsteret fører til fjernet" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "maks argumenter" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Maksimalt antall argumenter som kan sendes til kommandoen om gangen (likner " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "reverser" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Hvis dette er valgt, blir argumentlista brukt i omvendt rekkefølge" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Inndataverdi" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Verdi for %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Selvvalgte kommandoer" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Kjører selvvalgte kommandoer (buntvis hvis påkrevet) på låter som bruker " "valgt(e) tagg(er)." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Rediger selvvalgte kommandoer" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Klarte ikke å kjøre selvvalgt kommando %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplikatgruppe" msgstr[1] "%d duplikatgrupper" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Fold sammen / Utvid alle" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Uttrykk for duplikatnøkkel er «%s»" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Dupliserer utforsker" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "FInner og viser låtversjoner med liknende tagger." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Godtar QL-tagguttrykk som <tt>~artist~title</tt> eller " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Grupper duplikater etter:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplikatnøkkel" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Fjern _blanktegn" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Fjern _diakritikk" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Fjern _tegnsetting" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Ignorer små/store bokstaver" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Søkevalg" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Rediger antall avspillinger" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Rediger <tt>~#playcount</tt> og <tt>~#skipcount</tt> for en låt.\n" "\n" "Antall blir økt - ikke endret - hvis flere låter er valgt.\n" "\n" "Hvis du endrer <tt>~#playcount</tt> til 0, blir <tt>~#lastplayed</tt> og " "<tt>~#laststarted</tt> tømt. Hvis du endrer den fra 0 til et positivt tall, " "får ingen av disse noen verdi." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Antall avspillinger" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Antall ganger hoppet over" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Flere filer valgt." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Antall blir økt." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Rediger innebygde bilder" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Legger til, fjerner eller erstatter innebygde bilder." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Innebygg" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Velg bilde å bygge inn i %d-sporet" msgstr[1] "Velg bilde å bygge inn i %d-sporene" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Fjern alle bilder" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Bygg inn gjeldende bilde" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Velg bilde …" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Endre nøyaktig vurdering" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Tillater endring av låtvurderinger med tallverdier." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Skriv inn en vurderingsverdi mellom 0.0 og 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrer etter hvilken som helst tagg" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Lager søkespørring basert på tagger for valgte låter." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrer etter mappe" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtrerer på mappe i nytt utforskervindu." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akustisk fingeravtrykk-søk" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Slår opp låt-metadata ved hjelp av akustisk fingeravtrykk." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Send inn akustiske fingeravtrykk" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Lager akustiske fingeravtrykk ved hjelp av chromaprint og sender dem inn til " "acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API-nøkkel mangler" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Du må legge inn API-nøkkel for acoustid.org i tilleggsoppsettet for å sende " "inn fingeravtrykk." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Be om API-nøkkel" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API-_nøkkel:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID-nettjeneste" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "I kø" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analyserer" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Oppslag" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Skriv" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Utgivelse" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Skriv MusicBrainz-tagger" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Grupper etter mappe" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Albummodus" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "SKriver album-relaterte tagger og prøver å redusere antall ulike " "albumutgivelser" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Lager fingeravtrykk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detaljer" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Send inn" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Låter enten ha taggen <i><b>musicbrainz_trackid</b></i> eller taggene " "<i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i> for å bli " "sendt inn." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Fingeravtrykk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Låter med MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Låter med tilstrekkelig taggdata:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Låter å sende inn:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Ferdig. %(to-send)d/%(all)d låter å sende inn." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Sender inn fingeravtrykk:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Sender inn …" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Oppdater tagger i filer" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Oppdater endrede tagger i filer. Dette holder avspillingsstatistikk og " "vurderinger oppdatert." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Eksporter til HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Eksporterer valgt låtliste i HTML-format." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Send til iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Last opp låter til iRiver iFP-enhet." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Fant ingen iFP-enhet" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Klarte ikke å kontakte iFP-enhet. Kontroller at enheten er slått på, koblet " "til og at du har rett ifp-driver installert (se http://ifp-driver.sf.net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Laster opp %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "Klarte ikke å laste opp %s. Enheten kan være full eller slått av." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Feil under opplasting" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Eksporter brukerdata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Eksporter tagger" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Eksporter tagger og brukerdata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Eksporter filstammer og brukerdata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Eksporter filstamme og tagger" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Eksporter filstammer, tagger, og brukerdata" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Import/eksport" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Importerer og eksporterer tagger og spor-brukerdata." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Mer informasjon" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Begrepet «spor-brukerdata» inkluderer spillelister de valgte sporene er i og " "følgende metadata:\n" "\n" "%s\n" "\n" "Merk at alt du velger å eksportere blir importert. Hvis du eksporterte " "filstammer (filer uten etternavn), får valgte filer nye navn ved " "importering.\n" "\n" "Etter eksport av album kan du importere data inn i en annen versjon av " "albumet. Rekkefølge og antall spor kan være forskjellige. Tillegget " "sammenstiller eksportert data med nye spor, selv hvis navnene på sporene er " "litt ulike. Automatisk sammenstilling gir ikke alltid korrekt resultat, så " "det er bedre å ikke redusere disse likhetsverdiene for mye." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Brukerinteraksjon ved import" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Krev bekreftelse hvis antall spor ikke samsvarer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Krev bekreftelse hvis antall album ikke samsvarer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Nedre prosentgrense før bruker manuelt må sjekke og alternativt endre hvilke " "spor som hører sammen." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Spor-sammenlignbarhet:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Album-likhet:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Eksporter filer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Skriv skjønn og ren JSON (tregere)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Slett eksportfiler etter at de har blitt importert" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importer" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Åpne eksporteringsmappe" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Plater" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Spor" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artist(er)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Stiens ende" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Sammenstill album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Fortsett" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Ingenting å importere" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Du må eksportere noe før du kan importere." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Indeksen var korrupt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "Klarte ikke å tolke JSON i %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Klarte ikke å lese %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Filnavn" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Sammenstill spor" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Oppdaterer liste." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Allerede oppdatert." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Henter ukeliste for %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synk utført." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Feil under synkronisering (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm-synk" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Oppdaterer bibliotekstatistikk med data fra Last.fm-profil." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Br_ukernavn:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Lag sorteringstagger" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Konverterer album- og artistnavn til sorteringsnavn, på enkelt vis." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Eksporter som M3U-/PLS-spillelistefil" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksporterer låter til M3U- eller PLS-spilleliste." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Bruk relative filstier" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Bruk fullstendige filstier" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "Skriving til %s mislyktes." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Søk gjennom låter på nytt" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Ser etter filendringer, og fjerner eller laster inn låter på nytt hvis " "nødvendig." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Søk gjennom låter på nytt" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analyseringsverktøy" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Spor" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Framdrift" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Forsterkning" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Maksverdi" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "%(to-process)s album skal oppdateres (av %(all)s)" msgstr[1] "%(to-process)s album skal oppdateres (av %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyserer og oppdaterer <a href=\"%(rg_link)s\">ReplayGain</a>-informasjon " "ved hjelp av GStreamer. Resultater blir gruppert per album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "alltid" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "hvis <b>hvilken som helst</b> RG-tagg mangler" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "hvis <b>album</b>-RG-tagg mangler" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Behandle album:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Gjeldende tagger" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Splitt tagger" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Skiller platenummer fra albumnavn og samtidig versjon fra tittel." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Del opp album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Trekk ut platenummer." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "i/t" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Tilbakestill" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Trykk" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Beregn BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Trykk i takt og finn BPM for valgt låt." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Nettsted-søk" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Søker på valgt nettside med tagger.\n" "Støtter mønstre som f.eks. «%(pattern)s»." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Søk i adressemønstre" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Rediger søkeadresser" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Sett opp søk …" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Søk etter tagg på Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Åpner nettleservindu med Wikipedia-artikkel om det som står i taggen for " "valgt låt." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Søk på %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Rediger tagger" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Søk mislyktes" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Fant ikke tagg «%s»." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliotek" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Kontrollerer monteringspunkter" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Søker gjennom bibliotek" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Søker gjennom %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Laster inn filer" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Flytter bibliotekfiler" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Fjerner bibliotekfiler" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Legger til overvåkning av %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "Fant ingen biblioteklåter i gammel-formatert spilleliste %(filename)r (med " "størrelse %(size).1f kB)." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "Har du endret rotmappe(r) for biblioteket, men ikke denne spillelista?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "Klarte ikke å konvertere %d spilleliste" msgstr[1] "Klarte ikke å konvertere %d spillelister" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Musikkavspiller og bibliotekbehandler" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Klarte ikke å laste inn fil: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Vis tagger" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Skriv ut kortfattet info" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Kolonner som skal vises og sortering i kortfattet modus (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Vis programmatiske tagger" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Argument(er) mangler" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "For mange argumenter" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Beskrivelse" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Verdi" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Vis alle fellestagger" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopier tagger fra en fil til en annen" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Vis endringer, men ikke lagre dem" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Hopp over tagger som ikke kan skrives" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Klarte ikke å kopiere tagg {tagname} til fil: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Rediger tagger med tekstbehandler" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Redigering avbrutt" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Oppstart av tekstbehadnler «%(editor-name)s» mislyktes." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Fant ingen endringer" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Endre tagg og fjern gjeldende verdier" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Klarte ikke å endre %(tag)r for %(format)s-fil %(file)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Fjern tagger" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Verdien er et regulært uttrykk" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Fjern alle tagger" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Du kan ikke bruke «--all» og «--regexp» samtidig" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Klarte ikke å fjerne {tagname} fra {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Fjern taggverdi" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Legg til taggverdi" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Klarte ikke å endre %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Vis filinformasjon" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Bruk gjeldende bilde som primært innebygd bilde, og fjern alle andre " "innebygde bilder" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Klarte ikke å laste inn bildefil: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "Bilderedigering støttes ikke for %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Fjern alle innebygde bilder" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Pakk ut innebygde bilder i %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Sti hvor bilder skal lagres (standard er gjeldende arbeidsmappe)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Gi filer nytt navn basert på tagger" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Fyll ut tagger basert på filsti" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fil" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Fyll ut spornummer for alle filer" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Skriv tagger basert på valgt mønster" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Vis hjelpetekst" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "«%(column-id)s» er et ugyldig kolonnenavn (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Ukjent" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "I rekkefølge" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_I rekkefølge" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Tilfeldig" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Tilfeldig" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Foretrekk låter med høy vurderingskarakter" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Foretrekk _høyere vurdering" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Gjenta gjeldende spor" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Gjenta _dette sporet" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Gjenta alle" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Gjenta _alle" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Én låt" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Én _låt" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Strøm" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Bygger mellomlager" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Klarte ikke å lage GStreamer-datarør (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Fant ingen GStreamer-element som kan håndtere gjeldende medieformat" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Medieformat: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Klarte ikke å laste inn GStreamer-tillegg «%(name)s»" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStramer-utdatarør som skal brukes til avspilling. La dette stå tomt for å " "bruke forvalgt datarør. Hvis datarøret inneholder en utgang, blir denne " "brukt i stedet for forvalgt utgang." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Utdatarør:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Mellomlagringstid:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Slå av _sømløs avspilling" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Slå av sømløs avspilling for å omgå problemer som oppstår med enkelte " "versjoner av GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Bruk JACK for avspilling hvis det forefinnes" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Bruker «jackaudiosink» som avspillingsutgang hvis den finnes" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Koble til automatisk til JACK-utgangsenheter" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Ber «jackaudiosink» om å koble til automatisk" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Fant ingen GStreamer-lydutgang. Prøvde: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Ugyldig GStreamer-utdatarør" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Klarte ikke å sende ut lyd" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "Fant ikke lydenhet %r. Kontroller Xine-oppsett i ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Fant ikke modul «{module}». Har du installert den?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Fant ikke GStreamer-element «{element}»." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Besøk Tillegg-vinduet for å sette opp ListenBrainz. Ingen låter blir sendt " "inn før du gjør dette." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "For mange feilaktige innsendingsforsøk på rad (%d). Bruker frakoblet modus. " "Besøk Tillegg-vinduet for å tilbakestille ListenBrainz. I mellomtiden blir " "lyttinger ikke sendt inn." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz-innsending" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Send inn lyttinger til ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Bruker_symbol:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "E_tiketter:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Liste over tagger som skal sendes inn, adskilt med komma. Bruk doble " "sitattegn hvis nødvendig." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Låter som samsvarer med dette filteret blir ikke sendt inn." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Vil du kjøre tillegget «%(name)s» på %(count)s spilleliste?" msgstr[1] "Vil du kjøre tillegget «%(name)s» på %(count)s spillelister?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Kjør tillegg" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Bruk" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Begynnelse" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "I.T" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tid" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Bokmerkenavn" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Bokmerker" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtre" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Sist s_pilt" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Sist lagt til" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 på _topp" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Alle _låter" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "På gjeldende _sjanger(e)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "På gjeldende _artist(er)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "På gjeldende al_bum" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Tilfeldig _sjanger" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Tilfeldig _artist" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Tilfeldig al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "De 40 mest spilte låtene i biblioteket (det kan dukke opp flere enn 40 hvis " "ulike låter er blitt spilt av like mange ganger)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Navn:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Verdi:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Lagrede verdier" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Rediger lagrede verdier …" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matisk" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Spormodus" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albummodus" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Demp" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain-modus" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Ny %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(ukjent)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Legg til …" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "R_ediger" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Tagguttrykk" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tagguttrykk, som f.eks. «people:real» «~album~year»" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Skriv inn ny tagg" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Rediger tagguttrykk" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Filer:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Valgte låter blir fjernet fra biblioteket og slettet fra lagringsenheten de " "ligger på." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Valgte filer blir slettet for godt." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Er du sikker på at du vil slette %(file_count)d fil for godt?" msgstr[1] "Er du sikker på at du vil slette %(file_count)d filer for godt?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Sle_tt filer" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Valgte låter blir fjernet fra biblioteket og lagt i papirkurven for " "lagringsenheten de ligger på." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Valgte filer blir flyttet til papirkurv." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Vil du legge %(file_count)d fil i papirkurv?" msgstr[1] "Vil du legge %(file_count)d filer i papirkurv?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Flytt til papirkurv" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Flytter %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Klarte ikke å flytte til papirkurv" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Flytting av én eller flere filer til papirkurv mislyktes." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Sletter %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Klarte ikke å slette filer" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Sletting av én eller flere filer mislyktes." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Utforsker" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Laster ned filer" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "mangler i %d låt" msgstr[1] "mangler i %d låter" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "ulikt i %d låt" msgstr[1] "ulikt i %d låter" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Del opp i _flere verdier" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Trekk platenummer ut av _album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Trekk _versjon ut av tittel" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Trekk arrangør ut av ar_tist" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Trekk _utøver ut av artist" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Trekk _utøver ut av tittel" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Trekk _originalartist ut av tittel" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Legg til tagg" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tagg:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Vis programmatiske tagger" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Se alle tagger, inkludert maskingenererte som f.eks. MusicBrainz- eller " "Replay Gain-tagger" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Vis tagger med flere linjer" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" "Vis tagger som muligvis går over flere linjer (f.eks. «sangtekster») her også" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Tilbakestill" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Lagre" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Sett opp" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Splitt tagger" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "Kopier _verdi(er)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Klarte ikke å legge til tagg" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "Klarte ikke å legge til %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Valgte filer støtter ikke flere enn én verdi for %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Ugyldig tagg" msgstr[1] "Ugyldige tagger" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "%s er en ugyldig tagg\n" "\n" "Valgte filer støtter ikke redigering av denne taggen." msgstr[1] "" "%s er en ugyldig tagg\n" "\n" "Valgte filer støtter ikke redigering av denne taggen." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Ugyldig verdi" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Verdien %(value)s er ugyldig\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Taggen er kanskje ikke nøyaktig" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s ble endret mens programmet kjørte. Hvis du lagrer uten å " "oppdatere biblioteket, kan du overskrive andre endringer som er utført i " "mellomtiden." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Klarte ikke å lagre låt" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Lagring av %(file-name)s mislyktes. Fila kan være skrivebeskyttet, ødelagt, " "eller du mangler tillatelser til å endre den." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Flere valg …" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Angre" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Gjør om" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "O_m" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Se etter oppdateringer …" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Tillegg" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s og %(count)s annen" msgstr[1] "%(title)s og %(count)s andre" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso-innstillinger" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mapper" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Ny mappe …" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Velg alle undermapper" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Ny mappe" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Skriv inn navn på ny mappe:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Klarte ikke å lage mappe" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Klarte ikke å slette mappe" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Låter" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "av %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Plate %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Spor %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Gjeldende _låt" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "R_ediger visning …" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ingen låter er valgt." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Ingen låter" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informasjon" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Sangtekst" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produsert av %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artist" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artister" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "utøvere" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Aldri" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d gang" msgstr[1] "%(n)d ganger" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "lagt til" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "sist spilt" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "avspillinger" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "hoppet over" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "vurdering" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "sti" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "varighet" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "koding" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitfrekvens" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "filstørrelse" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "endret" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Tillegg" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valgt" msgstr[1] "%d valgte" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Spor utilgjengelig" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d låt uten album" msgstr[1] "%d låter uten album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Valgt diskografi" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d låt uten artist" msgstr[1] "%d låter uten artist" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Total varighet:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Total størrelse:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Filer" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Vis på nett" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Fant ingen sangtekst for denne låta." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Er du sikker på at du vil fjerne alle låter?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Valgte låter blir fjernet fra biblioteket." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Vis" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Vis" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Sjekk om kolonner på venstre side omtrentlig samsvarer med høyre side. Hvis " "ikke, kan du endre rekkefølgen her. (Bruk «_» for rader som ikke skal " "knyttes sammen):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Rekkefølge på høyre side:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Vil du forkaste taggendringer?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tagger er endret, men ikke lagret. Vil du lagre filene, eller tilbakestille " "og forkaste alle endringer?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Tilbakestill" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Fila finnes" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Vil du erstatte %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Erstatt fil" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Pågående oppgaver" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d kjørende oppgaver" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Slå av/på omstokket rekkefølge" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Slå av/på gjentakelse" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Hendelser" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Avspillingsrekkefølge" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Redigering" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Navnendring" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Spørring" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Omslag" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Programtillegg-feil" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Enhver tilstand" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Slått på" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Slått av" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Ingen kategori" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Enhver kategori" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Fant ingen tillegg." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Tillegg" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrer etter tilstand / tagg" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrer etter type" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrer etter navn eller beskrivelse" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Vis _feil" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Plate" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Spor" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Gru_ppering" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artist" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Filnavn" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Varighet" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Hopp til spillende låt automatisk" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Hopp til gjeldende spor i låtliste ved låtbytte" #: quodlibet/qltk/prefs.py:72 #, fuzzy msgid "_Sort songs when tags are modified" msgstr "Sorter spor når du endrer tagger" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "Automatisk omorganisering av låter i låtlista når du endrer tagger" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Annet:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "R_ediger …" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Legg til eller fjern tilleggskolonner" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Synlige kolonner" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Tittel inkluderer _versjon" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album inneholder _plate-undertittel" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Artist inneholder alle _personer" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Filnavn inneholder _mappe" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Kolonneoppsett" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Rediger kolonner" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "Bruk gjeldende oppsett på låtliste, og legg til nye kolonner i slutten" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Låtliste" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Rediger kolonner" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Total varighet" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globalt filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Bruk denne spørringa i tillegg til andre" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Søk" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Utforskere" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Bekreft _multi-vurdering" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Be bruker om å bekrefte endring av vurderingskarakter for flere låter " "samtidig" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Slå på _énklikksvurdering" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Slå på vurdering ved å trykke på vurderingskolonnen i låtlista" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Vurderinger" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Foretrekk _innebygd omslag" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "Foretrekk omslagsbilder som er innebygd i lydfiler" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Album-omslagsfil(er) å bruke, når tilgjengelig (støtter jokertegn). Hvis du " "vil legge inn flere enn én fil, holder du dem adskilt med komma." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Foretrukket bildefilnavn:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumomslag" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Avspilling" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Utdata-oppsett" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Juster volum med denne verdien på låter som ikke har Replay Gain-informasjon" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Tilbakefall:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Juster volum med denne verdien på alle låter, så lenge det ikke fører til " "forvregning" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Forforsterkning:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Slå på Replay Gain-volumjustering" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain-volumjustering" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Gjenoppta avspilling ved oppstart" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Hvis du hører på musikk mens du slår av systemet, fortsetter den der du " "slapp ved oppstart" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Forvalgt vurdering:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Vurderings_skala:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesisk gjennomsnittsfaktor (C) for sammenstilte vurderinger.\n" "0 betyr typisk gjennomsnitt, og høyere verdier betyr at album med færre spor " "får mindre ekstreme vurderinger. Alle album får ny kalkulert vurdering hvis " "du endrer denne verdien." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesisk gjennomsnittsmengde:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-post:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Vurderinger og antall avspillinger blir tagget og knyttet til denne e-" "postadressen" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "Lagre taggendringer _automatisk" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Lagre endringer av tagger uten å be om bekreftelse ved endring av flere filer" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Liste over skilletegn som skal brukes ved oppdeling av taggverdier. Selve " "lista bruker mellomrom som skilletegn." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Del opp _tagg på:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Liste over skilletegn som skal brukes ved oppdeling av taggverdier i " "redigereren. Selve lista bruker mellomrom som skilletegn og hver oppføring " "må inneholde to tegn." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Del opp _undertagg på:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tagger" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Taggredigering" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Ser etter nye vurderinger" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Søk gjennom bibliotek" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Se etter endringer i biblioteket" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "_Bygg bibliotek på nytt" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Laster inn hele biblioteket på nytt (dette kan ta lang tid)." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Skjulte låter" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Søk gjennom bibliotek ved _oppstart" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "_Se etter endringer i mapper" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "Følg med på nye, slettede og omdøpte filer i bibliotekmapper." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Søk gjennom mapper" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s og %(count)d annen" msgstr[1] "%(title)s og %(count)d andre" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Egenskaper" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Kø" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Tøm kø" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Skru av kø - køen blir ignorert under avspilling" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Skiftende" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Fjern spor fra kø etter avspilling" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Vedvarende" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Behold spor i kø etter avspilling" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modus" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Stopp ved køslut" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d låt (%(time)s)" msgstr[1] "%(count)d låter (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Utforsk bibliotek" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Vis/skjul kø" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Avspillingsfeil" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Vil du velge bibliotekmapper?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Du har ikke satt opp et musikkbibliotek. Vil du gjøre det nå?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Ikke nå" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Sett opp" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Klarte ikke å legge til låter" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s bruker en ustøttet protokoll." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Hopp til spillende låt" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Fil" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Låter" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Visning" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Bla gjennom" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Kontroll" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Hjelp" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Legg til mappe …" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Legg til fil …" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Legg til plassering …" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Rediger bokmerker …" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Stopp" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Stopp etter denne låta" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Tastatursnarveier" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Hjelp på nett" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Søk etter hjelp" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Legg til plassering" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Skriv inn plassering til en lydfil:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Klarte ikke å legge til plassering" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s er en ugyldig plassering." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Legg til musikk" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Legg til mapper" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Musikkfiler" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Legg til filer" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Er du sikker på at du vil legge %d låt i kø?" msgstr[1] "Er du sikker på at du vil legge %d låter i kø?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Legg i kø" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Er du sikker på at du vil endre vurdering av %d låter?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Gjeldende vurderinger blir fjernet" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Fjern vurdering" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Vurdering av valgte låter blir endret til %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Fjern _vurdering" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Erstatt mellomrom med _understrek" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Erstatt [semi]kolon-oppdeling med bindestrek" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "f.eks. «iv: allegro.flac» → «iv - allegro.flac»" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Fjern tegn som ikke søttes av _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Fjern diakritiske merker" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Fjern tegn som ikke er en del av _ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Bare bruk _små bokstaver" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Endre filnavn" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Forhåndsvisning" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Filnavn" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Flytt albumomslag" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Se oppsettsvalg «[albumart] filenames» for bilde-søkestrenger" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Overskriv albumomslag ved mål" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Fjern tomme mapper" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Albumomslag" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nytt navn" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Klarte ikke å endre filnavn" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Endring av navn fra %(old-name)s til %(new-name)s mislyktes. Målfila finnes " "allerede, eller du mangler tillatelser til å enten lage ny eller fjerne " "gammel fil." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorer _alle feil" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stopp" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Fortsett" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Stien er ikke absolutt" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Mønsteret\n" "\t%s\n" "inneholder «/», men starter ikke fra rotmappe. For å unngå feilutformede " "mappenavn må mønsteret begynne med «/» eller «~/»." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Låter som ligger i disse mappene blir lagt til når du oppdaterer biblioteket" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Ny mappe blir gjennomsøkt etter at du legger den til" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Alle låter i valgte mapper blir også fjernet fra biblioteket" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Flytt" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Flytt en rotmappe for skanning (men ikke filene). Dette flytter metadata for " "alle inkluderte spor." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Vil du fjerne {dir!r} og alle spor i den?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Vil du fjerne {n} bibliotekstier og sporene i dem?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Fjern bibliotek-sti?" msgstr[1] "Fjern bibliotek-stier?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Fjern" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Velg mapper" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Velg denne mappa" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Velg faktisk/ny mappe for {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Dette flytter Quod Libet-metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "Selve lydfilene blir ikke flyttet.\n" "Uansett anbefaler vi at du tar en sikkerhetskopi (inkludert «songs»-fila fra " "Quod Libet)" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Vil du flytte rotmappe for skanning {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "Ja, flytt den!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Lagrede søk" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Rediger lagrede søk …" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Søk i bibliotek ved bruk av fritekst eller QL-spørringer" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Søk e_tter skriving" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Vil søketreff når bruker slutter å skrive" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Grense:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Vekting" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Legg til spørring" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Legg til en QL-spørring eller fritekst, adskilt med «&»" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Vis gjenstående tid" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hovedvindu" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Hopp 10 sekunder bakover" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Hopp 10 sekunder framover" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Fokuser på søkefelt" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Tilbakestill filtre og hopp til spillende låt" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Åpne informasjonsvindu for valgte låter" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Åpne taggbehandler for valgte låter" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Legg valgte låter i kø" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Slett valgte låter" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Vis søketekst" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Venstreklikk på kolonneoverskrift" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Legg til kolonne i lista over kolonner som låter blir sortert på" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Trevisning" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Folder sammen element eller velger forelder-element" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Utvider element" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Tekstskriving" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Angre siste endring" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Gjør om siste angrede endring" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Velg alle låter i faner" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrer på %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Alle _hoder" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Sporkolonner" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumkolonner" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Personkolonner" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Datokolonner" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Filkolonner" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Produksjonskolonner" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Tilpass hoder …" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Utvid kolonne" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Vil du fjerne sporet «%(title)s» fra biblioteket?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Vil du fjerne %(count)d spor fra biblioteket?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Fjern fra bibliotek" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Vil du kjøre tillegget «%(name)s» på %(count)d låt?" msgstr[1] "Vil du kjøre tillegget «%(name)s» på %(count)d låter?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Vil du kjøre tillegget «%(name)s» på %(count)d album?" msgstr[1] "Vil du kjøre tillegget «%(name)s» på %(count)d album?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Sett opp tillegg …" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Legg i _kø" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Fjern fra bibliotek …" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Klarte ikke å vise filer" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Klarte ikke å vise filer, eller så mangler det et program som kan vise dem." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Vis i filbehandler" msgstr[1] "_Vis %(total)d filer i filbehandler" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Last ned fil …" msgstr[1] "_Last ned %(total)d filer …" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "vellykket" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "mislykket" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Nedlasting fullført" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Last ned {name!r} til" msgstr[1] "Last ned {total} filer til" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Last ned hit" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Erstatt _understrek med mellomrom" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Tittelversaliser tagger" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Del opp i flere _verdier" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tagger fra sti" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tagger erstatter gjeldende tagger" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tagger legges til gjeldende tagger" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Mønsteret\n" "\t%s\n" "er ugyldig. Det inneholder enten samme tagg flere ganger, eller har " "ubalanserte parenteser (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Mønsteret du skrev inn er ugyldig. Pass på å skrive < og > som " "«\\<» og «\\>», og se til at taggene er balansert.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Rediger visning" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Spornummer" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Start fr_a:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Totalt antall:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Spill av/pause" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Forrige" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "og %d andre …" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Lagrer endrede låter." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d låter lagret\n" "(%(remaining)s gjenstår)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s av %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Ser etter oppdateringer" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Tilkobling mislyktes" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Du bruker allerede nyeste versjon (%(version)s)" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Det har kommet en ny versjon (%(new-version)s)\n" "\n" "Du bruker nå versjon %(old-version)s\n" "\n" "Besøk <a href='%(url)s'>programnettstedet</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Tom spilleliste" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Spillelister må ha navn" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Du har allerede en spilleliste med navn %(name)s i %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Innebygde album-omslag" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Bruker innebygde omslagsbilder." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Filsystem-omslag" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "Bruker omslagsbildefiler som ligger i mapper sammen med låter." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Omslagsbilde" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Søker etter album-omslag hos tilbydere" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Vis kortfattet bruksinformasjon" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Vis versjon og opphavsrett" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Skriv ut feilsøkingsinfo" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Bruk: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[valg]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Valget %r er ukjent." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Valget %r krever argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r er ikke et unikt prefiks." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekund" msgstr[1] "%s sekunder" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Ingen tidsinformasjon" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minutt" msgstr[1] "%d minutter" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d time" msgstr[1] "%d timer" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dager" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d år" msgstr[1] "%d år" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "tittelversaler?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Dato må skrives inn i form av «ÅÅÅÅ», «ÅÅÅÅ-MM-DD» eller «ÅÅÅÅ-MM-DD TT:MM:" "SS»." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain-forsterkninger må skrives inn i formatet «x.yy dB»." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain-maksnivå må skrives inn i formatet «x.yy dB»." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz-ID-er skal være i UUID-format." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-utgivelsesstatus må være «official», «promotional» eller " "«bootleg»." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Språk må velges med en tre-bokstavs ISO 639-2-kode" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Lagrer %d fil" msgstr[1] "Lagrer %d filer" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Autolagring" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Klarte ikke å redigere låt" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Lagring av %s mislyktes. Fila kan være skrivebeskyttet, ødelagt, eller du " "mangler tillatelser til å redigere den." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Ugyldig tegnkoding]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangør" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangører" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arrangement" #: quodlibet/util/tags.py:86 msgid "author" msgstr "opphavsrettseier" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "opphavsrettseiere" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "kommentar" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "komponist" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "komponister" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "komposisjon" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenter" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigering" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "opphavsrett" #: quodlibet/util/tags.py:93 msgid "date" msgstr "dato" #: quodlibet/util/tags.py:94 msgid "description" msgstr "beskrivelse" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "sjanger" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "sjangrer" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "utøver" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "fremføring" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "gruppering" #: quodlibet/util/tags.py:98 msgid "language" msgstr "språk" #: quodlibet/util/tags.py:99 msgid "license" msgstr "lisens" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "sangtekstforfatter" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "sangtekstforfattere" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "sangtekst" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisasjon" #: quodlibet/util/tags.py:104 msgid "title" msgstr "tittel" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versjon" #: quodlibet/util/tags.py:106 msgid "website" msgstr "nettsted" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albumartist" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "plate-undertittel" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "plate" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "spor" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "platemerke-ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "opprinnelig utgivelsesdato" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "opprinnelig album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "opprinnelig artist" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "innspillingsdato" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "utgivelsesland" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "grunntone" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz-innspillings-ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz-utgivelsesspor-ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz-utgivelses-ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz-artist-ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz-utgivelsesartist-ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz-TRM-ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP-PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz-albumstatus" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz-albumtype" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz-utgivelsesgruppe-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "sporforsterkning" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "spor-maksverdi" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albumforsterkning" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album-maksverdi" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "referansenivå" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "plater" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "spor" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "sist startet" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "fullt navn" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "monteringspunkt" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personer" #: quodlibet/util/tags.py:168 msgid "year" msgstr "år" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "opprinnelig utgivelsesår" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "bokmerke" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bit-dybde" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "filformat" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "spillelister" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "samplingsrate" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "antall kanaler" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "sortering" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "roller" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Lydtagg-behandler" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Rediger tagger i lydfiler" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musikkspiller" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Lytt til, bla gjennom eller rediger lydsamling" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso er en taggbehandler med samme tagg-grensesnitt som Quod Libet. Det " "lar deg se og redigere alle tagger i alle støttede filformater." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Programmet støtter formatene Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC og MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet er et program for håndtering av musikk. Det tilbyr ulike måter å " "vise et lydbibliotek på, og støtter avspilling av internettradio og andre " "lydstrømmer. Det er også et godt verktøy for redigering av metadata-tagger " "og søking." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Eksporterer en spilleliste til Sonos-format, gitt at både deling og " #~ "mappestruktur eksisterer." #~ msgid "Export to Sonos playlist" #~ msgstr "Eksporter som Sonos-spilleliste" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Klarte ikke å legge til <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Ugyldige tagger" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Taggene <b>%s</b> er ugyldige\n" #~ "\n" #~ "Valgte filer støtter ikke redigering av disse taggene." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Gir låter automatisk vurdering basert på om du spiller gjennom eller " #~ "hopper over dem. Denne funksjonen bruker vux-algoritmen «accelerated» av " #~ "Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekunder" #, fuzzy #~ msgid "Startup" #~ msgstr "Oppstart" #~ msgid "Audio Feeds" #~ msgstr "Lydkilder" #~ msgid "_Audio Feeds" #~ msgstr "_Lydkilder" #, fuzzy #~ msgid "New" #~ msgstr "_Ny" #~ msgid "Automatic Library Update" #~ msgstr "Automatisk bibliotek-oppdatering" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Holder biblioteket oppdatert ved hjelp av inotify. Krever %s." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Tillater styring av Quod Libet ved bruk av-D-Bus-grensesnitt-" #~ "spesifikasjonen MPRIS 2.0." #~ msgid "Searching for lyrics…" #~ msgstr "Søker etter sangtekst …" #~ msgid "broker username" #~ msgstr "meglerbrukernavn" #~ msgid "broker password" #~ msgstr "meglerpassord" #~ msgid "<artist>" #~ msgstr "<artist>" #~ msgid "<album>" #~ msgstr "<album>" #~ msgid "<title>" #~ msgstr "<tittel>" #, fuzzy #~ msgid "OK" #~ msgstr "_OK" #~ msgid "" #~ "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " #~ "both share a directory structure. Shares configuration with <a href=" #~ "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</" #~ "a>." #~ msgstr "" #~ "Eksporterer en spilleliste dynamisk til Logitech Squeezebox, gitt at " #~ "begge bruker samme mappestruktur. Deler oppsett med <a href=" #~ "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync</a>-" #~ "tillegget." #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Eksporterer metadata for valgte låter til en «.tags»-fil." #~ msgid "Import Metadata" #~ msgstr "Importer metadata" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Importerer metadata for valgte låter fra en «.tags»-fil." #~ msgid "Migrate Metadata" #~ msgstr "Flytt over metadata" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Kopierer quodlibet-bestemte metadata mellom låter." #~ msgid "_Copy" #~ msgstr "_Kopier" #~ msgid "_Paste" #~ msgstr "_Lim inn" #~ msgid "Information to copy/paste" #~ msgstr "Informasjon å kopiere/lime inn" #~ msgid "Map tracks by disc and track number" #~ msgstr "Tilordne spor etter plate- og spornummer" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Slå på dette når du vil flytte metadata fra et album til et annet med " #~ "tilsvarende plate- og spornumre.\n" #~ "\n" #~ "<b>Merk:</b> dette må være slått på når metadata blir kopiert for at " #~ "sporinformasjon skal bli lagret." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Det finnes %d lagret spor." #~ msgstr[1] "Det finnes %d lagrede spor." #~ msgid "Unsupported file type" #~ msgstr "Gjeldende filtype støttes ikke" #~ msgid "Unable to add station" #~ msgstr "Klarte ikke å legge til stasjon" #~ msgid "_Wide Mode" #~ msgstr "_Bred modus" #~ msgid "Search Library" #~ msgstr "Søk i bibliotek" #~ msgid "_Search Library" #~ msgstr "_Søk i bibliotek" #~ msgid "Rate the playing song" #~ msgstr "Vurder låt som spilles av" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Vis eller skjul hovedlåtliste (utgått)" #~ msgid "Quit Program" #~ msgstr "Avslutt program" #~ msgid "Top of screen" #~ msgstr "Toppen av skjermen" #~ msgid "Middle of screen" #~ msgstr "Midt på skjermen" #~ msgid "Bottom of screen" #~ msgstr "Bunnen av skjermen" #~ msgid "_Clear" #~ msgstr "_Tøm" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Hindrer GNOME-skjermspareren fra å slå seg på mens du spiller av musikk." #~ msgid "No lyrics found" #~ msgstr "Fant ingen sangtekst" #~ msgid "_Zoom level:" #~ msgstr "_Zoomnivå:" #~ msgid "URL:" #~ msgstr "Adresse:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Søk via ovennevnt nettadresse hvis sangtekst ikke finnes på LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternativt søk" #~ msgid "Web Lyrics" #~ msgstr "Sangtekst fra nett" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Henter sangtekst fra nett for spillende låt og viser den på en sidelinje." #~ msgid "Skip Songs" #~ msgstr "Hopp over låter" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Avspilling hopper over låter med vurderingskarakter som er lik eller " #~ "under valgt terskelverdi." #~ msgid "Browse Folders" #~ msgstr "Utforsk mapper" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Åpner låtmapper i filutforsker." #~ msgid "Unable to open folders" #~ msgstr "Klarte ikke å åpne mapper" #~ msgid "No program available to open folders." #~ msgstr "Ingen filutforsker tilgjengelig." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Støtter QL-mønstre\n" #~ "f.eks. <tt><~artist~title></tt>" #~ msgid "Burn CD" #~ msgstr "Skriv CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Skriver CD-er med K3b, Brasero eller xfburn." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Søk etter artist på Wikipedia" #~ msgid "" #~ "Opens a browser window with Wikipedia article on the playing song artist." #~ msgstr "" #~ "Åpner nettleservindu med Wikipedia-artikkel om artisten for spillende " #~ "artist." #~ msgid "The single image filename to use if selected" #~ msgstr "Bildefilnavn som skal brukes hvis dette er valgt" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "Omslagsbildefil som skal brukes ved tvang (støtter jokertegn)" #~ msgid "Stop Once Empty" #~ msgstr "Stopp når tomt" #~ msgid "Fix MP3 Duration" #~ msgstr "Rett opp MP3-låtvarighet" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Fjerner TLEN-rammer fra ID3-tagger som kan forårsake feilaktige " #~ "varighetsverdier." #~ msgid "File Bug Report" #~ msgstr "Send feilrapport" #~ msgid "Audio device: %s" #~ msgstr "Lydenhet: %s" #~ msgid "Lyrics:" #~ msgstr "Sangtekst:" #~ msgid "Lyrics Window" #~ msgstr "Sangtekst-vindu" #~ msgid "_Lyrics" #~ msgstr "Sa_ngtekst" #~ msgid "" #~ "Use Python expressions in queries. Syntax is '@(python: expression)'. The " #~ "variable 's' is the song being matched." #~ msgstr "" #~ "Bruk Python-uttrykk i spørringer. Syntaks: «@(python: uttrykk)». " #~ "Variabelen «s» er låta som samsvarer med uttrykket." #~ msgid "Downloads" #~ msgstr "Nedlastninger" #~ msgid "Size" #~ msgstr "Størrelse" #~ msgid "_Download" #~ msgstr "_Last ned" #~ msgid "Vertical Split" #~ msgstr "Vertikal opp\tdeling" #~ msgid "Device Properties" #~ msgstr "Egenskaper for enhet" #~ msgid "Device:" #~ msgstr "Enhet:" #~ msgid "Not mounted" #~ msgstr "Ikke montert" #~ msgid "Mount point:" #~ msgstr "Monteringspunkt:" #~ msgid "Media Devices" #~ msgstr "Medieenheter" #~ msgid "_Media Devices" #~ msgstr "_Medieenheter" #~ msgid "_Eject" #~ msgstr "_Løs ut" #~ msgid "_Properties" #~ msgstr "_Egenskaper" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s brukt, %(free-size)s tilgjengelig" #~ msgid "%s is not connected." #~ msgstr "%s er ikke tilkoblet." #~ msgid "Copying %(song)s" #~ msgstr "Kopierer %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Klarte ikke å kopiere låt" #~ msgid "There is not enough free space for this song." #~ msgstr "Det er ikke nok ledig lagringsplass til denne låta." #~ msgid "%s could not be copied." #~ msgstr "Klarte ikke å kopiere %s." #~ msgid "Unable to delete songs" #~ msgstr "Klarte ikke å slette låter" #~ msgid "Deleting %(song)s" #~ msgstr "Sletter %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "Klarte ikke å slette %s." #~ msgid "Unable to delete song" #~ msgstr "Klarte ikke å slette låt" #~ msgid "Ejecting %s failed." #~ msgstr "Klarte ikke å løse ut %s." #~ msgid "Unable to eject device" #~ msgstr "Klarte ikke å løse ut enhet" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "Bakstykke for enhet mangler. Medieenhet-utforsker slått av." #~ msgid "Unknown Device" #~ msgstr "Ukjent enhet" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Klarte ikke å importere %s. Dette er påkrevet for enhetsstøtte." #~ msgid "%r is not a supported device." #~ msgstr "Enheten %r støttes ikke." #~ msgid "Initializing device backend." #~ msgstr "Laster inn enhet-bakstykke." #~ msgid "Trying '%s'" #~ msgstr "Prøver «%s»" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Klarte ikke å koble til enhet-bakstykke." #~ msgid "Device backend initialized." #~ msgstr "Enhet-bakstykke lastet inn." #~ msgid "_Filename pattern:" #~ msgstr "_Filnavnmønster:" #~ msgid "_Copy to Device" #~ msgstr "_Kopier til enhet" #~ msgid "Save" #~ msgstr "Lagre" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Klarte ikke å importere %s. Lydstrøm-utforsker slått av." #~ msgid "High Res" #~ msgstr "Høy oppløsning" #~ msgid "Audio Backend Failed to Load" #~ msgstr "Klarte ikke å laste inn lyd-bakstykke" #~ msgid "" #~ "Loading the audio backend '%(name)s' failed. Audio playback will be " #~ "disabled." #~ msgstr "" #~ "Innlasting av lyd-bakstykke «%(name)s» mislyktes. Avspilling av lyd er " #~ "slått av." #~ msgid "_Open" #~ msgstr "_Åpne" #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Det har oppstått en programfeil i Quod Libet. En fil med informasjon om " #~ "feilen er lagret som <b >%(dump-path)s</b>. Vi ber om at du rapporterer " #~ "dette som en ny programfeil via %(new-issue-url)sog legger ved innholdet " #~ "i denne fila. Den kan inneholde informasjon som identifiserer deg og/" #~ "eller systemet ditt, som f.eks. en liste over filer som er blitt spilt av " #~ "nylig. Bruk heller fila <b>%(mini-dump-path)s</b> og beskriv hva du " #~ "gjorde da feilen oppstod hvis du ikke vil at personlig informasjon skal " #~ "bli med i rapporten." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "Quod Libet kan nå oppføre seg ustabilt. Du bør lukke programmet og starte " #~ "det på nytt. Biblioteket blir lagret som normalt." #~ msgid "Controls the tone of your music with an equalizer." #~ msgstr "Kontrollerer overtoner i musikken med en «equalizer»." #~ msgid "browsers" #~ msgstr "utforskere" #~ msgid "tooltip" #~ msgstr "hjelpeboble" #~ msgid "Event Logging" #~ msgstr "Loggføring av hendelser" #~ msgid "Sends song events to the Zeitgeist event logging service." #~ msgstr "Sender låthendelser til Zeitgeist-loggtjeneste." #~ msgid "Unable to download lyrics." #~ msgstr "Klarte ikke å laste ned sangtekst." #~ msgid "Uninitialized iPod" #~ msgstr "iPod ikke klartgjort" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Vil du lage en tom database på denne iPod-en?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volumforsterkning (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Kombiner tagger med _flere verdier" #~ msgid "Capacity:" #~ msgstr "Kapasitet:" #~ msgid "Firmware:" #~ msgstr "Fastvare:" #~ msgid "Saving iPod database…" #~ msgstr "Lagrer iPod-database …" #~ msgid "Unable to save iPod database" #~ msgstr "Klarte ikke å lagre iPod-database" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Fant ikke libgpod. Støtte for iPod er slått av." #~ msgid "Set or toggle the playback order" #~ msgstr "Velg eller bytt avspillingsrekkefølge" #~ msgid "Playback follows your selection." #~ msgstr "Avspilling følger utvalg." #~ msgid "Track Repeat" #~ msgstr "Gjenta låt" #~ msgid "Shuffle" #~ msgstr "Omstokket" #~ msgid "Weighted" #~ msgstr "Vektet" #~ msgid "_Weighted" #~ msgstr "_Vektet" #~ msgid "_One Song" #~ msgstr "_Én låt" #~ msgid "Restart the playlist when finished" #~ msgstr "Spill av spillelista på nytt når den er ferdig" #~ msgid "Disable Browser" #~ msgstr "Slå av utforsker" #~ msgid "_Disable Browser" #~ msgstr "_Slå av utforsker" #, fuzzy #~ msgid "Force Write" #~ msgstr "Skriv" #~ msgid "Filter on _Genre" #~ msgstr "Filtrer på _sjanger" #~ msgid "Filter on _Artist" #~ msgstr "Filtrer på _artist" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrer på al_bum" #~ msgid "_Music" #~ msgstr "_Musikk" #~ msgid "Add Bookmark" #~ msgstr "Legg til bokmerke" #~ msgid "Song _List" #~ msgstr "Låt_liste" #~ msgid "D:" #~ msgstr "D:" #~ msgid "W:" #~ msgstr "A:" #~ msgid "E:" #~ msgstr "F:" #~ msgid "Stop _after this song" #~ msgstr "Stopp _etter denne låta" #~ msgid "_Release:" #~ msgstr "_Utgivelse:" #~ msgid "%d _release:" #~ msgid_plural "%d _releases:" #~ msgstr[0] "%d utgivelse:" #~ msgstr[1] "%d _utgivelser:" #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "%d resultat funnet." #~ msgstr[1] "%d resultater funnet." #~ msgid "Split _disc from album" #~ msgstr "Trekk platenummer ut av album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Tid" #~ msgid "Select an album" #~ msgstr "Velg alle" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s og %(count)d til" #~ msgstr[1] "%(title)s og %(count)d til" #~ msgid "Playlist Export" #~ msgstr "Eksporter spillelister" #~ msgid "Re_fresh Library" #~ msgstr "_Oppdater bibliotek" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Vurdering" #, fuzzy #~ msgid "Unable to open input files" #~ msgstr "Klarte ikke å åpne filer" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Ugyldig verdi" #~ msgid "command|filename" #~ msgstr "kommando|filnavn" #~ msgid "command|tag" #~ msgstr "kommando|tagg" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Søk" #~ msgid "%d of %d" #~ msgstr "%d av %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Bruk: %s %s" #~ msgid "_Download..." #~ msgstr "_Last ned..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Ny stasjon" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Skrive over <b>%s</b>?" #, fuzzy #~ msgid "Output Error" #~ msgstr "_Utdatalogg" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet kjører allerede." #~ msgid "No song is currently playing." #~ msgstr "For øyeblikket spilles ingen låt." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Klarte ikke å skrive til %s. Fjerner den." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Rediger bokmerker..." #~ msgid "_New Folder..." #~ msgstr "_Ny mappe..." #~ msgid "_Add to Playlist" #~ msgstr "_Legg til spilleliste" #~ msgid "_Edit Display..." #~ msgstr "_Rediger visning..." #, fuzzy #~ msgid "Output Log" #~ msgstr "_Utdatalogg" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stasjon" #~ msgid "_Add a Location..." #~ msgstr "_Legg til en adresse..." #~ msgid "_Output Log" #~ msgstr "_Utdatalogg" #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "Kolonne_instillinger..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Sporkolonner" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Personkolonner" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Albumkolonner" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Datokolonner" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Filkolonner" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Produksjonskolonner" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tagg:" #, fuzzy #~ msgid "Warnings" #~ msgstr "_Vurdering" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "album-artist" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artister" #, fuzzy #~ msgid "album (sort)" #~ msgstr "album-artist" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "utøvere" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "utøvere" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album-artist-ID" #~ msgid "errors" #~ msgstr "feil" #~ msgid "Permanently delete this file?" #~ msgstr "Vil du slette denne fila permanent?" #~ msgid "Permanently delete these files?" #~ msgstr "Vil du slette disse filene permanent" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s og %(count)d annen..." #~ msgstr[1] "%(title)s og %(count)d andre..." #, fuzzy #~ msgid "Version:" #~ msgstr "versjon" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "_Fjern feilmeldinger" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "Klarte ikke å legge til %s i biblioteket.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Ingen utløsningskommando funnet." #~ msgid "Unable to start web browser" #~ msgstr "Klarte ikke å starte nettleseren" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Fant ingen nettleser. Gi en verdi til $BROWSER-variabelen, eller sørg for " #~ "at /usr/bin/sensible-browser finnes." #, fuzzy #~ msgid "Library Error" #~ msgstr "Bibliotekvisning" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Utdatalogg" #~ msgid "translator-credits" #~ msgstr "Eirik Haatveit" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Vis andre kolonner, separert av mellomrom" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Fortsett" #, fuzzy #~ msgid "Confirm rating" #~ msgstr "Informasjon" #~ msgid "Search your library" #~ msgstr "Søk i bibliotek" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Opphavsrett 2004-2007 Joe Wreschnig, Michael Urman, og andre\n" #~ "\n" #~ "Dette er fri programvare, se kildekoden for kopieringsbetingelser.\n" #~ "Det finnes INGEN garanti, ikke engang for SALGBARHET eller SKIKKETHET\n" #~ "FOR ET BESTEMT FORMÅL.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Total størrelse:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet-programtillegg" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "Viser enkle søk i blått, avanserte i grønt, og ugyldige i rødt" #~ msgid "Separators for splitting tags" #~ msgstr "Separator for splitting av tagger" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet-instillinger" #~ msgid "Not Played To_day" #~ msgstr "Ikke spilt i _dag" #~ msgid "Not Played in a _Week" #~ msgstr "Ikke spilt på en _uke" #~ msgid "Not Played in a _Month" #~ msgstr "Ikke spilt på en _måned" #~ msgid "B_ottom 40" #~ msgstr "40 på _bunn" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "De 40 minst spilte låtene i biblioteket (det kan være mer enn 40 valgte, " #~ "om det er flere som har vært hørt på like mange ganger)" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | kontroll ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Dato" #~ msgid "Choose New Stations" #~ msgstr "Velg nye stasjoner" #~ msgid "Add" #~ msgstr "Legg til" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stasjoner..." #~ msgid "Unable to save library" #~ msgstr "Klarte ikke å lagre biblioteket" #~ msgid "Sort by title" #~ msgstr "Sorter etter tittel" #~ msgid "Sort by artist" #~ msgstr "Sorter etter artist" #~ msgid "Lyrics provided by %s." #~ msgstr "Låttekster fra %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Ingen låttekst funnet\n" #~ "\n" #~ "Du kan trykke på «Last ned»-knappen for å få Quod Libet til å søke etter " #~ "låttekster på nettet. Du kan også skrive dem inn selv, og trykke på " #~ "«Lagre»-knappen." #~ msgid "part" #~ msgstr "del " #~ msgid "Opening audio device." #~ msgstr "Åpner lydenhet." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d låter lagret" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album-ID" #~ msgid "Unable to open audio device" #~ msgstr "Klarte ikke å åpne lydenhet" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet forsøkte å få tilgang til «autosink»- og «%(sink)s»-driverene, " #~ "men klarte ikke å åpne dem. Velg GStreamer-kommandokø ved å endre linja " #~ "med\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "i ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet fant ikke GStreamer-elementet «filesrc». Kontroller GStreamer-" #~ "installasjonen din." ����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/nl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000776340�14436352625�013625� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# translation of nl.po to Nederlands # English translation of Quod Libet. # Copyright (C) 2005 THE Quod Libet'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # # dok <dok@xs4all.nl>, 2005. # Hans van Dok <dok@xs4all.nl>, 2005, 2006, 2007. msgid "" msgstr "" "Project-Id-Version: nl\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" "PO-Revision-Date: 2022-04-01 14:02+0200\n" "Last-Translator: Heimen Stoffels <vistausss@fastmail.com>\n" "Language-Team: Dutch <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/nl/>\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 3.0.1\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "personen" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "Toevoegings_datum" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Oorspronkelijke datum" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "Waa_rdering" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Aantal keer afges_peeld" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Sorteren o_p…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Voorkeuren" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumlijst" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumlijst" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Alle albums" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Album_hoes herladen" msgstr[1] "Album_hoezen herladen" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Albumloze nummers" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d nummer" msgstr[1] "%d nummers" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d schijf" msgstr[1] "%d schijven" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Een voorbeeldalbum" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albumlijstvoorkeuren" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Album_hoezen tonen" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Ook artiesten tonen in _snelzoekresultaten" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opties" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albumweergave" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Sluiten" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Verzameling verkennen" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d nummer" msgstr[1] "%d nummers" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Ongeldig patroon" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumverzameling" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Album_verzameling" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Onbekende %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Meerdere %s waarden" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Aangepast" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Toevoegen" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "Ve_rwijderen" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Samenvoegen" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Albumverzamelingsvoorkeuren" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "Toep_assen" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "Ann_uleren" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Hoesrooster" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Hoesrooster" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Hoesroostervoorkeuren" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Album_tekst tonen" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Item ‘Alle albums’ tonen" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Brede modus" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Hoesvergroting" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Bestandssysteem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Bestandssysteem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Kan nummers niet kopiëren" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "De geselecteerde bestanden kunnen niet worden gekopieerd naar andere " "nummerlijsten of de wachtrij." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "Toevoegen _aan verzameling" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Zenderlijsten kunnen alleen locaties van zenders bevatten, geen andere " "zenderlijsten of afspeellijsten. De volgende locaties kunnen niet worden " "geladen:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Online-radiostation" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Zenders toevoegen" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Bezig met ophalen van zenderlijst" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nieuwe zender" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Voer de locatie van een online-radiozender in:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronisch" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hiphop/Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Gouwe ouwen" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japans" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indisch" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religieus" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Hitlijsten" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turks" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Studentenradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Praatprogramma's/Nieuws" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Sfeervol" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassiek" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatief" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Nieuws" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavisch" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grieks" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Wil je de lijst met populaire radiozenders bekijken?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "Zenders _bekijken" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Onl_ine-radiostation" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Alle zenders" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favorieten" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Geen categorie" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nieuwe zender…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Zenders bijwerken" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Geen zenders gevonden" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Er zijn geen online-radiozenders gevonden op %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Er valt niks toe te voegen" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Alle vermelde zenders staan al in je verzameling." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Toevoegen aan favorieten" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Verwijderen uit favorieten" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d zender" msgstr[1] "%(count)d zenders" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneelverkenner" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Paneelverkenner" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "_Alles selecteren" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Onbekend" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Alles" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Klein" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Breed" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Kolommen" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Een tagpatroon met optionele opmaak, bijv. <tt>componist</tt> of\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Paneelverkennervoorkeuren" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Kolomindeling" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Kolominhoud" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Vaste paneelbreedte" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Afspeellijsten" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Afs_peellijsten" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Ve_rwijderen van afspeellijst" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nieuw" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importeren" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Kan afspeellijst niet importeren" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet kan alleen m3u(8)- en pls-afspeellijsten importeren." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "Verwij_deren" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Naam wijzigen" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Kan afspeellijstnaam niet wijzigen" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Afspeellijst importeren" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importeren" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nieuwe afspeellijst…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Wat wil je doen met %d nummer?" msgstr[1] "Wat wil je doen met %d nummers?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Bevestig de actie op afspeellijst \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "blanco" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Voorbeeldafspeellijst" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Paneelverkennervoorkeuren" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Afspeellijstweergave" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Weet je zeker dat je de afspeellijst ‘%s’ wilt verwijderen?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Alle informatie over de geselecteerde afspeellijst wordt verwijderd en kan " "niet worden hersteld." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Nummers" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nieuwe afspeellijst" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Geef de nieuwe afspeellijst een naam:" #: quodlibet/browsers/playlists/util.py:73 #, fuzzy msgid "_Create" msgstr "Database aanma_ken" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "De afspeellijst wordt geïmporteerd.\n" "\n" "%(current)d/%(total)d nummers toegevoegd." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nieuwe feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Voer de locatie van een audiofeed in:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Best_and toevoegen…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Ve_rversen" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Controleer deze map op nieuwe nummers" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Kan feed niet toevoegen" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s kan niet worden toegevoegd. Wellicht is de server tijdelijk niet " "beschikbaar of de locatie geen audiofeed." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Het huidige audiobackend ondersteunt geen url's - de audiofeedverkenner is " "uitgeschakeld." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Resu_ltaten beperken" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "Meerdere w_aarden toestaan" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Nummerlijst" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "Nummerlijs_t" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud-verkenner" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Zoeken" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Mijn nummers" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Ga naar %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Verbonden" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet is nu verbonden met ‘%s’!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "%s ontkoppelen" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Voer de code in…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "%s koppelen" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud-autorisatie" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Voer de Soundcloud-autorisatiecode in:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet is niet actief (voeg ‘--run’ toe om te starten)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "een muziekverzameling en -speler" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[optie]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Toon het spelende nummer en sluit af" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Onmiddelijk beginnen met afspelen" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Geminimaliseerd opstarten" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Ga naar volgend nummer" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Ga naar vorig nummer of begin afspelen opnieuw indien dichtbij begin" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Ga naar vorig nummer" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Afspelen" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Afspelen onderbreken" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Afspelen/Pauzeren aan/uit" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Afspelen stoppen" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Volume verhogen" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Volume verlagen" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Waardering van spelend nummer verhogen met één ster" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Waardering van spelend nummer verlagen met één ster" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Toon de spelerstatus" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Hoofdvenster verbergen" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Hoofdvenster tonen" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Hoofdvenster tonen/verbergen" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Actieve speler focussen" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Actieve verkennerfilters wissen" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Verversen en verzameling opnieuw doorzoeken" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Beschikbare verkenners tonen" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Toon de huidige afspeellijst" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Toon de inhoud van de wachtrij" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Toon de actieve tekstzoekopdracht" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Starten zonder plug-ins" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet indien inactief" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Sluit Quod Libet af" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Spelend nummer verderspoelen" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][UU:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Willekeurig aan/uit" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Willekeurige modus instellen" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Herhalen aan/uit" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Herhaalmodus instellen" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Volume instellen" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Verzameling doorzoeken" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "zoekopdracht" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Bestand afspelen" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "bestandsnaam" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Spelende nummer waarderen" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Huidige verkenner instellen" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Stoppen na spelende nummer" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Nieuwe verkenner openen" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Wachtrij tonen/verbergen" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filteren op willekeurige waarde" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filteren op tagwaarde" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=waarde" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Bestand of zoekopdracht in wachtrij zetten" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Plaats door komma's gescheiden bestanden in wachtrij" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "bestandsnaam" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Stuur bestandsnamen van zoekresultaten naar stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Bestand of zoekopdracht uit wachtrij halen" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Bestand of map toevoegen aan verzameling" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "locatie" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "patroon" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Ongeldig argument voor ‘%s’." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Probeer %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Er is een fout opgetreden" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Je kunt deze fout negeren, maar Quod Libet kan instabiel zijn. Meld deze " "fout aan de ontwikkelaars - dit kost slechts een paar seconden van je tijd." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Foutrapportage versturen" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Herstarten" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Fout negeren" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Foutinformatie:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Er wordt verscheidene informatie over deze fout en je systeem verstuurd naar " "een online-dienst (<a href=‘https://www.sentry.io'>www.sentry.io</a>). " "Hieronder zie je welke gegevens worden doorgestuurd." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(optioneel) Beschrijf wat je deed ten tijde van de fout:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "Ver_sturen" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Korte omschrijving…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Te versturen:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "een audiotagbewerker" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "map" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Audiometagegevensbewerker" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL van albumhoesbron" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Haalt albumhoezen op van de bij <tt>artwork_url-tag</tt> opgegeven link. Dit " "werkt met de Soundcloud-verkenner." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs-albumhoesbron" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Haalt albumhoezen op van Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm-albumhoesbron" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Haalt albumhoezen op uit Last.fm's albumhoesarchief." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-albumhoesbron" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Haalt albumhoezen op uit Musicbrainz's albumhoesarchief." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Coderingen converteren" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Verbetert verkeerd geïnterpreteerd tagwaardecoderingen in de tagbewerker." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "Codering _converteren…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji-omvormer" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Converteert kana/kanji naar romaji bij naamswijzigingen." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "_Japanse tekst romaniseren" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "De ‘Kana/Kanji-omvormer’ (kakasi) is niet aangetroffen." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Regex-vervanging" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Laat arbitraire regex-vervangingen toe (<tt>s/van/tot/</tt>) bij taggen of " "naamswijzigingen." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Hoofdletters" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Geeft hoofdletters aan tagwaarden in de tagbewerker." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Hoof_dletterwaarde" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Laat _ALLEEN HOOFDLETTERS in tags toe" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Begin_hoofdletters" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Gebruikt gangbare Engelse regels voor hoofdlettergebruik, zoals in \"Dark " "Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Geavanceerde voorkeuren" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Pas de geavanceerde configuratie-instellingen aan." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Ik weet wat ik doe" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Geanimeerd weergavescherm" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Toont nummerinformatie op je scherm bij veranderingen." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Positie:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Hoesgrootte:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Weergave" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Lettertype:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Links" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Midden" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Rechts" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "Tekst _uitlijnen:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Tekst" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Tekst:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Vullen:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Kleuren" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Schaduwen" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "C_ontour" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Afgero_nde hoeken" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "Ver_traging:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Effecten" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Weergavepa_troon aanpassen…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Voorvertoning" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Programma-informatie" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Verscheidene informatie over het programma en de werkomgeving." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Ondersteunde formaten" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Configuratiemap" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Cachemap" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Audiobackend" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Telkens na het afspelen (standaard)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Als een nummer is afgespeeld, maar niet overgeslagen, schrijft de plug-in de " "tags naar het bestand. Overgeslagen tellingen worden niet bijgehouden in " "bestanden, dus voorkom je hiermee onnodige schrijfacties." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Telkens na het afspelen of overslaan" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Als een nummer is afgespeeld of overgeslagen, schrijft de plug-in de tags " "naar het bestand. Dit kan handig zijn als je je er van wilt verzekeren dat " "waarderingen worden weggeschreven." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Eenmaal, na waarderen van album" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Als een nummer is afgespeeld of overgeslagen, wordt het bijbehorende album " "gecontroleerd. Als alle nummers op het album zijn gewaardeerd en er is " "minimaal één zonder waardering of afspeeltelling, dan schrijft de plug-in de " "tags weg.\n" "\n" "Gebruik deze optie om constant bijwerken te voorkomen, maar let op: als een " "album eenmaal is bijgewerkt, dien je de plug-in ‘Tags in bestanden " "bijwerken’ te gebruiken om nieuwe bijwerkingen weg te schrijven." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Als de plug-in tags van een album wegschrijft, wordt eerst de afspeeltelling " "van de nummers op ingesteld op één.\n" "Soms weet je op voorhand dat je een nummer niet leuk vindt, dus kan dit " "later van pas komen als je naar reeds beluisterde albums zoekt (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Kon ‘%s’ niet wegschrijven" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Tags in bestanden automatisch bijwerken" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Werkt de tags bij na het afspelen. Dit zorgt er voor dat afspeeltellingen en " "waarderingen actueel zijn." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "De volgende instelling is vereist om deze plug-in te gebruiken:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Waarderingen en afspeeltellin_gen opslaan" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Instellingen bijgewerkt" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Fout in %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Verzekert dat afspeeltellingen niet op nul staan tijdens het opslaan" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Bijwerkmethode:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Voorkeuren" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatisch verbergen" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Verbergt schijven of toont ze automatisch zodra ze worden los- of " "aangekoppeld." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatische waardering" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Geeft nummers automatisch een waardering als ze worden afgespeeld of " "overgeslagen. Dit gebruikt het ‘accelerated’-algoritme van vux door Brian " "Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "De opgegeven Banshee-databank is beschadigd of ontbreekt" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importeren mislukt" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Waarderingen en statistieken van %d nummer geïmporteerd" msgstr[1] "Waarderingen en statistieken van %d nummers geïmporteerd" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Importeren uit Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Importeer waarderingen en nummerstatistieken uit Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Databanklocatie:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Importeren starten" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Wekker" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Maakt je wakker met harde muziek." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Slaapliedje" # betere vertaling dan 'vervagen' nodig #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Vervaagt en pauzeert je muziek." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim-statusbericht" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim-statusbericht" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Past je Gajim-statusbericht aan naar waar je naar luistert." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Gepauzeerd:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Statustekst" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Statustekst" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Plat" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Live" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Volledige bas en hoge tonen" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Club" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Grote zaal" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Feest" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Zacht" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Volledige bas" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Hoofdtelefoon" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Softrock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Volledige hoge tonen" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizer" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Bepaal muziekklanken met een equalizer.\n" "Klik of gebruik toetsen om de niveaus aan te passen (rechtsklikken = " "standaardwaarden)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Het huidige backend biedt geen ondersteuning voor equalizing." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Standaard voorinstellingen" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Selecteren…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "Standaa_rdwaarden" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Aangepaste voorinstellingen" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "Selectie verwij_deren" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Naam van voorinstellingen:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "Op_slaan" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "online" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "offline" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "chatten" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "afwezig" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "onzichtbaar" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim-statusbericht" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Past je Gajim-statusbericht aan naar waar je naar luistert." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "gepauzeerd" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Patroon:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Lijst met accounts, spatiegescheiden, voor het aanpassen van je " "statusbericht. Als je niks opgeeft, wordt het statusbericht van alle " "accounts aangepast." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Accounts:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "‘[gepauzeerd]’ toevoegen" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Vink aan om ‘[gepauzeerd]’ toe te voegen aan het statusbericht bij " "nummerpauzering" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statussen waarvoor het statusbericht wordt aangepast" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pauzeren bij losmaken van hoofdtelefoon" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pauzeer als je je hoofdtelefoon losmaakt en hervat als je hem weer inplugt." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Schermbeveiliging/Pauzestand verhinderen" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Voorkom dat de schermbeveiliging wordt ingeschakeld of dat de computer in de " "pauzestand wordt gezet. Werkt alleen binnen de GNOME-werkomgeving." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Muziek wordt afgespeeld" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Modus:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Schermbeveiliging verhinderen" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Pauzestand verhinderen" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Online-radiologboek" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Legt de recentste 10 via radiozenders afgespeelde nummers vast en toont ze " "in het doorspoelmenu." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" "Legt een Jabber User Tunes-bestand vast in <tt>~/.quodlibet/jabber</tt>." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Taal wijzigen" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Wijzig de programmataal." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Systeemstandaard" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Herstart om de wijzigingen toe te passen" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV-mediaserver" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Beschrijft alle albums aan de Rygel UPnP-mediaserver via de MediaServer2 D-" "Bus-interface." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Zorg dat het volgende in je Rygel-configuratiebestand staat (~/.config/rygel." "conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD-server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Staat bediening op afstand van Quod Libet met een MPD-client toe. Streamen, " "afspeellijst- en verzamelingsbeheer worden niet ondersteund." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Poort:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokaal _ip-adres:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "W_achtwoord:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Verbinding" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Geteste clients" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus-ondersteuning" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Hoofdvenster verbergen na sluiten" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Quod Libet-patronen, zoals %s, zijn toegestaan." #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT-uitgever" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publiceert statusberichten in een MQTT-onderwerp." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Broker-hostnaam/ip-adres" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Standaard: localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Broker-poort" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Standaard: 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Broker-gebruikersnaam" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Broker-wachtwoord" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Onderwerp" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Afspeelpatroon" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "De statustekst bij het afspelen van een nummer." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Pauzeerpatroon" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "De statustekst bij het pauzeren van een nummer." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Geen nummer" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Platte tekst als er geen nummer wordt afgespeeld." #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT-configuratie" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Statustekst" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Verbonden met broker op %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Kan niet verbinden met %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Verbindingsfout" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz-synchronisatie" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synchroniseer waarderingen met MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Gebruikers_naam:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Wachtwoord:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Account" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Meldingstekst" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Titel:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Standaardpatroon herstellen" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Inhoud:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "Melding _tonen" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Meldingen tonen" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Alleen bij <i>hand_matige</i> nummerveranderingen" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Alleen bij <i>_automatische</i> nummerveranderingen" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Bij <i>a_lle</i> nummerveranderingen" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Alleen als het hoofdvenster niet ge_focust is" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "‘Volgende’-knop tonen" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Verbindingsfout" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Kan niet verbinden met de meldingsdienst." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Nummermeldingen" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Toont een melding als het nummer verandert." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Volgende" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Nummermeldingen" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Stel QLScrobbler in in het plug-invenster. Tot dan worden nummers niet " "ingediend." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Kan niet verbinden met de dienst ‘%s’." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Authenticatie mislukt: ongeldige url." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Authenticatie mislukt: ongeldige gebruikersnaam ‘%s’ of onjuist wachtwoord." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "De client is verbannen. Neem contact op met de maker." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Onjuiste systeemtijd. Indienen werkt niet totdat je tijd juist is ingesteld." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-indiening" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "AudioScrobbler-client voor Last.fm, Libre.fm en andere AudioScrobbler-" "diensten." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Authenticatie gelukt." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "Dien_st:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Overige…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "Accountgegevens _verifiëren" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Artiestpatroon:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Titelpatroon:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Uitsluit_filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Het patroon om de artiestnaam op te maken voor indienen. Laat leeg voor " "standaardinstelling." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Het patroon om de titel op te maken voor indienen. Laat leeg voor " "standaardinstelling." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Nummers die overeenkomen met dit filter worden niet ingediend" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Offline-modus (niets indienen)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Indienen" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Radioreclame dempen" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Demp de uitvoer als er reclame op de radio wordt afgespeeld.\n" "Zenders: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Willekeurig album afspelen" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Speel een willekeurig album af als het einde van de afspeellijst bereikt " "wordt. Dit vereist dat je actieve verkenner albumfiltering ondersteunt." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Hoger gewaardeerd" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Vaker afgespeeld" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Vaker overgeslagen" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Recenter afgespeeld" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Recenter gestart" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Recenter toegevoegd" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Langere albums" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "aantal seconden voor volgend album wordt afgespeeld" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Niveau's" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Speel sommige albums meer af dan andere" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "vermijden" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "verkiezen" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Willekeurig album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Wachten om %s te starten" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Waarderingen en statistieken van %d nummers geïmporteerd" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox-import" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importeert waarderingen en nummerstatistieken uit Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Schermbeveiligingspauze" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pauzeert afspelen als de GNOME-schermbeveiliging actief is." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Geen GNOME Shell-zoekmachine voor Quod Libet geïnstalleerd." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME-zoekmachine" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Staat GNOME Shell toe de verzameling te doorzoeken." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternatieve spoelbalk" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Een alternatieve zoekbalk welke altijd zichtbaar is en de net zo breed is " "als het venster." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Spoelpositiebladwijzers" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Sla spoelposities A en/of B van nummers op. Spoel door naar tijd A en stop " "na tijd B als het nummer wordt afgespeeld.\n" "\n" "ℹ Let op: door de namen van onderstaande posities te wijzigen worden de " "posities zelf niet gewijzigd, maar alleen de namen waar de plug-in naar " "zoekt." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Bladwijzernaam van positie A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "De bladwijzernaam voor als een nummer wordt afgespeeld. Indien aangetroffen " "wordt er doorgespoeld naar het opgegeven tijdstempel." #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Bladwijzernaam van positie B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "De bladwijzernaam die tijdens het afspelen bepaalt of een nummer bestaat. " "Als de huidige positie voorbij het tijdstempel ligt, wordt er doorgespoeld " "naar het einde." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox-synchronisatie" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Laat Logitech Squeezebox de uitvoer van Quod Libet nabootsen, zolang beide " "een identieke verzameling uitlezen." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Deelt zijn configuratie met de plug-in ‘<a href=\"%(plugin_link)s" "\">Exporteren naar Squeezebox</a>’." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Fout bij zoeken naar Squeezebox-server" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fout bij zoeken naar %s. Controleer de instellingen." #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Stoppen na pauzeren" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Met deze plug-in kun je de pauzeerknop instellen als stop-, afspeel- of " "spoelknop.\n" "\n" "Dit is handig als Quod Libet niet kan overschakelen naar een ander audio-" "apparaat na het verbinden met een nieuw apparaat (bluetoothluidspreker, USB-" "DAC, etc.).\n" "\n" "De positie in de huidige bron wordt bewaard als de optie ‘Alleen spoelbare " "bronnen’ is uitgeschakeld, anders moet het afspelen van vooraf aan beginnen." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Alleen spoelbare bronnen" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Plug-inopties" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Kopie in wachtrij" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Te verwijderen" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "verwijderen" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Overslaan" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLICAAT" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Bezig met synchroniseren" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Bezig met verwijderen" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Voltooid" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "MISLUKT" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Bestaand bestand is overgeslagen" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "De bestandsnaam van een nummer kan niet worden ingesteld." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Synchroniseren naar apparaat" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchroniseert alle nummers uit de geselecteerde zoekopdrachten met de " "opgegeven map." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synchroniseer de volgende zoekopdrachten:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Het volledige lo naar de exportlocatie" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Alle bestaande bestanden op de bestemming die geen zoekopdrachten zijn " "worden verwijderd." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "Bij met mtp aangekoppelde apparaten moet er eerst een lokale export worden " "gemaakt - daarna kan deze worden overgezet met rsync. Of, in het geval van " "Android-apparaten, adb-sync." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Bestemming:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Locatiepatronen" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Opgeslagen patronen bewerken…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "De structuur van de geëxporteerde bestandsnamen, op basis van hun tags" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Exportpartroon:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Voorvertoning stoppen" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Bronbestand" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Exportlocatie" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Er zijn twee dezelfde exportlocaties aangetroffen. Pas deze aan voordat je " "de synchronisatie start." #: quodlibet/ext/events/synchronize_to_device.py:256 #, fuzzy msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "Bestaande bestanden op de bestemming worden verwijderd!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Synchronisatie starten" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Synchronisatie afbreken" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "Je hebt nog geen opgeslagen zoekopdrachten." #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Kies een bestemming" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "De exportlocatie van ‘[{filename}]’ is gewijzigd. Oude locatie: [{old_path}] " "- Nieuwe locatie: [{new_path}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Bezig met synchronisatievoorvertoning" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Er wordt een synchronisatievoorvertoning uitgevoerd." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Synchronisatievoorvertoning voltooid" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Bezig met afbreken van synchronisatievoorvertoning" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "De synchronisatievoorvertoning is afgebroken." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "De synchronisatievoorvertoning is voltooid." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "De synchronisatievoorvertoning is afgebroken" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Er is een andere plug-in gekozen - de voorvertoning wordt afgebroken" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "De synchronisatie zal" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "proberen {count} bestand weg te schrijven" msgstr[1] "proberen {count} bestanden weg te schrijven" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "{count} duplicaat overslaan" msgstr[1] "{count} duplicaten overslaan" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "{count} bestand verwijderen" msgstr[1] "{count} bestanden verwijderen" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Geen bestemming gekozen" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Kies de map waarnaar nummer moeten worden geëxporteerd." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Geen exportpatroon opgegeven" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Geef een exportpatroon op voor de namen van de geëxporteerde nummers." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "De exportlocatie is niet absoluut" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Het patroon\n" "\n" "\t<b>{}</b>\n" "\n" "bevat ‘/’ maar begint niet op bovenliggend niveau. Geef een absolute " "bestemming op door te beginnen met de map / of ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Geen opgeslagen zoekopdrachten geselecteerd" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Selecteer minimaal één opgeslagen zoekopdracht." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Er zijn geen nummers uit de zoekopdrachten geselecteerd" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Alle geselecteerde zoekopdrachten zijn blanco." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "{} te synchroniseren nummers aangetroffen" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Geen overeenkomst tussen bestemming en exportpatroon" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Het exportpatroon begint met een locatie die verschilt van dat van de " "bestemming. Corrigeer het patroon.\n" "\n" "Foutmelding:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Kan niet synchroniseren" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Kan niet synchroniseren tijdens sorteren op <b>status</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Bezig met starten van nummersynchronisatie" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Bezig met synchroniseren…" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Nummersynchronisatie afgerond" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Nummersynchronisatie afgebroken" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "De synchronisatie is afgebroken." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "De synchronisatie is voltooid." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "De synchronisatie is afgebroken" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Er is een andere plug-in gekozen - de synchronisatie wordt afgebroken" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - ‘{filename}’" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Bezig met verwijderen van ‘{}’" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "De synchronisatie heeft" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "{count}/{total} bestand weggeschreven" msgstr[1] "{count}/{total} bestanden weggeschreven" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "({count} bestaand bestand overgeslagen)" msgstr[1] "({count} bestaande bestanden overgeslagen)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "{count}/{total} duplicaat overgeslagen" msgstr[1] "{count}/{total} duplicaten overgeslagen" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "{count}/{total} bestand verwijderd" msgstr[1] "{count}/{total} bestanden verwijderd" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "{count} bestand niet kunnen wegschrijven" msgstr[1] "{count} bestanden niet kunnen wegschrijven" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "{count} bestand uit een eerdere synchronisatie overgeslagen" msgstr[1] "{count} bestanden uit een eerdere synchronisatie overgeslagen" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Gesynchroniseerde songteksten" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Toont gesynchroniseerde songteksten uit .lrc-bestanden met dezelfde naam als " "de nummers (of vergelijkbaar)." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Achtergrond:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Lettertype" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Grootte (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy-statusberichten" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Werkt alle im-accounts gebaseerd op Telepathy (zoals ingesteld in Empathy, " "etc.) bij met een statusbericht gebaseerd op het huidige nummer." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Wordt afgespeeld:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "De statustekst bij het afspelen van een nummer. Quod Libet-patronen, zoals " "%s, zijn toegestaan." #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Gepauzeerd:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "De statustekst bij het pauzeren van een nummer. Quod Libet-patronen, zoals " "%s, zijn toegestaan." #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Platte tekst voor status als er geen nummer wordt afgespeeld" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Geen nummer:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Statuspatronen" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Themawisselaar" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Verandert het actieve GTK+-thema." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Thema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Standaardthema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Voorkeur voor donker thema" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Waarderen met duimpjes" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Biedt een waardeersysteem met duimpjes (duimpje omhoog/omlaag), wat wordt " "omgezet naar een waardeerwaarde. Dit is handig voor totalen en sorteren op " "<b><tt>~#score</tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Menubalk tonen/verbergen" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Toon of verberg de menubalk door op Alt te drukken." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Speelt niet" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Systeemvakpictogram" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Bedien Quod Libet vanuit het systeemvak." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "%(application-name)s _tonen" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "Afs_pelen" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_auzeren" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Vorige" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "Volge_nde" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Willekeurig" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "He_rhalen" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Stoppen n_a dit nummer" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "_Verkenner openen" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "_Tags bewerken" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informatie" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Afspeel_lijsten" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Afsluiten" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Gedrag" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Volume aanpassen met scrollwiel" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Van nummer veranderen met scrollwiel" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Scroll_wiel" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Hulpballonweergave" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Songtekst bekijken" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Toont songteksten op basis van tags of bestanden in een zijbalk." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Geen songtekst gevonden bij\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Je luistert nergens naar" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Visualisaties tonen" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Toon externe visualisaties." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Visualisaties kunnen niet worden getoond met ‘%s’" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Fout" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Uitvoerbaar bestand:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Herladen" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Golvende spoelbalk" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" "∿ Een spoelbalk in de vorm van een golf die het huidige nummer representeert." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Andere voorgrondkleur:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Andere zweefkleur:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Andere resterende kleur:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Huidige positie tonen" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Tijdstempels tonen" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Spoellengte bij scrollen (in milliseconden):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Afbeeldingen opslaan" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Slaat de albumhoes van het huidige nummer op naar een bestand." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Bestand:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Drempelwaarde:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Drempelwaarde voordat het filter wordt geactiveerd" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "Verho_uding:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Compressieverhouding" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Audiocompressie" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Verandert de amplitude van alle samples boven een bepaalde drempelwaarde met " "een specifieke verhouding." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Voorinstelling:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filter-voorinstelling" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frequentie-afbreking:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Low-pass filter-frequentie-afbreking" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Feed_niveau:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Feedniveau" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Standaard" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Dichtst bij virtuele luidsprekerplaatsing (30°, 3 meter)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Dichtbij Chu Moys crossfeeder (populair)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Dichtbij Jan Meiers CORDA-versterkers (weinig verandering)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Aangepast" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Aangepaste instellingen" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mengt het linkse en het rechtse kanaal op een manier die een " "luidsprekerinstelling simuleert bij het gebruik van een hoofdtelefoon, of om " "aan te passen voor hele oude stereo-opnamen." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filter_band:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "De frequentieband van het filter" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filterbree_dte:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "De frequentiebreedte van het filter" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Niveau:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Niveau van het effect" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Verwijdert belangrijkste zang uit het audiospoor." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono downmix" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Downmixt audiokanalen naar mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Snelheid:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "Toon_hoogte:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Audiotoonhoogte/-snelheid" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Bepaalt de toonhoogte van een audiostream." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Afspeellijst exporteren naar map" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exporteren" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Bestemming:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Bestandsnaampatroon:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" "Exporteert een afspeellijst door de bestanden te kopiëren naar een map." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Kan afspeellijst niet exporteren" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Zorg dat je schrijfrechten hebt op de map." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Standaard bestandsnaampatroon:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Oké" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Geef de afspeellijst een nieuwe naam\n" "of kies een te overschrijven Sonos-afspeellijst" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Exporteren als Sonos-afspeellijst" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "" "Exporteert een afspeellijst door de bestanden te kopiëren naar een map." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Fout bij zoeken naar Sonos-apparaten" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Fout bij zoeken naar Sonos. Controleer de instellingen." #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exporteren naar Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Exporteert een afspeellijst als Sonos-afspeellijst, mits deze dezelfde " "mappenstructuur delen." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Deelt zijn configuratie met de plug-in ‘<a href=\"%(plugin_link)s" "\">Squeezebox-synchronisatie</a>’." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Afspeellijst exporteren naar Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Afspeellijstnaam (bestaande naam wordt overschreven)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exporteren naar Squeezebox-afspeellijst" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Duplicaten verwijderen uit afspeellijst" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Verwijdert dubbele items van een afspeellijst." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Weet je zeker dat je %d dubbel nummer wil verwijderen?" msgstr[1] "Weet je zeker dat je %d dubbele nummers wil verwijderen?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "De dubbele nummers worden verwijderd van de afspeellijst ‘%s’." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Willekeurig afspelen" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Speelt een afspeellijst willekeurig af." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Cursor volgen" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Speelt af op basis van je selectie of het volgende nummer op de lijst " "(indien het einde is bereikt)." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Cursor volgen" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "Cursor _volgen" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Afspeeltelling-equalizer" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Speel willekeurig af met voorkeur voor minder vaak afgespeelde nummers." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Voorkeur voor minder vaak" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Voor_keur voor minder vaak" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Alleen wachtrij" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Beperkt afspelen tot nummers in de wachtrij.\n" "\n" "Selecteer de afspeelvolgorde in het hoofdvenster en dubbelklik op een nummer " "om het in de wachtrij te plaatsen." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Alleen wachtrij" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "Alleen _wachtrij" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Afspelen na dubbelklikken op nummer" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Omkeren" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Keert de afspeelvolgorde van de nummers om." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Om_keren" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Willekeurige groepen afspelen" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Speelt willekeurige groepen met nummers af op basis van een " "gemeenschappelijke tag, vergelijkbaar met het afspelen van albums.\n" "\n" "Hiermee kun je bijv. heel handig klassieke werken in de juiste volgorde " "afspelen." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Willekeurige groepen afspelen" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "Willekeurige _groepen afspelen" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Bezig met wachten op nieuwe groep…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Groepstag:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Tag om nummers op te groeperen" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filtertag:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Groeperen wordt alleen toegepast als het filter is opgegeven.\n" "Een nummer met een niet-ingestelde filtertag wordt behandeld als\n" "losse groep. De filtertag dient doorgaans (deels) overeen te komen\n" "met de groepstag." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Vertraging:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Het aantal seconden voor de volgende groep wordt afgespeeld" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Standaardwaarden herstellen" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Nummers met lage waardering overslaan" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Voegt een (willekeurige) afspeelvolgorde toe die nummers met een waardering " "lager dan of gelijk aan een opgegeven waarde overslaat." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Nummers met lage waardering overslaan" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Nummers met lage waar_dering overslaan" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Elk nummer herhalen" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Speel nummers willekeurig af, maar herhaal elk nummer een bepaald aantal " "keer." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Elk nummer herhalen" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "_Elk nummer herhalen" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Aantal keer dat elk nummer afgespeeld moet worden:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Voorwaarden" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Bepaal de voorwaarden waarop een overeenkomst dient plaats te vinden." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: condition-query, then-query, else-query)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Ontbrekende opdracht" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Laat nummers met de opgegeven tag overeenkomen." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Ook blanco tags opnemen" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python-zoekopdracht" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Gebruik Python-uitdrukkingen in zoekopdrachten." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: uitdrukking)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "De variabel <tt>s</tt> (of <tt>a</tt>) is het nummer/album dat overeen dient " "te komen.\n" "\n" "<tt>_ts</tt> is het tijdstempel (bestaand getal) aan het begin van een " "zoekopdracht.\n" "\n" "Verder zijn de modules <tt>time</tt> en <tt>random</tt> beschikbaar, evenals " "de klasse <tt>Random (==random.Random)</tt>." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Opgeslagen zoekopdracht opnemen" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 Toon ook resultaten van opgeslagen zoekopdrachten." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: zoekopdracht)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "uniek" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox oké. De enige speler wordt gebruikt (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Kan niet verbinden met %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Hostnaam:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Poort:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Gebruikersnaam:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Wachtwoord:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "De verzamelingsmap waarmee de server dient te verbinden" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Verzamelingslocatie:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "Instellingen _verifiëren" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox-server" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Foutopsporing" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "De Squeezebox-server op {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "ongeïdentificeerde Squeezebox-server" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "ongeïdentificeerde Squeezebox-speler: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Kies de Squeezebox-speler" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "De Squeezebox-server is aangetroffen.\n" "Kies de speler." #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Afbeelding inpassen in _venster" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Neem ‘[plugins] cover_filenames’ in het configuratiebestand door voor meer " "informatie" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programma:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "Afbeelding b_ewerken na opslaan" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Bestands_naam:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Opslaan mislukt" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Kan \"%s\" niet opslaan." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-fout: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "van %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Resolutie: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Grootte: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Resultaatlimiet van maximale afmetingen" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Zoeken" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Bezig met zoeken…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Klaar" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Albumhoes ophalen" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Haalt albumhoezen op van verscheidene websites." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Bronnen" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 naar ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Converteert je APEv2-tags naar ID3v2-tags. De APEv2-tags worden na het " "converteren verwijderd." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Ga naar bladwijzer" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Beheer alle bladwijzers in de geselecteerde bestanden." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "Bladwijzers aanpass_en…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Geen bladwijzers" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Opzoeken op MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Hertagt een album op basis van een MusicBrainz-zoekopdracht." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Alleen jaartal opnemen in de \"datum\"-tag" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "\"_albumartist\" wegschrijven indien nodig" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Sorteertags wegschrijven vóór artiestennamen" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "_Standaard MusicBrainz-tags wegschrijven" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "\"labelid\"-tag wegschrijven" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Bestandsnaam" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Schijf" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Nummer" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Titel" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artiest" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Opzoeken op MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "Zoe_kopdracht:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "Zo_eken" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Resultaten <i>(versleep om rangschikking aan te passen)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Voer een zoekopdracht in." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Er is een fout opgetreden. Probeer het opnieuw." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Bezig met laden van resultaten…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Geen resultaten gevonden." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python-opdrachtregel" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Opent de interactieve Python-opdrachtregel in een nieuw venster." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} voor {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python-opdrachtregel in zijbalk" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Opent de interactieve Python-opdrachtregel in de zijbalk en neemt de " "geselecteerde nummers over." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Je hebt standaard toegang tot de volgende objecten:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Je huidige werkmap is:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Aanvulling" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Haalt hoogwaardige albumhoezen op middels hoesplug-ins." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Traditioneel" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Groot" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Bezig met laden van %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Niks gevonden voor:\n" "<i>%(albums)s</i>.\n" "\n" "Gebruikte diensten:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Geen hoezen gevonden" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Voorvertoningsgrootte" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Opslagmap" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Als dit geen jpeg-bestand is, dan wordt de afbeelding geconverteerd naar een " "jpeg van hoge kwaliteit" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Opslaan als jpeg" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Opdracht" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "naam" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "De naam van deze opdracht" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "opdracht" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "De uit te voeren shellopdrachtsyntaxis" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "opdrachtregeloptie" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Indien opgegeven: een opdrachtregeloptie waarvan de vermeldingen in de " "opdracht vervangen worden door een waarde opgegeven door de gebruiker. " "Voorbeeld: door ‘PARAM’ te gebruiken zullen alle vermeldingen van ‘{PARAM}’ " "in je opdracht de opgegeven waarde hebben als de opdracht wordt uitgevoerd." #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Het te gebruiken QL-patroon, bijv. <~filename>, voor het berekenen van een " "waarde van de opdracht. Afspeellijsten hebben ondersteuning voor " "<~playlistname> en <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "uniek" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Indien ingesteld zal dit dubbele berekende waarden van het patroon " "verwijderen" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "max. aantal opties" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Het maximumaantal opdrachtregelopties dat tegelijk aan de opdracht kan " "worden doorgegeven (zoals xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "Omkeren" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Stel in om de opdrachtregellijst om te keren" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Invoerwaarde" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Waarde van %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Aangepaste opdrachten" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Voert aangepaste opdrachten uit op nummers (evt. meerdere tegelijk) op basis " "van eender welke van hun tags." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Aangepaste opdrachten bewerken" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Kan aangepast opdracht \"%s\" niet uitvoeren" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d dubbele groep" msgstr[1] "%d dubbele groepen" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Alles in-/uitklappen" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Dubbele sleuteluitdrukking is ‘%s’" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Duplicaatverkenner" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Zoekt en toont gelijkaardig getagde versies van nummers." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "QL-taguitdrukkingen, zoals <tt>~artist~title</tt> of " "<tt>musicbrainz_track_id</tt>, worden aanvaard" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "Duplicaten _groeperen op:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Dubbele sleutel" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "_Witruimte verwijderen" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "_Diakritische tekens verwijderen" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "_Leestekens verwijderen" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "N_iet hoofdlettergevoelig" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Bijpassende opties" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Afspeeltelling bewerken" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Bewerk de <tt>~#playcount</tt> en ~<tt>#skipcount</tt> van een nummer.\n" "\n" "Indien meerdere nummers geselecteerd zijn, zullen de tellers verhoogd worden " "i.p.v. ingesteld.\n" "\n" "Indien de <tt>~#playcount</tt> van een nummer op 0 wordt gezet, zullen de " "<tt>~#lastplayed</tt>- en ~#<tt>laststarted</tt>-items worden gewist. Als " "echter aan een nummer dat nog nooit is afgespeeld een ‘playcount’ boven nul " "wordt toegekend, zullen geen speeltijden worden aangemaakt." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Aantal keer afgespeeld" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Aantal keer overgeslagen" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Meerdere %s waarden" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Bijgevoegde afbeeldingen bewerken" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Verwijdert of vervangt bijgevoegde afbeeldingen." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "Alle afbeeldingen ve_rwijderen" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "Huidige afbeeldingen bijvo_egen" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Exacte waardering instellen" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Sta toe nummers te waarderen met een getal." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Geef je gewenste waardering op op een schaal van 0.0 tot 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filteren op eender welke tag" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Maakt een zoekopdracht aan op basis van tags van de geselecteerde nummers." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filteren op map" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtert op map in een nieuw venster." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akoestische vingerafdruk opzoeken" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" "Zoekt metagegevens van nummers op op basis van akoestische vingerafdrukken." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Akoestische vingerafdrukken indienen" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Maakt akoestische vingerafdrukken aan op basis van chromaprint en dient ze " "in op acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "De api-sleutel ontbreekt" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Geef een acoustid.org api-sleutel op in de plug-invoorkeuren om " "vingerafdrukken in te dienen." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Api-sleutel aanvragen" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "Api-_sleutel:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID-webdienst" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "In wachtrij" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analyseren" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Opzoeken" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Schrijven" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Uitgave" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "MusicBrainz-tags wegschrijven" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Groeperen op map" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Albummodus" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Schrijf albumgerelateerde tags weg en probeer het aantal verschillende " "albumuitgaven te verminderen" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Aanmaken van vingerafdrukken:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Details" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "In_dienen" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Nummers hebben een <i><b>musicbrainz_trackid</b></i> of <i><b>artist</b></i>/" "<i><b>title</b></i>/<i><b>album</b></i>-tags nodig om ze te kunnen indienen." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Vingerafdrukken:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Nummers met MBID's:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Nummers met voldoende tags:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "In te dienen nummers:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Klaar. %(to-send)d/%(all)d in te dienen nummers." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Indienen van vingerafdrukken:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Bezig met indienen…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Tags in bestanden bijwerken" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Slaat de bestanden opnieuw op. Dit zorgt er voor dat afspeeltellingen en " "waarderingen actueel zijn." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exporteren naar html" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exporteert de gekozen nummerlijst naar html." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Versturen naar iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Uploadt nummers naar een iRiver iFP-apparaat." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Geen iFP-apparaat aangetroffen" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Er kan geen verbinding worden gemaakt met je iFP-apparaat. Controleer of het " "apparaat is ingeschakeld en aangesloten en of ifp-line (http://ifp-driver.sf." "net) geïnstalleerd is." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Bezig met uploaden: %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Kan <b>%s</b> niet uploaden. Het apparaat beschikt over onvoldoende vrije " "ruimte of is uitgeschakeld." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Fout tijdens uploaden" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Gegevens exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Labels exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Labels en gegevens exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Bestandsinformatie en gebruikersgegevens exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Bestandsinformatie en labels exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Bestandsinformatie, labels en gebruikersgegevens exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Import / Export" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Im- en exporteer labels en gebruikersgegevens." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Meer informatie" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, fuzzy, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "De term ‘gebruikersgegevens’ omvat alle afspeellijsten waar de geselecteerde " "nummers op voorkomen, evenals de volgende metagegevens:\n" "\n" "<tt>%s</tt>\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "Na het exporteren van een album kun je de gegevens importeren naar een " "andere versie van het album. De volgorde en het aantal kunnen echter " "afwijken. De plug-in zorgt dat de geëxporteerde gegevens overeenkomen met " "die van de nieuwe nummers, zelfs als de namen enigszins afwijken. De " "automatische overeenkomsten zijn niet altijd juist, dus pas onderstaande " "waarden niet teveel aan." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Actie na importeren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Om bevestiging vragen als aantal nummers afwijkt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Om bevestiging vragen als aantal albums afwijkt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Het percentage waaronder de gebruiker een handmatige controle dient uit te " "voeren en evt. de overeenkomende nummers dient te wijzigen." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Nummer-gelijkaardigheid:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Album-gelijkaardigheid:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Bestanden exporteren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Schone, duidelijke json wegschrijven (langzamer)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Exportbestanden verwijderen na importeren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importeren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Exportmap openen" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Schijven" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Nummers" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Artiest(en)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Einde van locatie" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Albums overeen laten komen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Doorgaan" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Er valt niks te importeren" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Exporteer iets alvorens te importeren." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "De index is beschadigd." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "De json-code in ‘%s’ kan niet worden verwerkt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "‘%s’ kan niet worden uitgelezen" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Bestandsnaam" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Nummers overeen laten komen" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "De hitlijsten worden bijgewerkt." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Reeds actueel." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "De hitlijst van week van %s wordt opgehaald." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronisatie voltooid." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Fout tijdens synchronisatie (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm-synchronisatie" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Werkt je verzamelingsstatistieken bij van je Last.fm-profiel." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Gebr_uikersnaam:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Sorteertags aanmaken" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Converteert album- en artiestennamen in sorteernamen, maar slecht." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Exporteren als m3u- of pls-afspeellijst" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exporteer nummers naar een m3u- of pls-afspeellijst." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Relatieve locaties gebruiken" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Absolute locaties gebruiken" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Kan niet wegschrijven naar <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Opnieuw indexeren" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Controleert op bestandswijzigingen en herlaadt/verwijdert nummers indien " "nodig." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Opnieuw indexeren" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analyse" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Nummer" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Voortgang" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Versterking" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Piek" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" "Er is <b>%(to-process)s</b> bij te werken album (van %(all)s totaal)" msgstr[1] "" "Er zijn <b>%(to-process)s</b> bij te werken albums (van %(all)s totaal)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyseert en werkt <a href=\"%(rg_link)s\">ReplayGain</a>-informatie bij " "met GStreamer. De resultaten worden gegroepeerd per album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://nl.wikipedia.org/wiki/Replay_Gain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "altijd" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "indien er RG-tags ontbreken" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "indien <b>album</b>-RG-tags ontbreken" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "Te verwerken al_bums:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Bestaande tags" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Tags splitsen" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Scheidt zowel het schijfnummer van het album als de versie in de titel." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Album splitsen" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Splits het schijfnummer." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/b" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Standaardwaarden" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Tap" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Tap BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Tap de BPM van het geselecteerde nummer." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Zoeken op website" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Doorzoekt de door jou opgegeven website aan de hand van eender welke " "nummertags.\n" "Ondersteunt patronen als <tt>%(pattern-example)s</tt>." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Zoek-urlpatronen" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Zoek-url's wijzigen" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Zoekopdrachten instellen…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Tag zoeken op Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Opent een verkennervenster met het Wikipedia-artikel over het album waarvan " "een nummer wordt afgespeeld." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Zoeken op %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Tags bewerken" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Zoeken mislukt" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "De tag \"%s\" kan niet worden gevonden." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Verzameling" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Bezig met controleren van aankoppelpunten" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Bezig met doorzoeken van verzameling" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Bezig met scannen van %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Bezig met laden van bestanden" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Bezig met verplaatsen van verzameling" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Bezig met verwijderen van verzamelingsbestanden" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Een muziekverzameling en -speler" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Laden van bestand mislukt: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Lijst met tags" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Toon beknopte uitvoer" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" "Het aantal te tonen kolommen en sorteervolgorde in de beknopte modus (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Ook programmatische tags tonen" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Onvoldoende opdrachtregelopties" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Te veel opdrachtregelopties" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Omschrijving" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Waarde" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Lijst met veelgebruikte tags" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Tags van het ene naar het andere bestand kopiëren" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Aanpassingen tonen, maar niet toepassen" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Tags overslaan die niet weggeschreven kunnen worden" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Kan tag \"{tagname}\" niet kopiëren naar bestand: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Tags bewerken in een tekstbewerker" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Bewerken afgebroken" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "De tekstverwerker ‘%(editor-name)s’ kan niet worden geopend." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Geen aanpassingen gevonden" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Stel een tag in en verwijder bestaande waarden" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Kan %(tag)r niet instellen op %(format)s-bestand ‘%(file)r’" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Tags verwijderen" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "De waarde is een reguliere uitdrukking" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Alle tags verwijderen" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan ‘--all’ niet combineren met ‘--regexp’" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Kan \"{tagname}\" niet wissen uit {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Tagwaarde verwijderen" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Tagwaarde toevoegen" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Kan %r niet instellen" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Bestandsinformatie tonen" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Stel de opgegeven afbeelding in als primaire bijgevoegde afbeelding en " "verwijder alle andere ingesloten afbeeldingen" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Laden van afbeeldingsbestand mislukt: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Bewerken van afbeelding niet ondersteund voor %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Alle bijgevoegde afbeeldingen verwijderen" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraheer bijgevoegde afbeeldingen naar %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "De locatie waar de afbeeldingen zullen worden opgeslagen (standaard is dit " "de werkmap)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Bestandsnamen wijzigen op basis van tags" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Tags invullen op basis van bestandslocatie" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Bestand" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Volgnummers toekennen aan alle bestanden" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Tags tonen op basis van opgegeven patroon" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Hulpinformatie tonen" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "‘%(column-id)s’ is geen geldige kolomnaam (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Onbekend" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Op volgorde" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Op volgorde" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Willekeurig" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "Willekeu_rig" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Voorkeur voor hoger gewaardeerd" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Voorkeur voor _hoger gewaardeerd" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Nummer herhalen" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Numme_r herhalen" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Alles herhalen" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "_Alles herhalen" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Eén nummer" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Eén _nummer" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Bufferen" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Kan geen GStreamer-pijplijn aanmaken (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Geen GStreamer-element gevonden om mediaformaat te verwerken" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Mediaformaat: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "De GStreamer-plug-in ‘%(name)s’ kan niet worden geïnitialiseerd" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "De GStreamer-uitvoerpijplijn die gebruikt wordt bij het afspelen. Laat leeg " "om de standaard pijplijn te gebruiken. Als de pijplijn een sink bevat, zal " "die worden gebruikt in plaats van de standaard." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Uitv_oerpijplijn:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Bufferduur:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "_Naadloos afspelen uitschakelen" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Het uitschakelen van naadloos afspelen kan nummerwisselproblemen bij sommige " "GStreamer-versies verhelpen" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "JACK gebruiken (indien beschikbaar)" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" "Gebruik `jackaudiosink` bij gebruik van een playbin-sink (indien beschikbaar)" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Automatisch verbinden met JACK-uitvoerapparaten" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Verbind automatisch met `jackaudiosink`" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Geen GStreamer-audiosink aangetroffen. Getracht: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Ongeldige GStreamer-uitvoerpijplijn" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Kan audio-uitvoer niet aanmaken" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Het audio-apparaat ‘%r’ is niet aangetroffen. Controleer je Xine-" "instellingen in ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "De module ‘{module}’ is niet aangetroffen. Wellicht moet je het pakket nog " "installeren?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Het GStreamer-element ‘{element}’ is niet aangetroffen." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Stel ListenBrainz in in het plug-invenster. Tot dan worden nummers niet " "ingediend." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Te veel mislukte indienpogingen (%d) - de offline-modus wordt ingesteld. " "Stel ListenBrainz in in het plug-invenster. Tot dan worden nummers niet " "ingediend." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz-indiening" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Dient beluisterde nummers in op ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Gebruikers_sleutel:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "T_ags:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Een lijst met mee te sturen tags. Deze is kommagescheiden en dubbele " "aanhalingstekens zijn toegestaan." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Nummers die overeenkomen met dit filter worden niet ingediend." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Wil je de plug-in '%(name)s' uitvoeren op %(count)s afspeellijst?" msgstr[1] "Wil je de plug-in '%(name)s' uitvoeren op %(count)s afspeellijsten?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "Plugin uitvoe_ren" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Gebruik" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Begin" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/B" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tijd" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Bladwijzernaam" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Bladwijzers" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filters" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Onlangs afges_peeld" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Onl_angs toegevoegd" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Alle nummer_s" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Op huidig(e) _genre(s)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Op huidige _artiest(en)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Op huidige al_bum" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Willekeurig _genre" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Willekeurige _artiest" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Willekeurig al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "De 40 nummers die je het vaakst hebt beluisterd (meer dan 40 als bepaalde " "nummers even vaak zijn afgespeeld)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Naam:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Waarde:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Opgeslagen waarden" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Opgeslagen waarden bewerken…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matisch" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Nummermodus" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albummodus" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "De_mpen" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_ReplayGain-modus" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nieuw(e) %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(onbekend)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Toevoegen" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "B_ewerken" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Tag-uitdrukking" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tag-uitdrukking, bijv. personen:echt of ~album~jaar" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Voer een nieuwe tag in" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Tag-uitdrukking" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Bestanden:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "De geselecteerde nummers worden verwijderd uit je verzameling en hun " "bestanden verwijderd van de schijf." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "De geselecteerde bestanden worden verwijderd van de schijf." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Wil je %(file_count)d bestand permanent verwijderen?" msgstr[1] "Wil je %(file_count)d bestanden permanent verwijderen?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Bestanden verwij_deren" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "De geselecteerde nummers worden verwijderd uit je verzameling en hun " "bestanden verplaatst naar de prullenbak." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "De geselecteerde bestanden worden verplaatst naar de prullenbak." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Wil je %(file_count)d bestand verplaatsen naar de prullenbak?" msgstr[1] "Wil je %(file_count)d bestanden verplaatsen naar de prullenbak?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Verplaatsen naar prullenbak" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Bezig met verplaatsen van %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Kan niet verplaatsen naar prullenbak" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "" "Het verplaatsen van een of meerdere bestanden naar de prullenbak is mislukt." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Bezig met verwijderen van %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Kan bestanden niet verwijderen" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Het verwijderen van een of meerdere bestanden mislukt." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Webbrowser" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Bezig met downloaden…" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "ontbreekt in %d nummer" msgstr[1] "ontbreekt in %d nummers" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "verschilt in %d nummer" msgstr[1] "verschilt in %d nummers" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Splitsen in _meerdere waarden" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Schijf losmaken van _album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "_Versie uit titel splitsen" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Componist losmaken van ar_tiest" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "_Uitvoerend artiest scheiden van artiest" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "_Uitvoerend artiest weghalen uit titel" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "_Oorspronkelijke artiest weghalen uit titel" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Tag toevoegen" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "_Programmatische tags tonen" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Toegang tot alle tags, inclusief door de computer aangemaakte tags, zoals " "MusicBrainz- of ReplayGain-tags" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Labels met _meerdere regels tonen" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "Toon labels met meerdere regels (bijv. songteksten) hier" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "Onge_daan maken" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "Op_slaan" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Instellen" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "Tag _splitsen" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "Waarde(n) _kopiëren" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Kan tag niet toevoegen" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Kan nummers niet toevoegen" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "De geselecteerde bestanden ondersteunen meerdere waarden van <b>%s</b> niet." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Ongeldige tag" msgstr[1] "Ongeldige tag" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Ongeldige tag <b>%s</b>\n" "\n" "De geselecteerde bestanden ondersteunen het bewerken van deze tag niet." msgstr[1] "" "Ongeldige tag <b>%s</b>\n" "\n" "De geselecteerde bestanden ondersteunen het bewerken van deze tag niet." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Ongeldige waarde" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Ongeldige waarde: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "De tag is mogelijk onjuist" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s is aangepast terwijl Quod Libet actief was. Opslaan zonder je " "verzameling opnieuw te doorzoeken kan andere aanpassingen aan het nummer " "overschrijven." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Kan nummer niet opslaan" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Het opslaan van %(file-name)s is mislukt. Het bestand is alleen-lezen, " "beschadigd of je hebt geen rechten om het aan te passen." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Meer opties…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "O_ngedaan maken" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Opnieuw" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "Ov_er" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Controleren op updates…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Plug-ins" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s en nog %(count)s andere" msgstr[1] "%(title)s en nog %(count)s anderen" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso-voorkeuren" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mappen" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nieuwe map…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "Alle onderliggende mappen _selecteren" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nieuwe map" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Geef de nieuwe map een naam:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Kan map niet aanmaken" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Kan map niet verwijderen" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Nummers" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "door %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disc %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Nummer %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Huidige _nummer" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "Weergave aanpass_en…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Er zijn geen nummers geselecteerd." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Geen nummers" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informatie" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Songtekst" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Geproduceerd door %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artiest" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artiesten" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "uitvoerend artiesten" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nooit" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d keer" msgstr[1] "%(n)d keer" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "toegevoegd" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "laatst afgespeeld" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "speelt" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "slaat over" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "waardering" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "locatie" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "duur" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formaat" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codering" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitsnelheid" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "bestandsgrootte" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "gewijzigd" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Aanvullend" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d geselecteerd" msgstr[1] "%d geselecteerd" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Het nummer is niet beschikbaar" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d nummer zonder album" msgstr[1] "%d nummers zonder album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Bepaalde discografie" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d nummer zonder artiest" msgstr[1] "%d nummers zonder artiest" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albums" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Totaalduur:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Totaalgrootte:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Bestanden" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "Online _bekijken" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Geen songtekst gevonden bij dit nummer." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Weet je zeker dat je alle nummers wilt verwijderen?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "De geselecteerde nummers worden verwijderd uit je verzameling." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Tonen" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Tonen" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Controleer of de kolommen aan de linkerkant overeenkomen met die aan de " "rechterkant. Als dat niet zo is, dan kun je hier de volgorde aanpassen " "(gebruik _ bij rijen die niet overeen moeten komen):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Volgorde aan rechterzijde:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Tagwijzigingen verwerpen?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "De tags zijn gewijzigd, maar niet opgeslagen. Wil je deze bestanden opslaan " "de wijzigingen verwerpen?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Onge_daan maken" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Bestand bestaat" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "%(file-name)s vervangen?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "Bestand ve_rvangen" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Actieve taken" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "Er worden %d taken uitgevoerd" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Willekeurige modus aan/uit" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Herhaalmodus aan/uit" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Evenementen" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Afspeelvolgorde" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Bewerken" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Naam wijzigen" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Zoekopdracht" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Hoezen" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plug-infouten" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Iedere status" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Ingeschakeld" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Uitgeschakeld" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Geen categorie" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Iedere categorie" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Geen plug-ins aangetroffen." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Plug-ins" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filteren op plug-instatus/tag" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filteren op soort plug-in" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filteren op plug-innaam of -omschrijving" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Fout_en tonen" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Schijf" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Nummer" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Groe_peren" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artiest" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Bestandsnaam" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Duur" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Automatisch schakelen naar huidige nummer" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Als het nummer dat afgespeeld wordt wordt aangepast, ga er dan naar toe in " "de nummerlijst" #: quodlibet/qltk/prefs.py:72 #, fuzzy msgid "_Sort songs when tags are modified" msgstr "Nummers sorteren als tags zijn aangepast" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "Sorteer nummers automatisch opnieuw als tags zijn aangepast" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Overige:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "B_ewerken…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Kolomkoppen toevoegen of verwijderen" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Zichtbare kolommen" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Titel bevat _versie" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album bevat schijfon_dertitels" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Artiest bevat alle _personen" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Bestandsnaam bevat _map" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Kolomvoorkeuren" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Kolommen aanpassen" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Huidige instellingen toepassen op nummerlijst, waarbij nieuwe kolommen aan " "het einde worden toegevoegd" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Nummerlijst" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Kolommen aanpassen" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Totaalduur" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globaal filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Deze opdracht toepassen bovenop alle anderen" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Zoeken" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Verkenners" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "_Meerdere waarderingen bevestigen" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Vragen om bevestiging om de waardering van meerdere nummers tegelijk aan te " "passen" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Eé_nklikwaarderingen inschakelen" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Waardeer door te klikken op de waardeerkolom in de nummerlijst" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Waarderingen" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Voorkeur voor bijg_evoegde hoes" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Gebruik de albumhoes die bijgevoegd is bij de audio (waar mogelijk) vóór " "andere bronnen" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "De te gebruiken albumhoezen (indien beschikbaar - jokertekens zijn " "toegestaan). Als je meer dan één wilt gebruiken, scheidt ze dan met komma's." #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "Bestandsnamen van _voorkeursafbeeldingen:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumhoes" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Afspelen" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Uitvoerinstellingen" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Schaal het volume van een nummer met deze waarde als er geen ReplayGain-" "informatie beschikbaar is" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Terug_valversterking (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Schaal volume van alle nummers met deze waarde zolang er geen clipping " "optreedt bij het resultaat" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Voorvers_terking (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "ReplayGain volume-aanpassing inschak_elen" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "ReplayGain volume-aanpassing" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "Afspelen her_vatten bij opstarten" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Speel automatisch de laatste muziek af die draaide tijdens de vorige sessie" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Stan_daardwaardering:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Waardeer_schaal:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesiaans gemiddelde-factor (C) voor geaggregeerde waarderingen.\n" "0 betekent een gebruikelijk gemiddelde; hogere waarden betekenen dat albums " "met weinig nummers minder extreme waarderingen zullen hebben. Als je deze " "waarde aanpast, wordt een herberekening voor alle albums uitgevoerd." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesiaans gemiddelde-waarde:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-mailadres:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Beoordelingen en afspeeltellingen worden voor dit e-mailadres bewaard" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Tagwijzigingen automatisch opslaan" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Sla aanpassingen aan tags op zonder bevestiging bij bewerken van meerdere " "bestanden" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Een lijst van te gebruiken scheidingstekens bij het splitsen van tagwaarden. " "De lijst is spatiegescheiden." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Tag _splitsen op:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Een lijst van te gebruiken scheidingstekens bij het splitsen van tagwaarden. " "De lijst is spatiegescheiden." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "_Subtag splitsen op:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Tags" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Tag bewerken" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Bijwerken voor nieuwe waarderingen" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "Verzameling _doorzoeken" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Controleren op aanpassingen aan je verzameling" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Verzameling o_pnieuw samenstellen" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Herlaad alle nummers in je verzameling. Dit kan lang duren." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Verborgen nummers" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Verzameling d_oorzoeken bij opstarten" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Mappen doorzoeken" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s en nog %(count)d" msgstr[1] "%(title)s en nog %(count)d" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Eigenschappen" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Wachtrij" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Wachtrij wissen" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Schakel de wachtrij uit om deze te negeren tijdens het afspelen" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Eenmalig" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Verwijder alle nummers uit de wachtrij nadat ze zijn afgespeeld" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Permanent" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Behoud alle nummers in de wachtrij nadat ze zijn afgespeeld" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modus" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Stoppen na einde" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d nummer (%(time)s)" msgstr[1] "%(count)d nummers (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Verzameling _verkennen" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Wachtrij tonen/verbergen" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Afspeelfout" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Verzamelingsmappen instellen?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Je hebt nog geen muziekverzameling samengesteld. Wil je dat nu doen?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Niet nu" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "Samen_stellen" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Kan nummers niet toevoegen" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s gebruikt een niet-ondersteund protocol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Ga naar spelend nummer" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Bestand" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Nummer" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "Weerga_ve" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Verkennen" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Bediening" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Hulp" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "M_ap toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Best_and toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Loc_atie toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Bladwijzers bewerken…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Stoppen" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Stoppen na dit nummer" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Sneltoetsen" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Online-hulp" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Zoekhulp" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Locatie toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Voer de locatie van een audiobestand in:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Kan locatie niet toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s is geen geldige locatie." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Muziek toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "M_appen toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Muziekbestanden" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "Best_anden toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Weet je zeker dat je alle nummers wilt verwijderen?" msgstr[1] "Weet je zeker dat je alle nummers wilt verwijderen?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Wachtrij" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Weet je zeker dat je de waardering van alle %d de nummers wilt aanpassen?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "De opgeslagen waarderingen worden verwijderd" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "Waardering ve_rwijderen" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "De waardering van alle geselecteerde nummers wordt veranderd in ‘%s’" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Waa_rdering veranderen" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Spaties vervangen door _onderliggende streepjes" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Puntkomma's/Dubbele punten vervangen door streepjes" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "bijv. \"iv: allegro.flac → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "_Windows-incompatibele tekens wissen" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "_Diakritische tekens wissen" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Niet-_ascii-tekens wissen" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Alleen k_leine letters gebruiken" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Bestandsnamen wijzigen" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Voorvertoning" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Bestandsnamen" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "Albu_mhoezen verplaatsen" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Neem ‘[albumart] filenames’ in het configuratiebestand door voor meer " "informatie" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "Albumhoezen _overschrijven" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "Lege mappen ve_rwijderen" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Albumhoezen" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nieuwe naam" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Kan bestandsnaam niet wijzigen" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Het wijzigen van de naam van <b>%(old-name)s</b> in <b>%(new-name)s</b> is " "mislukt. Mogelijk bestaat het doelbestand al of heb je geen rechten om het " "nieuwe bestand aan te maken of het oude te verwijderen." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "_Alle fouten negeren" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stoppen" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Doorgaan" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "De locatie is niet absoluut" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Het patroon\n" "\t<b>%s</b>\n" "bevat/maar begint niet op rootniveau. Om mappen met onjuiste namen te " "voorkomen dien je het patroon te ‘rooten’ door te beginnen met de map / of " "~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Nummers in de getoonde mappen worden toegevoegd aan je verzameling tijdens " "het verversen ervan" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "De nieuwe map wordt na het toevoegen doorzocht" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "De geselecteerde nummers worden verwijderd uit je verzameling" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Verplaatsen" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Verplaatst een hoofdmap (zonder bestanden) en migreert de metagegevens van " "alle opgegeven nummers." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Wil je {dir!r) en alle bijbehorende nummers verwijderen?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" "Wil je {n} verzamelingslocaties en alle bijbehorende nummers verwijderen?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Verzamelingslocatie verwijderen?" msgstr[1] "Verzamelingslocaties verwijderen?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Verwijderen" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Mappen kiezen" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Map kiezen" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Huidige/Nieuwe map kiezen voor {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Hiermee verplaats je QL-metagegevens:\n" "\n" "{old!r} -> {new!r}\n" "\n" "De audiobestanden worden niet verplaatst.\n" "Een back-up is echter aanbevolen (inclusief het Quodlibet ‘nummers’-bestand)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Hoofdmap verplaatsen?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "Verplaatsen die handel!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Opgeslagen zoekopdrachten" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Opgeslagen zoekopdrachten bewerken…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Doorzoek je verzameling met vrije tekst of QL-zoekopdrachten" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Zoeken na _typen" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Zoekresultaten tonen nadat stoppen met typen" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limiet:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "Z_waarte" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Zoekopdracht toevoegen" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Voeg een QL-zoekopdracht of vrije tekst toe om samen naar te zoeken" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Resterende tijd tonen" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hoofdvenster" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "10 seconden terugspoelen" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "10 seconden vooruitspoelen" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Zoekvak focussen" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Filters wissen en spelend nummer markeren" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Open het informatievenster van de geselecteerde nummers" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Open de tagbewerker van de geselecteerde nummers" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Selectie toevoegen aan wachtrij" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Selectie verwijderen" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Zoekvak tonen" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Klik links op een kolomkop" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Voeg de kolom toe aan de sorteerkolom" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Boomstructuurweergave" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Klapt het item in of selecteert het bovenliggende item" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Klapt het item uit" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Tekstitems" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Recentste aanpassing ongedaan maken" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Recentste aanpassing opnieuw uitvoeren" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Alle nummers in alle panelen selecteren" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filteren op %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Alle _koppen" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Nummerkoppen" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumkoppen" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Persoonkoppen" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Datumkoppen" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Bestandskoppen" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Productiekoppen" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "Kop_pen aanpassen…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "Kolom uitvouw_en" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Wil je \"%%(title)s\" ve_rwijderen uit je verzameling?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Wil je \"%%(title)s\" ve_rwijderen uit je verzameling?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Ve_rwijderen uit verzameling" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Wil je de plug-in \"%(name)s\" uitvoeren op %(count)d nummer?" msgstr[1] "Wil je de plug-in \"%(name)s\" uitvoeren op %(count)d nummers?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Wil je de plug-in \"%(name)s\" uitvoeren op %(count)d album?" msgstr[1] "Wil je de plug-in \"%(name)s\" uitvoeren op %(count)d albums?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Plug-ins instellen…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Toevoegen aan _wachtrij" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "Ve_rwijderen uit verzameling…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Kan bestanden niet tonen" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "De bestanden kunnen niet worden getoond of er is geen programma dat ze kan " "tonen." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "Tonen in bestand_sbeheerder" msgstr[1] "%(total)d bestanden tonen in bestand_sbeheerder" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "Bestand _downloaden…" msgstr[1] "%(total)d bestanden downloaden…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "Voltooid" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "mislukt" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Het downloaden is voltooid" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "{name!r} opslaan in" msgstr[1] "{total} bestanden opslaan in" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Hier opslaan" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "_Onderliggende streepjes vervangen door spaties" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Tags met hoofdletters" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Splitsen in meerdere _waarden" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tags vanuit locatie" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Tags vervangen bestaande tags" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Tags worden toegevoegd aan bestaande tags" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Het patroon\n" "\t<b>%s</b>\n" "is ongeldig. Mogelijk bevat het tweemaal dezelfde tag of heeft het " "onvoldoende haakjes (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Het patroon dat je hebt ingevoerd is onjuist. Controleer of je < en > " "hebt ingevoerd als \\< en \\> en dat de tags voldoende zijn.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Weergave aanpassen" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Volgnummers" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Beginnen b_ij:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Totaalaantal:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Afspelen/Pauzeren" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Vorige" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "en nog %d…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Slaat de aangepaste nummers op." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d nummers opgeslagen\n" "(%(remaining)s resterend)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s van %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Bezig met controleren op updates" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Verbinding mislukt" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Je beschikt al over de nieuwste versie (%(version)s)" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Er is een nieuwe versie (%(new-version)s) beschikbaar\n" "\n" "Momenteel gebruik je versie %(old-version)s\n" "\n" "Ga naar de <a href='%(url)s'>website</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Lege afspeellijst" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Afspeellijsten moeten een naam hebben" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Er is al een afspeellijst met deze naam (\"%(name)s\") in %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Bijgevoegde albumhoezen" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Gebruik albumhoezen bijgevoegd bij audiobestanden." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Bestandssysteemhoes" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Gebruikt afbeeldingen die vaak worden gebruikt in dezelfde map als het " "nummer als albumhoes." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Albumhoezen" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Bezig met opvragen bij albumhoesdiensten" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Toon korte gebruiksinformatie" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Toon versie en auteursrecht" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Toon foutopsporingsinformatie" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Gebruik: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opties]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "De optie ‘%r’ wordt niet herkend." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "De optie ‘%r’ vereist een opdrachtregeloptie." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "‘%r’ is geen uniek voorvoegsel." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s seconde" msgstr[1] "%s seconden" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Geen tijdsinformatie" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d seconden" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuut" msgstr[1] "%d minuten" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d uur" msgstr[1] "%d uur" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dagen" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d jaar" msgstr[1] "%d jaar" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "hoofdletters?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "De datum moet ingevoerd worden in ‘JJJJ’-, ‘JJJJ-MM-DD’- of ‘JJJJ-MM-DD UU:" "MM:SS’-formaat." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" "ReplayGain-versterkingen dienen te worden ingevoerd in ‘x.yy dB’-opmaak." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "ReplayGain-pieken dienen te worden ingevoerd in ‘x.yy’-opmaak." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz id's dienen in uuid-opmaak te zijn." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "De MusicBrainz-uitgavestatus moet ‘official’, ‘promotional’ of ‘bootleg’ " "zijn." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "De taal moet een ISO 639-2 drielettercode zijn" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Opslaan mislukt" msgstr[1] "Opslaan mislukt" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Kan nummer niet aanpassen" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Kan <b>%s</b> niet opslaan. Het bestand is alleen-lezen, beschadigd of je " "hebt geen toestemming om het aan te passen." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[ongeldige codering]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangeur" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangeurs" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arrangement" #: quodlibet/util/tags.py:86 msgid "author" msgstr "auteur" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "auteurs" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "opmerking" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "componist" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "componisten" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "compositie" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenten" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigeren" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contact" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "auteursrecht" #: quodlibet/util/tags.py:93 msgid "date" msgstr "datum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "omschrijving" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "genres" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "uitvoerend artiest" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "uitvoering" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "groeperen" #: quodlibet/util/tags.py:98 msgid "language" msgstr "taal" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licentie" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "tekstschrijver" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "tekstschrijvers" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "songtekst" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisatie" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titel" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versie" #: quodlibet/util/tags.py:106 msgid "website" msgstr "website" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albumartiest" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "schijfondertitel" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "schijf" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "nummer" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "label-id" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "oorspronkelijke uitgavedatum" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "oorspronkelijk album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "oorspronkelijke artiest" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "opnamedatum" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "land van uitgave" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "initiële sleutel" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz-opname-id" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz-uitgavenummer-id" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz-uitgave-id" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz-artiest-id" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz-uitgave-artiest-id" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM-id" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz-albumstatus" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz-albumsoort" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz-uitgavegroep-id" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "nummerversterking" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "nummerpiek" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albumversterking" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albumpiek" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "indicatieve geluidssterkte" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "schijven" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "nummers" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "recentst gestart" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "volledige naam" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "aankoppelpunt" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personen" #: quodlibet/util/tags.py:168 msgid "year" msgstr "jaar" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "oorspronkelijke uitgavedatum" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "bladwijzer" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bitdiepte" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "bestandsformaat" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "afspeellijsten" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "samplesnelheid" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "aantal kanalen" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "sorteren" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "rollen" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Audiotagbewerker" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Bewerk tags in je audiobestanden" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Muziekspeler" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Luister naar, doorzoek of bewerk je audioverzameling" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso is een tagbewerker met dezelfde tagbewerkingsvormgeving als Quod " "Libet. Het laat je eender welke tags in het bestand zien en bewerken van " "alle ondersteunde bestandsindelingen." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Ondersteunde bestandsindelingen zijn onder andere ogg vorbis/opus/speex/" "flac, mp3, flac, mod/xm/it, musepack, wavpack, mpeg-4 aac, monkeys audio, " "wma, spc en midi." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet is een programma voor het beheren van je muziek. Het biedt " "verschillende manieren om je audioverzameling te tonen en ondersteunt online-" "radiostations en audiofeeds. Het biedt zeer flexibele mogelijkheden om " "metagegevenstags te bewerken en je verzameling te doorzoeken." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Exporteert een afspeellijst als Sonos-afspeellijst, mits deze dezelfde " #~ "mappenstructuur delen." #~ msgid "Export to Sonos playlist" #~ msgstr "Exporteren naar Sonos-afspeellijst" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Kan <b>%s</b> niet toevoegen" #~ msgid "Invalid tags" #~ msgstr "Ongeldige tags" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Ongeldige tags <b>%s</b>\n" #~ "\n" #~ "De geselecteerde bestanden ondersteunen het bewerken van deze tags niet." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Geeft nummers automatisch een waardering als ze worden afgespeeld of " #~ "overgeslagen. Dit gebruikt het ‘accelerated’-algoritme van vux door Brian " #~ "Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f seconden" #~ msgid "Startup" #~ msgstr "Opstarten" #~ msgid "Audio Feeds" #~ msgstr "Audiofeeds" #~ msgid "_Audio Feeds" #~ msgstr "_Audiofeeds" #~ msgid "New" #~ msgstr "Nieuw" #~ msgid "Automatic Library Update" #~ msgstr "Verzameling automatisch bijwerken" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Gebruik inotify om je verzameling actueel te houden. Vereist %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Staat bediening van Quod Libet met behulp van de MPRIS 1.0/2.0 D-Bus " #~ "Interface-specificatie toe." #~ msgid "Searching for lyrics…" #~ msgstr "Bezig met zoeken naar songtekst…" #~ msgid "Shares configuration with %(plugin)s." #~ msgstr "Deelt zijn configuratie met %(plugin)s." #~ msgid "Shares configuration with %(plugin)s" #~ msgstr "Deelt zijn configuratie met %(plugin)s" #~ msgid "" #~ "Analyzes and updates %(rg_link)s information, using GStreamer. Results " #~ "are grouped by album." #~ msgstr "" #~ "Analyseert en werkt %(rg_link)s-informatie bij met GStreamer. De " #~ "resultaten worden gegroepeerd per album." #~ msgid "broker username" #~ msgstr "broker-gebruikersnaam" #~ msgid "broker password" #~ msgstr "broker-wachtwoord" #~ msgid "<artist>" #~ msgstr "<artiest>" #~ msgid "<album>" #~ msgstr "<album>" #~ msgid "<title>" #~ msgstr "<titel>" #~ msgid "OK" #~ msgstr "Oké" #~ msgid "" #~ "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " #~ "both share a directory structure. Shares configuration with <a href=" #~ "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</" #~ "a>." #~ msgstr "" #~ "Exporteert dynamisch een afspeellijst naar een Logitech Squeezebox-" #~ "afspeellijst, mits beide een mappenstructuur delen. Deelt configuratie " #~ "met de <a href=\"quodlibet:///prefs/plugins/Squeezebox Output" #~ "\">Squeezebox Sync-plug-in</a>." #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Exporteer metagegevens van geselecteerde nummers naar een .tags-bestand." #~ msgid "Import Metadata" #~ msgstr "Metagegevens importeren" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Importeer metagegevens van geselecteerde nummers uit een .tags-bestand." #~ msgid "Migrate Metadata" #~ msgstr "Metagegevens exporteren" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "" #~ "Synchroniseert de Quod Libet-specifieke metagegevens tussen nummers." #~ msgid "_Copy" #~ msgstr "_Kopiëren" #~ msgid "_Paste" #~ msgstr "_Plakken" #~ msgid "Information to copy/paste" #~ msgstr "De te kopiëren/plakken informatie" #~ msgid "Map tracks by disc and track number" #~ msgstr "Schijf- en volgnummer toekennen aan nummers" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Schakel dit in als je metagegevens wilt migreren van het ene naar het " #~ "andere album, maar ook de schijf- en volgnummers wilt behouden.\n" #~ "\n" #~ "<b>Let op:</b> dit dient te worden ingeschakeld om nummerinformatie vast " #~ "te leggen." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Er is %d opgeslagen nummer." #~ msgstr[1] "Er zijn %d opgeslagen nummers." #~ msgid "No lyrics found" #~ msgstr "Geen songteksten gevonden" #~ msgid "_Zoom level:" #~ msgstr "_Zoomniveau:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Revert to default" #~ msgstr "Standaardwaarden" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Gebruik bovenstaande url om te zoeken naar songteksten als ze niet kunnen " #~ "worden gevonden op LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternatieve zoekopdracht" #~ msgid "Web Lyrics" #~ msgstr "Online-songteksten" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "Toont een zijbalk met de songtekst van het huidige nummer." #~ msgid "Burn CD" #~ msgstr "CD branden" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Brand cd's met K3b, Brasero of xfburn." #~ msgid "Unsupported file type" #~ msgstr "Niet-ondersteund bestandstype" #~ msgid "Unable to add station" #~ msgstr "Kan zender niet toevoegen" #~ msgid "Skip Songs" #~ msgstr "Nummers overslaan" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "Nummers met een waardering gelijk aan of lager dat deze waarde worden " #~ "overgeslagen." #~ msgid "Device Properties" #~ msgstr "Apparaateigenschappen" #~ msgid "Device:" #~ msgstr "Apparaat" #~ msgid "Not mounted" #~ msgstr "Niet gekoppeld" #~ msgid "Mount point:" #~ msgstr "Koppelpunt:" #~ msgid "Media Devices" #~ msgstr "Media-apparaten" #~ msgid "_Media Devices" #~ msgstr "_Media-apparaten" #~ msgid "_Eject" #~ msgstr "Uitwerp_en" #~ msgid "_Properties" #~ msgstr "Eigenscha_ppen" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s gebruikt, %(free-size)s beschikbaar" #~ msgid "%s is not connected." #~ msgstr "%s is niet aangesloten." #~ msgid "Copying %(song)s" #~ msgstr "Kopiëren van %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Kan nummer niet kopiëren" #~ msgid "There is not enough free space for this song." #~ msgstr "Er is onvoldoende beschikbare ruimte voor dit nummer." #~ msgid "%s could not be copied." #~ msgstr "%s kon niet worden gekopieerd." #~ msgid "Unable to delete songs" #~ msgstr "Kan nummers niet verwijderen" #~ msgid "Deleting %(song)s" #~ msgstr "Verwijderen van %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s kon niet worden verwijderd." #~ msgid "Unable to delete song" #~ msgstr "Kan nummer niet verwijderen" #~ msgid "Ejecting %s failed." #~ msgstr "Uitwerpen van %s mislukt." #~ msgid "Unable to eject device" #~ msgstr "Kan apparaat niet uitwerpen" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "Geen apparaatsbackend, media-apparatenbrowser uitgeschakeld." #~ msgid "Search Library" #~ msgstr "Doorzoek bibliotheek" #~ msgid "_Search Library" #~ msgstr "_Doorzoek bibliotheek" #~ msgid "Rate the playing song" #~ msgstr "Beoordeel het spelende nummer" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Hoofdsonglijst tonen of verbergen" #~ msgid "Unknown Device" #~ msgstr "Onbekend apparaat" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Kon %s niet importeren, wat nodig is voor apparaatsondersteuning." #~ msgid "%r is not a supported device." #~ msgstr "%r is geen ondersteund apparaat." #~ msgid "Initializing device backend." #~ msgstr "Apparaatsbackend wordt geïnitialiseerd." #~ msgid "Trying '%s'" #~ msgstr "'%s' proberen" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Kon niet verbinden met een apparaatsbackend." #~ msgid "Device backend initialized." #~ msgstr "Apparaatsbackend geïnitialiseerd." #~ msgid "_Filename pattern:" #~ msgstr "_Bestandsnaampatroon:" #, fuzzy #~ msgid "Quit Program" #~ msgstr "_Programma:" #~ msgid "Top of screen" #~ msgstr "Bovenkant van scherm" #~ msgid "Middle of screen" #~ msgstr "Midden van scherm" #~ msgid "Bottom of screen" #~ msgstr "Onderkant van scherm" #~ msgid "_Clear" #~ msgstr "W_issen" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Voorkomt activatie van de GNOME-schermbeveiliging wanneer een liedje " #~ "wordt afgespeeld." #~ msgid "Lyrics:" #~ msgstr "Teksten:" #~ msgid "Lyrics Window" #~ msgstr "Tekstvenster" #~ msgid "_Lyrics" #~ msgstr "Te_ksten" #~ msgid "Browse Folders" #~ msgstr "Bladeren door mappen" #~ msgid "Opens the songs' folders in a file manager." #~ msgstr "Opent de mappen van de nummers in een bestandsbeheerder." #~ msgid "Unable to open folders" #~ msgstr "Kan mappen niet openen" #~ msgid "No program available to open folders." #~ msgstr "Geen programma beschikbaar voor het openen van mappen." #, fuzzy #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Biedt ondersteuning voor QL-patronen\n" #~ "bv. <tt><~artist~title></tt>" #~ msgid "Fix MP3 Duration" #~ msgstr "Corrigeer MP3-duur" #~ msgid "" #~ "Removes TLEN frames from ID3 tags which can be the cause for invalid song " #~ "durations." #~ msgstr "" #~ "Verwijdert TLEN-frames van ID3-tags die kunnen leiden tot het onjuist " #~ "weergeven van de duur van nummers." #~ msgid "Search Artist in Wikipedia" #~ msgstr "Zoek artiest op Wikipedia" #~ msgid "" #~ "Opens a browser window with Wikipedia article on the playing song artist." #~ msgstr "" #~ "Opent een browservenster met het Wikipedia-artikel over de artiest " #~ "waarvan een nummer wordt afgespeeld." #~ msgid "Audio device: %s" #~ msgstr "Audio-apparaat: %s" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgid "Size" #~ msgstr "Grootte" #~ msgid "_Download" #~ msgstr "_Download" #~ msgid "The single image filename to use if selected" #~ msgstr "De te gebruiken bestandsnaam voor afbeeldingen indien geselecteerd" #~ msgid "The album art image file to use when forced" #~ msgstr "Het te gebruiken albumhoesbestand indien gedwongen" #~ msgid "_Copy to Device" #~ msgstr "_Kopieer naar apparaat" #~ msgid "Save" #~ msgstr "Opslaan" #, fuzzy #~ msgid "browsers" #~ msgstr "Browsers" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Kon %s niet importeren. Audiofeedsbrowser uitgeschakeld." #~ msgid "Controls the tone of your music with an equalizer." #~ msgstr "Bepaalt de toon van je muziek met een equalizer." #~ msgid "Event Logging" #~ msgstr "Evenementloggen" #~ msgid "Sends song events to the Zeitgeist event logging service." #~ msgstr "Stuurt songevenementen naar de Zeitgeist evenementlogdienst." #~ msgid "Audio Backend Failed to Load" #~ msgstr "Kon de audio-backend niet laden" #~ msgid "" #~ "Loading the audio backend '%(name)s' failed. Audio playback will be " #~ "disabled." #~ msgstr "" #~ "Laden van audio-backend '%(name)s' mislukt. Afspelen van audio zal worden " #~ "uitgeschakeld." #~ msgid "_Open" #~ msgstr "_Openen" #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Een fout is opgetreden in Quod Libet. Een dumpbestand is opgeslagen in <b " #~ ">%(dump-path)s</b> dat ons zal helpen de crash te analyseren. Gelieve het " #~ "probleem te melden op %(new-issue-url)s en voeg dit bestand of de inhoud " #~ "ervan toe. Dit bestand kan identificeerbare informatie over jou of je " #~ "systeem bevatten, zoals een lijst van recent gespeelde bestanden. Als dit " #~ "niet aanvaardbaar is voor je, kan je <b>%(mini-dump-path)s</b> sturen met " #~ "een beschrijving van wat je deed toen de fout optrad." #~ msgid "" #~ "Quod Libet may now be unstable. Closing it and restarting is recommended. " #~ "Your library will be saved." #~ msgstr "" #~ "Quod Libet kan nu onstabiel zijn, het opnieuw opstarten is aangeraden. Je " #~ "bibliotheek zal worden opgeslagen." #~ msgid "Unable to download lyrics." #~ msgstr "Kan tekst niet downloaden." #~ msgid "Set or toggle the playback order" #~ msgstr "Stel de afspeelvolgorde in of wissel ze" #~ msgid "Uninitialized iPod" #~ msgstr "Ongeïnitialiseerde iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Wil je een lege database aanmaken op deze iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volume gain (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combineer tags met _meerdere waarden" #~ msgid "Capacity:" #~ msgstr "Capaciteit:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Saving iPod database…" #~ msgstr "iPod-database wordt opgeslagen…" #~ msgid "Unable to save iPod database" #~ msgstr "Kan iPod-database niet opslaan" #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Kon libgpod niet vinden, iPod-ondersteuning uitgeschakeld." #~ msgid "Playback follows your selection." #~ msgstr "Afspelen volgt je selectie" #~ msgid "Track Repeat" #~ msgstr "Track herhalen" #~ msgid "Shuffle" #~ msgstr "Shuffle" #~ msgid "Weighted" #~ msgstr "Gewogen" #~ msgid "_Weighted" #~ msgstr "Ge_wogen" #~ msgid "_One Song" #~ msgstr "_Één nummer" #~ msgid "Restart the playlist when finished" #~ msgstr "Start de speellijst opnieuw nadat alle nummers gespeeld zijn" #~ msgid "Disable Browser" #~ msgstr "Zet browser uit" #~ msgid "_Disable Browser" #~ msgstr "_Zet browser uit" #~ msgid "Use header bars" #~ msgstr "Gebruik headerbars" #~ msgid "Force Write" #~ msgstr "Schrijven dwingen" #~ msgid "Filter on _Genre" #~ msgstr "Filter op _genre" #~ msgid "Filter on _Artist" #~ msgstr "Filter op _artiest" #~ msgid "Filter on Al_bum" #~ msgstr "Filter op al_bum" #~ msgid "_Music" #~ msgstr "_Muziek" #~ msgid "Add Bookmark" #~ msgstr "Bladwijzer toevoegen" #~ msgid "Song _List" #~ msgstr "Song_lijst" #, fuzzy #~ msgid "Rate the selected songs with 0-4 stars" #~ msgstr "Exporteert de gekozen songlijst naar HTML." #~ msgid "Embed cover" #~ msgstr "Albumhoes inbedden" #~ msgid "D:" #~ msgstr "D:" #~ msgid "W:" #~ msgstr "W:" #~ msgid "E:" #~ msgstr "E:" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Scrollwiel verandert liedje\n" #~ "Shift en scrollwiel verandert volume" #~ msgid "Stop _after this song" #~ msgstr "Stop n_a deze song" #~ msgid "_Release:" #~ msgstr "_Release:" #~ msgid "%d _release:" #~ msgid_plural "%d _releases:" #~ msgstr[0] "%d _release:" #~ msgstr[1] "%d _releases:" #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "%d resultaat gevonden." #~ msgstr[1] "%d resultaten gevonden." #~ msgid "Split _disc from album" #~ msgstr "Splits _disc van album" #~ msgid "Split _featured performers from track" #~ msgstr "Splits uit_voerenden uit track" #~ msgid "Write _labelid tag (fixes multi-disc albums)" #~ msgstr "Schrijf _labelid-tags (oplossing voor multi-disc albums)" #~ msgid "CDDB Lookup" #~ msgstr "CDDB opzoeken" #~ msgid "Looks up album information in FreeDB. Requires CDDB.py." #~ msgstr "Zoekt albuminformatie op FreeDB. Vereist CDDB.py." #~ msgid "Timeout" #~ msgstr "Time-out" #~ msgid "Query could not be executed, connection timed out" #~ msgstr "Zoekopdracht kon niet worden uitgevoerd, time-out bij verbinden" #~ msgid "Select an album" #~ msgstr "Kies een album" #~ msgid "Select the album you wish to retrieve." #~ msgstr "Kies het album dat je wil ophalen." #~ msgid "CDDB lookup failed (%s)" #~ msgstr "CDDB opzoeken mislukt (%s)" #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s en %(count)d meer…" #~ msgstr[1] "%(title)s en %(count)d meer…" #~ msgid "Send To…" #~ msgstr "Sturen naar…" #~ msgid "Generic file-opening plugin." #~ msgstr "Algemene plugin voor openen van bestanden." #~ msgid "Playlist Export" #~ msgstr "Speellijst exporteren" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "Gebr_uik ronde hoeken voor miniaturen" #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "Rondt de hoeken van albumhoezen in miniaturen af." #~ msgid "Re_fresh Library" #~ msgstr "Ver_vers bibliotheek" #~ msgid "_Remove rating" #~ msgstr "Waardering ve_rwijderen" #~ msgid "Unable to open input files" #~ msgstr "Kan invoerbestanden niet openen" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer heeft geen element voor het lezen van bestanden. Controleer de " #~ "instellingen van je GStreamer-installatie." #~ msgid "Invalid audio backend" #~ msgstr "Ongeldige audio-backend" #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "De audio-backend '%(backend-name)s' kon niet geladen worden." #~ msgid "ql-save" #~ msgstr "ql-opslaan" #~ msgid "ql-revert" #~ msgstr "ql-omkeren" #~ msgid "command|filename" #~ msgstr "bestandsnaam" #~ msgid "command|tag" #~ msgstr "tag" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Zoek" #~ msgid "%d of %d" #~ msgstr "%d van %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Gebruik: %s %s" #~ msgid "_Download..." #~ msgstr "_Download..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nieuw Station" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "<b>%s</b> overschrijven?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet draait al" #~ msgid "No song is currently playing." #~ msgstr "Momenteel wordt geen song gespeelt." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Niet in staat om naar %s te schrijven." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Bewerk Bookmarks..." #~ msgid "_New Folder..." #~ msgstr "_Nieuwe Folder..." #~ msgid "_Add to Playlist" #~ msgstr "_Voeg Toe Aan Speellijst" #~ msgid "_Edit Display..." #~ msgstr "_Bewerk Weergave..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d station" #~ msgid "_Add a Location..." #~ msgstr "_Voeg Locatie Toe..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Pas Headers Aan" #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Trackheaders" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Mensenheaders" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Albumheaders" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Datumheaders" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Bestandsheaders" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Productieheaders" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tag:" #, fuzzy #~ msgid "Warnings" #~ msgstr "_Cijfer" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "albumartiest" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artiesten" #, fuzzy #~ msgid "album (sort)" #~ msgstr "albumartiest" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "uitvoerenden" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "uitvoerenden" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artiest ID" #~ msgid "errors" #~ msgstr "errors" #~ msgid "Permanently delete this file?" #~ msgstr "Permanent dit bestand verwijderen?" #~ msgid "Permanently delete these files?" #~ msgstr "Permanent deze bestanden verwijderen?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s en %(count)d meer..." #~ msgstr[1] "%(title)s en %(count)d meer..." #, fuzzy #~ msgid "Version:" #~ msgstr "versie" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "_Schoon Fouten" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s kon niet worden toegevoegd aan je collectie.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Geen verwijder commando gevonden." #~ msgid "Unable to start web browser" #~ msgstr "Niet in staat om een webbrowser te starten" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Een web browser kon niet niet gevonden worden Stel alstublieft uw " #~ "$BROWSER variabele in, of controleer that /usr/bin/sensibe-browser " #~ "bestaat." #, fuzzy #~ msgid "Library Error" #~ msgstr "Bibliotheek Browser" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Kopiëer naar device " #~ msgid "translator-credits" #~ msgstr "Hans van Dok" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Andere kopjes om weer te geven, gescheiden door spaties" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Ga door" #, fuzzy #~ msgid "Confirm rating" #~ msgstr "Informatie" #~ msgid "Search your library" #~ msgstr "Zoek in je audio collectie" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, en anderen\n" #~ "\n" #~ "Dit is vrije software; zie de broncode voor kopieer-voorwaarder. Er is " #~ "GEEN\n" #~ "garantie; zelfs niet voor VERKOOPBAARHEID of NUT VOOR EEN GEGEVEN DOEL.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "totale grootte:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet Plugins" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Geef eenvoudige zoekopdrachten weer in blauw, ingewikkelde in groen, en " #~ "ongeldige in rood" #~ msgid "Separators for splitting tags" #~ msgstr "Seperatoren om tags the splitsen" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet Voorkeuren" #~ msgid "Not Played To_day" #~ msgstr "Vandaag Niet Ge_speeld" #~ msgid "Not Played in a _Week" #~ msgstr "Een _Week Niet Gespeeld" #~ msgid "Not Played in a _Month" #~ msgstr "Een _Maand Niet Gespeeld" #~ msgid "B_ottom 40" #~ msgstr "_Onderste 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "De 40 songs die je het minst heb beluisterd (meer dan 40 kunnen worden " #~ "gekozen als er sprake is van gelijkspel)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-spelend | controle ]" #, fuzzy #~ msgid "Date" #~ msgstr "Dat_um" #~ msgid "Choose New Stations" #~ msgstr "Kies Nieuwe Stations" #~ msgid "Add" #~ msgstr "Voeg toe" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stations..." #~ msgid "Unable to save library" #~ msgstr "Niet in staat om collectie op te slaan" #~ msgid "Sort by title" #~ msgstr "Sorteer op titel" #~ msgid "Sort by artist" #~ msgstr "Sorteer op artiest" #~ msgid "Lyrics provided by %s." #~ msgstr "Tekst gegeven door %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Geen tekst gevonden.\n" #~ "\n" #~ "Je kunt clicken op de Download knop om Quod Libet online te laten zoeken " #~ "naar de tekst. Je kunt ze ook zelf invoeren en op save clicken. " #~ msgid "part" #~ msgstr "deel" #~ msgid "Opening audio device." #~ msgstr "Opent audio device" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d songs opgeslagen" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album ID" #~ msgid "Loaded song library." #~ msgstr "geladen song collectie" #~ msgid "Unable to open audio device" #~ msgstr "Niet in staat om audio device te openen" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet probeerde toegang the krijgen tot de 'autosink' en '%(sink)s' " #~ "drivers maar kon ze niet openen. Set je GStreamer pipeline door de regel\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "aan te passen in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet kon het 'filesrc' GStreamer element niet vinden. Check je " #~ "GStreamer installatie." ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/pl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000722346�14436352625�013624� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Polish translation for quodlibet. # Copyright © 2005-2020 the quodlibet authors. # This file is distributed under the same license as the quodlibet package. # msgid "" msgstr "" "Project-Id-Version: quodlibet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/pl/>\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit;\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Tytuł" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "osoby" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "Da_ta" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Nagłówki _dat" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Oryginalna data" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Gatunek" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Ocena" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Liczba odtworzeń" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Porządkowanie _według…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Preferencje" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista albumów" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Lista _albumów" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Wszystkie albumy" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albumy" msgstr[2] "%d albumów" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Ponownie wczytaj o_kładkę albumu" msgstr[1] "Ponownie wczytaj o_kładki albumów" msgstr[2] "Ponownie wczytaj o_kładki albumów" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Utwory nieprzypisane do albumów" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d ścieżka" msgstr[1] "%d ścieżki" msgstr[2] "%d ścieżek" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d płyta" msgstr[1] "%d płyty" msgstr[2] "%d płyt" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Przykładowy album" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferencje listy albumów" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Wyświetlanie o_kładek albumów" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Wewnętrzne wy_szukiwanie obejmuje osoby" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opcje" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Lista albumów" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "Za_mknij" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Przeglądarka kolekcji" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d utwór" msgstr[1] "%d utwory" msgstr[2] "%d utworów" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Nieprawidłowy wzorzec" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Kolekcja albumów" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Kolekcja albumów" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Nieznane %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Wiele wartości %s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Niestandardowe" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Dodaj" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Usuń" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etykieta" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Połącz" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Preferencje kolekcji albumów" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Zastosuj" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Anuluj" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Siatka okładek" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Siatka okładek" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Preferencje siatki okładek" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "_Wyświetlanie tekstów albumów" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Wyświetlanie elementu „Wszystkie albumy”" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Tryb szeroki" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Powiększanie okładek" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "System plików" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_System plików" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nie można skopiować utworów" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Nie można skopiować wybranych plików do innych list utworów lub kolejki." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Dodaj do kolekcji" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Lista stacji może zawierać tylko położenia stacji, a nie ich listy lub listy " "odtwarzania. Następujące położenia nie mogą zostać wczytane:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio internetowe" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Wszystkie stacje" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Pobieranie listy stacji" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nowa stacja" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Położenie internetowej stacji radiowej:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektroniczne" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip-hop/rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japońskie" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indyjskie" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religijne" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Listy przebojów" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Tureckie" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latynoskie" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Radia uniwersyteckie" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Talk-show/wiadomości" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasyczna" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Wiadomości" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Słowiańskie" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Greckie" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Wczytać listę popularnych stacji radiowych?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Wczytaj stacje" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Radio _internetowe" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Wszystkie stacje" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Ulubione" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Bez kategorii" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nowa stacja…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "Zakt_ualizuj stacje" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nie odnaleziono żadnych stacji" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nie odnaleziono internetowych stacji radiowych w %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Wszystkie podane stacje już znajdują się w kolekcji." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Dodaj do ulubionych" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Usuń z ulubionych" #: quodlibet/browsers/iradio.py:973 #, fuzzy, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d utwór (%(time)s)" msgstr[1] "%(count)d utwory (%(time)s)" msgstr[2] "%(count)d utworów (%(time)s)" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Przeglądarka panelowa" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Przeglądarka panelowa" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Z_aznacz wszystko" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nieznany" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Wszystkie" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Mały" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Szeroki" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Kolumnowy" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Wzorzec etykiety z opcjonalnymi znacznikami, np. <tt>composer</tt> lub\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferencje przeglądarki panelowej" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Układ kolumn" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Treść kolumn" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Równa szerokość paneli" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listy odtwarzania" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Listy odtwarzania" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Usuń z listy odtwarzania" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nowe" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "Za_importuj" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Nie można zaimportować listy odtwarzania" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Można importować tylko listy odtwarzania w formatach M3U/M3U8 i PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Usuń" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Zmień nazwę" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Nie można zmienić nazwy listy odtwarzania" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Zaimportuj listę odtwarzania" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "Za_importuj" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nowa lista odtwarzania…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Co zrobić z %d utworem?" msgstr[1] "Co zrobić z %d utworami?" msgstr[2] "Co zrobić z %d utworami?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Potwierdź działanie dla listy odtwarzania „%s”" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "puste" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Przykładowa lista odtwarzania" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Preferencje przeglądarki list odtwarzania" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Wyświetlanie list odtwarzania" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Na pewno usunąć listę odtwarzania „%s”?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Wszystkie informacje o zaznaczonej liście odtwarzania zostaną usunięte i nie " "mogą zostać przywrócone." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Ścieżka" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nowa lista odtwarzania" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Nazwa nowej listy odtwarzania:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importowanie listy odtwarzania.\n" "\n" "Dodano utwory: %(current)d/%(total)d." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nowy kanał" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Położenie kanału dźwiękowego:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Dodaj plik…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Odśwież" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Nie można dodać kanału" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Nie można dodać %s. Serwer może nie działać lub położenie może nie być " "kanałem dźwiękowym." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Obecny mechanizm dźwięku nie obsługuje adresów URL. Przeglądarka kanałów " "dźwiękowych została wyłączona." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Ograniczenie liczby wyników" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Wiele zapytań" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Lista ścieżek" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Lista ścieżek" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_Cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Przeglądarka SoundCloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_Cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Wyszukaj" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Moje ścieżki" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Przechodzi do serwisu %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Połączono" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Program Quod Libet jest teraz połączony, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Wyloguj z serwisu %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Kod…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Zaloguj w serwisie %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Upoważnienie serwisu SoundCloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Kod upoważnienia serwisu SoundCloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Program Quod Libet nie jest uruchomiony (parametr „--run” go uruchomi)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "kolekcja muzyki i odtwarzacz" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[opcja]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Wyświetla odtwarzany utwór i kończy działanie" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Natychmiast rozpoczyna odtwarzanie" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Bez wyświetlania okien po uruchomieniu" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Przechodzi do następnego utworu" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Przechodzi do poprzedniego utworu lub rozpoczyna ponownie, jeśli jest blisko " "początku" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Przechodzi do poprzedniego utworu" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Rozpoczyna odtwarzanie" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Wstrzymuje odtwarzanie" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Przełącza tryb odtwarzania/wstrzymania" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Zatrzymuje odtwarzanie" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Zwiększa głośność" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Zmniejsza głośność" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Zwiększa ocenę odtwarzanego utworu o jedną gwiazdkę" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Zmniejsza ocenę odtwarzanego utworu o jedną gwiazdkę" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Wyświetla stan odtwarzacza" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Ukrywa główne okno" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Wyświetla główne okno" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Przełącza widoczność głównego okna" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Przenosi działający odtwarzacz na pierwszy plan" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Usuwa aktywne filtry przeglądarki" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Odświeża i ponownie skanuje kolekcję" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Wyświetla listę dostępnych przeglądarek" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Wyświetla obecną listę odtwarzania" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Wyświetla zawartość kolejki" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Wyświetla aktywne zapytanie tekstowe" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Uruchamia bez wtyczek" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Uruchamia program Quod Libet, jeśli nie jest uruchomiony" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Kończy działanie programu Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Przewija odtwarzany utwór" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][GG∶]MM∶SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Ustawia lub przełącza tryb losowy" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Ustawia typ trybu losowego" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Włącza, wyłącza lub przełącza stan powtarzania" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Ustawia typ trybu powtarzania" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ustawia głośność" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Przeszukuje kolekcję" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "zapytanie" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Odtwarza plik" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "nazwa pliku" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Ustawia ocenę odtwarzanego utworu" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Ustawia obecną przeglądarkę" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Zatrzymuje po odtwarzanym utworze" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Otwiera nową przeglądarkę" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Wyświetla lub ukrywa kolejkę" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtruje losowo" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "etykieta" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtruje według wartości etykiety" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etykieta=wartość" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Dodaje do kolejki plik lub zapytanie" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Dodaje do kolejki pliki oddzielone przecinkami" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nazwa pliku" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Wyświetla nazwy plików wyniku zapytania na standardowym wyjściu" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Usuwa z kolejki plik lub zapytanie" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Dodaje plik lub katalog do kolekcji" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "położenie" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "wzorzec" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Nieprawidłowy parametr dla „%s”." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Proszę spróbować polecenia „%s --help”." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Wystąpił błąd" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Można zignorować ten błąd, ale program może być niestabilny do ponownego " "uruchomienia. Wysłanie błędu zajmie tylko kilka sekund i bardzo nam pomoże." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Wyślij błąd" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Zignoruj błąd" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Informacje o błędzie:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Różne informacje o błędzie i systemie zostaną wysłane do serwisu " "internetowego niezależnego od programu Quod Libet (<a href='https://www." "sentry.io'>www.sentry.io</a>). Poniżej można przejrzeć dane przed wysłaniem." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(opcjonalne) Proszę podać krótki opis okoliczności wystąpienia błędu:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Wyślij" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Krótki opis…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Dane do wysłania:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "edytor etykiet plików dźwiękowych" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "katalog" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Edytor metadanych plików dźwiękowych" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Źródło okładek z adresu URL" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Pobiera okładki powiązane przez etykietę „artwork_url”. Działa " "z przeglądarką SoundCloud." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Źródło okładek serwisu Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Pobiera okładki z serwisu Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Źródło okładek serwisu Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Pobiera okładki z archiwum serwisu Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Źródło okładek serwisu MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Pobiera okładki z archiwum serwisu MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Konwertowanie kodowań" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Naprawia błędnie zinterpretowane kodowania wartości etykiet w edytorze " "etykiet." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Konwertuj kodowanie…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Proste odwracanie znaków kana/kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Konwertuje znaki kana/kanji na romaji przed zmianą nazw." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "_Romanizuj japoński tekst" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Nie można odnaleźć „Kanji Kana Simple Inverter” (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Podstawianie wyrażeń regularnych" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Umożliwia podstawianie wyrażeń regularnych (s///) podczas zmieniania etykiet " "lub nazw plików." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Jak W Tytule" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Zmienia wielkości znaków w edytorze etykiet na Jak W Tytule." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Wartość Jak W _Tytule" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Dozwolenie _WIELKICH LITER w etykietach" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Angielska wartość Jak w Tytule" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Używa reguł języka angielskiego do ustalania wielkości znaków, np. „Dark " "Night of the Soul”" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Zaawansowane preferencje" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Umożliwia modyfikowanie zaawansowanych ustawień konfiguracji." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Wiem, co robię" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animowane informacje na ekranie" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Wyświetla na ekranie informacje o utworze po jego zmianie." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Położenie:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Rozmiar _okładki:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Wyświetlanie" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Czcionka:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Lewo" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Środek" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Prawo" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "Wy_równanie tekstu:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Tekst" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Tekst:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Wypełnianie:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Kolory" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Cienie" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Obrys" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Zaokrąglo_ne rogi" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "Opóźni_enie:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efekty" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Modyfikuj wzorzec wyświetlania…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Podgląd" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informacje o programie" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Różne informacje o programie i jego środowisku." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Obsługiwane formaty" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Katalog konfiguracji" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Katalog pamięci podręcznej" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Mechanizm dźwięku" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Przywróć domyślne" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Nie można połączyć z serwisem „%s”." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Aktualizacja etykiet w plikach" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Aktualizuje etykiety w plikach. Zapewni to aktualność liczby odtworzeń " "i ocen." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Zapisywanie ocen i _liczby odtworzeń w etykietach" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "data nagrania" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Błąd podczas synchronizacji" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "Zakt_ualizuj stacje" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Preferencje" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatyczne maskowanie" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Automatycznie maskuje i odmaskowuje napędy po ich odmontowaniu lub " "zamontowaniu." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatyczne oceny" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Automatycznie ocenia utwory podczas ich odtwarzania lub pomijania. Używa " "„przyspieszonego” algorytmu z vux autorstwa Briana Nelsona." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" "Podana baza danych programu Banshee nie istnieje lub jest błędnie " "sformatowana" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importowanie się nie powiodło" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Pomyślnie zaimportowano oceny i statystyki %d utworu" msgstr[1] "Pomyślnie zaimportowano oceny i statystyki %d utworów" msgstr[2] "Pomyślnie zaimportowano oceny i statystyki %d utworów" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Importowanie z programu Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Importuje oceny i statystyki utworów z programu Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "Ś_cieżka do bazy danych:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Rozpocznij importowanie" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Budzik" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Budzi za pomocą głośnej muzyki." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Kołysanka" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Wycisza i wstrzymuje odtwarzanie muzyki." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Aktualizowanie stanu programu Gajim" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Aktualizowanie stanu programu Gajim" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Zmienia wiadomość stanu programu Gajim na obecnie słuchany utwór." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Wstrzymano:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Tekst stanu" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Tekst stanu" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Płasko" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Na żywo" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Mocne niskie i wysokie tony" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klub" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Duża sala" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Impreza" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Lekko" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Mocne niskie tony" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Słuchawki" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Soft Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Mocne wysokie tony" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Korektor graficzny" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Steruje brzmieniem muzyki za pomocą korektora graficznego.\n" "Można kliknąć lub użyć klawiszy, aby dostosować poziomy (kliknięcie prawym " "przyciskiem myszy przywraca dane pasmo)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Obecny mechanizm nie obsługuje korektora graficznego." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Domyślne ustawienia" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Wybierz…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Przywróć korektor graficzny" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Niestandardowe ustawienia" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Usuń zaznaczone" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Nazwa zapisywanych ustawień:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Zapisz" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "dostępny" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "rozłączony" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "rozmowny" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "nieobecny" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "zajęty" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "niewidoczny" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Aktualizowanie stanu programu Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Zmienia wiadomość stanu programu Gajim na obecnie słuchany utwór." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "wstrzymano" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Wzorzec:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Lista kont, oddzielonych spacjami, dla których zmieniać wiadomość stanu. " "Jeśli nie podano żadnego, to zmienione zostaną wiadomości stanu wszystkich " "kont." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Konta:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Dodanie „[wstrzymano]”" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Jeśli jest zaznaczone, to „[wstrzymano]” będzie dodawane do wiadomości stanu " "podczas wstrzymania" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Stany, dla których wiadomość będzie zmieniana" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Wstrzymanie po odłączeniu słuchawek" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "Wstrzymuje po odłączeniu słuchawek i wznawia po ich podłączeniu." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Wstrzymanie wygaszacza ekranu" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Odtwarzanie muzyki" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Tryb" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Wstrzymanie wygaszacza ekranu" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Wstrzymanie wygaszacza ekranu" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Dziennik radia internetowego" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Nagrywa dziesięć ostatnich utworów odtwarzanych na stacjach radiowych " "i wyświetla je w menu kontekstowym przewijania." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Wypisuje plik „Jabber User Tunes” do ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Zmiana języka" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Zmienia język interfejsu użytkownika." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Domyślny systemu" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Wymagane jest ponowne uruchomienie, aby uwzględnić zmiany" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Serwer multimediów AV UPnP" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Wystawia wszystkie albumy serwerowi multimediów UPnP Rygel przez interfejs D-" "Bus MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Proszę upewnić się, że poniższe znajduje się w pliku konfiguracji usługi " "Rygel (~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Serwer MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Zdalnie steruje programem Quod Libet za pomocą klienta MPD. Odtwarzanie " "strumieniowe, listy odtwarzania i zarządzanie kolekcją nie są obsługiwane." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokalny adres _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "_Hasło:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Połączenie" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Przetestowani klienci" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Obsługa MPRIS przez D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Ukrywanie głównego okna podczas zamykania" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Przyjmuje wzorce QL, np. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Publikowanie MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publikuje wiadomości stanu do tematu MQTT." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Nazwa komputera brokera" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "nazwa komputera/adres IP brokera (domyślnie „localhost”)" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Port brokera" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "port brokera (domyślnie 1883)" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Nazwa komputera brokera" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Port brokera" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Temat" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Wzorzec odtwarzania" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Tekst stanu, kiedy utwór jest rozpoczynany." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Wzorzec wstrzymania" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Tekst, kiedy utwór jest wstrzymany." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Tekst braku utworu" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Zwykły tekst, kiedy żaden utwór nie jest odtwarzany" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Konfiguracja MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Tekst stanu" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Połączono z brokerem pod adresem %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Nie można połączyć z %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Błąd połączenia" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Wyszukiwanie w serwisie MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Umożliwia ustawianie oceny utworu jako liczby." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Nazwa użytkownika:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Hasło:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Tekst powiadomienia" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Tytuł:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Przywraca domyślny wzorzec" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "T_reść:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Powiadomienia" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Wyświetlanie powiadomień" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Tylko podczas <i>rę_cznej</i> zmiany utworu" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Tylko podczas <i>_automatycznej</i> zmiany utworu" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Podczas <i>_każdej</i> zmiany utworu" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Tylko, jeśli główne _okno nie jest aktywne" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Przycisk „_Następny”" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Błąd połączenia" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Nie można połączyć z usługą powiadomień." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Powiadomienia o utworach" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Wyświetla powiadomienia podczas zmiany utworu." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Następny" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Powiadomienia o utworach" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Proszę przejść do okna Wtyczki, aby ustawić QLScrobbler. Do tego czasu " "utwory nie będą wysyłane." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Nie można połączyć z serwisem „%s”." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Uwierzytelnienie się nie powiodło: nieprawidłowy adres URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Uwierzytelnienie się nie powiodło: nieprawidłowa nazwa użytkownika „%s” lub " "hasło." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Klient został zabroniony. Proszę skontaktować się z autorem." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Błędny czas systemu. Wysyłanie może się nie udawać, dopóki czas nie zostanie " "poprawiony." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Wysyłanie do serwisów AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "Klient AudioScrobbler dla serwisów Last.fm, Libre.fm i innych." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Pomyślnie uwierzytelniono." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Serwis:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "Adres _URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Inny…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Sprawdź poprawność danych konta" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Wzorzec wykonawcy:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Wzorzec _tytułu:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "_Filtr wykluczenia:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Wzorzec używany do formatowania nazwy wykonawcy do wysyłki. Pozostawienie " "pustego pola spowoduje użycie domyślnego." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Wzorzec używany do formatowania tytułu do wysyłki. Pozostawienie pustego " "pola spowoduje użycie domyślnego." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Utwory pasujące do tego filtru nie będą wysyłane" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Tryb _offline (bez wysyłania)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Wysyłanie" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Wyciszanie reklam radiowych" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Wycisza wyjście, kiedy odtwarzane są reklamy radiowe.\n" "Stacje: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Odtwarzanie losowego albumu" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Odtwarza losowy album, kiedy lista odtwarzania dojdzie do końca. Wymagana " "jest obsługa filtrowania według albumów przez aktywną przeglądarkę." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Wyżej oceniane" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Częściej odtwarzane" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Częściej pomijane" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Ostatnio odtwarzane" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Ostatnio rozpoczęte" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Ostatnio dodane" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Dłuższe albumy" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekundy przed rozpoczęciem następnego albumu" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Waga" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Odtwarzanie niektórych albumów częściej, niż innych" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "unikanie" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "preferowanie" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Losowy album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Oczekiwanie na rozpoczęcie %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Pomyślnie zaimportowano oceny i statystyki dla tylu utworów: %d" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Importowanie z programu Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importuje oceny i statystyki utworów z programu Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Wstrzymywanie po wygaszeniu ekranu" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" "Wstrzymuje odtwarzanie, kiedy wygaszacz ekranu środowiska GNOME jest aktywny." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Nie zainstalowano dostawcy wyszukiwania GNOME Shell dla programu Quod Libet." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Dostawca wyszukiwania GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Umożliwia GNOME Shell przeszukiwanie kolekcji." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternatywny pasek przewijania" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternatywny pasek przewijania, który jest zawsze widoczny i rozciąga się na " "całą szerokość okna." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Zakładki punktów przewijania" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Przechowywanie punktów przewijania A i B dla ścieżek. Przechodzenie do czasu " "A i zatrzymywanie po czasie B podczas odtwarzania ścieżki.\n" "Proszę zauważyć, że zmiana nazw punktów poniżej nie aktualizuje właściwych " "nazw zakładek, a tylko które nazwy zakładek wtyczka wyszukuje podczas " "podejmowania decyzji, czy przewinąć." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nazwa zakładki dla punktu A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Nazwa zakładki sprawdzana podczas rozpoczynania ścieżki, i jeśli istnieje, " "to odtwarzacz przewija do tego czasu" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nazwa zakładki dla punktu B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Nazwa zakładki używana podczas odtwarzania ścieżki, jeśli istnieje. Jeśli " "obecne położenie przekroczyło czas, to przewija do końca ścieżki." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Synchronizacja ze Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Sprawia, że urządzenie Logitech Squeezebox ma to samo wyjście, co program " "Quod Libet, jeśli oba odczytują ze wspólnej kolekcji." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Błąd podczas wyszukiwania serwera Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Błąd podczas wyszukiwania %s. Proszę sprawdzić poprawność ustawień" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Opcje" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "kodowanie" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "data nagrania" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Usuń" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Usuń" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Częściej pomijane" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Katalog docelowy:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Wzorzec ścieżki" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Modyfikuj zapisane wzorce…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Wzorzec wykonawcy:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Podgląd" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Stan" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Źródła" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Eksport metadanych" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "wydawca" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Miejsce docelowe zapisywania" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Ścieżka nie jest bezwzględna" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Wzorzec\n" "\t<b>%s</b>\n" "zawiera „/”, ale nie zaczyna się od głównego katalogu. W celu uniknięcia " "błędnie nazwanych katalogów, należy zaczynać wzorzec od katalogu / lub ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nie wybrano żadnych utworów." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nie wybrano żadnych utworów." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Nie można zapisać utworu" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Częściej pomijane" msgstr[1] "Częściej pomijane" msgstr[2] "Częściej pomijane" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Wczytanie pliku się nie powiodło: %r" msgstr[1] "Wczytanie pliku się nie powiodło: %r" msgstr[2] "Wczytanie pliku się nie powiodło: %r" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Wyświetla synchronizowany tekst utworu z pliku .lrc o tej samej nazwie co " "ścieżka." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Tło:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Czcionka" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Rozmiar (w pikselach):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Wiadomości stanu Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Aktualizuje wszystkie konta komunikatora oparte na mechanizmie Telepathy " "(skonfigurowane w programie Empathy itp.) wiadomością stanu zawierającą " "obecnie odtwarzany utwór." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Odtwarzanie:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Tekst stanu, kiedy utwór jest rozpoczynany. Przyjmuje wzorce QL, np. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Wstrzymano:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Tekst stanu, kiedy utwór jest wstrzymany. Przyjmuje wzorce QL, np. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Zwykły tekst dla stanu, kiedy żaden utwór nie jest odtwarzany" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Brak utworu:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Wzorce stanu" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Przełączanie motywu" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Zmienia aktywny motyw biblioteki GTK+." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Motyw:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Domyślny motyw" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Ciemny motyw" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Oceny „kciuk w górę/kciuk w dół”" #: quodlibet/ext/events/thumbrating.py:90 #, fuzzy msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Dodaje system ocen „kciuk w górę/kciuk w dół”, który jest konwertowany na " "wartość oceny. Przydatne do przechowywania całkowitych głosów " "i porządkowania według „~#score”." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Przełączanie paska menu" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Przełącza pasek menu przez naciśnięcie klawisza Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Bezczynny" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Ikona obszaru powiadamiania" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Steruje programem Quod Libet z obszaru powiadamiania." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Okno programu %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Odtwórz" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Wstrzymaj" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Poprzedni" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Następny" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Losowo" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "Powta_rzanie" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "_Zatrzymanie po tym utworze" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Otwórz p_rzeglądarkę" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Modyfikuj _etykiety" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informacje" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Listy odtwarzania" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "Za_kończ" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Zachowanie" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Przewinięcie kółkiem myszy zmienia głośność" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Przewinięcie kółkiem myszy zmienia utwór" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Przewijanie _kółkiem myszy" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Wyświetlanie podpowiedzi" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Wyświetlenie tekstu utworu" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Automatycznie wyświetla tekst utworu z etykiety lub pliku w panelu bocznym." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Nie odnaleziono tekstu dla utworu\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Brak aktywnego utworu" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Uruchamianie wizualizacji" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Uruchamia zewnętrzne wizualizacje." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Nie można uruchomić wizualizacji za pomocą „%s”" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Błąd" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Plik wykonywalny wizualizacji:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Wczytaj ponownie" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Pasek przewijania w kształcie fali" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "Pasek przewijania w kształcie fali obecnego utworu." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Zastąpienie koloru czcionki:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Zastąpienie koloru najechania:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Zastąpienie koloru pozostałych:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Obecne położenie" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Etykiety czasu" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "O ile przewijać podczas przewijania myszą (w milisekundach):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Zapisywanie obrazów" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Zapisuje okładkę obecnego utworu do pliku." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Plik:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Próg:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Próg, po którym filtr jest aktywny" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Współczynnik:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Współczynnik kompresji" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d%%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Kompresja dźwięku" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Zmienia amplitudy wszystkich próbek powyżej podanego progu za pomocą " "podanego współczynnika." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Ustawienie:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filtruj ustawienia" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "Wycięcie _częstotliwości:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Częstotliwość niskiego filtru wycięcia" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Poziom _kanału:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Poziom kanału" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Domyślne" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Najbliżej do położenia głośnika wirtualnego (30°, 3 metry)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Najbliżej do przenikania Chu Moy (popularne)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Najbliżej do amplitunerów CORDA Jana Meiera (mała zmiana)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Niestandardowe" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Niestandardowe ustawienia" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Przenikanie" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Miksuje lewy i prawy kanał tak, aby symulować dźwięk z głośników podczas " "używania słuchawek, lub dostosować wczesne nagrania stereofoniczne." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Filtrowanie pasma:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Pasmo częstotliwości filtru" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filtrowanie _szerokości:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Szerokość częstotliwości filtru" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Poziom:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Poziom efektu" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Usuwa głos z nagrania." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Miksowanie do mono" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Miksuje kanały do dźwięku monofonicznego." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Prędkość:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "T_onacja:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Tonacja/prędkość dźwięku" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Steruje tonacją strumienia dźwiękowego." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Eksport listy odtwarzania do katalogu" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "Wy_eksportuj" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Katalog docelowy:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Wzorzec nazw plików:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Eksportuje listę odtwarzania przez skopiowanie plików do katalogu." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Nie można wyeksportować listy odtwarzania" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Proszę się upewnić, że cel jest dostępny do zapisu." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Domyślny wzorzec nazw plików:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Wyeksportuj jako listę odtwarzania" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Eksportuje listę odtwarzania przez skopiowanie plików do katalogu." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Błąd podczas wyszukiwania serwera Squeezebox" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Błąd podczas wyszukiwania %s. Proszę sprawdzić poprawność ustawień" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Wyeksportuj do Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dynamicznie eksportuje listę odtwarzania do listy odtwarzania urządzenia " "Logitech Squeezebox, jeśli oba używają takiej samej struktury katalogów. " "Używa konfiguracji <a href=\"quodlibet:///prefs/plugins/Squeezebox Output" "\">wtyczki synchronizacji z urządzeniem Squeezebox</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Eksport listy odtwarzania do urządzenia Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Nazwa listy odtwarzania (zastąpi istniejącą)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Eksport do listy odtwarzania urządzenia Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Usunięcie duplikatów na liście odtwarzania" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Usuwa podwójne wpisy na liście odtwarzania." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Na pewno usunąć %d duplikat utworu?" msgstr[1] "Na pewno usunąć %d duplikaty utworów?" msgstr[2] "Na pewno usunąć %d duplikatów utworów?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplikaty utworów zostaną usunięte z listy odtwarzania „%s”." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Losowa lista odtwarzania" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Losuje kolejność utworów na liście odtwarzania." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Podążanie za kursorem" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Odtwarzanie podąża za zaznaczeniem lub następnym utworem na liście po " "wyczerpaniu zaznaczonych." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Podążanie za kursorem" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Podążanie za kursorem" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Wyrównywanie liczby odtworzeń" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Losuje kolejność, preferując utwory z mniejszą liczbą odtworzeń." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Preferowanie rzadziej odtwarzanych" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Preferowanie rzadziej odtwarzanych" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Tylko kolejka" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Ogranicza odtwarzanie utworów do kolejki. Wybranie tej kolejności " "odtwarzania w głównym oknie, a następnie podwójne kliknięcie utworu doda go " "do kolejki." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Tylko kolejka" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Tylko kolejka" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Odwrotnie" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Odwraca kolejność odtwarzania utworów." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Odwrotnie" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Losowa kolejność według grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Losuje kolejność odtwarzania przez grupowanie utworów określonych przez " "wspólną etykietę zamiast ścieżki, podobnie do losowania albumów. Jest to " "przydatne do losowania klasycznych utworów o wielu częściach, aby upewnić " "się, że wszystkie części są odtwarzane w kolejności przed wylosowaniem " "następnego utworu." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Losowa kolejność według grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Losowa kolejność według grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Oczekiwanie na rozpoczęcie nowej grupy…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Etykieta grupowania:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Etykieta, według której grupować utwory" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Etykieta filtrowania:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Grupowanie jest zastosowywane tylko, jeśli określono\n" "etykietę filtrowania. Utwór o nieokreślonej etykiecie\n" "filtrowania będzie traktowany jako grupa składająca się\n" "tylko z niego. Zwykle etykieta filtrowania powinna\n" "całkowicie lub częściowo zgadzać się z etykietą grupowania." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Opóźnienie:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Sekundy przed rozpoczęciem następnej grupy" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Przywróć domyślne" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Powtarzanie każdej ścieżki" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Losowanie kolejności utworów, ale powtarzanie każdej ścieżki podaną liczbę " "razy." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Powtarzanie każdej ścieżki" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Powtarzanie każdej ścieżki" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Ile razy odtwarzać każdy utwór:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Zapytanie warunkowe" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Wybiera zapytanie do dopasowania na podstawie zapytania warunkowego. " "Składnia: „@(if: condition, then, else)”." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Zapytanie brakujących" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Dopasowuje utwory bez podanej etykiety." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Dołączenie pustych etykiet" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Zapytanie języka Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Wrażenie etykiety" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Należy używać wyrażeń języka Python w zapytaniach. Składnia to „@(python: " "wyrażenie)”. Zmienna „s” (lub „a”) to dopasowywany utwór/album. „_ts” to " "(liczba rzeczywista) czas na początku zapytania. Dostępne są także moduły " "„time” i „random” oraz klasa „Random” (==random.Random)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Dołączenie zapisanego wyszukiwania" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Dołączenie wyników zapisanego wyszukiwania jako część innego zapytania. " "Składnia: „@(saved: search name)”." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Zapisane wyszukiwania" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "unikalny" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox jest OK. Używanie jedynego odtwarzacza (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Nie można połączyć z %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nazwa komputera:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nazwa użytkownika:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Hasło:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Katalog kolekcji, z którym serwer ma się łączyć" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Ścieżka do kolekcji:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Sprawdź ustawienia" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Serwer Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Debugowanie" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Serwer Squeezebox pod adresem {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "niezidentyfikowany serwer Squeezebox" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "niezidentyfikowany odtwarzacz Squeezebox: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Wybór odtwarzacza Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Odnaleziono serwer Squeezebox.\n" "Proszę wybrać odtwarzacz" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Dopasowanie _obrazu do okna" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Wpis konfiguracji „[plugins] cover_filenames” zawiera ciągi nazw plików " "obrazów" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Modyfikowanie obrazu po zapisaniu" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Nazwa pliku:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Zapisanie się nie powiodło" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Nie można zapisać „%s”." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Błąd HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "z %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Rozdzielczość: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Rozmiar: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Ograniczenie wyników „co najwyżej” na mechanizm" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "Wy_szukaj" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Wyszukiwanie…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Gotowe" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Pobiera okładki z różnych stron WWW." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Źródła" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 na ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Konwertuje etykiety APEv2 na ID3v2. Spowoduje usunięcie etykiet APEv2 po " "konwersji." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Przejdź do zakładki" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Zarządza zakładkami w zaznaczonych plikach." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Modyfikuj zakładki…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Brak zakładek" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Wyszukiwanie w serwisie MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" "Ponownie nadaje etykiety albumu na podstawie wyszukiwania w serwisie " "MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Użycie tylko roku z etykiety „date”" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Zapisywanie etykiety „_albumartist”, kiedy jest to konieczne" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Zapisywanie etykiet porządkowania dla nazw wykonawców" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Zapisywanie _standardowych etykiet serwisu MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Zapisywanie etykiety „labelid”" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nazwa pliku" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Płyta" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Ścieżka" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Tytuł" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Wykonawca" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Wyszukiwanie w serwisie MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Zapytanie:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "Wy_szukaj" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Wyniki <i>(przeciągnięcie zmienia kolejność)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Proszę wprowadzić zapytanie." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Wystąpił błąd. Proszę ponowić." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Wczytywanie wyników…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Nie odnaleziono wyników." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Konsola języka Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktywna konsola języka Python. Otwiera nowe okno." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} dla: {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Panel boczny konsoli języka Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Panel boczny interaktywnej konsoli języka Python, podążający za wybranymi " "utworami w głównym oknie." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Domyślnie można uzyskać dostęp do następujących obiektów:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Bieżący katalog roboczy:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Połączenie" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Pobiera wysokiej jakości okładki albumów za pomocą wtyczek." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klasyczny" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Duży" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Wczytywanie %(source)s — %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Nic nie odnaleziono dla albumów:\n" "<i>%(albums)s</i>.\n" "\n" "Użyci dostawcy:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Nie odnaleziono okładek" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d×%(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Rozmiar podglądu" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Miejsce docelowe zapisywania" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Polecenie" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nazwa" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Nazwa tego polecenia" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "polecenie" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Składnia wykonywanego polecenia powłoki" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parametr" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Jeśli podano, to parametr, którego wystąpienia w poleceniu będą zastępowane " "wartością podaną przez użytkownika, np. za pomocą „PARAM” wszystkie kopie " "„{PARAM}” w poleceniu będą prosiły o podanie wartości podczas wykonywania" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Wzorzec QL, np. <~filename>, używany do obliczania wartości dla polecenia. " "Dla list odtwarzania obsługiwane są także etykiety wirtualne <~playlistname> " "i <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "unikalny" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Jeśli ustawiono, to usunie duplikaty obliczonych wartości wzorca" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "maksymalna liczba parametrów" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Maksymalna liczba parametrów przekazywanych poleceniu za jednym razem (jak " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Odwrotnie" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Wprowadzenie wartości" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Wartość dla %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Niestandardowe polecenia" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Wykonuje niestandardowe polecenia (wsadowo, jeśli trzeba) na utworach za " "pomocą ich etykiet." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Modyfikuj niestandardowe polecenia" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Nie można wykonać niestandardowego polecenia %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, fuzzy, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "Przeglądarka duplikatów" msgstr[1] "Przeglądarka duplikatów" msgstr[2] "Przeglądarka duplikatów" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Zwiń/rozwiń wszystko" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Wyrażenie klucza duplikatu: „%s”" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Przeglądarka duplikatów" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Wyszukuje i wyświetla podobnie oznaczone wersje utworów." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Przyjmuje wzorce etykiet QL, takie jak <tt>~artist~title</tt> lub " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Grupowanie duplikatów według:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Klucz duplikatu" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Usuwanie _spacji" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Usuwanie znaków _diakrytycznych" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Usuwanie _interpunkcji" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Rozróżnianie wielkości _liter" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Opcje dopasowywania" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Modyfikuj liczbę odtworzeń" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Modyfikuje ~#playcount i ~#skipcount utworu.\n" "\n" "Kiedy zaznaczono wiele utworów, liczby będą zwiększanie, a nie ustawiane.\n" "\n" "Kiedy ~#playcount utworu jest ustawiany na 0, wpisy ~#lastplayed " "i ~#laststarted zostaną wyczyszczone. Jednakże, kiedy utwór z zerem " "odtworzeń jest ustawiany na dodatnią liczbę odtworzeń, żadne czasy " "odtworzenia nie zostaną utworzone." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Liczba odtworzeń" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Liczba pominięć" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Wiele wartości %s" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Modyfikowanie osadzonych obrazów" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Usuwa lub zastępuje osadzone obrazy." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Usuń wszystkie obrazy" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Osadź obecny obraz" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Ustawianie dokładnej oceny" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Umożliwia ustawianie oceny utworu jako liczby." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Proszę podać ocenę na skali od 0,0 do 1,0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrowanie dowolnej etykiety" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Tworzy zapytanie wyszukiwania na podstawie etykiet zaznaczonych utworów." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrowanie według katalogów" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtruje według katalogów w nowym oknie przeglądarki." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Wyszukiwanie odcisku akustycznego" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Wyszukuje metadane utworu przez odcisk akustyczny." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Wysłanie odcisków akustycznych" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Tworzy odciski akustyczne za pomocą programu chromaprint i wysyła je do " "serwisu acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Brak klucza API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Należy podać klucz API serwisu acoustid.org w preferencjach wtyczki przed " "wysłaniem odcisków." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Zażądaj klucza API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Klucz API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Usługa WWW AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "W kolejce" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analizowanie" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Wyszukaj" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Zapisz" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Wydanie" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Zapisywanie etykiet serwisu MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Grupowanie według katalogów" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Tryb albumów" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Zapisywanie etykiet powiązanych z albumem i próbowanie zmniejszenia liczby " "różnych wydań albumu" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Tworzenie odcisków:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Szczegóły" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Wyślij" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Utwory wymagają etykiet <i><b>musicbrainz_trackid</b></i> lub <i><b>artist</" "b></i>/<i><b>title</b></i>/<i><b>album</b></i>, aby wysłać." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Odciski:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Utwory z MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Utwory z wystarczającymi etykietami:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Utwory do wysłania:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Gotowe. Utwory do wysłania: %(to-send)d/%(all)d." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Wysyłanie odcisków:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Wysyłanie…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Aktualizacja etykiet w plikach" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Aktualizuje etykiety w plikach. Zapewni to aktualność liczby odtworzeń " "i ocen." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Eksport do pliku HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Eksportuje zaznaczoną listę utworów do pliku HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Wysłanie do urządzenia iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Wysyła utwory do urządzenia iFP iRiver." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Nie odnaleziono urządzenia iFP" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Nie można skontaktować się z urządzeniem iFP. Proszę sprawdzić, czy " "urządzenie jest włączone i podłączone oraz czy pakiet ifp-line (http://ifp-" "driver.sf.net) jest zainstalowany." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Wysyłanie %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Nie można wysłać <b>%s</b>. Na urządzeniu może nie być miejsca lub jest " "wyłączone." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Błąd podczas wysyłania" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Eksport metadanych" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Eksport metadanych" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Eksport metadanych" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Eksport metadanych" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Brak informacji o czasie" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Okładka" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importowanie się nie powiodło" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Zaimportuj" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrowanie według katalogów" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Płyta" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Ścieżka" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Wykonawca" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albumy" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Kontynuuj" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Nie można połączyć z serwisem „%s”." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Nie można połączyć z serwisem „%s”." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Nazwy plików" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Powtarzanie każdej ścieżki" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Aktualizowanie listy wykresów." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Jest już aktualne." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Pobieranie wykresu dla tygodnia: %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronizacja ukończona." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Błąd podczas synchronizacji" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Synchronizacja z serwisem Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Aktualizuje statystyki kolekcji z profilu serwisu Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Nazwa _użytkownika:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Tworzenie etykiet porządkowania" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Konwertuje nazwy albumów i wykonawców do ich porządkowania (niezbyt dobrze)." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Wyeksportuj jako listę odtwarzania" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksportuje utwory do listy odtwarzania M3U lub PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Ścieżki względne" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Ścieżki bezwzględne" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Zapisanie do <b>%s</b> się nie powiodło." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Ponownie skanuj utwory" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "Wyszukuje zmiany plików i wczytuje ponownie/usuwa je w razie potrzeby." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Ponownie skanuj utwory" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Analizator ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Ścieżka" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Postęp" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Wzmocnienie" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Szczyt" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "<b>%(to-process)s</b> album do zaktualizowania (z %(all)s)" msgstr[1] "<b>%(to-process)s</b> albumy do zaktualizowania (z %(all)s)" msgstr[2] "<b>%(to-process)s</b> albumów do zaktualizowania (z %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analizuje i aktualizuje informacje <a href=\"%(rg_link)s\">ReplayGain</a> za " "pomocą biblioteki GStreamer. Wyniki są grupowane według albumów." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "zawsze" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "jeśli brakuje <b>dowolnych</b> etykiet RG" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "jeśli brakuje etykiet RG <b>album</b>" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Przetwarzane albumy:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Istniejące etykiety" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Rozdzielanie etykiet" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Rozdziela numer płyty z albumu i wersję z tytułu w tym samym czasie." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Rozdzielanie albumów" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Rozdziela numer płyty." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "Nie dotyczy" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "Uderzenia na minutę:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Przywróć" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Wystukaj" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Wystukiwanie uderzeń na minutę" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Wystukuje uderzenia na minutę zaznaczonego utworu." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Wyszukiwanie na stronie WWW" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Przeszukuje wybraną stronę WWW za pomocą dowolnych etykiet utworów.\n" "Obsługuje wzorce, np. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Wzorzec adresu URL wyszukiwania" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Modyfikowanie adresów URL wyszukiwania" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Skonfiguruj wyszukiwania…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Wyszukiwanie etykiety w angielskiej Wikipedii" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Otwiera okno przeglądarki z artykułem z angielskiej Wikipedii o etykiecie " "zaznaczonego utworu." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Wyszukaj w serwisie %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Modyfikuj etykiety" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Wyszukanie się nie powiodło" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Nie odnaleziono etykiety „%s”." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Kolekcja" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Wyszukiwanie punktów montowania" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Skanowanie kolekcji" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Skanowanie %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Wczytywanie plików" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Skanowanie kolekcji" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Usuwa aktywne filtry przeglądarki" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Odtwarzacz muzyki i menedżer kolekcji" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Wczytanie pliku się nie powiodło: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Wyświetla listę etykiet" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Wyświetla zwięzłe wyjście" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Kolumny do wyświetlenia i kolejność w trybie zwięzłym (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Wyświetlanie także etykiet programistycznych" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Brak wystarczającej liczby parametrów" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Za dużo parametrów" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Opis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Wartość" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Wyświetla wszystkie popularne etykiety" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopiuje etykiety z jednego pliku do drugiego" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Wyświetla zmiany, bez ich zastosowywania" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Pomija etykiety, które nie mogą zostać zapisane" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Nie można skopiować etykiety {tagname} do pliku: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Modyfikuj etykiety w edytorze tekstu" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Przerwano modyfikowanie" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Uruchomienie edytora tekstu „%(editor-name)s” się nie powiodło." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Nie wykryto zmian" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Ustawia etykietę i usuwa istniejące wartości" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Nie można ustawić %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Usuwa etykiety" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Wartość jest wyrażeniem regularnym" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Usuwa wszystkie etykiety" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Nie można łączyć „--all” z „--regexp”" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Nie można usunąć {tagname} z {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Usuwa wartość etykiety" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Dodaje wartość etykiety" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Nie można ustawić %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Wyświetla informacje o pliku" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Ustawia podany obraz jako główny obraz osadzony i usuwa wszystkie pozostałe " "osadzone obrazy" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Wczytanie pliku obrazu się nie powiodło: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Modyfikowanie obrazów nie jest obsługiwane dla %(file_name)s " "(%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Usuwa wszystkie osadzone obrazy" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Wydobywa osadzone obrazy do %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Ścieżka, do której zapisywać obrazy (domyślnie katalog roboczy)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Zmienia nazwy plików na podstawie etykiet" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Wypełnia etykiety na podstawie ścieżek plików" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Plik" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Wypełnia numery ścieżek dla wszystkich plików" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Wyświetla etykiety na podstawie podanego wzorca" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Wyświetla informacje o pomocy" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" "„%(column-id)s” nie jest prawidłową nazwą kolumny (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Nieznane" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "W kolejności" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_W kolejności" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Losowo" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Losowo" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Preferowanie wyżej ocenionych" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Preferowanie wyżej ocenionych" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Powtarzanie tej ścieżki" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Powtarzanie tej ścieżki" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Powtarzanie wszystkich" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Powtarzanie wszystkich" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Pojedynczo" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Pojedynczo" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Strumień" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Buforowanie" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Nie można utworzyć potoku biblioteki GStreamer" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" "Nie odnaleziono elementu biblioteki GStreamer do obsługi formatu multimediów" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Format multimediów: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Nie można zainicjować wtyczki biblioteki GStreamer „%(name)s”" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Potok wyjściowy biblioteki GStreamer używany do odtwarzania. Pozostawienie " "pustego spowoduje użycie domyślnego potoku. Jeśli potok zawiera odpływ, to " "będzie on używany zamiast domyślnego." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Potok wyjściowy:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Długość _bufora:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Wyłączenie płynnego _odtwarzania" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Wyłączenie płynnego odtwarzania może pomóc uniknąć problemów podczas " "zmieniania utworów w niektórych wersjach biblioteki GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nie odnaleziono żadnych odpływów dźwięku biblioteki GStreamer" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Nieprawidłowy potok wyjściowy biblioteki GStreamer" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Nie można utworzyć wyjścia dźwięku" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Nie odnaleziono urządzenia dźwiękowego %r. Proszę sprawdzić poprawność " "ustawień programu Xine w ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "Nie można odnaleźć modułu „{module}”. Może trzeba zainstalować pakiet?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nie można odnaleźć elementu biblioteki GStreamer „{element}”." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Proszę przejść do okna Wtyczki, aby ustawić QLScrobbler. Do tego czasu " "utwory nie będą wysyłane." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Proszę przejść do okna Wtyczki, aby ustawić QLScrobbler. Do tego czasu " "utwory nie będą wysyłane." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Wysyłanie" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nazwa użytkownika:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Utwory pasujące do tego filtru nie będą wysyłane" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Uruchomić wtyczkę „%(name)s” na %(count)s liście odtwarzania?" msgstr[1] "Uruchomić wtyczkę „%(name)s” na %(count)s listach odtwarzania?" msgstr[2] "Uruchomić wtyczkę „%(name)s” na %(count)s listach odtwarzania?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Uruchom wtyczkę" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Początek" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Nie dotyczy" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Czas" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nazwa zakładki" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM∶SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Zakładki" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtry" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "_Ostatnio odtwarzane" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Ostatnio _dodane" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 pop_ularnych" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "_Wszystkie utwory" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Ob_ecny gatunek" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Obecny wy_konawca" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Obecny al_bum" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Losuj g_atunek" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Losuj _wykonawcę" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Losuj al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 najczęściej odtwarzanych utworów (może być więcej, jeśli utwory mają tę " "samą liczbę odtworzeń)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nazwa:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Wartość:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Zapisane wartości" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Modyfikuj zapisane wartości…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matycznie" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Tryb ś_cieżek" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Tryb _albumów" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "Wy_ciszenie" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Tryb ReplayGain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nowe %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(nieznany)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Dodaj" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Modyfikuj…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Wrażenie etykiety" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Wrażenie etykiety, np. people:real lub ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Nowa etykieta" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Wrażenie etykiety" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Pliki:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Zaznaczone utwory zostaną usunięte z kolekcji, a pliki usunięte z dysku." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Zaznaczone pliki zostaną usunięte z dysku." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Usuń pliki" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Zaznaczone utwory zostaną usunięte z kolekcji, a pliki przeniesione do kosza." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Zaznaczone pliki zostaną przeniesione do kosza." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Przenieś do kosza" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Przenoszenie %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Nie można przenieść do kosza" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Przeniesienie jednego lub więcej plików do kosza się nie powiodło." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Usuwanie %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Nie można usunąć plików" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Usunięcie jednego lub więcej plików się nie powiodło." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Przeglądarki" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Wczytywanie plików" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Rozdziel na _wiele wartości" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Oddziel płytę od al_bumu" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Oddziel _wersję od tytułu" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Oddziel aranżera od _wykonawcy" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Oddziel _wykonawcę od wykonawcy" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Oddziel _wykonawcę od tytułu" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Oddziel p_ierwotnego wykonawcę od tytułu" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Dodaj etykietę" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Etykieta:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "_Wyświetlanie etykiet programistycznych" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Dostęp do wszystkich etykiet, w tym tych utworzonych przez komputer, tzn. " "etykiet MusicBrainz lub ReplayGain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "_Wyświetlanie etykiet programistycznych" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Odwrotnie" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Zapisz" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Konfiguruj" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Rozdziel etykietę" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "S_kopiuj wartości" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Nie można dodać etykiety" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Nie można dodać utworów" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Zaznaczone pliki nie obsługują wielu wartości dla <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Nieprawidłowa etykieta" msgstr[1] "Nieprawidłowa etykieta" msgstr[2] "Nieprawidłowa etykieta" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Nieprawidłowa etykieta <b>%s</b>\n" "\n" "Zaznaczone pliki nie obsługują modyfikowania tej etykiety." msgstr[1] "" "Nieprawidłowa etykieta <b>%s</b>\n" "\n" "Zaznaczone pliki nie obsługują modyfikowania tej etykiety." msgstr[2] "" "Nieprawidłowa etykieta <b>%s</b>\n" "\n" "Zaznaczone pliki nie obsługują modyfikowania tej etykiety." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Nieprawidłowa wartość" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Nieprawidłowa wartość: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Etykieta może być niewłaściwa" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "Zmieniono %(file-name)s w trakcie działania programu. Zapisanie bez " "odświeżenia kolekcji może spowodować zastąpienie innych zmian w utworze." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Nie można zapisać utworu" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Zapisanie %(file-name)s się nie powiodło. Plik jest tylko do odczytu, " "uszkodzony lub brak uprawnień do jego modyfikacji." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Więcej opcji…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "C_ofnij" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "Po_nów" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_O programie" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "Wy_szukaj aktualizacje…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Wtyczki" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s i %(count)s więcej" msgstr[1] "%(title)s i %(count)s więcej" msgstr[2] "%(title)s i %(count)s więcej" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferencje programu Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Katalogi" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nowy katalog…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "Z_aznacz wszystkie podkatalogi" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nowy katalog" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Nazwa nowego katalogu:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Nie można utworzyć katalogu" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Nie można usunąć katalogu" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Utwory" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr " %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "%s. płyta" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "%s. ścieżka" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "Ob_ecny gatunek" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Modyfikuj wyświetlanie…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nie wybrano żadnych utworów." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Brak utworów" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informacje" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Tekst utworu" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Wyprodukowane przez %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "wykonawca" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "wykonawcy" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "wykonawcy" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nigdy" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "dodano" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "ostatnio odtworzone" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "odtwarzań" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "pominięć" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "ocena" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "ścieżka" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "długość" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "kodowanie" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "gęstość bitowa" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "rozmiar pliku" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "zmodyfikowano" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Dodatkowe" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "Zaznaczono: %d" msgstr[1] "Zaznaczono: %d" msgstr[2] "Zaznaczono: %d" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Ścieżka jest niedostępna" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d utwór bez albumu" msgstr[1] "%d utwory bez albumu" msgstr[2] "%d utworów bez albumu" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Wybrana dyskografia" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d utwór bez wykonawcy" msgstr[1] "%d utwory bez wykonawcy" msgstr[2] "%d utworów bez wykonawcy" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumy" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Całkowita długość:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Całkowity rozmiar:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Pliki" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Wyświetl w Internecie" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nie odnaleziono tekstu tego utworu." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Na pewno usunąć wszystkie utwory?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Zaznaczone utwory zostaną usunięte z kolekcji." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Wyświetl" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Wyświetl" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Odrzucić zmiany w etykietach?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Etykiety zostały zmienione, ale nie zostały zapisane. Zapisać te pliki czy " "przywrócić poprzednie wersje i odrzucić zmiany?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Przywróć" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Plik istnieje" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Zastąpić %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Zastąp plik" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktywne zadania" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "Uruchomione zadania: %d" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Przełącza tryb losowy" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Przełącza tryb powtarzania" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Wydarzenia" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Kolejność odtwarzania" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Modyfikowanie" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Zmień nazwę" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Zapytanie:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Okładki" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Błędy wtyczek" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Włączone" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Wyłączone" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Brak kategorii" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Brak kategorii" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nie odnaleziono żadnych wtyczek." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Wtyczki" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrowanie według stanu wtyczki/etykiety" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrowanie według typu wtyczki" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrowanie według nazwy lub opisu wtyczki" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Wyświetlanie _błędów" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Płyta" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "Ścież_ka" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "_Grupowanie" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Wykonawca" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Nazwa pliku" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Długość" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Automatyczne p_rzechodzenie do odtwarzanego utworu" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Podczas zmiany odtwarzanego utworu, lista zostanie przesunięta na nowy utwór" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Inne:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Modyfikuj…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Dodawanie lub usuwanie dodatkowych nagłówków kolumn" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Widoczne kolumny" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Tytuł zawiera _wersję" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album zawiera p_odpis płyty" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Wykonawca zawiera wszystkie _osoby" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Nazwa pliku zawiera _katalog" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Preferencje kolumn" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Modyfikuj kolumny" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Zastosowuje obecną konfigurację do listy utworów, dodając nowe kolumny na " "końcu" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista utworów" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Modyfikuj kolumny" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Całkowity czas trwania" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Filtr globalny:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Zastosowuje to zapytanie w dodatku do innych" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Wyszukiwanie" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Przeglądarki" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Potwierdzanie _wielu ocen" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Pyta o potwierdzenie przed zmienianiem ocen wielu utworów na raz" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Oceny jednym _kliknięciem" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Włącza ocenianie kliknięciem na kolumnę ocen na liście utworów" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Oceny" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Preferowanie okładek _osadzonych" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Używa okładek osadzonych w pliku dźwiękowym (jeśli są dostępne) zamiast " "innych źródeł" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Stała nazwa pliku obrazu:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Okładki" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Odtwarzanie" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Konfiguracja wyjścia" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Jeśli informacja ReplayGain nie jest dostępna dla utworu, to skaluje " "głośność według tej wartości" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Wzmocnienie _zapasowe (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Skaluje głośność wszystkich utworów według tej wartości, dopóki wynikowy " "dźwięk się nie przycina" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Przedwzmocnienie (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Dopasowywanie głośności _ReplayGain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Dopasowywanie głośności ReplayGain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Kontynuowanie odtwarzania po uruchomieniu" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Jeśli muzyka była odtwarzana podczas wyłączania, to automatycznie rozpoczyna " "odtwarzania po następnym uruchomieniu" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Domyślna ocena:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Skala ocen:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Czynnik średniej Bayesa (C) dla zgromadzonych ocen.\n" "0 oznacza zwykłą średnią, wyższe wartości oznaczają, że albumy z kilkoma " "ścieżkami będą miały mniej ekstremalne oceny. Zmiana tej wartości wywołuje " "ponowne obliczenie ocen wszystkich albumów." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Ilość uśredniania _Bayesa:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "Adres _e-mail:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Oceny i liczby odtworzeń będą zapisywane w etykietach dla tego adresu e-mail" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Automatyczne zapisywanie zmian etykiet" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Zapisywanie zmian etykiet bez potwierdzania podczas modyfikowania wielu " "plików" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Zestaw separatorów do użycia podczas rozdzielania wartości etykiet " "w edytorze etykiet. Lista jest rozdzielana spacjami." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "_Rozdzielanie etykiety przy:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Zestaw separatorów do użycia podczas wydzielania etykiet podrzędnych " "z etykiet w edytorze. Lista jest rozdzielana spacjami, a każdy wpis musi " "zawierać tylko dwa znaki." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Rozdzielanie _etykiety podrzędnej przy:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Etykiety" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Modyfikowanie etykiet" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Aktualizowanie dla nowych ocen" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Skanuj kolekcję" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Wyszukuje zmiany w kolekcji" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "_Ponownie zbuduj kolekcję" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Ponownie wczytuje wszystkie utwory w kolekcji. Może to chwilę potrwać." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Ukryte utwory" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "_Skanowanie kolekcji podczas uruchamiania" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Skanowane katalogów" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s i %(count)d więcej" msgstr[1] "%(title)s i %(count)d więcej" msgstr[2] "%(title)s i %(count)d więcej" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Właściwości" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Kolejka" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "Wy_czyść kolejkę" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Wyłącza kolejkę — kolejka będzie ignorowana podczas odtwarzania" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Nietrwała" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Usuwa utwory z kolejki po ich odtworzeniu" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Trwała" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Nie usuwa utworów z kolejki po ich odtworzeniu" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Tryb" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Zatrzymanie na końcu" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d utwór (%(time)s)" msgstr[1] "%(count)d utwory (%(time)s)" msgstr[2] "%(count)d utworów (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Przeglądaj kolekcję" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Przełącza widoczność kolejki" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Błąd odtwarzania" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Ustawić katalogi kolekcji?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Nie ustawiono kolekcji muzyki. Zrobić to teraz?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Nie teraz" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Ustaw" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Nie można dodać utworów" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s używa nieobsługiwanego protokołu." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Przejdź do odtwarzanego utworu" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Plik" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Utwór" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Widok" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "P_rzeglądaj" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Sterowanie" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "Pomo_c" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Dodaj katalog…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Dodaj plik…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Dodaj położenie…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Modyfikuj zakładki…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "Za_trzymaj" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Zatrzymaj po tym utworze" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Skróty klawiszowe" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Pomoc online" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Przeszukiwanie pomocy" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Dodaj położenie" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Położenie pliku dźwiękowego:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Nie można dodać położenia" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s nie jest prawidłowym położeniem." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Dodaj muzykę" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Dodaj katalogi" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Pliki muzyczne" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Dodaj pliki" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Na pewno usunąć wszystkie utwory?" msgstr[1] "Na pewno usunąć wszystkie utwory?" msgstr[2] "Na pewno usunąć wszystkie utwory?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Kolejka" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Na pewno zmienić ocenę wszystkich %d utworów?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Zapisane oceny zostaną usunięte" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Usuń oceny" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Ocena zaznaczonych utworów zostanie zmieniona na „%s”" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Zmień _oceny" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Zmienianie spacji na p_odkreślenia" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Usuwanie znaków niezgodnych z systemem _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Usuwanie znaków _diakrytycznych" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Usuwanie znaków spoza zestawu _ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Używanie tylko _małych znaków" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Zmień nazwy plików" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Podgląd" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Nazwy plików" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Przenoszenie okładki albumu" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Wpis konfiguracji „[albumart] filenames” zawiera ciągi wyszukiwania obrazów" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Zastępowanie okładki w miejscu docelowym" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Usuwanie pustych katalogów" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Okładka" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nowa nazwa" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Nie można zmienić nazwy pliku" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Zmiana nazwy <b>%(old-name)s</b> na <b>%(new-name)s</b> się nie powiodła. " "Prawdopodobnie docelowy plik już istnieje lub brak uprawnień do tworzenia " "nowych plików lub usuwania poprzednich." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "_Ignorowanie wszystkich błędów" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "Za_trzymaj" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Kontynuuj" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Ścieżka nie jest bezwzględna" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Wzorzec\n" "\t<b>%s</b>\n" "zawiera „/”, ale nie zaczyna się od głównego katalogu. W celu uniknięcia " "błędnie nazwanych katalogów, należy zaczynać wzorzec od katalogu / lub ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Utwory znajdujące się w tych katalogach zostaną dodane do kolekcji podczas " "jej odświeżania" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Zaznaczone utwory zostaną usunięte z kolekcji." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Ścieżka do kolekcji:" msgstr[1] "Ścieżka do kolekcji:" msgstr[2] "Ścieżka do kolekcji:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Usuń" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Wybierz katalogi" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Wybierz katalogi" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Zapisane wyszukiwania" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Modyfikuj zapisane wyszukiwania…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Przeszukuje kolekcję za pomocą zwykłego tekstu lub zapytań programu QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Wy_szukiwanie podczas pisania" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Wyświetla wyniki wyszukiwania, kiedy użytkownik przestaje pisać" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Ograniczenie:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Waga" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Dodanie zapytania" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Dodaje zapytanie QL lub dowolny tekst do dołączenia" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Wyświetlanie pozostałego czasu" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Główne okno" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Przewinięcie o 10 sekund do tyłu" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Przewinięcie o 10 sekund do przodu" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Przejście do wyszukiwania" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Przywrócenie filtrów i przejście do odtwarzanego utworu" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Otwarcie okna informacji o zaznaczonych utworach" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Otwarcie edytora etykiet dla zaznaczonych utworów" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Kolejkowanie zaznaczonych utworów" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Usunięcie zaznaczonych utworów" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Wyświetlenie wewnętrznego pola wyszukiwania" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Kliknięcie lewym przyciskiem myszy na nagłówku kolumny" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Dodanie kolumny do listy kolumn, według których porządkować" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Widok drzewa" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Zwinięcie elementu lub zaznaczenie elementu nadrzędnego" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Rozwinięcie elementu" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Pola tekstowe" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Cofnięcie ostatniej zmiany" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Ponowienie ostatnio cofniętej zmiany" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Zaznaczenie wszystkich utworów we wszystkich panelach" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrowanie według %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Wszystkie _nagłówki" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Nagłówki ś_cieżek" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Nagłówki _albumów" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Nagłówki _osób" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Nagłówki _dat" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Nagłówki p_lików" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Nagłówki p_rodukcji" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Dostosuj nagłówki…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Rozwiń kolumnę" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Usunąć ścieżkę „%%(title)s” z kolekcji?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Usunąć ścieżkę „%%(title)s” z kolekcji?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Usunięcie z kolekcji" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Uruchomić wtyczkę „%(name)s” na %(count)d utworze?" msgstr[1] "Uruchomić wtyczkę „%(name)s” na %(count)d utworach?" msgstr[2] "Uruchomić wtyczkę „%(name)s” na %(count)d utworach?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Uruchomić wtyczkę „%(name)s” na %(count)d albumie?" msgstr[1] "Uruchomić wtyczkę „%(name)s” na %(count)d albumach?" msgstr[2] "Uruchomić wtyczkę „%(name)s” na %(count)d albumach?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Skonfiguruj wtyczki…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Dodaj do _kolejki" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Usuń z kolekcji…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Nie można wyświetlić plików" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Błąd podczas wyświetlania plików, albo żaden program do ich wyświetlenia nie " "jest dostępny." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Wyświetl w menedżerze plików" msgstr[1] "_Wyświetl %(total)d pliki w menedżerze plików" msgstr[2] "_Wyświetl %(total)d plików w menedżerze plików" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Zapisanie się nie powiodło" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Pobieranie okładek" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Pobieranie okładek" msgstr[1] "Pobieranie okładek" msgstr[2] "Pobieranie okładek" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Pobieranie okładek" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Zmienianie p_odkreśleń na spacje" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Wielkie litery Jak W _Tytule" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Rozdzielanie na wiele _wartości" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etykiety ze ścieżki" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Zastępowanie istniejących etykiet nowymi" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Dodawanie nowych etykiet do istniejących" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Wzorzec\n" "\t<b>%s</b>\n" "jest nieprawidłowy. Prawdopodobnie zawiera on dwa razy tę samą etykietę lub " "niezamknięte nawiasy (< i >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Podany wzorzec jest nieprawidłowy. Proszę upewnić się, że znaki < i > " "zostały wpisane jako \\< i \\>, a wszystkie otwarte etykiety zostały " "zamknięte.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Modyfikuj wyświetlanie" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Numery ścieżek" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "_Rozpoczynanie od:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Razem ścieżek:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Odtwórz/wstrzymaj" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Poprzednia" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "i %d więcej…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Zapisywanie zmienionych utworów." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "Zapisane utwory: %(current)d/%(total)d\n" "(pozostało: %(remaining)s)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s z %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Wyszukiwanie aktualizacji" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Połączenie się nie powiodło" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Używana jest najnowsza wersja %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Dostępna jest nowa wersja %(new-version)s\n" "\n" "Obecnie używana jest wersja %(old-version)s\n" "\n" "Proszę odwiedzić <a href='%(url)s'>stronę programu</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Zaimportuj listę odtwarzania" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Listy odtwarzania muszą mieć nazwy" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Lista odtwarzania o nazwie %s już istnieje." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Osadzone okładki albumów" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Używa okładek osadzonych w plikach dźwiękowych." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Okładka w systemie plików" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Używa najczęściej spotykanych nazw plików obrazów umieszczonych w katalogach " "obok plików utworów." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Okładka" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Odpytywanie dostawców okładek" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Wyświetla skrócone informacje o użyciu" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Wyświetla wersję i prawa autorskie" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Wyświetla informacje debugowania" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Użycie: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opcje]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Opcja %r nie została rozpoznana." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Opcja %r wymaga parametru." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r nie jest unikalnym przedrostkiem." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekunda" msgstr[1] "%s sekundy" msgstr[2] "%s sekund" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Brak informacji o czasie" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunda" msgstr[1] "%d sekundy" msgstr[2] "%d sekund" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuta" msgstr[1] "%d minuty" msgstr[2] "%d minut" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d godzina" msgstr[1] "%d godziny" msgstr[2] "%d godzin" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dzień" msgstr[1] "%d dni" msgstr[2] "%d dni" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d rok" msgstr[1] "%d lata" msgstr[2] "%d lat" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "no_capitalize" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datę należy podać w formacie „RRRR”, „RRRR-MM-DD” lub „RRRR-MM-DD GG∶MM∶SS”." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Wzmocnienie ReplayGain należy podać w formacie „x.yy dB”." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Szczyty ReplayGain należy podać w formacie „x.yy”." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Identyfikatory MusicBrainz muszą być w formacie UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Stan wydania MusicBrainz może wynosić tylko „official”, „promotional” lub " "„bootleg”." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Język musi być trzyliterowym kodem ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Zapisanie się nie powiodło" msgstr[1] "Zapisanie się nie powiodło" msgstr[2] "Zapisanie się nie powiodło" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Nie można zmodyfikować utworu" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Zapisanie <b>%s</b> się nie powiodło. Plik jest tylko do odczytu, uszkodzony " "lub brak uprawnień do jego modyfikacji." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Nieprawidłowe kodowanie]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranżer" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranżerowie" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "aranżacja" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autorzy" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "komentarz" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "kompozytor" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "kompozytorzy" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "kompozycja" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dyrygent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dyrygenci" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dyrygowanie" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "prawa autorskie" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "opis" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "gatunek" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "gatunki" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "wykonawca" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "występ" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupowanie" #: quodlibet/util/tags.py:98 msgid "language" msgstr "język" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licencja" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "autor tekstu" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "autorzy tekstu" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "tekst utworu" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "wydawca" #: quodlibet/util/tags.py:104 msgid "title" msgstr "tytuł" #: quodlibet/util/tags.py:105 msgid "version" msgstr "wersja" #: quodlibet/util/tags.py:106 msgid "website" msgstr "strona WWW" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "wykonawca albumu" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "Uderzenia na minutę" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "podpis płyty" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "płyta" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "ścieżka" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "numer katalogowy" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "data pierwszego wydania" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "oryginalny album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "oryginalny wykonawca" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "data nagrania" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "kraj wydania" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "Identyfikator nagrania MusicBrainz" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "Identyfikator ścieżki wydania MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "Identyfikator wydania MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "Identyfikator wykonawcy MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "Identyfikator wykonawcy wydania MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "Identyfikator TRM MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Stan albumu MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Typ albumu MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "Identyfikator grupy wydania MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "wzmocnienie ścieżki" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "szczyt ścieżki" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "wzmocnienie albumu" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "szczyt albumu" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "punkt odniesienia głośności" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "płyty" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "ścieżki" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "ostatnio rozpoczęte" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "pełna nazwa" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "punkt montowania" #: quodlibet/util/tags.py:166 msgid "people" msgstr "osoby" #: quodlibet/util/tags.py:168 msgid "year" msgstr "rok" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "data pierwszego wydania" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "zakładka" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "głębia bitowa" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "format pliku" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "listy odtwarzania" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "częstotliwość próbkowania" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "liczba kanałów" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "porządkowanie" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "role" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Edytor etykiet plików dźwiękowych" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Modyfikowanie etykiet w plikach dźwiękowych" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Odtwarzacz muzyki" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Słuchanie, przeglądanie i modyfikowanie kolekcji muzycznej" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso to edytor etykiet, posiadający ten sam interfejs modyfikowania " "etykiet, co odtwarzacz Quod Libet. Umożliwia on przeglądanie i modyfikowanie " "wszystkich etykiet w plikach muzycznych, we wszystkich obsługiwanych " "formatach." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Obsługiwane formaty plików: Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, MusePack, WavPack, MPEG-4 AAC, Monkey’s Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet jest programem do zarządzania muzyką. Dostarcza on wiele sposobów " "na przeglądanie kolekcji muzyki, a także obsługę radia internetowego " "i kanałów dźwiękowych. Posiada on także niezwykle elastyczne funkcje " "modyfikowania etykiet metadanych i wyszukiwania." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Eksport do listy odtwarzania urządzenia Squeezebox" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Nie można dodać <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Nieprawidłowe etykiety" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Nieprawidłowe etykiety <b>%s</b>\n" #~ "\n" #~ "Obecnie zaznaczone pliki nie obsługują modyfikowania tych etykiet." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Automatycznie ocenia utwory podczas ich odtwarzania lub pomijania. Używa " #~ "„przyspieszonego” algorytmu z vux autorstwa Briana Nelsona." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f s" #~ msgid "Startup" #~ msgstr "Uruchamianie" #~ msgid "Audio Feeds" #~ msgstr "Kanały dźwiękowe" #~ msgid "_Audio Feeds" #~ msgstr "_Kanały dźwiękowe" #~ msgid "New" #~ msgstr "Nowa" #~ msgid "Automatic Library Update" #~ msgstr "Automatyczna aktualizacja kolekcji" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Aktualizuje kolekcję za pomocą mechanizmu inotify. Wymaga %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Steruje programem Quod Libet za pomocą specyfikacji interfejsu MPRIS 2 " #~ "usługi D-Bus." #~ msgid "Searching for lyrics…" #~ msgstr "Wyszukiwanie tekstu utworu…" #, fuzzy #~ msgid "broker username" #~ msgstr "Nazwa komputera brokera" #, fuzzy #~ msgid "broker password" #~ msgstr "Port brokera" #, fuzzy #~ msgid "<artist>" #~ msgstr "wykonawca" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "tytuł" #, fuzzy #~ msgid "OK" #~ msgstr "_OK" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Eksportuje metadane zaznaczonych utworów jako plik .tags." #~ msgid "Import Metadata" #~ msgstr "Import metadanych" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Importuje metadane zaznaczonych utworów z pliku .tags." #~ msgid "Migrate Metadata" #~ msgstr "Migracja metadanych" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Kopiuje metadane programu Quod Libet między utworami." #~ msgid "_Copy" #~ msgstr "S_kopiuj" #~ msgid "_Paste" #~ msgstr "Wk_lej" #~ msgid "Information to copy/paste" #~ msgstr "Informacje do skopiowania/wklejenia" #~ msgid "Map tracks by disc and track number" #~ msgstr "Mapowanie ścieżek według numerów płyty i ścieżki" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Należy to włączyć, kiedy ma być wykonana migracja z jednego albumu do " #~ "drugiego, dopasowując numery płyty i ścieżki.\n" #~ "\n" #~ "<b>Uwaga:</b> musi to zostać włączone, kiedy metadane są kopiowane, aby " #~ "przechować informacje o ścieżce." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Jest %d przechowywana ścieżka." #~ msgstr[1] "Są %d przechowywane ścieżki." #~ msgstr[2] "Jest %d przechowywanych ścieżek." #~ msgid "browsers" #~ msgstr "przeglądarki" #~ msgid "Unsupported file type" #~ msgstr "Nieobsługiwany typ pliku" #~ msgid "Unable to add station" #~ msgstr "Nie można dodać stacji" #~ msgid "Search Library" #~ msgstr "Wyszukiwanie w kolekcji" #~ msgid "_Search Library" #~ msgstr "_Wyszukiwanie w kolekcji" #~ msgid "Quit Program" #~ msgstr "Zakończ program" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Uniemożliwia działanie wygaszacza ekranu środowiska GNOME podczas " #~ "odtwarzania muzyki." #~ msgid "settings" #~ msgstr "ustawienia" #~ msgid "titlepattern" #~ msgstr "wzorzec tytułu" #~ msgid "bodypattern" #~ msgstr "wzorzec treści" #~ msgid "show_notifications" #~ msgstr "wyświetlanie_powiadomień" #~ msgid "tooltip" #~ msgstr "podpowiedź" #~ msgid "No lyrics found" #~ msgstr "Nie odnaleziono tekstu utworu" #~ msgid "_Zoom level:" #~ msgstr "_Poziom powiększenia:" #~ msgid "URL:" #~ msgstr "Adres URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Wyszukiwanie przez powyższy adres URL, jeśli nie można znaleźć tekstu " #~ "utworu w serwisie LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternatywne wyszukiwanie" #~ msgid "Web Lyrics" #~ msgstr "Teksty utworów z Internetu" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Wyświetla panel boczny zawierający tekst odtwarzanego utworu z Internetu." #~ msgid "grouping_filter" #~ msgstr "filtr_grupowania" #~ msgid "Skip Songs" #~ msgstr "Pomijanie utworów" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "Odtwarzanie pomija utwory z oceną równą lub niższą niż podany próg." #~ msgid "Burn CD" #~ msgstr "Nagrywanie płyt CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Nagrywa płyty CD za pomocą programu K3b, Brasero lub xfburn." #~ msgid "player" #~ msgstr "odtwarzacz" #~ msgid "editing" #~ msgstr "modyfikowanie" #~ msgid "The single image filename to use if selected" #~ msgstr "Jedyna używana nazwa pliku obrazu, jeśli zaznaczono" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "Obraz okładki używany podczas wymuszania (obsługuje wieloznaczniki)" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/pt.po����������������������������������������������������������������������������0000644�0001750�0001750�00001022713�14436352625�013624� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Portuguese/Brazil translation of Quod Libet. # Copyright (C) 2004 Joe Wreschnig # This file is distributed under the same license as the Quod Libet package. # Alexandre Passos <alexandre.tp@gmail.com>, 2006. # Djavan Fagundes <djavan@comum.org>, 2010. # Hugo Musso Gualandi <hugo_musso_gualandi@hotmail.com>, 2019 msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.23\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-03-19 11:37+0000\n" "Last-Translator: ssantos <ssantos@web.de>\n" "Language-Team: Portuguese <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/pt/>\n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.16.2-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Título" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "pessoas" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Cabeçalhos de _data" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "Data _original" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Gênero" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Avaliação" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Número de reproduções" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "_Ordenar por…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Preferências" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista de álbuns" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Lista de álbuns" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Todos os álbuns" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbuns" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Recarregar _capa" msgstr[1] "Recarregar _capas" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Músicas em nenhum álbum" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d faixa" msgstr[1] "%d faixas" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disco" msgstr[1] "%d discos" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Álbum exemplo" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferências da lista de álbuns" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Mostrar _capas" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_Pesquisa inline inclui pessoas" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opções" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Visualização do álbum" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Fechar" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navegador da biblioteca" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d música" msgstr[1] "%d músicas" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Padrão inválido" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Coleção de álbums" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Coleção de álbums" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "%s desconhecido" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Mais de um valor para %s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizado" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Adicionar" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Remover" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etiqueta" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Juntar" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Preferências da coleção de álbuns" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Aplicar" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Cancelar" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Grade de capas" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Grade de capas" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Preferências da grade de capas" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Mostrar dados do álbum" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Incluir item \"Todos os álbuns\" na grade" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Modo largo" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Ampliação das capas" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Sistema de ficheiros" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Sistema de ficheiros" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Não copiar músicas" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Os ficheiros selecionados não puderam ser copiados para outras listas de " "músicas ou para a fila de reprodução." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Adicionar à biblioteca" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Listas de estações só podem conter endereços de estações, não outras listas " "de estações ou playlists. Os seguintes endereços não puderam ser " "carregados:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Rádio via Internet" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Todas as estações" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Baixando lista de estações" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nova estação" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Insira o endereço de uma estação de rádio via internet:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Eletrônica" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonesa" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indiana" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religiosa" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Parada de sucessos" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latino-americana" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Universitária" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambiente" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clássica" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Notícias" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Eslávica" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grega" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gótica" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Você gostaria de baixar uma lista de estações de rádio populares?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Baixar lista" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Rádio via internet" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Todas as estações" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoritos" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Nenhuma categoria" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nova estação…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Atualizar estações" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nenhuma estação encontrada" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nenhuma estação de rádio via internet foi encontrada em %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Todas as estações listadas já estão em sua biblioteca." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "_Adicionar aos favoritos" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "_Remover dos favoritos" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d estação" msgstr[1] "%(count)d estações" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Painéis" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Painéis" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Selecionar _todos" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Desconhecido" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Todos" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Pequena" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Larga" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Em colunas" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Padrão de etiqueta com marcação opcional. Por exemplo, <tt>composer</tt> ou\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferências da navegação por painéis" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Configuração dos painéis" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Conteúdo dos painéis" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Igualar largura dos painéis" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Listas de reprodução" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Listas de re_produção" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Remover da lista de reprodução" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Novo" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importar" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Não foi possível importar a lista de reprodução" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet só é capaz de importar listas de reprodução nos formatos M3U/M3U8 " "e PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Excluir" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Renomear" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Não foi possível renomear a lista de reprodução" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importar lista de reprodução" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importar" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nova lista de reprodução…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "O que você gostaria de fazer com esta %d música?" msgstr[1] "O que você gostaria de fazer com estas %d músicas?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Confirmar ação para lista de reprodução \"%s\"" # Empty playlist? #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "vazia" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Lista de reprodução exemplo" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Preferências das listas de reprodução" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Visualização da lista de reprodução" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Tem certeza de que você quer excluir a lista de reprodução \"%s\"?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Todas as informações relativas à lista de reprodução selecionada serão " "excluídas e não poderão ser recuperadas." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Faixa" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nova lista de reprodução" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Digite um nome da nova lista de reprodução:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importando lista de reprodução.\n" "\n" "%(current)d/%(total)d músicas adicionadas." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Novo feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Insira o endereço de um feed de áudio:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Adicionar um _ficheiro…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Atuali_zar" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Buscar nessa pasta por novas músicas" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Não foi possível adicionar o feed" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s não pôde ser adicionado. O servidor pode estar fora do ar, ou o endereço " "pode não ser o de um feed válido." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "O backend atual de áudio não suporta URLs. Assim, o navegador de feeds de " "áudio está desabilitado." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Restringir resultados" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Permitir múltiplas consultas" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Lista de faixas" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Lista de faixas" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Navegador para Soundclound" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Procurar" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Minhas faixas" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Ir para %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Conectado" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet está conectado, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Sair de %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Inserir código…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Conectar a %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Credenciais do Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Insira o código de autorização do Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet não está em execução. Adicione \"--run\" para iniciá-lo" # Descrição para `quodlibet --help` #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "um gerenciador e reprodutor de músicas" # Usado em `quodlibet --help` #: quodlibet/cli.py:88 msgid "[option]" msgstr "[opção]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Exibe a música em reprodução e sai" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Começa a reproduzir imediatamente" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Não mostra janelas ao iniciar" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Vai para a próxima música" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Vai para a música anterior, ou reinicia se estiver próximo ao início" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Vai para a música anterior" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Reproduz" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pausa a reproução" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Altera o estado tocando/pausado" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Para a reprodução" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Aumenta o volume" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Diminui o volume" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Aumenta a avaliação da música em reprodução em uma estrela" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Diminui a avaliação da música em reprodução em uma estrela" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Escreve o estado do reprodutor (a reproduzir/pausado)" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Oculta a janela principal" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Mostra a janela principal" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Altera a visibilidade da janela principal (visível/invisível)" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Foca no tocador atual" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Remove filtros de navegação ativos" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Atualiza e re-escaneia a biblioteca" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Lista os navegadores disponíveis" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Exibe a lista de reprodução atual" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Exibe o conteúdo da fila" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Exibe a consulta de texto ativa" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Inicia sem plugins" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Inicia o Quod Libet caso não já esteja em execução" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Sai do Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Avança/recua na música em reprodução" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Desliga, liga, ou altera o modo de embaralhamento" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Altera o modo de embaralhamento" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Desliga, liga, ou altera o modo repetição" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Altera o modo de repetição" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ajusta o volume" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Pesquise na sua biblioteca" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "busca" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Reproduz um ficheiro" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "ficheiro" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Ajusta a avaliação da música em reprodução" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Altera o navegador atual" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Parar após esta música" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Abre um novo navegador" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Mostra ou oculta a fila" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtra por um valor aleatório" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "etiqueta" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrar pelo valor de uma etiqueta" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etiqueta=valor" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Enfileira um ficheiro ou busca" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Enfileira ficheiros separados por vírgula" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "ficheiro" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Exibe nomes de ficheiro do resultado da busca em stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Desenfileira um ficheiro ou busca" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Adiciona um ficheiro ou pasta à biblioteca" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "endereço" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "padrão" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumento inválido para \"%s\"." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Tente %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Houve um erro" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Você pode ignorar este erro, mas a aplicação pode ficar instável até ser " "reiniciada. Por favor nos mande um relatório de erro. Deve levar apenas " "alguns segundos e nos ajudaria bastante." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Enviar relatório de erro" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Ignorar erro" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Detalhes do erro:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Vários detalhes relativos ao erro e ao seu sistema serão enviados a um " "serviço online de terceiros (<a href='https://www.sentry.io'>www.sentry.io</" "a>). Você pode revisar estes dados antes de enviá-los." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(Opcional) Por favor, providencie uma curta descrição de o que houve quando " "o erro ocorreu:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Enviar" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Descrição curta…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Dados a serem enviados:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "um editor de metadados de áudio" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "pasta" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Editor de metadados de áudio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Fonte de capas artwork_url" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Baixa imagens de capa de álbuns através do link descrito na etiqueta " "\"artwork_url\" (se estiver presente). Funciona com o navegador Soundcloud." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Fonte de capas Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Baixa imagens de capa de álbuns pelo Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Fonte de capas Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Descarrega imagens de capa de álbum pelo arquivo Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Fonte de capas MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Descarrega imagens de capa de álbum pelo MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Converter codificação" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Corrige no editor de etiquetas as que foram originalmente gravadas com uma " "codificação de texto incorreta." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Converter codificação…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Inversor simples para Kana/Kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Converte kana/kanji para romaji antes de renomear." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanizar texto _japonês" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Não foi encontrado o conversor para Kanji/Kana (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Substituição via regex" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Permite substituições por expressões regulares (s///) ao etiquetar ou " "renomear ficheiros." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Maiusculização de títulos" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" "Maiusculiza etiquetas no editor de etiquetas, pelas regras de maiusculização " "de títulos." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Maius_culizar valor como título" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Permitir TUDO EM M_AIÚSCULAS em etiquetas" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Maiusculização de títulos _humana" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Usa regras comuns para maiusculização de títulos em inglês, como em \"Dark " "Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Preferências avançadas" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Permite editar configurações mais avançadas." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Eu sei o que estou fazendo" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Mensagem na tela (OSD)" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Mostra informações sobre a música quando ela começa a tocar." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Posição:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Tamanho da imagem:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Visualização" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Fonte:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Esquerda" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centro" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Direita" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Alinhamento do texto:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Texto" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Texto:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Fundo:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Cores" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Sombras" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Contorno" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Bordas Arredo_ndadas" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Atraso:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efeitos" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Editar formato…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Visualizar" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informações sobre esta aplicação" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Informações diversas sobre esta aplicação e ambiente de execução dela." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Formatos de áudio com suporte" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Pasta de configuração" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Pasta de cache" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Backend de áudio" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Reverter ao padrão" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Não foi possível encontrar \"%s\"." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Atualiza etiquetas nos ficheiros" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Salva as atualizações de etiquetas nos ficheiros correspondentes " "automaticamente. Isso garante que contagens de reprodução e avaliações estão " "sempre em dia." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Salvar avaliações e _contagem de reproduções em etiquetas" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "data de gravação" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Erro durante a sincronização" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Atualizar estações" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Preferências" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Máscara automática" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Mascara e desmascara discos automaticamente quando estes são montados e " "desmontados." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Avaliação automática" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Avalia as músicas automaticamente a medida elas são reproduzidas ou puladas/" "ignoradas. Este plug-in usa um algoritmo \"acelerado\" originário do vux, " "desenvolvido por Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Falha ao importar" #: quodlibet/ext/events/bansheeimport.py:118 #, fuzzy, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" "Avaliações e estatísticas para %d músicas foram importadas com sucesso" msgstr[1] "" "Avaliações e estatísticas para %d músicas foram importadas com sucesso" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importar" #: quodlibet/ext/events/bansheeimport.py:128 #, fuzzy msgid "Imports ratings and song statistics from Banshee." msgstr "Importa avaliações e estatísticas de música do Rhythmbox." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "_Importar" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Despertador" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Te acorda com música alta." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Canção de ninar" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" "Diminui o volume e pausa a sua música automaticamente no horário escolhido." # Tentei seguir as traduções do próprio Gajim. # Ver https://dev.gajim.org/gajim/gajim/blob/master/po/pt_BR.po #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Status do Gajim" # Tentei seguir as traduções do próprio Gajim. # Ver https://dev.gajim.org/gajim/gajim/blob/master/po/pt_BR.po #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Status do Gajim" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Altera a mensagem de estado do Gajim conforme o que escuta." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Pausado:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Status" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Status" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Achatado" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Concerto" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Graves e agudos totais" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Club" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Salão" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Festa" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Suave" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Graves totais" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Fone de ouvido" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Rock suave" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Agudos totais" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dance" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Equalizador" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Controla o tom da sua música com um equalizador.\n" "Use o rato o teclado para configurar os diversos níveis (o botão direito " "restaura a faixa para o valor padrão)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "O backend atual não tem suporte a equalização." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Predefinições padrão" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Selecione…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Restaurar EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Predefinições customizadas" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Excluir selecionadas" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Nome da predefinição:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Salvar" # Ver comentário em "Gajim Status Message" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "conectado" # Ver comentário em "Gajim Status Message" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "desconectado" # Ver comentário em "Gajim Status Message" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "bate-papo" # Ver comentário em "Gajim Status Message" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "inativo" # Ver comentário em "Gajim Status Message" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "fora" # Ver comentário em "Gajim Status Message" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "invisível" # Tentei seguir as traduções do próprio Gajim. # Ver https://dev.gajim.org/gajim/gajim/blob/master/po/pt_BR.po #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Status do Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Altera a mensagem de estado do Gajim conforme o que escuta." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "pausado" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Padrão:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Liste as contas para qual alterar a mensagem de estado, separadas por " "espaço. Se nenhuma for especificada, a mensagem de estado de todas as contas " "será alterada." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Contas:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Adicionar \"[pausado]\"" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Se marcada, adiciona \"[pausado]\" ao fim da mensagem durante uma pausa" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Status para os quais alterar a mensagem" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Detecção de fone de ouvido" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pausa a reprodução se os fones de ouvidos forem desconectados e reinicia " "quando eles forem reconectados." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Inibir o protetor de tela" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Música está a ser reproduzida" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modo" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Inibir o protetor de tela" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Inibir o protetor de tela" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Log de rádio de internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Lembra as últimas 10 músicas tocadas em estações de rádio, e as lista no " "menu de contexto da posição de reprodução." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Produz um ficheiro \"Jabber User Tunes\" em ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Alterar idioma" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Altera o idioma da interface de usuário." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Padrão do sistema" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "É necessário reiniciar este aplicativo para que a mudança tenha efeito" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Servidor UPnP de mídia" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Expõe todos os álbuns ao Rygel, um servidor de mídia Universal Plug and Play " "(UPnP), através da interface D-Bus MediaServer2." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Certifique-se de que os seguintes campos estejam presentes no seu ficheiro " "de configuração do rygel (~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Servidor MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Permite controlar remotamente o Quod Libet por um cliente MPD. Não há " "suporte para streaming, listas de reprodução e gestão da biblioteca." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Porta:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_IP local:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "_Senha:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Conexão" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Clientes testados" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Suporte a MPRIS" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Esconder janela principal ao fechar" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Aceita padrões QL. Por exemplo, %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Publicador MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publica mensagens de estado para um tópico MQTT." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Padrão" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Erro de conexão" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Procurar no MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Permite definir a avaliação de uma música com um número." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Nome de usuário:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Senha:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Conta" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Texto da notificação" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Título:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Reverte para o padrão padrão" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Corpo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Exibir notificação" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Exibir notificações" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Apenas nas transições manuais" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Apenas nas transições automáticas" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Em todas as transições" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Apenas quando a janela principal não esteja em foco" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Incluir botão de \"_Próxima\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Erro de conexão" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Não foi possível se conectar ao daemon de notificação." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Notificações de música" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Exibe uma notificação durante a transição entre músicas." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Próxima" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Notificações de música" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Por favor visite a jánela de plug-ins para configurar o QLScrobbler. Antes " "disso ser feito as suas músicas não poderão ser enviadas." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Não foi possível se conectar ao serviço \"%s\"." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Autenticação falhou: URL inválido." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Autenticação falhou: Nome de usuário \"%s\" inválido, ou senha errada." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "O cliente foi banido. Entre em contato com o autor." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "O relógio do sistema está errado. Submissões podem falhar até isto ser " "corrigido." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Submeter ao AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Um cliente Audioscrobbler para Last.fm, Libre.fm and outros serviços " "Audioscrobbler." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Autenticação realizada com sucesso." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Serviço:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Outros…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Verificar conta" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Padrão para _artista:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Padrão para _título:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Filtro de _exclusão:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Este padrão é usado para formatar o nome de artista antes de enviá-lo. Deixe " "em branco para usar o padrão." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Este padrão é usado para formatar o título antes de enviá-lo. Deixe em " "branco para usar o padrão." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Músicas que corresponderem a este filtro não serão enviadas" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Modo _offline (não enviar nada)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Submissão" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Silenciar anúncios de rádio" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Silencia a saída de áudio quando anúncios de rádio estiverem tocando.\n" "Estações: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Reproduzir álbum aleatório" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Começa a reproduzir um álbum aleatório quando a sua lista de reprodução " "chega ao fim. Requer que o seu navegador atual dê suporte a filtragem por " "álbum." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Melhor avaliado" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Mais reproduzido" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Mais ignorado" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Reproduzido mais recentemente" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Iniciado mais recentemente" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Adicionado mais recentemente" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Mais longo" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "segundos antes de começar o próximo álbum" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Ponderações" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Reproduzir alguns álbuns mais que os outros" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "evitar" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "preferir" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Álbum aleatório" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Esperando para começar a reproduzir %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Avaliações e estatísticas para %d músicas foram importadas com sucesso" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Importar do Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importa avaliações e estatísticas de música do Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Interrompe durante a proteção de tela" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Interrompe a reprodução enquanto o GNOME Screensaver estiver ativo." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Nenhum provedor de pesquisa GNOME Shell para Quod Libet foi instalado." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Provedor de pesquisa GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" "Permite pesquisar na biblioteca do Quod Libet através da barra de pesquisa " "do GNOME Shell." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Barra alternativa para a posição de reprodução" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Uma barra de posição de reprodução que é sempre visível e que percorre toda " "a largura da janela." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Marcadores de posição de reprodução" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Guarda marcadores de início (A) e fim (B) para as suas faixas. Ao reproduzir " "uma música, automaticamente pula para o marcador de início e automaticamente " "termina ao atingir o marcador de fim.\n" "Note que alterar os nomes dos marcadores abaixo não altera nos nomes dos " "marcadores existentes, apenas altera o nome dos marcadores que o plug-in usa " "na hora de decidir se deve mover o ponto de reprodução." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Nome do marcador de início" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Se existente, pula automaticamente para a posição deste marcador ao " "reproduzir uma música" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Nome do marcador de fim" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "Se existente, termina a reprodução da música ao atingir este marcador." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Sincronizar com Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Espelha a saída do Quod Libet num Squeezebox da Logitech, desde que ambos " "possam ler de uma biblioteca idêntica." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Não foi possível encontrar o servidor Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Não foi possível encontrar %s. Por favor verifique a configuração" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Opções" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "codificação" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "data de gravação" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Excluir" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Apagando %d/%d." #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Mais ignorado" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Pasta de destino:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Padrões de caminho" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Editar padrões salvos…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "Padrão para _artista:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Visualizar" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Fontes" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Exportar metadados" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "gravadora" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Caminho de destino" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "O caminho não é absoluto" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "O padrão\n" "\t<b>%s</b>\n" "contem / mas não começa do diretório raiz. Para evitar pastas com os nomes " "incorretos, inicie o seu padrão com / ou ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nenhuma música selecionada." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nenhuma música selecionada." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Não foi possível salvar a música" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, fuzzy, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "Tag por ficheiro" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Mais ignorado" msgstr[1] "Mais ignorado" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Impossível abrir arquivos de entrada" msgstr[1] "Impossível abrir arquivos de entrada" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Exibe letras sincronizadas a partir de um ficheiro \".lrc\" com o mesmo nome " "do usado na faixa." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Texto:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Fundo:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Fonte" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Tamanho (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Status do Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Atualiza todas as contas de bate-papo baseadas no Telepathy (como " "configurado no Empathy, etc) com uma mensagem de estado baseada na música " "atual." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Reproduzindo:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Mensagem de estado quando uma música começa a ser reproduzida. Aceita " "padrões QL. Por exemplo, %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Pausado:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Mensagem de estado quando uma música está pausada. Aceita padrões QL. Por " "exemplo, %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Mensagem de estado quando não há uma música a ser reproduzida" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Nenhuma música:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Padrões da mensagem de estado" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Seletor de tema do GTK+" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Altera o tema GTK+ usado." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Tema padrão" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Preferir versão escura" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Avaliação por curtidas" #: quodlibet/ext/events/thumbrating.py:90 #, fuzzy msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Adiciona um sistema em que \"curtidas\" (👍) e \"descurtidas\" (👎) são " "internamente convertidas para uma nota numérica de sempre. É útil para " "contar o total de votos e ordenar por \"~#score\"." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Alternar barra de menu" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Exibe/esconde a barra de menu com a tecla Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Não está reproduzindo" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Ícone na área de notificação" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" "Controla o Quod Libet a partir de um ícone na área de notificação do sistema." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Exibir %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Reproduzir" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Pausar" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Anterior" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "Pró_xima" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Embaralhar" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "Repe_tir" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Parar após esta _música" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Abrir _Navegador" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editar _etiquetas" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informações" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Listas de reprodução" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Sair" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Comportamento" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Roda do rato ajusta volume" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Roda do rato troca de música" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Roda do rato" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Mostrar dicas" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Exibir letra" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Exibe a letra da música em uma barra lateral. Obtém a letra de etiquetas ou " "de ficheiros." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Nenhuma letra encontrada para\n" "%s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Nenhuma música está a ser reproduzida" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Lançar visualizações" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Lança visualizações externas." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Não foi possível executar visualizações com \"%s\"" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Erro" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Executável do visualizador:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Recarregar" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Barra de forma de onda" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" "Uma barra de posição de reprodução que mostra a forma de onda da música em " "reprodução." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Cor de fundo:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Cor ao passar o rato:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Cor restante:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Mostrar a posição atual" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Mostrar tempo" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Quantidade de busca ao rolar (milissegundos):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Salvar imagens" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Salva a imagem de capa do álbum da música em reprodução num ficheiro." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Arquivo:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Limite:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Limite após o qual o filtro é ativado" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Razão:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Razão de compressão" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Compressor de áudio" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Altera a amplitude de todas as amostras acima de um limite escolhido, por " "uma razão específica." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Predefinição:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Predefinição do filtro" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frequência de corte:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Frequência de corte do filtro de passa-baixa" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Padrão" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Mais próximo do auto-falante virtual (30°, 3 metros)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Similar a Chu Moy (popular)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Similar aos amplificadores CORDA de Jan Meier (pequena diferença)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Customizado" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Configurações customizadas" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mistura o canal de áudio esquerdo com o direito, de forma a simular uma " "configuração com auto-falantes para quem usa fone de ouvido. Pode ser útil " "para compensar gravações estéreo mais antigas, em que os canais de áudio " "eram muito diferentes um do outro." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Banda de filtragem:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Banda de frequência a ser fitrada" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "_Largura do filtro:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Largura da banda de frequência a ser filtrada" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Nível:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Nível do efeito" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaokê" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Remove os vocais do áudio." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Converter para mono" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Converte canais estéreo para mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Taxa de amostragem:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Velocidade:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Altura (tom):" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Afinação e velocidade" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Controla a afinação e velocidade do fluxo de áudio." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Exportar lista de reprodução para pasta" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exportar" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Pasta de destino:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Padrão de nome de ficheiro:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Exporta uma lista de reprodução, copiando ficheiros para uma pasta." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Não foi possível exportar a lista de reprodução" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" "Certifique-se de que você tem permissão de escrita para a pasta de destino." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Formato padrão de _nome de ficheiro:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Exportar como lista de reprodução" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Exporta uma lista de reprodução, copiando ficheiros para uma pasta." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Não foi possível encontrar o servidor Squeezebox" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Não foi possível encontrar %s. Por favor verifique a configuração" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exportar para Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dinamicamente exporta uma lista de reprodução do Quod Libet para o " "Squeezebox da Logitech, desde que ambos compartilhem a mesma estrutura de " "diretório. Este plug-in compartilha a sua configuração com o <a href=" "\"quodlibet:///prefs/plugins/Squeezebox Output\">plug-in Sincronizar com " "Squeezebox</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Exportar lista de produção para o Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Nome da lista de reprodução (sobrescreve existente)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exportar para lista de reprodução do Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Remover duplicatas em listas de reprodução" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Remove músicas que ocorrem mais de uma vez em uma lista de reprodução." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Você tem certeza de que quer remover %d música duplicada?" msgstr[1] "Você tem certeza de que quer remover %d músicas duplicada?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "As músicas duplicadas serão removidas da lista de reprodução \"%s\"." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Embaralhar lista de reprodução" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Embaralha uma lista de reprodução aleatoriamente." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Seguir cursor" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "A reprodução segue a seleção do cursor, ou a próxima música na lista quando " "a seleção for exausta." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Seguir cursor" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Seguir cursor" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Equalizador de reproduções" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Modo de embaralhamento da ordem re reprodução, que privilegia as músicas " "menos reproduzidas." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Preferir menos reproduzidas" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Preferir menos reproduzidas" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Apenas enfileirar" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Restringe a reprodução de músicas às presentes na fila de reprodução. Se " "você selecionar esta ordem de reprodução na janela principal, um clique " "duplo em uma música irá apenas enfileirá-la em vez de reproduzi-la " "diretamente." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Apenas enfileirar" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Apenas enfileirar" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Reverter" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Reverte a ordem de reprodução das músicas." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Reverter" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Embaralhar por agrupamento" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Embaralha pelo agrupamento de músicas especificado pela etiqueta comum de " "\"grouping\", em vez de por faixa. Similar ao embaralhamento por álbum. Isso " "pode ser útil para embaralhar peças clássicas com mais de um movimento, para " "garantir que cada movimento é reproduzido inteiramente antes de trocar para " "outro movimento." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Por agrupamento" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Por agrupamento" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Esperando para iniciar o próximo agrupamento…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Etiqueta de agrupamento:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Etiqueta para agrupar músicas" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Etiqueta de filtragem:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "O agrupamento só ocorre se a etiqueta de filtragem \n" "estiver presente.\n" " Uma música sem a etiqueta de filtro\n" " será tratada como um grupo que consiste apenas de si\n" " mesma. Normalmente a etiqueta de filtragem deve\n" "corresponder total ou parcialmente à etiqueta de agrupamento." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Intervalo:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Espera em segundos para começar a reproduzir o próximo grupo" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Restaurar para o padrão" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Repetir cada faixa" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Embaralha as músicas, mas repete cada uma um certo número de vezes." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Repetir cada faixa" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Repetir cada faixa" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Número de vezes para repetir cada música:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Consuta condicional" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Habilita sintaxe para de consultas condicionais. A sintaxe é \"@(if: " "condition, then, else)\"." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Pesquisa inclui etiquetas vazias" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" "Pesquisas também incluem músicas em que o valor da etiqueta está vazio." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Incluir etiquetas vazias" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Consulta Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Expressão de etiqueta" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Permite o uso de Python nas consultas. A sintaxe é \"@(python: " "expression)\".\n" "A variável \"s\" referencia a música em reprodução e a variável \"a\" o " "álbum.\n" "\"_ts\" é horário do início da consulta, expresso como um número real.\n" "Os módulos \"time\" e a classe \"Random\" também estão disponíveis." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Incluir consulta salva" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Inclui os resultados de uma consulta salva como parte de outra consulta. A " "sintaxe é \"@(saved: search name)\"." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Consultas salvas" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "único" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox está OK. Usando o único reprodutor (%s)" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Não foi possível conectar a %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Nome do servidor:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Porta:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Nome de usuário:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Senha:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Pasta de biblioteca que o servidor se conecta" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Caminho da biblioteca:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Verificar configuração" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Servidor Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Depurar" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Servidor Squeezebox em {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "servidor Squeezebox não identificado" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "reprodutor Squeezebox não identificado: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Escolha o reprodutor Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "O servidor Squeezebox foi encontrado. Por favor escolha o reprodutor" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Ajustar à _janela" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Refira-se à entrada \"[plugins] cover_filenames\", no ficheiro de " "configuração" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Programa:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Editar imagem após salvar" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Nome do ficheiro:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Falha ao salvar" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Não foi possível salvar \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "Erro HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Baixar capa de álbum" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "obtido de %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Resolução: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Tamanho: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Limite de capas por fonte" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Procurar" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Procurando…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Concluído" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Baixar capas de álbum" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Baixa capas de álbum de diversos websites." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Fontes" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 para ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Converte etiquetas no formato APEv2 para etiquetas ID3v2. As etiquetas APEv2 " "serão removidas após a conversão." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Ir para marcador" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Gira marcadores nos ficheiros selecionados." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Editar marcadores…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Nenhum marcador" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Procurar no MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" "Re-etiqueta um álbum baseado em uma consulta ao banco de dados MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Usar apenas o ano para etiqueta \"data\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Escrever etiqueta \"_albumartist\" quando necessário" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Escrever etiquetas de ordenação para nomes de artista" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Escrever etiquetas MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Escrever etiqueta \"labelid\"" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nome de ficheiro" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "_Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Faixa" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Título" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Procurar no MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Consulta:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Procurar" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Resultados <i>(arraste para reordenar)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Por favor, entre com uma consulta." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Erro encontrado. Favor tentar novamente." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Carregando resultado…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Nenhum resultado encontrado." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Console Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Um console interativo Python. Abre em nova janela." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} para {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Console Python (barra lateral)" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Um console interativo Python, em uma barra lateral na janela principal. " "Segue as músicas selecionadas pela janela principal." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Você pode acessar os seguintes objetos por padrao:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "O diretório de trabalho atual é:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Conexão" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Baixar capas de álbum" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Baixa capas de álbum de alta qualidade, através de plug-ins." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Clássico" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Grande" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Baixar capa de álbum" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Carregando %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Nada foi encontrado para estes álbuns:\n" "<i>%(albums)s</i>.\n" "\n" "Provedores usados:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Nenhuma capa foi encontrada" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Tamanho da visualização" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Caminho de destino" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Comando" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "nome" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "O nome deste comando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "comando" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "O comando shell a executar" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parâmetro" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Se especificado, um parâmetro cujas ocorrências serão substituídas por um " "valor especificado pelo usuário.\n" "Por exemplo, se o parâmetro for \"PARAM\", todas as instâncias de " "\"{PARAM}\" no seu comando terão o valor providenciado pelo usuário" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "O padrão QL usado para calcular um valor para o comando, por exemplo " "<~filename>. Para listas de reprodução também há suporte para as etiquetas " "virtuais <~playlistname> e <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "único" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Se ativado, remove valores duplicados que forem produzidos pelo padrão" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "max argumentos" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Limite de argumentos a serem passados para o comando de uma só vez (estilo " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Reverter" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Valor de entrada" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Valor para %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Comandos personalizados" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Executa comandos personalizados nas músicas (por lote, se preciso), usando " "qualquer uma de suas etiquetas." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Editar comandos personalizados" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Não foi possível executar o comando personalizado %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d grupo de duplicatas" msgstr[1] "%d gruposde duplicatas" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Colapsar/expandir todos" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "A expressão chave é \"%s\"" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Navegador de duplicatas" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Encontra e exibe músicas com etiquetas semelhantes." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Aceita expressões de etiqueta QL como <tt>~artist~title</tt> ou " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Agrupar duplicatas por:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Expressão chave" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Remover espaços em branco" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Remover acentos e diacríticos" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Remover pontuação" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Não diferenciar maiúsculas de minúsculas" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Opções de emparelhamento" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Editar contagem de reproduções" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Edita o ~#playcount e ~#skipcount de uma música.\n" "\n" "Quando mais de uma música for selecionada, incrementa as contagens ao invés " "de sobrescrever.\n" "\n" "Se ~#playcount for definida como 0, as entradas~#lastplayed e ~#laststarted " "serão apagadas. No entando se o número de reproduções or alterado de zero " "para um número positivo não serão criados timestamps de reprodução." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Número de reproduções" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Número de ignoradas" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Mais de um valor para %s" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Editar imagens embutidas" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Remove ou substitui imagens embutidas." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Remover todas as imagens" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Embutir a imagem atual" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Definir avaliação exata" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Permite definir a avaliação de uma música com um número." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Por favor, informe a avaliação desejada em uma escala de 0.0 a 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrar por qualquer etiqueta" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" "Cria uma consulta baseada nos valores das etiquetas das músicas selecionadas." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrar por pasta" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtra por pasta em uma nova janela." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Pesquisar por impressão digital" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" "Pesquisa por metadados pela impressão digital acústica (<i>fingerprint</i>) " "da música." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Submeter impressão digital" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Gera impressões digitais acústicas usando o Chromaprint e as envia a " "acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "A chave da API está faltando" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Você deve especificar uma chave para a API do acoustid.org nas configurações " "do plug-in antes de puder enviar uma impressão digital." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Requisitar chave de API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Chave da API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Serviço web AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Enfileirada" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analisando" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Procura" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Escreve" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Publicação" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Escrever etiquetas MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Agrupar por pasta" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Modo álbum" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Escreve etiquetas relacionadas ao álbum, e tenta reduzir o número de versões " "e álbuns distintos" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Gerando impressões digitais:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detalhes" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Enviar" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "As músicas precisam de uma das etiqueta <i><b>musicbrainz_trackid</b></i> ou " "das etiquetas <i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></" "i> para poderem ser enviadas." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Impressões digitais:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Músicas com IDs MusicBrainz:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Músicas com etiquetas suficientes:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Musicas a enviar:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Feito. %(to-send)d/%(all)d músicas a enviar." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Enviando impressões digitais:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Enviando…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Atualiza etiquetas nos ficheiros" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Salva as atualizações de etiquetas nos ficheiros correspondentes " "automaticamente. Isso garante que contagens de reprodução e avaliações estão " "sempre em dia." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exportar para HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exporta a lista de músicas selecionada em formato HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Enviar para iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Envia suas músicas para o dispositivo iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Nenhum dispositivo iFP foi encontrado" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Não foi possível entrar em contato com seu dispositivo iFP. Verifique se o " "seu dispositivo está ligado e conectado, e que você instalou o ifp-line " "(http://ifp-driver.sf.net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Enviando %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Não foi possível enviar <b>%s</b>. O dispositivo pode não ter espaço " "disponível, ou pode estar desligado." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Erro no envio" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Exportar metadados" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Exportar metadados" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Exportar metadados" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Exportar metadados" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Informação de tempo ausente" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Capas de álbum" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Falha ao importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Importar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrar por pasta" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Disco" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Faixa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Artista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "álbums" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Continue" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Não foi possível encontrar \"%s\"." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Não foi possível encontrar \"%s\"." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Nomes de ficheiro" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Repetir cada faixa" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Atualizando lista de músicas favoritas." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Já está atualizada." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Obtendo a lista de músicas favoritas para a semana de %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Sincronização completa." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Erro durante a sincronização" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Sincronizar com Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" "Atualiza as estatísticas da sua biblioteca com base em seu perfil na Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "Nome de _usuário:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Criar etiquetas de ordenação" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Converte nomes de álbuns e de artistas para nomes de ordenação, porcamente." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Exportar como lista de reprodução" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exporta músicas para uma lista de reprodução em formato M3U ou PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Usar caminhos relativos" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Usar caminhos absolutos" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Falha ao escrever em <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Reescanear músicas" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Verifica por alterações nos ficheiros e recarrega ou remove músicas se " "necessário." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Reescaneando músicas" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Analizador ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Faixa" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Progresso" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Ganho" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Pico" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "<b>%(to-process)s</b> álbum a ser atualizado (de %(all)s)" msgstr[1] "<b>%(to-process)s</b> álbuns a serem atualizados (de %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analisa e atualiza a os metadados do <a href=\"%(rg_link)s\">ReplayGain</a>, " "usando o GStreamer. Os resultados são agrupados por álbum." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://pt.wikipedia.org/wiki/Replay_Gain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "sempre" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "se <b>pelo menus uma</b> etiqueta Repaly Gain estiver faltando" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "se as etiquetas Replay Gain de <b>álbum</b> estiverem faltando" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Processar álbuns:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Etiquetas existentes" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Separar etiquetas" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Separa o número de disco do álbum e a versão do título, ao mesmo tempo." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Separar álbum" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Separa o número de disco." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/d" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Restaurar" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Clique" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "BPM via clique" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "" "Calcula o número de batidas por minuto (BPM) para a música selecionada, " "manualmente, por cliques." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Pesquisa em website" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Pesquisa no website de sua escolha, usando qualquer etiqueta da música.\n" "Tem suporte a padrões, por exemplo %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Padrões de URL para pesquisa" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Editar URLs" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Configurar pesquisas…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Pesquisar etiqueta na Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Abre uma janela de navegador Web com o artigo da Wikipedia referente a uma " "das etiquetas da música selecionada." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Pesquisar em %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Editar etiquetas" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "A pesquisa falhou" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "A etiqueta\"%s\" não foi encontrada." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Biblioteca" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Verificando pontos de montagem" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Escaneando biblioteca" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Escaneando %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Carregando ficheiros" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Escaneando biblioteca" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Remove filtros de navegação ativos" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Reprodutor de música e gestor de biblioteca de música" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Falha ao carregar o ficheiro: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Lista etiquetas" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Imprime saída concisa" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Colunas a mostrar e ordem no modo conciso (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Também mostra etiquetas geradas _automaticamente" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Argumentos de menos" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Argumentos de mais" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Descrição" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valor" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Lista todas as etiquetas comumente usadas" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Copia etiquetas de um ficheiro para o outro" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Mostra alterações, mas não as aplica" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Ignora etiquetas que não podem ser gravadas" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" "Não foi possível copiar a etiqueta {tagname} para o ficheiro: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Edita etiquetas com um editor de texto" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Edição abortada" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Falha ao iniciar o editor \"%(editor-name)s\"." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Nenhuma alteração detectada" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Redefine o valor de uma etiqueta, removendo os valores existentes" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Não foi possível redefinir o valor de %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Remove etiquetas" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "O valor é uma expressão regular" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Remove todas as etiquetas" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Não é permitido combinar as opções \"--all\" com \"--regexp\"" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Não foi possível remover a etiqueta {tagname} de {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Remove valores de certas etiquetas" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Adiciona etiquetas" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Não foi possível redefinir o valor de %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Lista informações do ficheiro" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Define a imagem escolhida como a imagem embutida primária e remove todas as " "outas imagens embutidas" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Falha ao carregar ficheiro de imagem: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Não há suporte de edição de imagem para %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Remove todas as imagens embutidas" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrai as imagens embutidas para %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Caminho para onde as imagens devem ser salvas (o padrão é a pasta atual)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Renomeia ficheiros baseado nas etiquetas" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Preenche etiquetas baseado no nome do ficheiro" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Arquivo" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Preenche números de faixa para todos os ficheiros" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Imprime etiquetas baseado no padrão escolhido" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Mostra a ajuda" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "\"%(column-id)s\" não é um nome de coluna válido (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Desconhecido" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Em ordem" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "Em _ordem" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Aleatória" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "A_leatória" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Preferir a melhor avaliada" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Preferir a melhor avaliada" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Repetir esta música" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Repetir esta música" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Repetir todas" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Repetir todas" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Uma música" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Uma música" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Preenchimento do buffer" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Não foi possível criar a fila de processamento do GStreamer" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" "Não foi encontrado um elemento de GStreamer capaz de lidar com este formato " "de mídia" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Formato de mídia: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "O plug-in do GStreamer \"%(name)s\" não pode ser inicializado" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "A fila de processamento de saída do GStreamer a ser usada para reprodução. " "Deixe em branco para usar a fila padrão. Caso a fila de processamento " "contenha um consumidor, ele será usado ao invés do consumidor padrão." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "Fila de processamento de _saída:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Duração do _buffer:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Desativar reprodução sem intervalos" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Desativar a reprodução sem intervalos pode evitar problemas na troca de " "faixas que ocorrem em certas versões do GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nenhum consumidor de áudio do GStreamer foi encontrado" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "A fila de processamento de saída do GStreamer é inválida" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Não foi possível criar a saída de áudio" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "O dispositivo de áudio %r não foi encontrado. Verifique as suas " "configurações do Xine em ~/.quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Não foi encontrado o módulo \"{module}\". Talvez você precise instalar o " "pacote?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Não foi encontrado o elemento do GStreamer \"{element}\"." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Por favor visite a jánela de plug-ins para configurar o QLScrobbler. Antes " "disso ser feito as suas músicas não poderão ser enviadas." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Por favor visite a jánela de plug-ins para configurar o QLScrobbler. Antes " "disso ser feito as suas músicas não poderão ser enviadas." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Submissão" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nome de usuário:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Músicas que corresponderem a este filtro não serão enviadas" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Executar o plug-in \"%(name)s\" em %(count)s lista de reprodução?" msgstr[1] "Executar o plug-in \"%(name)s\" em %(count)s listas de reprodução?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Executar plug-in" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Início" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tempo" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nome do marcador" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Marcadores" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtros" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Recentemente _reproduzidas" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Recentemente _adicionadas" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Todas as _músicas" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Do _gênero atual" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Do _artista atual" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Do ál_bum atual" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "_Gênero aleatório" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "_Artista aleatório" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Ál_bum aleatório" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "As quarenta músicas que você mais tocou (mais de quarenta podem ser " "escolhidas se houver empates)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nome:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valor:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Valores gravados" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Editar valores gravados…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_mático" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Por _faixa" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Por _álbum" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Mudo" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "Modo do Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Novo %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(desconhecido)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Adicionar" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Editar display..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Expressão de etiqueta" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Expressão de etiqueta. Por exemplo, people:real or ~album~year." #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Insira uma nova etiqueta" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Expressão de etiqueta" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Arquivos:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "As músicas selecionadas serão removidas da biblioteca e seus ficheiros serão " "removidos do disco." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Os ficheiros selecionados serão excluídos do disco." #: quodlibet/qltk/delete.py:76 #, fuzzy, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" "Excluir %(file_count)d ficheiro permanentemente?Excluir %(file_count)d " "ficheiros permanentemente?" msgstr[1] "" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Exclui_r ficheiros" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "As músicas selecionadas serão removidas da biblioteca e ficheiros dela serão " "movidos para o lixo." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Os ficheiros selecionados serão movidos para o lixo." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Mover %(file_count)d ficheiro para o lixo?" msgstr[1] "Mover %(file_count)d ficheiros para o lixo?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mover para o lixo" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Movendo %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Não foi possível mover para o lixo" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Falha ao mover um ou mais ficheiros para o lixo." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Excluindo %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Não foi possível de excluir os ficheiros" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Falha ao excluir um ou mais ficheiros." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Navegadores" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Baixar arquivos" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "faltando em %d música" msgstr[1] "faltando em %d músicas" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "diferente em %d música" msgstr[1] "diferente em %d músicas" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Divide em vári_os valores" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Separar disco de á_lbum" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Separar _versão de título" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Separar arranjador de ar_tista" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Separar _intérprete do artista" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Separar _intérprete de título" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Separar _artistaoriginal de título" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Adicionar uma etiqueta" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "Etique_ta:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Mostrar etiquetas geradas _automaticamente" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Acessar todas as etiquetas, incluindo as geradas automaticamente. Por " "exemplo, etiquetas do MusicBrainz ou Replay Gain" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Mostrar etiquetas geradas _automaticamente" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Reverter" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Salvar" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Configurar" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "Dividir etiqueta" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Copiar valor(es)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Não foi possível adicionar a etiqueta" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Não foi possível adicionar as músicas" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Os ficheiros selecionados não dão suporte a múltiplos valores de <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Etiqueta inválida" msgstr[1] "Etiqueta inválida" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Etiqueta <b>%s</b> inválida\n" "\n" "Os ficheiros selecionados não suportam a edição desta etiqueta." msgstr[1] "" "Etiqueta <b>%s</b> inválida\n" "\n" "Os ficheiros selecionados não suportam a edição desta etiqueta." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Valor inválido" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Valor inválido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Etiqueta pode não estar correta" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s mudou enquanto este programa estava rodando. Se você salvar " "sem antes atualizar a sua biblioteca você poderá sobrescrever outras " "alterações feitas nesta música." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Não foi possível salvar a música" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Falha ao salvar %(file-name)s. O ficheiro pode ser somente leitura, estar " "corrompido , ou você pode não ter permissão para editá-lo." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Mais opções…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Desfazer" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Refazer" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Sobre" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Verificar por atualizações…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "Plu_g-ins" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s e %(count)s mais" msgstr[1] "%(title)s e %(count)s mais" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferências do Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Pastas" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nova pasta…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Selecionar todas as subpastas" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nova pasta" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Entre com o nome da nova pasta:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Não foi possível criar a pasta" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Não foi possível excluir a pasta" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Músicas" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "por %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Faixa %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "Do _gênero atual" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Editar exibição…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nenhuma música selecionada." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nenhuma música" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informação" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Letra" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produzido por %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistas" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "intérpretes" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nunca" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d vez" msgstr[1] "%(n)d vezes" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "adicionada" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "última reprodução" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "reproduções" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "ignorada" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "avaliação" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "caminho" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "duração" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formato" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codificação" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "taxa de bits" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "tamanho" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificado" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Adicional" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selecionado" msgstr[1] "%d selecionados" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Faixa indisponível" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d música sem álbum" msgstr[1] "%d músicas sem álbum" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discografia selecionada" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d música sem artista" msgstr[1] "%d músicas sem artistas" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "álbums" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Duração total:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Tamanho total:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Arquivos" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Procurar na internet" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Não foram encontradas letras para esta música." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Tem certeza que você quer excluir todas as músicas?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "As músicas selecionadas serão removidas da biblioteca." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Mostrar" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Mostrar" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Descartar alterações nas etiquetas?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Etiquetas foram alteradas, mas não gravadas. Salvar estes ficheiros, ou " "reverter e descartar as alterações?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Reverter" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Arquivo existe" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Sobrescrever %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Sobrescrever ficheiro" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Tarefas ativas" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d tarefas ativas" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Ativar/desativar o embaralhamento" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Ativar/desativar a repetição" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Eventos" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Ordem de Reprodução" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Edição" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Renomear" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Consulta:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Capas" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Plug-ins with errors" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Ativado" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Desativado" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Nenhuma categoria" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Nenhuma categoria" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nenhum plug-in foi encontrado." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Plug-ins" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrar pelo estado do plug-in" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrar pelo tipo do plug-in" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrar pelo nome ou descrição do plug-in" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Mostrar _erros" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Faixa" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "A_grupamento" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artista" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Ál_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Nome de ficheiro" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "Du_ração" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Ir automaticamente para a música em reprodução" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Quando a música em reprodução mudar, mostrá-la na lista" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Outros:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Editar…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Adicionar ou remover colunas" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Colunas visíveis" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Título inclui _versão" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Álbum inclui subtítulo do _disco" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Busca por artista inclui todas as _pessoas" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Nome do ficheiro inclui a _pasta" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Preferências das colunas" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Editar colunas" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Aplicar configuração atual à lista de músicas, incluindo as novas colunas no " "final" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de músicas" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Editar colunas" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Durações" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Filtro global:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Adicionar esta consulta a todas as outras" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Pesquisa" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Confirmar avaliações _conjuntas" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Pede confirmação antes de alterar a avaliação de múltiplas faixas " "simultaneamente" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Habilitar avaliação de _um clique" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Permite avaliar uma musica clicando na coluna de avaliação na lista de " "músicas" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Avaliações" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Preferir arte _embutida" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Preferir arte embutida dentro da trilha de áudio, se disponível, ao invés de " "outras fontes" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "Nome _fixo para ficheiro de imagem:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Capa de álbuns" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Reprodução" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Configuração da saída" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Caso não haja informação de Replay Gain disponível, modula o volume por este " "valor" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Ganho padrão (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Modula o volume de todas as músicas por este valor, contanto que não haja " "clipping" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Ganho pré-amp (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Habilitar o ajuste de volume Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Ajuste de volume Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Continuar reprodução ao iniciar" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Se uma música estiver tocando quando este aplicativo for fechado, reiniciá-" "la automaticamente na próxima sessão" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "Avaliação _padrão:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Escala de avaliação:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Fator da média bayesiana para avaliações agregadas.\n" "0 corresponde à média aritmética usual. Valores mais altos significam que " "álbuns com poucas faixas tem avaliações menos extremas. Alterar este valor " "resulta num recalculo da avaliação de todos os álbuns." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Fator da média _bayesiana:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Avaliações e o número de reproduções serão salvos em etiquetas para este " "email" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Salvar alterações automaticamente" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Salva alterações em etiquetas sem pedir confirmação, ao editar múltiplos " "ficheiros" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Um conjunto de separadores usados para separar valores de etiqueta no editor " "de etiquetas. Esta lista é separada por espaços." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Separar _etiquetas em:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Um conjunto de separadores usados para extrair sub-etiquetas no editor de " "etiquetas. Esta lista é separada por espaços, e cada elemento deve conter " "apenas dois caracteres." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Separar _sub-etiquetas em:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Etiquetas" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Edição de etiquetas" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Atualizando para novas avaliações" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "Atuali_zar biblioteca" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Verificar por alterações na biblioteca" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Re_construir biblioteca" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Recarregar todas as músicas na biblioteca. Isto pode demorar bastante." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Músicas escondidas" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Atualizar biblioteca ao _iniciar" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Pastas a escanear" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s e %(count)d mais" msgstr[1] "%(title)s e %(count)d mais" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Propriedades" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Fila de reprodução" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Esvaziar fila" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Desativar a fila – a fila será ignorada pelo tocador" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Efêmero" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Remover músicas da fila após reproduzí-las" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Persistente" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Manter músicas na fila após reproduzí-las" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Modo" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Parar no fim" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d música (%(time)s)" msgstr[1] "%(count)d músicas (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Navegar pela biblioteca" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Mostra/esconde a fila" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Erro de reprodução" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Configurar pastas da biblioteca?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" "Você ainda não configurou uma biblioteca. Gostaria de configurar uma agora?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "Agora _não" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Configurar" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Não foi possível adicionar as músicas" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s utiliza um protocolo para qual não há suporte." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "Ir para a música em reprodução" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Arquivo" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Músicas" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Ver" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Navegar" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Controle" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "A_juda" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "Adicionar uma _pasta…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Adicionar um _ficheiro…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Adicionar um _endereço…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Editar _marcadores…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Parar" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Parar após esta música" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Atalhos de _teclado" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "_Ajuda online" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Como _pesquisar na biblioteca" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Adicionar um endereço" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Insira o endereço de um ficheiro de áudio:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Não foi possível adicionar o endereço" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s não é um endereço válido." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Adicionar música" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Adicionar pastas" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Ficheiros de música" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Adicionar ficheiros" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Tem certeza que você quer excluir todas as músicas?" msgstr[1] "Tem certeza que você quer excluir todas as músicas?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Fila de reprodução" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Tem certeza que você quer alterar a avaliação de todas estas %d músicas?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "As avaliações salvas serão excluidas" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Remover avaliação" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "A avaliação das músicas selecionadas será alterada para \"%s\"" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Alterar _avaliação" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Substituir espaços por _sublinhados (\"_\")" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Remover caracteres incompatíveis com o _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Remover acentos e diacríticos" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Remover caracteres não-_ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Usar apenas letras minúsculas" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Renomear ficheiros" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Visualizar" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Nomes de ficheiro" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Mover capas de álbum" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Os nomes de ficheiros usados na busca são descritos na entrada \"[albumart] " "filenames\" do ficheiro de configuração" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Sobrescrever capa do álbum no destino" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "E_xcluir pastas vazias" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Capas de álbum" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Novo nome" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Não foi possível renomear o ficheiro" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Renomear <b>%(old-name)s</b> para <b>%(new-name)s</b> falhou. Possivelmente " "o novo nome é já está em uso, ou não tem permissão para criar o novo " "ficheiro ou apagar o antigo." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorar _todos os erros" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Parar" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continue" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "O caminho não é absoluto" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "O padrão\n" "\t<b>%s</b>\n" "contem / mas não começa do diretório raiz. Para evitar pastas com os nomes " "incorretos, inicie o seu padrão com / ou ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Músicas nestas pastas serão adicionadas à sua biblioteca quando ocorrer uma " "atualização da biblioteca" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "As músicas selecionadas serão removidas da biblioteca." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Removendo faixa órfã do iPod" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Caminho da biblioteca:" msgstr[1] "Caminho da biblioteca:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Remover" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Selecionar pastas" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Selecionar pastas" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Consultas salvas" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Editar consultas salvas…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Pesquise em sua biblioteca, por texto livre ou consultas QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Pesquise após digi_tar" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Exibir resultados da pesquisa após o usuário terminar de digitar" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limite:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Peso" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Adicionar consulta" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" "Adicionar uma consulta QL ou texto livre, a fazer parte do conjunto de busca" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Mostra o tempo restante" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Janela principal" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Recua 10 segundos" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Avança 10 segundos" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Foca o cursor na barra de pesquisa" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Restaura os critérios de filtragem e vai para a música em reprodução" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Abre a janela de informações para as músicas selecionadas" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Abre o editor de etiquetas para as músicas selecionadas" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Enfileira as músicas selecionadas" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Exclui as músicas selecionadas" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Mostrar a entrada de pesquisa inline" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Botão esquerdo num cabeçalho de coluna" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Adiciona a coluna aos critérios de ordenação" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Visualizador de árvore" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Colapsa o elemento, ou seleciona o seu pai" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Expande o elemento" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Entrada de texto" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Desfazer a última alteração" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Refazer a última alteração desfeita" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Selecionar todas as músicas de todos os painéis" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Todos os _cabeçalhos" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Cabeçalhos de _faixa" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Cabeçalhos de ál_buns" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Cabeçalhos de _pessoas" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Cabeçalhos de _data" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Cabeçalhos de _ficheiros" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Cabeçalhos de _produção" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Personalizar cabeçalhos…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Expandir coluna" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Remover a faixa \"%%(title)s\" da biblioteca?" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Remover a faixa \"%%(title)s\" da biblioteca?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "_Remover da biblioteca" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Executar o plug-in \"%(name)s\" em %(count)d faixas?" msgstr[1] "Executar o plug-in \"%(name)s\" em %(count)d faixa?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Executar o plugin \"%(name)s\" em %(count)d álbum?" msgstr[1] "Executar o plugin \"%(name)s\" em %(count)d álbuns?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Configurar plug-ins…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Adicionar à _fila" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Remover da biblioteca…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Não foi possível exibir os ficheiros" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Falha ao exibir ficheiros, ou não há um programa disponível para exibi-los." #: quodlibet/qltk/songsmenu.py:419 #, fuzzy, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" "_Exibir no gerenciador de ficheiros_Exibir %(total)d ficheiros no " "gerenciador de ficheiros" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Baixar…" msgstr[1] "_Baixar…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Falha ao salvar" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Baixar arquivo" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Baixar capas de álbum" msgstr[1] "Baixar capas de álbum" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Baixar arquivo" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Substituir _sublinhados (\"__\") por espaços" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Maiusculizar etiquetas" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "_Separar em múltiplos valores" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etiquetas pelo nome" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Etiquetas substituem as existentes" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Etiquetas são adicionadas às existentes" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "O padrão\n" "\t<b>%s</b>\n" "é inválido. Ele talvez contenha a mesma etiqueta mais de uma vez ou tenha " "delimitadores desbalanceados (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "O padrão inserido por você era inválido. Lembre-se de sempre escrever < e " "> como \\< e \\> e certifique-se de que as suas etiquetas estão " "balanceadas.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Editar exibição" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Números de faixa" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Começar _de:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Total de faixas:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Reproduzir/Pausar" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "_Anterior" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "e %d mais…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Salvando as músicas que você alterou." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d músicas salvas\n" "(%(remaining)s restando)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s de %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Verificação por atualizações" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Falha na conexão" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Você já está usando a versão mais recente (%(version)s)" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "A versão mais nova %(new-version)s já está disponível\n" "\n" "Você está usando a versão %(old-version)s\n" "\n" "Visite o <a href='%(url)s'>website</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importar lista de reprodução" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "A lista de reprodução deve ter um nome" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Uma lista de reprodução chamada %s já existe." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Capas de álbum embutidas" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Usa capas de álbum embutidas nos ficheiros de áudio." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Capa de álbum pelo sistema de ficheiros" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Procura próximo ao argivo da música por imagens com certos nomes comuns, " "para usar como capa do álbum." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Capas de álbum" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Consultando provedores de capas de álbum" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Mostra a ajuda" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Mostra versão e direitos autorais" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Imprime informação de depuração" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Uso: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opções]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "A opção %r não é reconhecida." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "A opção %r requer um parâmetro." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r não é um prefixo único." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s segundo" msgstr[1] "%s segundos" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Informação de tempo ausente" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dia" msgstr[1] "%d dias" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d ano" msgstr[1] "%d anos" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" "apenas a primeira letra deve ser maiúscula em português\n" "#?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "A data deve ser expressa nos formatos AAAA, AAAA-MM-DD ou AAAA-MM-DD HH:MM:" "SS." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Ganhos do Replay Gain devem ser inseridos no formato \"x.yy dB\"." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Picos do ReplayGain devem ser inseridos no formato \"x.yy\"." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Identificadores do MusicBrainz devem estar no formato UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "O \"MusicBrainz release status\" deve ser \"official\", \"promotional\" ou " "\"bootleg\"." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "O idioma deve ser um código de três letras ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Falha ao salvar" msgstr[1] "Falha ao salvar" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Não foi possível editar a música" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Falha ao salvar <b>%s</b>. O ficheiro pode ser somente leitura, estar " "corrompido , ou você pode não ter permissão para editá-lo." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codificação inválida]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "álbum" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arranjador" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arranjadores" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "arranjo" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autores" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "comentário" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compositor" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compositores" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "composição" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "condutor" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "condutores" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "condução" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contato" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "data" #: quodlibet/util/tags.py:94 msgid "description" msgstr "descrição" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "gênero" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "gêneros" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "intérprete" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "performance" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "agrupamento" #: quodlibet/util/tags.py:98 msgid "language" msgstr "língua" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licença" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "compositor" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "compositores" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "letras" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "gravadora" #: quodlibet/util/tags.py:104 msgid "title" msgstr "título" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versão" #: quodlibet/util/tags.py:106 msgid "website" msgstr "website" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "artista do álbum" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "subtítulo do álbum" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "faixa" # label ID #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "identificador de rótulo" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "data de lançamento original" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "álbum original" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artista original" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "data de gravação" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "país de lançamento" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "ganho da faixa" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "pico da faixa" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "ganho do álbum" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "pico do álbum" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "referência de sonoridade" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "discos" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "faixas" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "último inicio" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nome completo" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "ponto de montagem" #: quodlibet/util/tags.py:166 msgid "people" msgstr "pessoas" #: quodlibet/util/tags.py:168 msgid "year" msgstr "ano" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "ano de lançamento original" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "marcador" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "profundidade de bits" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "formato de ficheiro" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "listas de reprodução" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "taxa de amostragem" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "número de canais" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "ordenação" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "papel" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor de etiquetas de metadados para ficheiros de áudio" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Edite etiquetas de metadados em seus ficheiros de áudio" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Reprodutor de músicas" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Ouça, navegue, ou edite sua coleção de músicas" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso é um editor de etiquetas de metadados para ficheiros de áudio, com " "a mesma interface do Quod Libet. Permite visualizar e alterar qualquer " "etiqueta, para qualquer ficheiro num dos formatos para qual haja suporte." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Há suporte para ficheiros Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/IT, " "Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, e MIDI, dentre " "outros." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "O Quod Libet é um aplicativo de gestão de músicas. Ele disponibiliza " "diversas maneiras de visualizar a sua coleção de músicas, e também tem " "suporte a rádio via internet e feeds de áudio. Ele também é um poderoso e " "flexível editor de etiquetas de metadados para áudio." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Exportar para lista de reprodução do Squeezebox" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Não foi possível adicionar <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Etiquetas inválidas" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "<b>%s</b> não são etiquetas válidas\n" #~ "\n" #~ "Os ficheiros selecionados não tem suporte a estas etiquetas." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Avalia as músicas automaticamente a medida elas são reproduzidas ou " #~ "puladas/ignoradas. Este plug-in usa um algoritmo \"acelerado\" originário " #~ "do vux, desenvolvido por Brian Nelson." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f segundos" #~ msgid "Startup" #~ msgstr "Inicialização" #~ msgid "Audio Feeds" #~ msgstr "Feeds de áudio" #~ msgid "_Audio Feeds" #~ msgstr "_Feeds de áudio" #~ msgid "New" #~ msgstr "Nova" #~ msgid "Automatic Library Update" #~ msgstr "Atualização automática da biblioteca" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Mantém sua biblioteca atualizada via inotify. Requer %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Permite controlar remotamente o Quod Libet pela interface MPRIS 2 para D-" #~ "Bus." #~ msgid "Searching for lyrics…" #~ msgstr "Procurando por letras…" #, fuzzy #~ msgid "<artist>" #~ msgstr "artista" #, fuzzy #~ msgid "<album>" #~ msgstr "álbum" #, fuzzy #~ msgid "<title>" #~ msgstr "título" #, fuzzy #~ msgid "OK" #~ msgstr "_OK" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "" #~ "Exporta os metadados das músicas selecionadas num ficheiro \".tags\"." #~ msgid "Import Metadata" #~ msgstr "Importar metadados" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "" #~ "Importa metadados para as músicas selecionadas de um ficheiro \".tags\"." #~ msgid "Migrate Metadata" #~ msgstr "Migrar metadados" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "" #~ "Copia metadados específicos ao Quod Libet de uma música para a outra." #~ msgid "_Copy" #~ msgstr "_Copiar" #~ msgid "_Paste" #~ msgstr "_Colar" #~ msgid "Information to copy/paste" #~ msgstr "Informação a copiar/colar" #~ msgid "Map tracks by disc and track number" #~ msgstr "Mapear faixas por disco e número da faixa" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Ative esta opção quando você quiser migrar metadados de um álbum para o " #~ "outro, emparelhando por disco e número de faixa.\n" #~ "\n" #~ "<b>Nota:</b> esta opção precisa estar ativada durante a cópia para que a " #~ "informação seja armazenada." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "%d faixa armazenada." #~ msgstr[1] "%d faixas armazenadas." #~ msgid "Unsupported file type" #~ msgstr "Não há suporte para este formato de arquivo" #~ msgid "Unable to add station" #~ msgstr "Não foi possível adicionar a estação" #~ msgid "Search Library" #~ msgstr "Pesquisar na biblioteca" #~ msgid "_Search Library" #~ msgstr "_Pesquisar na biblioteca" #~ msgid "Quit Program" #~ msgstr "Sair do programa" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Impede o protetor de tela do GNOME de ativar enquanto uma música estiver " #~ "sendo reproduzida." #~ msgid "No lyrics found" #~ msgstr "Nenhuma letra foi encontrada" #~ msgid "_Zoom level:" #~ msgstr "_Ampliação:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Procure as letras pelo URL acima, caso elas não sejam encontradas na " #~ "LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Pesquisa alternativa" #~ msgid "Web Lyrics" #~ msgstr "Letras online" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Exibe uma barra lateral com a letra da música em reprodução, obtida a " #~ "partir da internet." #~ msgid "Skip Songs" #~ msgstr "Ignorar músicas" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "" #~ "A reprodução ignora músicas com uma avaliação igual ou abaixo o limite " #~ "especificado." #~ msgid "" #~ "Supports QL patterns\n" #~ "eg <tt><~artist~title></tt>" #~ msgstr "" #~ "Há suporte para padrões QL\n" #~ "Por exemplo, <tt><~artist~title></tt>" #~ msgid "Burn CD" #~ msgstr "Gravar em CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Grava em CDs com K3b, Brasero ou xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "Usar apenas este nome de arquivo para imagem" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "" #~ "O nome do arquivo de imagem de capa de álbum a ser usado. Pode conter " #~ "curingas." #~ msgid "Vertical Split" #~ msgstr "Divisão vertical" #~ msgid "Device Properties" #~ msgstr "Propriedades do aparelho" #~ msgid "Device:" #~ msgstr "Aparelho:" #~ msgid "Not mounted" #~ msgstr "Não montado" #~ msgid "Mount point:" #~ msgstr "Ponto de montagem:" #~ msgid "Media Devices" #~ msgstr "Aparelhos externos" #~ msgid "_Media Devices" #~ msgstr "_Aparelhos externos" #~ msgid "_Eject" #~ msgstr "_Ejetar" #~ msgid "_Properties" #~ msgstr "_Propriedades" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "%(used-size)s usado, %(free-size)s disponível" #~ msgid "%s is not connected." #~ msgstr "%s não está conectado." #~ msgid "Copying %(song)s" #~ msgstr "Copiando %(song)s" #~ msgid "Unable to copy song" #~ msgstr "Impossível copiar a música" #~ msgid "There is not enough free space for this song." #~ msgstr "Não existe espaço livre suficiente para esta música." #~ msgid "%s could not be copied." #~ msgstr "%s não pôde ser copiado." #~ msgid "Unable to delete songs" #~ msgstr "Impossível remover músicas" #~ msgid "Deleting %(song)s" #~ msgstr "Removendo %(song)s" #~ msgid "%s could not be deleted." #~ msgstr "%s não pôde ser removida." #~ msgid "Unable to delete song" #~ msgstr "Impossível apagar música" #~ msgid "Ejecting %s failed." #~ msgstr "Falha ao ejetar %s." #~ msgid "Unable to eject device" #~ msgstr "Impossível ejetar aparelho" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "" #~ "Nenhum backend de dispositivo. O navegador de dispositivos multimídia foi " #~ "desabilitado." #~ msgid "Rate the playing song" #~ msgstr "Avaliar a música atual" #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Mostrar ou ocultar a lista de músicas principal (deprecado)" #~ msgid "Unknown Device" #~ msgstr "Aparelho desconhecido" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Não foi possível importar %s, que é necessário para suporte a " #~ "dispositivos." #~ msgid "%r is not a supported device." #~ msgstr "Não há suporte para o dispositivo %r." #~ msgid "Initializing device backend." #~ msgstr "Inicializando o backend de dispositivo." #~ msgid "Trying '%s'" #~ msgstr "Tentando \"%s\"" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Não foi possível conectar ao backend de dispositivo." #~ msgid "Device backend initialized." #~ msgstr "Backend de dispositivos inicializado." #~ msgid "_Filename pattern:" #~ msgstr "Formato do _nome do arquivo:" #~ msgid "File Bug Report" #~ msgstr "Preencher um relatório de erro." #, fuzzy #~ msgid "_Clear" #~ msgstr "Limpar _erros" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Letras" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Letras" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Letras" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Impossível criar pasta" #~ msgid "Supported formats: %s" #~ msgstr "Formatos suportados: %s" #~ msgid "Audio device: %s" #~ msgstr "Dispositivo de som: %s" #~ msgid "Downloads" #~ msgstr "Downloads" #~ msgid "Size" #~ msgstr "Tamanho" #~ msgid "_Download" #~ msgstr "_Download" #~ msgid "_Copy to Device" #~ msgstr "_Copiar para o aparelho" #, fuzzy #~ msgid "browsers" #~ msgstr "Navegadores" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Não foi possível importar python-feedparser, navegador de feeds de áudio " #~ "desabilitado." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Uma exceção ocorreu no Quod Libet. Um arquivo de dump foi salvo em <b>%s</" #~ "b> ele ajudará você a depurar o erro. Por favor, encaminhe o erro para " #~ "http://code.google.com/p/quodlibet/issues/list e anexe este arquivo ou " #~ "inclua seu conteúdo. Este arquivo pode conter alguma informação de " #~ "identificação sobre você e seu sistema, assim como a lista de arquivos " #~ "recentes reproduzidos. Se isto não for aceitável para você envie <b>%s</" #~ "b> no lugar e uma descrição do que você estava fazendo no momento.\n" #~ "\n" #~ "Quod Libet pode agora instável agora. Fechá-lo e reiniciá-lo é " #~ "recomendado. Sua biblioteca irá ser salva." #~ msgid "Unable to download lyrics." #~ msgstr "Impossível baixar letras" #~ msgid "Set or toggle the playback order" #~ msgstr "Define ou altera a ordem de reprodução" #~ msgid "Uninitialized iPod" #~ msgstr "iPod não-inicializado" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Você deseja criar uma base de dados vazia nesse iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Ganho de _Volume (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combinar etiquetas com _múltiplos valores" #~ msgid "Capacity:" #~ msgstr "Capacidade:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Impossível gravar biblioteca do iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Impossível gravar biblioteca do iPod" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "" #~ "Não foi possível importar python-gpod, suporte ao iPod desabilitado." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "pico da faixa" #~ msgid "Shuffle" #~ msgstr "Embaralhar" #~ msgid "Weighted" #~ msgstr "Ponderado" #~ msgid "_Weighted" #~ msgstr "_Ponderado" #~ msgid "_One Song" #~ msgstr "_Uma música" #~ msgid "Restart the playlist when finished" #~ msgstr "Reiniciar a lista de reprodução quando acabado" #~ msgid "Disable Browser" #~ msgstr "Desabilitar navegador" #~ msgid "_Disable Browser" #~ msgstr "_Desabilitar navegador" #, fuzzy #~ msgid "Force Write" #~ msgstr "Escrever" #~ msgid "Filter on _Genre" #~ msgstr "Filtrar por _gênero" #~ msgid "Filter on _Artist" #~ msgstr "Filtrar por _artista" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrar por ál_bum" #~ msgid "_Music" #~ msgstr "_Música" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Marcadores" #~ msgid "Song _List" #~ msgstr "_Lista de músicas" #, fuzzy #~ msgid "D:" #~ msgstr "W: " #, fuzzy #~ msgid "W:" #~ msgstr "W: " #, fuzzy #~ msgid "E:" #~ msgstr "E: " #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Roda do mouse troca de música;\n" #~ "Shift e roda do mouse ajusta o volume" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Parar após essa música" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "e %d mais..." #~ msgstr[1] "e %d mais..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Separar disco de á_lbum" #, fuzzy #~ msgid "Timeout" #~ msgstr "Tempo" #, fuzzy #~ msgid "Select an album" #~ msgstr "Selecionar _todos" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s e %(count)d mais" #~ msgstr[1] "%(title)s e %(count)d mais" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Listas de reprodução" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Usar cantos arredondados nas miniaturas" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Arredonda os cantos da imagem de miniatura da arte da capa. Pode requerer " #~ "a reinicialização para funcionar." #~ msgid "Re_fresh Library" #~ msgstr "Atuali_zar biblioteca" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Remover Estação" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "O GStreamer não possui elementos para manipular arquivos. Verifique suas " #~ "configurações de instalação do GStreamer." #~ msgid "Invalid audio backend" #~ msgstr "Backend de áudio inválido" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "O backend de áudio %r não está instalado." #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "nome_de_arquivo" #~ msgid "command|tag" #~ msgstr "etiqueta" #, fuzzy #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Não foi possível encontrar o media-player-info." #, fuzzy #~ msgid "heading|Search" #~ msgstr "Buscar" #~ msgid "%d of %d" #~ msgstr "%d de %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Uso: %s %s" #~ msgid "_Download..." #~ msgstr "_Download..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nova estação" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Sobrescrever <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Erro de saída" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "O pipeline de saída do GStreamer não pôde ser inicializado. O pipeline " #~ "deve ser inválido, ou o dispositivo deve estar em uso. Verifique as " #~ "preferências de reprodução." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet já está em execução." #~ msgid "No song is currently playing." #~ msgstr "Nenhuma música está sendo tocada." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Impossível escrever em %s. Removendo." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Editar marcadores..." #~ msgid "_New Folder..." #~ msgstr "_Nova pasta..." #~ msgid "_Add to Playlist" #~ msgstr "_Adicionar à lista de reprodução" #~ msgid "_Edit Display..." #~ msgstr "_Editar display..." #~ msgid "Output Log" #~ msgstr "Registro de saída" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d estação" #~ msgid "_Order:" #~ msgstr "_Ordem:" #~ msgid "_Add a Location..." #~ msgstr "_Adicionar um local..." #~ msgid "_Output Log" #~ msgstr "Registr_o de saída" #~ msgid "Invalid command %r received." #~ msgstr "Comando inválido %r recebido." #~ msgid "Unknown browser %r." #~ msgstr "Navegador desconhecido: %r" #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "Per_sonalizar cabeçalhos" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #~ msgstr[1] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #~ msgstr[1] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "Cabeçalhos de Faixa" #, fuzzy #~ msgid "People Headers" #~ msgstr "Cabeçalhos de _pessoas" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Cabeçalhos de á_lbuns" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Cabeçalhos de _data" #, fuzzy #~ msgid "File Headers" #~ msgstr "Cabeçalhos de _filtros" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Cabeçalhos de p_rodução" #, fuzzy #~ msgid "Tag:" #~ msgstr "Etique_ta:" #~ msgid "Too Many Errors" #~ msgstr "Muitos erros" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Parando a reprodução pelo fato de haver %d erros em uma linha." #~ msgid "Warnings" #~ msgstr "Avisos" #, fuzzy #~ msgid "No log available." #~ msgstr "No information available" #~ msgid "album artist (sort)" #~ msgstr "artista do álbum (ordenado)" #~ msgid "artist (sort)" #~ msgstr "artistas (ordenado)" #~ msgid "album (sort)" #~ msgstr "álbum (ordenado)" #~ msgid "performer (sort)" #~ msgstr "intérprete (ordenado)" #~ msgid "performers (sort)" #~ msgstr "intérpretes (ordenado)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID do álbum do artista no MusicBrainz" #~ msgid "errors" #~ msgstr "erros" #~ msgid "Permanently delete this file?" #~ msgstr "Permanentemente apagar este arquivo?" #~ msgid "Permanently delete these files?" #~ msgstr "Permanently apagar estes arquivos?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s e %(count)d mais..." #~ msgstr[1] "%(title)s e %(count)d mais..." #, fuzzy #~ msgid "Version:" #~ msgstr "_Version" #~ msgid "_Cause an Error" #~ msgstr "_Causar um erro" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s não pode ser adicionada à sua biblioteca.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Nenhum comando para ejetar encontrado." #~ msgid "Unable to start web browser" #~ msgstr "Impossível abrir um navegador web" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Um navegador de internet não foi encontrado. Por favor, defina a variável " #~ "$BROWSER, ou garanta que /usr/bin/sensible-browser exista." #, fuzzy #~ msgid "Library Error" #~ msgstr "Navegador de biblioteca" #, fuzzy #~ msgid "_Output device:" #~ msgstr "Saída d_o pipeline:" #~ msgid "translator-credits" #~ msgstr "" #~ "Alexandre Passos <alexandre.tp@gmail.com>\n" #~ "Djavan Fagundes <djavan@comum.org>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Outras colunas a mostrar, separadas por espaços" #~ msgid "_Edit and Continue" #~ msgstr "_Editar e continuar" #, fuzzy #~ msgid "You are about to change the rating of %d song." #~ msgid_plural "You are about to change the rating of %d songs." #~ msgstr[0] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #~ msgstr[1] "" #~ "Você irá alterar a classificação de %d músicas.\n" #~ "Você tem certeza que deseja continuar?" #~ msgid "Confirm rating" #~ msgstr "Confirmar classificação" #~ msgid "Search your library" #~ msgstr "Busca na sua biblioteca" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, e outros\n" #~ "\n" #~ "Este software é livre; veja o código fonte para as condições de " #~ "redistribuição. Não há\n" #~ "NENHUMA garantia; nem para COMERCIALIZAÇÃO ou UTILIDADE PARA UM PROPÓSITO " #~ "ESPECÍFICO.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r não possui nenhum navegador." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Tamanho total:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r não contém nenhum dispositivo." #~ msgid "%s: Could not import ctypes." #~ msgstr "%s: Não foi possível importar ctypes." #~ msgid "%s: Could not find media-player-info." #~ msgstr "%s: Não foi possível encontrar o media-player-info." #, fuzzy #~ msgid "Couldn't find module %s." #~ msgstr "%s: Não foi possível encontrar o media-player-info." #~ msgid "Quod Libet Plugins" #~ msgstr "Plug-ins do Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Mostra buscas simples em azul, avançadas em verde, e inválidas em vermelho" #~ msgid "Separators for splitting tags" #~ msgstr "Separadores para as etiquetas" #~ msgid "Quod Libet Preferences" #~ msgstr "Preferências do Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Não reproduzidas _hoje" #~ msgid "Not Played in a _Week" #~ msgstr "Não reproduzidas em uma _semana" #~ msgid "Not Played in a _Month" #~ msgstr "Não reproduzidas em um _mês" #~ msgid "B_ottom 40" #~ msgstr "40 m_enos" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "As quarenta músicas menos tocadas (mais de quarenta podem ser escolhidas " #~ "se houver empates)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #~ msgid "Date" #~ msgstr "Data" #~ msgid "Choose New Stations" #~ msgstr "Escolher novas estações" #~ msgid "Add" #~ msgstr "Adicionar" #~ msgid "Bitrate" #~ msgstr "Taxa de bits" #~ msgid "_Stations..." #~ msgstr "_Estações..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Inicializando backend de áudio (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Inicializando biblioteca principal (%s)" #~ msgid "Unable to save library" #~ msgstr "Impossível gravar biblioteca" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Impossível tocar música" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "O pipeline de saída de áudio %r não pôde ser criado. Verifique suas " #~ "configurações do GStreamer em ~/.quodlibet/config." #~ msgid "Sort by title" #~ msgstr "Ordenar por título" #~ msgid "Sort by artist" #~ msgstr "Ordenar por artista" #~ msgid "Lyrics provided by %s." #~ msgstr "Letras por %s" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Nenhuma letra foi encontrada.\n" #~ "\n" #~ "Você pode clicar no botão Download para que Quod Libet busque por letras " #~ "das músicas na internet. Você pode digitá-las você mesmo e clicar em " #~ "gravar." #~ msgid "part" #~ msgstr "parte" #~ msgid "Opening audio device." #~ msgstr "Abrindo dispositivo de som." #~ msgid "Moving %d/%d." #~ msgstr "Movendo %d/%d." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d músicas gravadas" #~ msgid "MusicBrainz album ID" #~ msgstr "ID de álbum MusicBrainz" #~ msgid "Loaded song library." #~ msgstr "Biblioteca carregada." #~ msgid "Unable to open audio device" #~ msgstr "Impossível abrir dispositivo de som" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet tentou acessar os drivers 'autosink' e '%(sink)s' mas não foi " #~ "capaz de abrir nenhum deles. Escolhe a pipeline correta no seu GStreamer " #~ "mudando a linha\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "no seu arquivo ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet não conseguiu achar o elemento GStreamer 'filesrc'. Verificque " #~ "a sua instalação do GStreamer." #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "Mostrar _capas" #~ msgid "Unable to retag multiple values" #~ msgstr "Impossível alterar as tags de múltiplos valores" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Mudar o nome de uma tag com valores múltiplos não é possível." #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s não é uma base de dados de músicas QL." #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Ajuste por música (\"Radio\")" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Ajuste por álbum (\"Audiófilo\")" #~ msgid "_Volume Normalization" #~ msgstr "Normalização do _Volume" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Quod Libet está lendo a sua biblioteca. Isso pode demorar vários " #~ "minutos.\n" #~ "\n" #~ "%d músicas recarregadas\n" #~ "%d músicas removidas" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Quod Libet está procurando por músicas novas e adicionando-as à sua " #~ "biblioteca.\n" #~ "\n" #~ "%d músicas adicionadas" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "Playlists M3U não podem ser carregadas." #~ msgid "This station is already in your library." #~ msgstr "Essa estação já está em sua biblioteca." #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "por <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disco <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Faixa <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "" #~ "A biblioteca não pode ser atualizada enquando Quod Libet está rodando." #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Carregando, lendo e gravando a biblioteca." #~ msgid "Rescan your library and exit" #~ msgstr "Relê a sua biblioteca e sai" #~ msgid "" #~ "It looks like you are running Quod Libet right now. If you edit songs " #~ "also in Quod Libet's library while it is running, you may need to refresh " #~ "or re-add them.\n" #~ "\n" #~ "If you are not running Quod Libet, or are editing songs outside of its " #~ "library, you may ignore this warning." #~ msgstr "" #~ "Parece que você está usando o Quod Libet agora. Se você editar músicas " #~ "que também estão na biblioteca do Quod Libet enquanto ele está rodando, " #~ "você precisa mandar atualizá-las ou relê-las.\n" #~ "\n" #~ "Se você não está usando o Quod Libet, ou está editando músicas que não " #~ "estão em sua biblioteca, você pode ignorar esse aviso." #~ msgid "GStreamer status %r != %r" #~ msgstr "Status do GStreamer %r != %r" #~ msgid "_Pane %d:" #~ msgstr "_Painel %d:" #~ msgid "Double-click a tag value to change it, right-click for other options" #~ msgstr "Duplo-clique numa tag altera, botão direito dá opções" #~ msgid "Add a new tag" #~ msgstr "Adicionar nova tag" #~ msgid "The first letter of each word will be capitalized" #~ msgstr "A primeira letra de cada palavra estará em maiúsculas" #~ msgid "" #~ "Characters not allowed in Windows filenames (\\:?;\"<>|) will be replaced " #~ "by underscores" #~ msgstr "" #~ "Caracteres não permitidos em arquivos Windows (\\:?;\"<>|) serão " #~ "substituídos por underscores" #~ msgid "" #~ "Characters outside of the ASCII set (A-Z, a-z, 0-9, and punctuation) will " #~ "be replaced by underscores" #~ msgstr "" #~ "Caracteres não-ASCII (A-Z, a-z, 0-9, e pontuação básica) serão " #~ "substituídos por underscores" #~ msgid "Apply to these _files..." #~ msgstr "Aplicar a esses _arquivos..." #~ msgid "Path" #~ msgstr "Caminho" #~ msgid "Tray Preferences - Quod Libet" #~ msgstr "Preferências do Painel - Quod Libet" #~ msgid "E: You need GTK+ 2.6 and PyGTK 2.6 or greater." #~ msgstr "E: Você precisa de GTK+ 2.6 e PyGTK 2.6 ou mais recente." #~ msgid "E: You have GTK+ %s and PyGTK %s." #~ msgstr "E: Você tem GTK+ %s e PyGTK %s." #~ msgid "E: Please upgrade GTK+/PyGTK." #~ msgstr "E: Por favor, atualize GTK+/PyGTK." #~ msgid "%(different)s, %(missing)s" #~ msgstr "%(different)s, %(missing)s" #~ msgid "Play songs in random order" #~ msgstr "Tocas as músicas em ordem aleatória" #~ msgid "S_ong" #~ msgstr "Mú_sica" #~ msgid "_Choose randomly" #~ msgstr "_Escolher aleatoriamente" #~ msgid "Drag songs here to add them to the play queue" #~ msgstr "Arraste músicas para cá para adicioná-las à fila de reprodução" #~ msgid "" #~ "Deleting <b>%s</b> failed. Possibly the target file does not exist, or " #~ "you do not have permission to delete it." #~ msgstr "" #~ "Apagar <b>%s</b> falhou. Possivelmente o arquivo não existe, ou você não " #~ "tem permissão para apagá-lo." #~ msgid "" #~ "Quod Libet was unable to open your audio device. Often this means another " #~ "program is using it, or your audio drivers are not configured.\n" #~ "\n" #~ "Quod Libet will now exit." #~ msgstr "" #~ "Quod Libet não conseguiu abrir o seu dispositivo de som. Normalmente, " #~ "isso significa que outro programa está usando-o, ou os seus drivers de " #~ "som não estão configurados. \n" #~ "Quod Libet vai sair." #~ msgid "_New/Edit Playlist..." #~ msgstr "_New/Edit Playlist..." #~ msgid "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgstr "" #~ "Enter a name for the new playlist. If it already exists it will be opened " #~ "for editing." #~ msgid "Turn shuffle off, on, or toggle it" #~ msgstr "Turn shuffle off, on, or toggle it" #~ msgid "Closing _minimizes to system tray" #~ msgstr "Closing _minimizes to system tray" #~ msgid "Performed by %s" #~ msgstr "Performed by %s" #~ msgid "arranged by %s" #~ msgstr "arranged by %s" #~ msgid "conducted by %s" #~ msgstr "conducted by %s" #~ msgid "composed by %s" #~ msgstr "composed by %s" #~ msgid "written by %s" #~ msgstr "written by %s" #~ msgid "Add songs to your library" #~ msgstr "Add songs to your library" #~ msgid "Visit the artist's website" #~ msgstr "Visit the artist's website" #~ msgid "Change volume" #~ msgstr "Change volume" #~ msgid "" #~ "Invalid tag <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing this tag.Invalid tags " #~ "<b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Invalid tag <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing this tag.Invalid tags " #~ "<b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgid "(shared across all %d songs)" #~ msgstr "(shared across all %d songs)" #~ msgid "(different across %d songs, missing from %d songs)" #~ msgstr "(different across %d songs, missing from %d songs)" #~ msgid "1 minute" #~ msgstr "1 minute" #~ msgid "1 hour" #~ msgstr "1 hour" #~ msgid "1 day" #~ msgstr "1 day" #~ msgid "An audio player and tag editor" #~ msgstr "An audio player and tag editor" #~ msgid "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgstr "" #~ "If you have songs in directories that will not always be mounted (for " #~ "example, a removable device or an NFS shared drive), list those mount " #~ "points here. Files in these directories will not be removed from the " #~ "library if the device is not mounted." #~ msgid "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgstr "" #~ "These characters will be used as separators when \"Split values\" is " #~ "selected in the tag editor" #~ msgid "Initialized multimedia key support." #~ msgstr "Initialised multimedia key support." #~ msgid "1 track" #~ msgstr "1 track" #~ msgid "Adjust audio volume" #~ msgstr "Adjust audio volume" #~ msgid "Check for changes in the library made since the program was started" #~ msgstr "Check for changes in the library made since the program was started" #~ msgid "1 time" #~ msgstr "1 time" #~ msgid "Add a new tag to the file" #~ msgstr "Add a new tag to the file" #~ msgid "Invalid date format" #~ msgstr "Invalid date format" #~ msgid "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgstr "" #~ "Invalid date: <b>%s</b>.\n" #~ "\n" #~ "The date must be entered in YYYY or YYYY-MM-DD format." #~ msgid "No on-screen display" #~ msgstr "No on-screen display" #~ msgid "Display OSD on the top" #~ msgstr "Display OSD on the top" #~ msgid "Display OSD on the bottom" #~ msgstr "Display OSD on the bottom" #~ msgid "Select a color for the OSD" #~ msgstr "Select a colour for the OSD" #~ msgid "Select a second color for the OSD" #~ msgstr "Select a second colour for the OSD" #~ msgid "Song _list" #~ msgstr "Song _list" #, fuzzy #~ msgid "[directory]" #~ msgstr "directory" #~ msgid "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgstr "" #~ "Quod Libet - a music library and player\n" #~ "Options:\n" #~ " --help, -h Display this help message\n" #~ " --version Display version and copyright information\n" #~ " --refresh-library Rescan your song cache and then exit.\n" #~ " --print-playing Print the currently playing song.\n" #~ "\n" #~ " Player controls:\n" #~ " --next, --previous, --play-pause, --play, --pause\n" #~ " Change songs or pause/resume playing.\n" #~ " --volume +|-|0..100\n" #~ " Increase, decrease, or set the volume.\n" #~ " --shuffle 0|1|t, --repeat 0|1|t\n" #~ " Enable, disable, or toggle shuffle and repeat. \n" #~ " --query search-string\n" #~ " Make a new playlist from the given search.\n" #~ " --seek [+|-][HH:MM:]SS\n" #~ " Seek to a position in the current song.\n" #~ " --play-file filename\n" #~ " Play this file, adding it to the library if necessary.\n" #~ "\n" #~ "For more information, see the manual page (`man 1 quodlibet').\n" #~ msgid "" #~ "Quod Libet %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE." #~ msgstr "" #~ "Quod Libet %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE." #~ msgid "E: Unknown command line option: %s" #~ msgstr "E: Unknown command line option: %s" #~ msgid "%d:%02d:%02d" #~ msgstr "%d:%02d:%02d" #~ msgid "%d:%02d" #~ msgstr "%d:%02d" #~ msgid "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgstr "" #~ "Ex Falso - an audio file tagger\n" #~ "Usage: %s [directory]\n" #~ "\n" #~ "For more information, see the manual page (`man 1 exfalso').\n" #~ msgid "Quod Libet is free software licensed under the GNU GPL v2." #~ msgstr "Quod Libet is free software licensed under the GNU GPL v2." #~ msgid "Songs heard:" #~ msgstr "Songs heard:" #~ msgid "Listening" #~ msgstr "Listening" #~ msgid "%s and %d more - Properties" #~ msgstr "%s and %d more - Properties" #~ msgid "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgstr "" #~ "No on-screen display\n" #~ "Display OSD on the top\n" #~ "Display OSD on the bottom" #~ msgid "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "" #~ "No volume adjustment\n" #~ "Per-song (\"Radio\") volume adjustment\n" #~ "Per-album (\"Audiophile\") volume adjustment" #~ msgid "Perfor_mer" #~ msgstr "Perfor_mer" #~ msgid "Pick a random album from your library" #~ msgstr "Pick a random album from your library" #~ msgid "Pick a random artist from your library" #~ msgstr "Pick a random artist from your library" #~ msgid "Pick a random genre from your library" #~ msgstr "Pick a random genre from your library" #~ msgid "Play next song" #~ msgstr "Play next song" #~ msgid "Pre_vious song" #~ msgstr "Pre_vious song" #~ msgid "Select a font for the OSD" #~ msgstr "Select a font for the OSD" #~ msgid "Pause _song" #~ msgstr "Pause _song" #~ msgid "xx minutes, " #~ msgstr "xx minutes, " �����������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/quodlibet.pot��������������������������������������������������������������������0000644�0001750�0001750�00000532611�14470736246�015362� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1302 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1428 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "" #: quodlibet/cli.py:88 msgid "[option]" msgstr "" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "" #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1165 msgid "_Play" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1167 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "" #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "" #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1311 #, python-format msgid "%s uses an unsupported protocol." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1300 msgid "Add a Location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Enter the location of an audio file:" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1306 #: quodlibet/qltk/quodlibetwindow.py:1310 msgid "Unable to add location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1307 #, python-format msgid "%s is not a valid location." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1319 #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Add Music" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1319 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1326 msgid "Music Files" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "_Add Files" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1419 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:1429 msgid "_Enqueue" msgstr "" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "" #: quodlibet/qltk/songlist.py:1195 msgid "All _Headers" msgstr "" #: quodlibet/qltk/songlist.py:1196 msgid "_Track Headers" msgstr "" #: quodlibet/qltk/songlist.py:1197 msgid "_Album Headers" msgstr "" #: quodlibet/qltk/songlist.py:1198 msgid "_People Headers" msgstr "" #: quodlibet/qltk/songlist.py:1199 msgid "_Date Headers" msgstr "" #: quodlibet/qltk/songlist.py:1200 msgid "_File Headers" msgstr "" #: quodlibet/qltk/songlist.py:1201 msgid "_Production Headers" msgstr "" #: quodlibet/qltk/songlist.py:1216 msgid "_Customize Headers…" msgstr "" #: quodlibet/qltk/songlist.py:1221 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "" msgstr[1] "" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "" msgstr[1] "" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "" #: quodlibet/util/tags.py:83 msgid "album" msgstr "" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "" #: quodlibet/util/tags.py:86 msgid "author" msgstr "" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "" #: quodlibet/util/tags.py:93 msgid "date" msgstr "" #: quodlibet/util/tags.py:94 msgid "description" msgstr "" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "" #: quodlibet/util/tags.py:98 msgid "language" msgstr "" #: quodlibet/util/tags.py:99 msgid "license" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "" #: quodlibet/util/tags.py:104 msgid "title" msgstr "" #: quodlibet/util/tags.py:105 msgid "version" msgstr "" #: quodlibet/util/tags.py:106 msgid "website" msgstr "" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "" #: quodlibet/util/tags.py:166 msgid "people" msgstr "" #: quodlibet/util/tags.py:168 msgid "year" msgstr "" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" �����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/ro.po����������������������������������������������������������������������������0000644�0001750�0001750�00000644053�14436352625�013627� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# translation of ro.po to Română # Romanian translation of Quod Libet # Copyright (C) 2006, Free Software Foundation # This file is distributed under the same license as the Quod Libet package. # # # Mugurel Tudor <mugurelu@gnome.ro>, 2006. # Mişu Moldovan <dumol@gnome.ro>, 2006. msgid "" msgstr "" "Project-Id-Version: ro\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2013-07-20 22:30+0100\n" "Last-Translator: Mugurel Tudor <mugurelu@gnome.ro>\n" "Language-Team: Română <gnomero@lists.sourceforge.net>\n" "Language: ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3;plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" "2:1));\n" "X-Generator: Poedit 1.5.4\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 #, fuzzy msgid "_Title" msgstr "Titlu" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "persoane" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Dată" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "Coloane _dată" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 #, fuzzy msgid "_Original Date" msgstr "artist iniţial" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 #, fuzzy msgid "_Genre" msgstr "gen" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "E_valuare" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "Editare afişare" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Sortează după dată" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 #, fuzzy msgid "_Preferences" msgstr "Preferinţe" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Listă albume" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Listă _albume" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Toate albumele" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albume" msgstr[2] "%d de albume" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Arată _coperţile albumelor" msgstr[1] "Arată _coperţile albumelor" msgstr[2] "Arată _coperţile albumelor" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Piese ce nu aparţin unui album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d pistă" msgstr[1] "%d piste" msgstr[2] "%d de piste" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disc" msgstr[1] "%d discuri" msgstr[2] "%d de discuri" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 #, fuzzy msgid "An Example Album" msgstr "Toate albumele" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferinţe listă albume" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Arată _coperţile albumelor" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 #, fuzzy msgid "Options" msgstr "[opţiuni]" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Afişare albume" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Navigator colecţie" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d piesă" msgstr[1] "%d piese" msgstr[2] "%d de piese" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Şablon invalid" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "" #: quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Necunoscut" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Separă în valori _multiple" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Personalizat" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 #, fuzzy msgid "_Remove" msgstr "E_valuare" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etichetă" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "" #: quodlibet/browsers/collection/prefs.py:187 #, fuzzy msgid "Album Collection Preferences" msgstr "Preferinţe listă albume" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Mărime totală:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Mărime totală:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Preferinţe navigator încastrat" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Arată _coperţile albumelor" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Toate albumele" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "organizaţie" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Sistem de fişiere" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "Sistem de _fişiere" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nu s-au putut copia piesele" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Fişierele selectate nu pot fi copiate în alte liste de piese sau în coadă." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Adaugă la colecţie" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Listele de staţii pot conţine doar locaţiile staţiilor, nu şi alte liste de " "staţii sau liste de redare. Următoarele locaţii nu pot fi încărcate:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Staţie nouă" #: quodlibet/browsers/iradio.py:265 #, fuzzy msgid "Downloading station list" msgstr "Descarcă fişierele" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Staţie nouă" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Introduceţi locaţia unei staţii radio Internet:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:399 #, fuzzy msgid "Latin" msgstr "evaluare" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "Staţie _nouă" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "Radio _Internet" #: quodlibet/browsers/iradio.py:587 #, fuzzy msgid "All Stations" msgstr "Staţie nouă" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Staţie nouă" #: quodlibet/browsers/iradio.py:653 #, fuzzy msgid "_Update Stations" msgstr "Staţie _nouă" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nici s-a găsit nici o staţie" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nu s-a găsit nici o staţie radio Internet la %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Toate staţiile listate sunt deja în colecţie." #: quodlibet/browsers/iradio.py:869 #, fuzzy msgid "Add to Favorites" msgstr "_Adaugă în listă" #: quodlibet/browsers/iradio.py:873 #, fuzzy msgid "Remove from Favorites" msgstr "Şte_rge din listă" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d staţie" msgstr[1] "%(count)d staţii" msgstr[2] "%(count)d de staţii" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Navigator încastrat" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Navigator încastrat" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Selectează t_ot" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Necunoscut" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Toate" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Coloane vizibile" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Preferinţe navigator încastrat" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Liste" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Liste" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Şte_rge din listă" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importă" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Nu s-a putut importa lista de redare" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet poate importa liste de redare doar în formatele M3U sau PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Ştergere fişiere" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Redenumeşte" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Nu s-a putut redenumi lista" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importă lista" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importă" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "Listă _nouă" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Listă nouă" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Preferinţe navigator încastrat" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Liste" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Pistă" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Listă nouă" #: quodlibet/browsers/playlists/util.py:72 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Introduceţi un nume pentru noul director:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Se importă lista de redare.\n" "\n" "%d/%d piese adăugate." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Flux nou" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Introduceţi locaţia unui flux audio:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Adăugare _fişier..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Reactualizare c_olecţie" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Monitorizează acest director pentru piese noi" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Nu s-a putut adăuga fluxul" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> nu a putut fi adăugat. Serverul ar putea fi nefuncţional ori " "locaţia ar putea să nu fie a unui flux audio." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Limitează rezultatele" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Separă în valori m_ultiple" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Listă piste" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Listă piste" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Navigator încastrat" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Navigator încastrat" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Caută" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "piste" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "locaţie" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> nu este conectat." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nu este pornit." #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "redare audio pentru colecţii de muzică" #: quodlibet/cli.py:88 #, fuzzy msgid "[option]" msgstr "[opţiuni]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Afişare piesă redată curent" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Cu pornire imediată a redării" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Salt la piesa următoare" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Salt la piesa precedentă" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Start redare" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pauză redare" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Comutare între start şi pauză redare" #: quodlibet/cli.py:102 #, fuzzy msgid "Stop playback" msgstr "Start redare" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Volum mai mare" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Volum mai mic" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Afişare status curent" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Ascundere fereastră principală" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Afişare fereastră principală" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Comutare a vizibilităţii ferestrei principale" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Focalizare a ferestrei de redare" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:113 #, fuzzy msgid "Refresh and rescan library" msgstr "Reactualizare c_olecţie" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Dezactivează navigatorul" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Afişare a listei curente" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Afişare a cozii curente" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Afişare a cozii curente" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nu este pornit." #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Ieşire Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Derulare în piesa redată curent" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Comutare între start şi pauză redare" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Comutare între start şi pauză redare" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Anulare, activare sau comutare a repetării" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Comutare între start şi pauză redare" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Setare volum" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Căutare în colecţia muzicală" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "căutare" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Redare fişier" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "nume" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Derulare în piesa redată curent" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Setare a navigatorului web utilizat" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Evaluare a piesei redate curent" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Deschidere nou navigator web" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Afişare/ascundere a cozii" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrare după o valoare aleatoare" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "Etichetă" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etichetă=valoare" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Punere fişier în coadă sau căutare" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "nume" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:146 #, fuzzy msgid "Unqueue a file or query" msgstr "Punere fişier în coadă sau căutare" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "locaţie" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Şablon invalid" #: quodlibet/cli.py:216 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Argument invalid pentru „%s”." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Încercaţi %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Arată _erorile" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "descriere" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "un editor de etichete audio" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "director" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Editor pentru etichete audio" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "ID pistă MusicBrainz" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID pistă MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Codare invalidă]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Titlu" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Editor pentru etichete audio" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Prima literă _majusculă" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Preferinţe navigator încastrat" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Mărime totală:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Editare afişare" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Pondere" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editare afişare" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Previzualizare" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Informaţii" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Formate suportate: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtrare după _gen" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "director" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Fluxuri audio" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Staţie _nouă" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Salvează evaluarile şi numărul de redări" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "dată de înregistrare" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Arată _erorile" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "Staţie _nouă" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 #, fuzzy msgid "Preferences" msgstr "Preferinţe" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Importă lista" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importă" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Importă" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Anulaţi modificarea etichetelor?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Anulaţi modificarea etichetelor?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Redare" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "şablon" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "şablon" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d secundă" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Filtrare după _artist" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Selectează" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Previzualizare" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Personalizat" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Nu s-au putut şterge piesele" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Şablon invalid" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Redare audio" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Model:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Radio Internet" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "E_valuare" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "locaţie" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Ascundere fereastră principală" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "şablon" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "şablon" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d piesă" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Informaţii" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "şablon" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "locaţie" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "Tip album MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Nume:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "Titlu" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Nume favorit" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Dispozitiv:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "Alt_ele:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "Model nume _fişier:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "A_lbum aleator" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "albume" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Pondere" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "A_lbum aleator" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Favorite" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Nume favorit" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Nume favorit" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[opţiuni]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "[Codare invalidă]" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "dată de înregistrare" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Ştergere fişiere" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Versuri" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Ştergere fişiere" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Versuri" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Nici s-a găsit nici o staţie" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 #, fuzzy msgid "Path Patterns" msgstr "şablon" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Editare valori salvate..." #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Artist" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Previzualizare" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Redare audio" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Importă lista" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organizaţie" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Adăugare staţii noi" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Versuri" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Calea nu este una absolută" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Şablonul\n" "\t<b>%s</b>\n" "conţine / dar nu porneşte din rădăcină. Pentru a evita directoarele greşit " "numite, aveţi grijă ca şablonul să înceapă cu / sau ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Nici o piesă nu este selectată." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Nici o piesă nu este selectată." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Nu s-a putut salva piesa" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Versuri" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Nu s-au putut deschide fişierele" msgstr[1] "Nu s-au putut deschide fişierele" msgstr[2] "Nu s-au putut deschide fişierele" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Versuri" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Oprit" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d piesă" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "şablon" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "E_valuare" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Oprit" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "_Liste" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Redare" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "_Previzualizare" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Aleator" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetare" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Stop după această piesă" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Deschidere nou navigator web" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Editare _etichete" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informaţii" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Liste" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Editare afişare" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Versuri" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Versurile pentru această piesă nu au putut fi găsite." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Nu s-a putut salva piesa" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Arată _erorile" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Fişiere" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Previzualizare" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtrare după _artist" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Personalizat" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Personalizat" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filtrare după _gen" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filtrare după _artist" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Fluxuri audio" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Introduceţi locaţia unui flux audio:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importă lista" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Importă" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Nici s-a găsit nici o staţie" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "Model nume _fişier:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Nu s-a putut importa lista de redare" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "Model nume _fişier:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Importă lista" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Şte_rge din listă" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Listă nouă" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "ultima redare" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "ultima redare" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "_Coadă" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "_Coadă" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "_Coadă" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Niciodată" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Niciodată" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "grupare" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Nu s-au putut copia piesele" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtrare după _gen" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Etichete invalide" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Valori salvate" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Valori salvate" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Redenumeşte" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Colecţie" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Ascundere fereastră principală" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Nume fişier" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Nu s-a putut salva piesa" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Listă albume" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Mărime" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Caută:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Caută" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Listă albume" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Editare favorite..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Editare favorite..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Favorite" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "Tip album MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Nume fişier" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "Di_sc" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Pistă" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Titlu" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Artist" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "Tip album MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "căutare" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Caută" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Nici un modul nu a fost găsit." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "locaţie" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Listă albume" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Listă albume" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Nici un modul nu a fost găsit." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Previzualizare" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "comandă|etichetă" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Redenumeşte" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "comandă|etichetă" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Niciodată" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Valoare invalidă" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Personalizat" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Nu s-au putut copia piesele" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Dezactivează navigatorul" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "E_valuare" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "E_valuare" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Editare afişare" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Separă în valori _multiple" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "E_valuare" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filtrare dupa o valoare din etichetă" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer nu a putut încărca piesa selectată." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtrare după _gen" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "_Coadă" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Scrie" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "ID pistă MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "director" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "Coloane _album" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "Staţie _nouă" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Nici un modul nu a fost găsit." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Mut %d/%d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Importă lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Importă lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Durată necunoscută" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Listă albume" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importă lista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importă" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrare după _gen" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Di_sc" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Pistă" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Artist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albume" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Continuă" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Nume fişier" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "piste" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Arată _erorile" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Redenumeşte" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Importă lista" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Ejectarea <b>%s</b> a eşuat." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Reactualizare c_olecţie" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Reactualizare c_olecţie" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Pistă" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Editare etichete" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Editare etichete" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Toate albumele" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Previzualizare" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etichetă" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Nu s-au putut şterge piesele" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Caută" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "şablon" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Editare valori salvate..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Colorează termenii de _căutare" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Editare etichete" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Caută" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Colecţie" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Se verifică punctele de montare" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Se verifică colecţia" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Se verifică %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Se verifică colecţia" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "redare audio pentru colecţii de muzică" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Arată etichetele _programatice" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "descriere" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Valoare" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Editor pentru etichete audio" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Nici o piesă nu este selectată." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Durată necunoscută" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Nu s-a putut redenumi fişierul" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fişier" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Arată pe scurt informaţiile de utilizare" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nu este o locaţie validă." #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "Necunoscut" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "În ordine" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "În _ordine" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Aleator" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Aleator" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "ultima redare" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Repetare" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Repetare" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "O singură piesă" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "O singură piesă" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%d secundă" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nici s-a găsit nici o staţie" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "Nu s-a putut crea directorul" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Nume:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Module" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Început" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Timp" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Nume favorit" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Favorite" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtre" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "Nu a fost _niciodată redat" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Primele 40" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Staţie nouă" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "_Gen aleator" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "A_rtist aleator" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "A_lbum aleator" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "Cele mai des redate 40 de piese (mai mult de 40 în anumite cazuri)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Nume:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Valoare:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Valori salvate" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Editare valori salvate..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "Coloane _pistă" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "Coloane _album" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ajustare de volum _replay gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Necunoscut" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "Adăugare _fişier..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Editare afişare..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filtrare dupa o valoare din etichetă" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Editor pentru etichete audio" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Fişiere" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Ştergere fişiere" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mută la Gunoi" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "Mut %d/%d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Nu s-a putut salva baza de date iPod" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Ejectarea <b>%s</b> a eşuat." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Se şterge %d/%d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Nu s-a putut şterge fişierul" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Ştergerea <b>%s</b> a eşuat." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Navigatoare" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Descarcă fişierele" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "lipseşte din %d piesă" msgstr[1] "lipseşte din %d piese" msgstr[2] "lipseşte din %d de piese" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "diferit în %d piesă" msgstr[1] "diferit în %d piese" msgstr[2] "diferit în %d de piese" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Separă în valori _multiple" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Separă discul de _album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Separă _versiunea de titlu" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Separă aranjorul de ar_tist" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Separă _interpretul de artist" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Separă _interpretul de artist" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Separă _versiunea de titlu" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Adaugă o etichetă" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Etichetă:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Arată etichetele _programatice" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Arată etichetele _programatice" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Niciodată" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Continuă" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Editare etichete" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Copiază coperţile _albumelor" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Nu s-a putut adăuga eticheta" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Nu s-au putut adăuga piesele" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Nu s-a putut adăuga <b>%s</b>\n" "\n" "Fişierul selectat nu suportă valori multiple." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Etichetă invalidă" msgstr[1] "Etichetă invalidă" msgstr[2] "Etichetă invalidă" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Etichetă invalidă <b>%s</b>\n" "\n" "Fişierle selectate curent nu suportă editarea acestei etichete." msgstr[1] "" "Etichetă invalidă <b>%s</b>\n" "\n" "Fişierle selectate curent nu suportă editarea acestei etichete." msgstr[2] "" "Etichetă invalidă <b>%s</b>\n" "\n" "Fişierle selectate curent nu suportă editarea acestei etichete." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Valoare invalidă" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Valoare invalidă: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Eticheta ar putea fi imprecisă" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> a fost modificat în timp ce aplicaţia era pornită. Salvarea sa " "fără reactualizarea colecţiei ar putea suprascrie alte modificări ale " "piesei.\n" "\n" "Salvaţi totuşi această piesă?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Nu s-a putut salva piesa" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Salvarea <b>%s</b> a eşuat. Fişierul ar putea fi protejat la scriere, corupt " "sau cu drepturi prea stricte pentru a-l putea edita." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Mai multe opţiuni..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Module" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s şi %(count)d în plus" msgstr[1] "%(title)s şi %(count)d în plus" msgstr[2] "%(title)s şi %(count)d în plus" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Preferinţe Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Directoare" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Director nou" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Selectează toate subdirectoarele" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Director nou" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Introduceţi un nume pentru noul director:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Nu s-a putut crea directorul" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Nu s-a putut şterge directorul" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Piese" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "de către %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Discul %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Pista %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Editare afişare" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nici o piesă nu este selectată." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nici o piesă" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informaţii" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Versuri" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Produs de către %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artist" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artişti" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "interpreţi" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Niciodată" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "O dată" msgstr[1] "De %(n)d ori" msgstr[2] "De %(n)d de ori" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "adăugat" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "ultima redare" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "redări" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "întreruperi" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "evaluare" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "durată" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Informaţii" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[Codare invalidă]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "rată de biţi" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "mărime fişier" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificat" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selectată" msgstr[1] "%d selectate" msgstr[2] "%d selectate" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Pistă nedisponibilă" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d piesă fără album" msgstr[1] "%d piese fără album" msgstr[2] "%d de piese fără album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Discografie selectată" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d piesă fără artist" msgstr[1] "%d piese fără artist" msgstr[2] "%d de piese fără artist" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albume" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Durată totală:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Mărime totală:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Fişiere" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Versurile pentru această piesă nu au putut fi găsite." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Anulaţi modificarea etichetelor?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Etichetele au fost modificate, dar nu au fost salvate. Salvaţi aceste " "fişiere sau reveniţi la valorile iniţiale şi anulaţi modificările?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Niciodată" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Fişierul există" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Redenumire fişiere" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Comutare între start şi pauză redare" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Comutare între start şi pauză redare" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Ordine:" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Editare etichete" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Redenumeşte" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "căutare" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Mărime totală:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Erori module" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "Dezactivează navigatorul" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nici un modul nu a fost găsit." #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Module" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Arată _erorile" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "Di_sc" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Pistă" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "grupare" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artist" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Nume _fişier" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "D_urată" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Sări automat la piesa redată" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Când se schimbă piesa redată, derulează la aceasta în listă" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "Alt_ele:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Editare afişare..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Coloane vizibile" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Titlul include ver_siunea" #: quodlibet/qltk/prefs.py:139 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Albumul include pa_rtea" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Titlul include ver_siunea" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Numele de fişier include dire_ctorul" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Preferinţe" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Coloane vizibile" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Listă piese" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Coloane vizibile" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "Filtru _global:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Caută" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navigatoare" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "Când se schimbă piesa redată, derulează la aceasta în listă" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 #, fuzzy msgid "Ratings" msgstr "E_valuare" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Listă albume" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Pauză redare" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Volume Gain (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Volume Gain (dB):" #: quodlibet/qltk/prefs.py:428 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Ajustare de volum _replay gain" #: quodlibet/qltk/prefs.py:445 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Ajustare de volum _replay gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "E_valuare" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Adresă de mail:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Evaluările şi numărul de redări vor fi setate pentru această adresă de mail" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Anulaţi modificarea etichetelor?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Separare _la:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Separare _la:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Editare etichete" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Editare etichete" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "Staţie _nouă" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "Caută în c_olecţie" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Caută noutăţi în colecţie" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Reîn_cărcare colecţie" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Reîncarcă toate piesele din colecţie (poate dura foarte mult)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Nici o piesă" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "Reactualizare c_olecţie" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" # ??? #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "_Directoare indexate" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, fuzzy, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s şi %(count)d în plus" msgstr[1] "%(title)s şi %(count)d în plus" msgstr[2] "%(title)s şi %(count)d în plus" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Proprietăţi" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Coadă" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "Erori module" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Şterge toate piesele din coadă" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Model:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d piesă (%(time)s)" msgstr[1] "%(count)d piese (%(time)s)" msgstr[2] "%(count)d de piese (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Navigare în colecţie" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Comutare a vizibilităţii ferestrei principale" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Pauză redare" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Selectare directoare" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Nu s-au putut adăuga piesele" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> foloseşte un protocol nesuportat." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Sări la piesa redată" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Fişier" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Piese" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Vizualizare" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Navigatoare" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Control" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Ajutor" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "Adăugare _director..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "Adăugare _fişier..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Adăugare locaţie" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editare favorite..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Stop după această piesă" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Caută" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Adăugare locaţie" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Introduceţi locaţia unui fişier audio:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Nu s-a putut adăuga locaţia" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nu este o locaţie validă." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Adăugare muzică" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "Adăugare _director..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Redare audio" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "Adăugare _fişier..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Coadă" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "E_valuare" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "E_valuare" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Înlocuieşte spaţiile cu liniuţe de _subliniere" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Şterge caracterele incompatibile cu sistemele _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Şterge semnele _diacritice" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Şterge caracterele non-_ASCII" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Redenumire fişiere" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Previzualizare" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Nume fişier" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "artist album" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "Ş_terge directoarele şi coperţile nefolosite" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Listă albume" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nume nou" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Nu s-a putut redenumi fişierul" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Redenumirea fişierului <b>%s</b> în <b>%s</b> a eşuat. S-ar putea ca " "fişierul ţintă să existe deja sau poate nu aveţi drepturile necesare pentru " "a crea noul fişier sau a-l şterge pe cel vechi." #: quodlibet/qltk/renamefiles.py:346 #, fuzzy msgid "Ignore _All Errors" msgstr "Arată _erorile" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Continuă" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Calea nu este una absolută" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Şablonul\n" "\t<b>%s</b>\n" "conţine / dar nu porneşte din rădăcină. Pentru a evita directoarele greşit " "numite, aveţi grijă ca şablonul să înceapă cu / sau ~/." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Piesele din aceste directoare (separate de „:”) vor fi adăugate la colecţie" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "W: sterg pista orfană din iPod" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Colecţie" msgstr[1] "Colecţie" msgstr[2] "Colecţie" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "E_valuare" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Selectare directoare" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Selectare directoare" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Valori salvate" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Editare valori salvate..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "Stop după această piesă" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Limită:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Pondere" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "căutare" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Arată timpul rămas" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Versuri" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Focalizare a ferestrei de redare" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Derulare în piesa redată curent" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Nu s-au putut şterge piesele" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Nu s-au putut şterge piesele" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrare după %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "Coloane _album" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "Coloane _pistă" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "Coloane _album" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "Coloane _persoane" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "Coloane _dată" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "Coloane _fişier" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "Coloane _producţie" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Personalizează coloanele..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Şte_rge din listă" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Şte_rge din listă" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "Şte_rge din listă" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Colorează termenii de _căutare" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Adaugă în _coadă" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "Şte_rge din listă" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Nu s-a putut şterge fişierul" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Caută" msgstr[1] "_Caută" msgstr[2] "_Caută" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Caută" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Descarcă fişierul" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Listă albume" msgstr[1] "Listă albume" msgstr[2] "Listă albume" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Descarcă fişierul" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Înlocuieşte liniuţele de _subliniere cu spaţii" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Prima literă _majusculă" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Separă în valori m_ultiple" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Etichetare din cale" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Etichetele le înlocuiesc pe cele actuale" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Etichetele sunt adăugate la cele actuale" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Şablonul\n" "\t<b>%s</b>\n" "este invalid. S-ar putea să conţină aceeaşi etichetă de două ori sau " "paranteze potrivite greşit (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Şablonul introdus a fost invalid. Asiguraţi-vă că aţi introdus < şi > " "ca \\< şi \\> şi că parantezele sunt potrivite corect.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Editare afişare" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Număr piste" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Start _de la:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Total piste:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Redare" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "_Previzualizare" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "şi alte %d..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Se salvează piesele modificate." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Mut %d/%d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Se verifică punctele de montare" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "locaţie" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importă lista" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "O listă cu numele „%s” există deja." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Arată _coperţile albumelor" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Sistem de fişiere" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Mărime totală:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Arată pe scurt informaţiile de utilizare" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Arată versiunea şi drepturile de autor" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Durată necunoscută" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opţiuni]" #: quodlibet/util/__init__.py:167 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Opţiunea „%s” nu a fost recunoscută." #: quodlibet/util/__init__.py:170 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Opţiunea „%s” necesită un argument." #: quodlibet/util/__init__.py:173 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: „%s” nu este un prefix unic." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d secundă" msgstr[1] "%d secunde" msgstr[2] "%d de secunde" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Durată necunoscută" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d secundă" msgstr[1] "%d secunde" msgstr[2] "%d de secunde" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minute" msgstr[2] "%d de minute" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d oră" msgstr[1] "%d ore" msgstr[2] "%d de ore" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d zi" msgstr[1] "%d zile" msgstr[2] "%d de zile" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d an" msgstr[1] "%d ani" msgstr[2] "%d de ani" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "fără_capitalizare" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Data trebuie introdusă în formatul „YYYY”, „YYYY-MM-DD” sau „YYYY-MM-DD HH:" "MM:SS”." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Normalizarea Replay Gain trebuie introdusă în format „x.yy dB”." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Vârfurile Replay Gain trebuie introduse în format „x.yy”." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "ID-urile MusicBrainz trebuie să fie în formatul UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Statusul de lansare MusicBrainz trebuie să fie „official” (oficial), " "„promotional” (promoţional) sau „bootleg” (ilegal)." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Ejectarea <b>%s</b> a eşuat." msgstr[1] "Ejectarea <b>%s</b> a eşuat." msgstr[2] "Ejectarea <b>%s</b> a eşuat." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Nu s-a putut edita piesa" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Salvarea <b>%s</b> a eşuat. Fişierul ar putea fi protejat la scriere, corupt " "sau cu drepturi prea stricte pentru a-l putea edita." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Codare invalidă]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranjor" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranjori" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "aranjor" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "comandă|etichetă" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "compozitor" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "compozitori" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "compozitor" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirijor" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirijori" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "dirijor" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "contact" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "drepturi de autor" #: quodlibet/util/tags.py:93 msgid "date" msgstr "dată" #: quodlibet/util/tags.py:94 msgid "description" msgstr "descriere" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "gen" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "gen" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "interpret" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "interpret" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupare" #: quodlibet/util/tags.py:98 msgid "language" msgstr "limbaj" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licenţă" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "textier" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "textieri" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "textier" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizaţie" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titlu" #: quodlibet/util/tags.py:105 msgid "version" msgstr "versiune" #: quodlibet/util/tags.py:106 msgid "website" msgstr "adresă internet" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "artist album" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disc" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "pistă" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "ID etichetă" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "dată iniţială de lansare" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "album iniţial" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "artist iniţial" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "dată de înregistrare" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "ţara de lansare" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID pistă MusicBrainz" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID pistă MusicBrainz" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "ID pistă MusicBrainz" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID artist MusicBrainz" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID pistă MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "ID TRM MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "ID PUID MusicBrainz" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Status album MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Tip album MusicBrainz" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID pistă MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "corecţie pistă" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "vârf pistă" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "corecţie album" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "vârf album" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Preferinţe" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "discuri" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "piste" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "ultima lansare" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "nume complet" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "punct de montare" #: quodlibet/util/tags.py:166 msgid "people" msgstr "persoane" #: quodlibet/util/tags.py:168 msgid "year" msgstr "an" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "dată iniţială de lansare" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "Favorite" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "format" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Liste" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor pentru etichete audio" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Editare etichete fişiere audio" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Ieşire Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Redare audio" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Ascultaţi, editaţi sau cautaţi în propria colecţie audio" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Importă lista" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Nu s-a putut adăuga piesa" #~ msgid "Invalid tags" #~ msgstr "Etichete invalide" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Etichete invalide <b>%s</b>\n" #~ "\n" #~ "Fişierele selectate nu suportă editarea acestor etichete." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d secundă" #, fuzzy #~ msgid "Startup" #~ msgstr "_Importă" #~ msgid "Audio Feeds" #~ msgstr "Fluxuri audio" #~ msgid "_Audio Feeds" #~ msgstr "Fluxuri a_udio" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Se caută versurile..." #, fuzzy #~ msgid "<artist>" #~ msgstr "artist" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "titlu" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importă lista" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importă lista" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informaţii" #~ msgid "Unsupported file type" #~ msgstr "Tip nesuportat de fişier" #~ msgid "Unable to add station" #~ msgstr "Nu s-a putut adăuga staţia" #~ msgid "Device Properties" #~ msgstr "Proprietăţi dispozitiv" #~ msgid "Device:" #~ msgstr "Dispozitiv:" #~ msgid "Not mounted" #~ msgstr "Nu este montat" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Punct de montare:" #~ msgid "Media Devices" #~ msgstr "Dispozitive media" #~ msgid "_Media Devices" #~ msgstr "Dispozitive _media" #~ msgid "_Eject" #~ msgstr "_Ejectare" #, fuzzy #~ msgid "_Properties" #~ msgstr "Proprietăţi" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> folosit, <b>%s</b> disponibil" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Copiez <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "Nu s-a putut copia piesa" #~ msgid "There is not enough free space for this song." #~ msgstr "Nu există suficient spaţiu disponibil pentru această piesă." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> nu a putut fi copiat." #~ msgid "Unable to delete songs" #~ msgstr "Nu s-au putut şterge piesele" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Şterg <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> nu a putut fi şters." #~ msgid "Unable to delete song" #~ msgstr "Nu s-a putut şterge piesa" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Ejectarea <b>%s</b> a eşuat." #~ msgid "Unable to eject device" #~ msgstr "Nu s-a putut ejecta dispozitivul" #~ msgid "Search Library" #~ msgstr "Căutare în colecţie" #~ msgid "_Search Library" #~ msgstr "Caută în c_olecţie" #~ msgid "Rate the playing song" #~ msgstr "Evaluare a piesei redate curent" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Afişare/ascundere a listei principale de piese" #~ msgid "Unknown Device" #~ msgstr "Dispozitiv necunoscut" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: „%s” nu este un prefix unic." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Valoare invalidă" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "Model nume _fişier:" #, fuzzy #~ msgid "_Clear" #~ msgstr "Erori module" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Versuri" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Şterge căutarea" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Versuri" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Versuri" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Nici o piesă" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Navigatoare" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Nu s-a putut crea directorul" #~ msgid "Audio device: %s" #~ msgstr "Dispozitiv audio: %s" #~ msgid "Downloads" #~ msgstr "Transferuri" #~ msgid "Size" #~ msgstr "Mărime" #~ msgid "_Download" #~ msgstr "_Caută" #~ msgid "_Copy to Device" #~ msgstr "_Copiază către dispozitiv" #, fuzzy #~ msgid "browsers" #~ msgstr "Navigatoare" #~ msgid "Unable to download lyrics." #~ msgstr "Nu s-au putut descărca versurile." #~ msgid "Set or toggle the playback order" #~ msgstr "Setare ori comutare a ordinii de redare" #~ msgid "Uninitialized iPod" #~ msgstr "iPod neiniţializat" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Doriţi să creaţi o bază de date goală pe acest iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volume Gain (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Combină etichetele cu valori m_ultiple" #~ msgid "Capacity:" #~ msgstr "Capacitate:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Nu s-a putut salva baza de date iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Nu s-a putut salva baza de date iPod" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "vârf pistă" #~ msgid "Shuffle" #~ msgstr "Aleator" #~ msgid "Weighted" #~ msgstr "Ponderat" #~ msgid "_Weighted" #~ msgstr "_Ponderat" #~ msgid "_One Song" #~ msgstr "O _singură piesă" #~ msgid "Restart the playlist when finished" #~ msgstr "Repetă lista" #~ msgid "Disable Browser" #~ msgstr "Dezactivează navigatorul" #~ msgid "_Disable Browser" #~ msgstr "_Dezactivează navigatorul" #, fuzzy #~ msgid "Force Write" #~ msgstr "Scrie" #~ msgid "Filter on _Genre" #~ msgstr "Filtrare după _gen" #~ msgid "Filter on _Artist" #~ msgstr "Filtrare după _artist" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrare după al_bum" #~ msgid "_Music" #~ msgstr "_Muzică" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Favorite" #~ msgid "Song _List" #~ msgstr "Listă _piese" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Stop după această piesă" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "şi alte %d..." #~ msgstr[1] "şi alte %d..." #~ msgstr[2] "şi alte %d..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Separă discul de _album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Timp" #, fuzzy #~ msgid "Select an album" #~ msgstr "Selectează t_ot" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s şi %(count)d în plus" #~ msgstr[1] "%(title)s şi %(count)d în plus" #~ msgstr[2] "%(title)s şi %(count)d în plus" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Liste" #~ msgid "Re_fresh Library" #~ msgstr "Reactualizare c_olecţie" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "E_valuare" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Valoare invalidă" #~ msgid "command|filename" #~ msgstr "comandă|nume" #~ msgid "command|tag" #~ msgstr "comandă|etichetă" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Caută" #~ msgid "%d of %d" #~ msgstr "%d din %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Utilizare: %s %s" #~ msgid "_Download..." #~ msgstr "_Descarcă..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "Staţie _nouă" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Suprascriu <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet este deja pornit." #~ msgid "No song is currently playing." #~ msgstr "Nici o piesă nu este redată curent." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Nu se poate scrie %s. Va fi eliminat din listă." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Editare favorite..." #~ msgid "_New Folder..." #~ msgstr "Director _nou..." #~ msgid "_Add to Playlist" #~ msgstr "_Adaugă în listă" #~ msgid "_Edit Display..." #~ msgstr "_Editare afişare..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d staţie" #~ msgid "_Add a Location..." #~ msgstr "Adăugare _locaţie..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Personalizează coloanele..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "Coloane _pistă" #, fuzzy #~ msgid "People Headers" #~ msgstr "Coloane _persoane" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Coloane _album" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Coloane _dată" #, fuzzy #~ msgid "File Headers" #~ msgstr "Coloane _fişier" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Coloane _producţie" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Etichetă:" #, fuzzy #~ msgid "Warnings" #~ msgstr "E_valuare" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "artist album" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "artişti" #, fuzzy #~ msgid "album (sort)" #~ msgstr "artist album" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "interpreţi" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "interpreţi" #~ msgid "MusicBrainz album artist ID" #~ msgstr "ID artist album MusicBrainz" #, fuzzy #~ msgid "errors" #~ msgstr "interpreţi" #~ msgid "Permanently delete this file?" #~ msgstr "Ştergeţi permanent acest fişier?" #~ msgid "Permanently delete these files?" #~ msgstr "Ştergeţi permanent aceste fişiere?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s şi alte %(count)d în plus..." #~ msgstr[1] "%(title)s şi alte %(count)d în plus..." #~ msgstr[2] "%(title)s şi alte %(count)d în plus..." #, fuzzy #~ msgid "Version:" #~ msgstr "versiune" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "Erori module" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s nu a putut fi adăugat la colecţie.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Nu s-a găsit comanda eject." #~ msgid "Unable to start web browser" #~ msgstr "Nu s-a putut porni navigatorul web" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Nu s-a găsit un navigator web. Setaţi variabila $BROWSER, sau asiguraţi-" #~ "vă că /usr/bin/sensible-browser există." #, fuzzy #~ msgid "Library Error" #~ msgstr "Navigator colecţie" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Copiază către dispozitiv" #~ msgid "translator-credits" #~ msgstr "" #~ "Mugurel Tudor <mugurelu@gnome.ro>\n" #~ "Mişu Moldovan <dumol@gnome.ro>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Alte coloane pentru afişare, separate prin spaţii" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Continuă" #~ msgid "Search your library" #~ msgstr "Căutare în colecţie" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Drepturi de autor © 2004-2006 Joe Wreschnig, Michael Urman şi alţii\n" #~ "\n" #~ "Acesta este free software, vedeţi sursele pentru condiţiile de copiere. " #~ "Nu\n" #~ "se oferă NICI o garanţie, nici măcar pentru o POSIBILĂ COMERCIALIZARE sau " #~ "de\n" #~ "FOLOSIRE PENTRU UN SCOP ANUME.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Mărime totală:" #~ msgid "Quod Libet Plugins" #~ msgstr "Module Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Colorează căutările simple cu albastru, cele avansate cu verde şi cele " #~ "invalide cu roşu" #~ msgid "Separators for splitting tags" #~ msgstr "Caractere pentru separarea etichetelor" #~ msgid "Quod Libet Preferences" #~ msgstr "Preferinţe Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Nu a fost redat _astăzi" #~ msgid "Not Played in a _Week" #~ msgstr "Nu a fost redat de o _săptămână" #~ msgid "Not Played in a _Month" #~ msgstr "Nu a fost redat de o _lună" #~ msgid "B_ottom 40" #~ msgstr "_Ultimele 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "Cele mai rar redate 40 de piese (mai mult de 40 în anumite cazuri)" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Dată" #~ msgid "Add" #~ msgstr "Adaugă" #, fuzzy #~ msgid "Bitrate" #~ msgstr "rată de biţi" #~ msgid "_Stations..." #~ msgstr "_Staţii..." #~ msgid "Unable to save library" #~ msgstr "Nu s-a putut salva colecţia" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Nu s-a putut reda piesa" #~ msgid "Sort by title" #~ msgstr "Sortează după titlu" #~ msgid "Sort by artist" #~ msgstr "Sortează după artist" #~ msgid "Lyrics provided by %s." #~ msgstr "Versuri furnizate de către %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Nu s-au găsit versuri salvate.\n" #~ "\n" #~ "Puteţi apăsa pe butonul „Caută” pentru a căuta versuri pe internet. Le " #~ "puteţi de asemenea introduce dumneavoastră, nu uitaţi să apăsaţi apoi " #~ "„Salvează”." #~ msgid "part" #~ msgstr "parte" #~ msgid "Opening audio device." #~ msgstr "Se deschide dispozitivul audio." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d piese salvate" #~ msgid "MusicBrainz album ID" #~ msgstr "ID album MusicBrainz" #~ msgid "Loaded song library." #~ msgstr "S-a încărcat colecţia de piese." #~ msgid "Unable to open audio device" #~ msgstr "Nu s-a putut deschide dispozitivul audio" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "S-a încercat accesarea driver-elor „autosink” şi „%(sink)s” dar acestea " #~ "nu au putut fi deschise. Setaţi un pipelinel GStreamer schimbând linia\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "în ~/.quodlibet/config ." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Nu s-a găsit elementul GStreamer „filesrc”. Verificaţi instalarea " #~ "GStreamer." �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/ru.po����������������������������������������������������������������������������0000644�0001750�0001750�00001054733�14436352625�013636� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Russian translation of Quod Libet # Copyright (C) 2018 THE quodlibet'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # wvxwxvw <https://github.com/wvxwxvw>, 2018, 2021. # Anton Shestakov <engored@ya.ru>, 2017 # Andrey Fedoseev <andrey.fedoseev@gmail.com>, 2005, 2006. # Sergey Fedoseev <fedoseev.sergey@gmail.com>, 2005, 2006. # Nikolai Prokoschenko <nikolai@prokoschenko.de>, 2005. # Russian L10N Team <debian-l10n-russian@lists.debian.org>, 2005. # # msgid "" msgstr "" "Project-Id-Version: Quod Libet 4.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-05-22 02:52+0000\n" "Last-Translator: Andrei Stepanov <adem4ik@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/ru/>\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.18-dev\n" "X-Poedit-Basepath: .\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Название" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Исполнители" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Дата" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Дата добавления" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Дата оригинала" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Жанр" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "О_ценка" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "Про_слушивания" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Сортировать _по…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Настройки" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Список альбомов" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Список _альбомов" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Все альбомы" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d альбом" msgstr[1] "%d альбома" msgstr[2] "%d альбомов" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Перезагрузить _обложку" msgstr[1] "Перезагрузить _обложки" msgstr[2] "Перезагрузить _обложки" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Треки не в альбоме" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d трек" msgstr[1] "%d трека" msgstr[2] "%d треков" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d диск" msgstr[1] "%d диска" msgstr[2] "%d дисков" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Пример альбома" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Настройка списка альбомов" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Показывать обложки _альбомов" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "При быстром поиске _искать также исполнителей" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Параметры" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Список альбомов" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Закрыть" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Браузер фонотеки" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d трек" msgstr[1] "%d трека" msgstr[2] "%d треков" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Некорректный шаблон" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Коллекция альбомов" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Коллекция альбомов" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Неизвестный %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Несколько значений %s" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "Св_ои" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Добавить" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Удалить" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Тег" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Группировать" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Настройка коллекции альбомов" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Применить" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Отмена" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Сетка обложек" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "Сетка _обложек" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Настройки сетки обложек" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Показывать текст _альбомов" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Показывать пункт \"Все альбомы\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Широкий режим" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Увеличивать обложку" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Файловая система" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Файловая система" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Не удалось копировать треки" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Выбранные файлы не могут быть копированы в другой плейлист или очередь." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Добавить в фонотеку" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Списки станций могут содержать только адреса станций, но не списки станций " "или плейлисты. Не удалось загрузить следующие станции:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Интернет-радио" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Добавить станцию" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Загрузка списка станций" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Новая станция" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Введите адрес интернет-радиостанции:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Электронная" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Хип-хоп / Рэп" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Ретро" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Японская" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Индийская" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Религиозная" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Чарты" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Турецкий" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Регги / Дэнсхолл" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Латинская" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Радио колледжа" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Разговоры / Новости" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Эмбиент" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Джаз" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Классическая" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Поп" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Альтернативная" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Металл" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Кантри" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Новости" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Шлягер" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Фанк" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Инди" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Блюз" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Соул" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Лаунж" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Панк" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Реггетон" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Славянская" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Греческая" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Готика" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Рок" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Загрузить список популярных радиостанций?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Загрузить станции" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Интернет-радио" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Все станции" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Избранное" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Без категории" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Новая станция…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Обновить станции" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Станции не найдены" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "По адресу %s интернет-радиостанций не найдено." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Добавить нечего" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Все перечисленные станции уже в вашей фонотеке." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Добавить в избранное" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Удалить из избранного" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d станция" msgstr[1] "%(count)d станции" msgstr[2] "%(count)d станций" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Панели обзора" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "Панели о_бзора" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "В_ыбрать всё" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Неизвестно" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Все" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Маленький" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Широкий" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Столбчатый" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Шаблон тега с дополнительной разметкой, например: \n" "<tt>композитор</tt> или %s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Настройки панелей обзора" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Расположение столбцов" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Содержимое столбца" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Равная ширина панелей" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Плейлисты" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "П_лейлисты" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Удалить из плейли_ста" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Новый" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Импорт…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Не удалось импортировать плейлист" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet может импортировать плейлисты только в форматах M3U/M3U8 и PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Удалить" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Переименовать" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Не удалось переименовать плейлист" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Импортировать плейлист" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Импорт" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Новый плейлист…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Изменить оценку %d трека?" msgstr[1] "Изменить оценку %d треков?" msgstr[2] "Изменить оценку %d треков?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Подтвердите действие для плейлиста '%s'" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "пусто" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Новый плейлист" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Параметры вида плейлиста" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Показать плейлист" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Удалить плейлист '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Все сведения выбранного плейлиста будут удалены и восстановлению не подлежат." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "Дополнить «{pl_name}» ещё {num} треком?" msgstr[1] "Дополнить «{pl_name}» ещё {num} треками?" msgstr[2] "Дополнить «{pl_name}» ещё {num} треками?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Добавить треки" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Новый плейлист" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Введите название нового плейлиста:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Создать" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Импортирование плейлиста.\n" "\n" "%(current)d/%(total)d треков добавлено." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Новая лента" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Введите путь подкаста / аудио-ленты:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Подкасты" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "По_дкасты" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "Добавить _ленту…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "Об_новить" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Искать источник новых эпизодов" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Пересобрать" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" "Удалить все существующие эпизоды, затем повторно загрузить из источника" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Удалить этот подкаст и его эпизоды" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Не удалось добавить ленту" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Не удалось добавить %s. Возможно, указанный сервер не работает или путь не " "является подкастом / аудио-лентой." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Текущий движок аудио не поддерживает адреса URL. Поддержка подкастов " "отключена." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Ограничить результаты" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "Разрешить _множественные запросы" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Список треков" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Список треков" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Обзор SoundCloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Обзор Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Найти" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Мои треки" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Перейти к %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Подключено" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet теперь подключён, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Выйти из %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Введите код…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Вход в %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Авторизация в SoundCloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Введите код авторизации SoundCloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet не запущен ('--run' для запуска)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "музыкальный проигрыватель и фонотека" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[option]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Вывести текущий трек и выйти" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Сразу начать воспроизведение" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Не показывать окна при запуске" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Перейти к следующему треку" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Перейти к предыдущему треку или в начало текущего" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Перейти к предыдущему треку" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Воспроизвести" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Пауза воспроизведения" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Воспроизведение/пауза" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Остановить воспроизведение" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Увеличить громкость" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Уменьшить громкость" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Увеличить рейтинг проигрываемой песни на одну звезду" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Уменьшить рейтинг проигрываемой песни на одну звезду" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Вывести состояние воспроизведения" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Скрыть главное окно" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Показать главное окно" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Показать/скрыть главное окно" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Фокус на окно Quod Libet" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Убрать текущие фильтры просмотра" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Обновить и пересканировать фонотеку" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Список режимов просмотра" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Показать текущий плейлист" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Показать содержимое очереди" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Показать содержимое очереди" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Отключить расширения" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Запустить Quod Libet, если он не запущен" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Выйти из Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Перемотка по воспроизводимому треку" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ЧЧ:]ММ:СС" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Установить или переключить режим случайного порядка" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Режим случайного порядка" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Вкл./выкл. повтор треков" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Режим типа повтора" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Установить громкость" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Поиск в вашей фонотеке" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "запрос" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Воспроизвести файл" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "имя файла" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Оценить воспроизводимый трек" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Режим текущего просмотра" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Оценить воспроизводимый трек" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Открыть новый просмотр" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Показать/скрыть очередь" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Фильтр по случайному значению" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "тег" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Фильтр по значению тега" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "тег=значение" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Добавить файл или запрос в очередь" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Добавить в очередь разделённые запятыми файлы" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "имя файла" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Отправить полученные имена файлов в стандартный вывод" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Удалить из очереди файл или запрос" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Добавить файл или каталог в фонотеку" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "расположение" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Установить шаблон для команд вида --print-*" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "шаблон" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Недопустимый аргумент для «%s»." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Попробуйте '%s --help'." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Произошла ошибка" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Вы можете игнорировать эту ошибку, но приложение может быть нестабильным до " "перезапуска. Отправка отчёта об ошибке займёт у вас всего несколько секунд, " "но поможет нам исправить это." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Отправить отчет об ошибке" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Перезапуск" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Игнорировать ошибку" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Сведения об ошибке:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Различные сведения об ошибке и вашей системе будут отправлены на стороннюю " "интернет-службу (<a href='https://www.sentry.io'>www.sentry.io</a>). Ниже вы " "можете просмотреть отправляемые данные." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(не обязательно) Краткое описание ситуации до и во время ошибки:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Отправить" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Краткое описание…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Данные для отправки:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "редактор тегов аудио" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "папка" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Редактор аудио тегов" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Адрес источника обложки" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Загружает обложки, привязанные по тегу <tt>artwork_url</tt>. Это работает " "при просмотре в Soundcloud и Подкастах." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Обложки с Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Загружать обложки с Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Обложки с Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Загружать обложки с Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Обложки с MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Загружать обложки с MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Преобразовать кодировки" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Исправление ошибочных кодировок значений в тегах, в редакторе тегов." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Изменить кодировку…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kanji Kana Simple Inverter" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Преобразует кана/кандзи в ромадзи перед переименованием." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Латинизировать _японский текст" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Не удалось найти 'Kanji Kana Simple Inverter' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Замена регулярных выражений" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Разрешает замены регулярных выражений (<tt>s/from/to/</tt>) при получении " "тегов или переименовании файлов." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Регистр заголовков" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" "Все слова с заглавных для английских значений тегов. Или вообще для всех " "значений." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "'_Все с заглавных'" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Разрешить _ALL-CAPS в тегах (все заглавными)" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Соблюдать правила английского языка" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Следовать общим правилам изменения регистра букв, принятым в английском " "языке, например, «Dark Night of the Soul»" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Расширенные настройки" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Настройка дополнительных параметров." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Я знаю, что делаю" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Анимация смены трека" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Показывать анимацию при смене трека." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Положение:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Общий размер:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Вид" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Шрифт:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "По левому краю" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "По центру" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "По правому краю" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Выравнивание:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Текст" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Текст:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "За_ливка:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Цвета" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "Т_ени" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Контуры" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "З_акруглённые углы" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "За_держка:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Эффекты" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Изменить шаблон…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Предпросмотр" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Сведения о приложении" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Различные сведения о приложении и его окружении." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Поддерживаемые форматы" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Каталог конфигурации" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Каталог кэша" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Обработчик аудио" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "После каждого воспроизведения (по умолчанию)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Каждый раз при воспроизведении трека плагин будет записывать теги в файл. За " "исключением пропущенных треков. Счётчики пропусков не хранятся в файлах, это " "позволяет избежать ненужных операций записи." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "После каждого воспроизведения или пропуска" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Каждый раз, при воспроизведении и пропуске трека, плагин будет записывать " "теги в файл. Может быть полезно, если вы хотите быть уверенными, что оценки " "песен, которые вам не нравятся и поэтому пропущены, записываются в файлы." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Один раз, когда альбом будет полностью оценён" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Если песня была воспроизведена или пропущена, альбом этой песни будет " "проверен. И если каждая песня в альбоме была оценена и хотя бы одна из них " "не имеет рейтингов или количества воспроизведения, хранящихся в её файле, " "плагин запишет теги в файлы песен.\n" "\n" "Используйте это, чтобы избежать постоянных обновлений файлов, но имейте в " "виду, что после обновления альбома вам придётся использовать плагин " "«Обновить теги в файлах» всякий раз, когда вы хотите, чтобы изменённые " "рейтинги и счётчики воспроизведения были записаны в файлы." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Когда плагин записывает теги альбома, он сначала устанавливает счётчик " "воспроизведений песен равным нулю или единице.\n" "Иногда вы уже знаете, что вам не нравится песня, поэтому установка единицы " "при сохранении может быть полезна позже, при поиске альбомов, которые вы " "полностью прослушали (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Не удалось записать '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Автообновление тегов в файлов" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Если песни были воспроизведены, обновить теги в их файлах. Это гарантирует, " "что счётчики воспроизведений и оценки будут в актуальном состоянии." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Для работы этого плагина необходим и был включен следующий параметр:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Сохранять оценки и _счётчики воспроизведений в тегах" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Настройки обновлены" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Ошибка в %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Убедиться, что счётчики воспроизведений больше нуля, при сохранении" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Стратегия обновления:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Параметры" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Автоскрытие дисков" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Автоматически показывает и прячет диски при их добавлении или извлечении." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Автоматическая оценка" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Оценивает песни автоматически, когда они воспроизводятся или пропускаются. " "Использует ускоренный алгоритм из vux (Vacillating Utilitarian eXtemporizer) " "от Брайана Нельсона." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Указанная база данных Banshee искажена или отсутствует" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Ошибка импорта" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Успешный импорт рейтингов и статистики для %d песни" msgstr[1] "Успешный импорт рейтингов и статистики для %d песен" msgstr[2] "Успешный импорт рейтингов и статистики для %d песен" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Импорт из Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Импортирует рейтинги и статистику песен из Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "Путь _базы данных:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Импортировать" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Будильник" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Включает музыку в заданное время." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Колыбельная" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Постепенно убавляет громкость и приостанавливает воспроизведение." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Состояние Discord" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Состояние Discord" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Обновляет ваш статус Discord в соответствии с воспроизводимым треком." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Пауза" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Строка состояния 1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Строка состояния 2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Плоский" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Концерт" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Низкие и высокие частоты" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Клуб" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Большой зал" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Вечеринка" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Мягкий" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Низкие частоты" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Регги" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Наушники" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Софт-рок" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Высокие частоты" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Танцевальная" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Техно" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ска" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Ноутбук" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Эквалайзер" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Управление тембром музыки с помощью эквалайзера.\n" "Щёлкните или используйте клавиши для настройки уровней (ПКМ — сброс)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Текущий аудиовывод не поддерживает коррекцию аудиосигнала." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f кГц" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Гц" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f дБ" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Стандартные предустановки" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Выбрать…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Сброс EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Свои предустановки" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Удалить выбранное" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Имя предустановки для сохранения:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Сохранить" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "в сети" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "не в сети" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "чат" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "отошёл" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "недоступен" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "невидимый" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Статусное сообщение Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Обновляет ваш статус Gajim в соответствии с прослушиваемым треком." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "пауза" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Пример:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Список учётных записей, разделённых пробелами, для изменения статуса. Если " "не указано, будет изменён статус всех учётных записей." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Аккаунты:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Добавлять '[paused]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "Если отмечено, '[paused]' в статус будет добавлено сообщение о паузе" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Статусы, для которых будет изменятся сообщение" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Пауза при отключении наушников" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "Пауза при отключении наушников и снятие с неё при их включении." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Запрет хранителя экрана / ждущего режима" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "На рабочем столе GNOME при воспроизведении трека будут запрещены как " "хранитель экрана, так и ждущий режим компьютера." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Играет музыка" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Режим:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Запретить хранитель экрана" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Запретить приостановку" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Журнал интернет-радио" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "Запоминает и отображает 10 последних радиостанций в контекстном меню." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Выводит файл Jabber User Tunes в %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Смена языка" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Изменить язык интерфейса." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "По умолчанию" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Для вступления изменений в силу требуется перезапуск" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Медиасервер UPnP AV" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Предоставляет все альбомы на Rygel UPnP Media Server, черезMediaServer2 D-" "Bus интерфейс." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "Убедитесь, что в конфигурационном файле rygel (~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Сервер MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Управление Quod Libet удалённо с использованием клиента MPD. Потоковое " "вещание, плейлист и управление фонотекой не поддерживается." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Порт:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_Локальный IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "Па_роль:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Соединение" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Проверенные клиенты" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Поддержка MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Предоставляет управление Quod Libet посредством спецификации интерфейса D-" "Bus <a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a>, что " "позволяет использовать различные интеграции с настольными компьютерами Linux " "(например, мультимедийные клавиши)." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Скрывать главное окно при закрытии" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Принимает QL-шаблоны, например %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Публикатор MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Публикует статусные сообщения в темы MQTT." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Имя хоста / IP брокера" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "По умолчанию localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Порт брокера" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "По умолчанию 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Имя пользователя брокера" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Пароль брокера" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Тема" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Шаблоны воспроизведения" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Текст статуса при запуске трека." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Сохранённые шаблоны" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Текст при паузе трека." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Текст когда нет трека" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Обычный текст, когда нет текущего трека" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Конфигурация MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Текст статуса" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Подключён к брокеру на %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Не удалось подключится к %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Ошибка соединения" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "Синхронизация MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Синхронизирует рейтинг песни с MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Имя пользова_теля:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Пароль:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Аккаунт" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Текст уведомления" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "З_аголовок:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Сбросить на шаблон по умолчанию" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Тело:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Показать уведомление" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Показывать уведомления" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Только при смене трека <i>_вручную</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Только при <i>авто_матической</i> смене трека" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "При <i>_любой</i> смене трека" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Только когда _фокус не в главном окне" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Показать кнопку \"_Следующий\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Ошибка соединения" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Не удалось подключиться к системе уведомлений." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Системные уведомления" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Показывать уведомление при смене трека." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Следующий" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Уведомления о закладках" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Использует уведомления для отображения закладок/комментариев в режиме " "реального времени. Хорошо работает в браузере Soundcloud." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Необходимо настроить расширение QLScrobbler в окне расширений. Иначе " "скробблинг треков не будет работать." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Не удалось связаться со службой «%s»." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Авторизация не удалась: неверно указан URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Авторизация не удалась: неверное имя пользователя '%s' или пароль." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Клиент заблокирован. Свяжитесь с автором." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Неправильное системное время.Передачи могут завершаться ошибкой, пока не " "будет исправлено." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Передача аудиоскробблера" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Клиент скробблинга аудио на Last.fm, Libre.fm и другие подобные службы." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Авторизация прошла успешно." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Служба:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Другой…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Проверка учетной записи" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Шаблон _Исполнителя:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Шаблон _Имени файла:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "И_сключать:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Шаблон форматирования имени исполнителя для отправки. Оставьте пустым для " "значения по умолчанию." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Шаблон форматирования заголовка для отправки. Оставьте пустым длязначения по " "умолчанию." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Треки, соответствующие этому фильтру, не будут отправлены" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Автономный режим (ничего не отправлять)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Отправка" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Приглушение рекламы в радио" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Приглушает звук при воспроизведении рекламы на радио.\n" "Станция: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Играть случайный альбом" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Запускает случайный альбом, когда плейлист подходит к концу. Требуется, " "чтобы ваш активный браузер поддерживал фильтрацию по альбому." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Выше рейтинг" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Чаще воспроизводятся" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Чаще пропускаются" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Недавно проигрывались" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Недавно запускались" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Недавно добавлены" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Более длинные альбомы" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "секунд до начала следующего альбома" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Вес" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Играть некоторые альбомы чаще, чем другие" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "избегать" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "предпочитать" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Случайный альбом" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Ожидание до начала %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Оценки и статистика для %d треков успешно импортированы" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Импорт из Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Импорт оценок и статистики из Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Пауза при хранителе экрана" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Приостанавливает воспроизведение, пока хранитель экрана GNOME активен." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Поставщик поиска GNOME Shell для Quod Libet не установлен." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "Скопировали ли вы файл ini в %s (или похожее)?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Поставщик поиска GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Позволяет GNOME Shell искать в фонотеке." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Альтернативная панель поиска" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Альтернативная панель перемотки, всегда видна и охватывает всю ширину окна." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Закладки точки поиска" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Сохранять точки поиска A и/или B для треков. Переход к время A и остановка " "после времени B, при воспроизведении трека.\n" "\n" "Обратите внимание, что изменение имен нижеуказанных точек не обновляет " "фактические имена закладок, меняются только имена закладок, которые ищет " "плагин при решении о поиске." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Имя закладки для точки А" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Имя закладки старта трека, если существует, плеер переходит к этой точкедля " "начала воспроизведения" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Имя закладки для точки B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Имя закладки конца трека, если существует, плеер, при достижении этой точки, " "переходит к следующему треку." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Синхронизация Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Делает Logitech Squeezebox зеркалом Quod Libet, при условии, что оба читают " "идентичные фонотеки." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Совместно использует конфигурацию с <a href=\"%(plugin_link)s\">плагином " "Экспорт в Squeezebox</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Ошибка поиска сервера Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Ошибка поиска %s. Проверьте настройки" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Остановить при паузе" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Этот плагин изменяет паузу на остановку/воспроизведение/перемотку.\n" "\n" "Полезно, если QuodLibet не может переключить аудиоустройства, когда в " "систему добавляется новое (динамик Bluetooth, USB-ЦАП и прочее).\n" "\n" "Гарантирует, что положение в текущем источнике сохранится до тех пор, пока " "отключён параметр «Только доступные для перемотки источники». В ином случае " "воспроизведение будет остановлено и должно быть перезапущено с самого начала." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Только доступные для перемотки источники" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Параметры плагина" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Ожидание копирования" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Ожидание удаления" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "удалить" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Пропустить" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "КОПИЯ" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Синхронизация" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Удаление" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Успешно" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "СБОЙ" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Пропущен существующий файл" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Невозможно задать имя файла песни." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Синхронизация с устройством" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Синхронизирует все песни из выбранных сохранённых поисков с указанной папкой." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Синхронизирует следующие сохранённые поиски:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Абсолютный путь к вашему месту экспорта" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Все ранее существовавшие файлы в папке назначения, которых нет в сохранённых " "результатах поиска, будут удалены." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "Для устройств, смонтированных через MTP, экспортируйте в локальную папку " "назначения, а затем перенесите на своё устройство с помощью rsync. Или, при " "синхронизации большого количества файлов с устройством Android, используйте " "adb-sync, что намного быстрее." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Папка назначения:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Шаблон пути к файлам" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Изменить сохранённые шаблоны…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Структура имён экспортируемых файлов на основе их тегов" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Шаблон экспорта:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Остановить предпросмотр" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Состояние" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Источник" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Путь экспорта" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Обнаружены повторяющиеся пути экспорта! Приведённые выше пути экспорта можно " "исправить перед началом синхронизации." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Существующие файлы в пути назначения будут удалены (за исключением файлов с " "именем «cover.jpg»)!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Начать синхронизацию" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Остановить синхронизацию" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "Пока нет сохранённых поисков, создайте их и возвращайтесь!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Выберите путь" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Путь экспорта для файла [{filename}] изменён с [{old_path}] на [{new_path}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Запуск предпросмотра синхронизации" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Предпросмотр синхронизации в процессе." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Предпросмотр синхронизации завершён" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Остановка предпросмотра синхронизации" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Предпросмотр синхронизации был остановлен." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Предпросмотр синхронизации завершён." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Предпросмотр синхронизации остановлен" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Было выбрано другое расширение — остановите предпросмотр" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Синхронизация будет:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "попытка записи {count} файла" msgstr[1] "попытка записи {count} файлов" msgstr[2] "попытка записи {count} файлов" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "пропуск {count} повторяющегося файла" msgstr[1] "пропуск {count} повторяющихся файлов" msgstr[2] "пропуск {count} повторяющихся файлов" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "удалить {count} файл" msgstr[1] "удалить {count} файла" msgstr[2] "удалить {count} файлов" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Путь назначения не указан" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" "Пожалуйста, укажите каталог, в который должны быть экспортированы песни." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Шаблон экспорта не указан" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Пожалуйста, укажите шаблон экспорта для имён экспортируемых песен." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Путь экспорта не является абсолютным" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Шаблон \n" " \n" "{} \n" "\n" "содержит «/», но начинается не с корневого каталога. Пожалуйста, укажите " "абсолютный путь назначения, убедившись, что он начинается с «/» или «~/»." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Сохранённые поиски не выбраны" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Пожалуйста, выберите хотя бы один сохранённый поиск." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Нет песен в выбранных сохранённых поисках" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Все выбранные сохранённые поиски пусты." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Найдено {} песен для синхронизации" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Несоответствие между путём назначения и шаблоном экспорта" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Шаблон экспорта начинается с пути отличного от пути назначения. Пожалуйста, " "исправьте шаблон.\n" "\n" "Ошибка:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Не удаётся синхронизировать" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Не удаётся запустить синхронизацию при сортировке по <b>Статусу</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Запуск синхронизации песен" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Выполняется синхронизация." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Синхронизации песен завершена" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Остановка синхронизации песен" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Синхронизация остановлена." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Синхронизация завершена." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Синхронизация песен остановлена" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Было выбрано другое расширение — остановите синхронизацию" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Удаление «{}»" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Синхронизация имеет:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "записан {count}/{total} файл" msgstr[1] "записаны {count}/{total} файла" msgstr[2] "записано {count}/{total} файлов" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(пропущен {count} существующий файл)" msgstr[1] "(пропущены {count} существующих файла)" msgstr[2] "(пропущено {count} существующих файлов)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "пропущен {count}/{total} повторяющийся файл" msgstr[1] "пропущено {count}/{total} повторяющихся файла" msgstr[2] "пропущено {count}/{total} повторяющихся файлов" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "удалён {count}/{total} файл" msgstr[1] "удалено {count}/{total} файла" msgstr[2] "удалено {count}/{total} файлов" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "не удалось синхронизировать {count} файл" msgstr[1] "не удалось синхронизировать {count} файла" msgstr[2] "не удалось синхронизировать {count} файлов" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "пропущен {count} файл, синхронизированный ранее" msgstr[1] "пропущены {count} файла, синхронизированные ранее" msgstr[2] "пропущено {count} файлов, синхронизированных ранее" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Синхронизованные тексты песен" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Синхронно показывает текст песни из файла .lrc с тем же именем (или " "похожим), что и трек ." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Текст:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Фон:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Шрифт" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Размер (пикс):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Статус Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Обновляет во всех основанных на Telepathy IM аккаунтах (Empathy и т." "д.)статусы на основе текущего трека." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Воспроизведение:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Текст статуса при запуске трека. Принимает QL шаблоны, например %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Пауза:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Текст статуса при паузе песни. Принимает QL шаблоны, например %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Обычный текст статуса, когда нет текущего трека" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Нет трека:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Шаблоны состояний" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Тема оформления" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Смена используемой темы GTK+." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Тема:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Тема по умолчанию" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Предпочитать тёмную версию темы" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Оценка Thumb" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Добавляет систему оценки с помощью большого пальца вверх или вниз, которая " "преобразуется в значение рейтинга. Полезно для ведения подсчёта голосов и " "сортировки по <b><tt>~#score</tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Панель меню по Alt" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Переключение отображения строки меню клавишей Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Не воспроизводится" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Значок в трее" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Управление Quod Libet из трея." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Показать %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Играть" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Пауза" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Предыдущий" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Следующий" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Случайно" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Повторять" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Стоп после _трека" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "В новом о_кне" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Править т_еги" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Информация" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Плейли_сты" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Выход" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Поведение" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Прокрутка меняет громкость" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Прокрутка меняет трек" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Колесо мыши" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Показывать подсказки" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Текст песни" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Отображение тегов или файлов лирики в боковой панели." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Текст трека не найден\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Нет активного трека" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Визуализации" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Запуск внешних визуализаций." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Не удалось запустить визуализацию, используя '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Ошибка" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Исполняемый файл визуализатора:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Обновить" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Панель перемотки Waveform" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ Панель поиска в виде формы волны текущей песни." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Цвет пройденного :" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Цвет наведения:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Цвет оставшегося:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Показать текущую позицию" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Показать метки времени" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Шаг при прокрутке (миллисекунды):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Хранитель изображений" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Сохраняет обложку текущего трека в файл." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Файл:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Порог:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Порог до активации фильтра" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Коэффициент:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Коэффициент компрессии" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Аудиокомпрессор" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Изменяет амплитуду сигнала, превышающего определённое значение, с указанным " "коэффициентом." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Предустановка:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Предустановка фильтра" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Частоты среза:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Частота среза низких частот" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Уровень _ленты:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Уровень ленты" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "По умолчанию" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Ближайшее к виртуальному размещению динамиков (30°, 3 метра)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Чу Мой" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Близко к кроссфидеру Чу Мой (популярно)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Ян Мейер" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Близко к усилителям CORDA Яна Мейера (небольшое отличие)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Свое" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Свои настройки" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Смешение каналов" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Смешивает левый и правый каналы имитируя настройку динамика при " "использовании наушников или для настройки ранних стерео записей." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Частота фильтра:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Полоса частот фильтра" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "_Диапазон фильтра:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Диапазон частот фильтра" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Уровень:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Интенсивность эффекта" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Караоке" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Убирает вокал из аудио." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Сведение в моно" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Микширует аудио каналы в моно." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Коэффициент:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Темп:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Высота:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Высота и скорость звука" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Управление параметрами аудиопотока." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Экспорт плейлиста в папку" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Экспорт" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Папка назначения:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Шаблон имени файла:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Экспорт плейлиста путём копирования файлов в папку." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Не удаётся экспортировать плейлист" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Убедитесь, что у вас есть доступ на запись к месту назначения." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "_Шаблон имени файла:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Хорошо" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Введите новое имя плейлиста, \n" "или выберите существующий плейлист Sonos для перезаписи" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Экспорт в плейлист Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "Экспорт плейлиста в Sonos путём сопоставления треков." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Ошибка обнаружения устройства Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Ошибка поиска Sonos. Пожалуйста, проверьте настройки" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Не удалось удалить существующий плейлист Sonos %s:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Экспорт в плейлист %(playlist)r (%(total)d дорожек)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Экспорт на Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Динамически экспортирует плейлист в список воспроизведения Logitech " "Squeezebox при условии, что оба имеют общую структуру каталогов." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Совместно использует конфигурацию с <a href=\"%(plugin_link)s\">расширением " "Squeezebox Sync</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Экспорт плейлиста на Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Имя плейлиста (перезапишет существующий)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Экспорт в плейлист Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Удаление дубликатов" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Удаляет дубликаты записей из плейлиста." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Удалить %d повтор?" msgstr[1] "Удалить %d повтора?" msgstr[2] "Удалить %d повторов?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Из плейлиста '%s' будут удалены все дубли треков." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Перемешать плейлист" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Переставляет треки в плейлисте в случайном порядке." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Следовать за курсором" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "Воспроизведение выбранных или, если нет выбора, следующего трека." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Следовать за курсором" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "Следов_ать за курсором" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Уравнитель прослушиваний" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Перемешать, предпочитая треки с меньшим числом прослушиваний." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Меньше воспроизведений" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Пре_дпочитать наименее прослушиваемые" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Только очередь" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Ограничивает воспроизведение песен очередью.\n" "\n" "Выберите этот порядок проигрывания в главном окне, затем двойной щелчок по " "любой песне поставит её в очередь вместо воспроизведения." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Только очередь" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "Только о_чередь" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Автозапускать воспроизведение песен по двойному щелчку" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Реверс" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" "Добавляет режим случайного воспроизведения, который меняет порядок " "воспроизведения песен." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Ревер_с" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Перемешать по группировке" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Добавляет режим перемешивания, в котором песни группируются общим тегом — " "аналогично перемешиванию альбомов.\n" "\n" "Полезно для перетасовки классических пьес, состоящих из нескольких частей, " "чтобы убедиться, что все части воспроизводятся по порядку, прежде чем " "переходить к следующей пьесе." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Перемешивание по группировке" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "_Перемешать по группировке" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Ожидание запуска новой группы…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Тег группы:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Тег для группировки треков" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Тег фильтра:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Группировка применяется только в случае, если определён тег фильтра.\n" "Трек с неопределённым тегом фильтра будет рассматриваться как группа\n" "состоящая только из себя. Обычно тег фильтра должен совпадать или\n" "частично совпадать с тегом группы." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Задержка:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Задержка в секундах перед началом следующей группы" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Сброс к значениям по умолчанию" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Пропуск непонравившихся треков" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Добавляет режим воспроизведения (в случайном порядке), который " "воспроизводится по порядку, но пропускает дорожки с рейтингом ниже (или " "равным) заданному порогу." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Пропустить непонравившиеся треки" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Пропустить не понра_вившиеся треки" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Повтор каждого трека" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Добавляет режим воспроизведения (в случайном порядке), в котором треки " "воспроизводятся по порядку, но каждый трек повторяется заданное количество " "раз." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Повторять каждый трек" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "Повторять _каждый трек" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Сколько раз воспроизводить каждый трек:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Условный запрос" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Позволяет запросу получать результаты на основе условия поиска." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: condition-query, then-query, else-query)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Отсутствующий запрос" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Соответствует трекам без указанного тега." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Включать пустые теги" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Запрос Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Использовать регулярные выражения Python в запросах." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: expression)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Переменная <tt>s</tt> (или <tt>a</tt>) соответствует песне/альбому.\n" "\n" "<tt>_ts</tt> — метка времени (действительное число) в начале запроса.\n" "\n" "Также доступны модули <tt>time</tt> и <tt>random</tt>, а также класс " "<tt>Random</tt> (==<tt>random.Random</tt>)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Учитывать сохранённый поиск" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" "💾 Включить результаты сохранённого поиска в виде части другого запроса." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: search-name)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Уникальный запрос" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Фильтрация результатов поиска по уникальным тегам." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: tag)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox ОК. Используя только плеер (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Не удалось подключиться к %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Имя машины:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Порт:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Имя пользователя:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Пароль:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Каталог фонотеки, к которому подключается сервер" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Путь к фонотеке:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Проверка настроек" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Сервер Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Отладка" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Сервер Squeezebox на {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "неопознанный сервер Squeezebox" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "неопознанный Squeezebox плеер: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Выберите Squeezebox плеер" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Найден сервер Squeezebox.\n" "Пожалуйста, выберите проигрыватель" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "_Масштаб по размеру окна" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Смотрите конфигурационную запись '[plugins] cover_filenames' для имени файла " "изображения" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Программа:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "Из_менить изображение после сохранения" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Имя файла:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Не удалось сохранить" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Не удалось сохранить '%s'." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Ошибка HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Загрузка обложек альбомов" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "с %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Разрешение: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Размер: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Лимит для каждого поиска" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Найти" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Поиск…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Готово" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Загрузить обложку альбома" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Загрузка обложек альбомов с различных веб-сайтов." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Источники" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 в ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Преобразует теги APEv2 в теги ID3v2. Это удаляет теги APEv2 после " "преобразования." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Переход к закладке" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Менеджер закладок для выделенных файлов." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Изменить закладки…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Нет закладок" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Поиск на MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Поиск альбома на MusicBrainz и запись найденных тегов." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Записывать год только для тега \"date\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Записывать \"_albumartist\" при необходимости" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Записывать теги сортировки для имён исполнителей" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Записывать _стандартные теги MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Записывать тег «labelid»" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Имя файла" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Диск" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Трек" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Название" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Исполнитель" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Поиск на MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Запрос:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Найти" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Результаты <i>(порядок можно изменить перетаскиванием)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Введите запрос." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Обнаружена ошибка. Повторите попытку." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Загрузка результата…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Ничего не найдено." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Консоль Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Интерактивная консоль Python. Открывает новое окно." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} для {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Боковая панель консоли Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Интерактивная панель консоли Python, которая следует за выбранными песнями в " "главном окне." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "По умолчанию доступны следующие объекты:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Текущий рабочий каталог:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Заполнение" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Загрузить обложку" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Загружает высококачественные обложки альбомов с помощью плагинов обложек " "Quad Libet." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Обычные" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Большие" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Загрузка обложек" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Загрузка %(source)s – %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Нет результатов для следующих альбомов:\n" "%(albums)s.\n" "\n" "Используемые поставщики:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Обложки не найдены" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} пикс" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Размер предпросмотра" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Сохранить расположение" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Если это не JPEG, конвертирует изображение в высококачественный JPEG того же " "размера" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Сохранить в JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Команда" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "название" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Название этой команды" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "команда" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Синтаксис команды оболочки для запуска" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "параметр" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Если указано, параметр вхождения которого в команду будут заменены " "пользовательским значением, например, с помощью параметра 'PARAM' все " "экземпляры '{PARAM}' в вашей команде будут иметь значение, запрошенное при " "запуске" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL шаблон, например <~filename>, используется для вычисления значения " "команды. Для плейлистов это также поддерживает виртуальные теги " "<~playlistname> и <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "уникальный" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Если установлено, то удалит дубли вычисленных значений шаблона" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "max args" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Наибольшее количество аргументов, которое будет передано приложению за один " "раз (аналогично xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "реверс" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Если указано, список аргументов будет инвертирован" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Введите значение" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Значение %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Пользовательские команды" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Выполнение пользовательских команд над треками (в пакетном режиме, если " "требуется), используя любые теги в качестве аргументов." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Изменить команды" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Не удалось выполнить пользовательскую команду %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d группа повторов" msgstr[1] "%d группы повторов" msgstr[2] "%d групп повторов" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Свернуть/развернуть всё" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Выражение для поиска дублей: '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Поиск дублей" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Поиск и просмотр треков с похожими тегами." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Поддерживает выражения с тегами, например, <tt>~artist~title</tt> или " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Группировать повторы по:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Выражение для поиска" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Удалить _пробелы" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Удалить _диакритические знаки" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Удалить п_унктуацию" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Без учёта рег_истра" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Настройки сравнения" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Править счётчик воспроизведений" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Изменить значения <tt>~#playcount</tt> и <tt>~#skipcount</tt> для треков \n" "\n" "Когда выбрано несколько треков, счётчики будут увеличены, а не заданы.\n" "\n" "Если для трека значение <tt>~#playcount</tt> установлено на 0, то записи " "<tt>~#lastplayed</tt> и <tt>~#laststarted</tt> будут очищены. Однако, если " "для трека с 0 прослушиваний установлено положительное число, количество " "воспроизведений не создаётся." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Счётчик воспроизведений" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Счётчик пропусков" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Выбрано несколько файлов." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Счётчики будут приращены." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Править вложенные изображения" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Добавляет, удаляет или заменяет вложенные изображения." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Вложить" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Выберите изображение для вложения в %d трек" msgstr[1] "Выберите изображение для вложения в %d трека" msgstr[2] "Выберите изображение для вложения в %d треков" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Удалить все" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Внедрить текущее" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Выберите изображение…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Установка точной оценки" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Позволяет дать точную оценку треку в числах." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Введите оценку в виде числа от 0.0 до 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Фильтр по любому тегу" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Создание поисковых запросов по тегам выбранных треков." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Фильтр по папке" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Фильтр по папке в новом окне." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Поиск акустических отпечатков" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Поиск информации о треках по их акустическим отпечаткам." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Отправлять акустические отпечатки" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Создание акустических отпечатков треков с помощью chromaprint и отправка их " "на acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Требуется ключ API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Вы должны указать acoustid.org API-ключ в настройках плагина, а потом уже " "сможете отправлять отпечатки." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Запросить ключ" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Ключ API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Веб-служба AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "В очереди" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Анализ" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Поиск" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Записать" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Выпуск" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Записать теги MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Группировать по папке" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Режим альбома" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Создание тегов, связанных с альбомами, для попытки уменьшения количества " "версий альбома" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Создание отпечатков:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Подробности" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Отправить" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "У треков должен быть либо тег <i><b>musicbrainz_trackid</b></i>, либо теги " "<i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i>." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Отпечатки:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Треки с MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Треки с заполненными тегами:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Треков для отправки:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Готово. %(to-send)d/%(all)d треков для отправки." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Отправка отпечатков:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Отправка…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Обновить теги в файлах" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Обновление изменённых тегов в файлах. Это обеспечит актуализацию счётчика " "воспроизведений и оценок." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Экспорт списка в HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Экспорт выбранного списка треков в HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Отправить на iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Загружает треки на устройства iRiver iFP." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Устройство iFP не найдено" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Не удаётся связаться с устройством iFP. Убедитесь, что устройство включено и " "подключено, и у вас установлен ifp-line (http://ifp-driver.sf.net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Загрузка %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "Не удаётся отправить %s. Возможно устройство недоступно или отключено." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Ошибка загрузки" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Экспорт данных пользователя" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Экспорт тегов" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Экспорт тегов и данных пользователя" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Экспорт имён файлов без расширения и данных пользователя" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Экспорт имён файлов без расширения и тегов" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Экспорт имён файлов без расширения, тегов и данных пользователя" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Импорт/экспорт" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Импортирует и экспортирует теги и пользовательские данные треков." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Прочая информация" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Термин «пользовательские данные трека» включает списки воспроизведения, в " "которых находятся выбранные треки, и следующие метаданные:\n" "\n" "%s\n" "\n" "Имейте в виду, что все, что вы выбрали для экспорта, будет импортировано. " "Если вы экспортировали имена файлов без расширения, то при импорте выбранные " "файлы будут переименованы.\n" "\n" "После экспорта альбома вы можете импортировать данные в другую версию " "альбома. Порядок и число дорожек могут быть разными. Плагин сопоставляет " "экспортированные данные с новыми треками, даже если названия треков немного " "отличаются. Автоматическое сопоставление не всегда верно, поэтому следующие " "значения сходства лучше не занижать." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Взаимодействие с пользователем при импорте" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Требуется подтверждение, если количество треков отличается" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Требуется подтверждение, если количество альбомов отличается" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Процент, ниже которого пользователю придётся вручную проверять и при " "необходимости изменять, сопоставление треков." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Сходство треков:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Сходство альбомов:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Экспорт файлов" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Записать красивый и понятный JSON (медленно)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Удалить файлы экспорта после их импорта" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Импортировать" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Открыть каталог экспорта" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Диски" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Треки" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Исполнитель(-и)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Конец пути" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Сопоставление альбомов" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Продолжить" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Нечего импортировать" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Вы должны экспортировать что-то, прежде чем импортировать." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Индекс был повреждён." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "Не удалось разобрать JSON в %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Не удалось прочесть %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Имя файла" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Сопоставлять треки" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Обновление списка чартов." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Не требует обновления." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Загрузка чарта за неделю от %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Синхронизация завершена." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Ошибка синхронизации (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Синхронизация с Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Дополняет статистику фонотеки данными из профиля на Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Имя пользователя:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Создать теги сортировки" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Плохо конвертирует имена альбомов и исполнителей для сортировки по имени." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Экспорт в файл плейлиста M3U/PLS" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Экспорт треков в файл плейлиста M3U или PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Относительные пути" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Абсолютные пути" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "Не удалось записать в %s." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Пересканировать треки" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Проверка изменений файлов и перезагрузка / удаление треков, если это " "необходимо." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Пересканировать треки" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Анализатор ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Трек" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Прогресс" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Усиление" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Пик" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Обновляется %(to-process)s альбом (из %(all)s)" msgstr[1] "Обновляется %(to-process)s альбома (из %(all)s)" msgstr[2] "Обновляется %(to-process)s альбомов (из %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Выравнивание громкости (Replay Gain)" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Анализирует и обновляет информацию <a href=\"%(rg_link)s\">ReplayGain</a> с " "помощью GStreamer, группируя результаты по альбомам." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://ru.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "всегда" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "Если <b>какие-либо</b> теги ReplayGain отсутствуют" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "Если <b>альбомные</b> теги ReplayGain отсутствуют" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "О_брабатывать альбомы:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Существующие теги" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Разделить теги" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Отделить номер диска от альбома, а версию от названия." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Разделить альбом" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Отделить номер диска." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "н/д" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "Ударов в минуту:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Сброс" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Такт" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Получить Tap BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Получить значение Tap BPM (ударов в минуту) для выбранного трека." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Поиск в интернете" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Поиск на выбранном вами сайте с использованием любых тегов песен.\n" "Поддерживает шаблоны, например, %(pattern)s ." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Шаблоны URL для поиска" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Изменить поисковые шаблоны" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Настройка поиска…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Поиск тегов в Википедии" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Открывает окно браузера со статьей Википедии о соответствующем теге " "выбранного трека." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Искать на %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Редактировать теги" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Поиск не удался" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Тег \"%s\" отсутствует." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Фонотека" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Проверка точек монтирования" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Сканируется фонотека" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Сканируется %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Не удалось сохранить" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Перемещение файлов фонотеки" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Удаление файлов фонотеки" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Добавление наблюдения за %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "В унаследованном плейлисте %(filename)r (размером %(size).1f КБ) не найдены " "песни из фонотеки." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "Вы меняли корневой каталог(и) фонотеки, но не этот плейлист?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d плейлист не удалось конвертировать" msgstr[1] "%d плейлиста не удалось конвертировать" msgstr[2] "%d плейлистов не удалось конвертировать" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Музыкальный плеер и менеджер фонотеки" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Не удалось загрузить файл: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Список тегов" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Показать сокращенный вывод" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Столбцы и порядок отображения в сокращённом режиме (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Показывать программные теги" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Недостаточно аргументов" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Слишком много аргументов" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Описание" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Значение" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Список всех общих тегов" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Копировать теги из одного файла в другой" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Показать изменения, но не применять их" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Пропускать теги, которые нельзя записать" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Не удаётся копировать тег {tagname} в файл: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Править теги в текстовом редакторе" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Изменение прервано" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Не удалось запустить текстовый редактор '%(editor-name)s'." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Изменения не найдены" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Установка тега и удаление существующих значений" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Не удалось установить %(tag)r для %(format)s файла %(file)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Удалить теги" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Значение - регулярное выражение" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Удалить все теги" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Не удается объединить '--all' с '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Не удается удалить {tagname} из {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Удалить значение тега" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Добавить значение тега" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Не удалось установить %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Вывести информацию о файле" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Установить полученное изображение в качестве основного вложенного " "изображения и удалить все другие вложенные изображения" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Не удалось загрузить файл: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Изменение изображения %(file_name)s (%(file_format)s) не поддерживается" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Удалить все вложенные изображения" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Извлечь вложенные изображения в %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Путь к месту сохранения изображений (по умолчанию — рабочий каталог)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Переименование файлов на основе тегов" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Заполнение тегов на основе пути к файлу" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Файл" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Заполнить номер трека для всех файлов" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Выводить теги на основе указанного шаблона" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Вывести справку" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' недопустимое имя столбца (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Неизвестно" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "По порядку" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_По порядку" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Случайно" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Случайно" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "По рейтингу" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "П_редпочитать более оценённые" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Повторить этот" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Повторить этот тр_ек" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Повторить все" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Повторить _все" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Одна песня" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Одна пе_сня" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Поток" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Буферизация" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Не удалось создать конвейер GStreamer (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Не найден элемент GStreamer для обработки формата мультимедиа" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Формат мультимедиа: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Не удалось инициализировать расширение GStreamer '%(name)s'" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Используется конвейер вывода GStreamer для воспроизведения. Пустое поле " "соответствует конвейеру по умолчанию. Если конвейер содержит выход, он будет " "использовано вместо выхода по умолчанию." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Конвейер вывода:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f с" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Размер буфера:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "_Отключить воспроизведение без пауз" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Отключение воспроизведения без пауз (gapless) может помочь решить проблемы " "при смене треков с некоторыми версиями GStreamer" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Использовать JACK для воспроизведения по доступности" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" "Использует `jackaudiosink` для выхода playbin, если его можно обнаружить" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Автоматическое подключение к устройствам вывода JACK" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Указывает `jackaudiosink` подключаться автоматически" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Не найдено устройство аудиовывода GStreamer. Попробовано: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Некорректный конвейер вывода GStreamer" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Не удалось создать аудиовыход" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Аудиоустройство %r не найдено. Проверьте настройки Xine в ~/.quodlibet/" "config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Не удалось найти модуль '{module}'. Возможно, вам нужно установить пакет?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Не удалось найти элемент GStreamer: '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Пожалуйста, откройте окно Расширений для настройки ListenBrainz. Без этого " "прослушивания не будут отправляться." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Слишком много последовательных передач не удались (%d). Переведено в offline-" "режим. Пожалуйста, посетите окно плагинов, чтобы сбросить ListenBrainz. До " "этого прослушивания отправляться не будут." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "Отправка в ListenBrainz" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Отправлять прослушивания в ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Ток_ен пользователя:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "Т_еги:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Список тегов для включения в отправку. Через запятую, при необходимости " "используйте двойные кавычки." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Песни, соответствующие этому фильтру, не будут отправлены." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Запустить плагин \"%(name)s\" для %(count)s плейлиста?" msgstr[1] "Запустить плагин \"%(name)s\" для %(count)s плейлистов?" msgstr[2] "Запустить плагин \"%(name)s\" для %(count)s плейлистов?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Запустить плагин" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Использование" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Начало" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "н/д" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Время" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Имя закладки" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "ММ:СС" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Закладки" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Фильтры" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Недавно прос_лушанные" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Недавно _добавленные" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _лучших" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "_Все треки" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "По текущим _жанрам" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "По текущим _исполнителям" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "По текущему _альбому" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Случайный _жанр" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Случайный _исполнитель" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Случайный _альбом" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 треков, которые воспроизводились большее количество раз, чем остальные " "(может быть выбрано больше 40, если есть треки, воспроизводившиеся равное " "количество раз)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Имя:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Значение:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Сохранённые значения" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Изменить сохранённые значения…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Авто_матически" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "Режим _трека" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "Режим _альбома" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Тихо" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Режим Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Новый %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(неизвестно)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "Доба_вить…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Изменить" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Выражение тега" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Выражение тега, например, people:real или ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Введите новое значение" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Изменить выражение тега" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Файлы:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Выбранные треки будут удалены из фонотеки, а их файлы — с диска." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Выбранные файлы будут удалены с диска." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Удалить %(file_count)d файл безвозвратно?" msgstr[1] "Удалить %(file_count)d файла безвозвратно?" msgstr[2] "Удалить %(file_count)d файлов безвозвратно?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Удалить файлы" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Выбранные треки будут удалены из фонотеки, а их файлы переместятся в корзину." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Выбранные файлы будут перемещены в корзину." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Переместить %(file_count)d файл в корзину?" msgstr[1] "Переместить %(file_count)d файла в корзину?" msgstr[2] "Переместить %(file_count)d файлов в корзину?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Переместить в корзину" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Перемещение %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Не удалось переместить в корзину" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Не удалось переместить в корзину некоторые файлы." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Удаление %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Не удалось удалить файлы" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Не удалось удалить некоторые файлы." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Обозреватель" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Загрузка файлов" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "отсутствует у %d трека" msgstr[1] "отсутствует у %d треков" msgstr[2] "отсутствует у %d треков" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "разное у %d трека" msgstr[1] "разное у %d треков" msgstr[2] "разное у %d треков" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "_Разделить на несколько значений" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Выделить 'Disc' из '_Album'" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Выделить '_Version' из 'Title'" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Выделить 'Arranger' из 'Ar_tist'" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Выделить '_Performer' из 'Artist'" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Выделить 'Performer' из '_Title'" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Выделить '_Originalartist' из 'Title'" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Добавить тег" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "Т_ег:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Пока_зывать программные теги" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "Доступ ко всем тегам, включая машинные (MusicBrainz, Replay Gain)" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Показыват_ь многострочные теги" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" "Показывать здесь потенциально многострочные теги (например, «текст песни») " "тоже" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Сброс" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "Со_хранить" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Настроить" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Разделить тег" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Копировать значения" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Не удалось добавить тег" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "Не удаётся добавить %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Выбранные файлы не поддерживают множественные значения для %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Недопустимый тег" msgstr[1] "Недопустимые теги" msgstr[2] "Недопустимые теги" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Недопустимый тег %s\n" "\n" "Выбранные файлы не поддерживают изменение этого тега." msgstr[1] "" "Недопустимые теги %s\n" "\n" "Выбранные файлы не поддерживают изменение этих тегов." msgstr[2] "" "Недопустимые теги %s\n" "\n" "Выбранные файлы не поддерживают изменение этих тегов." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Недопустимое значение" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Некорректное значение: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Возможно неправильный тег" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s был изменён во время работы программы. Сохранение файла без " "обновления фонотеки может привести к перезаписи других изменений песни." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Не удалось сохранить трек" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Не удалось сохранить %(file-name)s. Возможно, файл доступен только для " "чтения, испорчен, или у вас нет прав для его изменения." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Дополнительные параметры…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Отменить" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Вернуть" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_О программе" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Проверить обновления…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Расширения" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s и ещё %(count)s трек" msgstr[1] "%(title)s и ещё %(count)s трека" msgstr[2] "%(title)s и ещё %(count)s треков" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Настройки Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Папки" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Создать папку…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "В_ыбрать все вложенные папки" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Новая папка" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Введите имя новой папки:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Не удалось создать папку" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Не удалось удалить папку" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Треки" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "в исполнении %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Диск %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Трек %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Текущий _трек" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Изменить вид…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Нет выбранных треков." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Нет треков" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Информация" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Текст песни" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Продюсер: %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "исполнитель" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "исполнители" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "интерпретаторы" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Никогда" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d раз" msgstr[1] "%(n)d раза" msgstr[2] "%(n)d раз" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "добавлен" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "последний раз" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "воспроизведений" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "пропусков" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "оценка" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "путь" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "время" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "формат" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "кодек" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "декодер" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "битрейт" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "размер файла" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "изменён" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Дополнительно" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d выбран" msgstr[1] "%d выбрано" msgstr[2] "%d выбрано" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Трек недоступен" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d трек без альбома" msgstr[1] "%d трека без альбома" msgstr[2] "%d треков без альбома" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Выбранные альбомы" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d трек без исполнителем" msgstr[1] "%d трека без исполнителем" msgstr[2] "%d треков без исполнителем" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "альбомы" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Общая продолжительность:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Общий размер:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Файлы" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Показать онлайн" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Текст песни не найден." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Удалить все треки?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Выбранные треки будут удалены из фонотеки." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Показать" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Показать" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Убедитесь, что столбцы слева примерно совпадают со столбцами справа. Если " "это не так, вы можете изменить порядок здесь (используйте «_» для строк, " "которые не должны сопоставляться):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Правосторонний порядок:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Отменить изменения тегов?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Теги были изменены, но изменения не были сохранены. Сохранить файлы или " "отменить изменения?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Сбр_ос" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Файл существует" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Заменить %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Заменить файл" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Активные задачи" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d задач активно" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Перемешать" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Повторить" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "События" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Порядок проигрывания" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Редактор тегов" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Переименование" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Запрос" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Обложки" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Ошибки расширений" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Любое состояние" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Включено" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Отключено" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Нет категории" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Любая категория" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Расширения не найдены." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Расширения" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Фильтр по состоянию/тегу расширения" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Фильтр по типу расширения" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Фильтр по имени или описанию расширения" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "По_казать ошибки" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Диск" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Трек" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "_Группировка" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Исполнитель" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Альбом" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Имя _файла" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "Вре_мя" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Автопереход к воспроизводимому треку" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Когда воспроизведение переходит к другому треку, переходить к нему в " "плейлисте" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "Сортиро_вать песни при изменении тегов" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "Автоматически пересортировать песни в списке песен при изменении тегов" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Всегда разрешать сортировку" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" "Разрешить сортировать по заголовкам столбцов, даже для плейлистов и т. п." #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "Д_ругие:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Изменить…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Добавить или удалить столбцы" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Отображаемые столбцы" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Название содержит _версию" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Альбом содержит _номер диска" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Исполнитель содержит всех _артистов" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Имя файла содержит _путь" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Параметры столбцов" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Обновить столбцы" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "Применить текущие параметры к списку, добавив новые столбцы в конец" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Список треков" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Изменить столбцы" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Общая длительность" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Общий фильтр:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Применять этот запрос в дополнение ко всем другим" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Поиск" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Отображение" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "_Запрашивать подтверждение при множественном изменении оценок" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Подтверждать смену оценки для нескольких треков" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "О_ценивать трек одним щелчком" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Изменять оценку трека при щелчке в соответствующем столбце" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Оценка" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "_Предпочитать вложенную обложку" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Предпочитать вложенную в аудио обложку (если есть) вместо других источников" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Файлы изображений обложек альбомов, если они доступны (поддерживает " "подстановочные знаки). Если вы хотите указать более одного, разделите их " "запятыми." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "Предпочитаемые фиксированные имена файлов и_зображений" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Обложки альбома" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Воспроизведение" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Настройки вывода" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Если информация Replay Gain для трека отсутствует, изменять уровень " "громкости на это значение" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "Р_езервное усиление:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Изменять уровень громкости всех треков на данное значение, если исходное " "значение ниже" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "Усиление пре_дусилителя:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "Корректировка _громкости Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Настройка Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Продолжить воспроизведение при запуске" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Если музыка воспроизводится при выключении, автоматически начинать " "воспроизведение при следующем запуске" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Оценка по умолчанию:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Шкала оценок:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Средний коэффициент Байеса (C) для агрегированных оценок.\n" "«0» означает обычное среднее значение; значения выше приведут к более низким " "оценкам альбомов с меньшим количеством треков. Изменение этого значения " "вызовет перерасчёт для всех альбомов." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Усреднение по Байесу:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Эл. почта:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Оценки и счётчики воспроизведений будут сохранены в тегах для этого адреса " "электронной почты" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "Автоматически сохран_ять изменения тегов" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Сохранять изменения тегов без подтверждения при редактировании нескольких " "файлов" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Список разделителей (через пробел), которые будут использоваться для " "разделения тегов." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Разд_елитель тега:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Набор разделителей, используемых при извлечении подтегов из тегов в " "редакторе тегов. Список разделяется пробелами, и каждая запись должна " "содержать только два символа." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Р_азделитель подтега:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Теги" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Редактор тегов" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Обновлять оценки" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Сканировать фонотеку" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Проверить наличие изменений в вашей фонотеке" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "_Пересоздать фонотеку" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Перезагрузить все треки в вашей фонотеке. Это может занять много времени." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Скрытые треки" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Сканировать фонотеку при _запуске" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "Следить за изменени_ями в каталогах" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Наблюдать за каталогами фонотеки на предмет добавления, удаления и " "переименования внешних файлов." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Сканировать папки" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s и %(count)d следующий" msgstr[1] "%(title)s и %(count)d следующих" msgstr[2] "%(title)s и %(count)d следующих" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Свойства" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Очередь" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Очистить очередь" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Отключить очередь — очередь будет игнорироваться при воспроизведении" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Эфемерный" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Удалять треки из очереди после их воспроизведения" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Настойчивый" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Оставлять треки в очереди после их воспроизведения" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Режим" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Остановить в конце" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d трек (%(time)s)" msgstr[1] "%(count)d трека (%(time)s)" msgstr[2] "%(count)d треков (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Обзор фонотек_и" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Показать/скрыть очередь" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Ошибка воспроизведения" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Настроить каталоги фонотеки?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "У вас нет настроенной фонотеки. Хотите сделать это сейчас?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Не сейчас" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Выбрать" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Не удалось добавить треки" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s использует неподдерживаемый протокол." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "Перейти _к текущему" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Файл" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Трек" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Вид" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Вид" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Управление" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Справка" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "Добавить пап_ку…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Добавить _файл…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "Добавить _адрес…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Закладки…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Стоп" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Стоп после трека" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "Сочетания клавиш" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Справка онлайн" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Справка онлайн по поиску" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Добавить адрес" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Введите адрес аудиофайла:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Не удалось добавить адрес" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s не является корректным адресом." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Добавить музыку" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "Добавить пап_ки" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Музыкальные файлы" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "Добавить _файлы" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Уверены, что хотите поставить %d песню в очередь?" msgstr[1] "Уверены, что хотите поставить %d песни в очередь?" msgstr[2] "Уверены, что хотите поставить %d песен в очередь?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_В очередь" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Изменить оценку %d треков?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Сохранённые оценки будут удалены" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Удалить оценку" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Оценка всех треков будет изменена на «%s»" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Изменить _рейтинг" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "_Заменить пробел подчёркиванием" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Заменить двоеточия или точки с запятой - дефисами" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "пример: «iv: allegro.flac» -> «iv - allegro.flac»" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Заменить _Windows-несовместимые символы" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "_Удалить диакритические знаки" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Заменить не-_ASCII символы" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "_Только строчные символы" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Переименовать файлы" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Предпросмотр" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Имя файла" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "Переместить обложку альбома" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Смотрите строку конфигурации '[albumart] filenames' поиска имен файлов" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "Перезаписать _обложку альбома в месте назначения" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "Удалить пустые папки" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Обложка альбома" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Новое имя" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Не удалось переименовать файл" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Не удалось переименовать %(old-name)s в %(new-name)s. Возможно, целевой файл " "уже существует, или у вас нет прав для создания нового или удаления старого " "файла." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "_Пропустить все ошибки" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Стоп" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Продолжить" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Неабсолютный путь" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Шаблон\n" "\t%s\n" "содержит «/», но начинается не с корневого каталога. Чтобы избежать ошибки в " "названиях папок, начните шаблон с «/» или «~/»." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "Треки из этих папок будут добавлены в фонотеку во время её обновления" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Новый каталог будет отсканирован после добавления" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Все песни в выбранных каталогах также будут удалены из фонотеки" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "Переместит_ь" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Переместить корень сканирования (но не файлы) с миграцией метаданных всех " "включённых треков." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Удалить {dir!r} и все его треки?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Удалить {n} путей фонотеки и их треки?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Удалить путь фонотеки?" msgstr[1] "Удалить пути фонотеки?" msgstr[2] "Удалить пути фонотеки?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Удалить" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Выбор папок" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Выбрать этот каталог" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Выбрать актуальный / новый каталог для {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Это приведёт к перемещению метаданных QL:\n" "\n" "{old!r} → {new!r}\n" "\n" "Сами аудиофайлы при этом не перемещаются.\n" "Тем не менее, рекомендуется сделать резервную копию (включая файл Quod Libet " "«songs»)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Переместить корень сканирования {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "Хорошо, переместить его!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Сохранённые запросы" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Изменить сохранённые запросы…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Поиск в вашей фонотеке с помощью свободного текста или запросов QL" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "_Производить поиск по окончании ввода" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Производить поиск сразу после прекращения ввода" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Ограничение:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "По _оценкам" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Добавить запрос" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Добавить QL-запрос или свободный текст для совместного использования" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Отображать оставшееся время" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Главное окно" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Перемотка назад на 10 секунд" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Перемотка вперед на 10 секунд" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Фокус на строке поиска" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Сброс фильтров и переход к воспроизводимому треку" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Открыть информационное окно для выбранных треков" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Открыть редактор тегов для выбранных треков" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Добавить в очередь выбранные треки" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Удалить выбранные треки" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Показать строку поиска" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Щелкните на заголовке столбца" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Добавить столбец в список столбцов для сортировки" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "В виде дерева" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Свернуть элемент или выбрать родительский элемент" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Развернуть элемент" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Текстовые поля" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Отменить последнее изменение" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Повторить последнее отменённое изменение" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Выбрать все треки на всех панелях" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "Фильтр по %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "_Все заголовки" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Трек" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Альбом" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Заголовки исполнителей" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Дата" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Файл" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Производство" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Настроить…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "Автоши_рина" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Удалить трек «%(title)s» из фонотеки?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Удалить %(count)d треков из фонотеки?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Удалить из фонотеки" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Запустить плагин '%(name)s' для %(count)d трека?" msgstr[1] "Запустить плагин '%(name)s' для %(count)d треков?" msgstr[2] "Запустить плагин '%(name)s' для %(count)d треков?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Запустить плагин '%(name)s' для %(count)d альбома?" msgstr[1] "Запустить плагин '%(name)s' для %(count)d альбомов?" msgstr[2] "Запустить плагин '%(name)s' для %(count)d альбомов?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Настройки расширений…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Добавить в _очередь" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "Удалить из _фонотеки…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Не удается отобразить файлы" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "Ошибка отображения файлов, или нет программы для их отображения." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Показать %(total)d файл в менеджере файлов" msgstr[1] "_Показать %(total)d файла в менеджере файлов" msgstr[2] "_Показать %(total)d файлов в менеджере файлов" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Загрузить %(total)d файл…" msgstr[1] "_Загрузить %(total)d файла…" msgstr[2] "_Загрузить %(total)d файлов…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "успешно" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "неудачно" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Загрузки завершены" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Загрузить {name!r} в" msgstr[1] "Загрузить {total} файла в" msgstr[2] "Загрузить {total} файлов в" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Загрузите здесь" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "_Заменить подчёркивание пробелом" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "С з_аглавных" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Р_азделить на несколько значений" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Теги из пути файла" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Теги заменят существующие" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Теги будут добавлены к существующим" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t%s\n" "недопустим. Возможно, он содержит незакрытые скобки (< / >) или один и " "тот же тег дважды." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Введённый шаблон некорректен. Убедитесь, что вы ввели '<' и '>' как " "'\\<' и '\\>', и закрыли все открытые теги.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Изменить внешний вид" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Номера треков" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "_Начинать с:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "Всего _треков:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Воспроизведение/пауза" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Предыдущий" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "и ещё %d…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Сохранение изменений." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d треков сохранено\n" "(%(remaining)s осталось)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s из %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Проверить обновления" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Ошибка соединения" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Вы уже используете новейшую версию %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Доступна новая версия %(new-version)s\n" "\n" "Вы используете версию %(old-version)s\n" "\n" "Посетите <a href='%(url)s'>веб-сайт</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Пустой плейлист" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Плейлисты должны иметь имя" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Плейлист с названием %(name)s уже существует в %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Встроенные обложки альбомов" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Использует вложенные в аудиофайлы обложки." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Обложка из отдельного файла" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "Использует стандартно именованные изображения, из папки с треком." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Обложка" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Поиск у поставщиков обложек альбомов" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Вывести краткую информацию об использовании" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Вывести версию и информацию об авторских правах" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Вывести отладочную информацию" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Используется: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[options]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Неопознанный параметр '%r'." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Для параметра '%r' требуется аргумент." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r — не уникальный префикс." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d кбит/с" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s секунда" msgstr[1] "%s секунды" msgstr[2] "%s секунд" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Нет информации о времени" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунды" msgstr[2] "%d секунд" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минута" msgstr[1] "%d минуты" msgstr[2] "%d минут" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d час" msgstr[1] "%d часа" msgstr[2] "%d часов" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d день" msgstr[1] "%d дня" msgstr[2] "%d дней" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d год" msgstr[1] "%d года" msgstr[2] "%d лет" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "регистр_заголовка?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Дата должна быть в формате 'ГГГГ', 'ГГГГ-ММ-ДД' или 'ГГГГ-ММ-ДД ЧЧ:ММ:СС'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Значения усилений Replay Gain должны быть в формате 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Значения пиков Replay Gain должны быть введены в формате «x.yy»." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID должны быть в формате UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Статус выпуска MusicBrainz должен быть «official», «promotional» или " "«bootleg»." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Язык должен быть трёхзначным кодом ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Сохраняется %d файл" msgstr[1] "Сохраняются %d файла" msgstr[2] "Сохраняются %d файлов" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Автосохранение" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Не удалось изменить трек" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Не удалось сохранить %s. Возможно, файл доступен только для чтения, испорчен " "или у вас нет прав для его изменения." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Неверная кодировка]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "альбом" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "аранжировщик" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "аранжировщики" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "аранжировка" #: quodlibet/util/tags.py:86 msgid "author" msgstr "автор" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "авторы" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "комментарий" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "композитор" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "композиторы" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "композиция" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "дирижёр" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "дирижёры" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "дирижирование" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "контакты" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "авторское право" #: quodlibet/util/tags.py:93 msgid "date" msgstr "дата" #: quodlibet/util/tags.py:94 msgid "description" msgstr "описание" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "жанр" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "жанры" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "интерпретатор" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "исполнение" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "группировка" #: quodlibet/util/tags.py:98 msgid "language" msgstr "язык" #: quodlibet/util/tags.py:99 msgid "license" msgstr "лицензия" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "автор слов" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "авторы слов" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "текст песни" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "организация" #: quodlibet/util/tags.py:104 msgid "title" msgstr "название" #: quodlibet/util/tags.py:105 msgid "version" msgstr "версия" #: quodlibet/util/tags.py:106 msgid "website" msgstr "веб-сайт" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "исполнитель альбома" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "ударов в минуту" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "номер диска" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "диск" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "трек" # label ID #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "Label-ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "оригинальная дата выпуска" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "оригинальный альбом" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "оригинальный исполнитель" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "дата записи" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "страна выпуска" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "начальный ключ" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID записи" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID трека выпуска" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID выпуска" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID исполнителя" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID исполнителя выпуска" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Состояние альбома MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Тип альбома MusicBrainz" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "ID группы выпуска MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "усиление трека" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "пик трека" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "усиление альбома" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "пик альбома" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "эталонная громкость" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "диски" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "треков" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "последний запуск" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "полное имя" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "точка монтирования" #: quodlibet/util/tags.py:166 msgid "people" msgstr "исполнители" #: quodlibet/util/tags.py:168 msgid "year" msgstr "год" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "оригинальный год выпуска" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "закладка" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "битовая глубина" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "формат файла" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "плейлисты" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "частота дискретизации" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "число каналов" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "сортировка" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "роли" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Редактор тегов аудио" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Редактирование тегов в аудиофайлах" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Музыкальный проигрыватель" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Слушайте, просматривайте или изменяйте свою фонотеку" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso — это редактор тегов с интерфейсом как в Quod Libet. Он позволяет " "отображать и редактировать любые теги в файлах поддерживаемых форматов." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Поддерживаемые форматы файлов включают Ogg Vorbis/Opus/Speex/FLAC, MP3, " "FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, " "MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet — это программа управления музыкой. Предоставляет несколько " "различных способов просмотра вашей фонотеки, а также поддержку интернет-" "радио и аудиопотоков. Содержит крайне гибкие возможности правки и поиска " "тегов метаданных." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Экспортирует плейлист в плейлист Sonos, при условии, что оба имеют общую " #~ "структуру каталогов." #~ msgid "Export to Sonos playlist" #~ msgstr "Экспорт в плейлист Sonos" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Не удалось добавить <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Недопустимые теги" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Недопустимый теги <b>%s</b>\n" #~ "\n" #~ "Выбранные файлы не поддерживают изменение этих тегов." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Автооценка треков в зависимости от того, воспроизведены ли они полностью " #~ "или пропущены. Использует ускоренный алгоритм Брайана Нельсона." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f секунд" #~ msgid "Startup" #~ msgstr "Запуск" #~ msgid "Audio Feeds" #~ msgstr "Аудио-ленты" #~ msgid "_Audio Feeds" #~ msgstr "Аудио-_ленты" #~ msgid "New" #~ msgstr "Создать" #~ msgid "Automatic Library Update" #~ msgstr "Автообновление фонотеки" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Автоматически обновляет фонотеку с помощью inotify. Требует %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "Управление Quod Libet, через MPRIS 2 D-Bus Interface Specification." #~ msgid "Searching for lyrics…" #~ msgstr "Идёт поиск текста песни…" #, fuzzy #~ msgid "<artist>" #~ msgstr "исполнитель" #, fuzzy #~ msgid "<album>" #~ msgstr "альбом" #, fuzzy #~ msgid "<title>" #~ msgstr "название" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Экспорт метаданных выбранных треков в файл .tags." #~ msgid "Import Metadata" #~ msgstr "Теги - Импорт метаданных" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Импорт метаданных для выбранных треков из файла .tags." #~ msgid "Migrate Metadata" #~ msgstr "Теги - Миграция метаданных" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Копирует метаданные, специфичные для QuodLibet, между песнями." #~ msgid "_Copy" #~ msgstr "_Копировать" #~ msgid "_Paste" #~ msgstr "_Вставить" #~ msgid "Information to copy/paste" #~ msgstr "Инфо для копирования/вставки" #~ msgid "Map tracks by disc and track number" #~ msgstr "Карта треков по диску и номеру трека" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Включите эту функцию, если требуется перенести метаданные из одного " #~ "альбома в другой, при совпадении номеров дисков и треков.\n" #~ "\n" #~ "<b>Примечание:</b> этот параметр должен быть включен при копировании " #~ "метаданных для сохранения сведений о треке." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "%d трек сохранен" #~ msgstr[1] "%d трека сохранено" #~ msgstr[2] "%d треков сохранено" #~ msgid "No lyrics found" #~ msgstr "Текст песни не найден" #~ msgid "_Zoom level:" #~ msgstr "_Масштаб:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Revert to default" #~ msgstr "Вернуться к умолчанию" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "Поиск по URL выше, если текст не может быть найден в LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Альтернативный поиск" #~ msgid "Web Lyrics" #~ msgstr "Тексты песен из сети" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "Боковая панель, содержащая тексты песни из интернета." #~ msgid "Burn CD" #~ msgstr "Запись CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Запись CD с помощью K3b, Brasero или xfburn." �������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/sk.po����������������������������������������������������������������������������0000644�0001750�0001750�00000770262�14470736246�013631� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Slovak translations for Quod Libet/Ex Falso # Lukáš Lalinský <lalinsky@gmail.com>, 2006. msgid "" msgstr "" "Project-Id-Version: sk\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-06-04 12:49+0000\n" "Last-Translator: menom <menom1@protonmail.com>\n" "Language-Team: Slovak <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/sk/>\n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Generator: Weblate 4.18-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Názov" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "Ľu_dia" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Dátum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Dátum pridania" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Pôvodný dátum" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Žáner" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Hodnotenie" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "Počet _prehratí" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Zoradiť _podľa…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Nastavenia" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Zoznam albumov" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Zoznam albumov" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Všetky albumy" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albumy" msgstr[2] "%d albumov" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Opätovne načítať _obal albumu" msgstr[1] "Opätovne načítať _obaly albumov" msgstr[2] "Opätovne načítať _obalov albumov" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Skladby mimo albumu" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d stopa" msgstr[1] "%d stopy" msgstr[2] "%d stôp" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d disky" msgstr[2] "%d diskov" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Vzor albumu" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Nastavenia zoznamu albumov" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Zobraziť _obaly albumov" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Rýchle _vyhľadávanie zahŕňa osoby" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Možnosti" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Zobrazenie albumov" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Zavrieť" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Prehliadač knižnice" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d skladba" msgstr[1] "%d skladby" msgstr[2] "%d skladieb" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Neplatný vzor" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Zbierka albumov" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Zbierka albumov" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Neznáme %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Viacero %s hodnôt" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Vlastné" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Pridať" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Odstrániť" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Značka" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Zlúčiť" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Nastavenia zbierky albumov" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Použiť" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Zrušiť" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Mriežka obalov albumov" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Mriežka obalov albumov" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Nastavenia mriežky obalov albumov" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Zobraziť _texty albumu" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Zobraziť položku „Všetky albumy“" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Široké rozloženie" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Zväčšenie obalu albumu" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Súborový systém" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Súborový systém" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nepodarilo sa skopírovať skladby" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Vybrané súbory nemožno skopírovať do iných zoznamov skladieb ani do fronty." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Pridať do knižnice" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Zoznamy staníc môžu obsahovať jedine umiestnenia staníc ale nie iné zoznamy " "staníc alebo zoznamy prehrávania. Nasledovné umiestnenia nie je možné " "pridať:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internetové rádio" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Pridať stanice" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Sťahuje sa zoznam staníc" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nová stanica" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Zadajte umiestnenie internetovej rozhlasovej stanice:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronická" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip hop / rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Staré piesne" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonská" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indická" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Náboženská" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Rebríčky" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turecká" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / tanečná" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latinskoamerická" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Univerzitné rádio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Rozhovory / spravodajstvo" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambientná" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Džez" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Vážna" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Populárna" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatívna" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metalová" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Spravodajstvo" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Šlágre" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soulová" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punková" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slovanská" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grécka" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotická" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rocková" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Želáte si načítať zoznam obľúbených rozhlasových staníc?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Načítať stanice" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internetové rádio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Všetky stanice" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Obľúbené" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Žiadna kategória" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_Pridať stanicu…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Aktualizovať stanice" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nenašli sa žiadne stanice" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Na %s sa nenašla žiadna internetová rozhlasová stanica." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Niet čo pridať" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Všetky stanice na zozname sú už v knižnici." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Pridať do obľúbených" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Odstrániť z obľúbených" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stanica" msgstr[1] "%(count)d stanice" msgstr[2] "%(count)d staníc" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Panelový prehliadač" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Panelový prehliadač" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Vybrať _všetko" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Neznáme" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Všetko" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Malé" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Široké" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Stĺpcovité" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Vzor značky s voliteľným značením, napr. <tt>composer</tt> alebo\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Nastavenie panelového prehliadača" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Stĺpcovité rozloženie" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Obsah stĺpcov" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Rovnomerná šírka panelov" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Zoznamy prehrávania" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Zoznamy prehrávania" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Odstrániť zo zoznamu prehrávania" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nový" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "_Načítať…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Nepodarilo sa načítať zoznam prehrávania" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet môže načítať len zoznamy prehrávania vo formáte M3U/M3U8 alebo " "PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Zmazať" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Premenovať" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Neporadilo sa premenovať zoznam prehrávania" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Načítať zoznam prehrávania" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Načítať" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nový zoznam prehrávania…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Čo chcete urobiť s touto %d skladbou?" msgstr[1] "Čo chcete urobiť s týmito %d skladbami?" msgstr[2] "Čo chcete urobiť s týmito %d skladbami?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Potvrdiť činnosť pre zoznam prehrávania „%s“" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "prázdny" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Príklad zoznamu prehrávania" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Nastavenia prehliadača zoznamu prehrávania" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Zobrazenie zoznamu prehrávania" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Ste si istí, že chcete odstrániť zoznam prehrávania „%s“?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Všetky údaje o vybranom zozname prehrávania sa odstránia a už nebude možné " "ich obnoviť." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "Chcete rozšíriť \"{pl_name}\" o {num} ďalšiu skladbu?" msgstr[1] "Chcete rozšíriť \"{pl_name}\" o {num} ďalšie skladby?" msgstr[2] "Chcete rozšíriť \"{pl_name}\" o {num} ďalších skladieb?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Pridať Stopy" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nový zoznam prehrávania" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Zadajte názov nového zoznamu prehrávania:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "Vy_tvoriť" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Načítavanie zoznamu prehrávania.\n" "\n" "%(current)d/%(total)d pridaných skladieb." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Nový zdroj" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Zadajte umiestnenie podcastu / zdroja zvuku:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Podcasty" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Podcasty" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "_Pridať zdroj…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Obnoviť" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Vyhľadajte zdroj nových epizód" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Prestavať" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" "Odstráňte všetky existujúce epizódy a potom ich znova načítajte zo zdroja" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Odstráňte tento podcast a jeho epizódy" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Nepodarilo sa pridať zdroj" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s nebolo možné pridať. Server môže byť mimo prevádzky alebo umiestnenie " "nemusí byť podcast / zvukový kanál." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Aktuálny zvukový backend nepodporuje adresy URL, prehliadač podcastov je " "vypnutý." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Obmedziť výsledky" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Povoliť viaceré požiadavky" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Zoznam stôp" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Zoznam stôp" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Prehliadač Soundcloudu" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Hľadať" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Moje stopy" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Ísť na %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Pripojené" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet je teraz pripojený, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Odhlásiť sa z %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Zadajte kód…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Prihlásiť sa do %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud overenie" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Vložiť overovací kód pre Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nie je spustený (pre spustenie pridajte „--run“)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "hudobná knižnica a prehrávač" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[možnosť]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Vypísať prehrávanú skladbu a skončiť" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Začať prehrávanie okamžite" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Pri spustení nezobrazovať žiadne okná" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Preskočiť na nasledujúcu skladbu" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Preskočiť na predchádzajúcu skladbu alebo začať odznova, ak je prehrávanie " "na začiatku" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Preskočiť na predchádzajúcu skladbu" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Spustiť prehrávanie" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pozastaviť prehrávanie" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Prepnúť medzi prehrávaním a pozastavením" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Zastaviť prehrávanie" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Zvýšiť hlasitosť" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Znížiť hlasitosť" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Zvýšiť hodnotenie práve prehrávanej skladby o jednu hviezdičku" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Znížiť hodnotenie práve prehrávanej skladby o jednu hviezdičku" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Zobraziť stav prehrávača" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Skryť hlavné okno" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Zobraziť hlavné okno" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Prepnúť viditeľnosť hlavného okna" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Zamerať spustený prehrávač" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Odstrániť použité filtre prehliadača" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Obnoviť a opätovne načítať knižnicu" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Zobraziť zoznam dostupných prehliadačov" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Vypísať terajší zoznam prehrávania" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Vypísať obsah fronty" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Vypísať použitú textovú požiadavku" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Spustiť bez zásuvných modulov" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Spustiť Quod Libet, ak ešte nie je spustený" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Ukončiť Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Presunúť sa v prehrávanej skladbe" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Nastaviť alebo prepnúť náhodné prehrávanie" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Nastaviť spôsob náhodného prehrávania" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Zapnúť, vypnúť alebo prepnúť opakovanie" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Nastaviť spôsob opakovania" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Nastaviť hlasitosť" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Prehľadávať hudobnú knižnicu" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "požiadavka" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Prehrať súbor" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "názov súboru" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Nastaviť hodnotenie prehrávanej skladby" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Nastaviť súčasný prehliadač" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Zastaviť prehrávanie po skončení súčasnej skladby" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Otvoriť nový prehliadač" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Zobraziť alebo skryť frontu" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrovať podľa náhodnej hodnoty" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "značka" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrovať podľa značky" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "značka=hodnota" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Pridať súbor alebo požiadavku do fronty" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Pridať súbory oddelené čiarkou do fronty" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "názov súboru" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "" "Zobraziť názvy súborov, ktoré sú výsledkom požiadavky, na štandardnom výstupe" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Odobrať súbor alebo požiadavku z fronty" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Pridať súbor alebo priečinok do knižnice" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "umiestnenie" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "Nastaviť šablónu pre príkazy --print-*" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "vzor" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Neplatný parameter pre „%s“." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Skúste %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Vyskytla sa chyba" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Nemusíte si túto chybu všímať, ale aplikácia môže byť nestabilná pokiaľ ju " "nereštartujete. Odoslanie správy o chybe zaberie len pár sekúnd, ale môže " "nám významne pomôcť." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Odoslať správu o chybe" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Reštartovať" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Nevšímať si túto chybu" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Podrobnosti o chybe:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Rôzne podrobnosti o chybe a o vašom systéme sa odošlú službe tretej strany " "(<a href='https://www.sentry.io'>www.sentry.io</a>). Odosielané údaje si " "môžete prezrieť nižšie." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(voliteľné) Pridajte krátky popis toho, čo sa stalo, keď chyba nastala:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Odoslať" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Krátky popis…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Odosielané údaje:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "editor značiek" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "priečinok" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Editor údajov o skladbe" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL zdroj obalu albumu" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Sťahuje obaly, na ktoré je odkazované značkou <tt>artwork_url</tt>. Funguje " "to s prehliadačmi Soundcloud a Podcasts." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Zdroj obalov albumov Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Stiahne obaly albumov z Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Zdroj obalov albumov Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Stiahne obaly albumov z archívu Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Zdroj obalov albumov MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Stiahne obaly albumov z archívu MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Zmeniť kódovanie" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Opravuje nesprávne kódovanie hodnôt značiek v editore značiek." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Zmeniť kódovanie…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Nástroj na jednoduché prevedenie znakov kana/kanji" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Prevádza kana/kanji na romaji pred premenovávaním." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "_Japonský text na latinku" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" "Nepodarilo sa nájsť „Nástroj na jednoduché prevedenie znakov kana/" "kanji“ (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Nahradenie pomocou regulárneho výrazu" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Umožňuje ľubovoľné nahradzovanie pomocou regulárnych výrazov (<tt>s/z/na/</" "tt>) počas značkovania alebo premenovávania súborov." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Veľkosť písmen v názvoch" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Upravuje veľkosť písmen v názvoch pomocou editora značiek." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "_Veľkosť písmen v názvoch" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Povoliť _VŠETKY-VEĽKÉ v značkách" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Bežné použitie veľkých a malých písmen" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "V názvoch používa anglické pravidlá pre písanie veľkých a malých písmen, " "napr. „Dark Night of the Soul“" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Pokročilé nastavenia" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Povoliť úpravu pokročilých nastavení." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Viem, čo robím" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animované oznámenia na obrazovke" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Zobrazí oznámenie s podrobnosťami o skladbe, keď sa zmení." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Poloha:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Veľkosť obalu:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Zobrazenie" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Písmo:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Vľavo" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Uprostred" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Vpravo" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Zarovnať text:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Text" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Text:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Vyplniť:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Farby" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Tiene" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Okraje" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Zaoblené okraje" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Oneskorenie:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efekty" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Upraviť vzor zobrazenia…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Náhľad" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Podrobnosti o programe" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Rôzne údaje o programe a jeho prostredí." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Podporované formáty" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Priečinok nastavení" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Priečinok vyrovnávacej pamäte" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Zvuková obslužná aplikácia" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Po každom prehratí (predvolené)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Zásuvný modul zapíše značky do súboru pri každom prehratí, ale nie " "preskočení, skladby. Počet preskočení sa do súboru vôbec neukladá, aby sa " "predišlo nepotrebným zápisom." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Po každom prehratí alebo preskočení" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Zásuvný modul zapíše značky do súboru pri každom prehratí alebo preskočení " "skladby. Toto môže byť užitočné, ak sa chcete uistiť, že hodnotenia " "pesničiek, ktoré nemáte radi a preskočíte ich sa zapíšu do súboru." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Iba raz, po ohodnotení celého albumu" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Po prehratí alebo preskočení skladby sa album skontroluje. Ak boli všetky " "skladby v albume ohodnotené a aspoň jedna z nich nemá v súbore uložené " "hodnotenie alebo počet prehratí, zásuvný modul zapíše značky do príslušného " "súboru skladby.\n" "\n" "Takto sa môžete vyhnúť neustálym aktualizáciám, ale buďte opatrní. Keď sa " "raz album aktualizuje, na zapísanie nových hodnotení a počtov prehratí do " "súboru budete musieť použiť zásuvný modul „Aktualizácia značiek v súboroch“." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Keď zásuvný modul zapíše značky albumu, najprv nastaví počet prehratí na " "jedno pre všetky skladby s nulovým počtom prehratí.\n" "Niekedy už dopredu viete, že pesničku nemáte radi. Takže nastavenie počtu " "prehratí na jedno môžete využiť neskôr pri vyhľadávaní úplne vypočutých " "albumov (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "Nepodarilo sa zapísať „%s“" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Automaticky aktualizovať značky v súboroch" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Pri prehrávaní skladieb aktualizovať značky v príslušných súboroch. Toto " "zaručí, že počty prehratí a hodnotenia zostanú aktuálne." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Nasledovné nastavenie bolo povolené, pretože sa vyžaduje pre správne " "fungovanie zásuvného modulu:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Ukladať hodnotenia a _počty prehratí do značiek" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Nastavenia aktualizované" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Chyba v %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Pri ukladaní sa uistiť, že počty prehratí sú väčšie ako nula" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Spôsob aktualizácie:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Možnosti" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatické skrývanie" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Automaticky skryť alebo zobraziť jednotky pri odpojení alebo pripojení." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatické hodnotenie" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Automaticky hodnotí skladby, keď sa prehrajú alebo preskočia. Používa sa " "'zrýchlený' algoritmus z vux od Briana Nelsona." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Určená databáza Banshee má nesprávny tvar alebo chýba" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Načítanie zlyhalo" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Hodnotenia a štatistika %d skladby boli úspešne načítané" msgstr[1] "Hodnotenia a štatistika %d skladieb boli úspešne načítané" msgstr[2] "Hodnotenia a štatistika %d skladieb boli úspešne načítané" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Načítať z Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Načíta hodnotenia a štatistiku skladieb z Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Cesta k databáze:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Začať načítavanie" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Budík" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Zobudí vás hlasnou hudbou." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Uspávanka" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Stlmí a pozastaví prehrávanie." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord stavová správa" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discord Stavová Správa" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Zmení stavovú správu Discord podľa toho, čo práve počúvate." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Pozastavené" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Stavová Línia #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Stavová Línia #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Ploché" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Naživo" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Plné hĺbky aj výšky" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klub" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Veľká hala" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Oslava" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Jemne" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Plné hĺbky" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Reggae" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Slúchadlá" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Jemný rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Plné výšky" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Tanečná" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Techno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Prenosný počítač" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Ekvalizér" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Ovládanie zvuku pomocou ekvalizéra.\n" "Kliknite alebo použite klávesy pre prispôsobenie úrovní (pravé kliknutie " "obnoví pôvodnú hodnotu daného pásma)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Súčasná obslužná aplikácia na pozadí nepodporuje ekvalizér." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Predvolené zoznamy nastavení" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Vybrať…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Obnoviť EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Vlastný zoznam nastavení" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Odstrániť vybraté" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Názov zoznam nastavení pre uloženie:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Uložiť" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "pripojený" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "nepripojený" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "výmena správ" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "preč" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "neviditeľný" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Stav správy Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Zmení stav správy Gajim podľa toho čo práve počúvate." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "pozastavené" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Vzor:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Zobraziť zoznam účtov, oddelených čiarkou, pre zmenu stavu. Ak nie je " "vybratý žiaden účet, zmení sa stav všetkých účtov." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Účty:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Pridať '[pozastavené]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Ak je označené, pri pozastavení skladby sa pridá '[pozastavené]' do stavu " "správy" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Stavy, pre ktoré sa zmení správa" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pozastaviť pri odpojení slúchadiel" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pozastaví prehrávanie pri odpojení slúchadiel a obnoví prehrávanie pri ich " "opätovnom pripojení." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Zakázať šetrič obrazovky/režim spánku" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "V pracovnom prostredí GNOME zabraňuje spusteniu šetriča obrazovky alebo " "prechodu počítača do režimu spánku ak sa práve prehráva skladba." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Prehráva sa hudba" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Režim:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Zakázať šetrič obrazovky" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Zakázať režim spánku" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Záznam internetového rozhlasu" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Zaznamená posledných desať skladieb hraných v rozhlase a zobrazí ich zoznam " "v kontextovej ponuke vyhľadávania." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Uloží súbor Jabber User Tunes do %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Zmeniť jazyk" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Zmeniť jazyk používateľského rozhrania." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Predvolený jazyk systému" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Pre uplatnenie zmien sa vyžaduje reštart aplikácie" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "Server médií UPnP AV" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Sprístupní všetky albumy serveru médií Rygel UPnP prostredníctvom rozhrania " "MediaServer2 D-Bus." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Uistite sa, že váš súbor nastavení rygel (~/.config/rygel.conf) obsahuje " "nasledovné:" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Server MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Umožňuje diaľkové ovládanie Quod Libet pomocou MPD klienta. Streamovanie, " "zoznam prehrávania a správa knižnice nie sú podporované." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Koncový bod:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Miestna _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "_Heslo:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Pripojenie" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Otestovaní klienti" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Podpora MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Povoľuje ovládanie Quod Libet použitím <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> špecifikácie D-Bus rozhrania. Toto povoľuje " "rôzne integrácie Linuxového desktopu (napr. multimediálnych kláves)." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Pri zatváraní skryť hlavné okno" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Prijíma QL vzory, napr. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Nástroj na uverejňovanie MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Uverejňuje správy o stave do MQTT témy." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Názov hostiteľa sprostredkovateľa / IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Predvolený je tento počítač" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Port sprostredkovateľa" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Predvolený je 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Používateľské meno sprostredkovateľa" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Heslo sprostredkovateľa" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Téma" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Vzor pre prehrávanie" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Text správy o stave pri začatí prehrávania." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Vzor pre pozastavenie" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Text pri pozastavení prehrávania." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Text, keď sa nič neprehráva" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Text, keď sa momentálne neprehráva žiadna skladba" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Nastavenie MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Text správy o stave" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Pripojené k sprostredkovateľovi na %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Nepodarilo sa pripojiť k %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Chyba pripojenia" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz synchronizácia" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Synchronizuje hodnotenia skladieb s MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Používateľské _meno:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Heslo:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Účet" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Text oznámenia" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Názov:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Obnoviť predvolený vzor" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Telo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Zobraziť oznámenie" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Zobraziť oznámenia" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Iba pri <i>ručnom</i> prepnutí skladby" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Iba pri <i>automatickom</i> prepnutí skladby" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Pri <i>každej</i> zmene skladby" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Len keď je hlavné okno _nezamerané" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Zobraziť tlačidlo \"_Ďalšie\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Chyba pripojenia" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Nepodarilo sa pripojiť k démonovi oznámení." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Oznámenia o skladbách" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Zobrazí oznámenie pri zmene skladby." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Ďalšie" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Upozornenia na záložky" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Používa upozornenia na zobrazenie záložiek / komentárov v reálnom čase. " "Funguje dobre pre prehliadač Soundcloud." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Pre nastavenie QLScrobblera navštívte okno zásuvných modulov. Dovtedy sa " "skladby odosielať nebudú." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Nepodarilo sa spojiť so službou „%s“." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Overenie totožnosti zlyhalo: neplatné prepojenie." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Overenie totožnosti zlyhalo: Neplatné používateľské meno „%s“ alebo heslo." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Klient bol zablokovaný. Spojte sa s autorom." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Nesprávny systémový čas. Ak túto chybu neodstránite, odosielanie skladieb " "môže zlyhať." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "Odosielanie skladieb AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler klient pre Last.fm, Libre.fm a ďalšie Audioscrobbler služby." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Overenie totožnosti prebehlo úspešne." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Služba:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_Prepojenie:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Ďalšia…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Overiť údaje účtu" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Vzor pre umelca:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Vzor pre názov skladby:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Vylučovací _filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Vzor používaný na formátovanie mena umelca pri odosielaní skladieb. " "Ponechajte prázdne, ak chcete použiť predvolenú hodnotu." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Vzor používaný na formátovanie názvu skladby pri odosielaní skladieb. " "Ponechajte prázdne, ak chcete použiť predvolenú hodnotu." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Skladby zodpovedajúce tomuto filtru sa neodošlú" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Režim offline (neodosielať nič)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Odoslanie" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Stlmiť reklamy v rozhlase" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Stlmí výstup počas prehrávania reklám v rozhlase.\n" "Stanice: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Prehrávanie náhodného albumu" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Začne prehrávať náhodný album po dosiahnutí konca vášho zoznamu prehrávania. " "Vyžaduje podporu filtrovania albumov vo vašom aktívnom prehliadači." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Lepšie hodnotené" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Častejšie prehrávané" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Častejšie preskakované" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Nedávno prehrávané" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Nedávno spustené" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Nedávno pridané" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Dlhšie albumy" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekundy pred začiatkom prehrávania ďalšieho albumu" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Váhy" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Niektoré albumy prehrávať častejšie než iné" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "vyhnúť sa" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "uprednostniť" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Náhodný album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Čaká sa na začiatok %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Nahrávanie hodnotení a štatistík pre %d skladieb bolo úspešné" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Import z Rhythmboxu" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importuje hodnotenia a štatistiky skladieb z Rhythmboxu." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pozastavenie pri použití šetriča obrazovky" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pozastaví prehrávanie, keď je zapnutý šetrič obrazovky GNOME." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Nie je nainštalovaný žiadny poskytovateľ vyhľadávania GNOME Shell pre Quod " "Libet." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "Skopírovali ste ini súbor do %s (alebo podobného)?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "Poskytovateľ vyhľadávania GNOME" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Umožňuje GNOME Shell prehľadávať hudobnú knižnicu." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Náhradný panel vyhľadávania" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Náhradný panel vyhľadávania, ktorý je vždy zapnutý a roztiahnutý na šírku " "okna." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Záložky bodov presunu" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Uložiť body presunu A a/alebo B pre jednotlivé stopy. Pri prehrávaní stopy " "preskočiť na čas A a zastaviť v čase B.\n" "\n" "ℹ Vedzte, že pri zmene názvov bodov nižšie sa názvy záložiek neaktualizujú. " "Ovplyvňuje to len to, ktoré názvy záložiek zásuvný modul vyhľadáva pri " "posúvaní stopy." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Názov záložky pre bod A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Názov záložky, ktorý sa má vyhľadať na začiatku prehrávania stopy. Ak " "jestvuje, prehrávač sa presunie na daný časový bod" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Názov záložky pre bod B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Názov záložky, ktorý sa má vyhľadať počas prehrávania stopy. Ak súčasná " "poloha presahuje daný časový bod, prehrávač sa presunie na koniec stopy." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox synchronizácia" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Umožní Logitech Squeezebox zrkadliť výstup Quod Libet pri prehrávaní z " "rovnakej hudobnej knižnice." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Zdieľa nastavenie s <a href=\"%(plugin_link)s\">Exportovať do zásuvného " "modulu Squeezebox</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Nepodarilo sa nájsť server Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Nepodarilo sa nájsť %s. Preverte nastavenie" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Pri pozastavení zastaviť" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Tento zásuvný modul zmení Pozastaviť na Zastaviť/Prehrať/Posunúť.\n" "\n" "Toto sa môže zísť, ak Quod Libet nemôže prepnúť zvukové zariadenia po " "pripojení nového zariadenia (Bluetooth reproduktory, USB DAC, atď.) do " "systému.\n" "\n" "Ak je voľba „Len zdroje podporujúce preskakovanie“ vypnutá, uistí sa, že " "súčasná poloha v skladbe sa zachová. V opačnom prípade sa prehrávanie " "zastaví a musí sa začať odznova." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Len zdroje podporujúce preskakovanie" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Možnosti zásuvného modulu" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Čaká sa na kopírovanie" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Čaká sa na odstránenie" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "odstrániť" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Preskočiť" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "DUPLIKOVAŤ" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Synchronizuje sa" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Odstraňuje sa" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Úspech" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "ZLYHANIE" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Vynechal sa jestvujúci súbor" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Nedá sa nastaviť názov súboru skladby." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Synchronizovať so zariadením" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchronizuje všetky skladby z vybratých uložených vyhľadávaní so zadaným " "priečinkom." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Synchronizovať nasledovné uložené vyhľadávania:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Úplná cesta k umiestneniu výsledku exportu" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Všetky jestvujúce súbory v cieľovom umiestnení, ktoré nie sú v uložených " "vyhľadávaniach sa vymažú." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "V prípade zariadení pripojených cez MTP exportovať najprv do miestneho " "priečinka a potom presunúť do vášho zariadenia pomocou rsync. Alebo, pri " "synchronizácii veľkého množstva súborov do Android zariadenia, použiť omnoho " "rýchlejší adb-sync." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Cieľové umiestnenie:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Vzory cesty" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Upraviť uložené vzory…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Zloženie exportovaných názvov súborov založené na ich značkách" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Vzor exportu:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Zastaviť náhľad" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Stav" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Zdrojový súbor" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Cesta exportu" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Niektoré cesty exportu sú uvedené dvojmo! Pred začatím synchronizácie môžete " "upraviť vyššie uvedené cesty." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Existujúce súbory v cieľovej ceste budú vymazané (okrem súborov s názvom " "'cover.jpg')!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Spustiť synchronizáciu" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Zastaviť synchronizáciu" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" "Zatiaľ nemáte žiadne uložené vyhľadávania. Nejaké si vytvorte a vráťte sa " "späť!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Vyberte cieľové umiestnenie" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Cesta exportu pre súbor [{filename}] sa zmenila z [{old_path}] na " "[{new_path}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Spúšťa sa náhľad synchronizácie" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Prebieha náhľad synchronizácie." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Náhľad synchronizácie sa dokončil" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Zastavuje sa náhľad synchronizácie" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Náhľad synchronizácie sa zastavil." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Náhľad synchronizácie sa dokončil." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Náhľad synchronizácie sa zastavil" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Bol zistený iný zásuvný modul - zastaviť náhľad" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Synchronizácia:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "sa pokúsi zapísať {count} súbor" msgstr[1] "sa pokúsi zapísať {count} súbory" msgstr[2] "sa pokúsi zapísať {count} súborov" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "preskočí {count} duplicitný súbor" msgstr[1] "preskočí {count} duplicitné súbory" msgstr[2] "preskočí {count} duplicitných súborov" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "odstráni {count} súbor" msgstr[1] "odstráni {count} súbory" msgstr[2] "odstráni {count} súborov" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Nebola zadaná žiadna cieľová cesta" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Zadajte priečinok, kde sa majú skladby exportovať." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Nebol zadaný žiadny vzor exportu" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Zadajte vzor názvov exportovaných skladieb." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Cesta exportu nie je úplná" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Vzor\n" "\n" "{}\n" "\n" "obsahuje \"/\" ale nezačína v koreňovom priečinku. Zadajte úplnú cieľovú " "cestu, ktorá začína / alebo ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Nie sú vybrané žiadne uložené vyhľadávania" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Vyberte aspoň jedno uložené vyhľadávanie." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Nie sú vybrané žiadne skladby v uložených vyhľadávaniach" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Všetky uložené vyhľadávania sú prázdne." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Našlo sa {} skladieb na synchronizovanie" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Cieľová cesta je v rozpore so vzorom exportu" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Vzor exportu začína cestou, ktorá sa líši od cieľovej cesty. Opravte vzor.\n" "\n" "Chyba:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Nepodarilo sa synchronizovať" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Nie je možné spustiť synchronizáciu pri zoradení podľa <b>Stavu</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Spúšťa sa synchronizácia skladieb" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Prebieha synchronizácia." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Synchronizácia skladieb je dokončená" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Zastavuje sa synchronizácia skladieb" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Synchronizácia bola zastavená." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Synchronizácia je dokončená." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Synchronizácia skladieb sa zastavila" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Bol zistený iný zásuvný modul - zastaviť synchronizáciu" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - „{filename}“" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Odstraňuje sa „{}“" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Počas synchronizácie sa:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "zapísal {count} súbor z {total}" msgstr[1] "zapísali {count} súbory z {total}" msgstr[2] "zapísalo {count} súborov z {total}" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(preskočil {count} jestvujúci súbor)" msgstr[1] "(preskočili {count} jestvujúce súbory)" msgstr[2] "(preskočilo {count} jestvujúcich súborov)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "preskočil {count} duplicitný súbor z {total}" msgstr[1] "preskočili {count} duplicitné súbory z {total}" msgstr[2] "preskočilo {count} duplicitných súborov z {total}" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "odstránil {count} súbor z {total}" msgstr[1] "odstránili {count} súbory z {total}" msgstr[2] "odstránilo {count} súborov z {total}" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "nepodarilo synchronizovať {count} súbor" msgstr[1] "nepodarilo synchronizovať {count} súbory" msgstr[2] "nepodarilo synchronizovať {count} súborov" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "preskočil {count} predtým synchronizovaný súbor" msgstr[1] "preskočili {count} predtým synchronizované súbory" msgstr[2] "preskočilo {count} predtým synchronizovaných súborov" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Synchronizované texty piesní" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Zobrazuje synchronizované texty piesní z .lrc súboru, ktorý má rovnaký názov " "ako stopa." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Text:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Pozadie:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Písmo" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Veľkosť (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Správy o stave Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Aktualizuje správu o stave vo všetkých účtoch rýchlych správ založených na " "Telepathy (Empathy, apod.) na správu o práve prehrávanej skladbe." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Prehráva sa:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" "Text správy o stave pri spustení prehrávania skladby. Možno použiť QL vzory, " "napr. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Pozastavené:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Text správy o stave pri pozastavení skladby. Možno použiť QL vzory, napr. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Čistý text pre správu o stave, keď sa neprehráva žiadna skladba" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Žiadna skladba:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Vzory správ o stave" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Prepínač motívov" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Zmení súčasný GTK+ motív." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Motív:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Predvolený motív" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Uprednostňovať tmavý odtieň motívu" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Hodnotenie palcom" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Pridá spôsob hodnotenia palcom hore alebo palcom dole, ktoré sa prevedie na " "číselné hodnotenie. Užitočné pre ukladanie súčtov prebiehajúcich hodnotení a " "triedenie podľa <b><tt>~#score</tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Prepnúť panel ponuky" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Prepnúť panel ponuky stlačením klávesy Alt." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Nehrá" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Ikona v oznamovacej oblasti" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Ovláda Quod Libet z panela úloh." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Zobraziť %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Prehrať" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ozastaviť" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Naspäť" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Ďalej" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Náhodne" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Opakovať" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Zastaviť _po tejto skladbe" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Otvoriť _prehliadač" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Upraviť _tagy" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informácie" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "_Zoznamy prehrávania" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Ukončiť" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Správanie" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Ovládať hlasitosť kolieskom myši" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Prepínať skladby kolieskom myši" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Koliesko myši" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Zobrazenie tipov" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Zobraziť texty piesní" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Automaticky zobraziť texty piesní v bočnom paneli." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Nenašiel sa žiadny text pre skladbu\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Žiadna aktívna skladba" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Spustiť vizualizácie" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Spustiť externé vizualizácie." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Nepodarilo sa spustiť vizualizácie pomocou „%s“" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Chyba" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Spustiteľný súbor vizualizéra:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Opätovne načítať" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Panel posunu vo vlnovej krivke skladby" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ Panel posunu v tvare vlnovej krivky prehrávanej skladby." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Nahradiť farbu popredia:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Nahradiť farbu pri prechode myšou:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Nahradiť zvyšnú farbu:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Zobraziť súčasnú polohu" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Zobraziť časové značky" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Dĺžka posunu kolieskom myši (v milisekundách):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Ukladač obrázkov" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Uloží obrázok obalu súčasnej skladby do súboru." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Súbor:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Prah:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Prahová hodnota pre zapnutie filtra" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "P_omer:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Pomer kompresie" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Zvukový kompresor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Zmení vrcholovú hodnotu všetkých vzoriek presahujúcich určitý prah na " "základe určitého pomeru." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Prednastavenie:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Prednastavenie filtra" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Orezanie frekvencie:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Frekvencia orezávania dolného priepustu" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Úroveň _kanálu:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Úroveň kanálu" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Predvolená hodnota" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Umiestnenie najbližšie k virtuálnemu reproduktoru (30°, 3 metre)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Blízke zmiešavaču Chu Moy (obľúbené)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Blízke zosilňovačom CORDA Jana Meiera (malá zmena)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Vlastné" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Vlastné nastavenie" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Zmiešavanie kanálov" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Zmieša ľavý kanál s pravým pre napodobnenie nastavenia pri počúvaní " "slúchadlami alebo prispôsobí nastavenie zvuku starým stereo nahrávkam." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "_Pásmo filtra:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Frekvenčné pásmo filtra" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Šírka _filtra:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Šírka frekvencie filtra" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "Ú_roveň:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Úroveň efektu" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Odstráni hlavné vokály zo zvuku." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Zlúčenie kanálov" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Zlúči kanály do jedného." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "_Hodnotenie:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Výška tónov:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Výška tónov / rýchlosť zvuku" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Ovláda výšku tónov zvukového prúdu." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Exportovať zoznam prehrávania do priečinka" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Exportovať" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Cieľový priečinok:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "_Vzor názvu súborov:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Vyexportuje zoznam prehrávania skopírovaním súborov do priečinka." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Nepodarilo sa exportovať zoznam prehrávania" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Uistite sa, že máte právo zapisovať do cieľového umiestnenia." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Predvolený vzor názvu súborov:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "D_obre" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Zadajte názov nového zoznamu prehrávania\n" "alebo vyberte jestvujúci zoznam prehrávania Sonos na prepísanie" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Exportovať do zoznamu prehrávania Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "Exportuje zoznam skladieb do systému Sonos priraďovaním skladieb." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Nastala chyba pri vyhľadávaní zariadení Sonos" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Chyba pri vyhľadávaní Sonos. Preverte nastavenia" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Nepodarilo sa odstrániť existujúci zoznam skladieb Sonos %s:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Exportovať do zoznamu skladieb %(playlist)r (%(total)d tracks)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exportovať pre Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dynamicky vyexportuje zoznam prehrávania do zoznamu prehrávania Logitech " "Squeezebox pokiaľ obidva zdieľajú usporiadanie priečinka." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Zdieľa nastavenie so <a href=\"%(plugin_link)s\">zásuvným modulom Squeezebox " "Sync</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Exportovať zoznam prehrávania pre Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Názov zoznamu prehrávania (prepíše jestvujúci)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Exportovať do zoznamu skladieb Squeezebox" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Odstrániť duplicitné položky zo zoznamu prehrávania" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Odstraňuje duplicitné položky zo zoznamu prehrávania." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Ste si istí, že chcete odstrániť %d duplicitnú skladbu?" msgstr[1] "Ste si istí, že chcete odstrániť %d duplicitné skladby?" msgstr[2] "Ste si istí, že chcete odstrániť %d duplicitných skladieb?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplicitné skladby sa odstránia zo zoznamu prehrávania „%s“." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Zamiešať zoznam prehrávania" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Náhodne zamieša zoznam prehrávania." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Zamerať ukazovateľa myši" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Umožňuje prehrávanie skladieb podľa vlastného výberu. Po vyčerpaní zoznamu " "sa prehrá nasledujúca skladba." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "Zamerať ukazovateľa myši" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_Zamerať ukazovateľa myši" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Ekvalizér počtu prehratí" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" "Umožňuje zamiešať skladby tak, aby sa uprednostnili tie s menším počtom " "prehratí." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Uprednostňovať menej prehrávané" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Uprednostňovať _menej prehrávané" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Len fronta" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Obmedzí prehrávanie skladieb na tie vo fronte.\n" "\n" "Zvoľte toto poradie prehrávania skladieb v hlavnom okne. Potom sa skladby po " "dvojitom kliknutí namiesto okamžitého prehrania pridajú do fronty." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Len fronta" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "_Len fronta" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Automaticky prehrá piesne dvojitým kliknutím" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Opačne" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Umožňuje prevrátiť poradie prehrávania skladieb." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Pre_vrátiť" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Skupinové zamiešanie" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Umožňuje zamiešať skladby zoskupené na základe spoločnej značky (podobne ako " "pri zamiešaní albumu).\n" "\n" "Pomôže pri miešaní klasických skladieb s viacerými časťami, kedy je potrebné " "sa uistiť, že sa všetky časti prehrajú v správnom poradí pred prechodom na " "ďalšiu časť." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Skupinové zamiešanie" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "_Skupinové zamiešanie" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Čaká sa na začiatok novej skupiny…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Značka pre zoskupenie:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Značka, na základe ktorej sa majú skladby zoskupiť" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filtrovacia značka:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "K zoskupeniu dôjde len vtedy, ak je určená filtrovacia značka.\n" "Skladba bez určenej filtrovacej značky sa bude považovať za\n" "osobitnú skupinu. Filtrovacia značka by sa mala aspoň čiastočne\n" "zhodovať so značkou pre zoskupenie." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Oneskorenie:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Oneskorenie pred začatím ďalšej skupiny (v sekundách)" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Obnoviť predvolené" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Preskočiť skladby, ktoré sa mi nepáčia" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Počas prehrávania umožňuje preskočiť skladby, ktorých hodnotenie nedosahuje " "zadaný prah." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Preskočiť skladby, ktoré sa mi nepáčia" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Preskočiť skladby, ktoré sa mi _nepáčia" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Opakovať každú skladbu" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Pri prehrávaní podľa určitého poradia umožňuje zopakovať každú skladbu " "nastavený počet krát." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Zopakovať každú skladbu" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "Zopakovať _každú skladbu" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Počet prehratí každej skladby:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Podmienená požiadavka" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Umožňuje výber výrazu vyhľadávania založený na podmienenej požiadavke." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: podmienená požiadavka, tak-požiadavka, ak nie-požiadavka)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Vyhľadávanie podľa chýbajúcich značiek" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Vyhľadáva skladby bez danej značky." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Zahrnúť prázdne značky" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Požiadavka v jazyku Python" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍V požiadavkách používať výrazy jazyka Python." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: výraz)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Premenná <tt>s</tt> (alebo <tt>a</tt>) predstavuje porovnávanú skladbu / " "album.\n" "\n" "<tt>_ts</tt> je celé číslo, ktoré predstavuje časový bod na začiatku " "požiadavky.\n" "\n" "Taktiež sú dostupné moduly <tt>time</tt> a <tt>random</tt>, rovnako ako aj " "trieda <tt>Random</tt> (==<tt>random.Random</tt>)." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Zahrnúť uložené vyhľadávania" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 Uložiť výsledky uloženého vyhľadávania ako súčasť inej požiadavky." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: názov-vyhľadávania)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Unikátny dopyt" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Filtrujte výsledky vyhľadávania podľa unikátnych značiek." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unikátne: značka)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox je v poriadku. Používa sa jediný prehrávač (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Nepodarilo sa pripojiť k %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Názov hostiteľa:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Meno používateľa:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Heslo:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Priečinok knižnice, ku ktorému sa server pripája" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Cesta ku knižnici:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Overiť nastavenie" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Server Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Ladiť" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Server Squeezebox na {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "nestotožnený server Squeezebox" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "nestotožnený prehrávač Squeezebox: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Vyberte Squeezebox prehrávač" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Našiel sa server Squeezebox.\n" "Vyberte prehrávač" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Prispôsobiť obrázok _oknu" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Viď reťazce názvov súborov obrázkov v nastavení „[plugins] cover_filenames“" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Upraviť obrázok po uložení" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "_Názov súboru:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Ukladanie zlyhalo" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Nepodarilo sa uložiť „%s“." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Chyba HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Nástroj na sťahovanie obrázkov albumov" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "z %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Rozlíšenie: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Veľkosť: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Obmedzenie na istý počet najlepších výsledkov pre každý nástroj" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Hľadať" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Vyhľadáva sa…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Hotovo" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Stiahnuť obrázok albumu" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Sťahuje obrázky albumov z rôznych internetových stránok." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Zdroje" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 na ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Prevádza značky APEv2 na značky ID3v2. Pôvodné APEv2 značky sa po prevode " "odstránia." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Prejsť na záložku" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Spravuje záložky vo vybraných súboroch." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Upraviť záložky…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Žiadne záložky" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "Prehľadávanie MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Opätovne označkuje album na základe vyhľadávania v MusicBrainz." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Pre značku „date“ použiť len rok" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "V prípade potreby zapísať „_albumartist“" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Zapísať značky na triedenie umelcov" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Zapísať _obvyklé značky MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Zapísať značku „labelid“" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Názov súboru" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Skladba" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Názov" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Umelec" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "Prehľadávanie MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Požiadavka:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Hľadať" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Výsledky <i>(potiahnutím zmeníte poradie)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Zadajte požiadavku." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Vyskytla sa chyba. Skúste to znova." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Načítavajú sa výsledky…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Nenašli sa žiadne výsledky." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Príkazový riadok Pythonu" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktívny príkazový riadok Pythonu. Otvorí nové okno." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} pre {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Bočný panel príkazového riadka Pythonu" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Bočný panel s interaktívnym príkazovým riadkom Pythonu, ktorý umožňuje " "pristupovať k označeným skladbám v hlavnom okne." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "V základe môžete pristupovať k nasledovným objektom:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Váš súčasný pracovný adresár je:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Dokončovanie" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Stiahnuť obrázok albumu" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Sťahuje vysokokvalitné obaly albumov pomocou doplnkov pre obaly Quod Libet." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klasika" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Široký priestor" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Sťahovanie obrázkov albumov" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Načítava sa %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Nenašlo sa nič pre albumy:\n" "%(albums)s.\n" "\n" "Používaní poskytovatelia:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Nenašli sa žiadne obrázky albumov" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Veľkosť náhľadu" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Uložiť cieľ" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Ak ešte nie je v JPEG formáte, previesť obrázok do vysokokvalitného JPEG s " "rovnakými rozmermi" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Uložiť ako JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Príkaz" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "názov" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Názov tohto príkazu" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "príkaz" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Príkaz shellu, ktorý sa má spustiť" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parameter" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Ak je uvedený, parameter, ktorého výskyty v príkaze sa nahradia používateľom " "poskytnutou hodnotou, napr. pri použití „PARAM“ budú všetky výskyty " "„{PARAM}“ vo vašom príkaze nahradené hodnotou, o ktorú bude používateľ pri " "spustení požiadaný" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL vzor, napr. <~filename>, ktorý sa použije pri výpočte hodnoty pre príkaz. " "V prípade zoznamov prehrávania je tiež možné použiť virtuálne značky " "<~playlistname> a <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "jedinečný" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Ak je nastavené, všetky duplicitne vypočítané hodnoty vzoru sa odstránia" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "najvyšší možný počet parametrov" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Najvyšší možný počet parametrov, ktorý možno naraz odovzdať príkazu (ako " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "obrátiť" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Ak je nastavené, zoznam parametrov sa obráti" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Vstupná hodnota" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Hodnota pre %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Vlastné príkazy" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Spúšťa vlastné príkazy (v dávkach ak je to nutné) na skladbách s použitím " "ich značiek." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Upraviť vlastné príkazy" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Nepodarilo sa vykonať vlastný príkaz %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplicitná skupina" msgstr[1] "%d duplicitné skupiny" msgstr[2] "%d duplicitných skupín" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Zbaliť / Rozbaliť všetko" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Duplicitný kľúčový výraz je „%s“" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Prehliadač duplikátov" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Vyhľadáva a zobrazuje podobne označkované verzie skladieb." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Prijíma výrazy s QL značkami ako napríklad <tt>~artist~title</tt> alebo " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Zoskupiť duplikáty podľa:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplicitný kľúč" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Odstrániť _biele znaky" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Odstrániť _diakritiku" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Odstrániť _interpunkciu" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Nezohľadňovať _veľkosť písmen" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Zhodujúce sa možnosti" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Upraviť počet prehratí" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Upraviť <tt>~#playcount</tt> a <tt>~#skipcount.</tt> skladby.\n" "\n" "Pri výbere viacerých skladieb sa počty neprepíšu ale navýšia.\n" "\n" "Nastavením <tt>~#playcount</tt> skladby na 0 sa hodnoty <tt>~#lastplayed</" "tt> a <tt>~#laststarted</tt> stratia. Avšak, nastavenie počtu prehratí ešte " "nikdy neprehratej skladby na kladnú hodnotu neovplyvní časy prehrávania." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Počet prehratí" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Počet preskočení" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Vybratých viacero súborov." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Počty sa budú zvyšovať." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Upraviť vložené obrázky" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Pridáva, odstraňuje alebo nahrádza vložené obrázky." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Vložiť" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "Vybrať obrázok na vloženie do %d stopy" msgstr[1] "Vybrať obrázok na vloženie do %d stôp" msgstr[2] "Vybrať obrázok na vloženie do %d stôp" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Odstrániť všetky obrázky" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Vložiť súčasný obrázok" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Vybrať Obrázok…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Nastaviť presné hodnotenie" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Umožňuje nastavovať číselné hodnotenie skladby." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Zadajte požadované hodnotenie v rozmedzí od 0,0 do 1,0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtrovať ktorúkoľvek značku" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Vytvára výrazy vyhľadávania na základe značiek vybraných skladieb." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtrovať adresár" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Vyfiltruje priečinok v novom okne prehliadača." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Vyhľadávanie podľa zvukového odtlačku" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Vyhľadáva údaje o skladbách prostredníctvom zvukového odtlačku." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Odovzdať zvukový odtlačok" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Vytvára zvukové odtlačky pomocou Chromaprintu a odovzdáva ich na acoustid." "org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Chýbajúci kľúč API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Pre odosielanie odtlačkov musíte zadať API kľúč acoustid.org v nastaveniach " "zásuvného modulu." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Vyžiadať kľúč API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _kľúč:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "Internetová služba AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Zaradené do fronty" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Vyhodnocuje sa" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Vyhľadávanie" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Zapísať" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Vydanie" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Zapísať značky MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Zoskupiť podľa adresára" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Režim albumu" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Zapísať značky týkajúce sa albumu a pokúsiť sa zúžiť počet rôznych vydaní " "albumu" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Vytvárajú sa odtlačky:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Podrobnosti" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Odovzdať" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Skladby musia mať buď <i><b>musicbrainz_trackid</b></i>, alebo značky " "<i><b>artist</b></i> / <i><b>title</b></i> / <i><b>album</b></i> aby ich " "bolo možné odovzdať." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Odtlačky:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Skladby s MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Skladby s dostatočnými značkami:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Skladby na odovzdanie:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Hotovo. %(to-send)d/%(all)d skladieb na odovzdanie." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Odovzdávanie odtlačkov:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Odovzdáva sa…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Aktualizovať značky v súboroch" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Aktualizovať upravené značky v súboroch. Týmto sa zaistí, že počty prehratí " "a hodnotenia sú aktuálne." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Exportovať do HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Vyexportuje zoznam vybraných skladieb do HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Odoslať do iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Nahráva skladby do iRiver iFP zariadení." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Nenašlo sa žiadne iFP zariadenie" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Nepodarilo sa spojiť s vašim iFP zariadením. Overte, či je zariadenie " "zapnuté a pripojené, a či máte nainštalovaný ifp-line (http://ifp-driver.sf." "net)." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Nahráva sa %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Nie je možné nahrať %s. Zariadenie môže mať nedostatok miesta alebo je " "vypnuté." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Chyba nahrávania" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Exportovať údaje používateľa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Exportovať značky" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Exportovať značky a údaje používateľa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Exportovať zdroje súborov a údaje používateľa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Exportovať zdroje súborov a značky" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Exportovať zdroje súborov, značky a údaje používateľa" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "Import / Export" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Nahráva a exportuje značky a používateľské údaje stôp." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "Viac podrobností" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Pojem „údaje používateľa stopy“ zahŕňa zoznamy skladieb, v ktorých sú " "vybraté stopy, a nasledujúce metadáta:\n" "\n" "%s\n" "\n" "Uvedomte si, že všetko čo sa rozhodnete exportovať sa zohľadní aj pri " "načítaní. Ak ste vyexportovali názvy súborov (bez prípon), potom sa vybrané " "súbory pri načítaní premenujú.\n" "\n" "Po vyexportovaní albumu môžete údaje načítať do inej verzie albumu. Poradie " "a počet skladieb sa môžu líšiť. Doplnok priraďuje exportované údaje k novým " "skladbám a to aj v prípade, že sa názvy skladieb mierne líšia. Automatická " "zhoda nie je vždy správna, takže je lepšie zachovať čo najväčšiu podobnosť " "hodnôt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "Interakcia s používateľom pri načítaní" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Vyžadovať potvrdenie ak sa počet stôp líši" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Vyžadovať potvrdenie ak sa počet albumov líši" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Percentuálna hodnota, ktorá ak nebude dosiahnutá, tak bude používateľ musieť " "ručne overiť a prípadne aj nastaviť, ktorá s ktorou stopou majú byť " "spárované." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Podobnosť stôp:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Podobnosť albumov:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Exportovať súbory" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Zapísať úhľadný a čistý JSON (pomalšie)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Zmazať súbory exportu po ich načítaní" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Načítať" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Otvoriť priečinok exportu" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Disky" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Stopy" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Umelci" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Koniec cesty" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Spárovať albumy" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Pokračovať" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "Niet čo načítať" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Predtým než budete môcť niečo načítať, musíte najprv niečo exportovať." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Index bol poškodený." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "Nepodarilo sa prečítať JSON v „%s“" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "Nepodarilo sa čítať „%s“" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Názov súboru" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Spárovať stopy" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Aktualizuje sa rebríček." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Niet čo aktualizovať." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Získava sa rebríček pre %s. týždeň." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Synchronizácia dokončená." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Chyba počas synchronizácie (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Synchronizácia s Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Aktualizuje štatistiky vašej knižnice s vašim profilom na Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Používateľské meno:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Vytvoriť značky na triedenie" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Prevádza mená umelcov a názvy albumov na názvy na triedenie, voľne." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "Exportovať ako súbor zoznamu prehrávania M3U / PLS" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exportuje skladby do zoznamu prehrávania M3U alebo PLS." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Používať relatívne cesty" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Používať úplné cesty" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "Zápis do %s zlyhal." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Opätovne načítať skladby" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Zisťuje zmeny súborov a opätovne načítava / odstraňuje skladby, ak je to " "potrebné." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Opätovne načítať skladby" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "Vyhodnocovač ReplayGain" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Stopa" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Priebeh" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Zosilnenie" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Vrcholová hodnota" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Je tu %(to-process)s album na aktualizáciu (z %(all)s)" msgstr[1] "Sú tu %(to-process)s albumy na aktualizáciu (z %(all)s)" msgstr[2] "Je tu %(to-process)s albumov na aktualizáciu (z %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Zosilnenie opätovného prehrávania" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Vyhodnocuje a aktualizuje údaje <a href=\"%(rg_link)s\">ReplayGain</a> " "pomocou GStreamera. Výsledky sú zoskupené podľa albumu." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "vždy" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "ak <b>akékoľvek</b> RG značky chýbajú" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "ak <b>album</b> RG značky chýbajú" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Spracovať albumy:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Jestvujúce značky" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Rozdeliť značky" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Súčasne oddeliť číslo disku od albumu a verziu od názvu." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Rozdeliť albumy" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Oddeliť číslo disku." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "nedostupné" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "Úderov za minútu:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Resetovať" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Vyťukať" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Počet ťuknutí za minútu" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Vyťukať tempo pre vybranú skladbu." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Vyhľadávanie na internete" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Vyhľadá webovú lokalitu podľa vášho výberu pomocou akýchkoľvek značiek " "skladieb.\n" "Podporuje vzory napr. %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Prehľadávať vzory URL" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Upraviť URL pre vyhľadávanie" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Nastaviť vyhľadávanie…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Vyhľadať značku na Wikipédii" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Otvorí okno prehliadača a zobrazí článok o značke vybranej piesne na " "Wikipédii." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Hľadať na %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Upraviť tagy" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Vyhľadávanie zlyhalo" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Značka „%s“ sa nenašla." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Knižnica" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Kontrola prípojných bodov" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Skenovanie knižnice" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Skenovanie %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Načítavajú sa súbory" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Presúvajú sa súbory knižnice" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Odstraňujú sa súbory knižnice" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "Pridanie sledovania pre %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "V starom zozname skladieb %(filename)r (s veľkosťou %(size).1f kB) sa " "nenašli žiadne skladby z knižnice." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "Zmenili ste koreňové adresáre knižnice, ale nie tento zoznam skladieb?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d zoznam skladieb sa nepodarilo konvertovať" msgstr[1] "%d zoznamy skladieb sa nepodarilo konvertovať" msgstr[2] "%d zoznamov skladieb sa nepodarilo konvertovať" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Hudobný prehrávač a správca hudobnej knižnice" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Nepodarilo sa načítať súbor: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Zobraziť zoznam značiek" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Zobraziť stručný výstup" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Stĺpce na zobrazenie a zoradenie v skrátenom režime (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Zobraziť tiež zoznam programovacích značiek" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Nedostatok parametrov" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Príliš mnoho parametrov" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Popis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Hodnota" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Zobraziť zoznam všetkých spoločných značiek" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopírovať značky z jedného súboru do druhého" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Zobraziť zmeny, bez vykonávania" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Preskočiť značky, ktoré nemožno zapísať" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Nedá sa skopírovať značka {tagname} do súboru: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Upraviť značky v textovom editore" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Úprava prerušená" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Spúšťanie textového editora „%(editor-name)s“ zlyhalo." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Nezistili sa žiadne zmeny" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Nastaviť značku a odstrániť jestvujúce hodnoty" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Nedá sa nastaviť %(tag)r pre %(format)s súbor %(file)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Odstrániť značky" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Hodnota je regulárny výraz" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Odstrániť všetky značky" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Nemožno zároveň použiť „--all“ aj „--regexp“" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Nedá sa odstrániť {tagname} z {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Odstrániť hodnotu" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Pridať hodnotu" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Nedá sa nastaviť %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Zobraziť podrobnosti o súbore" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Nastaviť poskytnutý obrázok ako hlavný vložený obrázok a odstrániť všetky " "ostatné vložené obrázky" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Nepodarilo sa načítať súbor obrázku: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Upravovanie obrázkov nie je podporované pre %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Odstrániť všetky vložené obrázky" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Vytiahnuť vložené obrázky do %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Cesta k priečinku, kde sa obrázky uložia (predvolene do pracovného priečinka)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Premenovať súbory na základe značiek" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Vyplniť značky na základe ciest k súborom" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Súbor" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Vyplniť čísla stôp pre všetky súbory" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Zobraziť značky na základe zadaného vzoru" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Zobraziť podrobnosti o použití" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "„%(column-id)s“ nie je platný názov stĺpca (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Neznáme" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "V poradí" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_V poradí" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Náhodne" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Náhodne" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Uprednostňovať lepšie hodnotené" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "Uprednostňovať _lepšie hodnotené" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Opakovať túto stopu" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Opakovať _túto stopu" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Opakovať všetky" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Opakovať _všetky" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Jedna skladba" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Jedna _skladba" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Prúd" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Ukladanie do vyrovnávacej pamäte" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Nepodarilo sa vytvoriť rúru GStreamera (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Nenašiel sa žiadny prvok GStreamera na spracovanie tohto formátu" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Formát: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "Zásuvný modul GStreamera „%(name)s“ sa nepodarilo spustiť" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Na prehrávanie je použitý výstupný kanál GStreamer. Ponechajte prázdne pre " "použitie predvoleného kanála. V prípade, že kanál obsahuje vývod, použije sa " "namiesto predvoleného." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Výstupná rúra:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Dĺžka medzipamäte:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Zakázať prehrávanie bez _medzier" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Zakázanie prehrávania bez medzier môže v niektorých verziách GStreamera " "predísť ťažkostiam pri zmene stopy" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Na prehrávanie použiť JACK, ak je dostupný" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Ak sa ho podarí zistiť, používa „jackaudiosink“ na prietok prehrávania" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "Automaticky sa pripojiť k výstupným zariadeniam JACK" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "Zaisťuje, že sa „jackaudiosink“ automaticky pripojí" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nenašiel sa žiaden zvukový vývod GStreamera. Vyskúšali sa: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Neplatná výstupná rúra GStreamera" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Nepodarilo sa vytvoriť zvukový výstup" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Zvukové zariadenie %r sa nenašlo. Preverte vaše nastavenie Xine v ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Nepodarilo sa nájsť modul „{module}“. Treba nainštalovať príslušný balík?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nepodarilo sa nájsť prvok GStreamera „{element}“." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Pre nastavenie ListenBrainz prejdite do okna Zásuvných modulov. Dovtedy sa " "údaje o počúvaní nebudú odovzdávať." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Príliš mnoho po sebe nasledujúcich neúspešných odovzdaní (%d). Prechádza sa " "do režimu offline. Prejdite do okna Zásuvných modulov a vynulujte " "ListenBrainz. Dovtedy sa údaje o počúvaní nebudú odovzdávať." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "Odovzdávanie do ListenBrainz" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Odovzdávať údaje o počúvaní do ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Používateľov _token:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "Značky:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Zoznam značiek oddelených čiarkami, ktoré sa majú zaradiť do odovzdania. V " "prípade potreby použite úvodzovky." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Skladby zhodujúce sa s týmto filtrom sa neodovzdajú." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Použiť zásuvný modul „%(name)s“ na %(count)s zoznam prehrávania?" msgstr[1] "Použiť zásuvný modul „%(name)s“ na %(count)s zoznamy prehrávania?" msgstr[2] "Použiť zásuvný modul „%(name)s“ na %(count)s zoznamov prehrávania?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Použiť zásuvný modul" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Použitie" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Začiatok" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Čas" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Názov záložky" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Záložky" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtre" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Nedávno _hrané" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Nedávno _pridané" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Všetky skladby" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Z práve prehrávaného žánru" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Od práve prehrávaného umelca" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Z práve prehrávaného albumu" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Náhodný _žáner" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Náhodný _umelec" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Náhodný _album" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "40 skladieb ktoré ste hrali najviac" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Názov:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Hodnota:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Uložené hodnoty" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Upraviť uložené hodnoty…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_maticky" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Režim stopy" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Režim albumu" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Stlmené" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain režim" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nový %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(neznáme)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Pridať…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Upraviť" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Výraz značky" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Výraz značky, napr. osoba:fakt alebo ~album~rok" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Zadajte novú značku" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Upraviť výraz značky" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Súbory:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Vybrané skladby sa odstránia z knižnice a ich súbory sa odstránia z disku." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Vybrané súbory sa odstránia z disku." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Navždy odstrániť %(file_count)d súbor?" msgstr[1] "Navždy odstrániť %(file_count)d súbory?" msgstr[2] "Navždy odstrániť %(file_count)d súborov?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Odstrániť súbory" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Vybrané skladby sa odstránia z knižnice a ich súbory sa presunú do koša." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Vybrané súbory sa presunú do koša." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Presunúť %(file_count)d súbor do koša?" msgstr[1] "Presunúť %(file_count)d súbory do koša?" msgstr[2] "Presunúť %(file_count)d súborov do koša?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Presunúť do koša" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Presúva sa %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Neporadilo sa presunúť do koša" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Presúvanie jedného alebo viacerých súborov do koša zlyhalo." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Odstraňuje sa %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Nepodarilo sa odstrániť súbory" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Odstraňovanie jedného alebo viacerých súborov zlyhalo." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Prehliadač" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Sťahovanie súborov" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "chýba v %d skladbe" msgstr[1] "chýba v %d skladbách" msgstr[2] "chýba v %d skladbách" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "rôzne v %d skladbe" msgstr[1] "rôzne v %d skladbách" msgstr[2] "rôzne v %d skladbách" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Rozdeliť na _viacero hodnôt" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Oddeliť disk od _albumu" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Oddeliť _verziu od názvu" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Oddeliť aranžéra od interpreta" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Oddeliť _interpreta od umelca" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Oddeliť _účinkujúceho od názvu" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Oddeliť _pôvodného umelca od názvu" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Pridať tag" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Zobraziť _programové tagy" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Používať všetky značky vrátane strojovo vytvorených, napr. značky " "MusicBrainz alebo Replay Gain" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "Ukázať _viacriadkové tagy" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "Ukázať potenciálne viacriadkové tagy (e.g 'lyrics') aj tu" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Obrátiť" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Uložiť" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Nastaviť" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Rozdeliť značku" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Kopírovať hodnoty" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Nepodarilo sa pridať tag" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "Nie je možné pridať %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Práve vybrané súbory nepodporujú viacero hodnôt pre %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Neplatný tag" msgstr[1] "Neplatné tagy" msgstr[2] "Neplatných tagov" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Neplatný tag %s\n" "\n" "Vybraný súbor nepodporuje editovanie tagu." msgstr[1] "" "Neplatné tagy %s\n" "\n" "Vybrané súbory nepodporujú editovanie tagov." msgstr[2] "" "Neplatných tagov %s\n" "\n" "Vybrané súbory nepodporujú editovanie tagov." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Neplatná hodnota" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Neplatná hodnota: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Tag môže byť nepresný" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s sa zmenili. Uloženie bez obnovenia knižnice by mohlo prepísať " "iné zmeny skladby." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Nepodarilo sa uložiť skladbu" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Uloženie %(file-name)s zlyhalo. Súbor je možno len pre čítanie, poškodený " "alebo nemáte práva na jeho zmenu." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Viac možností…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Späť" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Znovu" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_O programe" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Vyhľadať aktualizácie…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Zásuvné moduly" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s a %(count)s ďalší" msgstr[1] "%(title)s a %(count)s ďalšie" msgstr[2] "%(title)s a %(count)s ďalších" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Predvoľby Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Priečinky" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nový priečinok…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Vybrať všetky podpriečinky" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nová zložka" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Vložte názov novej zložky:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Nepodarilo sa vytvoriť priečinok" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Nepodarilo sa odstrániť priečinok" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Skladby" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "od %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Skladba %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Terajšia _skladba" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Upraviť zobrazenie…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Nie sú vybrané žiadne skladby." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Žiadne skladby" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informácie" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Text" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Vytvorené v %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "interpret" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "interpreti" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "hudobníci" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nikdy" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d raz" msgstr[1] "%(n)d razy" msgstr[2] "%(n)d krát" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "pridané" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "naposledy prehrané" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "prehranie" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "preskočenie" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "hodnotenie" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "cesta" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "dĺžka" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "formát" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "kódovanie" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "veľkosť súboru" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "upravené" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Dodatočné" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d vybraná" msgstr[1] "%d vybrané" msgstr[2] "%d vybraných" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Skladba nedostupná" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d skladba bez albumu" msgstr[1] "%d skladby bez albumu" msgstr[2] "%d skladieb bez albumu" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Vybraná diskografia" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d skladba bez interpreta" msgstr[1] "%d skladby bez interpreta" msgstr[2] "%d skladieb bez interpreta" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumy" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Celková dĺžka:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Celková veľkosť:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Súbory" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Zobraziť online" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nenájdený žiadny text pre túto skladbu." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Ste si istí, že chcete odstrániť všetky skladby?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Vybrané skladby sa odstránia z knižnice." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Odkryť" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Odkryť" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Overte, či sa stĺpce na ľavej strane približne zhodujú s tými na pravej " "strane. Ak sa nezhodujú, tu môžete zmeniť poradie riadkov (použite _ v " "riadkoch, ktoré by sa nemali porovnávať):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Poradie na pravej strane:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Zahodiť zmeny v tagoch?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Tagy boli zmenéné ale nie uložené. Uložiť tieto súbory, alebo zahodiť zmeny?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Obrátiť" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Súbor existuje" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Nahradiť %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Nahradiť súbor" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Činné úlohy" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d úloh prebieha" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Prepnúť náhodné prehrávanie" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Prepnúť opakovanie" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Udalosti" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Poradie prehrávania" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Úprava" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Premenovávanie" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Odosielanie požiadaviek" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Obaly" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Chyby zásuvných modulov" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Akýkoľvek stav" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Povolené" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Zakázané" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Žiadna kategória" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Akákoľvek kategória" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Nenájdené žiadne zásuvné moduly." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Zásuvné moduly" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtrovať podľa stavu zásuvného modulu / značky" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtrovať podľa druhu zásuvného modulu" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtrovať podľa názvu alebo popisu zásuvného modulu" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Zobraziť _chyby" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Skladba" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Zoskupenie" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Umelec" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Album" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Názov súboru" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Dľžka" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Automaticky _preskočiť na hrajúcu skladbu" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Keď sa prehrávaná skladba zmení, posunúť sa k nej v zoznam skladieb" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "_Triediť skladby pri úprave značiek" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "Automaticky vytriediť skladby v zoznam pri zmene značiek" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Vždy povoliť triedenie" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" "Povoliť triedenie podľa hlavičiek stĺpcov, a to aj pre zoznamy skladieb atď" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Ostatné:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Upraviť…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Pridať alebo odobrať dodatočné hlavičky stĺpcov" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Viditeľné stĺpce" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Názov obsahuje _verziu" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album obsahuje podnázov _disku" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Umelec obsahuje všetkých _tvorcov" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Názov súboru obsahuje _priečinok" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Nastavenie stĺpca" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Aktualizovať stĺpce" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Použiť terajšie nastavenie na zoznam skladieb pridajúc nové stĺpce na koniec" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Zoznam skladieb" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Upraviť stĺpce" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Celková dĺžka" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globálny filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Použiť túto požiadavku spolu s ostatnými" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Vyhľadávanie" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Prehliadače" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Potvrdiť _viaceré hodnotenia" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Požiadať o potvrdenie pred zmenou hodnotenia viacerých skladieb naraz" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Povoliť _hodnotenie jedným kliknutím" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Povoliť hodnotenie kliknutím na stĺpec hodnotenia v zozname skladieb" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Hodnotenia" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Uprednostňovať _vložené obrázky" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Uprednostňovať obrázky vložené v zvukových súboroch (ak je to možné) pred " "ostatnými zdrojmi" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Súbory obrázku albumu, ktoré sa majú použiť ak sú dostupné (špeciálne znaky " "sú podporované). Ak chcete zadať viac ako jeden súbor, oddeľte ich čiarkami." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Preferované názvy súborov obrázkov" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Obrázok albumu" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Prehrávanie" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Nastavenie výstupu" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ak nie je dostupný žiaden údaj Replay Gain o skladbe, vynásobiť hlasitosť " "touto hodnotou" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Spätné zosilnenie:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Vynásobiť hlasitosť všetkých skladieb touto hodnotou, pokiaľ nedôjde k " "zníženiu kvality" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Predzosilnenie:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Povoliť prispôsobenie hlasitosti Replay Gain" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Prispôsobenie hlasitosti Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Pokračovať v prehrávaní pri spustení" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Ak bolo pri zatváraní spustené prehrávanie, automaticky pokračovať v " "prehrávaní pri ďalšom spustení" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Predvolené hodnotenie:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Stupnica hodnotenia:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Faktor Bayeseovského priemeru (C) pre zlúčené hodnotenia.\n" "0 znamená bežný priemer, vyššie hodnoty znamenajú, že albumy s menej " "skladbami budú mať menšie odchýlky v hodnotení. Zmena tejto hodnoty spustí " "prepočítanie hodnotenia všetkých albumov." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "Hodnota _Bayeseovského priemeru:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Hodnotenia a počty hraní budú uložené v značkách pre túto adresu " "elektronickej pošty" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "_Automaticky ukladať zmeny značiek" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Pri upravovaní viacerých súborov, uložiť zmeny v značkách bez potvrdenia" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Množina deliacich znakov, ktoré sa použijú pri oddeľovaní hodnôt značiek v " "nástroji na úpravu značiek. Hodnoty v zozname sú oddelené medzerou." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Rozdeliť _značku na:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Množina deliacich znakov, ktoré sa použijú pri výbere podznačiek zo značiek " "v nástroji na úpravu značiek. Hodnoty v zozname sú oddelené medzerou a každá " "hodnota musí obsahovať len dva znaky." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Rozdeliť _podznačku na:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Značky" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Editácia tagov" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Aktualizácia na nové hodnotenia" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Prehľadať knižnicu" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Skontrolovať zmeny v knižnici" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Opätovne _zostaviť knižnicu" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Opätovne načítať všetky skladby do knižnice. Môže to trvať dlho." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Skryté skladby" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Prehľadať knižnicu _pri spustení" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "_Sledovať zmeny adresárov" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Sledovať adresáre knižnice pre pridanie, zmazanie a premenovanie externého " "súboru." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Prehľadať priečinky" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s a %(count)d ďalší" msgstr[1] "%(title)s a %(count)d ďalšie" msgstr[2] "%(title)s a %(count)d ďalších" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Vlastnosti" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Fronta" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Vyčistiť frontu" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Zakázať frontu - fronta sa pri prehrávaní nebude brať do úvahy" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Nestála" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Po prehratí odstrániť skladby z fronty" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Stála" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Po prehratí ponechať skladby vo fronte" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Režim" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Zastaviť na konci" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d skladba (%(time)s)" msgstr[1] "%(count)d skladby (%(time)s)" msgstr[2] "%(count)d skladieb (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Prehliadať knižnicu" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Prepnúť viditeľnosť fronty" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Chyba prehrávania" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Nastaviť priečinky knižnice?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" "Zatiaľ nemáte nastavenú žiadnu hudobnú knižnicu. Chcete ju nastaviť teraz?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Nie teraz" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Nastaviť" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Neporadilo sa pridať skladby" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s používa nepodporovaný protokol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Preskočiť na hrajúcu skladbu" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Súbor" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Skladba" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Zobraziť" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Prechádzať" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Ovládanie" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Pomocník" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Pridať priečinok…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Pridať súbor…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Pridať umiestnenie…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Upraviť záložky…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Zastaviť" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Zastaviť po tejto skladbe" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Klávesové skratky" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Online pomocník" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Prehľadávať pomocníka" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Pridať umiestnenie" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Vložte umiestnenie audio súboru:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Nepodarilo sa pridať umiestnenie" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s nie je platné umiestnenie." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Pridať hudbu" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Pridať priečinky" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Hudobné súbory" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Pridať súbory" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Naozaj chcete zaradiť %d skladbu?" msgstr[1] "Naozaj chcete zaradiť %d skladby?" msgstr[2] "Naozaj chcete zaradiť %d skladieb?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Zaradiť" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Ste si istí, že chcete zmeniť hodnotenie všetkých %d skladieb?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Uložené hodnotenia sa stratia" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Odstrániť hodnotenie" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Hodnotenie vybraných skladieb sa zmení na %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Zmeniť _hodnotenie" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Nahradiť medzery _podtržítkami" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Nahradiť delenie bodkočiarkou alebo dvojbodkou pomlčkou" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "napr. \"iv: allegro.flac\" → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Odstrániť znaky nekompatibilné s _Windows" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Odstrániť _diakritiku" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Odstrániť ne-_ASCII znaky" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Používať len _malé písmená" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Premenovať súbory" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Náhľad" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Názvy súborov" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Presunúť obrázok albumu" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Viď reťazce vyhľadávania obrázkov v nastavení „[albumart] filenames“" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Prepísať obrázok albumu v cieli" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Odstrániť prázdne priečinky" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Obrázky albumov" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nový názov" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Nepodarilo sa premenovať súbory" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Premenovanie %(old-name)s na %(new-name)s zlyhalo. Možno cieľový súbor už " "jestvuje alebo nemáte právo vytvoriť nový súbor či odstrániť starý." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorovať _všetky chyby" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Zastaviť" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Pokračovať" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Cesta nie je absolútna" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Vzor\n" "\t%s\n" "obsahuje / ale nezačína v koreňovom priečinku. Aby ste sa vyhli nesprávne " "pomenovaným priečinkom, pridajte na začiatok vášho vzoru / alebo ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Skladby v týchto priečinkoch sa pri obnovení knižnice pridajú do knižnice" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Nový priečinok sa prehľadá po pridaní" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Všetky skladby vo vybraných priečinkoch sa tiež odstránia z knižnice" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Presunúť" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Presunúť koreň prehľadávania (ale nie súbory), ako aj údaje všetkých " "zahrnutých stôp." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "Odstrániť {dir!r} so všetkými stopami?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Odstrániť {n} ciest knižnice aj so stopami?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Odstrániť cestu knižnice?" msgstr[1] "Odstrániť cesty knižnice?" msgstr[2] "Odstrániť ciest knižnice?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Odstrániť" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Vyberte adresáre" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Vybrať tento priečinok" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "Vybrať terajší / nový priečinok pre {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Týmto sa presunú QL údaje.\n" "\n" "{old!r} → {new!r}\n" "\n" "Zvukové súbory samotné sa nepresunú.\n" "Avšak, odporúčame vám vytvoriť si zálohu (vrátane Quod Libet súboru „songs“)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Presunúť koreň prehľadávania {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "Dobre, presunúť ho!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Uložené vyhľadávania" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Upraviť uložené vyhľadávania…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Prehľadávať vašu knižnicu pomocou čistého textu alebo QL požiadaviek" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Hľadať po _dopísaní" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Zobraziť výsledky vyhľadávania potom, čo používateľ prestane písať" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Hranica:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Váha" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Pridať požiadavku" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Pridať QL požiadavku alebo čistý text pre spojenie dohromady" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Zobraziť zostávajúci čas" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Hlavné okno" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Posunúť o 10 sekúnd dozadu" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Posunúť o 10 sekúnd dopredu" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Zamerať výraz vyhľadávania" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Vynulovať filtre a preskočiť na prehrávanú skladbu" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Otvoriť okno s podrobnosťami pre vybrané skladby" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Otvoriť nástroj na úpravu značiek pre vybrané skladby" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Zaradiť vybrané skladby do fronty" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Vymazať vybrané skladby" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Zobraziť pole rýchleho vyhľadávania" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Ľavé kliknutie na hlavičku stĺpca" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Pridať stĺpec do zoznam stĺpcov, podľa ktorých sa má triediť" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Stromové usporiadanie priečinkov" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Zbalí položku alebo vyberie nadradenú položku" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Rozbaliť položku" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Textové vstupy" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Vrátiť poslednú zmenu" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Znova vykonať vrátenú zmenu" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Vybrať všetky skladby vo všetkých paneloch" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filter na %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Všetky _hlavičky" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Hlavičky skladby" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Hlavičky albumu" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Hlavičky ľudí" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Hlavičky dátumu" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Hlavičky súboru" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Hlavičky produkcie" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Prispôsobiť hlavičky…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Rozšíriť stĺpec" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "Odstrániť skladbu: \"%(title)s\" z knižnice?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Odstrániť %(count)d skladby z knižnice?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Odstrániť z knižnice" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Použiť zásuvný modul „%(name)s“ na %(count)d skladbu?" msgstr[1] "Použiť zásuvný modul „%(name)s“ na %(count)d skladby?" msgstr[2] "Použiť zásuvný modul „%(name)s“ na %(count)d skladieb?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "Použiť zásuvný modul „%(name)s“ na %(count)d album?" msgstr[1] "Použiť zásuvný modul „%(name)s“ na %(count)d albumy?" msgstr[2] "Použiť zásuvný modul „%(name)s“ na %(count)d albumov?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Nastaviť zásuvné moduly…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Pridať do _fronty" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Odstrániť z knižnice…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Nepodarilo sa zobraziť súbory" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "Chyba pri zobrazovaní súborov, alebo žiaden program na ich zobrazenie." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Zobraziť v správcovi súborov" msgstr[1] "_Zobraziť %(total)d súbory v správcovi súborov" msgstr[2] "_Zobraziť %(total)d súborov v správcovi súborov" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Stiahnuť súbor…" msgstr[1] "_Stiahnuť %(total)d súbory…" msgstr[2] "_Stiahnuť %(total)d súborov…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "úspešný" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "neúspešný" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "Sťahovanie dokončené" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Stiahnuť {name!r} do" msgstr[1] "Stiahnuť {total} súbory do" msgstr[2] "Stiahnuť {total} súborov do" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Stiahnuť sem" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Nahradiť _podržítko medzerami" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Každé slovo začína veľkým písmenom" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Rozdeliť na viacero hodnôt" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Tagy z cesty" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Nahradiť pôvodné tagy" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Pridať k pôvodným tagom" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Vzor\n" "\t%s\n" "je neplatný. Možno obsahuje rovnakú značku dvakrát alebo má neuzavreté " "zátvorky (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Vzor, ktorý ste zadali je neplatný. Uistite sa, že ste zadali < a > " "ako \\< a \\>, a že sú vaše značky vyvážené.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Upraviť zobrazenie" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Čísla skladieb" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Začať _od:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Celkový počet:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Prehrať/Pozastaviť" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Predchádzajúca" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "a %d viac…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Ukladanie skladieb, ktoré ste zmenili." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d uložených skladieb\n" "(zostáva %(remaining)s)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s z %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Vyhľadávajú sa aktualizácie" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Pripájanie zlyhalo" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Už používate najnovšiu verziu %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Je dostupná nová verzia %(new-version)s\n" "\n" "Teraz používate verziu %(old-version)s\n" "\n" "Navštívte <a href='%(url)s'>internetovú stránku</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Prázdny zoznam prehrávania" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Zoznamy prehrávania musia mať názov" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Zoznam prehrávania s názvom %(name)s už jestvuje v %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Vložené obaly albumov" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Používa obaly vložené do zvukových súborov." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Obal zo súborového systému" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Používa bežne pomenované obrázky nachádzajúce sa v bežných priečinkoch pri " "skladbách." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Obrázky obalov" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Prehľadávanie poskytovateľov obrázkov albumov" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Zobraziť krátku informáciu o použití" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Zobraziť verziu a copyright" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Zobraziť údaje ladenia" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Použitie: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[možnosti]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Voľba %r nebola rozpoznaná." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Voľba %r vyžaduje parameter." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r nie je jedinečná predpona." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekunda" msgstr[1] "%s sekundy" msgstr[2] "%s sekúnd" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Žiadna informácia o čase" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunda" msgstr[1] "%d sekundy" msgstr[2] "%d sekúnd" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minúta" msgstr[1] "%d minúty" msgstr[2] "%d minút" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hodina" msgstr[1] "%d hodiny" msgstr[2] "%d hodín" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d deň" msgstr[1] "%d dni" msgstr[2] "%d dní" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d rok" msgstr[1] "%d roky" msgstr[2] "%d rokov" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "Každé slovo s veľkým začiatočným písmenom?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Dátum musí byť vo formáte 'RRRR', 'RRRR-MM-DD' alebo 'RRRR-MM-DD HH:MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Zosilnenia Replay Gain musia byť zadané vo formáte „x.yy dB“." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Vrcholové hodnoty Replay Gain musia byť zadané vo formáte „x.yy“." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID musia byť v UUID formáte." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Stav vydania MusicBrainz musí byť „official“, „promotional“, alebo „bootleg“." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Jazyk musí byť v tvare troj-písmenového kódu ISO 639-2" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Ukladá sa %d súbor" msgstr[1] "Ukladajú sa %d súbory" msgstr[2] "Ukladá sa %d súborov" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Automatické ukladanie" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Neporadilo sa editovať skladbu" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Uloženie %s zlyhalo. Súbor môže byť len na čítanie, poškodený alebo nemáte " "práva na jeho zmenu." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Neplatné kódovanie]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranžér" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranžéri" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "usporiadanie" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "komentár" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "skladateľ" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "skladatelia" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "skladateľ" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenti" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigent" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "dátum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "popis" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "žáner" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "žánre" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "hudobník" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "umelecké prevedenie" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "zoskupenie" #: quodlibet/util/tags.py:98 msgid "language" msgstr "jazyk" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licencia" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "autor textu" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "autori textu" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "text piesne" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizácia" #: quodlibet/util/tags.py:104 msgid "title" msgstr "názov" #: quodlibet/util/tags.py:105 msgid "version" msgstr "verzia" #: quodlibet/util/tags.py:106 msgid "website" msgstr "webstránka" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "interpret albumu" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "podnázov disku" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "skladba" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "katalógové číslo" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "originálny dátum vydania" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "pôvodný album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "pôvodný interpret" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "dátum nahrania" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "krajina vydania" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "pôvodný kľúč" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "ID nahrávky MusicBrainz" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "ID vydania stopy MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "ID vydania MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "ID umelca MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "ID umelca vydania MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "TRM ID MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz status albumu" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz typ albumu" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "ID skupiny vydania MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "zosilnenie stopy" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "vrcholová hodnota stopy" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "zosilnenie albumu" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "vrcholová hodnota albumu" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "základná hlasitosť" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "disky" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "skladby" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "naposledy spustené" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "celý názov" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "prípojný bod" #: quodlibet/util/tags.py:166 msgid "people" msgstr "ľudia" #: quodlibet/util/tags.py:168 msgid "year" msgstr "rok" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "rok pôvodného vydania" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "záložka" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bitová hĺbka" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "formát súboru" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "zoznamy prehrávania" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "vzorkovacia frekvencia" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "počet kanálov" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "triedenie" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "úlohy" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor audio tagov" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Upraviť tagy vo vašich audio súboroch" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Hudobný prehrávač" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Počúvajte, prehliadajte, alebo upravujte svoju hudobnú kolekciu" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso je nástroj na úpravu značiek s rovnakým rozhraním ako Quod Libet. " "Umožňuje zobrazovať a upravovať akékoľvek značky v súbore, a to pre všetky " "podporované formáty." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Podporované formáty súborov zahŕňajú Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, " "MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet je program na správu hudby. Poskytuje niekoľko rozličných " "spôsobov zobrazenia vašej hudobnej knižnice ako aj podporu internetového " "rozhlasu a zvukových prúdov. Je mimoriadne dobre vybavený na prehľadávanie " "ako aj správu údajov a značiek skladieb." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Vyexportuje zoznam prehrávania do zoznamu prehrávania Sonos pokiaľ obidva " #~ "zdieľajú usporiadanie priečinka." #~ msgid "Export to Sonos playlist" #~ msgstr "Exportovať do zoznamu prehrávania Sonos" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Neporadilo sa pridať <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Neplatné tagy" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Neplatné značky <b>%s</b>\n" #~ "\n" #~ "Práve vybrané súbory nepodporujú tieto značky." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Automaticky ohodnotiť skladby pri prehratí alebo preskočení. Táto funkcia " #~ "používa „zrýchlený“ algoritmus z vuxu od Briana Nelsona." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekúnd" #~ msgid "Startup" #~ msgstr "Spustenie" #~ msgid "Audio Feeds" #~ msgstr "Zdroje zvukových záznamov" #~ msgid "_Audio Feeds" #~ msgstr "_Zdroje zvukových záznamov" #~ msgid "New" #~ msgstr "Nový" #~ msgid "Automatic Library Update" #~ msgstr "Automatická aktualizácia knižnice" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Udržiava vašu knižnicu aktuálnu pomocou inotify. Vyžaduje %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Umožňuje ovládanie Quod Libet pomocou špecifikácie rozhrania MPRIS 2 D-" #~ "Bus." #~ msgid "Searching for lyrics…" #~ msgstr "Vyhľadávanie textov piesní…" #, fuzzy #~ msgid "<artist>" #~ msgstr "interpret" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "názov" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importovať playlist" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importovať playlist" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Informácie" #~ msgid "Unsupported file type" #~ msgstr "Nepodporovaný typ súboru" #~ msgid "Unable to add station" #~ msgstr "Nepodarilo sa pridať stanicu" #~ msgid "Device Properties" #~ msgstr "Vlastnosti zariadenia" #~ msgid "Device:" #~ msgstr "Zariadenie:" #~ msgid "Not mounted" #~ msgstr "Nepripojené" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Prípojný bod:" #~ msgid "Media Devices" #~ msgstr "Média zariadenia" #~ msgid "_Media Devices" #~ msgstr "_Média zariadenia" #~ msgid "_Eject" #~ msgstr "_Vysunúť" #, fuzzy #~ msgid "_Properties" #~ msgstr "Vlastnosti" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> použité, <b>%s</b> dostupné" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> nie je pripojené." #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Kopírovanie <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "Neporadilo sa kopírovať skladbu" #~ msgid "There is not enough free space for this song." #~ msgstr "Na túto skladbu nie je dost voľného miesta" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> nemôže byť skopírované." #~ msgid "Unable to delete songs" #~ msgstr "Nepodarilo sa vymazať skladby" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Odstraňovanie <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> nemôže byť odstránené." #~ msgid "Unable to delete song" #~ msgstr "Nedá sa odstrániť skladba" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Vysúvanie <b>%s</b> zlyhalo." #~ msgid "Unable to eject device" #~ msgstr "Neporadilo sa vysunúť zariadenie" #~ msgid "Search Library" #~ msgstr "Vyhľadávať v knižnici" #~ msgid "_Search Library" #~ msgstr "_Vyhľadávať v knižnici" #~ msgid "Rate the playing song" #~ msgstr "Ohodnotiť hrajúcu skladbu" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Zobraziť alebo skryť hlavný zoznam skladieb" #~ msgid "Unknown Device" #~ msgstr "Neznáme zariadenie" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: '%s' nie je unikátny prefix." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Neplatná hodnota" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Formát názvu súboru:" #, fuzzy #~ msgid "_Clear" #~ msgstr "Chyby zásuvných modulov" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Text" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Vyčistiť vyhľadávanie" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Text" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Text" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Žiadne skladby" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Prehliadače" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Nepodarilo sa vytvoriť zložku" #~ msgid "Audio device: %s" #~ msgstr "Audio zariadenie: %s" #~ msgid "Downloads" #~ msgstr "Sťahovania" #~ msgid "Size" #~ msgstr "Veľkosť" #~ msgid "_Download" #~ msgstr "_Sťahovanie" #~ msgid "_Copy to Device" #~ msgstr "_Kopírovať na zariadenie" #, fuzzy #~ msgid "browsers" #~ msgstr "Prehliadače" #~ msgid "Unable to download lyrics." #~ msgstr "Neporadilo sa stiahnuť text." #~ msgid "Set or toggle the playback order" #~ msgstr "Nastaviť alebo prepnúť poradie prehrávania" #~ msgid "Uninitialized iPod" #~ msgstr "Neinicializovaný iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Chcete vytvoriť prázdnu databázu na tomto iPod-e?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Hlasitosť (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Kombinovať tagy z _viacerých hodnôt" #~ msgid "Capacity:" #~ msgstr "Kapacita:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Neporadilo sa uložiť iPod databázu" #~ msgid "Unable to save iPod database" #~ msgstr "Neporadilo sa uložiť iPod databázu" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "Hlavičky _skladby" #~ msgid "Shuffle" #~ msgstr "Náhodne" #~ msgid "Weighted" #~ msgstr "Podľa váhy" #~ msgid "_Weighted" #~ msgstr "_Podľa váhy" #~ msgid "_One Song" #~ msgstr "_Jedna skladba" #~ msgid "Restart the playlist when finished" #~ msgstr "Reštartovať playlist po skončení" #~ msgid "Disable Browser" #~ msgstr "Vypnúť prehliadač" #~ msgid "_Disable Browser" #~ msgstr "_Vypnúť prehliadač" #, fuzzy #~ msgid "Force Write" #~ msgstr "Zapísať" #~ msgid "Filter on _Genre" #~ msgstr "Filter na žá_ner" #~ msgid "Filter on _Artist" #~ msgstr "Filter na _interpreta" #~ msgid "Filter on Al_bum" #~ msgstr "Filter na _album" #~ msgid "_Music" #~ msgstr "_Hudba" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Záložky" #~ msgid "Song _List" #~ msgstr "_Zoznam skladieb" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Skončiť po tejto skladbe" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "a %d viac..." #~ msgstr[1] "a %d viac..." #~ msgstr[2] "a %d viac..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Oddeliť disk z _albumu" #, fuzzy #~ msgid "Timeout" #~ msgstr "Čas" #, fuzzy #~ msgid "Select an album" #~ msgstr "Označiť _všetko:" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s a %(count)d viac" #~ msgstr[1] "%(title)s a %(count)d viac" #~ msgstr[2] "%(title)s a %(count)d viac" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Playlisty" #~ msgid "Re_fresh Library" #~ msgstr "O_bnoviť knižnicu" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Hodnotenie" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Neplatná hodnota" #, fuzzy #~ msgid "ql-revert" #~ msgstr "_Odstrániť z knižnice" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Vyhľadávať" #~ msgid "%d of %d" #~ msgstr "%d z %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Použitie: %s %s" #~ msgid "_Download..." #~ msgstr "_Sťahovania..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Nová stanica" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Prepísať <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet už beží." #~ msgid "No song is currently playing." #~ msgstr "Momentálne nehrá žiadna skladba." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Nepodarilo sa zapísať do %s. Odstraňujem to." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Upraviť záložky..." #~ msgid "_New Folder..." #~ msgstr "_Nová zložka..." #~ msgid "_Add to Playlist" #~ msgstr "_Pridať do playlistu" #~ msgid "_Edit Display..." #~ msgstr "_Upraviť zobrazenie..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d stanica" #~ msgid "_Add a Location..." #~ msgstr "Pridať _umiestnenie..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Vlastné hlavičky..." #, fuzzy #~ msgid "People Headers" #~ msgstr "Hlavičky ľ_udí" #, fuzzy #~ msgid "Album Headers" #~ msgstr "Hlavičky _albumu" #, fuzzy #~ msgid "Date Headers" #~ msgstr "Hlavičky _dátumu" #, fuzzy #~ msgid "File Headers" #~ msgstr "Hlavičky _súboru" #, fuzzy #~ msgid "Production Headers" #~ msgstr "Hlavičky _produkcie" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Tag:" #, fuzzy #~ msgid "Warnings" #~ msgstr "_Hodnotenie" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "interpret albumu" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "interpreti" #, fuzzy #~ msgid "album (sort)" #~ msgstr "interpret albumu" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "hudobníci" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "hudobníci" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artist ID" #, fuzzy #~ msgid "errors" #~ msgstr "hudobníci" #~ msgid "Permanently delete this file?" #~ msgstr "Vymazať tento súbor natrvalo?" #~ msgid "Permanently delete these files?" #~ msgstr "Vymazať tieto súbory natrvalo?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s a %(count)d viac..." #~ msgstr[1] "%(title)s a %(count)d viac..." #~ msgstr[2] "%(title)s a %(count)d viac..." #, fuzzy #~ msgid "Version:" #~ msgstr "verzia" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "Chyby zásuvných modulov" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s nemôže byť pridané do knižnice.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Príkaz na vysunutie nenájdený." #~ msgid "Unable to start web browser" #~ msgstr "Neporadilo sa spustit webový prehliadač" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Nepodarilo sa nájst žiadny webový prehliadač. Nastavte prosím premennú " #~ "$BROWSER, alebo sa uistite že súbor /usr/bin/sensible-browser existuje." #, fuzzy #~ msgid "Library Error" #~ msgstr "Prehliadať knižnice" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Kopírovať na zariadenie" #~ msgid "translator-credits" #~ msgstr "Lukáš Lalinský <lalinsky@gmail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Ostatné stĺpce, oddelené medzerami" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Pokračovať" #~ msgid "Search your library" #~ msgstr "Vyhľadávať v knižnici" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman a ďalší\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Celková veľkosť:" #~ msgid "Quod Libet Plugins" #~ msgstr "Zásuvné moduly Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Zobraziť jednoduche vyhľadávanie modro, rozšírené zeleno a neplatné " #~ "červeno" #~ msgid "Separators for splitting tags" #~ msgstr "Oddelovače na delenie tagov" #~ msgid "Quod Libet Preferences" #~ msgstr "Nastavenie Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Nehrané _dnes" #~ msgid "Not Played in a _Week" #~ msgstr "Nehrané za posledný _týždeň" #~ msgid "Not Played in a _Month" #~ msgstr "Nehrané za posledný _mesiac" #~ msgid "B_ottom 40" #~ msgstr "_Spodných 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "40 skladieb ktoré ste hrali najmenej" #~ msgid "gtk-media-next" #~ msgstr "_Nasledujúca" #~ msgid "gtk-media-previous" #~ msgstr "Pre_dchádzajúca" #, fuzzy #~ msgid "Date" #~ msgstr "_Dátum" #~ msgid "Add" #~ msgstr "Pridať" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stanice:" #~ msgid "Unable to save library" #~ msgstr "Neporadilo sa uložiť knižnicu" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Neporadilo sa prehrať skladbu" #~ msgid "Sort by title" #~ msgstr "Podľa názvu" #~ msgid "Sort by artist" #~ msgstr "Podľa interpreta" #~ msgid "Lyrics provided by %s." #~ msgstr "Text od %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Žiadny text nenájdený.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgid "part" #~ msgstr "časť" #~ msgid "Opening audio device." #~ msgstr "Otváranie audio zariadenia." #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d skladieb uložených" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz ID albumu" #~ msgid "Loaded song library." #~ msgstr "Načítaná knižnica skladieb." #~ msgid "Unable to open audio device" #~ msgstr "Neporadilo sa otvoriť audio zariadenie" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet nenašiel GStreamer element 'filesrc'. Skontrolujte svoju " #~ "inštaláciu GStreameru." ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/sr_RS.po�������������������������������������������������������������������������0000644�0001750�0001750�00000777036�14436352625�014247� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Serbian translations for PACKAGE package # Преводи на српски језик за пакет „PACKAGE“. # Copyright (C) 2019 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2019. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Serbian <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/sr/>\n" "Language: sr_RS\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Назив" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "људи" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Датум" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Датум заглавље" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Изворни датум" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Жанр" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Оцена" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Број пуштања" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Разврстај _по…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Поставке" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Листа албума" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Листа албума" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Сви албуми" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d албум" msgstr[1] "%d албума" msgstr[2] "%d албума" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Поново учитај _омот албума" msgstr[1] "Ponovo učitaj _omota albuma" msgstr[2] "Ponovo učitaj _omota albuma" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Песме нису у албуму" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d запис" msgstr[1] "%d записа" msgstr[2] "%d записа" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d диск" msgstr[1] "%d диска" msgstr[2] "%d дискова" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Пример албума" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Поставке листе албума" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Прикажи _омоте албума" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Инлајн _претрага укључује људе" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Опције" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Приказ албума" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Затвори" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Претраживач библиотеке" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d песма" msgstr[1] "%d песме" msgstr[2] "%d песама" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Неисправан образац" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Библиотека албума" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Библиотека албума" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Непознат %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Више %s вредности" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Прилагођено" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Додај" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Уклони" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Ознака" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Споји" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Поставке библиотеке албума" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Примени" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Откажи" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Мрежа омота" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Мрежа омота" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Поставке мреже омота" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Прикажи _текст албума" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Прикажи ставку \"Сви албуми\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Широк режим" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Увеличавање омота" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Систем датотека" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Систем датотека" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Не могу да умножим песме" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "Одабране ставке не могу бити умножене у други низ или листу песама." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Додај у библиотеку" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Листа станица подржава само локације станица, не друге листе станица или " "листе репродукције. Следеће локације не могу бити учитане:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Интернет радио" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Све станице" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Преузимам листу станица" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Нова станица" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Унесите локацију интернет радио станице:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Електронска" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Хип Хоп / Реп" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Стара" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Јапанска" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Индијска" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Духовна" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Табеле" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Турска" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Реге / За плес" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Латино" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Факултетски радио" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Разговор / Вести" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Амбиентална" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Џез" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Класична" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Поп" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Алтернативна" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Метал" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Кантри" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Вести" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Шлагери" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Фанк" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Инди" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Блуз" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Соул" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "За одмарање" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Панк" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Регетон" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Словенска" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Грчка" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Готика" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Рок" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Да ли желите да учитате листу популарних радио станица?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Учитај станице" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Интернет радио" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Све станице" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Омиљено" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Без категорије" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Нова станица…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Ажурирај станице" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Нису пронађене станице" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Интернет радио станица није нађена на %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Излистане станице су већ у вашој библиотеци." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Додај у омиљене" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Уклони из омиљених" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d станица" msgstr[1] "%(count)d станице" msgstr[2] "%(count)d станица" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Пано претраживач" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Пано претраживач" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Одабери _све" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Непознато" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Све" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Мало" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Широко" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Колонар" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Означи шаблон опционим обележјима нпр. <tt>kompozitor</tt> или\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Postavke pano pretraživača" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Изглед колона" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Садржај колона" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Једнака ширина паноа" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Листа извођења" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Листа извођења" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Уклони са листе извођења" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Ново" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Увези" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Не могу да увезем листу извођења" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet не може да увози листе пуштања у M3U/M3U8 и PLS форматима." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Обриши" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Преименуј" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Не могу да преименујем листу пуштања" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Увези листу извођења" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Увези" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Нова листа извођења…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Шта желите да урадите са овом %d песмом?" msgstr[1] "Шта желите да урадите са ове %d песме?" msgstr[2] "Шта желите да урадите са ових %d песама?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Потврди радњу за листу извођења \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "празно" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Пример листе извођења" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Поставке претраживача листе извођења" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Приказ листе извођења" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Да ли сте сигурни да желите да избришете листу извођења '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Све информације о одабраној листи извођења ће бити неповратно избрисане." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Запис" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Нова листа извођења" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Унесите име за нову листу извођења:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Увозим листу извођења.\n" "\n" "%(current)d/%(total)d додато песама." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Нови извор" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Унесите локацију аудио извора:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Додај датотеку…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Освежи" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Не могу додати извор" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s не може бити додат. Можда је сервер недоступан или извор није аудио запис." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Тренутна аудио подршка не подржава URL, претраживач аудио извора је " "онемогућен." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Ограничи резултате" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Дозволи више претрага" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Листа записа" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Листа записа" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud претраживач" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Претрага" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Моји записи" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Иди на %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Повезан" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet је повезан, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Одјави се са %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Унеси код…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Пријави се на %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud аутентификација" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Унесите Soundcloud аутентификациони код:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet није покренут (додај '--run' за покретање)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "музичка библиотека и плејер" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[опција]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Одштампај пуштену песму и изађи" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Одмах почни извођење" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Не приказуј прозоре при покретању" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Скочи на следећу песму" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Скочи на претходну песму или пусти поново ако је при почетку" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Скочи на претходну песму" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Покрени извођење" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Паузирај извођење" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Мењај пусти/паузирај режим" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Заустави извођење" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Појачај" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Смањи" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Повећај оцену тренутне песме за једну звездицу" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Умањи оцену тренутне песме за једну звездицу" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Одштампај стање плејера" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Сакриј главни прозор" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Прикажи главни прозор" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Промени видљивост главног прозора" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Фокусирај покренути плејер" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Уклони филтере активног претраживача" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Освежи и претражи библиотеку" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Излистај доступне претраживаче" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Одштампај тренутну листу извођења" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Одштампај садржај низа" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Одштампај упит активног текста" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Покрени без прикључака" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Покрени Quod Libet ако није покренут" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Напусти Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Премотај тренутну песму" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Постави или промени режим мешања" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Постави тип режима мешања" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Укључи или искључи понављање" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Промени тип понављања" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Подеси јачину" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Претражи своју аудио библиотеку" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "упит" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Репродукуј датотеку" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "име дадотеке" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Оцени тренутну песму" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Постави тренутни претраживач" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Заустави након завршетка песме" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Отвори нов претраживач" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Прикажи или сакриј захтеве" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Филтрирај по насумичној вредности" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "ознака" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Филтрирај по вредношћу ознаке" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "ознака=вредност" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Нанизати датотеку или захтев" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Нанизати зарезом раздвојене датотеке" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "име датотеке" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Штампај имена датотека резултата захтева на стдоут" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Избаци из низа датотеку или захтев" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Додај датотеку или директоријум у библиотеку" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "локација" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "шаблон" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Неважећи аргумент за '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Покушај %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Дошло је до грешке" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Можете занемарити ову грешку, али апликација може бити нестабилна док се не " "покрене поново. Пријављивање грешке траје неколико секунди а нама помаже " "пуно." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Пријави грешку" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Занемари грешку" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Детаљи грешке:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Разни детаљи о грешци и вашем систему ће бити послати трећој страни на " "интернету (<a href='https://www.sentry.io'>www.sentry.io</a>). Испод можете " "прегледати податке пре слања." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(опционо) Укратко опишите шта се десило када је дошло до грешке:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Пошаљи" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Кратак опис…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Подаци за слање:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "уређивач аудио ознака" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "директоријум" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Уређивач аудио метаподатака" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL извор омота" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Преузима повезане омоте по artwork_url ознаци. Ово ради са Soundcloud " "претраживачем." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs извор омота" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Преузима омоте са Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm извор омота" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Преузима омоте из Last.fm архиве." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz извор омота" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Преузима омоте из MusicBrainz архиве." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Преобрати енкодирања" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Поправља погрешно протумачене вредности ознаке енкодирања у уређивачу ознака." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Преобрати енкодирања…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji претварач узорка" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Претвара kana/kanji на romaji пре преименовања." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Романизује _Јапански текст" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Не могу пронаћи \"Kanji Kana Simple Inverter\" (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Замена регуларног израза" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Дозвољава задату замену регуларног израза (s///) при означавању или " "преименовању датотека." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Велико слово" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Велико-слово вредности ознака у уређивачу ознака." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Велико-_слово вредност" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Дозволи _СВЕ-БЕЛИКА слова у ознакама" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Људска велика слова" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Користи уобичајена енглеска правила за велика слова, као што је \"Dark Night " "of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Напредне поставке" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Дозволи мењање напредних подешавања конфигурације." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Знам шта радим" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Анимирани На-Екрану приказ" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Приказује информације о песми на екрану при промени песме." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Позиција:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Величина омота:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Приказ" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Фонт:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Лево" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Центар" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Десно" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Изравнај текст:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Текст" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Текст:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Испуни:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Боје" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Сенке" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Спољна линија" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Окру_гли углови" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Кашњење:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Ефекти" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ур_еди шаблон приказа…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Преглед" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Информације о апликацији" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Разне информације о апликацији и њеном окружењу." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Подржани формати" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Директоријум конфигурације" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Кеш директоријум" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Аудио позадина" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Врати на подразумевано" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Не могу контактирати сервис '%s'." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Ажурирај ознаке у датотекама" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Ажурира измењене ознаке у датотекама. Ово ће осигурати да су број пуштања и " "оцене ажуриране." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Сачувај оцене и _број пуштања у ознакама" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "датум снимања" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Грешка при синхронизацији" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Ажурирај станице" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Поставке" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Аутоматско маскирање" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "Аутоматски маскира и демаскира уређаје у току качења или откачивања." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Аутоматско оцењивање" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Аутоматски оцењује песме када су пуштене или рпескочене. Ово користи " "\"убрзани\" алгоритам са вукс од Брајана Нелсона." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" "Оређује да ли је Banshee база података недоступна или је лоше формирана" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Увоз неуспешан" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Успешно увезене оцене и статистика за %d песму" msgstr[1] "Успешно увезене оцене и статистика за %d песме" msgstr[2] "Успешно увезене оцене и статистика за %d песама" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee увоз" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Увози оцене и статистику песме из Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_База података:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Почни увожење" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Будилник" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Буди вас помоћу гласне музике." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Успаванка" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Смањује и паузира музику." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim статус поруке" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim статус поруке" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Мења Gajim статусну поруку у оно шта тренутно слушате." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Паузирано:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Статус текст" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Статус текст" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Равно" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Уживо" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Пун бас и високи" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Клуб" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Велика дворана" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Журка" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Меко" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Пун бас" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Реге" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Слушалице" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Меки рок" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Пуни високи" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Игра" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Техно" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ска" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Лаптоп" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Еквилајзер" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Управља тоном музике уз помоћ изједначивача.\n" "Кликните или користите дирке да прилагодите нивое (десни-клик опозива све " "клизаче)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Тренутна позадина не подржава изједначавање." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Подразумевани одабир" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Одабери…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Поништи EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Прилагођен одабир" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Обриши одабрано" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Име одабира за чување:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Сачувај" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "на мрежи" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "ван мреже" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "ћаскање" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "ван" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "невидљив" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim статус поруке" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Мења Gajim статусну поруку у оно шта тренутно слушате." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "паузирано" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Шаблон:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Листа налоге, раздвојене размаком, за промену статусне поруке. Ако није " "прецизан налог, статус порука ће бити промењена." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Налози:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Додаје '[паузиран]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Ако је означено, '[паузиран]' ће бити додато у статусну поруку када је песма " "паузирана" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Статури за које ће порука бити измењена" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Паузирај када су слушалице откачене" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "Паузира када су слушалице откачене и наставља ако су прикачене поново." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Онемогући чувара екрана" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Музика свира" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Режим" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Онемогући чувара екрана" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Онемогући чувара екрана" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Интернет радио дневник" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Снима задњих 10 песма пуштаних на радио станицама, и листа их у менију " "претраге." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Шаље Jabber User Tunes датотеку у ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Промени језик" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Мења језик кориснилког сучеља." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Подразумевана подешавања" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Поновно покретање је потребно да би измене имале ефекат" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Media Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Излаже све албуме на Rygel UPnP Media Server кроз MediaServer2 D-Bus сучеље." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Осигурава да је следеће у вашој rygel конфигурационој датотеци (~/.config/" "rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD Server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Дозвољава даљинско управљање Quod Libet-om користећи MPD клијент. Стрим, " "листе извођења и библиотека нису подржани." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Порт:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Локална _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "Л_озинка:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Веза" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Тестирани клијенти" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus подршка" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Сакриј главни прозор при затварању" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Прихвата QL шаблоне нпр. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT објављивач" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Објављује статусне поруке на MQTT тему." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Име домаћина посредника" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "име домаћина посредника / IP (подразумевано на localhost)" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Порт посредника" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "порт посредника (подразумевано на 1883)" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Име домаћина посредника" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Порт посредника" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Тема" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Образац репродукције" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Статус текст када је песма пуштена." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Образац паузе" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Текст када је песма паузирана." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Текст без песме" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Празан текст када нема пуштене песме" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT конфигурација" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Статус текст" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Повезан ка посреднику на %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Не могу да повежем %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Грешка при повезивању" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz претрага" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Дозвољава оцењивање бројем." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Корисничко_име:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Лозинка:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Налог" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Текст обавештења" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_назив:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Врати на подразумевани образац" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_тело:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Прикажи обавештења" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Прикажи обавештења" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Само на <i>_manual</i> промени песме" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Само на <i>_automatic</i> премени песме" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "На <i>a_ll</i> промени песме" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Само када главни прозор није у _фокусу" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Прикажи тастер \"_Следеће\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Грешка при повезивању" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Не могу да повежем сервис обавештења." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Обавештење песме" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Приказује обавештења при промени песме." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Следеће" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Обавештење песме" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Молимо посетите прозор додатака да подесите QLScrobbler. До тада, песме неће " "бити приложене." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Не могу контактирати сервис '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Аутентификација неуспела: неважећи URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Аутентификација неуспела: Неважеће корисничко име '%s' или погрешна лозинка." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Забрањен приступ. Контактирајте аутора." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Погрешно системско време. Достава можда неће успети док се то не исправи." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler достава" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler клијент за Last.fm, Libre.fm и друге Audioscrobbler сервисе." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Аутентификација успешна." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Сервис:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Друго…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Провери податке налога" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Уметник шаблон:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Наслов шаблон:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Изузми _филтер:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Шаблон за форматирање имена уметника за доставу. Оставите празно за " "подразумевано." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Шаблон за форматирање имена наслова за доставу. Оставите празно за " "подразумевано." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Песме које се подударају овим филтером неће бити достављене" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Режим ван мреже (не достављај ништа)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Достава" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Ућуткај радио рекламе" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Ућуткује излаз када су рекламе на радио станици.\n" "Станице: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Насумично извођење албума" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Пушта насумично одабран албум када листа извођења дође до краја. Захтева да " "ваш активни претраживач подржава филтрирање по албуму." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Боље оцењено" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Чешће пуштано" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Чешће прескакано" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Скоро пуштано" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Скоро покретано" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Скоро додато" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Дужи албуми" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "секунди пре почетка следећег албума" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Значај" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Пуштај неке албуме чешће од других" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "избегни" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "преферирај" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Насумичан албум" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Чекам да почне %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Успешно увезене оцене и статистика за %d песама" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox увоз" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Увози оцене и статистике песме из Rhythmbox-а." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Пауза чувара екрана" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Паузира песму када је GNOME чувар екрана активиран." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "GNOME Shell претраживач Quod Libet није инсталиран." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME претраживач" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Дозволи GNOME Shell да претражује библиотеку." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Алтернативна трака мотања" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Алтернативна трака мотања која је увек видљива и прелази преко целог прозора." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Обележивачи тачке мотања" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Чува тачке мотања A и/или B за записе. Прескочи до тачке A и заустави након " "тачке B приликом репродукције.\n" "Обратите пажњу да промена имена тачака испод не ажурира имена обележивача, " "само мења која имена обележивача ће додатак тражити за одлуку када да мота." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Име обележивача тачке A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Име обележивача које ће бити потражено када је запис покренут, и ако је " "нађено мота до времена тачке" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Име обележивача тачке B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Име обележивача које ће користити сваки тик при репродукцији записа ако " "постоји. Ако тренутна позиција превазилази време тачке, иде на крај записа." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox Синхронизација" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Чини да Logitech Squeezebox опонашаQuod Libet излаз, уколико оба читају " "идентичну библиотеку." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Грешка у проналажењу Squeezebox сервера" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Грешка проналажења %s. Молимо проверите подешавања" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Опције" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "енкодирање" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "датум снимања" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Обриши" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Обриши" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Чешће прескакано" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Одредишна фасцикла:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Шаблон путање" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Уреди сачуване шаблоне…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Уметник шаблон:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Преглед" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Статус" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Извори" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Извези метаподатке" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "организација" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Одредиште чувања" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Путања није апсолутна" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "садржи / али не почиње од корена. Да би избегли погрешно именоване фасцикле, " "коренујте свој шаблон почетком са / или ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Ни једна песма није одабрана." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Ни једна песма није одабрана." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Не могу да сачувам песму" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Чешће прескакано" msgstr[1] "Чешће прескакано" msgstr[2] "Чешће прескакано" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Неуспешно учитавање датотеке: %r" msgstr[1] "Неуспешно учитавање датотеке: %r" msgstr[2] "Неуспешно учитавање датотеке: %r" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Показује синхронизовани текст песме из .lrc датотеке са истим именом као " "запис." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Текст:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Позадина:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Фонт" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Величина (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy статус поруке" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Ажурира све Telepathy базиране IM налоге (како је конфигурисано у Empathy " "итд.) са статусном поруком базираном на тренутној песми." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Пуштено:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Статус текст када је песма започела. Прихвата QL шаблоне нпр. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Паузирано:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Статус текст када је песма паузирана. Прихвата QL шаблоне нпр. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Празан текст за статус када ништа није пуштено" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Нема песме:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Статус шаблони" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Промена теме" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Мења тренутну GTK+ тему." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Тема:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Подразумевана тема" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Пожељнија тамна тема" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Палац оцена" #: quodlibet/ext/events/thumbrating.py:90 #, fuzzy msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Додаје палац горе/доле систем оцењивања конвертован у вредност оцене. " "Корисно за праћење целокупних гласова и сортирање са '~#score'." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Мењај траку избора" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Мења траку избора користећи Alt дугме (видљива/невидљива)." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Не свира" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Трака задатака" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Управља Quod Libet-ом из траке задатака." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Прикажи %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Пусти" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "П_аузирај" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Пре_тходно" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Следеће" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Мешај" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Понављај" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Заустави _после ове песме" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Отвори _претраживач" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Измени _ознаке" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Информације" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Листа _извођења" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Одустани" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Понашање" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Скрол мења јачину тона" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Скрол мења песму" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Скрол _точак" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Облачић информација" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Погледај текст" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Аутоматски приказује ознаке или текст из датотеке." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Текст није нађен за\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Нема активне песме" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Покрени визуализације" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Покрени спољне визуализације." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Не могу покренути визуализације користећи '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Грешка" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Покретач визуализација:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Напуни" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Таласна трака мотања" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "Трака мотања у облику таласа тренутне песме." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Користи боју предњег дела:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Користи боју плутања:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Користи за остале боје:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Прикажи тренутну позицију" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Прикажи имена времена" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Корак мотања приликом скроловања (милисекунде):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Чувач слика" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Ћува слику омота тренутне песме у датотеку." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Датотека:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Праг:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Праг док филтер не буде активиран" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "О_днос:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Однос компресије" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Аудио компресор" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "Мења опсег свих узорака изнад одређеног прага са одређеним односом." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Одабир:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Филтрирај одабир" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Фреквенција одсецање:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Ниски-пролаз филтер фреквенција одсецања" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Извор _ниво:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Извор ниво" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Подразумевано" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Најближе позицији виртуелног звучника (30°, 3 метра)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Близу Chu Moy укрштеног извора (популарно)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "БлизуJan Meier's CORDA појачалима (мала промена)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Прилагођено" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Прилагођена подешавања" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Укрштен извор" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Меша леви и десни канал како би симулирао звучнике користећи слушалице, или " "за усклађивање старијих стерео снимака." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Филтер _појас:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Фреквентни појас филтера" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Филтер _ширина:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Фреквентни опсег филтера" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Ниво:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Ниво ефеката" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Караоке" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Уклања глас из аудио записа." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Моно спуштање" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Спушта аудио канале на моно." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "У_честалост:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Темпо:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Степен:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Аудио степен / брзина" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Управља брзином аудио извора." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Извези листу извођења у фасциклу" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Извези" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Одредишна фасцикла:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Шаблон имена датотеке:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Извози листу извођења копирајући датотеке у фасцикле." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Не могу да извезем листу извођења" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Уверите се да имате приступ записивању на одредиште." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Подразумеван шаблон имена датотека:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_У реду" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Извези као листу извођења" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Извози листу извођења копирајући датотеке у фасцикле." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Грешка у проналажењу Squeezebox сервера" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Грешка проналажења %s. Молимо проверите подешавања" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Извези у Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Динамички извози листу извођења у Logitech Squeezebox листу, уколико деле " "структуру директоријума. Дели конфигурацију са <a href=\"quodlibet:///prefs/" "plugins/Squeezebox Output\">Squeezebox Sync plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Извези листу извођења у Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Име листе извођења (преписује постојеће)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Извези у Squeezebox листу извођења" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Уклони дупликате из листе извођења" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Уклања дупликате из листе извођења." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Да ли сте сигурни да желите да уклоните %d дупликат?" msgstr[1] "Да ли сте сигурни да желите да уклоните %d дупликата?" msgstr[2] "Да ли сте сигурни да желите да уклоните %d дупликата?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Дупликати ће бити уклоњени из листе извођења '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Мешај листу извођења" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Насумично меша листу извођења." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Прати показивач" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Репродукција прати ваш одабир, или следећу песму уколико је листа исцрпљена." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Прати показивач" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Прати показивач" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Уједначивач броја пуштања" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Меша и даје предност песмама које су ређе пуштане." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Пожели мање пуштане" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Пожели мање пуштане" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Само низ" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Ограничава пуштање песама на низ. Ако је овај поредак одабран, дупли-клик ће " "додати песму у низ уместо да је пусти." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Само низ" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Само низ" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Окренут" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Окреће редослед пуштања песама." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Окренут" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Мешај по групама" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Меша тако што групише песме дефинисане ознакама уместо записа, слично мешању " "албума." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Мешај по групама" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Мешај по групама" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Чекам да започнем нову групу…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Груписане ознаке:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Ознаке за груписање песама" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Филтер ознака:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Груписање је примењено само ако је филтер ознака одређен.\n" "Песма са неодређеним филтером ознаке ће бити третирана\n" "као група сама за себе. Обично филтер ознаке требају бити\n" "подударне или делимично подударне групи ознака." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "_Кашњење:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Временско закашњење у секундама пре почетка следеће групе" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Поништи на подразумевано" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Понављај сваки запис" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Меша песме, али понавља сваки запис постављеним бројем пута." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Понављај сваки запис" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Понављај сваки запис" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Број пута пуштања сваке песме:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Околносни упит" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Бира упит који се подудара са ситуационим упитом. синтакса је '@(if: " "condition, then, else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Недостајући упит" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Упарује песме без додељене ознаке." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Укључи празне ознаке" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python упит" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Израз ознаке" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Користи Python израз у упитима. Синтакса је \"@(python: expression)\". " "Променљива \"s\" (или \"a\") је подударна песма / албум. \"_ts\" је " "временска ознака на почетку упита. Модули \"време\" и \"насумично\" су " "доступни, и класа \"Насумично\" (==random.Random) такође." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Укључи сачувану претрагу" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Укључује резултате сачуваних претрага као део другог упита. Синтакса је " "'@(saved: search name)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Сачувана претрага" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "јединствен" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox је у реду. Користим само (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Не могу да се повежем на %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Име домаћина:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Порт:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Корисничко име:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Лозинка:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Директоријум библиотеке повезивања сервера" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Путања библиотеке:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Провери поставке" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox сервер" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Испитај" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox сервер на {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "неидентификовани Squeezebox сервер" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "неидентификовани Squeezebox плејер: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Одабери Squeezebox плејер" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Пронађен Squeezebox сервер.\n" "Молимо одаберите плејер" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Уклопи слику у _прозор" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "Види '[plugins] cover_filenames' конфигурацију за име слике" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Програм:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Уреди слику након чувања" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Име _датотеке:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Неуспешно чување" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Не могу да сачувам \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP грешка: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Преузимач омота" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "из %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Резолуција: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Величина: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "По покретачу \"најбољи\" резултат ограничење" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Претрага" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Тражим…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Завршено" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Преузми омот албума" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Преузима омоте албума са различитих интернет адреса." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Извори" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 на ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Претвара ваше APEv2 ознаке у ID3v2 ознаке. Ово ће обрисати APEv2 ознаке " "након преображаја." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Иди на обележивач" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Уређује обележиваче у одабраним датотекама." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Уреди обележиваче…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Без обележивача" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz претрага" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Назначи албум базиран на MusicBrainz претрази." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Користи само годину за \"датум\" ознаку" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Упиши \"_albumartist\" када је потребно" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Упиши поредак ознака за имена уметника" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Упиши _стандард MusicBrainz ознаке" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Упиши \"labelid\" ознаку" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Име датотеке" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Диск" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Запис" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Назив" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Уметник" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz претрага" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Упит:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "П_ретрага" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Резултати <i>(превуци за промену)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Молимо упишите упит." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Дошло је до грешке. Покушајте поново." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Учитавам резултате…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Нема резултата." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python конзола" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Интерактивна Python конзола. Отвара нови прозор." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} за {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python конзола бочна страница" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Бочна страна за интерактивну Python конзолу која прати одабране песме у " "главном прозору." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Можете приступити следећим подразумеваним објектима:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Ваш тренутни радни директоријум је:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Веза" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Преузимање омота" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Преузима омоте високог квалитета користећи додатак омота." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Класично" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Велико" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Омот преузимање" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Учитавам %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Ништа није пронађено за албуме:\n" "<i>%(albums)s</i>.\n" "\n" "Коришћени извори:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Нема пронађених омота" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Величина прегледа" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Одредиште чувања" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Команда" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "име" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Име ове команде" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "команда" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Синтакса команде шкољке за покретање" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "параметар" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Ако је назначено, параметар који се појављује у командама ће бити замењен " "вредношћу датом од стране корисника, нпр. користећи 'PARAM' у свим " "случајевима '{PARAM}' у вашој команди, имаће вредност дату када је покренуто" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL шаблон, нпр. <~filename>, за израчунавање вредности команде. За листе " "извођења, ово подржава виртуелне ознаке ovo <~playlistname> и " "<~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "јединствен" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Ако је постављено, ово ће уклонити дупликате израчунатих вредности шаблона" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "макс аргс" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "Највећи број аргумената послатих команди у датом тренутку (kao xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Окренут" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Вредност излаза" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Вредност за %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Прилагођене команде" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Покреће прилагођене команде (у гомили ако је потребно) за песме користећи " "било које ознаке." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Уреди прилагођене команде" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Не могу да покренем прилагођену команду %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d дупликат" msgstr[1] "%d дупликата" msgstr[2] "%d дупликата" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Сузи / Прошири све" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Заједнички израз дупликата је '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Претраживач дупликата" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Проналази и приказује слично означене верзије песама." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Прихвата QL израз ознаке као <tt>~artist~title</tt> или " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Групише дупликате по:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Дупликат кључ" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Уклони _бео простор" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Уклони _дијакритике" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Уклони _интерпукције" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Слово _неосетљиво" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Опције подударања" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Уреди број пуштања" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Уреди песмин ~#playcount и ~#skipcount.\n" "\n" "Када је одабрано више песама, број ће се повећавати.\n" "\n" "Када је ~#playcount песме подешен на 0, ~#lastplayed i ~#laststarted уноси " "ће бити очишћени. Али, када се подеси 0-пуштања песме на позитивну вредност, " "број пуштања неће бити креиран." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Број пуштања" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Број прескакања" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Више %s вредности" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Уреди уграђене слике" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Уклапа или замењује уграђене слике." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Уклони све слике" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Угради тренутну слику" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Подеси тачну оцену" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Дозвољава оцењивање бројем." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Молимо оцените на скали од 0.0 до 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Филтрирај по било којој ознаци" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Креира претрагу базирану на ознакама одабраних песама." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Филтрирај по директоријуму" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Филтрирај по директоријуму у новом прозору." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Звучни отисак претрага" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Тражи метаподатке песме преко звучног отиска." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Приложи звучни отисак" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Генерише звучни отисак користећи chromaprint и прилаже их на acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Недостаје API кључ" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Морате да назначите acoustid.org API кључ у опцијама додатка пре него што " "приложите." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Захтевај API кључ" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _кључ:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID веб сервис" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Припремљено" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Анализирам" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Претрага" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Пиши" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Издато" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Упиши MusicBrainz ознаке" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Групиши по директоријуму" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Албум режим" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Упиши ознаке повезане са албумима и покушај да умањиш број различитих издања " "албума" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Генеришем отиске:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Детаљи" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Пошаљи" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Песме захтевају <i><b>musicbrainz_trackid</b></i>, или <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> ознаке да би биле приложене." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Отисци:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Песме са MBIDs:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Песме са довољним ознакама:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Песме за слање:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Завршено. %(to-send)d/%(all)d песама за слање." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Шаљем отиске:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Шаљем…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Ажурирај ознаке у датотекама" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Ажурира измењене ознаке у датотекама. Ово ће осигурати да су број пуштања и " "оцене ажуриране." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Извези у HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Извози одабрану листу песама у HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Пошаљи на iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Шаље песме на iRiver iFP уређај." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Нема пронађеног iFP уређаја" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Не могу да повежем ваш iFP уређај. Проверите да ли је урешај прикључен, и да " "поседујете ifp-линију (http://ifp-driver.sf.net) инсталирану." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Шаљем %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Не могу да пошаљем <b>%s</b>. Уређај можда нема довољно простора или је " "искључен." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Грешка при слању" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Извези метаподатке" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Извези метаподатке" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Извези метаподатке" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Извези метаподатке" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Нема информација о трајању" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Омот албума" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Увоз неуспешан" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Увези" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Филтрирај по директоријуму" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Диск" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Запис" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Уметник" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "албуми" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Настави" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Не могу контактирати сервис '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Не могу контактирати сервис '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Имена датотека" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Понављај сваки запис" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Ажурирам листу образаца." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Већ је ажурирано." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Скупљам обрасце за недељу %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Синхронизација завршена." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Грешка при синхронизацији" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm Синхронизација" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Ажурира статистику ваше библиотеке са Last.fm профила." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Корисничко име:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Креирај назнаке сортирања" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Претвара имена албума и уметника да сортира имена, лоше." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Извези као листу извођења" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Извози песме у M3U или PLS листу извођења." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Користи релативне путање" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Користи апсолутне путање" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Уписивање на <b>%s</b> није успело." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Поново претражи песме" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Проверава промене у датотекама и поново учитава или уклања песме ако је " "потребно." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Поново претражи песме" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain испитивач" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Запис" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Напредак" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Доступан <b>%(to-process)s</b> албум за ажурирање (of %(all)s)" msgstr[1] "Доступно <b>%(to-process)s</b> албума за ажурирање (of %(all)s)" msgstr[2] "Доступно <b>%(to-process)s</b> албума за ажурирање (of %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Испитује и ажурира <a href=\"%(rg_link)s\">ReplayGain</a> информације " "користећи GStreamer. Резултати су груписани по албуму." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "увек" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "ако недостају <b>any</b> RG ознаке" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "ако недостају <b>album</b> RG ознаке" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_OОбрада албума:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Излазне ознаке" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Подели ознаке" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Дели број диска из албума и верзије са именом истовремено." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Подели албум" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Подели број диска." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "н/д" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Поништи" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Tap" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Tap BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Tap BPM за одабрану песму." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Претражи веб" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Претражује ваш избор странице користећи било које ознаке.\n" "Подржава шаблоне нпр. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Претрага URL шаблона" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Уреди претрагу URL-а" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Конфигуриши претрагу…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Претражи ознаку у Википедији" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Отвара прозор у прегледачу са страницом чланка Википедија за одабрану ознаку " "песме." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Потражи на %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Уреди ознаке" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Претрага није успела" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Ознака \"%s\" није нађена." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Библиотека" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Проверавам прикључне тачке" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Претрага библиотеке" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Претрага %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Учитавам датотеке" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Претрага библиотеке" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Уклони филтере активног претраживача" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Музички плејер и организатор билбиотеке" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Неуспешно учитавање датотеке: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Излистај ознаке" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Штампај сажет излаз" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Колоне за приказивање и редослед у сажетом режиму (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Такође излистај прагматичне ознаке" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Недовољно аргумената" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Превише аргумената" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Опис" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Вредност" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Излистај све учестале ознаке" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Умножи ознаке са једне на другу датотеку" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Прикажи промене, али их не примењуј" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Прескочи ознаке које се не могу уписати" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Не могу да имножим {tagname} у датотеку: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Уреди ознаке у уређивачу текста" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Уређивање прекинуто" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Покретање уређивача текста '%(editor-name)s' није успело." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Нема уочених промена" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Постави ознаку и уклони постојеће вредности" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Не могу пставити %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Уклони ознаке" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Вредност је обичан израз" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Уклони све ознаке" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Не могу да комбинујем'--all' са '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Не могу уклонити {tagname} из {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Уклони вредност ознаке" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Додај вредност ознаке" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Не могу пставити %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Излистај информације о датотеци" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Постави понуђену слику као примарну уграђену слику и уклони све остале " "уграђене слике" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Неуспешно учитавање слике: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "Неподржано уређивање слике за %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Уклони све уграђене слике" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Извези уграђене слике на %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Путања где ће слике бити сачуване (подразумевано је радни директоријум)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Преименуј датотеке користећи ознаке" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Испуни ознаке користећи путању датотеке" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Датотека" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Испуни број песме за све датотеке" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Штампај ознаке по одређеном шаблону" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Прикажи помоћне информације" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' није важеће име колоне (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Непознато" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "По реду" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_По реду" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Насумично" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Насумично" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Преферирај боље оцењене" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Преферирај боље оцењене" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Понови овај запис" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Понови овај запис" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Понови све" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Понови све" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Једна песма" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Једна песма" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Стрим" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Пуњење меморије" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Не могу створити GStreamer pipeline" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Није пронађен ни један GStreamer елемент за обраду формата" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Формат записа: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer додатак '%(name)s' не може бити покренут" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer output pipeline коришћен за репродукцију. Оставите празно за " "подразумевани. У неким другим случајевима, користиће се подразумевани." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Output pipeline:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buffer duration:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Онемогући _gapless репродукцију" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Онемогућавање gapless репродукције може избећи проблеме при мењању песама са " "неким верзијама GStreamer-а" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Нема нађеног GStreamer audio sink" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Неважећа GStreamer излазна pipeline" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Не могу да креирам аудио излаз" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Аудио уређај %r није пронађен. Проверите Xine подешавања у ~/.quodlibet/" "config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Не могу да пронађем модул '{module}'. Можда је потребно да инсталирате пакет?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Не могу пронаћи GStreamer елемент '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Молимо посетите прозор додатака да подесите QLScrobbler. До тада, песме неће " "бити приложене." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Молимо посетите прозор додатака да подесите QLScrobbler. До тада, песме неће " "бити приложене." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Достава" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "Корисничко_име:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Песме које се подударају овим филтером неће бити достављене" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Покрени додатак \"%(name)s\" у %(count)s листи извођења?" msgstr[1] "Покрени додатак \"%(name)s\" у %(count)s листе извођења?" msgstr[2] "Покрени додатак \"%(name)s\" у %(count)s листи извођења?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Покрени додатак" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Почетак" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Н/Д" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Време" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Име обележивача" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Обележивачи" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Филтери" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Скоро _пуштано" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Скоро _додато" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Топ 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Све _песме" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "По тренутном _жанру" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "По тренутном _уметнику" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "По тренутном ал_буму" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Насумичан _жанр" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Насумичан _уметник" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Насумичан ал_бум" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 најчешће пуштаних песама (више од 40 може бити одабрано ако су повезане)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Име:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "Вредност:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Сачуване вредности" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Уреди сачуване вредности…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Ауто_матски" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Режим записа" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Режим албума" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Утишај" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain Режим" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Нов %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "непознато)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Додај" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Уреди…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Израз ознаке" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Израз ознаке нпр. people:real ili ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Упиши нову ознаку" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Израз ознаке" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Датотеке:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Одабране песме ће бити уклоњене из библиотеке и њихове датотеке са диска." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Одабране датотеке ће бити уклоњене са диска." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Обрисати %(file_count)d датотеку заувек?" msgstr[1] "Обрисати %(file_count)d датотеке заувек?" msgstr[2] "Обрисати %(file_count)d датотека заувек?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Обриши датотеке" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Одабране песме ће бити избачене из библиотеке и њихове датотеке премештене у " "корпу за отпатке." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Одабране датотеке ће бити премештене у корпу за отпатке." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Премести %(file_count)d датотеку у корпу?" msgstr[1] "Премести %(file_count)d датотеке у корпу?" msgstr[2] "Премести %(file_count)d датотека у корпу?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Премести у корпу" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Премештам %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Није могуће преместити у корпу" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Премештање једне или више датотека у корпу није успело." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Бришем %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Не могу обрисати датотеке" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Брисање једне или више датотека неуспешно." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Претраживачи" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Учитавам датотеке" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "недостаје у %d песми" msgstr[1] "недостаје у %d песме" msgstr[2] "недостаје у %d песама" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "различито у %d песми" msgstr[1] "различито у %d песме" msgstr[2] "различито у %d песама" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Одвоју у _вишеструке вредности" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Одвоји диск од _албума" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Одвоји _верзију од назива" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Одвоји аранжера од Ум_етника" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Одвоји _извођача од уметника" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Одвоји _извођача од назива" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Одвоји _изворног уметника од назива" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Додај ознаку" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Ознака:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Прикажи _прагматичне ознаке" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Приступи свим ознакама, укључујући машински произведене нпр. MusicBrainz или " "Replay Gain ознаке" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Прикажи _прагматичне ознаке" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Врати" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Сачувај" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Подеси" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Раздвоји ознаке" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Умножи вредност(и)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Не могу додати ознаку" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Не могу да додам песме" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Тренутно одабране датотеке не подржавају вишеструке вредности за <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Неважећа ознака" msgstr[1] "Неважећа ознака" msgstr[2] "Неважећа ознака" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Неважећа ознака <b>%s</b>\n" "\n" "Тренутно одабрана датотека не подржава ову ознаку." msgstr[1] "" "Неважећа ознака <b>%s</b>\n" "\n" "Тренутно одабрана датотека не подржава ову ознаку." msgstr[2] "" "Неважећа ознака <b>%s</b>\n" "\n" "Тренутно одабрана датотека не подржава ову ознаку." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Неважећа вредност" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Неважећа вредност: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Ознака може бити непрецизна" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s је измењено док је програм био покренут. Чување без освежавања " "библиотеке може преписати друге измене на песми." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Не могу да сачувам песму" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Чување %(file-name)s није успело. Датотека је можда само за читање, " "оштећена, или немате дозволу да је измените." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Више опција…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Опозови" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Понови" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_О апликацији" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Провери доступна ажурирања…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Додаци" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso Поставке" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Фасцикле" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Нова фасцикла…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Одабери све под-фасцикле" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Нова фасцикла" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Унесите име за нову фасциклу:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Не могу да створим фасциклу" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Не могу да обришем фасциклу" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Песме" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "од %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Диск %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Запис %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "По тренутном _жанру" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Уреди приказ…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ни једна песма није одабрана." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Нема песама" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Информације" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Текст речи" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Издато од %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "уметник" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "уметници" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "извођачи" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Никад" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d пут" msgstr[1] "%(n)d пута" msgstr[2] "%(n)d пута" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "додато" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "задње пуштано" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "свира" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "прескаче" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "оцена" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "путања" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "дужина" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "формат" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "кодек" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "енкодирање" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "учесталост битова" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "величина датотеке" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "измењено" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Додатно" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d одабран" msgstr[1] "%d одабрана" msgstr[2] "%d одабраних" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Запис недоступан" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d песма без албума" msgstr[1] "%d песме без албума" msgstr[2] "%d песама без албума" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Одабрана дискографија" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d песма без уметника" msgstr[1] "%d песме без уметника" msgstr[2] "%d песама без уметника" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "албуми" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Укупна дужина:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Укупна величина:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Датотеке" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Погледај на интернету" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Нема понуђеног текста за ову песму." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Да ли сте сигурни да желите да уклоните све песме?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Одабране песме ће бити уклоњене из библиотеке." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Откриј" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Откриј" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Занемари промене ознака?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Ознаке су измењене али нису сачуване. сачувај датотеке или опозови и " "занемари измене?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Опозови" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Датотека постоји" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Замени %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Замени датотеку" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Активни задаци" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d покренутих задатака" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Мењај режим мешања" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Мењај режим понављања" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Догађаји" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Редослед извођења" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Уређивање" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Преименуј" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Упит:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Омоти" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Грешке додатка" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Омогућено" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Онемогућено" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Без категорије" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Без категорије" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Додаци нису нађени." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Додаци" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Филтрирај по стању додатка" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Филтрирај по типу додатка" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Филтрирај по имену или опису додатка" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Прикажи _грешке" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Диск" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Запис" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Гру_писање" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Уметник" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Ал_бум" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Име датотеке" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Дужина" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Аутоматски скочи на пуштену песму" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Када се промени пуштена песма, премотај до ње у листи песама" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Други:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Уреди…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Додај или уклони додатна заглавља колона" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Видљиве колоне" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Име укључује _верзију" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Албум укључује _диск поднатпис" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Уметник укључује све _људе" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Име датотеке укључује _фасциклу" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Поставке колоне" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Уреди колоне" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Примени тренутну конфигурацију на листу песама, додај нову колону на крају" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Листа песама" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Уреди колоне" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Укупно трајање" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Глобални филтер:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Примени овај упит уз све друге" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Претрага" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Претраживачи" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Потврди _више оцена" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Питај за потврду пре него што променим оцене за више песама одједном" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Омогући _један-клик оцене" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Омогућава оцењивање кликом на колону оцене у листи песама" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Оцене" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Преферирај _уграђени омот" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Одаберите за коришћење омота уграђеног у аудио запис (када је доступно) пре " "других извора" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Фиксирано име слике:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Омот албума" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Репродукција" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Конфигурација излаза" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ако нема Replay Gain информација за песму, постави јачину по овој вредности" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Fall-back gain (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "Постави јачину за све песме по задатој вредности" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Pre-amp gain (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Omogući Replay Gain промену јачине" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain промена јачине" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Настави репродукцију при покретању" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Ако је музика свирала при гашењу, аутоматски настави репродукцију при " "следећем покретању" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Подразумевана оцена:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Скала _оцена:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesian Average factor (C) за нагомилане оцене.\n" "0 значи конвенционални просек, више вредности значе да ће албум са мало " "записа имати мање екстремне оцене. Промена ове вредности узрокује поновно " "рачунање за све албуме." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesian просечна количина:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Имејл:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Оцене и број пуштања ће бити сачуване у ознакама за ову адресу електронске " "поште" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Аутоматски сачувај промену оцена" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Сачувај промене у ознакама без потврде при уређивању више датотека" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Скуп операција за коришћење при дељењу вредности датотека у уређивачу " "ознака. Листа је одвојена простором." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Подели _ознаке на:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Скуп операција за коришћење при извлачењу под-ознака из ознака у уређивачу " "ознака. Листа је одвојена простором, и сваки унос мора садржати два знака." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Подели _подознаке на:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Ознаке" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Уређивање ознака" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Ажурирам за нове оцене" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Скенирај библиотеку" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Провери промене у библиотеци" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Поново _изгради библиотеку" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Поново учитај све песме у библиотеку. Ово може потрајати веома дуго." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Скривене песме" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Скенирај библиотеку _при покретању" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Skeniraj direktorijume" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Својства" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Низ" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Очисти низ" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Онемогући низ - низ ће бити занемарен приликом репродукције" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Пролазан" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Уклони песме из низа после репродукције" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Непрестано" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Задржи песме у низу након репродукције" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Режим" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Заустави на крају" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d песма (%(time)s)" msgstr[1] "%(count)d песме (%(time)s)" msgstr[2] "%(count)d песама (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Прегледај библиотеку" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Мења видљивост низа" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Грешка при репродукцији" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Додај директоријум библиотеке?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Немате музику додату у библиотеку. Да ли желите сада да додате?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Не сад" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Додај" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Не могу да додам песме" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s користи неподржан протокол." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Скочи на пуштену песму" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Датотека" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Песма" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Преглед" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Истражи" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Управљај" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Помоћ" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Додај фасциклу…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Додај датотеку…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Додај локацију…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Уреди обележиваче…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Заустави" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Заустави после ове песме" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Пречице тастатуре" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Помоћ на мрежи" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Потражи помоћ" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Додај локацију" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Унеси локацију аудио датотеке:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Не могу да додам локацију" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s није исправна локација." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Додај музику" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Додај фасцикле" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Музичке датотеке" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Додај датотеке" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Да ли сте сигурни да желите да уклоните све песме?" msgstr[1] "Да ли сте сигурни да желите да уклоните све песме?" msgstr[2] "Да ли сте сигурни да желите да уклоните све песме?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Низ" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Да ли сте сигурни да желите да измените оцену свих %d песама?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Сачуване оцене ће бити уклоњене" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Уклони оцене" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Оцене свих одабраних песама ће бити промењене на '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Промени _оцену" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Замени празан простор са _доњим цртама" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Уклони _Виндоуз некомпатибилне карактере" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Уклони _дијакритичке ознаке" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Укони не-_ASCII карактере" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Користи само _мала слова" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Преименуј датотеке" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Преглед" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Имена датотека" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Помери омот албума" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Видите '[albumart] filenames' унос конфигурације за претрагу слика" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Препиши омот албума по циљу" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Уклони празне директоријуме" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Омот албума" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Ново име" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Не могу да преименујем датотеку" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Преименовање <b>%(old-name)s</b> у <b>%(new-name)s</b> неуспешно. Могуће да " "циљана датотека већ постоји, или немате дозволу да направите нову датотеку " "или уклоните стару." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Занемари _све грешке" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Заустави" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Настави" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Путања није апсолутна" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "садржи / али не почиње од корена. Да би избегли погрешно именоване фасцикле, " "коренујте свој шаблон почетком са / или ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Песме у излистаним фасциклама ће бити додате у библиотеку када се листа " "освежи" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Одабране песме ће бити уклоњене из библиотеке." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Путања библиотеке:" msgstr[1] "Путања библиотеке:" msgstr[2] "Путања библиотеке:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Уклони" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Одабери директоријуме" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Одабери директоријуме" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Сачувана претрага" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Уреди сачуване претраге…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Претрага ваше библиотеке користећи слободан текст или QL упите" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Тражи након _куцања" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Показује резултате претраге након што корисник заврши са куцањем" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Ограничење:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Значај" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Додај питање" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Додај QL упит или слободан текст да буде &ed заједно" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Прикажи преостало време" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Главни прозор" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Премотај 10 секунди уназад" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Премотај 10 секунди унапред" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Фокусирај ставку претраге" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Поништи филтере и скочи на тренутну песму" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Отвори информациони прозор за одабране песме" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Отоври уређивач ознака за одабране песме" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Стави у ред одабране песме" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Обриши одабране песме" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Прикажи упис инлајн претраге" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Леви клик на заглавље колоне" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Додај колону на листу колона за разврставање" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Преглед стабла" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Скупља све елементе или одабира елемент шаблона" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Прошири елемент" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Унос текста" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Опозови задњу измену" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Понови задњу измену" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Одабери све песме у свим паноима" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Филтрирај по %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Сва _заглавља" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Запис заглавље" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Албум заглавље" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Људи заглавље" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Датум заглавље" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Датотека заглавље" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Продукција заглавље" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Прилагоди заглавље…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Прошири колону" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Премести %(file_count)d датотеку у корпу?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Уклони из библиотеке" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Покрени додатак \"%(name)s\" за %(count)d песму?" msgstr[1] "Покрени додатак \"%(name)s\" за %(count)d песме?" msgstr[2] "Покрени додатак \"%(name)s\" за %(count)d песама?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Подеси додатке…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Додај у _Низ" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Уклони из библиотеке…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Не могу да прикажем датотеке" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Грешка при приказивању датотеке, или нема програма који би је приказали." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Неуспешно чување" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Преузимање омота" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Преузимање омота" msgstr[1] "Преузимање омота" msgstr[2] "Преузимање омота" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Преузимање омота" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Замени _доње црте са празним простором" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Велико-слово ознаке" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Подели у више _вредности" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Ознаке из путање" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Ознаке замењују постојеће" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Ознаке су додате на постојеће" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "је неисраван. Могуће да садржи исту ознаку два пута или има небалансиране " "заграде (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Шаблон који сте унели није исправан. Будите сигурни да сте унели < i > " "као \\< i \\> и да су ваше ознаке избалансиране.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Уреди приказ" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Бројеви записа" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Почни о_д:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Укупно записа:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Пусти/Паузирај" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Претходно" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "и %d још…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Чувам измењене песме." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d сачуваних песама\n" "(%(remaining)s remaining)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s од %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Проверавам ажурирања" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Веза неуспешна" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Већ користите задњу верзију %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Нова верзија %(new-version)s је доступна\n" "\n" "Тренутно користите верзију %(old-version)s\n" "\n" "Посетите <a href='%(url)s'>website</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Увези листу извођења" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Листа извођења мора имати име" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Листа извођења %s већ постоји." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Уграђени омоти албума" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Користи омоте уграђене у аудио датотеке." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Омоти фасцикле" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Користи уобичајено именоване слике нађене у заједничком директоријуму уз " "песму." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Омот" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Испитујем достављаче омота и албума" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Прикажи укратке информације коришћења" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Прикажи верзију и ауторска права" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Одштампај информације исправљања грешака" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Коришћење: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[опције]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Опција %r није позната." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Опција %r захтева аргумент." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r није јединствен префикс." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s секунда" msgstr[1] "%s секунде" msgstr[2] "%s секунди" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Нема информација о трајању" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунде" msgstr[2] "%d секунди" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минут" msgstr[1] "%d минута" msgstr[2] "%d минута" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d сат" msgstr[1] "%d сата" msgstr[2] "%d сати" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d дан" msgstr[1] "%d дана" msgstr[2] "%d дана" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d дан" msgstr[1] "%d дана" msgstr[2] "%d дана" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "не" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Датум мора бити унет у 'YYYY', 'YYYY-MM-DD' или 'YYYY-MM-DD HH:MM:SS' " "формату." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain повећања морају бити унета у 'x.yy dB' формату." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain peaks морају бити унети у 'x.yy' формату." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDs морају бити у UUID формату." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz статус издања мора бити 'official', 'promotional', или 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Језик мора бити ISO 639-2 три-слова стандард" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Неуспешно чување" msgstr[1] "Неуспешно чување" msgstr[2] "Неуспешно чување" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Не могу уредити песму" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Чување <b>%s</b> неуспешно. Датотека је можда само за читање, оштећена, или " "немате потребне дозволе." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Неисправно енкодирање]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "албум" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "аранжер" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "аранжери" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "аранжман" #: quodlibet/util/tags.py:86 msgid "author" msgstr "аутор" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "аутори" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "коментар" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "композитор" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "композитори" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "композиција" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "диригент" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "диригенти" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "дириговање" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "контакт" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "ауторска права" #: quodlibet/util/tags.py:93 msgid "date" msgstr "датум" #: quodlibet/util/tags.py:94 msgid "description" msgstr "опис" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "жанр" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "жанрови" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "извођач" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "извођење" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "групе" #: quodlibet/util/tags.py:98 msgid "language" msgstr "језик" #: quodlibet/util/tags.py:99 msgid "license" msgstr "лиценца" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "текстописац" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "текстописци" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "текст" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "организација" #: quodlibet/util/tags.py:104 msgid "title" msgstr "наслов" #: quodlibet/util/tags.py:105 msgid "version" msgstr "верзија" #: quodlibet/util/tags.py:106 msgid "website" msgstr "веб адреса" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "уметник албума" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "УПМ" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "поднатпис диска" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "диск" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "запис" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "издавачка кућа" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "датум премијере" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "оригинални албум" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "оригинални уметник" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "датум снимања" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "земља издања" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID снимања" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID издања записа" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID издања" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID уметника" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID издања уметника" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz статус албума" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz тип албума" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID издања групе" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "референца јачине звука" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "дискови" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "записи" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "задње покретано" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "пуно име" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "тачка качења" #: quodlibet/util/tags.py:166 msgid "people" msgstr "људи" #: quodlibet/util/tags.py:168 msgid "year" msgstr "година" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "оригинална година издања" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "обележивач" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "дубина бита" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "формат датотеке" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "листе пуштања" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "брзина узорка" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "број канала" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "разврстај" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "улоге" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Аудио уређивач ознака" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Уређује ознаке у вашим аудио датотекама" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Музички плејер" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Слушајте, претражите или уредите своју аудио колекцију" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso је уређивач ознака са истим уређивачким интерфејсом као и Quod " "Libet. Дозвољава вам да прикажете и уредите било коју жељену ознаку у " "датотеци, за све формате које подржава." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Подржани формати укључују и Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet је програм за организацију музике. Пружа више различитих начина " "да прегледате вашу аудио збирку/библиотеку, а такође поседује и подршку за " "интернет радио и аудио изворе. Има јако флексибилне способности уређивања " "метаподатака ознака и претраге." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Извези у Squeezebox листу извођења" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Не могу додати <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Неважеће ознаке" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Неважеће ознаке <b>%s</b>\n" #~ "\n" #~ "Тренутно одабрана датотека не подржава уређивање ових ознака." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Аутоматски оцењује песме када су пуштене или рпескочене. Ово користи " #~ "\"убрзани\" алгоритам са вукс од Брајана Нелсона." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f секунди" #~ msgid "Startup" #~ msgstr "Покретање" #~ msgid "Audio Feeds" #~ msgstr "Аудио извори" #~ msgid "_Audio Feeds" #~ msgstr "_Аудио извори" #~ msgid "New" #~ msgstr "Ново" #~ msgid "Automatic Library Update" #~ msgstr "Аутоматско ажурирање билбиотеке" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Држи вашу библиотеку ажурном користећи inotify. Захтева %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Омогућава контролу Quod Libet-а користећи MPRIS 2 D-Bus спецификацију " #~ "сучеља." #~ msgid "Searching for lyrics…" #~ msgstr "Тражим текст…" #, fuzzy #~ msgid "broker username" #~ msgstr "Име домаћина посредника" #, fuzzy #~ msgid "broker password" #~ msgstr "Порт посредника" #, fuzzy #~ msgid "<artist>" #~ msgstr "уметник" #, fuzzy #~ msgid "<album>" #~ msgstr "албум" #, fuzzy #~ msgid "<title>" #~ msgstr "наслов" #, fuzzy #~ msgid "OK" #~ msgstr "_У реду" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Извози метаподатке одабраних песама као .tags датотеку." #~ msgid "Import Metadata" #~ msgstr "Увези метаподатке" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Увози метаподатке одабраних песма из .tags датотеке." #~ msgid "Migrate Metadata" #~ msgstr "Премести метаподатке" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Копира quodlibet метаподатке између песама." #~ msgid "_Copy" #~ msgstr "_Умножи" #~ msgid "_Paste" #~ msgstr "_Убаци" #~ msgid "Information to copy/paste" #~ msgstr "Информација за умножавање/убацивање" #~ msgid "Map tracks by disc and track number" #~ msgstr "Мапира записе по диску и броју записа" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Омогућите ово када желите да пребаците метаподатке са једног албума на " #~ "други подударно са бројем диска и записа.\n" #~ "\n" #~ "<b>Упозорење:</b> ово мора бити омогућено када су метаподаци умножени да " #~ "би информација записа била сачувана." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Има %d сачуван запис." #~ msgstr[1] "Има %d сачувана записа." #~ msgstr[2] "Има %d сачуваних записа." #~ msgid "Unsupported file type" #~ msgstr "Неподржан тип датотеке" #~ msgid "Unable to add station" #~ msgstr "Не могу да додам страницу" #~ msgid "Search Library" #~ msgstr "Претражи библиотеку" #~ msgid "_Search Library" #~ msgstr "_Претражи библиотеку" #~ msgid "Quit Program" #~ msgstr "Изађи из програма" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Спречава GNOM чувара екрана да се активира када је у току репродукција " #~ "песме." #~ msgid "No lyrics found" #~ msgstr "Нема нађеног текста" #~ msgid "_Zoom level:" #~ msgstr "_Увеличавање ниво:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Тражи преко горњег URL-а ако текст не може бити пронађен на LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Алтернативна претрага" #~ msgid "Web Lyrics" #~ msgstr "Веб текст" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Прикажи бочну траку која садржи текст са интернета за тренутну песму." #~ msgid "Skip Songs" #~ msgstr "Прескочи песме" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "Прескаче песме са оценом једнаком или испод задатог прага." #~ msgid "Burn CD" #~ msgstr "Нарежи ЦД" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Уписује на ЦД користећи k3b, Brasero ili xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "Једиснтвено име слике за коришћење ако је одабрано" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "Слика омота за коришћење када је присиљено" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/sr_RS@latin.po�������������������������������������������������������������������0000644�0001750�0001750�00000701063�14436352625�015362� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Serbian translations for PACKAGE package # Преводи на српски језик за пакет „PACKAGE“. # Copyright (C) 2019 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2019. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2021-11-05 03:34+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Serbian (latin) <https://hosted.weblate.org/projects/" "quodlibet/quodlibet/sr_Latn/>\n" "Language: sr_RS@latin\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.9-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Naziv" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "ljudi" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 #, fuzzy msgid "_Date Added" msgstr "_Datum zaglavlje" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Izvorni datum" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Žanr" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Ocena" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Broj puštanja" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Razvrstaj _po…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Postavke" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Lista albuma" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Lista albuma" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Svi albumi" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albuma" msgstr[2] "%d albuma" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Ponovo učitaj _omot albuma" msgstr[1] "Ponovo učitaj _omota albuma" msgstr[2] "Ponovo učitaj _omota albuma" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Pesme nisu u albumu" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d zapis" msgstr[1] "%d zapisa" msgstr[2] "%d zapisa" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d diska" msgstr[2] "%d diskova" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Primer albuma" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Postavke liste albuma" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Prikaži _omote albuma" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_Pretraga uključuje ljude" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Opcije" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Prikaz Albuma" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Zatvori" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Pretraživač biblioteke" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d pesma" msgstr[1] "%d pesme" msgstr[2] "%d pesama" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Neispravan obrazac" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Biblioteka albuma" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Biblioteka albuma" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Nepoznat %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Više %s vrednosti" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Prilagođeno" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Dodaj" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Ukloni" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Oznaka" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Spoji" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Postavke biblioteke albuma" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Primeni" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Otkaži" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Mreža omota" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Mreža omota" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Postavke mreže omota" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Prikaži _tekst albuma" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Prikaži stavku \"Svi albumi\"" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Širok režim" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Uveličavanje omota" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Sistem datoteka" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Sistem datoteka" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Ne mogu da umnožim pesme" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "Odabrane stavke ne mogu biti umnožene u drugi niz ili listu pesama." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Dodaj u biblioteku" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Lista stanica podržava samo lokacije stanica, ne druge liste stanica ili " "liste reprodukcije. Sledeće lokacije ne mogu biti učitane:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internet radio" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Sve stanice" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Preuzimam listu stanica" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Nova stanica" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Unesite lokaciju internet radio stanice:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronska" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip hop / Rep" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Stara" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japanska" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indijska" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Duhovna" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Tabele" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turska" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Rege / Za ples" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latino" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Fakultetski radio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Razgovor / Vesti" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambientalna" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Džez" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasična" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativna" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Kantri" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Vesti" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Šlageri" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Fank" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indi" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Bluz" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Za odmaranje" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Pank" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Regeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slovenska" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grčka" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotika" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rok" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Da li želite da učitate listu popularnih radio stanica?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Učitaj stanice" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internet radio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Sve stanice" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Omiljeno" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Nema kategorije" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Nova stanica…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Ažuriraj stanice" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Nisu pronađene stanice" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Internet stanica nije nađena na %s." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Izlistane stanice su već u vašoj biblioteci." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Dodaj u omiljene" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Ukloni iz omiljenih" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d stanica" msgstr[1] "%(count)d stanice" msgstr[2] "%(count)d stanica" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Pano pretraživač" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Pano pretraživač" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Odaberi _sve" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nepoznato" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Sve" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Malo" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Široko" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Kolonar" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Označi šablon opcionim obeležjima npr. <tt>kompozitor</tt> ili\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Postavke pano pretraživača" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Izgled kolona" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Sadržaj kolona" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Jednaka širina panoa" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Lista izvođenja" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Lista izvođenja" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Ukloni sa liste izvođenja" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Novo" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Uvezi" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Ne mogu da uvezem listu izvođenja" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet ne može da uvozi liste puštanja u M3U/M3U8 i PLS formatima." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Obriši" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Preimenuj" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Ne mogu da preimenujem listu puštanja" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Uvezi listu izvođenja" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Uvezi" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Nova lista izvođenja…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Šta želite da uradite sa ovom %d pesmom?" msgstr[1] "Šta želite da uradite sa ove %d pesme?" msgstr[2] "Šta želite da uradite sa ovih %d pesama?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Potvrdi radnju za listu izvođenja \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "prazno" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Primer liste izvođenja" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Postavke pretraživača liste izvođenja" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Prikaz liste izvođenja" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Da li ste sigurni da želita da izbrišete listu izvođenja '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Sve informacije o odabranoj listi izvođenja će nepovratno biti izbrisane." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Zapis" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Nova lista izvođenja" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Unesite ime za novu listu izvođenja:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Uvozim listu izvođenja.\n" "\n" "%(current)d/%(total)d dodato pesama." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Novi izvor" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Unesi lokaciju audio izvora:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Dodaj datoteku…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Osveži" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Ne mogu dodati izvor" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s ne može biti dodat. Možda je server nedostupan ili izvor nije audio zapis." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Trenutna audio podrška ne podržava URL, pretraživač audio izvora je " "onemogućen." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Ograniči rezultate" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Dozvoli više pretraga" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Lista zapisa" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Lista zapisa" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud pretraživač" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Pretraga" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Moji zapisi" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Idi na %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Povezan" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet je povezan, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Odjavi se sa %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Unesi kod…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Prijavi se na %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud autentifikacija" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Unesite Soundcloud autentifikacioni kod:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nije pokrenut (dodaj '--run' za pokretanje)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "muzička biblioteka i plejer" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[opcija]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Odštampaj puštenu pesmu i izađi" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Odmah počni izvođenje" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Ne prikazuj prozore pri pokretanju" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Skoči na sledeću pesmu" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Skoči na prethodnu pesmu ili pusti ponovo ako je pri početku" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Skoči na prethodnu pesmu" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Pokreni izvođenje" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pauziraj izvođenje" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Menjaj pusti/pauziraj režim" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Zaustavi izvođenje" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Pojačaj" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Smanji" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Povećaj ocenu trenutne pesme za jednu zvezdicu" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Umanji ocenu trenutne pesme za jednu zvezdicu" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Odštampaj stanje plejera" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Sakrij glavnu prozor" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Prikaži glavni prozor" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Promeni vidljivost glavnog prozora" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokusiraj pokrenuti plejer" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Ukloni filtere aktivnog pretraživača" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Osveži i pretraži biblioteku" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Izlistaj dostupne pretraživače" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Odštampaj trenutnu listu izvođenja" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Odštampaj sadržaj niza" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Odštampaj upit aktivnog teksta" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Pokreni bez priključaka" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Pokreni Quod Libet ako nije pokrenut" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Napusti Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Premotaj trenutnu pesmu" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Postavi ili promeni režim mešanja" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Postavi tip režima mešanja" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Uključi ili isključi ponavljanje" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Promeni tip ponavljanja" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Podesi jačinu" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Pretraži svoju audio biblioteku" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "upit" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Reprodukuj datoteku" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "ime datoteke" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Oceni trenutnu pesmu" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Postavi trenutni pretraživač" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Zaustavi nakon završetka pesme" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Otvori nov pretraživač" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Prikaži ili sakrij zahteve" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtriraj po nasumičnoj vrednosti" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "oznaka" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filitriraj po vrednošću oznake" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "oznaka=vrednost" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Nanizati datoteku ili zahtev" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Nanizati zarezom razdvojene datoteke" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "ime datoteke" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Štampaj imena datoteka rezultata zahteva na stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Izbaci iz niza datoteku ili zahtev" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Dodaj datoteku ili direktorijum u biblioteku" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "lokacija" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "šablon" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Nevažeći argument za '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Pokušaj %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Došlo je do greške" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Možete zanemariti ovu grešku, ali aplikacija može biti nestabilna dok se ne " "pokrene ponovo. Prijavljivanje greške traje nekoliko sekundi a nama pomaže " "puno." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Prijavi grešku" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Zanemari grešku" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Detalji greške:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Razni detalji o grešci i vašem sistemu će biti poslati trećoj strani na " "internetu (<a href='https://www.sentry.io'>www.sentry.io</a>). Ispod možete " "pregledati podatke pre slanja." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(opciono) Ukratko opišite šta se desilo kada je došlo do greške:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Pošalji" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Kratak opis…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Podaci za slanje:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "uređivač audio oznaka" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "direktorijum" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Uređivač audio metapodataka" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL izvor omota" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Preuzima povezane omote po artwork_url oznaci. Ovo radi sa Soundcloud " "pretraživačem." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs izvor omota" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Preuzima omote sa Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm izvor omota" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Preuzima omote iz Last.fm arhive." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz izvor omota" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Preuzima omote iz MusicBrainz arhive." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Preobrati enkodiranja" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Popravlja pogrešno protumačene vrednosti oznake enkodiranja u uređivaču " "oznaka." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Preobrati enkodiranja…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji pretvarač uzorka" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Pretvara kana/kanji na romaji pre preimenovanja." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Romanizuje _Japanski tekst" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Ne mogu pronaći \"Kanji Kana Simple Inverter\" (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Zamena regularnog izraza" #: quodlibet/ext/editing/resub.py:20 #, fuzzy msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Dozvoljava zadatu zamenu regularnog izraza (s///) pri označavanju ili " "preimenovanju datoteka." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Veliko slovo" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Veliko-slovo vrednosti oznaka u uređivaču oznaka." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Veliko-_slovo vrednost" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Dozvoli _SVE-VELIKA slova u oznakama" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "_Ljudska velika slova" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Koristi uobičajena englska pravila za velika slova, kao što je \"Dark Night " "of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Napredne postavke" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Dozvoli menjanje naprednih podešavanja konfiguracije." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Znam šta radim" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Animirani Na-Ekranu prikaz" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Prikazuje informacije o pesmi na ekranu pri promeni pesme." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Pozicija:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Veličina omota:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Prikaz" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Font:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Levo" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Centar" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Desno" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Izravnaj tekst:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Tekst" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Tekst:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Ispuni:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Boje" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Senke" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Spoljna linija" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Okru_gli uglovi" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Kašnjenje:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efekti" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ur_edi šablon prikaza…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Pregled" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informacije o aplikaciji" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Razne informacije o aplikaciji i njenom okruženju." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Podržani formati" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Direktorijum konfiguracije" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Keš direktorijum" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Audio pozadina" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 #, fuzzy msgid "After every play (default)" msgstr "Vrati na podrazumevano" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "Ne mogu kontaktirati servis '%s'." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "Ažuriraj oznake u datotekama" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 #, fuzzy msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Ažurira izmenjene oznake u datotekama. Ovo će osigurati da su broj puštanja " "i ocene ažurirane." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Sačuvaj ocene i _broj puštanja u oznakama" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "datum snimanja" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Greška pri sinhronizaciji" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Ažuriraj stanice" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Postavke" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Automatsko maskiranje" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "Automatski maskira i demaskira uređaje u toku kačenja ili otkačivanja." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Automatsko ocenjivanje" #: quodlibet/ext/events/autorating.py:16 #, fuzzy msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Automatski ocenjuje pesme kada su puštene ili preskočene. Ovo koristi " "\"ubrzani\" algoritam sa vux od Brajana Nelsona." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Određuje da li je Banshee baza podataka nedostupna ili loše formirana" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Uvoz neuspešan" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Uspešno uvezene ocene i statistika za %d pesmu" msgstr[1] "Uspešno uvezene ocene i statistika za %d pesme" msgstr[2] "Uspešno uvezene ocene i statistika za %d pesama" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee uvoz" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Uvozi ocene i statistiku pesme iz Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Baza podataka:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Počni uvoženje" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Budilnik" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Budi vas pomoću glasne muzike." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Uspavanka" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Smanjuje i pauzra muziku." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Gajim status poruke" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Gajim status poruke" #: quodlibet/ext/events/discord_status.py:46 #, fuzzy msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Menja Gajim statusnu poruku u ono šta trenutno slušate." #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Pauzirano:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Status tekst" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Status tekst" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Ravno" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Uživo" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Pun bas i visoki" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Klub" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Velika dvorana" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Žurka" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Meko" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Pun bas" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Rege" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Slušalice" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Meki rok" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Puni visoki" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Igra" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Tehno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Laptop" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Ekvilajzer" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Upravlja tonom muzike uz pomoć izjednačivača.\n" "Kliknite ili koristite dirke da prilagodite nivoe (desni-klik opoziva sve " "klizače)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Trenutna pozadina ne podržava izjednačavanje." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Podrazumevani odabir" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Odaberi…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Poništi EQ" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Prilagođen odabir" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Obriši odabrano" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Ime odabira za čuvanje:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Sačuvaj" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "na mreži" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "van mreže" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "ćaskanje" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "van" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "nevidljiv" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim status poruke" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Menja Gajim statusnu poruku u ono šta trenutno slušate." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "pauzirano" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Šablon:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Lista naloge, razdvojene razmakom, za promenu statusne poruke. Ako nije " "preciziran nalog, status poruka za sve naloge će biti promenjena." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Nalozi:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Dodaje '[pauziran]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Ako je označeno, '[paused]' će biti dodato u statusnu poruku kada je pesma " "pauzirana" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Statusi za koje će poruka biti izmenjena" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Pauziraj kada su slušalice otkačene" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pauzira kada su slušalice otkačene i nastavlja ako su prikačene ponovo." #: quodlibet/ext/events/inhibit.py:50 #, fuzzy msgid "Inhibit Screensaver/Suspend" msgstr "Onemogući čuvara ekrana" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Muzika svira" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Režim" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Onemogući čuvara ekrana" #: quodlibet/ext/events/inhibit.py:126 #, fuzzy msgid "Inhibit Suspend" msgstr "Onemogući čuvara ekrana" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Internet radio dnevnik" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Snima zadnjih 10 pesama puštanih na radio stanicama, i lista ih u meniju " "pretrage." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, fuzzy, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Šalje Jabber User Tunes datoteku u ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Promeni jezik" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Menja jezik korisničkog sučelja." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Podrazumevana podešavanja" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Ponovno pokretanje je potrebno da bi izmene imale efekat" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Media Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Izlaže sve albume na Rygel UPnP Media Server kroz MediaServer2 D-Bus sučelje." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Osigurava da je sledeće u vašoj rygel konfiguracionoj datoteci (~/.config/" "rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD Server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Dozvoljava daljinsko upravljanje Quod Libet-om koristeći MPD klijent. Strim, " "liste izvođenja i biblioteka nisu podržani." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Port:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Lokalna _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "L_ozinka:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Veza" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Testirani klijenti" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus podrška" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Sakrij glavni prozor pri zatvaranju" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Prihvata QL šablone npr. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT objavljivač" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Objavljuje statusne poruke na MQTT temu." #: quodlibet/ext/events/mqtt.py:137 #, fuzzy msgid "Broker hostname / IP" msgstr "Ime domaćina posrednika" #: quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Defaults to localhost" msgstr "ime domaćina posrednika / IP (podrazumevano na localhost)" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Port posrednika" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "port posrednika (podrazumevano na 1883)" #: quodlibet/ext/events/mqtt.py:142 #, fuzzy msgid "Broker username" msgstr "Ime domaćina posrednika" #: quodlibet/ext/events/mqtt.py:144 #, fuzzy msgid "Broker password" msgstr "Port posrednika" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Tema" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Obrazac reprodukcije" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Status tekst kada je pesma puštena." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Obrazac pauze" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Tekst kada je pesma pauzirana." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Tekst bez pesme" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Prazan tekst kada nema puštene pesme" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT konfiguracija" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Status tekst" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Povezan ka posredniku na %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Ne mogu da povežem %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Greška pri povezivanju" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz pretraga" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Dozvoljava ocenjivanje brojem." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Korisničko_ime:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Lozinka:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Nalog" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Tekst obaveštenja" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Naziv:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Vrati na podrazumevani obrazac" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Telo:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Prikaži obaveštenja" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Prikaži obaveštenja" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Samo na <i>_manual</i> promeni pesme" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Samo na <i>_automatic</i> promeni pesme" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "Na <i>a_ll</i> promeni pesme" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Samo kada glavni prozor nije u _fokusu" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Prikaži taster \"_Sledeće\"" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Greška pri povezivanju" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Ne mogu da povežem servis obaveštenja." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Obaveštenje pesme" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Prikazuje obaveštenja pri promeni pesme." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Sledeće" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Obaveštenje pesme" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Molimo posetite prozor dodataka da podesite QLScrobbler. Do tada, pesme neće " "biti priložene." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Ne mogu kontaktirati servis '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Autentifikacija neuspela: nevažeći URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Autentifikacija neuspela: Nevažeće korisničko ime '%s' ili pogrešna lozinka." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Zabranjen pristup. Kontaktirajte autora." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Pogrešno sistemsko vreme. Dostava možda neće uspeti dok se to ne ispravi." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler dostava" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler klijent za Last.fm, Libre.fm i druge Audioscrobbler servise." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Autentifikacija uspešna." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Servis:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Drugo…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Proveri podatke naloga" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Umetnik šablon:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Naslov šablon:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Izuzmi _filter:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Šablon za formatiranje imena umetnika za dostavu. Ostavite prazno za " "podrazumevano." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Šablon za formatiranje imena naslova za dostavu. Ostavite prazno za " "podrazumevano." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Pesme koje se podudaraju ovim filterom neće biti dostavljene" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Režim van mreže (ne dostavljaj ništa)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Dostava" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Ućutkaj radio reklame" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Ućutkuje izlaz kada su reklame na radio stanici.\n" "Stanice: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Nasumično izvođenje albuma" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Pušta nasumično odabran album kada lista izvođenja dođe do kraja. Zahteva da " "vaš aktivni pretraživač podržava filtriranje po albumu." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Bolje ocenjeno" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Češće puštano" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Češće preskakano" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Skoro puštano" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Skoro pokretano" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Skoro dodato" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Duži albumi" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sekundi pre početka sledećeg albuma" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Značaj" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Puštaj neke albume češće od drugih" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "izbegni" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "preferiraj" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Nasumičan album" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Čekam da počne %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Uspešno uvezene ocene i statistika za %d pesama" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox uvoz" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Uvozi ocene i statistike pesme sa Rhythmbox-a." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Pauza čuvara ekrana" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pauzira pesmu kada je GNOME čuvar ekrana aktiviran." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "GNOME Shell pretraživač za Quod Libet nije instaliran." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME pretraživač" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Dozvoli GNOME Shell da pretražuje biblioteku." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternativna traka motanja" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternativna traka motanja koja je uvek vidljiva i prelazi preko celog " "prozora." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Obeleživači tačke motanja" #: quodlibet/ext/events/seekpoints.py:24 #, fuzzy msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Čuva tačke motanja A i/ili B za zapise. Preskoči do tačke A i zaustavi nakon " "tačke B prilikom reprodukcije.\n" "Obratite pažnju da promena imena tačaka ispod ne ažurira imena obeleživača, " "samo menja koja imena obeleživača će dodatak tražiti za odluku kada da mota." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Ime obeleživača tačke A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Ime obeleživača koje će biti potraženo kada je zapis pokrenut, i ako je " "nađeno mota do vremena tačke" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Ime obeleživača tačke B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Ime obeleživača koje će koristiti svaki tik pri reprodukciji zapisa ako " "postoji. Ako trenutna pozicija prevazilazi vreme tačke, ide na kraj zapisa." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox Sinhronizacija" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Čini da Logitech Squeezebox oponaša Quod Libet izlaz, ukoliko oba čitaju " "identičnu biblioteku." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Greška u pronalaženju Squeezebox servera" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Greška pronalaženja %s. Molimo proverite podešavanja" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Opcije" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "enkodiranje" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "datum snimanja" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "_Obriši" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "_Obriši" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 #, fuzzy msgid "Skipped existing file" msgstr "Češće preskakano" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Odredišna fascikla:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Šablon putanje" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Uredi saćuvane šablone…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Umetnik šablon:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "Pregled" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Izvori" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Izvezi metapodatke" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organizacija" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Odredište čuvanja" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Putanja nije apsolutna" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Šablon\n" "\t<b>%s</b>\n" "sarži / ali ne počinje od korena. Da bi izbegli pogrešno imenovane fascikle, " "korenujte svoj šablon početkom sa / ili ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Ni jedna pesma nije odabrana." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Ni jedna pesma nije odabrana." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Ne mogu da sačuvam pesmu" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "Češće preskakano" msgstr[1] "Češće preskakano" msgstr[2] "Češće preskakano" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Neuspešno učitavanje datoteke: %r" msgstr[1] "Neuspešno učitavanje datoteke: %r" msgstr[2] "Neuspešno učitavanje datoteke: %r" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronizedlyrics.py:30 #, fuzzy msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Pokazuje sinhronizovani tekst pesme iz .lrc datoteke sa istim imenom kao i " "zapis." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Pozadina:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Font" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Veličina (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy status poruke" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Ažurira sve Telepathy bazirane IM naloge (kako je konfigurisano u Empathy " "itd.) sa statusnom porukom baziranom na trenutnoj pesmi." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Pušteno:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Status tekst kada je pesma započela. Prihvata QL šablone npr. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Pauzirano:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Status tekst kada je pesma pauzirana. Prihvata QL šablone npr. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Prazan tekst za status kada ništa nije pušteno" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Nema pesme:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Status šabloni" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Promena teme" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Menja trenutnu GTK+ temu." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Podrazumevana tema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Poželjnija tamna tema" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Palac ocena" #: quodlibet/ext/events/thumbrating.py:90 #, fuzzy msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Dodaje palac gore/dole sistem ocenjivanja konvertovan u vrednost ocene. " "Korisno za praćenje celokupnih glasova i sortiranje sa '~#score'." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Menjaj traku izbora" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Menja traku izbora koristeći alt dugme (vidljiva/nevidljiva)." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Ne svira" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Traka zadataka" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Upravlja Quod Libet-om iz trake zadataka." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Prikaži %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Pusti" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_auziraj" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "Pre_thodno" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Sledeće" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Mešaj" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Ponavljaj" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Zaustavi _posle ove pesme" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Otvori _pretraživač" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Izmeni _oznake" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Informacije" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Lista _izvođenja" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Odustani" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Ponašanje" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Skrol menja jačinu tona" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Skrol menja pesmu" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Skrol _točak" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Oblačić informacija" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Pogledaj tekst" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Automatski prikazuje oznake ili tekst pesme iz datoteke." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Tekst nije nađen za\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Nema aktivne pesme" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Pokreni vizualizacije" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Pokreni spoljne vizualizacije." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Ne mogu pokrenuti vizualizacije koristeći '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Greška" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Pokretač vizualizacija:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Napuni" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Talasna traka motanja" #: quodlibet/ext/events/waveformseekbar.py:605 #, fuzzy msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "Traka motanja u obliku talasa trenutne pesme." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Koristi boju prednjeg dela:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Koristi boju plutanja:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Koristi za ostale boje:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Prikaži trenutnu poziciju" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Prikaži imena vremena" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Korak motanja prilikom skrolovanja (milisekunde):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Čuvač slika" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Čuva sliku omota trenutne pesme u datoteku." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Datoteka:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Prag:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Prag dok filter ne bude aktiviran" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "O_dnos:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Odnos kompresije" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Audio kompresor" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "Menja opseg svih uzoraka iznad određenog praga sa određenim odnosom." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Odabir:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Filtriraj odabir" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frekvencija odsecanje:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Niski-prolaz filter frekvencija odsecanja" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Izvor _nivo:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Izvor nivo" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Podrazumevano" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Najbliže poziciji virtuelnog zvučnika (30°, 3 metra)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Blizu Chu Moy ukrštenog izvora (popularno)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Blizu Jan Meier's CORDA pojačalima (mala promena)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Prilagođeno" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Prilagođena podešavanja" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Ukršten izvor" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Meša levi i desni kanal kako bi simulirao zvičnike koristeći slušalice, ili " "za usklađivanje starijih stereo snimaka." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Filter _pojas:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Frekventni pojas filtera" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Filter _širina:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Frekventni opseg filtera" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Nivo:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Nivo efekata" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Uklanja glas iz audio zapisa." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono spuštanje" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Spušta audio kanale na mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "U_čestalost:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Stepen:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Audio stepen / brzina" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Upravlja brzinom audio izvora." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Izvezi listu izvođenja u fasciklu" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "_Izvezi" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Odredišna fascikla:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Šablon imena datoteke:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Izvozi listu izvođenja kopirajući datoteke u fascikle." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Ne mogu da izvezem listu izvođenja" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Uverite se da imate pristup zapisivanju na odredište." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Podrazumevan šablon imena datoteka:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_U redu" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Izvezi kao listu izvođenja" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "Izvozi listu izvođenja kopirajući datoteke u fascikle." #: quodlibet/ext/playlist/export_to_sonos.py:246 #, fuzzy msgid "Error finding Sonos device(s)" msgstr "Greška u pronalaženju Squeezebox servera" #: quodlibet/ext/playlist/export_to_sonos.py:247 #, fuzzy msgid "Error finding Sonos. Please check settings" msgstr "Greška pronalaženja %s. Molimo proverite podešavanja" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Izvezi u Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 #, fuzzy msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dinamički izvozi listu izviđenja u Logitech Squeezebox listu, ukoliko dele " "strukturu direktorijuma. Deli konfiguraciju sa <a href=\"quodlibet:///prefs/" "plugins/Squeezebox Output\">Squeezebox Sync plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Izvezi listu izvođenja u Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Ime liste izvođenja (prepisuje postojeće)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Izvezi u Squeezebox listu izvođenja" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Ukloni duplikate iz liste izvođenja" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Uklanja duplikate iz liste izvođenja." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Da li ste sigurni da želite da uklonite %d duplikat?" msgstr[1] "Da li ste sigurni da želite da uklonite %d duplikata?" msgstr[2] "Da li ste sigurni da želite da uklonite %d duplikata?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Duplikati će biti uklonjeni iz liste izvođenja '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Mešaj listu izvođenja" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Nasumično meša listu izvođenja." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "Prati pokazivač" #: quodlibet/ext/playorder/follow.py:20 #, fuzzy msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Reprodukcija prati vaš odabir, ili sledeću pesmu ukoliko je lista iscrpljena." #: quodlibet/ext/playorder/follow.py:22 #, fuzzy msgid "Follow cursor" msgstr "Prati pokazivač" #: quodlibet/ext/playorder/follow.py:23 #, fuzzy msgid "_Follow cursor" msgstr "Prati pokazivač" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Ujednačivač broja puštanja" #: quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Meša i daje prednost pesmama koje su ređe puštane." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Poželi manje puštane" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "Poželi manje puštane" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Samo Niz" #: quodlibet/ext/playorder/queue.py:25 #, fuzzy msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Ograničava puštanje pesama na niz. Ako je ovaj poredak odabran, dupli-klik " "će dodati pesmu u niz umesto da je pusti." #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Samo Niz" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Samo Niz" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Okrenut" #: quodlibet/ext/playorder/reverse.py:16 #, fuzzy msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Okreće redoslet puštanja pesama." #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Okrenut" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Mešaj po grupama" #: quodlibet/ext/playorder/shufflebygrouping.py:33 #, fuzzy msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Meša tako što grupiše pesme definisane oznakama umesto zapisa, slično " "mešanju albuma." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Mešaj po grupama" #: quodlibet/ext/playorder/shufflebygrouping.py:40 #, fuzzy msgid "Shuffle by _grouping" msgstr "Mešaj po grupama" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Čekam da započnem novu grupu…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Grupisane oznake:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Oznake za grupisanje pesama" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Filter oznaka:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Grupisanje je primenjeno samo ako je filter oznaka određena.\n" "Pesma sa neodređenim filterom oznake će biti tretirana\n" "kao grupa sama za sebe. Obično filter oznake trebaju biti\n" "podudarne ili delimično podudarne grupi oznaka." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "_Kašnjenje:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Vremensko zakašnjenje u sekundama pre početka sledeće grupe" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Poništi na podrazumevano" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Ponavljaj svaki zapis" #: quodlibet/ext/playorder/track_repeat.py:30 #, fuzzy msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "Meša pesme, ali ponavlja svaki zapis postavljenim brojem puta." #: quodlibet/ext/playorder/track_repeat.py:32 #, fuzzy msgid "Repeat each track" msgstr "Ponavljaj svaki zapis" #: quodlibet/ext/playorder/track_repeat.py:33 #, fuzzy msgid "Repeat _each track" msgstr "Ponavljaj svaki zapis" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Broj puta puštanja svake pesme:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Okolnosni upit" #: quodlibet/ext/query/conditional.py:16 #, fuzzy msgid "Chooses the query to match based on a condition query." msgstr "" "Bira upit koji se podudara sa situacionim upitom. Sintaksa je '@(if: " "condition, then, else)'." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Nedostajući upit" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Uparuje pesme bez dodeljene oznake." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Uključi prazne oznake" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python upit" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Izraz oznake" #: quodlibet/ext/query/pythonexpression.py:23 #, fuzzy msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "Koristi Python izraz u upitima. Sintaksa je \"@(python: expression)\". " "Promenljiva \"s\" (ili \"a\") je podudarna pesma / album. \"_ts\" je " "vremenska oznaka na početku upita. Moduli \"vreme\" i \"nasumično\" su " "dostupni, i klasa \"Nasimično\" (==random.Random) takođe." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Uključi sačuvanu pretragu" #: quodlibet/ext/query/savedsearch.py:21 #, fuzzy msgid "💾 Include the results of a saved search as part of another query." msgstr "" "Uključuje rezultate sačuvanih pretraga kao deo drugog upita. Sintaksa je " "'@(saved: search name)'." #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Sačuvana pretraga" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 #, fuzzy msgid "@(unique: tag)" msgstr "jedisntven" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox je u redu. Koristim samo (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Ne mogu da se povežem na %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Ime domaćina:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Korisničko ime:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Lozinka:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Direktorijum biblioteke povezivanja servera" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Putanja biblioteke:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Proveri postavke" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox server" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Ispitaj" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox server na {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "neidentifikovani Squeezebox server" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "neidentifikovani Squeezebox plejer: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Odaberi Squeezebox plejer" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Pronađen Squeezebox server.\n" "Molimo odaberite plejer" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Uklopi sliku u _prozor" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "Vidi '[plugins] cover_filenames' konfiguraciju za ime slike" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Uredi sliku nakon čuvanja" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Ime _datoteke:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Neuspešno čuvanje" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "Ne mogu da sačuvam \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP greška: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Preuzimač omota" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "iz %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Rezolucija: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Veličina: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Po pokretaču \"najbolji\" rezultat ograničenje" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Pretraga" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Tražim…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Završeno" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Preuzmi omot albuma" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Preuzima omote albuma sa različitih internet adresa." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Izvori" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 na ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Pretvara vaše APEv2 oznake u ID3v2 oznake. Ovo će obrisati APEv2 oznake " "nakon preobražaja." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Idi na obeleživač" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Uređuje obeleživače u odabranim datotekama." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "_Uredi obeleživače…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Bez obeleživača" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz pretraga" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Naznači album baziran na MusicBrainz pretrazi." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Koristi samo godinu za \"datum\" oznaku" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Upiši \"_albumartist\" kada je potrebno" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Upiši poredak oznaka za imena umetnika" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "Upiši _standard MusicBrainz oznake" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "Upiši \"labelid\" oznaku" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Ime datoteke" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Zapis" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Naziv" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Umetnik" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz pretraga" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Upit:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "P_retraga" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Rezultati <i>(prevuci za promenu)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Molimo upišite upit." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Došlo je do greške. Pokušajte ponovo." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Učitavam rezultate…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Nema rezultata." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python konzola" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interaktivna Python konzola. Otvara novi prozor." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} za {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python konzola bočna stranica" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Bočna strana za interaktivnu Python konzolu koja prati odabrane pesme u " "glavnom prozoru." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Možete pristupiti sledećim podrazumevanim objektima:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Vaš trenutni radni direktorijum je:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Veza" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Preuzimanje omota" #: quodlibet/ext/songsmenu/cover_download.py:54 #, fuzzy msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Preuzima omote visokog kvaliteta koristeći dodatak omota." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klasično" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Veliko" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Omot preuzimanje" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Učitavam %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, fuzzy, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Ništa nije pronađeno za albume:\n" "<i>%(albums)s</i>.\n" "\n" "Korišćeni izvori:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Nema pronađenih omota" #: quodlibet/ext/songsmenu/cover_download.py:322 #, fuzzy, python-brace-format msgid "{size} ✕ {size} px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Veličina pregleda" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Odredište čuvanja" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Komanda" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "ime" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Ime ove komande" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "komanda" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Sintaksa komande školjke za pokretanje" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "parametar" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Ako je naznačeno, parametar koji se pojavljuje u komandama će biti zamenjen " "vrednošću datom od strane korisnika, npr. koristeći 'PARAM' u svim " "slučajevima '{PARAM}' u vašoj komandi, imaće vrednost datu kada je pokrenuto" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL šablon, npr. <~filename>, za izračunavanje vrednosti komande. Za liste " "izvođenja, ovo podržava virtuelne oznake <~playlistname> i <~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "jedisntven" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" "Ako je postavljeno, ovo će ukloniti duplikate izračunatih vrednosti šablona" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "maks args" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "Najveći broj argumenata poslatih komandi u datom trenutku (kao xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Okrenut" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Vrednost ulaza" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Vrednost za %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Prilagođene komande" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Pokreće prilagođene komande (u gomili ako je potrebno) za pesme koristeći " "bilo koje oznake." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Uredi prilagođene komande" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "Ne mogu da pokrenem prilagođenu komandu %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplikat" msgstr[1] "%d duplikata" msgstr[2] "%d duplikata" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Suzi / Proširi sve" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Zajednički izraz duplikata je '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Pretraživač duplikata" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Pronalazi i prikazuje slično označene verzije pesama." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Prihvata QL izraz oznake kao <tt>~artist~title</tt> ili " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Grupiše duplikate po:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Duplikat ključ" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "Ukloni _beo prostor" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "Ukoni _dijakritike" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "Ukoni _interpunkcije" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Slovo _neosetljivo" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Opcije podudaranja" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Uredi broj puštanja" #: quodlibet/ext/songsmenu/editplaycount.py:21 #, fuzzy msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Uredi pesmin ~#playcount i ~#skipcount.\n" "\n" "Kada je odabrano više pesama, broj će se povećavati.\n" "\n" "Kada je ~#playcount pesme podešen na 0, ~#lastplayed i ~#laststarted unosi " "će biti očišćeni. Ali, kada se podesi 0-puštanja pesmi na pozitivnu " "vrednost, broj puštanja neže biti kreiran." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Broj puštanja" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Broj preskakanja" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Više %s vrednosti" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Uredi ugrađene slike" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Uklanja ili zamenjuje ugrađene slike." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Ukloni sve slike" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "_Ugradi trenutnu sliku" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Podesi tačnu ocenu" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Dozvoljava ocenjivanje brojem." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Molimo ocenite na skali od 0.0 do 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Filtriraj po bilo kojoj oznaci" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Kreira pretragu baziranu na oznakama odabranih pesama." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Filtriraj po direktorijumu" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filtrira po direktorijumu u novom prozoru." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Zvučni otisak pretraga" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Traži metapodatke pesme preko zvučnog otiska." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Priloži zvučni otisak" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Generiše zvučni otisak koristeći chromaprint i prilaže ih na acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "Nedostaje API ključ" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Morate da naznačite acoustid.org API ključ u opcijama dodatka pre nego što " "priložite." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "Zahtevaj API ključ" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _ključ:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID veb servis" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Pripremljeno" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Analiziram" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Pretraga" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Piši" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Izdato" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "Upiši MusicBrainz oznake" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Grupiši po direktorijumu" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Album režim" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Upiši oznake povezane s albumima i pokušaj da umanjiš broj različitih " "izdanja albuma" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generišem otiske:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Detalji" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Pošalji" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Pesme zahtevaju <i><b>musicbrainz_trackid</b></i>, ili <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> oznake da bi bile priložene." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Otisci:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Pesme sa MBIDs:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Pesme sa dovoljnim oznakama:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Pesme za slanje:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Završeno. %(to-send)d/%(all)d pesama za slanje." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Šaljem otiske:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Šaljem…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Ažuriraj oznake u datotekama" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Ažurira izmenjene oznake u datotekama. Ovo će osigurati da su broj puštanja " "i ocene ažurirane." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Izvezi u HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Izvozi odabranu listu pesama u HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "Pošalji na iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Šalje pesme na iRiver iFP uređaj." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "Nema pronađenog iFP uređaja" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Ne mogu da povežem vaš iFP uređaj. Proverite da li je uređaj priključen, i " "da posedujete ifp-liniju (http://ifp-driver.sf.net) instaliranu." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Šaljem %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, fuzzy, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" "Ne mogu da pošaljem <b>%s</b>. Uređaj možda nema dovoljno prostora ili je " "isključen." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Greška pri slanju" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Izvezi metapodatke" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Izvezi metapodatke" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 #, fuzzy msgid "Export Tags and User Data" msgstr "Izvezi metapodatke" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 #, fuzzy msgid "Export File Stems and User Data" msgstr "Izvezi metapodatke" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Nema informacija o trajanju" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Omot albuma" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Uvoz neuspešan" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Uvezi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtriraj po direktorijumu" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "Disk" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Zapis" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "Umetnik" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "albumi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Nastavi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "Ne mogu kontaktirati servis '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Ne mogu kontaktirati servis '%s'." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Imena datoteka" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Ponavljaj svaki zapis" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Ažuriram listu obrazaca." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Već je ažurirano." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Skupljam obrasce za nedelju %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Sinhrnoizacija završena." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Greška pri sinhronizaciji" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm Sinhronizacija" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Ažurira statistiku vaše biblioteke sa Last.fm profila." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "_Korisničko ime:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Kreiraj naznake sortiranja" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Pretvara imena albuma i umetnika da sortira imena, loše." #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Izvezi kao listu izvođenja" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Izvozi pesme u M3U ili PLS listu izvođenja." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Koristi relativne putanje" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Koristi apsolutne putanje" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Upisivanje na <b>%s</b> nije uspelo." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Ponovo pretraži pesme" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Proverava promene u datotekama i ponovo učitava ili uklanja pesme ako je " "potrebno." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Ponovo pretraži pesme" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain ispitivač" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Zapis" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Napredak" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:453 #, fuzzy, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "Dostupan <b>%(to-process)s</b> album za ažuriranje (of %(all)s)" msgstr[1] "Dostupno <b>%(to-process)s</b> albuma za ažuriranje (of %(all)s)" msgstr[2] "Dostupno <b>%(to-process)s</b> albuma za ažuriranje (of %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Ispituje i ažurira <a href=\"%(rg_link)s\">ReplayGain</a> informacije " "koristeći GStreamer. Rezultati su grupisani po albumu." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "uvek" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "ako nedostaju <b>any</b> RG oznake" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "ako nedostaju <b>album</b> RG oznake" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "_Obrada albuma:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Izlazne oznake" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Podeli oznake" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Deli broj diska iz albuma i verzije sa imenom istovremeno." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Podeli album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Podeli broj diska." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/d" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Poništi" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Tap" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "Tap BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Tap BPM za odabranu pesmu." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Pretraži veb" #: quodlibet/ext/songsmenu/website_search.py:38 #, fuzzy, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Pretražuje vaš izbor stranice koristeći bilo koje oznake.\n" "Podržava šablone npr. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "Pretraga URL šablona" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "Uredi pretragu URL-a" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Konfiguriši pretragu…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Pretraži oznaku u Vikipediji" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Otvara prozor u pregledaču sa stranicom članka Vikipedije za odabranu oznaku " "pesme." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "Potraži na %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Uredi oznake" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Pretraga nije uspela" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Oznaka \"%s\" nije nađena." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Biblioteka" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Proveravam priključne tačke" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Pretraga biblioteke" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Pretraga %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Učitavam datoteke" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Pretraga biblioteke" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Ukloni filtere aktivnog pretraživača" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Muzički plejer i organizator biblioteke" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Neuspešno učitavanje datoteke: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Izlistaj oznake" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Štampaj sažet izlaz" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Kolone za prikazivanje i redosled u sažetom režimu (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Takođe izlistaj pragmatične oznake" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Nedovoljno argumenata" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Previše argumenata" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Opis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Vrednost" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Izlistaj sve učestale oznake" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Umnoži oznake sa jedne na drugu datoteku" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Prikaži promene, ali ih ne primenjuj" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Preskoči oznake koje se ne mogu upisati" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Ne mogu da umnožim {tagname} u datoteku: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Uredi oznake u uređivaču teksta" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Uređivanje prekinuto" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Pokretanje uređivača teksta '%(editor-name)s' nije uspelo." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Nema uočenih promena" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Postavi oznaku i ukloni postojeće vrednosti" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Ne mogu postaviti %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Ukloni oznake" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Vrednost je običan izraz" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Ukoni sve oznake" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Ne mogu da kombinujem '--all' sa '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Ne mogu ukloniti {tagname} iz {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Ukloni vrednost oznake" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Dodaj vrednost oznake" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Ne mogu postaviti %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Izlistaj informacije o datoteci" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Postavi ponuđenu sliku kao primarnu ugrađenu sliku i ukloni sve ostale " "ugrađene slike" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Neuspešno učitavanje slike: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "Nepodržano uređivanje slike za %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Ukoni sve ugrađene slike" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Izvezi ugrađene slike na %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Putanja gde će slike biti sačuvane (podrazumevano je radni direktorijum)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Preimenuj datoteke koristeći oznake" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Ispuni oznake koristeći putanju datoteke" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Datoteka" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Ispuni broj pesme za sve datoteke" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Štampaj oznake po određenom šablonu" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Prikaži pomoćne informacije" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' nije važeče ime kolone (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Nepoznato" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Po redu" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Po redu" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Nasumično" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Nasumično" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Preferiraj bolje ocenjene" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "Preferiraj bolje ocenjene" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Ponovi ovaj zapis" #: quodlibet/order/repeat.py:44 #, fuzzy msgid "Repeat _this track" msgstr "Ponovi ovaj zapis" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Ponovi sve" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "Ponovi sve" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Jedna pesma" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Jedna pesma" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Strim" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Punjenje memorije" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Ne mogu stvoriti GStreamer pipeline" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Nije pronađen ni jedan GStreamer element za obradu formata" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Format zapisa: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer dodatak '%(name)s' ne može biti pokrenut" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer output pipeline korišćen za reprodukciju. Ostavite prazno za " "podrazumevani. U drugim slučajevima, koristiće se pordrazumevani." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Output pipeline:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f dB" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buffer duration:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Onemogući _gapless reprodukciju" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Onemogućavanje gapless reprodukcije može izbeći probleme pri menjanju pesama " "sa nekim verzijama GStreamer-a" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Nema nađenog GStreamer audio sink" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Nevažeća GStreamer izlazna pipeline" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Ne mogu da kreiram audio izlaz" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Audio uređaj %r nije pronađen. Proverite Xine podešavanja u ~/.quodlibet/" "config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Ne mogu da nađem modul '{module}'. Možda je potrebno da instalirate paket?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Ne mogu pronaći GStreamer element '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 #, fuzzy msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Molimo posetite prozor dodataka da podesite QLScrobbler. Do tada, pesme neće " "biti priložene." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, fuzzy, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Molimo posetite prozor dodataka da podesite QLScrobbler. Do tada, pesme neće " "biti priložene." #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Dostava" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "Korisničko_ime:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 #, fuzzy msgid "Songs matching this filter will not be submitted." msgstr "Pesme koje se podudaraju ovim filterom neće biti dostavljene" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "Pokreni dodatak \"%(name)s\" u %(count)s listi izvođenja?" msgstr[1] "Pokreni dodatak \"%(name)s\" u %(count)s liste izvođenja?" msgstr[2] "Pokreni dodatak \"%(name)s\" u %(count)s listi izvođenja?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Pokreni dodatak" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Početak" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Vreme" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Ime obeleživača" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Obeleživači" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filteri" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Skoro _puštano" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Skoro _dodato" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Sve _pesme" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "Po trenutnom _žanru" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Po trenutnom _umetniku" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Po trenutnom al_bumu" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Nasumičan _žanr" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Nasumičan _umetnik" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Nasumičan al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 najčešće puštanih pesama (više od 40 može biti odabrano ako su povezane)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Ime:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "Vrednost:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Sačuvane vrednosti" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Uredi sačuvane vrednosti…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matski" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Režim zapisa" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Režim albuma" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Utišaj" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain Režim" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Nov %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(nepoznato)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Dodaj" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Uredi…" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Izraz oznake" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Izraz oznake npr. people:real ili ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Upiši novu oznaku" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Izraz oznake" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Datoteke:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Odabrane pesme će biti uklonjene iz bibilioteke i njihove datoteke sa diska." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Odabrane datoteke će biti uklonjene sa diska." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "Obrisati %(file_count)d datoteku zauvek?" msgstr[1] "Obrisati %(file_count)d datoteke zauvek?" msgstr[2] "Obrisati %(file_count)d datoteka zauvek?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Obriši datoteke" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Odabrane pesme će biti itbačene iz biblioteke i njihove datoteke premeštene " "u korpu za otpatke." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Odabrane datoteke će biti premeštene u korpu za otpatke." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "Premesti %(file_count)d datoteku u korpu?" msgstr[1] "Premesti %(file_count)d datoteke u korpu?" msgstr[2] "Premesti %(file_count)d datoteka u korpu?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Premesti u korpu" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Premeštam %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Nije moguće premestiti u korpu" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Premeštanje jedne ili više datoteka u korpu nije uspelo." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Brišem %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Ne mogu obrisati datoteke" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Brisanje jedne ili više datoteka neuspešno." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Pretraživači" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Učitavam datoteke" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "nedostaje u %d pesmi" msgstr[1] "nedostaje u %d pesme" msgstr[2] "nedostaje u %d pesama" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "različito u %d pesmi" msgstr[1] "različito u %d pesme" msgstr[2] "različito u %d pesama" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Odvoji u _višestruke vrednosti" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Odvoji disk od _albuma" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Odvoji _verziju od naziva" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Odvoji aranžera od Um_etnika" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Odvoji _izvođača od umetnika" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Odvoji _izvođača od naziva" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Odvoji _izvornog umetnika od naziva" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Dodaj oznaku" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Oznaka:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Prikaži _pragmatične oznake" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Pristupi svim oznakama, uključujući mašinski proizvedene npr. MusicBrainz " "ili Replay Gain oznake" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Prikaži _pragmatične oznake" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Vrati" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Sačuvaj" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Podesi" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Razdvoji oznake" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "_Umnoži vrednost(i)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Ne mogu dodati oznaku" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Ne mogu da dodam pesme" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Trenutno odabrane datoteke ne podržavaju višestruke vrednosti za <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Nevažeća oznaka" msgstr[1] "Nevažeća oznaka" msgstr[2] "Nevažeća oznaka" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Nevažeća oznaka <b>%s</b>\n" "\n" "Trenutno odabrana datoteka ne podržava ovu oznaku." msgstr[1] "" "Nevažeća oznaka <b>%s</b>\n" "\n" "Trenutno odabrana datoteka ne podržava ovu oznaku." msgstr[2] "" "Nevažeća oznaka <b>%s</b>\n" "\n" "Trenutno odabrana datoteka ne podržava ovu oznaku." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Nevažeća vrednost" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Nevažeća vrednost: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Oznaka može biti neprecizna" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s je izmenjeno dok je program bio pokrenut. Čuvanje bez " "osvežavanja biblioteke može prepisati druge izmene na pesmi." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Ne mogu da sačuvam pesmu" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Čuvanje %(file-name)s nije uspelo. Datoteka je možda samo za čitanje, " "oštećena, ili nemate dozvolu da je izmenite." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Više opcija…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Opozovi" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Ponovi" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_O aplikaciji" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "_Proveri dostupna ažuriranja…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Dodaci" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso Postavke" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Fascikle" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "_Nova fascikla…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Odaberi sve pod-fascikle" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Nova fascikla" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Unesi ime za novu fasciklu:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Ne mogu da stvorim fasciklu" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Ne mogu da obrišem fasciklu" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Pesme" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "od %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Zapis %s" #: quodlibet/qltk/info.py:104 #, fuzzy msgid "Current _Song" msgstr "Po trenutnom _žanru" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "_Uredi prikaz…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Ni jedna pesma nije odabrana." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Nema pesama" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Informacije" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Tekst reči" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Izdato od %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "umetnik" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "umetnici" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "izvođači" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nikad" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d put" msgstr[1] "%(n)d puta" msgstr[2] "%(n)d puta" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "dodato" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "zadnje puštano" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "svira" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "preskače" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "ocena" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "putanja" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "dužina" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "enkodiranje" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "učestalost bitova" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "veličina datoteke" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "izmenjeno" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "Dodatno" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d odabran" msgstr[1] "%d odabrana" msgstr[2] "%d odabranih" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Zapis nedostupan" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d pesma bez albuma" msgstr[1] "%d pesme bez albuma" msgstr[2] "%d pesama bez albuma" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Odabrana doskografija" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d pesma bez umetnika" msgstr[1] "%d pesme bez umetnika" msgstr[2] "%d pesama bez umetnika" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumi" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Ukupna dužina:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Ukupna veličina:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Datoteke" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Pregledaj na internetu" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Nema pronađenog teksta za ovu pesmu." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Da li ste sigurni da želite da uklonite sve pesme?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Odabrane pesme će biti uklonjene iz biblioteke." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Otkrij" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Otkrij" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Zanemari promene oznaka?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Oznake su izmenjene ali nisu sačuvane. Sačuvaj datoteke ili opozovi i " "zanemari izmene?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Opozovi" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Datoteka postoji" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "Zameni %(file-name)s?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Zameni datoteku" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktivni zadaci" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d pokrenutih zadataka" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Menjaj režim mešanja" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Menjaj režim ponavljanja" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Događaji" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Redosled izvođenja" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Uređivanje" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Preimenuj" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "_Upit:" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Omoti" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Greške dodatka" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Omogućeno" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Onemogućeno" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Bez kategorije" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Bez kategorije" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Dodaci nisu nađeni." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Dodaci" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Filtriraj po stanju dodatka" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Filtriraj po tipu dodatka" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Filtriraj po imenu ili opisu dodatka" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Prikaži _greške" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Zapis" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Gru_pisanje" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Umetnik" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_ime datoteke" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Dužina" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Automatski skoči na puštenu pesmu" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Kada se promeni puštena pesma, premotaj do nje u listi pesama" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Drugi:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "_Uredi…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "Dodaj ili ukloni dodatna zaglavlja kolona" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Vidljive kolone" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Ime uključuje _verziju" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album uključuje _disk podnatpis" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "Umetnik uključuje sve _ljude" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Ime datoteke uključjue _fasciklu" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Postavke kolone" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Uredi kolone" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Primeni trenutnu konfiguraciju na listu pesama, dodaj novu kolonu na kraju" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista pesama" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Uredi kolone" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Ukupno trajanje" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globalni filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Primeni ovaj upit uz sve druge" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Pretraga" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Pretraživači" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Potvrdi _više ocena" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Pitaj za potvrdu pre nego što promenim ocene za više pesama odjednom" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Omogući _jedan-klik ocene" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Omogućava ocenjivanje klikom na kolonu ocene u listi pesama" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Ocene" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Preferiraj _ugrađeni omot" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Odaberite za korišćenje omota ugrađenog u audio zapis (kada je dostupno) pre " "drugih izvora" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Fiksirano ime slike:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Omot albuma" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Reprodukcija" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Konfiguracija izlaza" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ako nema Replay Gain informacija za pesmu, postavi jačinu po ovoj vrednosti" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Fall-back gain (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "Postavi jačinu za sve pesme po zadatoj vrednosti" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Pre-amp gain (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Omogući Replay Gain promenu jačine" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain promena jačine" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Nastavi reprodukciju pri pokretanju" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Ako je muzika svirala pri gašenju, automatski nastavi reprodukciju pri " "sledećem pokretanju" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Podrazumevana ocena:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "Skala _ocena:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesian Average factor (C) za nagomilane ocene.\n" "0 znači konvenvionalni prosek, više vrednosti znače da će album sa malo " "zapisa imati manje ekstremne ocene. Promena ove vrednosti uzrokuje ponovno " "računanje za sve albume." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesian prosečna količina:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Imejl:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Ocene i broj puštanja će biti sačuvane u oznakama za ovu adresu elektronske " "pošte" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Automatski sačuvaj promene ocena" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Sačuvaj promene u oznakama bez potvrde pru uređivanju više datoteka" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Skup operacija za korišćenje pri deljenju vrednosti oznaka u uređivaču " "oznaka. Lista je odvojena prostorom." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Podeli _oznake na:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Skup operacija za korišćenje pri izvlačenju pod-oznaka iz oznaka u uređivaču " "oznaka. Lista je odvojena prostorom, i svaki unos mora sadržati dva znaka." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Podeli _podoznake na:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Oznake" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Uređivanje oznaka" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Ažuriram za nove ocene" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "_Skeniraj biblioteku" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Proveri promene u biblioteci" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Ponovo _izgradi biblioteku" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Ponovo učitaj sve pesme u biblioteku. Ovo može potrajati veoma dugo." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Skrivene pesme" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Skeniraj biblioteku _pri pokretanju" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Skeniraj direktorijume" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Svojstva" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Niz" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Očisti niz" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Onemogući niz - niz će biti zanemaren prilikom reprodukcije" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Prolazan" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Ukloni pesme iz niza posle reprodukcije" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Neprestano" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Zadrži pesme u nizu nakon reprodukcije" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Režim" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Zaustavi na kraju" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d pesma (%(time)s)" msgstr[1] "%(count)d pesme (%(time)s)" msgstr[2] "%(count)d pesama (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Pregledaj bibilioteku" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Menja vidljivost niza" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Greška pri reprodukciji" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Dodaj direktorijum bibilioteke?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Nemate muziku dodatu u biblioteku. Da li želite sada da dodate?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Ne sad" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Dodaj" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Ne mogu da dodam pesme" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s koristi nepodržan protokol." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Skoči na puštenu pesmu" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Datoteka" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Pesma" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Pregled" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Istraži" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Upravljaj" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Pomoć" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "_Dodaj u fasciklu…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "_Dodaj datoteku…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Dodaj lokaciju…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Uredi obeleživače…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "_Zaustavi" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Zaustavi posle ove pesme" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Prečice tastature" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Pomoć na mreži" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Potraži pomoć" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Dodaj lokaciju" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Unesi lokaciju audio datoteke:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Ne mogu da dodam lokaciju" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s nije ispravna lokacija." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Dodaj muziku" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "_Dodaj fascikle" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Muzičke datoteke" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "_Dodaj datoteke" #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Da li ste sigurni da želite da uklonite sve pesme?" msgstr[1] "Da li ste sigurni da želite da uklonite sve pesme?" msgstr[2] "Da li ste sigurni da želite da uklonite sve pesme?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Niz" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Da lis te sigurni da želite da izmenite ocenu svih %d pesama?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Sačuvane ocene će biti uklonjene" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "_Ukloni ocene" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Ocene svih odabranih pesama će biti promenjene na '%s'" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "Promeni _ocenu" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Zameni prazan prostor sa _donjim crtama" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Ukloni _Vindouz nekompatibilne karaktere" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Ukoni _dijakritičke oznake" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Ukloni ne-_ASCII karaktere" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Koristi samo _mala slova" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Preimenuj datoteke" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Pregled" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Imena datoteka" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Pomeri omot albuma" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Vidite '[albumart] filenames' unos konfiguracije za pretragu slika" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Prepiši omot albuma po cilju" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "_Ukoni prazne direktorijume" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Omot albuma" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Novo ime" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Ne mogu da preimenujem datoteku" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Preimenovanje <b>%(old-name)s</b> u <b>%(new-name)s</b> neuspešno. Moguže da " "ciljana datoteka već postoji, ili nemate dozvolu da napravite novu datoteku " "ili ulonite staru." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Zanemari _sve greške" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Zaustavi" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Nastavi" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Putanja nije apsolutna" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Šablon\n" "\t<b>%s</b>\n" "sarži / ali ne počinje od korena. Da bi izbegli pogrešno imenovane fascikle, " "korenujte svoj šablon početkom sa / ili ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Pesme u izlistanim fasciklama će biti dodate u bublioteku kada se lista " "osveži" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Odabrane pesme će biti uklonjene iz biblioteke." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Putanja biblioteke:" msgstr[1] "Putanja biblioteke:" msgstr[2] "Putanja biblioteke:" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Ukloni" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Odaberi direktorijume" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Odaberi direktorijume" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Sačuvana pretraga" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Uredi sačuvane pretrage…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "Pretraga vaše biblioteke koristeći slobodan tekst ili QL upite" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Traži nakon _kucanja" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Pokazuje rezultate pretrage nakon što korisnik završi s kucanjem" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Ograničenje:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Značaj" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Dodaj pitanje" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Dodaj QL upit ili slobodan tekst da bude &ed zajedno" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Prikaži preostalo vreme" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Glavni prozor" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "Premotaj 10 sekundi unazad" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "Premotaj 10 sekundi unapred" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Fokusiraj stavku pretrage" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Poništi filtere i skoči na trenutnu pesmu" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Otvori informacioni prozor za odabrane pesme" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Otvori uređivač oznaka za odabrane pesme" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Stavi u red odabrane pesme" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Obriši odabrane pesme" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Prikaži upis inlajn pretrage" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Levi klik na zaglavlje kolone" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Dodaj kolonu na listu kolona za razvrstavanje" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Pregled stabla" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Skuplja sve elemente ili odabira elemnt šablona" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Proširi element" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Unosi teksta" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Opozovi zadnju izmenu" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Ponovi zadnju izmenu" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Odaberi sve pesme u svim panoima" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtriraj po %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Sva _zaglavlja" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Zapis zaglavlje" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Album zaglavlje" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Ljudi zaglavlje" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Datum zaglavlje" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Datoteka zaglavlje" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Produkcija zaglavlje" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Prolagodi zaglavlje…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Proširi kolonu" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "Premesti %(file_count)d datoteku u korpu?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Ukloni iz biblioteke" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "Pokreni dodatak \"%(name)s\" za %(count)d pesmu?" msgstr[1] "Pokreni dodatak \"%(name)s\" za %(count)d pesme?" msgstr[2] "Pokreni dodatak \"%(name)s\" za %(count)d pesama?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Podesi dodatke…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Dodaj u _Niz" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "_Ukloni iz biblioteke…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Ne mogu da prikažem datoteke" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" "Greška pri prikazivanju datoteke, ili nema programa koji bi je prikazali." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Neuspešno čuvanje" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Preuzimanje omota" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Preuzimanje omota" msgstr[1] "Preuzimanje omota" msgstr[2] "Preuzimanje omota" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Preuzimanje omota" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Zameni _donje crte sa praznim prostorom" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Veliko-slovo oznake" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Podeli u više _vrednosti" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Oznake iz putanje" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Oznake zamenjuju postojeće" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Oznake su dodate na postojeće" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Šablon\n" "\t<b>%s</b>\n" "je neispravan. Moguće da sadrži istu oznaku dva puta ili ima nebalansirane " "zagrade (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Šablon koji ste uneli nije ispravan. Budite sigurni da ste uneli < i > " "kao \\< i \\> i da su vaše oznake izbalansirane.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Uredi prikaz" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Brojevi zapisa" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Počni o_d:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Ukupno zapisa:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Pusti/Pauziraj" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Prethodno" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "i %d još…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Čuvam izmenjene pesme." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d sačuvanih pesama\n" "(%(remaining)s remaining)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(current)s od %(all)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Proveravam ažuriranja" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Veza neuspešna" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Već koristite zadnju verziju %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Nova verzija %(new-version)s je dostupna\n" "\n" "Trenutno koristite verziju %(old-version)s\n" "\n" "Posetite <a href='%(url)s'>website</a>" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Uvezi listu izvođenja" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Lista izvođenja mora imati ime" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Lista izvođenja %s već postoji." #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Ugrađeni omoti albuma" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Koristi omote ugrađene u audio datoteke." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Omoti fascikle" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Koristi uobičajeno imenovane slike nađene u zajedničkom direktorijumu uz " "pesmu." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Omot" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Ispitujem dostavljače omota albuma" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Prikaži ukratke informacije korišćenja" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Prikaži verziju i autorska prava" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Odštampaj informacije ispravljanja grešaka" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Korišćenje: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[opcije]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Opcija %r nije prepoznata." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Opcija %r zahteva argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r nije jedinstven prefiks." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekunda" msgstr[1] "%s sekunde" msgstr[2] "%s sekundi" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Nema informacija o trajanju" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunda" msgstr[1] "%d sekunde" msgstr[2] "%d sekundi" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minuta" msgstr[2] "%d minuta" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d sat" msgstr[1] "%d sata" msgstr[2] "%d sati" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dan" msgstr[1] "%d dana" msgstr[2] "%d dana" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d dan" msgstr[1] "%d dana" msgstr[2] "%d dana" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "ne" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datum mora biti unet u 'YYYY', 'YYYY-MM-DD' ili 'YYYY-MM-DD HH:MM:SS' " "formatu." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain povećanja moraju biti uneta u 'x.yy dB' formatu." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain peaks moraju biti uneti u 'x.yy' formatu." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDs moraju biti u UUID formatu." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz status izdanja mora biti 'official', 'promotional', ili " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Jezik mora biti ISO 639-2 tri-slova standard" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Neuspešno čuvanje" msgstr[1] "Neuspešno čuvanje" msgstr[2] "Neuspešno čuvanje" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Ne mogu urediti pesmu" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Čuvanje <b>%s</b> neuspešno. Datoteka je možda samo za čitanje, oštećena, " "ili nemate potrebne dozvole." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Neispravno enkodiranje]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranžer" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranžeri" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "aranžman" #: quodlibet/util/tags.py:86 msgid "author" msgstr "autor" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "komentar" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "kompozitor" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "kompozitori" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "kompozicija" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenti" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "dirigovanje" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "autorska prava" #: quodlibet/util/tags.py:93 msgid "date" msgstr "datum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "opis" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "žanr" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "žanrovi" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "izvođač" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "izvođenje" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupe" #: quodlibet/util/tags.py:98 msgid "language" msgstr "jezik" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licenca" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "tekstopisac" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "tekstopisci" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "tekst" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizacija" #: quodlibet/util/tags.py:104 msgid "title" msgstr "naslov" #: quodlibet/util/tags.py:105 msgid "version" msgstr "verzija" #: quodlibet/util/tags.py:106 msgid "website" msgstr "veb adresa" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "umetnik albuma" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "UPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "podnatpis diska" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "zapis" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "izdavčka kuća" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "datum premijere" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "originalni album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "originalni umetnik" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "datum snimanja" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "zemlja izdanja" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID snimanja" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID izdanja zapisa" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID izdanja" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID umetnika" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID izdanja umetnika" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz status albuma" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz tip albuma" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID izdanja grupe" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "referenca jačine zvuka" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diskovi" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "zapisi" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "zadnje pokretano" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "puno ime" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "tačka kačenja" #: quodlibet/util/tags.py:166 msgid "people" msgstr "ljudi" #: quodlibet/util/tags.py:168 msgid "year" msgstr "godina" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "originalna godina izdanja" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "obeleživač" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "dubina bita" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "format datoteke" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "liste puštanja" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "brzina uzorka" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "broj kanala" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "razvrstaj" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "uloge" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Audio uređivać oznaka" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Uređuje oznake u vašim audio datotekama" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Muzički plejer" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Slušajte, pretražite ili uredite svoju audio kolekciju" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso je uređivač oznaka sa istim uređivačkim interfejsom kao i Quod " "Libet. Dozvoljava vam da prikažete i uredite bilo koju željenu oznaku u " "datoteci, za sve formate koje podržava." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Podržani formati uključuju i Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet je program za organizaciju muzike. Pruža više različitih načina " "da pregledate vašu audio zbirku/biblioteku, a takođe poseduje i podršku za " "internet radio i audio izvore. Ima jako fleksibilne sposobnosti uređivanja " "metapodataka oznaka i pretrage." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Izvezi u Squeezebox listu izvođenja" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Ne mogu dodati <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "Nevažeće oznake" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Nevažeće oznake <b>%s</b>\n" #~ "\n" #~ "Trenutno odabrana datoteka ne podržava uređivanje ovih oznaka." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Automatski ocenjuje pesme kada su puštene ili preskočene. Ovo koristi " #~ "\"ubrzani\" algoritam sa vux od Brajana Nelsona." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekundi" #~ msgid "Startup" #~ msgstr "Pokretanje" #~ msgid "Audio Feeds" #~ msgstr "Audio izvori" #~ msgid "_Audio Feeds" #~ msgstr "_Audio izvori" #~ msgid "New" #~ msgstr "Novo" #~ msgid "Automatic Library Update" #~ msgstr "Automatsko ažuriranje bibilioteke" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Drži vašu biblioteku ažurnom koristeći inotify. Zahteva %s." #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Omogućava kontolu Quod Libet-a koristeći MPRIS 2 D-Bus specifikaciju " #~ "sučelja." #~ msgid "Searching for lyrics…" #~ msgstr "Tražim tekst…" #, fuzzy #~ msgid "broker username" #~ msgstr "Ime domaćina posrednika" #, fuzzy #~ msgid "broker password" #~ msgstr "Port posrednika" #, fuzzy #~ msgid "<artist>" #~ msgstr "umetnik" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "naslov" #, fuzzy #~ msgid "OK" #~ msgstr "_U redu" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "Izvozi metapodatke odabranih pesama kao .tags datoteku." #~ msgid "Import Metadata" #~ msgstr "Uvezi metapodatke" #~ msgid "Imports metadata for selected songs from a .tags file." #~ msgstr "Uvozi metapodatke odabranih pesama iz .tags datoteke." #~ msgid "Migrate Metadata" #~ msgstr "Premesti metapodatke" #~ msgid "Copies the quodlibet-specific metadata between songs." #~ msgstr "Kopira quodlibet metapodatke između pesama." #~ msgid "_Copy" #~ msgstr "_Umnoži" #~ msgid "_Paste" #~ msgstr "_Ubaci" #~ msgid "Information to copy/paste" #~ msgstr "Informacija za umnožavanje/ubacivanje" #~ msgid "Map tracks by disc and track number" #~ msgstr "Mapira zapise po disku i broju zapisa" #~ msgid "" #~ "Enable this when you want to migrate metadata from one album to another " #~ "while matching the disc and track numbers.\n" #~ "\n" #~ "<b>Note:</b> this must be enabled when metadata is copied for track " #~ "information to be stored." #~ msgstr "" #~ "Omogućite ovo kada želite da prebacite metapodatke sa jednog albuma na " #~ "drugi podudarno sa brojem diska i zapisa.\n" #~ "\n" #~ "<b>Upozorenje:</b> ovo mora biti omogućeno kada su metapodaci umnoženi da " #~ "bi informacija zapisa bila sačuvana." #~ msgid "There is %d stored track." #~ msgid_plural "There are %d stored tracks." #~ msgstr[0] "Ima %d sačuvan zapis." #~ msgstr[1] "Ima %d sačuvana zapisa." #~ msgstr[2] "Ima %d sačuvanih zapisa." #~ msgid "Unsupported file type" #~ msgstr "Nepodržan tip datoteke" #~ msgid "Unable to add station" #~ msgstr "Ne mogu da dodam stanicu" #~ msgid "Search Library" #~ msgstr "Pretraži biblioteku" #~ msgid "_Search Library" #~ msgstr "_Pretraži biblioteku" #~ msgid "Quit Program" #~ msgstr "Izađi iz programa" #~ msgid "" #~ "Prevents the GNOME screensaver from activating while a song is playing." #~ msgstr "" #~ "Sprečava GNOM čuvara ekrana da se aktivira kada je u toku reprodukcija " #~ "pesme." #~ msgid "No lyrics found" #~ msgstr "Nema nađenog teksta" #~ msgid "_Zoom level:" #~ msgstr "_Uveličavanje nivo:" #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "" #~ "Traži preko gornjeg URL-a ako tekst ne može biti prnađen na LyricsWikia." #~ msgid "Alternate search" #~ msgstr "Alternativna pretraga" #~ msgid "Web Lyrics" #~ msgstr "Veb tekst" #~ msgid "Shows a sidebar containing online lyrics of the playing song." #~ msgstr "" #~ "Prikaži bočnu traku koja sadrži tekst sa interneta za trenutnu pesmu." #~ msgid "Skip Songs" #~ msgstr "Preskoči pesme" #~ msgid "" #~ "Playback skips over songs with a rating equal or below a given threshold." #~ msgstr "Preskače pesme sa ocenom jednakom ili ispod zadatog praga." #~ msgid "Burn CD" #~ msgstr "Nareži CD" #~ msgid "Burns CDs with K3b, Brasero or xfburn." #~ msgstr "Upisuje na CD koristeći k3b, Brasero ili xfburn." #~ msgid "The single image filename to use if selected" #~ msgstr "Jedinstveno ime slike za korišćenje ako je odabrano" #~ msgid "The album art image file to use when forced (supports wildcards)" #~ msgstr "Slika omota za korišćenje kada je prisiljeno" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/sv.po����������������������������������������������������������������������������0000644�0001750�0001750�00000666326�14436352625�013646� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Swedish translation of Quod Libet 2.5 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Daniel Nyberg <p.daniel.nyberg@gmail.com>, 2013. # Erik Christiansson <spam.erik@alphafish.com>, 2006. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 2.5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2022-10-31 05:02+0000\n" "Last-Translator: Kristofer Rickheden Gustavsson <hackan@bahnhof.se>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/sv/>\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.14.2-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Personer" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Datum Tillagd" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Ursprungligt Datum" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Betyg" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "Spelnings_Antal" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 #, fuzzy msgid "Sort _by…" msgstr "Sortera _på…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Inställningar" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albumlista" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albumlista" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Alla album" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Ladda om omslaget" msgstr[1] "Ladda om omslagen" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Låtar utan album" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d spår" msgstr[1] "%d spår" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d skiva" msgstr[1] "%d skivor" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Ett Exempelalbum" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Inställningar för albumlista" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Visa album_omslag" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Sökning inkluderar personer" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Alternativ" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albumvisning" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Stäng" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Biblioteksbläddrare" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d låt" msgstr[1] "%d låtar" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Ogiltigt mönster" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albumsamling" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Albumsamling" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Okänd %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Multipla %s-värden" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Anpassad" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Lägg till" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Ta bort" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Tagg" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Slå samman" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Inställningar för skivsamling" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Tillämpa" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Avrbyt" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Total storlek:" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "Total storlek:" #: quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Inställningar för panelbläddrare" #: quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Visa album_omslag" #: quodlibet/browsers/covergrid/prefs.py:70 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Alla album" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "Inga nya stationer" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Filsystem" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Filsystem" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Kunde ej kopiera låtar" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "De valda filerna kan inte kopieras till andra låtlistor eller till kön." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "Lägg _till i bibliotek" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Stationslistor kan endast innehålla stationsplatser, ej andra stationslistor " "eller spellistor. Följande platser kan ej laddas:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Internetradio" #: quodlibet/browsers/iradio.py:224 #, fuzzy msgid "Add stations" msgstr "Alla stationer" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Ladda hem stationslista" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Ny station" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Ange adressen till en internetradiostation:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektrinisk" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Gamla favoriter" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japanskt" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "indisk" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religiöst" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Topplistemusik" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turkiskt" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Universitetsradio" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Prat / Nyheter" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassiskt" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternativ" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Nyheter" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavisk" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Grekiskt" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:482 #, fuzzy msgid "_Load Stations" msgstr "_Uppdatera stationer" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Internetradio" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Alla stationer" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Favoriter" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Ingen kategori" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "Ny station" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Uppdatera stationer" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Inga stationer funna" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Inga internetradiostationer hittades på %s" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Alla listade stationer finns redan i biblioteket" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "_Lägg till som favorit" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Ta bort från favoriter" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" msgstr[1] "%(count)d stationer" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Panelbläddrare" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Panelbläddrare" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Välj _alla" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Okänd" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Alla" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: quodlibet/browsers/paned/prefs.py:43 #, fuzzy msgid "Columnar" msgstr "Synliga kolumner" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Inställningar för panelbläddrare" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Spellistor" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "Spellistor" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Ta _bort från spellista" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Importera" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Kan ej importera spellistor" #: quodlibet/browsers/playlists/main.py:472 #, fuzzy msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet kan endast importera spellistor i M3U- och PLS-format." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 #, fuzzy msgid "_Delete" msgstr "Ta bort filer" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Byt namn" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Kan ej byta namn på spellista" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Importera spellista" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Importera" #: quodlibet/browsers/playlists/menu.py:24 #, fuzzy msgid "_New Playlist…" msgstr "_Ny spellista" #: quodlibet/browsers/playlists/menu.py:78 #, fuzzy, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Är du säker på att du vill ändra betygen på alla %d låtar?" msgstr[1] "Är du säker på att du vill ändra betygen på alla %d låtar?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "" #: quodlibet/browsers/playlists/prefs.py:39 #, fuzzy msgid "Example Playlist" msgstr "Ny spellista" #: quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Inställningar för panelbläddrare" #: quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Spellistor" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Är du säker på att du vill ta bort spellistan '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "All information om den valda spellistan kommer att tas bort och kan inte " "återställas." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Spår" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Ny spellista" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Ange ett namn på den nya spellistan:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importerar spellista.\n" "\n" "%(current)d/%(total)d låtar tillagda." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Ny feed" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Ange platsen för en ljud-feed:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "Lägg _till fil..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 #, fuzzy msgid "_Refresh" msgstr "Uppdatera biblioteket" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Vaka över denna mapp för nya låtar" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Kunde ej lägga till feed" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "<b>%s</b> kunde ej läggas till. Servern kan vara nere eller så innehåller " "platsen ej en ljudfeed." #: quodlibet/browsers/podcasts.py:564 #, fuzzy msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Nuvarande ljud-backend stödjer inte URL:er. Ljudströmsbläddraren avaktiverad." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Begränsa resultat" #: quodlibet/browsers/tracks.py:39 #, fuzzy msgid "_Allow multiple queries" msgstr "Dela till flera _värden" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Spårlista" #: quodlibet/browsers/tracks.py:54 #, fuzzy msgid "_Track List" msgstr "Spårlista" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Panelbläddrare" #: quodlibet/browsers/soundcloud/main.py:40 #, fuzzy msgid "Soundcloud Browser" msgstr "Panelbläddrare" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Sök" #: quodlibet/browsers/soundcloud/main.py:70 #, fuzzy msgid "My tracks" msgstr "spår" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, fuzzy msgid "Connected" msgstr "plats" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "<b>%s</b> is ej ansluten." #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:51 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet körs inte" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "musikbibliotek och -spelare" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[alternativ]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Skriver ut den låt som spelas och avslutar" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Börja spela omgående" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Hoppa till nästa låt" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Hoppa till föregående låt, eller starta om aktuell låt om det är nära början" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Hoppa till föregående låt" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Starta uppspelning" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Pausa uppspelning" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Växla spelnings-/paus-läge" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Stoppa uppspelning" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Höj volymen" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Sänk volymen" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Skriv ut spelarstatus" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Dölj huvudfönstret" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Visa huvudfönstret" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Växla synlighet för huvudfönstret" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Fokuserar på den spelare som körs" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Ta bort aktuella bläddrarfilter" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Uppdatera och skanna om biblioteket" #: quodlibet/cli.py:114 #, fuzzy msgid "List available browsers" msgstr "Inaktivera bläddrare" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Skriv ut nuvarande spellista" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Skriv ut innehållet i kön" #: quodlibet/cli.py:117 #, fuzzy msgid "Print the active text query" msgstr "Skriv ut innehållet i kön" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Starta utan insticksmoduler" #: quodlibet/cli.py:119 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet körs inte" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Avsluta Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Sök innom spelande låt" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Växla spelnings-/paus-läge" #: quodlibet/cli.py:127 #, fuzzy msgid "Set shuffle mode type" msgstr "Växla spelnings-/paus-läge" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Stäng av, på eller växla repetering" #: quodlibet/cli.py:129 #, fuzzy msgid "Set repeat mode type" msgstr "Växla spelnings-/paus-läge" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ställ in volymen" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Sök i ljudbiblioteket" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "fråga" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Spela en fil" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "filnamn" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Sök innom spelande låt" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Ange nuvarande bläddrare" #: quodlibet/cli.py:135 #, fuzzy msgid "Stop after the playing song" msgstr "Betygsätt den spelande låten" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Öppna ny bläddrare" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Visa eller dölj bläddraren" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Filtrera på slumpvis värde" #: quodlibet/cli.py:138 #, fuzzy msgctxt "command" msgid "tag" msgstr "tagg" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Filtrera på ett taggvärde" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tagg=värde" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Kölägg en fil eller fråga" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Kölägg kommaseparerad lista" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "filnamn" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Skriv ut filnamnen på sökresultatet till stdout" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Ta bort fil eller fråga från kö" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "plats" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Ogiltigt mönster" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Ogiltigt argument för '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Försök med %s --help." #: quodlibet/errorreport/ui.py:58 #, fuzzy msgid "An Error Occurred" msgstr "Ett fel har inträffat" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "" #: quodlibet/errorreport/ui.py:71 #, fuzzy msgid "Ignore Error" msgstr "Ignorera _alla fel" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "" #: quodlibet/errorreport/ui.py:110 #, fuzzy msgid "Short description…" msgstr "beskrivning" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "en ljudtaggsredigerare" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "mapp" #: quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Ljudtaggsredigerare" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" #: quodlibet/ext/covers/discogs.py:28 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz spår-ID" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: quodlibet/ext/covers/musicbrainz.py:21 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz spår-ID" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Oglitig kodning]" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "_Titel" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Editera taggar i redigerare" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Första bokstaven i varje ord _versal" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 #, fuzzy msgid "Advanced Preferences" msgstr "Inställningar för panelbläddrare" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:189 #, fuzzy msgid "_Cover size:" msgstr "Total storlek:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 #, fuzzy msgid "Display" msgstr "Redigera visning" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:215 #, fuzzy msgid "Right" msgstr "_Vikt" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:259 #, fuzzy msgid "_Outline" msgstr "_Utgångspipeline" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Redigera visning" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 #, fuzzy msgid "Preview" msgstr "_Förhandsgranska" #: quodlibet/ext/events/appinfo.py:28 #, fuzzy msgid "Application Information" msgstr "Information" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "" #: quodlibet/ext/events/appinfo.py:62 #, fuzzy msgid "Supported Formats" msgstr "Format som stödjs: %s" #: quodlibet/ext/events/appinfo.py:70 #, fuzzy msgid "Configuration Directory" msgstr "Filtrera på _genre" #: quodlibet/ext/events/appinfo.py:77 #, fuzzy msgid "Cache Directory" msgstr "mapp" #: quodlibet/ext/events/appinfo.py:84 #, fuzzy msgid "Audio Backend" msgstr "Ljudfeeds" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, fuzzy, python-format msgid "Couldn't write '%s'" msgstr "%s: Kan inte hitta %s." #: quodlibet/ext/events/auto_update_tags_in_files.py:80 #, fuzzy msgid "Auto Update Tags in Files" msgstr "_Uppdatera stationer" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 #, fuzzy msgid "Save ratings and play _counts in tags" msgstr "Spara betyg och antalet _spelningar" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 #, fuzzy msgid "Settings updated" msgstr "inspelningsdatum" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, fuzzy, python-format msgid "Error in %s" msgstr "Fel vid läsning av %r" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 #, fuzzy msgid "_Update strategy:" msgstr "_Uppdatera stationer" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Inställningar" #: quodlibet/ext/events/automask.py:22 #, fuzzy msgid "Automatic Masking" msgstr "Auto_matisk" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 #, fuzzy msgid "Automatic Rating" msgstr "Auto_matisk" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 #, fuzzy msgid "Import Failed" msgstr "Importera spellista" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/bansheeimport.py:127 #, fuzzy msgid "Banshee Import" msgstr "_Importera" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 #, fuzzy msgid "Start Import" msgstr "_Importera" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "" #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Förkasta taggändringar?" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Förkasta taggändringar?" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Spela upp/pausera" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Sökvägsmönster" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Sökvägsmönster" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:48 #, fuzzy msgid "Reggae" msgstr "Reggaeton" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "" #: quodlibet/ext/events/equalizer.py:53 #, fuzzy msgid "Soft Rock" msgstr "Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" #: quodlibet/ext/events/equalizer.py:150 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "Nuvarande ljud-backend stödjer inte URL:er. Ljudströmsbläddraren avaktiverad." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, fuzzy, python-format msgid "%.1f dB" msgstr "%.1f sekunder" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Förval" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 #, fuzzy msgid "Select…" msgstr "_Välj" #: quodlibet/ext/events/equalizer.py:293 #, fuzzy msgid "_Reset EQ" msgstr "_Förhandsgranska" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "Anpassad sortering" #: quodlibet/ext/events/equalizer.py:315 #, fuzzy msgid "_Delete selected" msgstr "Kunde ej ta bort låtar." #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "" #: quodlibet/ext/events/gajim_status.py:145 #, fuzzy msgid "Pattern:" msgstr "Ogiltigt mönster" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 #, fuzzy msgid "Music is playing" msgstr "Musikspelare" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 #, fuzzy msgid "Mode:" msgstr "Modell:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 #, fuzzy msgid "Internet Radio Log" msgstr "Internetradio" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Betyg" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Förval" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:161 #, fuzzy msgid "Connection" msgstr "plats" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 #, fuzzy msgid "Hide main window on close" msgstr "Dölj huvudfönstret" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 #, fuzzy msgid "Defaults to 1883" msgstr "Förval" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:148 #, fuzzy msgid "Playing Pattern" msgstr "Sökvägsmönster" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:152 #, fuzzy msgid "Paused Pattern" msgstr "Sökvägsmönster" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:156 #, fuzzy msgid "No-song Text" msgstr "%d låt" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:169 #, fuzzy msgid "MQTT Configuration" msgstr "Utkonfiguration" #: quodlibet/ext/events/mqtt.py:173 #, fuzzy msgid "Status Text" msgstr "Sökvägsmönster" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Kunde inte ansluta till enhetsdrivrutin." #: quodlibet/ext/events/mqtt.py:213 #, fuzzy msgid "Connection error" msgstr "plats" #: quodlibet/ext/events/musicbrainzsync.py:36 #, fuzzy msgid "MusicBrainz Sync" msgstr "MusicBrainz album typ" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "User_name:" msgstr "_Namn:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "" #: quodlibet/ext/events/notify.py:65 #, fuzzy msgid "_Title:" msgstr "_Titel" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "" #: quodlibet/ext/events/notify.py:140 #, fuzzy msgid "Show notifications" msgstr "Inga nya stationer" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Kunde inte ansluta till enhetsdrivrutin." #: quodlibet/ext/events/notify.py:222 #, fuzzy msgid "Song Notifications" msgstr "Inga nya stationer" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Nästa" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Inga nya stationer" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:260 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Kunde inte ansluta till enhetsdrivrutin." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:487 #, fuzzy msgid "_Service:" msgstr "Enhet:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 #, fuzzy msgid "Other…" msgstr "_Andra:" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 #, fuzzy msgid "_Title pattern:" msgstr "_Filnamn mönster:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 #, fuzzy msgid "Random Album Playback" msgstr "Slumpvis al_bum" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "" #: quodlibet/ext/events/randomalbum.py:43 #, fuzzy msgid "Longer albums" msgstr "album" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "" #: quodlibet/ext/events/randomalbum.py:86 #, fuzzy msgid "Weights" msgstr "_Vikt" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "" #: quodlibet/ext/events/randomalbum.py:215 #, fuzzy msgid "Random Album" msgstr "Slumpvis al_bum" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "" #: quodlibet/ext/events/seekbar.py:122 #, fuzzy msgid "Alternative Seek Bar" msgstr "Alternativ" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Bokmärken" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 #, fuzzy msgid "Bookmark name for point A" msgstr "Bokmärkesnamn" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 #, fuzzy msgid "Bookmark name for point B" msgstr "Bokmärkesnamn" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "[alternativ]" #: quodlibet/ext/events/synchronize_to_device.py:51 #, fuzzy msgid "Pending copy" msgstr "Ökande" #: quodlibet/ext/events/synchronize_to_device.py:52 #, fuzzy msgid "Pending delete" msgstr "inspelningsdatum" #: quodlibet/ext/events/synchronize_to_device.py:53 #, fuzzy msgid "delete" msgstr "Ta bort filer" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:56 #, fuzzy msgid "Synchronizing" msgstr "Text" #: quodlibet/ext/events/synchronize_to_device.py:57 #, fuzzy msgid "Deleting" msgstr "Ta bort filer" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Text" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 #, fuzzy msgid "Destination path:" msgstr "Inga stationer funna" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Sökvägsmönster" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Edit saved patterns…" msgstr "Redigera sparade mönster" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 #, fuzzy msgid "Export pattern:" msgstr "_Artist" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 #, fuzzy msgid "Stop preview" msgstr "_Förhandsgranska" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:233 #, fuzzy msgid "Source File" msgstr "Musikspelare" #: quodlibet/ext/events/synchronize_to_device.py:242 #, fuzzy msgid "Export Path" msgstr "Importera spellista" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 #, fuzzy msgid "Stop synchronization" msgstr "organisation" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 #, fuzzy msgid "Choose destination path" msgstr "Välj nya stationer" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 #, fuzzy msgid "Synchronization will:" msgstr "Text" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 #, fuzzy msgid "Export path is not absolute" msgstr "Sökvägen är ej absolut" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Mönstret\t<b>%s</b>\n" "innehåller / men startar inte från roten. För att undvika feldöpta mappar " "ska mönster börja med / eller ~/." #: quodlibet/ext/events/synchronize_to_device.py:873 #, fuzzy msgid "No saved searches selected" msgstr "Inga låtar är valda." #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:883 #, fuzzy msgid "No songs in the selected saved searches" msgstr "Inga låtar är valda." #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 #, fuzzy msgid "Unable to sync" msgstr "Kunde ej spara låt" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1110 #, fuzzy msgid "Synchronization has:" msgstr "Text" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "Kunde ej öppna infiler" msgstr[1] "Kunde ej öppna infiler" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 #, fuzzy msgid "Synchronized Lyrics" msgstr "Text" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 #, fuzzy msgid "Playing:" msgstr "Spelar ej" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:161 #, fuzzy msgid "No song:" msgstr "%d låt" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 #, fuzzy msgid "Status Patterns" msgstr "Sökvägsmönster" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "Auto_matisk" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Spelar ej" #: quodlibet/ext/events/trayicon/__init__.py:52 #, fuzzy msgid "Tray Icon" msgstr "Inställningar för notifieringsikon" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "Spellistor" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Spela upp/pausera" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "Föregående" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 #, fuzzy msgid "_Next" msgstr "Nästa" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Blanda" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetera" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Stoppa efter denna låt" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Öppna ny bläddrare" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Redigera _taggar" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Information" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Spellistor" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Beteende" #: quodlibet/ext/events/trayicon/prefs.py:48 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Skrollhjulet justerar volymen\n" "Skift och skrollhjulet byter låt" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Rullhjul" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Hjälptextvisning" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Text" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Ingen text hittades för denna låt." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Kunde ej spara låt" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Visa fel" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:602 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternativ" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 #, fuzzy msgid "Show current position" msgstr "Inga nya stationer" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "" #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Filer" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Förhandsgranska" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Filtrera på _artist" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 #, fuzzy msgid "Default" msgstr "Förval" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Anpassad" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "Anpassad sortering" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Filtrera på _genre" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Filtrera på _artist" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Ljudfeeds" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Ange platsen för en ljud-feed:" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importera spellista" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Importera" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Inga stationer funna" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Filnamn mönster:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Kan ej importera spellistor" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Filnamn mönster:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Importera spellista" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "Ta bort dubletter" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, fuzzy, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "Är du säker på att du vill ta bort %d dublett?" msgstr[1] "Är du säker på att du vill ta bort %d dublett?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Ny spellista" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "senast spelad" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "senast spelad" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "Köad" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "Köad" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "Köad" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Aldrig" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Aldrig" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "gruppering" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Kunde ej kopiera låtar" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Filtrera på _genre" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Ogiltiga taggar" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 #, fuzzy msgid "@(python: expression)" msgstr "Värdet är ett reguljärt uttryck" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Sparade sökningar" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Sparade sökningar" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, fuzzy, python-format msgid "Couldn't connect to %s" msgstr "Kunde inte ansluta till enhetsdrivrutin." #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Byt namn" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Bibliotek" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Avlusa" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Dölj huvudfönstret" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Filnamn" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Kunde ej spara låt" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Albumomslag" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Storlek" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Sök:" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Sök" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Albumomslag" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Redigera bokmärken" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Redigera bokmärken" #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Bokmärken" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz album typ" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Filnamn" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Skiva" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Spår" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "_Titel" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Artist" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz album typ" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "fråga" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Sök" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Inga insticksmoduler hittades." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "plats" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Albumomslag" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 #, fuzzy msgid "Classic" msgstr "Klassiskt" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Albumomslag" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Inga insticksmoduler hittades." #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Förhandsgranska" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "tagg" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Byt namn" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "tagg" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Aldrig" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Ogiltigt värde" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "Anpassad sortering" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Kunde ej kopiera låtar" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Inaktivera bläddrare" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 #, fuzzy msgid "Duplicate Key" msgstr "Ta bort dubletter" #: quodlibet/ext/songsmenu/duplicates.py:408 #, fuzzy msgid "Remove _Whitespace" msgstr "Ta bort dubletter" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "Ta bort dubletter" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "Ta bort taggar" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Redigera visning" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Multipla %s-värden" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 #, fuzzy msgid "Edit Embedded Images" msgstr "Extrahera inbäddade bilder" #: quodlibet/ext/songsmenu/embedded.py:27 #, fuzzy msgid "Adds, removes or replaces embedded images." msgstr "Extrahera inbäddade bilder" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "Ta bort alla taggar" #: quodlibet/ext/songsmenu/embedded.py:110 #, fuzzy msgid "_Embed Current Image" msgstr "Extrahera inbäddade bilder" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Filtrera på ett taggvärde" #: quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer kunde ej ladda den valda låten." #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtrera på _genre" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Köad" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Skriv" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "MusicBrainz spår-ID" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "mapp" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Albumläge" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Uppdatera stationer" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Inga insticksmoduler hittades." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Flyttar %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Fel vid läsning av %r" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Importera spellista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Importera spellista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Ingen tidsinformation" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Albumomslag" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Importera spellista" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Import" msgstr "_Importera" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Filtrera på _genre" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Skiva" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Spår" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Artist" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "album" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Fortsätt" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, fuzzy, python-format msgid "Couldn't parse JSON in %s" msgstr "%s: Kan inte hitta %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "%s: Kan inte hitta %s." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Filnamn" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "spår" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Fel vid läsning av %r" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Byt namn" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Importera spellista" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Utmatning av <b>%s</b> misslyckades." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Uppdatera biblioteket" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "Uppdatera biblioteket" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Spår" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Redigera taggar" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Redigera taggar" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Alla album" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Förhandsgranska" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Tagg" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Kunde ej ta bort låtar." #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Sök" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "Sökvägsmönster" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Redigera sparade sökningar..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "Färglägg _söktermer" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Redigera taggar" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Sök i hjälpen" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Bibliotek" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Kontrollerar monteringspunkter" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Kontrollerar bibliotek" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Kontrollerar %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Kontrollerar bibliotek" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Ta bort aktuella bläddrarfilter" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "musikbibliotek och -spelare" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Kunde inte ladda filen: %r" #: quodlibet/operon/commands.py:36 #, fuzzy msgid "List tags" msgstr "Lista alla taggar." #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Koncis utmatning" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Vilka kolumner som syns och i vilken ordning i koncist läge (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Lista även programmatiska taggar" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Inte nog många argument" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "För många argument" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Beskrivning" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Värde" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Visa alla gemensamma taggar" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Kopiera taggar från en fil till en annan" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Visa förändringar, verkställ dem inte" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Hoppa över taggar som inte kan skrivas" #: quodlibet/operon/commands.py:145 #, fuzzy, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "Kan ej kopiera tagen %r till filen: %r" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Editera taggar i redigerare" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Inga låtar är valda." #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Sätt en tagg och ta bort alla existerande värden" #: quodlibet/operon/commands.py:306 #, fuzzy, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "Kan ej kopiera tagen %r till filen: %r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Ta bort taggar" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Värdet är ett reguljärt uttryck" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Ta bort alla taggar" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan inte kombinera '--all' med '--regexp'" #: quodlibet/operon/commands.py:368 #, fuzzy, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Kan inte ta bort %r från %r" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Ta bort ett taggvärde" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Lägg till ett taggvärde" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "Kunde inte sätta %r" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Visa filinformation" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Kunde inte ladda filen: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 #, fuzzy msgid "Remove all embedded images" msgstr "Extrahera inbäddade bilder" #: quodlibet/operon/commands.py:571 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrahera inbäddade bilder" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fil" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Visa kortfattad användningsinformation" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%s' är inte ett giltigt kolumnnamn (%s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Okänd" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "I ordning" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_I ordning" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Slumpvis" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Slumpvis" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "senast spelad" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Repetera" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Repetera" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "En låt" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "En låt" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Ström" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Buffrar" #: quodlibet/player/gstbe/player.py:463 #, fuzzy, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Kunde inte skapa förvald GStreamer pipeline." #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "GStreamer output-pipeline används för uppspelning, exempelvis 'alsasink " "device=default'. Lämna tomt för förinstäld pipeline." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Utgångspipeline" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f sekunder" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buffertlängd:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Inga stationer funna" #: quodlibet/player/gstbe/util.py:167 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Ogiltig GStreamer output pipeline, försöker med förvalt värde." #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Kunde ej skapa audiodata" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Ljudenheten %r hittades inte. Kontrollera dina Xine-inställningar i ~/." "quodlibet/config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Kunde inte länka GStreamer-pipeline: '%s'" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Namn:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Insticksmoduler" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Början" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Tid" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Bokmärkesnamn" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Bokmärken" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filter" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Nyligen _spelad" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Nyligen _tillagda" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _högsta" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Alla stationer" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Slumpvis _genre" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Slumpvis _artist" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Slumpvis al_bum" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "De 40 mesta spelade låtarna (mer än 40 kan väljas om flera låtar är spelade " "lika mycket)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Namn:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Värde:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Sparade värden" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Redigera sparade värden..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Auto_matisk" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Spårläge" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albumläge" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Replay Gain volymjusterning" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Okänd" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "Lägg _till fil..." #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Redigera visning..." #: quodlibet/qltk/data_editors.py:365 #, fuzzy msgid "Tag expression" msgstr "Värdet är ett reguljärt uttryck" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Filtrera på ett taggvärde" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Värdet är ett reguljärt uttryck" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Filer" #: quodlibet/qltk/delete.py:63 #, fuzzy msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/delete.py:72 #, fuzzy msgid "The selected files will be deleted from disk." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Ta bort filer" #: quodlibet/qltk/delete.py:106 #, fuzzy msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/delete.py:115 #, fuzzy msgid "The selected files will be moved to the trash." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Flytta till papperskorgen" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Flyttar %(current)d/%(total)d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Kunde ej flytta till papperskorg" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Misslyckades med att flytta <b>%s</b> till papperskorg." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Tar bort %(current)d/%(total)d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Kunde ej ta bort fil" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Borttagning av <b>%s</b> misslyckades." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Bläddrare" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Hämta filer" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "saknas från %d låt" msgstr[1] "saknas från %d låtar" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "skiljer sig mellan %d låt" msgstr[1] "skiljer sig mellan %d låtar" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Dela till flera värden" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Hämta skiva ur _album" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Hämta _version ur titel" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Hämta arrangör ur ar_tist" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Hämta _uppträdande ut artist" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "Hämta _framträdanden från titel" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "Hämta _originalartist från titel" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Lägg till en tagg" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Tagg:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Ta bort _programmatiska taggar" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Ge åtkomst till alla taggar, inklusive maskingenererade. Exempelvis " "MusicBrainz- och Replay Gain-taggar" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Ta bort _programmatiska taggar" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Aldrig" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Fortsätt" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Redigera taggar" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Kopiera _omslag" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Kunde ej lägga till tagg" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Kunde ej lägga till låtar" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Kunde ej lägga till <b>%s</b>\n" "\n" "Den valda filen har ej stöd för flera värden." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Ogiltig tall" msgstr[1] "Ogiltig tall" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Ogiltig tagg <b>%s</b>\n" "\n" "Den valda filen har ej stöd för att redigera den här taggen." msgstr[1] "" "Ogiltig tagg <b>%s</b>\n" "\n" "Den valda filen har ej stöd för att redigera den här taggen." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Ogiltigt värde" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Felaktigt värde: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Taggen är möjligtvis ej korrekt" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> har ändrats utanför programet. Att spara utan att uppdatera " "bilbioteket kan skriva över andra ändringar.\n" "\n" "Spara ändå?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Kunde ej spara låt" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Sparning av filen <b>%s</b> misslyckades. Filen kan vara skrivskyddad, " "korrupt eller så har du inte tillstånd att redigera den." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Fler alternativ" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Insticksmoduler" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s och %(count)d till" msgstr[1] "%(title)s och %(count)d till" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso inställningar" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Mappar" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Ny mapp" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Välj _alla rekursivt" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Ny mapp" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Namn på den nya mappen:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Kunde ej skapa mapp" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Kunde ej ta bort mapp" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Låtar" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "av %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Skiva %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Spår %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Redigera visning" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Inga låtar är valda." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Inga låtar" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Information" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Text" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Producerad av %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "artist" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artister" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "uppträdande" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Aldrig" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d gång" msgstr[1] "%(n)d gånger" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "tillagd" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "senast spelad" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "spelningar" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "överhoppningar" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "betyg" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "längd" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Information" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "Ökande" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "filstorlek" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "ändrad" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d vald" msgstr[1] "%d valda" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Spår otillgängligt" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d låt utan album" msgstr[1] "%d låtar utan album" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Vald discografi" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d låt utan artist" msgstr[1] "%d låtar utan artist" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Total längd:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Total storlek:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Filer" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Ingen text hittades för denna låt." #: quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "Är du säker på att du vill ta bort %d dublett?" #: quodlibet/qltk/maskedbox.py:21 #, fuzzy msgid "The selected songs will be removed from the library." msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Förkasta taggändringar?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Taggar har ändrats men ej sparade. Spara filerna eller återgå och förkasta " "ändringarna?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Aldrig" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Filen existerar" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Byt namn på filer" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Aktiva uppgifter" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d uppgifter körs" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Växla spelnings-/paus-läge" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Växla spelnings-/paus-läge" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "Spel_ordning" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Taggredigering" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Byt namn" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "fråga" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Total storlek:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Insticksmodulfel" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Aktiverad" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Inaktiverad" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Ingen kategori" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Ingen kategori" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Inga insticksmoduler hittades." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Insticksmoduler" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "Visa _fel" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Skiva" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "Sp_år" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "gruppering" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Artist" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Filnamn" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Längd" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "_Hoppa automatiskt till spelande låt" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "När en låt spelas, skrolla till den i låtlistan" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Andra:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Redigera visning..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Synliga kolumner" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Titel innehåller _version" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Album innehåller skivunderrubrik" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Sökning inkluderar personer" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Filnamn innehåller _mapp" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Inställningar" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Synliga kolumner" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Låtlista" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Synliga kolumner" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Globalt filter:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Använd den här sökningen som ett tillägg till alla andra" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Sök" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Bläddrare" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Bekräfta _multipla betyg" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Fråga om man är helt säker innan betygen ändras på flera låtar samtidigt" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Aktivera_ enklicksbetyg" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Möjliggör betygssättning genom att klicka på betygskolumnen i spellistan" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Betyg" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Föredra _inbäddade bilder" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "Använd grafik som finns inbäddade i ljudfilerna i första hand" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 #, fuzzy msgid "_Preferred fixed image filename(s)" msgstr "_Tvinga bildfilnamn:" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albumomslag" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Uppspelning" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Utkonfiguration" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Skala med volymen med det här värdet om ingen Reply Gain-information finns " "tillgänglig" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "_Fall-back förstärkning (dB):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Skala volymen för alla låtar med det här värdet så länge som resultatet inte " "klipper." #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "_Pre-amp förstärkning (dB):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Aktivera Replay Gain volymjusterning" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain volymjusterning" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 #, fuzzy msgid "_Default rating:" msgstr "Förval" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "Betyg" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesisk medelvärdesfaktor (C) för sammanlagt betyg.\n" "0 betyder vanligt medelvärde. Högre faktor betyder att album med får spår " "kommer få mindre extremt betyg. Förändring av faktorn startar en omberäkning " "av alla album." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesisk medelvärdesfaktor" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Epost:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Betyg och antalet spelningar kommer att sparas för denna epost adressen" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Spara taggförändringar automatiskt" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Spara taggförändringar utan bekräftelse när flera filer editerats" #: quodlibet/qltk/prefs.py:629 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "En lista med skiljetecken som används vid delning av taggvärden. Listan är " "mellanslagsseparerad." #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "Dela _på:" #: quodlibet/qltk/prefs.py:645 #, fuzzy msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "En lista med skiljetecken som används vid delning av taggvärden. Listan är " "mellanslagsseparerad." #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "Dela _på:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Taggar" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Taggredigering" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Uppdaterar betyg" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Sök i bibliotek" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Kontrollera ändringar i biblioteket" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "Ladda om biblioteket" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Ladda om alla låtar i bilbioteket (kan ta lång tid)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Inga låtar" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "_Uppdatera biblioteket vid programstart" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Skanna mappar" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s och %(count)d till" msgstr[1] "%(title)s och %(count)d till" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Egenskaper" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Kö" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Rensa fel" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 #, fuzzy msgid "Ephemeral" msgstr "Övergripande" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Ta bort alla låtar från kön" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Modell:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d låt (%(time)s)" msgstr[1] "%(count)d låtar (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Bläddra i bibliotek" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Växla synlighet för huvudfönstret" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Uppspelning" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Välj mappar" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Kunde ej lägga till låtar" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> använder ett protokoll som inte stödjs" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Hoppa till spelande låt" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Fil" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Låtar" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Visa" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Bläddrare" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Kontroll" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Hjälp" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "Lägg _till mapp.." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "Lägg _till fil..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Lägg till en plats" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Redigera bokmärken" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Stoppa efter denna låt" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Onlinehjälp" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Sök i hjälpen" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Lägg till en plats" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Ange platsen för en ljudfil:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Kan lägga till plats" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> är ej en giltig plats." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Lägg till musik" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "Lägg _till mapp.." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Musikspelare" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "Lägg _till fil..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Är du säker på att du vill ta bort %d dublett?" msgstr[1] "Är du säker på att du vill ta bort %d dublett?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Kö" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Är du säker på att du vill ändra betygen på alla %d låtar?" #: quodlibet/qltk/ratingsmenu.py:29 #, fuzzy msgid "The saved ratings will be removed" msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "Ta bort taggar" #: quodlibet/qltk/ratingsmenu.py:32 #, fuzzy, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Betyget på alla markerade låtar kommer att ändras till '%s'" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Betyg" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Ersätt mellanslag med _understreck" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Ta bort _Windows-inkompatibla " #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Ta bort diakritiska tecken" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Ta bort icke-ASCII-tecken" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Använd enbart _gemener" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Byt namn på filer" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Förhandsgranska" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Filnamn" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "album artist" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Ta bort oanvända omslag och kataloger" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Albumomslag" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Nytt namn" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Kunde ej byta namn på fil" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Namnbyte av <b>%s</b> till <b>%s</n> misslyckades. Möjligtvis finns redan " "målfilen eller så har du inte rättigheter att skapa den nya filen eller ta " "bort den gamla." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Ignorera _alla fel" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Fortsätt" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Sökvägen är ej absolut" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Mönstret\t<b>%s</b>\n" "innehåller / men startar inte från roten. För att undvika feldöpta mappar " "ska mönster börja med / eller ~/." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Låtar i de här mapparna kommer att läggas till i biblioteket när det " "uppdateras" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 #, fuzzy msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "Tar bort överblivna iPod-låtar" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Bibliotek" msgstr[1] "Bibliotek" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "Ta bort taggar" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Välj mappar" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Välj mappar" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Sparade sökningar" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Redigera sparade sökningar..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Sök när man slutat skriva" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Visa sökresultat när användaren har slutat skriva" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Gräns:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Vikt" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "fråga" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Visa återstående tid" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Text" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Fokuserar på den spelare som körs" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Sök innom spelande låt" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Kunde ej ta bort låtar." #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Kunde ej ta bort låtar." #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Filtrera på %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Alla _Kolumner" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Spårkolumner" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albumkolumner" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Personkolumner" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Datumkolumner" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Filkolumner" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Produktionskolumner" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Kolumninställningar..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Ta bort från bibliotek" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Ta bort från bibliotek" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Ta bort från bibliotek" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "Färglägg _söktermer" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Lägg till i _kö" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Ta bort från bibliotek" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Kunde ej ta bort fil" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Hämta" msgstr[1] "_Hämta" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Sök i hjälpen" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Hämta fil" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Albumomslag" msgstr[1] "Albumomslag" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Hämta fil" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Ersätt _understreck med mellanslag" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Första bokstaven i varje ord _versal" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Dela till flera _värden" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Taggar från sökväg" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Taggar ersätter redan existerande" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Taggar läggs till till redan existerande" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Mönstret\n" "\t<b>%s</b>\n" "är ogiltigt. Möjligtvis innehåller det samma tagg två gånger eller " "obalanserade hakar (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Mönstret är ogiltigt. Säkerställ att du skriver < och > som \\< och " "> och att hakarna är balanserade.\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Redigera visning" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Spårnummer" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Börja frå_n" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Antal spår:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Spela upp/pausera" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Föregående" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "och %d till..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Sparar låtarna du ändrade." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d låtar sparade\n" "(%(remaining)s återstår)" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Flyttar %(current)d/%(total)d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Kontrollerar monteringspunkter" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "plats" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Importera spellista" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "En spellista med namnet %s finns redan." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Ladda om omslaget" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Filsystem" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Total storlek:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Visa kortfattad användningsinformation" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Visa version och copyright" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Visa filinformation" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[alternativ]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "Alternativet %r känns ej igen." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "Alternativet %r kräver ett argument." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r är ej ett unikt prefix." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbit/s" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Ingen tidsinformation" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minuter" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d timma" msgstr[1] "%d timmar" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dagar" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d år" msgstr[1] "%d år" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "svenne" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Datumet måste skrivas in på formatet 'YYYY', 'YYYY-MM-DD' eller 'YYYY-MM-DD " "HH:MM:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain-förstärkningar måste anges på formen 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain-toppar måste anges på formen 'x.yy'." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID måste vara på UUID-format." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz utgivningsstatus måste vara 'official', 'promotional' eller " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Språket måste vara en ISO 639-2 trebokstavsförkortning" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Utmatning av <b>%s</b> misslyckades." msgstr[1] "Utmatning av <b>%s</b> misslyckades." #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Kunde ej redigera låt" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Sparning av filen <b>%s</b> misslyckades. Filen kan vara skrivskyddad, " "korrupt eller så har du inte tillstånd att redigera den." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Oglitig kodning]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "album" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "arrangör" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "arrangörer" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "arrangör" #: quodlibet/util/tags.py:86 msgid "author" msgstr "författare" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "författare" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "tagg" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "kompositör" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "kompositörer" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "kompositör" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "dirigent" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "dirigenter" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "dirigent" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "kontakt" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:93 msgid "date" msgstr "datum" #: quodlibet/util/tags.py:94 msgid "description" msgstr "beskrivning" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "genre" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "genre" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "uppträdande" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "uppträdande" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "gruppering" #: quodlibet/util/tags.py:98 msgid "language" msgstr "språk" #: quodlibet/util/tags.py:99 msgid "license" msgstr "licens" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "lyrist" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "lyrister" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "lyrist" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organisation" #: quodlibet/util/tags.py:104 msgid "title" msgstr "titel" #: quodlibet/util/tags.py:105 msgid "version" msgstr "version" #: quodlibet/util/tags.py:106 msgid "website" msgstr "webbsida" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "album artist" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "Skivunderrubrik" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "skiva" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "spår" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "katalognummer" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "ursprungligt släppdatum" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "ursprungligt album" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "ursprunglig artist" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "inspelningsdatum" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "utgivningsland" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz spår-ID" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz release-ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz release-ID" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist-ID" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz release-ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz album typ" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz release-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "spårförstärkning" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "spårtopp" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albumförstärkning" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albumtopp" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "Referensljudstyrka" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "skivor" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "spår" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "senast spelad" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "fullt namn" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "monteringspunkt" #: quodlibet/util/tags.py:166 msgid "people" msgstr "personer" #: quodlibet/util/tags.py:168 msgid "year" msgstr "år" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "ursprungligt släppdatum" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "Bokmärke" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "filformat" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Spellistor" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Ljudtaggsredigerare" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Redigera taggar i ljudfiler" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Avsluta Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Musikspelare" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Lyssna på, bläddra i eller redigera din ljudsamling" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Importera spellista" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Kunde ej lägga till låt" #~ msgid "Invalid tags" #~ msgstr "Ogiltiga taggar" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Ogiltiga taggar <b>%s</b>\n" #~ "\n" #~ "Filen har inte stöd för att redigera dessa taggar." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f sekunder" #, fuzzy #~ msgid "Startup" #~ msgstr "_Importera" #~ msgid "Audio Feeds" #~ msgstr "Ljudfeeds" #~ msgid "_Audio Feeds" #~ msgstr "_Ljudfeeds" #, fuzzy #~ msgid "New" #~ msgstr "Nyheter" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Söker efter text..." #, fuzzy #~ msgid "<artist>" #~ msgstr "artist" #, fuzzy #~ msgid "<album>" #~ msgstr "album" #, fuzzy #~ msgid "<title>" #~ msgstr "titel" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Importera spellista" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Importera spellista" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Information" #~ msgid "Unsupported file type" #~ msgstr "Filtypen stödjs ej" #~ msgid "Unable to add station" #~ msgstr "Kunde ej lägga till station" #~ msgid "Device Properties" #~ msgstr "Enhetsinställningar" #~ msgid "Device:" #~ msgstr "Enhet:" #~ msgid "Not mounted" #~ msgstr "Ej monterad" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Monteringspunkt:" #~ msgid "Media Devices" #~ msgstr "Mediaenheter" #~ msgid "_Media Devices" #~ msgstr "_Mediaenheter" #~ msgid "_Eject" #~ msgstr "_Mata ut" #, fuzzy #~ msgid "_Properties" #~ msgstr "Egenskaper" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> använt, <b>%s</b> tillgängligt" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Kopierar <b>%(song)s</b>" #~ msgid "Unable to copy song" #~ msgstr "Kunde ej kopiera låt" #~ msgid "There is not enough free space for this song." #~ msgstr "Det finns inte tillräckligt med fritt utrymme för den här sången." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> kunde inte kopieras." #~ msgid "Unable to delete songs" #~ msgstr "Kunde ej ta bort låtar." #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Tar bort <b>%(song)s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> kunde inte tas bort." #~ msgid "Unable to delete song" #~ msgstr "Kunde ej ta bort låt" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Utmatning av <b>%s</b> misslyckades." #~ msgid "Unable to eject device" #~ msgstr "Kunde inte mata ut enhet" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "Ingen enhetsdrivrutin. Mediaenheter avaktiverade." #~ msgid "Search Library" #~ msgstr "Sök i bibliotek" #~ msgid "_Search Library" #~ msgstr "_Sök i bibliotek" #~ msgid "Rate the playing song" #~ msgstr "Betygsätt den spelande låten" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Visa eller dölj huvudlåtfönstret" #~ msgid "Unknown Device" #~ msgstr "Okänd enhet" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "Kan inte importera %s, som behövs för enhetsstöd." #~ msgid "%r is not a supported device." #~ msgstr "%r stöds inte. " #~ msgid "Initializing device backend." #~ msgstr "Initialiserar enhetsdrivrutin." #~ msgid "Trying '%s'" #~ msgstr "Testar '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "Kunde inte ansluta till enhetsdrivrutin." #~ msgid "Device backend initialized." #~ msgstr "Enhetsdrivrutin initierad." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Filnamn mönster:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Rensa fel" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Text" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Töm sökning" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Text" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Text" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Inga låtar" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Bläddrare" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Kunde ej skapa mapp" #~ msgid "Audio device: %s" #~ msgstr "Ljudenhet: %s" #~ msgid "Downloads" #~ msgstr "Hämtningar" #~ msgid "Size" #~ msgstr "Storlek" #~ msgid "_Download" #~ msgstr "_Hämta" #, fuzzy #~ msgid "The single image filename to use if selected" #~ msgstr "Albumbild som ska tvunget ska användas" #~ msgid "The album art image file to use when forced" #~ msgstr "Albumbild som ska tvunget ska användas" #~ msgid "_Copy to Device" #~ msgstr "_Kopiera till enhet" #, fuzzy #~ msgid "browsers" #~ msgstr "Bläddrare" #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "Kunde inte importera %s. Ljudströmsbläddraren avaktiverad." #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Ett undantagsfel har inträffat i Quod Libet. En dumpfil har skapats i <b>" #~ "%s</b>. Den underlättar felsökningen. Skapa ett nytt ärende på http://" #~ "code.google.com/p/quodlibet/issues/list och bifoga filen eller infoga " #~ "innehållet. Filen kan innehålla viss personlig information om dig och din " #~ "dator. Exempelvis en lista med de senaste spelade filerna. Om det inte är " #~ "acceptabelt, skicka <b>%s</b> med en beskrivning om vad du gjorde i " #~ "stället.\n" #~ "\n" #~ "Nu är Quod Libet instabilt. Omstart rekommenderas. Ditt bibliotek kommer " #~ "att sparas." #~ msgid "Unable to download lyrics." #~ msgstr "Kunde ej hämta text." #~ msgid "Set or toggle the playback order" #~ msgstr "Ange eller växla spelordningen" #~ msgid "Uninitialized iPod" #~ msgstr "iPod ej initierad" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Vill du skapa en tom databas på den här iPoden?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volymsförstärkning (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Lägg ihop taggar med _multipla värden" #~ msgid "Capacity:" #~ msgstr "Kapacitet:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Kunde ej iPod-databas" #~ msgid "Unable to save iPod database" #~ msgstr "Kunde ej iPod-databas" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Kunde inte importera python-gpod, iPodstöd avaktiverat." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "spårtopp" #~ msgid "Shuffle" #~ msgstr "Blanda" #~ msgid "Weighted" #~ msgstr "Viktad" #~ msgid "_Weighted" #~ msgstr "_Viktad" #~ msgid "_One Song" #~ msgstr "_En låt" #~ msgid "Restart the playlist when finished" #~ msgstr "Starta om spellistan vid slut" #~ msgid "Disable Browser" #~ msgstr "Inaktivera bläddrare" #~ msgid "_Disable Browser" #~ msgstr "_Inaktivera bläddrare" #, fuzzy #~ msgid "Force Write" #~ msgstr "Skriv" #~ msgid "Filter on _Genre" #~ msgstr "Filtrera på _genre" #~ msgid "Filter on _Artist" #~ msgstr "Filtrera på _artist" #~ msgid "Filter on Al_bum" #~ msgstr "Filtrera på al_bum" #~ msgid "_Music" #~ msgstr "_Musik" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Bokmärken" #~ msgid "Song _List" #~ msgstr "Låt_lista" #, fuzzy #~ msgid "D:" #~ msgstr "D:" #, fuzzy #~ msgid "W:" #~ msgstr "W:" #, fuzzy #~ msgid "E:" #~ msgstr "E:" #~ msgid "" #~ "Scroll wheel changes song\n" #~ "Shift and scroll wheel adjusts volume" #~ msgstr "" #~ "Skrollhjulet byter låt\n" #~ "Skift och skrollhjulet justerar volymen" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Stoppa efter denna låt" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "och %d till..." #~ msgstr[1] "och %d till..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Hämta skiva ur _album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Tid" #, fuzzy #~ msgid "Select an album" #~ msgstr "Välj _alla" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s och %(count)d till" #~ msgstr[1] "%(title)s och %(count)d till" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Spellistor" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Använd rundande hörn på miniatyrbilder" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Runda hörnen på albumbilder. Omstart kan behövas för att träda i kraft" #~ msgid "Re_fresh Library" #~ msgstr "Uppdatera biblioteket" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "Ta bort taggar" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "GStreamer har ingen funktionalitet att läsa filer. Kontrollera dina " #~ "GStreamerinställningar." #~ msgid "Invalid audio backend" #~ msgstr "Ogiltigt ljuddrivrutin" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "Ljuddrivrutinen %r är inte installerad." #~ msgid "ql-save" #~ msgstr "ql-save" #~ msgid "ql-revert" #~ msgstr "ql-revert" #~ msgid "Print all tags to stdout" #~ msgstr "Skriv ut alla taggar till stdout" #~ msgid "Load tags dumped with 'dump'" #~ msgstr "Läs in taggar dumpade med 'dump'" #~ msgid "command|filename" #~ msgstr "filnamn" #~ msgid "command|tag" #~ msgstr "tagg" #~ msgid "%s: Could not find 'libudev'." #~ msgstr "%s: Hittar inte 'libudev'." #~ msgid "heading|Search" #~ msgstr "Sök" #~ msgid "%d of %d" #~ msgstr "%d av %d" #~ msgid "Usage: %s %s\n" #~ msgstr "Användning: %s %s\n" #~ msgid "_Download..." #~ msgstr "_Hämta..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Ny station" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Skriv över <b>%s</b>?" #~ msgid "Output Error" #~ msgstr "Utfel" #~ msgid "" #~ "GStreamer output pipeline could not be initialized. The pipeline might be " #~ "invalid, or the device may be in use. Check the player preferences." #~ msgstr "" #~ "GStreamer output pipeline kunde inte initieras. Pipelinen kan vara " #~ "ogiltig, eller så används redan enheten. Kontrollera " #~ "uppspelningsinställningarna." #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet körs redan." #~ msgid "No song is currently playing." #~ msgstr "Ingen låt spelas för tillfället" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Kunde inte skriva till %s. Tar bort den." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Redigera bokmärken" #~ msgid "_New Folder..." #~ msgstr "Ny mapp..." #~ msgid "_Add to Playlist" #~ msgstr "_Lägg till i spellista" #~ msgid "_Edit Display..." #~ msgstr "_Redigera visning..." #~ msgid "Output Log" #~ msgstr "Utgångslogg" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d station" #~ msgid "_Order:" #~ msgstr "_Ordning:" #~ msgid "_Add a Location..." #~ msgstr "Lägg _till plats..." #~ msgid "_Output Log" #~ msgstr "_Utlogg" #~ msgid "Invalid command %r received." #~ msgstr "Ogiltigt kommando %r." #~ msgid "Unknown browser %r." #~ msgstr "Okänd bläddrare %r." #~ msgid "Custom _Sort..." #~ msgstr "Egen _sortering..." #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d song?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d songs?" #~ msgstr[0] "Är du säker på att du vill ändra betygen på alla %d låtar?" #~ msgstr[1] "Är du säker på att du vill ändra betygen på alla %d låtar?" #, fuzzy #~ msgid "Are you sure you want to run the \"%s\" plugin on %d album?" #~ msgid_plural "Are you sure you want to run the \"%s\" plugin on %d albums?" #~ msgstr[0] "Är du säker på att du vill ta bort %d dublett?" #~ msgstr[1] "Är du säker på att du vill ta bort %d dubletter?" #~ msgid "Track Headers" #~ msgstr "Spårkolumner" #~ msgid "People Headers" #~ msgstr "Personkolumner" #~ msgid "Album Headers" #~ msgstr "Albumkolumner" #~ msgid "Date Headers" #~ msgstr "Datumkolumner" #~ msgid "File Headers" #~ msgstr "Filkolumner" #~ msgid "Production Headers" #~ msgstr "Produktionskolumner" #~ msgid "Tag:" #~ msgstr "Tagg:" #~ msgid "Descending" #~ msgstr "Avtagande" #~ msgid "Too Many Errors" #~ msgstr "För många fel" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Uppspelning avbryts på grund av att det var %d fel på rad." #~ msgid "Warnings" #~ msgstr "Varningar" #~ msgid "No log available." #~ msgstr "Inga loggar tillgängliga." #~ msgid "album artist (sort)" #~ msgstr "album artist (sort)" #~ msgid "artist (sort)" #~ msgstr "artist (sort)" #~ msgid "album (sort)" #~ msgstr "album (sort)" #~ msgid "performer (sort)" #~ msgstr "uppträdande (sort)" #~ msgid "performers (sort)" #~ msgstr "uppträdanden (sort)" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz album artist-ID" #~ msgid "errors" #~ msgstr "fel" #~ msgid "Failed reading album art \"%s\"" #~ msgstr "Kunde inte läsa albumbiler \"%s\"" #~ msgid "Permanently delete this file?" #~ msgstr "Ta bort filen permanent?" #~ msgid "Permanently delete these files?" #~ msgstr "Ta bort filerna permanent?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s och %(count)d till..." #~ msgstr[1] "%(title)s och %(count)d till..." #~ msgid "Version:" #~ msgstr "Version:" #~ msgid "_Cause an Error" #~ msgstr "_Orsaka ett fel" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s kunde ej läggas till i biblioteket.\n" #~ "\n" #~ msgid "Error running command %r, caused by: %r." #~ msgstr "Fel inträffade vid körning av kommando %r, orsakat av %r." #~ msgid "" #~ "Cannot save library contents to %s (it's a directory). Please remove it " #~ "and try again." #~ msgstr "" #~ "Kunde inte spara biblioteksinnehåll till %s (det är en katalog). Ta bort " #~ "den och försök igen." #~ msgid "Library Error" #~ msgstr "Biblioteksfel" #~ msgid "_Output device:" #~ msgstr "_Utenhet" #~ msgid "translator-credits" #~ msgstr "Erik Christiansson" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Andra kolumner att visa, separerade med mellanslag" #~ msgid "_Edit and Continue" #~ msgstr "_Editera och fortsätt" #~ msgid "Search your library" #~ msgstr "Sök i ditt bibliotek" #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "Detta är fri mjukvara, se källkoden för kopieringsvillkor. There is NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ "Inga garantier lämnas, inte ens för KÖP eller LÄMPLIGHET FÖR NÅGOT " #~ "SPECIELLT ÄNDAMÅL.\n" #~ msgid "Unable to start web browser" #~ msgstr "Kunde ej starta webbläsare" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Ingen webbläsare kunde hittas. Ställ in din $BROWSER-variabel eller " #~ "säkerställ att /usr/bin/sensible-browser finns." #, fuzzy #~ msgid "No eject command found." #~ msgstr "Inga stationer funna" #, fuzzy #~ msgid "Confirm rating" #~ msgstr "Information" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Total storlek:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet-insticksmoduler" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Visa enkla sökningar i blått, avancerade i grönt och ogiltiga i rött" #~ msgid "Separators for splitting tags" #~ msgstr "Avgränsare för taggdelning" #~ msgid "Quod Libet Preferences" #~ msgstr "Inställningar för Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Ej spelad i_dag" #~ msgid "Not Played in a _Week" #~ msgstr "Ej spelad på en _vecka" #~ msgid "Not Played in a _Month" #~ msgstr "Ej spelad på en _månad" #~ msgid "B_ottom 40" #~ msgstr "40 _lägsta" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "De 40 minst spelade låtarna (mer än 40 kan väljas om flera låtar är " #~ "spelade lika mycket)" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | kontroll ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Datum" #~ msgid "Add" #~ msgstr "Lägg till" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stationer..." #~ msgid "Unable to save library" #~ msgstr "Kunde ej spara bibliotek" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "Kan ej spela låt" #~ msgid "Sort by title" #~ msgstr "Sortera efter titel" #~ msgid "Sort by artist" #~ msgstr "Sortera efter artist" #~ msgid "Lyrics provided by %s." #~ msgstr "Texter från %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Texter hittades inte.\n" #~ "\n" #~ "Klicka på kanppen Hämta för att låte Quod Libet söka efter texten på " #~ "internet. Du kan också skriva in texten själv och klicka på Spara." #~ msgid "part" #~ msgstr "del" #~ msgid "Opening audio device." #~ msgstr "Öppnar ljudenhet" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d låtar sparade" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz album-ID" #~ msgid "Loaded song library." #~ msgstr "Låtbibliotek laddat." #~ msgid "Unable to open audio device" #~ msgstr "Kunde ej öppna ljudenhet" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet försökte komma åt drivrutinerna 'autosink' och '%(sink)s' men " #~ "kunde inte öppna dem. Konfigurera din GStreamer-pipeline genom att ändra " #~ "raden\n" #~ "....<b>pipeline = %(sink)s</b>\n" #~ "i ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet kunde ej hitta GStreamer-elementet 'filesrc'. Kontrollera din " #~ "GStreamer-installation." #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "Visa album_omslag" #~ msgid "Unable to retag multiple values" #~ msgstr "Kan ej tagga om flera värden" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "Det går ej att byta namn på en tagg med flera värden." #~ msgid "W: %s is not a QL song database." #~ msgstr "W: %s är ej en QL-låtdatabas." #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "Låtvis (\"radio\") volymjustering" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "Albumvis (\"audiofil\") volymjustering" #~ msgid "_Volume Normalization" #~ msgstr "_Volymnormalisering" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "Skannar biblioteket. Detta kan ta flera minuter.\n" #~ "\n" #~ "%d låtar omladdade\n" #~ "%d låtar borttagna" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "Söker efter nya låtar och lägger till dem i biblioteket.\n" #~ "\n" #~ "%d låtar tillagda" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3U-spellistor kan ej laddas." #~ msgid "This station is already in your library." #~ msgstr "Stationen finns redan i biblioteket." #~ msgid "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "by <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Disc <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Track <tracknumber>>>" #~ msgstr "" #~ "\\<span weight='bold' size='large'\\><title>\\</span\\><~length| " #~ "(<~length>)><version|\n" #~ "\\<small\\>\\<b\\><version>\\</b\\>\\</small\\>><~people|\n" #~ "av <~people>><album|\n" #~ "\\<b\\><album>\\</b\\><discnumber| - Skiva <discnumber>><part| - \\<b" #~ "\\><part>\\</b\\>><tracknumber| - Spår <tracknumber>>>" #~ msgid "The library cannot be refreshed while Quod Libet is running." #~ msgstr "Biblioteket kan inte uppdateras när Quod Libet körs" #~ msgid "Loading, scanning, and saving your library." #~ msgstr "Läser hem, skannar och sparar bilblioteket" #~ msgid "Rescan your library and exit" #~ msgstr "Skannar om biblioteket och avslutar" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/tr.po����������������������������������������������������������������������������0000644�0001750�0001750�00000763205�14436352625�013635� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Language po/tr translations for PACKAGE package. # Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # genel <turerkan@gmail.com>, 2009. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 2.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-05-01 03:50+0000\n" "Last-Translator: Sabri Ünal <libreajans@gmail.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/tr/>\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.18-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Başlık" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "_Kişiler" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Tarih" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Eklenme Tarihi" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Çıkış Tarihi" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Tür" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "_Puan" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "Çalma _Sayısı" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "_Sırala…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "_Tercihler" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Albüm Listesi" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "_Albüm Listesi" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Bütün Albümler" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albüm" msgstr[1] "%d albüm" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Albüm _kapağını yeniden yükle" msgstr[1] "Albüm _kapaklarını yeniden yükle" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Bir albümde olmayan şarkılar" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d parça" msgstr[1] "%d parça" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d disk" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Örnek Albüm" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albüm Listesi Tercihleri" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Albüm _kapaklarını göster" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "_Arama kişileri de içerir" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Seçenekler" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Albüm Görünümü" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Kapat" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Kitaplık Tarayıcı" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d şarkı" msgstr[1] "%d şarkı" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Geçersiz kalıp" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Albüm Koleksiyonu" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "Albüm _Koleksiyonu" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Bilinmeyen %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "Çoklu %s Değer" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Özel" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Ekle" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "_Kaldır" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Etiket" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Birleştir" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Albüm Koleksiyonu Tercihleri" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Uygula" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_İptal" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "Kapak Izgarası" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "_Kapak Izgarası" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Kapak Izgarası Tercihleri" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Albüm _metnini göster" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "\"Bütün Albümler\" Ögesini Göster" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Geniş Kip" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "Kapak Resmi Büyütme" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Dosya Sistemi" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Dosya Sistemi" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Şarkılar kopyalanamıyor" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Seçilen şarkılar başka çalma listelerine veya çalma kuyruğuna kopyalanamıyor." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Kitaplığa Ekle" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "İstasyon listesi sadece istasyon konumu içerebilir; diğer istasyon " "listelerini veya çalma listelerini içeremez. Aşağıdaki konumlar " "yüklenemiyor:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "İnternet Radyosu" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "İstasyon ekle" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "İstasyon listesi indiriliyor" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Yeni İstasyon" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "İnternet radyo istasyonu adresi girin:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Elektronik" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Nostalji" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japonca" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Hintçe" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Dini" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Grafikler" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Türkçe" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae / Dans Salonu" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Fakülte Radyosu" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Sohbet / Haberler" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ortam" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Caz" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasik" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternatif" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Haberler" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Bağımsız" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slav" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Yunan" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gotik" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Yaygın radyo istasyonlarının listesini yüklemek ister misiniz?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_İstasyonları Yükle" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_İnternet Radyosu" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Bütün İstasyonlar" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Beğenilenler" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Kategorisiz" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "_İstasyon Ekle…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "İstasyonları _Güncelle" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "İstasyon bulunamadı" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s adresinde İnternet radyo istasyonu bulunamadı." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Eklenecek bir şey yok" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Listelenen bütün radyo istasyonları zaten kitaplığınızda." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Beğenilenlere Ekle" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Beğenilenlerden Kaldır" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d istasyon" msgstr[1] "%(count)d istasyon" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Panelli Tarayıcı" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "_Panelli Tarayıcı" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Hepsini _Seç" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Bilinmeyen" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Hepsi" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Küçük" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Geniş" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Sütunlu" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "İsteğe bağlı biçimlendirmeli etiket kalıbı örn. <tt>composer</tt> veya\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "Panelli Tarayıcı Ayarları" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Sütun yerleşimi" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Sütun içeriği" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Eşit panel genişliği" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Çalma Listeleri" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Çalma Listeleri" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "Çalma Listesinden _Kaldır" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Yeni" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "İçe _Aktar…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Çalma listesi içe aktarılamadı" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet sadece M3U/M3U8 ve PLS biçimli çalma listelerini içe aktarabilir." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Sil" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Yeniden Adlandır" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Çalma listesinin adı değiştirilemedi" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Çalma Listesi İçe Aktar" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "İçe _Aktar" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Yeni Çalma Listesi…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Bu %d şarkı ile ne yapmak istersiniz?" msgstr[1] "Bu %d şarkı ile ne yapmak istersiniz?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "\"%s\" çalma listesi için eylemi doğrula" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "boş" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Örnek Çalma Listesi" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Çalma Listesi Tarayıcı Tercihleri" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Çalma listesi ekranı" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "'%s' çalma listesini silmek istediğinize emin misiniz?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Seçilen çalma listesi ile ilgili bütün bilgiler silinecek ve geri " "yüklenemeyecek." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "_Parça Ekle" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Yeni Çalma Listesi" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Yeni çalma listesi için ad girin:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_Oluştur" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Şarkı listesi içe aktarılıyor.\n" "\n" "%(current)d/%(total)d şarkı eklendi." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Yeni Besleme" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "Podcast / Ses beslemesi konumunu gir:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Podcastler" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_Podcastler" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "Besleme _Ekle…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Yenile" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "Kaynağı yeni bölümler için tara" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_Yeniden oluştur" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "Mevcut tüm bölümleri kaldır, ardından kaynaktan yeniden yükle" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "Bu podcast'i ve bölümlerini kaldır" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Besleme eklenemiyor" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "%s eklenemedi. Sunucu çalışmıyor olabilir veya adres podcast / ses beslemesi " "olmayabilir." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" "Mevcut ses arka ucu URL'leri desteklemiyor, Podcast tarayıcı devre dışı." #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "Sonuçları _Sınırla" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "Çoklu sorguya _izin ver" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Parça Listesi" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "_Parça Listesi" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud Tarayıcı" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Ara" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Parçalarım" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "%s sitesine git" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Bağlandı" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet şuan bağlandı, %s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "%s'ten çıkış yap" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Kod girin…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "%s sitesine oturum aç" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud kimlik doğrulama" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Soundcloud kimlik doğrulaması kodunu girin:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet çalışmıyor (program adı yanına '--run' ekleyip çalıştırın)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "bir müzik kitaplığı ve müzik çalar" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[seçenek]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Çalan şarkıyı yazdır ve çık" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Hemen çalmaya başla" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Başlangıçta hiç pencere gösterme" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Sonraki şarkıya atla" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Önceki şarkıya atla veya başlangıca yakınsa yeniden başla" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Önceki şarkıya atla" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Çalmaya başla" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Çalmayı duraklat" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Çalma/duraklama kipini aç/kapat" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Çalmayı durdur" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Sesi aç" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Sesi kıs" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Şarkıyı çalma puanını bir yıldız artır" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Şarkıyı çalma puanını bir yıldız azalt" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Durum bilgisini göster" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Ana pencereyi gizle" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Ana pencereyi göster" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Ana pencere görünürlüğünü aç/kapat" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Çalışan müzikçalara odaklan" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Etkin tarayıcı süzgeçlerini kaldır" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Kitaplığı yenile ve tekrar tara" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Mevcut tarayıcıları listele" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Şu anki çalma listesini göster" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Kuyruğun içeriğini göster" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Etkin yazı sorgusunu ekrana yazdır" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Eklentiler olmadan başlat" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet çalışmıyorsa başlat" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Quod Libet'ten çık" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Şarkı içinde ileri/geri git" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][SS:]DD:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Karıştırma kipini ayarla veya kipe geç" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Karışıktırma kipi türünü ayarla" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Tekrarlamayı aç, kapat veya değiştir" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Tekrarlama kipi türünü ayarla" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Ses yüksekliğini değiştir" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Müzik kitaplığınızda arama yapın" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "sorgu" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Bir ses dosyası çal" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "dosyaadi" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "Çalan şarkının puanını ayarla" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Geçerli tarayıcıyı ayarla" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Çalan şarkıdan sonra durdur" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Yeni tarayıcı aç" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Kuyruğu göster veya gizle" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Rastgele bir değerle süz" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "etiket" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Bir etiket değerine göre süz" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "etiket=değer" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Dosya veya sorguyu kuyruğa ekle" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Virgülle ayrılan dosyaları kuyruğa ekle" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "dosyaadı" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Sorgu sonuçlarının dosya adlarını stdout'a yazdır" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Dosya veya sorguyu çalma kuyruğundan çıkar" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Dosya veya dizini kitaplığa ekle" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "konum" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "--print-* komutları için şablon ayarla" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "kalıp" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "'%s' için geçersiz parametre." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Yardım için %s --help komutunu deneyin." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Hata Oluştu" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Bu hatayı görmezden gelebilirsiniz ancak uygulama yeniden başlatılıncaya " "kadar kararsız olabilecektir. Bir hata raporu göndermek bir kaç saniye " "alacaktır ve bize çok yardımı olur." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Hata Raporu Gönder" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Yeniden Başlat" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Hatayı Yoksay" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Hata ayrıntıları:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Hatayla ve sisteminizle ilgili çeşitli ayrıntılar üçüncü parti bir online " "hizmete (<a href='https://www.sentry.io'>www.sentry.io</a>) gönderilecektir. " "Göndermeden önce aşağıdaki veriye göz atabilirsiniz." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(isteğe bağlı) Lütfen hata oluştuğunda ne olduğuna dair kısa açıklama " "sağlayınız:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Gönder" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Kısa açıklama…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Gönderilecek veri:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "ses etiketi düzenleyici" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "dizin" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Ses üstverisi düzenleyici" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "Sanatsal URL Albüm Kapağı Kaynağı" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "<tt>artwork_url</tt> etiketi ile bağlantılı kapakları indirir. Bu, " "Soundcloud ve Podcasts tarayıcıları ile çalışır." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs Albüm Kapağı Kaynağı" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Albüm kapaklarını Discogs'tan indirir." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm Albüm Kapağı Kaynağı" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Albüm kapaklarını Last.fm kapak resmi arşivinden indirir." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz Albüm Kapağı Kaynağı" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Albüm kapaklarını MusicBrainz'in kapak resmi arşivinden indirir." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Kodlamaları Dönüştür" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Etiket düzenleyicide yorumlanmamış olan etiket değeri kodlamalarını onarır." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Kodlama Dönüştürülüyor…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji Basite Çevirme" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Kana/kanjiyi yeniden adlandırmadan önce romajiye dönüştürür." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Latince ile yazılmış _Japonca metin" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "'Kanji Kana Basit Çevirici' (kakasi) bulunamadı." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "Düzenli İfade Değişimi" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Dosyaları etiketlerken veya yeniden adlandırırken isteğe bağlı düzenli ifade " "değişimine (<tt>s/from/to/</tt>) izin verir." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Başlık Düzeni" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Etiket düzenleyicide etiket değerlerini Başlık Düzenine dönüştürür." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Başlık _Düzeni Değer" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Etiketlerde _TÜMÜ-BÜYÜK-HARF'e izin ver" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Kişilerin baş _harfi büyük" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Başlık gövdesi için genel İngilizce kurallarını kullanır; \"Dark Night of " "the Soul\" gibi" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Gelişmiş Tercihler" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Gelişmiş yapılandırma ayarlarını düzenlemeye izin ver." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Ne yaptığımı biliyorum" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "Hareketli Ekran Üstü İleti Penceresi" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Şarkı bilgilerinizi, değişiklik olduğunda ekranınızda görüntüler." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Konum:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "_Kapak boyutu:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Görüntü" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Yazıtipi:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Sol" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "Merkez" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Sağ" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Metni hizala:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Metin" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Metin:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "_Doldur:" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Renkler" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Gölgeler" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "_Dış Çizgi" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "Yuva_rlatılmış Köşeler" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Gecikme:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Efektler" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Görünüm Kalıbını _Düzenle…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Önizle" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Uygulama Bilgileri" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Uygulama ve ortamı hakkında çeşitli bilgiler." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Desteklenen Biçimler" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Yapılandırma Dizini" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Önbellek Dizini" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Ses Arka Ucu" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Her çalmadan sonra (varsayılan)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "Bir şarkı ne zaman atlanmadan çalınırsa, bu eklenti etiketleri dosyaya " "yazacaktır. Atlama sayısı dosyalarda hiçbir zaman depolanmaz ve böylece " "gereksiz yazmaların önüne geçer." #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Her çalmadan veya atlamadan sonra" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Bir şarkı ne zaman çalınır veya atlanırsa, bu eklenti etiketleri dosyaya " "yazacaktır. Beğenmediğiniz şarkıların puanlarından emin olmak isterseniz bu " "kullanışlı olabilir ve böylece atlananlar dosyalara yazılır." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Bir kez, albüm tamamen puanlandığında" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "Bir şarkı çalındığında veya atlandığında o şarkının albümü işaretlenir. Eğer " "albümdeki her şarkı puanlanmış ve en azından birinin puanı yoksa veya çalma " "sayısı dosyasında kayıtlıysa eklenti, şarkıların dosyalarına etiketleri " "yazacaktır.\n" "\n" "Sabit dosya güncellemelerinden kaçınmak için bunu kullanın ancak unutmayın " "ki bir kere bir albüm güncellendiğinde, değiştirilmiş puanların ve çalma " "sayılarının dosyalara yazılmasını her istediğinizde 'Dosyalardaki Etiketleri " "Güncelle' eklentisini kullanmanız gerekecektir." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "Eklenti bir albümün etiketlerini yazdığında, önce şarkıların çalma sayısını " "sıfırdan bire ayarlayacaktır.\n" "Bazen bir şarkıyı sevmediğinizi zaten bilirsiniz; böylece tamamını " "dinlediğiniz albümleri aradığınızda, kayıt ederken değerin bire ayarlanması " "ileride kullanışlı olabilir (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "'%s' yazılamadı" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Dosyalardaki Etiketleri Otomatik Güncelle" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "Şarkılar çalındığında dosyalarındaki etiketleri güncelle. Bu, çalma " "sayılarını ve puanları güncel tutacaktır." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "Bu eklentinin çalışabilmesi için gereken aşağıdaki ayarlar etkinleştirildi:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Puan ve _çalma sayılarını etiketlerde kaydet" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Ayarlar güncellendi" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "%s te hata" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "Kayıt ederken, çalma sayılarını sıfırın üzerinde tutar" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Stratejiyi güncelle:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Tercihler" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "Otomatik Maskeleme" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Sürücüleri, çıkarıldığında veya takıldığında otomatik olarak gizler ve " "gösterir." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Otomatik Puanlama" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Şarkılar çalındığında veya atlandığında otomatik olarak derecelendirir. Bu, " "Brian Nelson'ın vux (Vacillating Utilitarian eXtemporizer) 'hızlandırılmış' " "algoritmasını kullanır." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Belirtilen Banshee veri tabanı kötü biçimlendirilmiş veya kayıp" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "İçe Aktarma Başarısız" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "%d şarkının puanı ve istatistikleri içe aktarıldı" msgstr[1] "%d şarkının puanları ve istatistikleri içe aktarıldı" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee İçe Aktar" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Puanlar ve şarkı istatistiklerini Banshee'den içe aktarır." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Veri tabanı yolu:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "İçe Aktarmayı Başlat" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Alarm Saati" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "Sizi yüksek sesle uyandırır." #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Ninni" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Müziğinizi kısarak duraklatır." #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord durum iletisi" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Discord Durum İletisi" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "Discord durum iletisini şuan dinlediğiniz şeye göre değiştirin." #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "Duraklatıldı" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "Durum Satırı #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "Durum Satırı #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Düz" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Canlı" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "Tam Bas & Tiz" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Kulüp" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Geniş Salon" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Parti" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Hafif" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Tam Bas" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Regi" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Kulaklıklar" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Hafif Rock" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "Tam Tiz" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "Dans" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Tekno" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ska" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "Dizüstü" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Dengeleyici" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Müziğinizin tonunu bir dengeleyici ile denetler.\n" "Seviyeleri özelleştirmek için tıklayın veya tuşları kullanın (sağ tık, bantı " "sıfırlar)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "Mevcut arka uç, dengeleyiciyi desteklemiyor." #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "Varsayılan ön ayarlar" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Seç…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "EQ sıfı_rla" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "Özel ön ayarlar" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Seçileni sil" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "Kaydedilecek ön ayar adı:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Kaydet" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "çevrimiçi" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "çevrimdışı" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "sohbet" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "uzakta" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "görünmez" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim Durum İletisi" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "Gajim durum iletisini şuan dinlediğiniz şeye göre değiştirir." #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "duraklatıldı" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Kalıp:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "Durum iletisini değiştirmek için, boşluklarla ayrılmış olarak, hesapları " "listele. Hiçbiri belirtilmemişse, bütün hesapların durum iletileri " "değiştirilecek." #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Hesaplar:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Ekle '[duraklatıldı]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "İşaretlenirse, duraklatma olduğunda '[duraklatıldı]' ifadesi durum iletisine " "eklenecek" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "Değiştirilecek ileti için durumlar" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "Kulaklık Çıkarıldığında Duraklat" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "Kulaklık çıkartıldığında duraklatır ve tekrar takıldığında devam eder." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Ekran Koruyucuyu/Askıya Almayı Önle" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "Bir GNOME masaüstünde bir şarkı çalarken, ekran koruyucunun etkinleşmesini " "veya bilgisayarın askıya alınmasını önler." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Müzik çalıyor" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Kip:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Ekran Koruyucuyu Engelle" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Askıya Almayı Engelle" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "İnternet Radyosu Sistem Günlüğü" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Radyo istasyonlarında çalınan son 10 şarkıyı kaydeder ve bunları arama " "bağlam menüsünde listeler." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Bir Jabber Kullanıcı Ayarları dosyasını %(path)s adresine gönderir." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Dili Değiştir" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Kullanıcı arayüzü dilini değiştir." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Sistem Varsayılanı" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Değişikliklerin geçerli olması için yeniden başlatma gereklidir" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Ortam Sunucusu" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Bütün albümleri MediaServer2 D-Bus arayüzü yoluyla Rygel UPnP Ortam " "Sunucusunda gösterir." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Aşağıdakinin rygel yapılandırma dosyanızda (~/.config/rygel.conf) olduğundan " "emin olun:" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD Sunucusu" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Bir MPD İstemcisi kullanan Quod Libet'in uzaktan kontrolüne izin verir. " "Akış, çalma listesi ve kitaplık yönetimi desteklenmiyor." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Bağlantı Noktası:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "Yerel _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "P_arola:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Bağlantı" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Test Edilmiş İstemciler" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus Desteği" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "<a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a> D-Bus " "Arayüz Spesifikasyonunu kullanarak Quod Libet'in denetimine izin verir. Bu, " "çeşitli Linux masaüstü tümleşimlerine (örneğin çoklu ortam tuşları) izin " "verir." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Kapatırken ana pencereyi gizle" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "QL Kalıplarını Kabul Eder, örn. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT Yayıncısı" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Durum iletilerini bir MQTT konusunda yayınlar." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Aracı sunucu adı /IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Ana makine varsayılanları" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Aracı bağlantı noktası" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Varsayılan değer 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Aracı kullanıcı adı" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Aracı parolası" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Konu" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Çalma Kalıbı" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Bir şarkı başladığındaki durum metni." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Duraklatma Kalıbı" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Bir şarkı duraklatıldığındaki metin." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Şarkısız Metin" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Mevcut şarkı olmadığındaki düz metin" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT Yapılandırması" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Durum Metni" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "%(host)s:%(port)d üzerindeki aracıya bağlandı" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "Bağlanılamadı: %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Bağlantı hatası" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz Eşitleme" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Bir şarkının puanını MusicBrainz ile eşleştirir." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "Kulla_nıcı adı:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Parola:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Hesap" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Bildirim metni" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Başlık:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Varsayılan kalıba geri döndür" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Gövde:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "Bildirim gö_ster" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Bildirimleri göster" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Sadece <i>_elle</i> şarkı değiştirmede" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Sadece <i>_otomatik</i> şarkı değiştirmede" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "<i>_Bütün</i> şarkılar değiştiğinde" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Sadece ana pencereye _odaklanılmadığında" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "\"So_nraki\" düğmesini göster" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Bağlantı Hatası" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Bildirim sürecine bağlanılamadı." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Şarkı Bildirimleri" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Şarkı değiştiğinde bildirim görüntüler." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Sonraki" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "Yer İmi Bildirimleri" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Yer imlerini / yorumları gerçek zamanlı olarak görüntülemek için " "bildirimleri kullanır. Soundcloud tarayıcısı ile iyi çalışır." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "QLScrobbler'ı kurmak için lütfen Eklentiler penceresini ziyaret edin. O " "zamana kadar şarkılar görderilmeyecek." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "'%s' hizmeti ile iletişim sağlanamadı." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Doğrulama başarısız: geçersiz URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Doğrulama başarısız: Geçersiz kullanıcı adı '%s' veya yanlış parola." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "İstemci yasaklanmış. Sahibi ile iletişime geçin." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "Sistem saati yanlış. Düzeltilene kadar gönderimler başarısız olabilir." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler Gönderimi" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Last.fm, Libre.fm ve diğer Audioscrobbler hizmetleri için Audioscrobbler " "istemcisi." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Kimlik doğrulama başarılı." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Hizmet:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Diğeri…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "Hesap _verisini doğrula" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "_Sanatçı kalıbı:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "_Başlık kalıbı:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "Süzgeci _hariç tut:" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Alt görev için sanatçı adını biçimlendirmede kullanılan kalıp. Varsayılan " "için boş bırakın." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Gönderilecek başlığı biçimlendirmek için kullanılan kalıp. Varsayılan için " "boş bırakın." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Bu süzgeçle eşleşen şarkılar gönderilmeyecek" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Çevrimdışı kip (hiçbir şey gönderme)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Gönderim" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "Radyo Reklamlarını Sustur" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Raydo reklamları çalıyorken çıkışı susturur.\n" "İstasyonlar: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Rastgele Albüm Çalma" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Çalma listeniz sona geldiğinde rastgele bir albüm çalmaya başlar. Etkin " "tarayıcının albüme göre süzmeyi desteklemesini gerektirir." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Daha yüksek puanlanmış" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Daha sık çalınmış" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Daha sık atlanmış" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Yakın zamanda çalınmış" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Daha yakın zamanda başlatılmış" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Daha yakın zamanda eklenmiş" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Daha uzun albümler" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "sonraki albüm başlamadan önceki saniye" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Ağırlık" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Bazı albümleri diğerlerinden daha sık çal" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "kaçın" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "tercih et" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Rastgele Albüm" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "%s'in başlamasını bekliyor" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "%d şarkının puanları ve istatistikleri içe aktarıldı" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox İçe Aktarma" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Puanlar ve şarkı istatistiklerini Rhytmbox'tan içe aktarır." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Ekran Koruyucu Duraklatması" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "GNOME ekran koruyucu etkinken çalmayı duraklatır." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Quod Libet için hiçbir GNOME Kabuğu arama sağlayıcısı yüklü değil." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME Arama Sağlayıcısı" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "GNOME Kabuğu'nun kitaplığı aramasına izin verir." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "Alternatif İlerleme Çubuğu" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Her zaman görünür olan ve bütün pencere genişliğine uzayan alternatif " "ilerleme çubuğu." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "İlerleme Noktası Yer imleri" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Parçalar için A ve/veya B Arama Noktalarını sakla. Parça çalındığında A " "saatine atla ve B saatinden sonra dur.\n" "\n" "ℹ Aşağıdaki noktaların adlarını değiştirmenin gerçek yer imi adlarını " "güncellemediğini, yalnızca eklentinin aramaya karar verirken hangi yer imi " "adlarını arayacağını değiştirdiğini unutmayın." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "A noktası için yer imi adı" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Parçanın ne zaman başlatıldığını denetlemek için yer imi adı, ve bulunursa " "çalıcı zaman damgasını arar" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "B noktası için yer imi adı" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Varsa, parçanın çalınması sırasında her bir onay işaretini kullanmak için " "yer imi adı. Geçerli konum zaman damgasını aşarsa, parçanın sonuna kadar " "arayın." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox Eşitleme" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Logitech Squeezebox'u Quod Libet çıktısına yansıtır ve böylece her ikisinin " "eş bir kitaplıktan okumasını sağlar." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Yapılandırmayı <a href=\"%(plugin_link)s\">Squeezebox eklentisine paylaş</a> " "ile paylaşır." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Squeezebox sunucusu bulma hatası" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "%s bulma hatası. Lütfen ayarları denetleyin" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "Duraklatmada Durdur" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "Bu eklenti Duraklatma komutunu, Durdur/Çal/Sar komutlarıyla değiştirir.\n" "\n" "Eğer yeni bir aygıt (Bluetooth hoparlör, USB DAC vb.) sisteme bağlandığında " "Quod Libet ses aygıtlarına geçiş yapamazsa kullanışlıdır.\n" "\n" "'Sadece İleri/Geri Sarılabilen Kaynaklar'ın kapalı olması şartıyla, mevcut " "kaynaktaki konumun korunmasından emin olur. Aksi halde, çalma durdurulmuş " "olarak bırakılır ve yeniden baştan başlamak zorundadır." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Sadece İleri/Geri Sarılabilen Kaynaklar" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "Eklenti Seçenekleri" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Kopyalama askıya alınıyor" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Silme askıya alınıyor" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "sil" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Geç" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "ÇOĞALT" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Eşzamanlanıyor" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Siliniyor" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Başarılı" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "BAŞARISIZ" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Atlanan mevcut dosya" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Şarkının dosya adı ayarlanamıyor." #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "Aygıta Eşitle" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Seçilen kayıtlı aramalardan bütün şarkıları belirlenen klasör ile eşitler." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Aşağıdaki kayıtlı aramaları eşitle:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "Dışa aktarma konumunuzun tam yolu" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "Kayıtlı aramalarda olmayan ve hedef klasördeki önceden var olan bütün " "dosyalar silinecek." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "MTP ile takılı aygıtlar için, yerel hedef klasöre dışa aktarın sonra " "aygıtınıza tekrar eşitleme ile iletin. Veya birçok dosyayı Android Aygıta " "eşitlerken adb-eşitleme kullan ki bu daha hızlıdır." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Hedef yolu:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Yol Kalıpları" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Kayıtlı kalıpları düzenle…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "Dışa aktarıla dosya adlarının, etiketlerine bağlı olan yapısı" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Kalıbı dışa aktar:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Önizlemeyi durdur" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Durum" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Kaynak Dosya" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Yolu Dışa Aktar" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Dışarı aktarılan kopya yollar tespit edildi! Yukarıdaki dışa aktarılan " "yollar, eşitleme başlamadan önce düzenlenebilir." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Hedef yoldaki mevcut dosyalar silinecektir ('cover.jpg' adlı dosyalar hariç)!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Eşitlemeyi başlat" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Eşitlemeyi durdur" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "Henüz kaydedilmiş aramalar yok, birkaç tane oluştur ve geri dön!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Hedef yolu seç" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "[{filename}] dosyası için dışa aktarma yolu [{old_path}] iken [{new_path}] " "olarak değiştirildi" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "Eşitleme önizlemesi başlatılıyor" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "Eşitleme önizlemesi devam ediyor." #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "Eşitleme önizlemesi tamamlandı" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "Eşitleme önizlemesi durduruluyor" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "Eşitleme önizlemesi durduruldu." #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "Eşitleme önizlemesi tamamlandı." #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "Eşitleme önizlemesi durduruldu" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "Farklı bir eklenti seçildi - önizlemeyi durdur" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Şuna eşitlenecek:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "{count} dosya yazılmaya çalışıldı" msgstr[1] "{count} dosya yazılmaya çalışıldı" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "{count} kopya dosyayı atla" msgstr[1] "{count} kopya dosyayı atla" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "{count} dosyayı sil" msgstr[1] "{count} dosyayı sil" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "Hiçbir hedef yol sağlanmadı" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Lütfen şarkıların dışa aktarılması gereken dizini belirtin." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Hiçbir dışa aktarma kalıbı sağlanmadı" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" "Lütfen dışa aktarılan şarkıların adları için bir dışa aktarma kalıbı " "belirtin." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Dışa aktarma yolu mutlak değil" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Girdiğiniz\n" "<b>{}</b>\n" "kalıbı \"/\" içeriyor ama kökten başlamıyor.\n" "Lütfen / veya ~/ ile başladığından emin olarak tam hedef yolunu sağlayınız." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Hiçbir kayıtlı arama seçili değil" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Lütfen en azından bir kayıtlı arama seçin." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Seçilen kayıtlı aramalarda hiçbir şarkı yok" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Bütün seçilen kayıtlı aramalar boş." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Eşitlenecek {} şarkı bulundu" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Hedef yol ve dışa aktarma kalıbı uyumsuz" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "Dışa aktarma kalıbı hedef yoldan farklı olan bir yolla başlıyor. Lütfen " "kalıbı doğrulayın.\n" "\n" "Hata:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Şarkı eşitlenemedi" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "<b>Durum</b>'a göre sıralarken eşitleme başlatılamaz." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Şarkı eşitlemesi başlatılıyor" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Eşitleme devam ediyor." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Şarkı eşitleme bitirildi" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Şarkı eşitleme durduruluyor" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Eşitleme durduruldu." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Eşitleme bitirildi." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Şarkı eşitleme durduruldu" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "Farklı bir eklenti seçildi - eşitlemeyi durdur" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "\"{}\" kaldırılıyor" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Eşitleme:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "yazılan {count}/{total} dosya" msgstr[1] "yazılan {count}/{total} dosya" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "({count} mevcut dosya atlandı)" msgstr[1] "({count} mevcut dosya atlandı)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "{total} dosyadan {count} kopya dosya atlandı" msgstr[1] "{total} dosyadan {count} kopya dosya atlandı" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "{total} dosyadan {count} tanesi silindi" msgstr[1] "{total} dosyadan {count} tanesi silindi" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "{count} dosya eşitlenemedi" msgstr[1] "{count} dosya eşitlenemedi" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "daha önce eşitlenmiş {count} dosya atlandı" msgstr[1] "daha önce eşitlenmiş {count} dosya atlandı" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Eşitlenen Şarkı Sözleri" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Parça ile aynı (veya benzer) ada sahip .lrc dosyasından eşitlenen şarkı " "sözlerini göster." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Metin:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "Arkaplan:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Yazı Tipi" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Boyut (pks):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telephaty Durum İletileri" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Geçerli şarkıya bağlı durum iletisi olan Telephaty tabanlı bütün IM " "hesaplarını (Empathy vb. deki gibi yapılandırılmış) günceller." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Oynatılıyor:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Şarkı başladığındaki durum metni. QL Kalıplarını kabul eder, örn %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Duraklatıldı:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Şarkı duraklatıldığındaki durum metni. QL Kalıplarını kabul eder, örn %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Mevcut şarkı olmadığındaki durum için düz metin" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Şarkı yok:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Durum Kalıpları" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Tema Değiştirici" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "Etkin GTK+ temasını değiştirir." #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Varsayılan Tema" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Koyu tema sürümünü tercih et" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "Başparmak Puanlaması" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Puan değerine dönüştürülen başparmak yukarı / başparmak aşağı puanlama " "sistemi ekler. Oy toplamlarını tutmak ve <b><tt>~#score</tt></b>'a göre " "sıralamak için kullanışlıdır." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "Menü Çubuğunu Aç/Kapat" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Menü çubuğuna Alt tuşuna basarak geçiş yapın." #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Çalmıyor" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "Durum Çubuğu Simgesi" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Quod Libet'i durum çubuğundan denetler." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "%(application-name)s'i gö_ster" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "_Çal" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "Dur_aklat" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "_Önceki" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "So_nraki" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Karıştır" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "Tek_rarla" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "Bu Ş_arkıdan Sonra Dur" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "Tarayıcı _Aç" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "_Etiketleri Düzenle" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Bilgi" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "Çalma _Listeleri" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Çık" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Davranış" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Fare tekeri hareketi sesi ayarlar" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Fare tekeri hareketi şarkıyı değiştirir" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "Fare _Tekeri Hareketi" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "Araç İpucunu Göster" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "Sözleri Göster" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" "Etiketi veya dosya tabanlı şarkı sözlerini otomatik olarak kenar çubuğunda " "gösterir." #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "%s için \n" "şarkı sözü bulunamadı" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "Etkin şarkı yok" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Görselleştirmeleri Başlat" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Harici görselleştirmeleri başlat." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "'%s' kullanan görselleştirmeler çalıştırılamadı" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "Hata" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "Görselleştirici programı:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Tekrar Yükle" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "Ses Dalgası Kaydırma Çubuğu" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ Geçerli şarkının ses dalgası şeklinde kaydırma çubuğu." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "Önplan rengini yoksay:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "Üzerine gelme rengini yoksay:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "Kalan rengini yoksay:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Geçerli konumu göster" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Zaman etiketlerini göster" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "Kaydırırken ileri/geri sarma miktarı (milisaniye):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Resim Kaydedici" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Geçerli şarkının kapak resmini bir dosyaya kaydeder." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Dosya:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Eşik:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Süzgeç etkinleşinceye kadarki eşik" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "Or_an:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Sıkıştırma oranı" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Ses Sıkıştırıcısı" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Bütün örneklerin genliğini belirlenmiş oranla, belirli bir eşik üzerine " "çıkarır." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Ön ayar:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "Süzgeç ön ayarı" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frekans kesme:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Alçak geçiren süzgeç kesme frekansı" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Besleme _seviyesi:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Besleme seviyesi" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "Varsayılan" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Sanal hoparlör yerleşimine en yakın (30°, 3 metre)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Chu Moy'un (bilindik) çapraz-besleyicisine yakın" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Jan Meier'in CORDA yükselticilerine yakın (ufak değişiklik)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Özel" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "Özel ayarlar" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "Çapraz-besleme" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Kulaklık kullanırken veya erken Stereo kayıtlar için ayar yapmak için sol ve " "sağ kanalı hoparlör kurulumunu simüle edecek şekilde karıştırır." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "Süzgeç _bandı:" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "Süzgecin Frekans bandı" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "Süzgeç _genişliği:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "Süzgecin Frekans genişliği" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Seviye:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Efekt seviyesi" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Ana vokalleri sesten kaldırır." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "Mono Daraltma" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Ses kanallarını tek kanala daraltır." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "Or_an:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Usul:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Perde:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "Ses Perdesi / Hız" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "Ses akışının perdesini denetler." #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "Çalma Listesini Klasöre Aktar" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "Dışa _Aktar" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "Hedef klasör:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "Dosya adı kalıbı:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "Çalma listesini, dosyaları bir klasöre kopyalayarak dışa aktarır." #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "Çalma listesi dışa aktarılamadı" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "Hedefe yazma erişiminiz olduğundan emin olun." #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "Varsayılan dosya adı kalıbı:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Tamam" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "Yeni bir çalma listesi adı yazın\n" "veya üzerine yazılacak varolan bir Sonos çalma listesi seçin" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "Sonos Çalma Listesine Dışa Aktar" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "Parçaları eşleştirerek bir çalma listesini Sonos'a dışa aktarır." #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Sonot aygıt(lar)ı bulma hatası" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Sonos bulma hatası. Lütfen ayarları denetleyin" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "Mevcut Sonos çalma listesi silinemedi %s:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "Çalma listesine aktar %(playlist)r (%(total)d parça)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Squeezebox'a Dışa Aktar" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Bir çalma listesini dinamik olarak Logitech Squeezebox çalma listesine dışa " "aktarır ve böylece her ikisinin bir dizin yapısını paylaşmasını sağlar." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Yapılandırmayı <a href=\"%(plugin_link)s\">Squeezebox Eşitleme eklentisi</a> " "ile paylaşır." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "Çalma listesini Squeezebox'a dışa aktar" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Çalma listesi adı (var olanın üzerine yazılacak)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Squeezebox çalma listesine dışa aktar" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "Çalma Listesi Kopyalarını Kaldır" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Bir çalma listesindeki kopya girdileri kaldırır." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "%d kopya şarkıyı kaldırmak istediğinize emin misiniz?" msgstr[1] "%d tekrarlanan şarkıyı kaldırmak istediğinizden emin misiniz?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Kopya şarkılar '%s' çalma listesinden kaldırılacak." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "Çalma Listesini Karıştır" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Çalma listesini rastgele karıştırır." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "İmleci Takip Et" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Seçiminizi veya listede bulunan sıradaki bir kez çalınmış şarkıyı takip eden " "bir çalma sırası kipi ekler." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "İmleci takip et" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "_İmleci takip et" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Çalma Sayısı Dengeleyici" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Daha az çalınmış şarkıları tercih eden bir karıştırma kipi ekler." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "Daha az çalınanı tercih et" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "Daha az ça_lınanı tercih et" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "Sadece Kuyrukla" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Şarkı çalmayı kuyrukla sınırlar.\n" "\n" "Bu çalma düzenini ana pencerede seçin; bu durumda bir şarkıya çift tıklamak " "onu çalmak yerine kuyruğa ekleyecektir." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "Sadece kuyrukla" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "Sadece _kuyrukla" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Çift tıklanan şarkıları kendiliğinden çalmaya başla" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "Tersine Çevir" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Şarkıların çalma sırasını tersine çeviren bir karıştırma kipi ekler." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "Tersine Çe_vir" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "Gruplamaya göre Karıştır" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Şarkıları ortak bir etiketle gruplayan bir karıştırma kipi ekler - albüm " "karıştırmalarına benzer.\n" "\n" "Bu, çok hareketli klasik parçaları karıştırmak için kullanışlıdır ve bir " "sonraki parçaya karıştırmadan önce tüm hareketlerin sırayla çalındığından " "emin olur." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "Gruplamaya göre karıştır" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "_Gruplamaya göre karıştır" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "Yeni grubu başlatmak için bekliyor…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "Gruplama etiketi:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "Şarkıları gruplayacak etiket" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "Süzgeç etiketi:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Sadece süzgeç etiketi tanımlanmışsa gruplama uygulanır.\n" "Tanımlanmamış bir süzgeç etiketine sahip bir şarkıya, sadece\n" "kendisinden oluşan bir grup olarak davranılacaktır. Tipik olarak\n" "süzgeç etiketi, gruplama etiketiyle eşleşmeli veya kısmen eşleşmelidir." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "Gecikme:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Sonraki grup başlamadan önceki saniye cinsinden zaman gecikmesi" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Varsayılanlara sıfırla" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "Beğenilmeyen Parçaları Atla" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Sırayla çalan bir çalma düzeni (karıştırma) kipi ekler ama verilen eşiğin " "altında (veya eşit) puan verilen parçaları atlar." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "Beğenilmeyen parçaları atla" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "Beğenilmeyen _parçaları atla" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "Her Parçayı Tekrarla" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Parçaları sırayla çalan ama her bir parçayı ayarlı bir sayıda tekrar eden " "bir karıştırma kipi ekler." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "Her parçayı tekrarla" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "H_er parçayı tekrarla" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Her bir parçayı tekrar çalma sayısı:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "Koşullu Sorgu" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Koşul sorgusuna göre eşleşecek sorguyu seçer." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: condition-query, then-query, else-query)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "Eksik Sorgu" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Verilen etiketi olmayan şarkıları eşleştirir." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "Boş etiketleri içer" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python Sorgusu" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Sorgularda Python ifadeleri kullan." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: ifade)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "<tt>s</tt> (veya <tt>a</tt>) değişkeni eşleştirilmiş şarkı / albümdür.\n" "\n" "<tt>_ts</tt> sorgu başlangıcındaki (gerçek sayı) zaman damgasıdır.\n" "\n" "Ayrıca <tt>time</tt> ve <tt>random</tt> modülleri ve <tt>Random</tt> " "(==<tt>random.Random</tt>) sınıfı de mevcuttur." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "Kayıtlı Aramayı İçer" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" "💾 Bir kayıtlı aramanın sonuçlarını diğer bir sorgunun parçası olarak içer." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: ad-ara)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "Benzersiz Sorgu" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Arama sonuçlarını benzersiz etiketlere göre süz." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: tag)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox Tamamdır. Sadece (%s) oynatıcı kullanılıyor." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "%s'e bağlanılamadı" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Ana makine adı:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Bağlantı noktası:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "Kullanıcı adı:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Parola:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "Sunucunun bağlanacağı kitaplık dizini" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "Kitaplık yolu:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "Ayarları _doğrula" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox Sunucusu" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Hata Ayıklama" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "{hostname}:{port} üzerindeki Squeezebox sunucusu" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "tanımlanamayan Squeezebox sunucusu" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "tanımlanamayan Squeezebox oynatıcısı: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Squeezebox oynatıcısı seçin" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Squeezebox sunucusu bulundu.\n" "Lütfen oynatıcıyı seçin" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "Resmi _pencereye sığdır" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Resimler dosya adı dizeleri için '[plugins] cover_filenames' yapılandırma " "girdisine bakın" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "Kaydettikten sonra resmi düz_enle" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "Dosya _adı:" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Kayıt başarısız" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "\"%s\" kaydedilemedi." #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP Hatası: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "Albüm Kapağı İndirici" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "%(source)s den" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "Çözünürlük: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "Boyut: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Motor başına 'en iyi' sonuç sınırı" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "_Ara" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Aranıyor…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Tamamlandı" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "Albüm Resmi İndir" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Albüm kapaklarını çeşitli web sayfalarından indirir." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Kaynaklar" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2'den ID3v2'e" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "APEv2 etiketlerinizi ID3v2 etiketlere dönüştürür. Dönüşümden sonra APEv2 " "etiketlerini siler." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "Yer İmine Git" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Seçilen dosyalardaki yer imlerini yönetir." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "Yer İmlerini Düz_enle…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "Yer İmi Yok" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz Araması" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "MusicBrainz aramasına dayanarak bir albümü tekrar etiketler." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "\"tarih\" etiketi için sadece yıl kullan" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "Gerektiğinde \"_albumartist\" yazın" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "Sanatçı adları için sıralama etiketleri yazın" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "_Standart MusicBrainz etiketlerini yaz" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "\"labelid\" etiketini yazın" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Dosya adı" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Parça" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "Başlık" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "Sanatçı" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz araması" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "_Sorgu:" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "_Ara" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "Sonuçlar <i>(yeniden sıralamak için sürükle)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Lütfen bir sorgu girin." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "Hatayla karşılaşıldı. Lütfen tekrar deneyin." #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Sonuç yükleniyor…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "Sonuç bulunamadı." #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python Uçbirimi" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Etkileşimli Python uçbirimi. Yeni bir pencere açar." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{songs} ({app}) için {plugin_name}" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python Uçbirimi Kenar Çubuğu" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Etkileşimli Python uçbirimi kenar çubuğu; ana penceredeki seçilen şarkıları " "takip eder." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "Aşağıdaki nesnelere varsayılan olarak erişebilirsiniz:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Şu anki çalışma dizininiz şudur:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "Tamamlama" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "Kapak Resmi İndir" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" "Quod Libet kapak eklentilerini kullanarak yüksek kaliteli albüm kapakları " "indir." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "Klasik" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "Büyük" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Tam HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "Kapak Resmi İndirme" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "%(source)s - %(dimensions)s yükleniyor…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "Albümler için hiçbir şey bulunamadı:\n" "<i>%(albums)s</i>.\n" "\n" "Kullanılan sağlayıcılar:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "Kapak bulunamadı" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "Önizleme boyutu" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "Hedefi kaydet" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" "Eğer halen bir JPEG değilse, resmi aynı boyutta yüksek kalite bir JPEG'e " "dönüştür" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "JPEG olarak kaydet" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "Komut" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "ad" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Bu komutun adı" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "komut" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "Çalıştırılacak kabuk komutu söz dizimi" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "değişken" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "Ayarlanmışsa, komuttaki oluşumları kullanıcı tarafından sağlanan bir değerle " "değiştirilecek olan parametre. Örn. 'PARAM' kullanarak, komutunuzdaki tüm " "'{PARAM}' örnekleri çalıştırıldığında istenen değere sahip olur" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "Komut için değer hesaplayacak QL kalıbı, örn. <~filename>. Çalma listeleri " "için ayrıca <~playlistname> ve <~#playlistindex> sanal etiketleri " "desteklenir." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "tek" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Ayarlanırsa, kalıbın yinelenen hesaplanmış değerlerini kaldırır" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "maks dğşk" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "Tek seferde komuta aktarılacak azami argüman sayısı (xargs gibi)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "tersine çevir" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "Ayarlanırsa değişken listesi tersine çevrilecek" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "Girdi değeri" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "%s değeri mi?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "Özel Komutlar" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Etiketlerinden herhangi birini kullanarak şarkılar üzerinde özel komutlar " "(gerekirse toplu olarak) çalıştırır." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Özel Komutları Düzenle" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "%s özel komutu çalıştırılamıyor" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d yinelenen grup" msgstr[1] "%d yinelenen grup" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Hepsini Daralt / Genişlet" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Yinelenen anahtar ifade '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "Kopya Tarayıcısı" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "Şarkıların benzer şekilde etiketlenen sürümlerini bulur ve görüntüler." #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "<tt>~artist~title</tt> veya <tt>musicbrainz_track_id</tt> gibi QL etiketi " "ifadelerini kabul eder" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "_Yinelenenleri şuna göre gruplandır:" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "Yinelenen Anahtar" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "_Beyaz Boşlukları Kaldır" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "_Aksanları Kaldır" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "_Noktalama İşaretlerini Kaldır" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "Büyük/Küçük Harf _Duyarsız" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "Eşleme seçenekleri" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "Çalma Sayısını Düzenle" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Bir şarkının <tt>~#playcount</tt> ve <tt>~#skipcount</tt>'unu düzenleyin.\n" "\n" "Birden fazla şarkı seçildiğinde, sayılar ayarlanmak yerine artırılacaktır.\n" "\n" "Bir şarkının <tt>~#playcount</tt> değerini 0 olarak ayarlarken, " "<tt>~#lastplayed</tt> ve <tt>~#laststarted</tt> girdileri temizlenir. Ayrıca " "hiç çalınmamış bir şarkıyı pozitif çalma sayısına ayarlarken, hiçbir çalma " "süresi oluşturulmaz." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "Çalma Sayısı" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "Atlama Sayısı" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "Birden fazla dosya seçildi." #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "Sayılar artırılacaktır." #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Gömülü Resimleri Düzenle" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Gömülü resimleri ekler, kaldırır veya değiştirir." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "_Göm" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "%d parçaya gömmek için resim seçin" msgstr[1] "%d parçaya gömmek için resim seçin" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "_Bütün Resimleri Kaldır" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "G_eçerli Resmi Göm" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "_Resim Seç…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "Kesin Derecelendirmeyi Ayarla" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Şarkıların derecelendirmesini sayıyla ayarlamasına izin verir." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Lütfen istediğiniz puanı 0.0 ile 1.0 arasında verin" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "Herhangi Bir Etikette Süz" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Seçilen şarkıların etiketlerine göre arama sorgusu oluşturur." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "Dizinde Süz" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Yeni tarayıcı penceresinde dizinde filtreler." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Akustik Parmak İzi Arama" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Akustik parmak izi yoluyla şarkı üstverilerini arar." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "Akustik Parmak İzlerini Gönder" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Chromaprint kullanarak akustik parmak izleri oluşturur ve bunları acoustid." "org'a gönderir." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API Anahtarı Eksik" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Parmak izi gönderebilmeniz için eklenti tercihlerinde acoustid.org API " "anahtarı belirtmeniz gerekir." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "API anahtarı iste" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _anahtarı:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID Web Hizmeti" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "Kuyruğa Eklendi" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "Çözümleniyor" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Ara" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Yaz" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Yayımlama" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "MusicBrainz etiketlerini yaz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "Dizine göre grupla" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "Albüm Kipi" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Albümle ilgili etiketler yazın ve farklı albüm yayınlarının sayısını " "azaltmaya çalışın" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Parmak izi oluşturma:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Ayrıntılar" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Gönder" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Şarkıların gönderilebilmesi için <i><b>musicbrainz_trackid</b></i> ya da " "<i><b>sanatçı</b></i> / <i><b>başlık</b></i> / <i><b>albüm</b></i> " "etiketlerine ihtiyaç vardır." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Parmak İzleri:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "MBID'li Şarkılar:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "Yeterli etikete sahip şarkılar:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "Gönderilecek şarkılar:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Tamamlandı. %(to-send)d/%(all)d şarkı gönderilecek." #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "Parmak izi gönderiliyor:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "Gönderiliyor…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "Dosyalardaki Etiketleri Güncelle" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Dosyalardaki değiştirilen etiketleri güncelle. Bu, çalma sayıları ve " "puanların güncellenmesini sağlar." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "HTML'ye aktar" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Seçilen şarkı listesini HTML dosyasına aktarır." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "iFP'ye Gönder" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Şarkıları bir iRiver iFP aygıtına yükler." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "iFP aygıtı bulunamadı" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "iFP aygıtıyla bağlantı kurulamıyor. Aygıtın açık ve takılı olduğunu ve ifp-" "line (http://ifp-driver.sf.net) yüklü olduğunu denetleyin." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "%(current)d/%(total)d yükleniyor" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "%s yüklenemiyor. Aygıtta yer kalmamış veya kapalı olabilir." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Yüklenme hatası" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "Kullanıcı Verisini Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "Etiketleri Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "Etiketleri ve Kullanıcı Verisini Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "Dosya Gövdelerini ve Kullanıcı Verilerini Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "Dosya Gövdelerini ve Etiketleri Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "Dosya Gövdelerini, Etiketleri ve Kullanıcı Verilerini Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "İçe / Dışa Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Etiketler ve parça kullanıcı verisini içe ve dışa aktarır." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "İlave bilgiler" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "Burada kullanılan 'parça kullanıcı verisi' ifadesi, seçilen şarkıların " "bulunduğu çalma listelerini ve aşağıdaki üstverileri içerir:\n" "\n" "%s\n" "\n" "Dışa aktarmak için her ne seçtiyseniz içe aktarılacağını unutmayın. Eğer " "dosya köklerini (uzantısız dosya adlarını) dışa aktardıysanız, o halde, içe " "aktarmada, seçilen dosyalar yeniden adlandırılacak.\n" "\n" "Bir albümü dışa aktarmadan sonra veriyi albümün başka bir sürümüne içe " "aktarabilirsiniz. Parçaların sıralaması ve sayısı farklı olabilir. Eklenti, " "dışa aktarılan veriyi yeni parçalarla eşleştirir; parçaların adları çok az " "farklı olsa bile. Otomatik eşleştirme her zaman doğru olmaz, yani aşağıdaki " "benzerlik değerlerini çok fazla azaltmamak daha iyidir." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "İçe aktarmada kullanıcı etkileşimi" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Parça sayısı farklıysa onay iste" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Albüm sayısı farklıysa onay gerektir" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Kullanıcının hangi parçanın hangisiyle eşleştiğini elle denetlemesi ve " "isteğe bağlı olarak değiştirmesi gereken yüzde." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "Parça benzerliği:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "Albüm benzerliği:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "Dosyaları dışa aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Güzel ve net JSON yaz (daha yavaş)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Dışa aktarılan dosyaları içe aktardıktan sonra sil" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "İçe Aktar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "Dışa Aktarma Dizinini Aç" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "Diskler" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "Parçalar" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "Sanatçı(lar)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "Yolun sonu" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "Albümleri Eşle" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "Devam et" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "İçe aktaracak hiçbir şey yok" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "Bir şeyi içe aktarabilmeniz için önce dışa aktarmanız gerekir." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "Dizin bozuk." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "%s içinde JSON ayrıştırılamadı" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "%s okunamadı" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "Dosya adı" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "Parçaları Eşleştir" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Grafik listesi güncelleniyor." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Zaten güncel." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "%s haftası için grafik getiriliyor." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Eşitleme tamam." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "Eşitleme sırasında hata (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm Eşitleme" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Kitaplık istatistiklerinizi Last.fm profilinizden günceller." #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "K_ullanıcı adı:" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Sıralama Etiketleri Oluştur" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Albüm ve sanatçı adlarını kısa adlara dönüştür, kabaca." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "M3U / PLS Çalma Listesi Olarak Dışa Aktar" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Şarkıları bir M3U veya PLS çalma listesine aktarır." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "Bağıl yolları kullan" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "Tam yolları kullan" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "%s adresine yazma işlemi başarısız oldu." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "Şarkıları Yeniden Tara" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Dosya değişikliklerini denetler ve gerekirse şarkıları yeniden yükler / " "kaldırır." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "Şarkıları yeniden tara" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "ReplayGain Çözümleyici" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "Parça" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "Süreç" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "Kazanç" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "Tepe Noktası" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" "Güncellenecek <b>%(to-process)s</b> albüm var (toplama oranı %(all)s)" msgstr[1] "" "Güncellenecek <b>%(to-process)s</b> albüm var (toplama oranı %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "<a href=\"%(rg_link)s\">Tekrarlama Kazancı</a> bilgisini GStreamer " "kullanarak çözümler ve günceller. Sonuçlar albüme göre gruplanır." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "her zaman" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "eğer <b>herhangi bir</b> RG etiketi eksikse" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "eğer <b>albüm</b> RG etiketleri eksikse" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "Al_bümleri işle:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "Varolan Etiketler" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "Etiketleri Ayır" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "Disk numarasını albümden ve sürümü başlıktan aynı zamanda ayırır." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "Albümü Ayır" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Disk numarasını ayır." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "yok" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "Sıfırla" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "Tık" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "BPM'ye tıklayın" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Seçilen şarkı için BPM'a tıklayın." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "Web Sitesi Ara" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Herhangi bir şarkı etiketini kullanarak seçtiğiniz web sitesini arar.\n" "Kalıpları destekler, örneğin %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "URL kalıplarını ara" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "URL aramayı düzenle" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "Aramaları Yapılandır…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "Etiketi Wikipedia'da Ara" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Seçilen şarkıya uygun olan etikette Wikipedia makalesi ile bir tarayıcı " "penceresi açar." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "%(website)s üzerinde ara" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Etiketleri Düzenle" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "Arama başarısız" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "\"%s\" etiketi bulunamadı." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Kitaplık" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Bağlama yerleri denetleniyor" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Kitaplık taranıyor" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "%s taranıyor" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "Dosyalar yükleniyor" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "Kitaplık dosyaları taşınıyor" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "Kitaplık dosyaları kaldırılıyor" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "%s için saatler ekleniyor" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" "Eski çalma listesi %(filename)r içinde ( %(size).1f kB boyutunda) kitaplık " "şarkısı bulunamadı." #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" "Kütüphane kök dizinini/dizinlerini değiştirdiniz ama bu çalma listesini " "değiştirmediniz mi?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d çalma listesi dönüştürülemedi" msgstr[1] "%d çalma listesi dönüştürülemedi" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "Müzik çalar ve müzik kitaplığı yönetici" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "Bu dosya yüklenemedi: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Etiketleri sırala" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "Ekrana zarif çıktı yazdır" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Zarif kipte görüntülenecek ve sıralanacak sütunlar (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "Programatik etiketleri de listele" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "Yeterli olmayan değişken" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "Çok fazla argüman" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "Açıklama" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Değer" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Bütün genel etiketleri sırala" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Etiketleri bir dosyadan diğerine kopyala" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "Değişiklikleri göster, uygulama" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "Yazılamayan etiketleri atla" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "{tagname} etiketi bu dosyaya kopyalanamıyor: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "Etiketleri, etiket düzenleyicide düzenle" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "Düzenleme iptal edildi" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "'%(editor-name)s' metin düzenleyiciyi başlatma başarısız." #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "Değişiklik saptanmadı" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "Bir etiket ayarla ve mevcut değerleri kaldır" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "\"%(file)r\" %(format)s dosyası için %(tag)r ayarlanamıyor" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Etiketleri kaldır" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Değer bir düzenli ifade" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Bütün etiketleri kaldır" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "'--all' soneki '--regexp' ile birleştirilemez" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "{filename} dosyasından {tagname} etiketi kaldırılamıyor" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "Etiket değerini kaldır" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "Etiket değeri ekle" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "%r ayarlanamıyor" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "Dosya bilgilerini listele" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Sağlanan resmi öncelikli gömülü resim olarak ayarla ve diğer bütün gömülü " "resimleri kaldır" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "Bu resim dosyası yüklenemedi: %r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "%(file_format)s dosyası %(file_name)s için resim düzenleme desteklenmiyor" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "Bütün gömülü resimleri kaldır" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Gömülü resimleri %(filepath)s adresine çıkart" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "Resimlerin kaydedileceği yol (varsayılan olarak çalışma dizini)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "Dosyaları etiketlere bağlı olarak yeniden adlandır" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "Etiketleri dosya yoluna bağlı olarak doldur" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Dosya" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "Bütün dosyalar için parça numaralarını doldur" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Etiketleri verilen kalıba bağlı olarak ekrana yazdır" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "Yardım bilgilerini göster" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' geçerli bir sütun adı değil (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "_Bilinmeyen" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "Sırayla" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_Sırayla" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Rastgele" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Rastgele" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "Yüksek puanlıyı tercih et" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "_Yüksek puanlıyı tercih et" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "Bu parçayı tekrarla" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "Bu parçayı _tekrarla" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "Hepsini tekrarla" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "Hepsini _tekrarla" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "Bir şarkı" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "Bir _şarkı" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Akış" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Ara Belleğe Alınıyor" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "GStreamer iletişim hattı oluşturulamadı (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "Ortam biçimini işleyecek GStreamer unsuru bulunamadı" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Ortam biçimi: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer eklentisi '%(name)s' başlatılamadı" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "Çalma için kullanılan GStreamer çıktı iletişim hattı. Varsayılan iletişim " "hattı için boş bırakın. İletişim hattının bir alış noktası içermesi halinde, " "bu hat varsayılanın yerine kullanılacaktır." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Çıkış iletişim hattı:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f sn" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "Ara _belleğe alma süresi:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "Aralıksız _çalmayı devre dışı bırak" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Aralıksız çalmayı devre dışı bırakmak, bazı GStreamer sürümleri ile olan " "parça değiştirme sorunlarını önleyebilir" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "Eğer uygunsa çalma için JACK kullan" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Tespit edilebilirse playbin havuzu için `jackaudiosink` kullanır" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "JACK çıkış aygıtlarına otomatik bağlan" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "`jackaudiosink` e otomatik bağlanmasını söyler" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "GStreamer ses alış noktası bulunamadı. Bu denendi: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Geçersiz GStreamer çıkış iletişim hattı" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "Ses çıkışı yaratılamadı" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Ses aygıtı %r bulunamadı. ~/.quodlibet/config dosyasındaki Xine ayarlarınızı " "kontrol edin." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "'{module}' modülü bulunamadı. Acaba paket yüklemeniz gerekiyor olabilir mi?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "GStreamer elemanı '{element}' bulunamadı." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "ListenBrainz'i ayarlamak için lütfen Eklentiler penceresini ziyaret edin. O " "zamana kadar dinlemeler gönderilmeyecek." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Çok fazla ardışık gönderim hatası (%d). Çevrimdışı kipe ayarlanıyor. " "ListenBrainz'i sıfırlamak için lütfen Eklentiler penceresini ziyaret edin. O " "zamana kadar dinlemeler gönderilmeyecek." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz Gönderimi" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Dinlemeleri ListenBrainz'e gönderin." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "Kullanıcı _belirteci:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "Etike_tler:" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "Gönderimde içerilecek etiketlerin listesi. Virgülle ayrılmış, gerekirse çift " "tırnak işareti kullanın." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "Bu süzgeçle eşleşen şarkılar gönderilmeyecek." #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "\"%(name)s\" eklentisi %(count)s çalma listesinde çalışsın mı?" msgstr[1] "\"%(name)s\" eklentisi %(count)s çalma listesinde çalışsın mı?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "_Eklenti Çalıştır" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Kullanım" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Baş" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Yok" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Süre" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Yer İmi Adı" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "DD:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Yer İmleri" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Süzgeçler" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "Son _Çalınan" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Son _Eklenen" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Top 40" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "Bütün _Şarkılar" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "_Geçerli Tür(ler)de" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "Geçerli _Sanatçı(lar)da" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "Geçerli Al_bümde" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Rastgele Müzik _Türü" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Rastgele _Sanatçı" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "_Rastgele Albüm" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "En çok çaldığınız 40 şarkı (eşitlik varsa 40'tan fazla olabilir)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Ad:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Değer:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Kayıtlı Değerler" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "Kayıtlı değerleri düzenle…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "Oto_matik" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "_Parça Kipi" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "_Albüm Kipi" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "_Sustur" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "_Replay Gain Kipi" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "Yeni %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(bilinmeyen)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "_Ekle…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "_Düzenle" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "Etiket ifadesi" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Etiket ifadeleri, örn people:real ya da ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "Yeni etiket girin" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "Etiket ifadesini düzenle" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "Dosyalar:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Seçilen şarkılar kitaplıktan kaldırılacak ve dosyaları diskten silinecek." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Seçilen dosyalar diskten silinecek." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "%(file_count)d dosya kalıcı olarak silinsin mi?" msgstr[1] "%(file_count)d dosya kalıcı olarak silinsin mi?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "_Dosyaları Sil" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "Seçilen şakılar kitaplıktan kaldırılacak ve dosyaları çöpe taşınacak." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Seçilen dosyalar çöpe taşınacak." #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "%(file_count)d dosya çöpe taşınsın mı?" msgstr[1] "%(file_count)d dosya çöpe taşınsın mı?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Çöpe Taşı" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "%(current)d/%(total)d Taşınıyor." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "Çöpe taşınamadı" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "Bir veya daha fazla dosya çöpe taşınamadı." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "%(current)d/%(total)d siliniyor." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "Dosyalar silinemedi" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Bir veya daha fazla dosya silinemedi." #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "Tarayıcı" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "Dosyalar indiriliyor" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "%d şarkıda eksik" msgstr[1] "%d şarkıda eksik" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d şarkıda farklı" msgstr[1] "%d şarkıda farklı" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "Birden fazla değelere _böl" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Diski _Albümden ayır" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "_Sürümü addan ayır" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Aranjörü _Sanatçıdan ayır" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "_Seslendireni Sanatçıdan ayır" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "_Seslendireni Başlıktan ayır" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "_Originalartist'i başlıktan ayır" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Etiket ekle" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Etiket:" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "_Programatik etiketleri göster" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Makine tarafından oluşturulanlar da dahil olmak üzere tüm etiketlere eriş, " "ör. MusicBrainz veya Replay Gain etiketleri" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "_Çok satırlı etiketleri göster" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" "Olası çok satırlı etiketleri (örneğin 'şarkı sözleri') burada da göster" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "_Geri Al" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Kaydet" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "_Yapılandır" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "_Etiketi Ayır" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "Dğer(ler)i _Kopyala" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Etiket eklenemedi" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "%s eklenemedi" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "Seçilen dosyalar %s için çoklu değeri desteklemiyor." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Geçersiz etiket" msgstr[1] "Geçersiz etiketler" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "%s etiketi geçersiz\n" "\n" "Seçili dosyalar bu etiketi değiştirmeyi desteklemiyor." msgstr[1] "" "%s etiketleri geçersiz\n" "\n" "Seçili dosyalar bu etiketleri değiştirmeyi desteklemiyor." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Geçersiz değer" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Geçersiz değer: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Etiket doğru olmayabilir" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s program çalışıyorken değişti. Kitaplığı yenilemeden kaydetmek " "arada yapılan değişiklikleri yokedebilir." #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Şarkı kaydedilemedi" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "%(file-name)s kaydedilemedi. Dosya salt okunur olabilir, bozuk olabilir veya " "sizin dosyayı değiştirme izniniz olmayabilir." #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "_Daha çok seçenek…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Geri al" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Yinele" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "H_akkında" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "Gün_cellemeleri Denetle…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Eklentiler" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s ve %(count)s tane daha" msgstr[1] "%(title)s ve %(count)s tane daha" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso Ayarları" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Klasörler" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "Ye_ni Klasör…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "_Bütün Alt Klasörleri Seç" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Yeni Klasör" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Yeni klasör için ad girin:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Klasör oluşturulamadı" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Klasör silinemedi" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Şarkılar" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "%s eseri" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Parça %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "Geçerli _Şarkı" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "Görünümü Düz_enle…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Seçili şarkı yok." #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Şarkı Yok" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Bilgi" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Şarkı Sözleri" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Yapımcı %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "sanatçı" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "sanatçılar" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "seslendirenler" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Hiçbir Zaman" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d defa" msgstr[1] "%(n)d defa" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "eklendi" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "en son çalındı" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "defa çalındı" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "defa geçildi" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "puan" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "yol" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "uzunluk" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "biçim" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "çözücü" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "kodlama" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bit oranı" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "dosya boyutu" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "değiştirildi" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "İlave" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d tane seçili" msgstr[1] "%d tane seçili" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Parça yok" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d tane albümsüz şarkı" msgstr[1] "%d tane albümsüz şarkı" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Seçili Diskografi" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d sanatçısız şarkı" msgstr[1] "%d sanatçısız şarkı" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "albümler" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Toplam uzunluk:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Toplam boyut:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Dosyalar" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "_Çevrimiçi görüntüle" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Bu şarkının sözleri bulunamadı." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "Bütün şarkıları kaldırmak istediğinize emin misiniz?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "Seçilen şarkılar kitaplıktan kaldırılacak." #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "Açığa Çıkar" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "_Açığa Çıkar" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "Sol taraftaki sütunların sağ taraftaki sütunlarla yaklaşık olarak eşleşip " "eşleşmediğini denetler. Değilse, burada sıralamayı değiştirebilirsiniz " "(eşleştirilmemesi gereken satırlar için _ kullanın):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "Sağ taraf sırası:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Etiket değişikliklerini gözardı et?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Etiketler değiştirildi ama kaydedilmedi. Dosyaları kaydetmek mi yoksa " "değişiklikleri gözardı etmek mi istersiniz?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Geri Al" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Dosya zaten var" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "%(file-name)s değiştirilsin mi?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "_Dosya Değiştir" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "Görevleri etkinleştir" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d görev çalışıyor" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "Karıştırma kipini aç/kapat" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "Tekrarlama kipini aç/kapat" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "Olaylar" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "Çalma Sırası" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "Düzenleme" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "Yeniden adlandırma" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "Sorgulanıyor" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "Kapak Resimleri" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Eklenti Hataları" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "Herhangi durum" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "Etkinleştirildi" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "Devre dışı" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "Kategori yok" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "Herhangi kategori" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Eklenti bulunamadı." #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "Eklentiler" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "Eklenti durumuna / etiketine göre süz" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "Eklenti türüne göre süz" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "Eklenti adı veya tanımına göre süz" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "_Hataları Göster" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Parça" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "Gru_plama" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Sanatçı" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Albüm" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "_Dosya adı" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Uzunluk" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "Çalan şarkıya otomatik olarak _atla" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "Çalan şarkı değişince listede yeni şarkıya git" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "_Etiketler değiştirildiğinde şarkıları sırala" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" "Etiketler değiştirildiğinde şarkıları şarkı listesinde otomatik tekrar sırala" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "Her zaman sıralamaya izin ver" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "Oyun listeleri için bile, sütun başlıklarına göre sıralamaya izin ver" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Diğerleri:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "Düz_enle…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "İlave sütun başlıklarını ekle veya kaldır" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Görünen Sütunlar" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Başlık _sürümleri içersin" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "Albüm _disk altyazısını içersin" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "_Sanatçı tüm kişileri içerir" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Dosya adı _klasörleri içersin" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "Sütun Tercihleri" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "_Sütunları Güncelle" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Yeni sütunları sona ekleyerek geçerli yapılandırmayı şarkı listesine uygula" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Şarkı Listesi" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "Sütunları Düzenle" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "Toplam süre" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Evrensel süzgeç:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "Diğerlerine ek olarak bu sorguyu uygula" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "Ara" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Tarayıcılar" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "Çoklu puanla_maları doğrula" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Çoklu şarkıların puanlamalarını tek seferde değiştirmeden önce doğrulama iste" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "Tek tıkla p_uanlamaları etkinleştir" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Şarkı listesindeki puanlama sütununa tıklayarak puanlamayı etkinleştir" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "Puanlar" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "Gömülü r_esim tercih et" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Sese gömülü resimleri (mümkün olduğunda) diğer kaynaklara göre kullanmayı seç" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "Kullanılabilir olduğunda kullanılacak albüm kapağı resmi dosya(lar)ı (özel " "sembolleri destekler). Birden fazla temin etmek isterseniz virgül ile " "ayırınız." #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "_Tercih edilen sabit görüntü dosya ad(lar)ı" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "Albüm Kapağı" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "Çalma" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "Çıktı Yapılandırması" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Bir şarkı için Replay Gain bilgisi yoksa, ses seviyesini bu değere göre " "ölçekle" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Geri dönüş kazancı:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Sonuç kırpılmadığı sürece, bütün şarkıların ses seviyesini bu değere göre " "ölçekle" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Ön amfi kazancı:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "_Replay Gain ses düzeltmesini etkinleştir" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain Ses Düzeltmesi" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "_Başlangıçta çalmaya devam et" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Müzik çıkışta çalıyorsa, otomatik olarak sonraki başlangıçta çalınmaya başlar" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "_Varsayılan puanlama:" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "_Puan ölçeği:" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Birleştirilmiş puanlamalar için Bayesian Ortalama faktörü (C).\n" "0, geleneksel bir ortalama anlamına gelir, daha yüksek değerler, birkaç " "parça içeren albümlerin daha az aşırı puanlamaya sahip olacağı anlamına " "gelir. Bu değeri değiştirmek, tüm albümler için yeniden hesaplamayı tetikler." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayes ortalama miktarı:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_E-posta:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Puan ve çalma sayıları bu posta adresi için etiketlerde kaydedilecek" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "_Etiket değişikliklerini otomatik kaydet" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Çoklu dosya düzenlerken değişiklikleri doğrulamadan etiketlere kaydet" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" "Etiket düzenleyicide etiket değerleri bölündüğünde kullanılacak ayırıcı " "takımı. Liste, boşlukla ayılmıştır." #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "Etiketi _şuna göre ayır:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "Etiket düzenleyicide etiketlerden alt etiketleri çıkarırken kullanılacak " "ayırıcı takımı. Liste, boşlukla ayrılmıştır ve her bir girdi sadece iki " "karakter içermelidir." #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "Alt etiketleri şuna göre _ayır:" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "Etiketler" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Etiket Düzenleme" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "Yeni puanlar için güncelleniyor" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "Kitaplığı _Tara" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Kitaplığınızdaki değişiklikleri denetle" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "Kitaplığı _Yeniden Derle" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "Kitaplığınızdaki tüm şarkıları yeniden yükle. Bu uzun sürebilir." #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "Gizli Şarkılar" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "Başlangıçta kitaplığı _tara" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "_Dizinleri değişiklikler için izle" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" "Harici dosya eklemeleri, silmeleri ve yeniden adlandırmaları için kitaplık " "dizinlerini izle." #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "Dizinleri Tara" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s ve %(count)d tane daha" msgstr[1] "%(title)s ve %(count)d tane daha" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Özellikler" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Kuyruk" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "Kuyruğu Temizle" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "Kuyruğu devre dışı bırak - çalma sırasında kuyruk yoksayılacak" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "Geçici" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "Şarkıları, çaldıktan sonra kuyruktan kaldır" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "Sürekli" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "Şarkıları, çalındıktan sonra kuyrukta tut" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "Kip" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "Bitişte Durdur" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d şarkı (%(time)s)" msgstr[1] "%(count)d şarkı (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "Kitaplığı _Gez" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "Kuyruk görünürlüğünü aç/kapat" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "Çalma Hatası" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "Kitaplık dizinleri ayarlansın mı?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Kurulu bir müzik kitaplığınız yok. Şimdi kurmak ister misiniz?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "_Şimdi Değil" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "_Kur" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Şarkılar eklenemedi" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s desteklenmeyen iletişim kuralı kullanıyor." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "Çalan Şarkıya _Atla" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "_Dosya" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "_Şarkı" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Görünüm" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "_Gözat" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Denetle" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Yardım" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "Klasör _Ekle…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "Dosya _Ekle…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "_Konum Ekle…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "Yer İmlerini Düzenle…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "Durdur" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "Bu Şarkıdan Sonra Dur" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "_Klavye Kısayolları" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "Çevrimiçi Yardım" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "Yardım Ara" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Konum Ekle" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Ses dosyasının konumunu gir:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Konum eklenemedi" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s geçerli bir konum değil." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Müzik Ekle" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "Klasörler _Ekle" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "Müzik Dosyaları" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "Dosyalar _Ekle" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "%d şarkıyı kuyruğa almak istediğinizden emin misiniz?" msgstr[1] "%d şarkıyı kuyruğa almak istediğinizden emin misiniz?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "_Kuyrukla" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Bütün %d şarkılarının puanlamasını değiştirmek istediğinize emin misiniz?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "Kayıtlı puanlamalar kaldırılacak" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "Puanı Kaldı_r" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "Seçilen şarkıların puanları %s olarak değiştirilecek" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "_Puanı Değiştir" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Boşlukları _altçizgi ile değiştir" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "Noktalı virgül veya virgül ile ayırmayı tire ile değiştir" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "örn. \"iv: allegro.flac\" → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "_Windows'la uyumsuz karakterleri çıkart" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "_Düzeltme işaretlerini çıkart" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "_ASCII olmayan karakterleri çıkart" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "Sadece küçük harf_li karakterler kullan" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Dosyaları Yeniden Adlandır" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Önizle" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "Dosya adları" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "_Albüm kapağını taşı" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Resim arama dizeleri için '[albüm resmi] dosya adları' yapılandırma " "girdisine bak" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "_Hedefteki albüm resmi üzerine yaz" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "Boş dizinleri _kaldır" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "Albüm kapağı" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Yeni Ad" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Dosya yeniden adlandırılamadı" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "%(old-name)s dosyası %(new-name)s olarak yeniden adlandırılamadı. Yeni adla " "zaten bir dosya olabilir veya yeni bir dosya oluşturmak veya eskisini " "kaldırmak için izniniz olmayabilir." #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "Tüm _Hataları Yoksay" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Durdur" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Devam Et" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Yol mutlak değil" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Girdiğiniz %s kalıbı / karakteri içermekle beraber kök klasörden " "başlamıyor. \n" "Hatalı adlandırılmış klasörlerden sakınmak için kalıbınıza\n" "/ veya ~/ şeklinde bir kök verin." #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Listelenen klasörlerdeki şarkılar, kitaplık yenileme sırasında kitaplığa " "eklenecek" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "Yeni dizin eklendikten sonra taranacak" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "Seçilen dizinlerdeki bütün şarkılar da kitaplıktan kaldırılacak" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "_Taşı" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Bir tarama kökünü (dosyalar hariç) taşı. İçeren tüm parçalar için üst " "verileri de taşır." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "{dir!r} ve içindeki bütün parçalar kaldırılsın mı?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "{n} kitaplık yolu ve içerdikleri parçalar kaldırılsın mı?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Kitaplık yolu kaldırılsın mı?" msgstr[1] "Kitaplık yolları kaldırılsın mı?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "Kaldır" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Dizinleri Seç" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "Bu Dizini Seç" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "{dir!r} için Güncel/Yeni Dizin Seç" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "Bu işlem QL üstverisini taşıyacak:\n" "\n" "{old!r} → {new!r}\n" "\n" "Ses dosyalarının kendisi bu yolla taşınmaz.2\n" "Yine de bir yedek almanız tavsiye edilir (Quod Libet 'şarkılar' dosyasını " "içeren)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "Tarama kökü{dir!r} taşınsın mı?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "Tamam, taşı!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "Kayıtlı Aramalar" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "Kayıtlı aramaları düzenle…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "İstediğiniz metni veya QL sorgularını kullanarak kitaplığınızı arayın" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "Yazdık_tan sonra ara" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Arama sonuçlarını, kullanıcı yazmayı bitirdikten sonra göster" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Sınır:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "_Ağırlık" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "Sorgu ekle" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Birlikte &düzenlenecek QL sorgusu veya serbest metin ekle" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Kalan süreyi göster" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "Ana Pencere" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "10 saniye geri kaydır" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "10 saniye ileri sar" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "Arama ögesine odaklan" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "Süzgeçleri sıfırla ve çalan şarkıya atla" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "Seçilen şarkılar için bilgi penceresini aç" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "Seçilen şarkılar için etiket düzenleyiciyi aç" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "Seçilen şarkıları kuyruğa ekle" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "Seçilen şarkıları sil" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "Satır içi arama girdisini göster" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "Sütun başlığına sol tıkla" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "Sütunu, sıralanacak sütunlar listesine ekle" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "Ağaç Görünümü" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "Ögeyi daraltır veya üst ögeyi seçer" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "Elemanı genişletir" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "Metin Girişleri" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "Son değişikliği geri al" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "Geri alınan son değişikliği yinele" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "Bütün panolardaki bütün şarkıları seç" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Süzme türü: %s" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "Bütün _Başlıklar" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Parça Başlıkları" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Albüm Etiketleri" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Kişi Etiketleri" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Tarih Etiketleri" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Dosya Başlıkları" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Yapımcı Etiketleri" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "_Başlıkları Özelleştir…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "_Sütunu Genişlet" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "\"%(title)s\" parçası kitaplıktan kaldırılsın mı?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "%(count)d parça kitaplıktan kaldırılsın mı?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "Kitaplıktan Kaldır" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "\"%(name)s\" eklentisi %(count)d şarkıda çalışsın mı?" msgstr[1] "%(count)d şarkıda \"%(name)s\" eklentisi çalışsın mı?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "\"%(name)s\" eklentisi %(count)d albümde çalışsın mı?" msgstr[1] "%(count)d albümde \"%(name)s\" eklentisi çalışsın mı?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "Eklentileri yapılandır…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "_Kuyruğa Ekle" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "Kitaplıktan Kaldı_r…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "Dosyalar gösterilemedi" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "Dosyaları gösterme hatası veya dosyaları gösterecek uygun program yok." #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "Do_sya Yöneticisi'nde Göster" msgstr[1] "%(total)d Dosyayı Do_sya Yöneticisinde Göster" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "Dosyayı _indir…" msgstr[1] "%(total)d dosyayı _indir…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "başarılı" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "başarısız" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "İndirmeler tamamlandı" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "{name!r} dosyasını şuraya indir" msgstr[1] "{total} dosyayı şuraya indir" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "Buraya indir" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "_Altçizgileri boşlukla değiştir" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Başlık düzeni etiketler" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Birden fazla değere _ayır" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Dosya Yolundan Etiket" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Yeni etiketler eskilerin yerine geçsin" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Yeni etiketler eskilerine eklensin" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Girdiğiniz <b>%s</b> kalıbı geçersiz. \n" "Aynı etiketi iki defa içeriyor olabilir\n" "veya parantezleri hatalı olabilir (< / >)." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Girdiğiniz kalıp geçersiz. \\< ve \\> yerine < ve > kullanmaya " "ve parantez sayılarına dikkat edin.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Görünümü Düzenle" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Parça Numaraları" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "_Başlangıç:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Toplam parça:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Çal/Duraklat" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "Önceki" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "ve %d tane daha…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Değişiklik yapılan dosyalar kaydediliyor." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d şarkı kaydedildi.\n" "(%(remaining)s kaldı)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(all)s te %(current)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "Güncellemeler Denetleniyor" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "Bağlantı başarısız" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "Zaten en yeni sürümü (%(version)s) kullanıyorsunuz" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "Yeni sürüm var: %(new-version)s\n" "\n" "Şuan kullandığınız sürüm: %(old-version)s\n" "\n" " <a href='%(url)s'>web sayfasını</a> ziyaret edin" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "Çalma Listesini Boşalt" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "Çalma listelerinin bir adı olmalıdır" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "%(name)s adında çalma listesi zaten %(path)s yolunda var" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "Gömülü albüm kapakları" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "Ses dosyaları içine gömülü kapakları kullanır." #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "Dosya sistemi kapak resmi" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Bilinen dizinlerde şarkı yanında bulunan öylesine adlandırılmış resimleri " "kullanır." #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "Kapak Resmi" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "Albüm resmi sağlayıcıları sorgulanıyor" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Özet kullanım bilgilerini göster" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Sürüm ve telif haklarını göster" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "Hata ayıklama bilgisini ekrana yaz" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Kullanım: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[seçenekler]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "%r seçeneği anlaşılmadı." #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "%r seçeneği bir değişken gerektirir." #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r eşsiz bir önek değil." #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s saniye" msgstr[1] "%s saniye" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Süre bilgisi yok" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d saniye" msgstr[1] "%d saniye" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d dakika" msgstr[1] "%d dakika" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d saat" msgstr[1] "%d saat" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d gün" msgstr[1] "%d gün" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d yıl" msgstr[1] "%d yıl" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "başlık düzeni mi?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Tarih şu biçimlerin birinde girilmelidir: 'YYYY', 'YYYY-AA-GG' veya 'YYYY-AA-" "GG SS:DD:SS'." #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain ses düzeltmeleri 'x.yy dB' biçiminde girilmelidir." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain tepe ses seviyeleri 'x.yy' biçiminde girilmelidir." #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID'leri UUID biçminde girilmelidir." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz'de yayın durumu 'official', 'promotional' veya 'bootleg' " "olmalıdır." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Dil, ISO 639-2 üç-harf kod olmalıdır" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "%d dosya kaydediliyor" msgstr[1] "%d dosya kaydediliyor" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "Otomatik Kaydetme" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Şarkı değiştirilemedi" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "%s kaydedilemedi. Dosya salt okunur olabilir veya dosyayı değiştirme izniniz " "olmayabilir." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Geçersiz Kodlama]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "albüm" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "aranjör" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "aranjörler" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "aranje" #: quodlibet/util/tags.py:86 msgid "author" msgstr "yazar" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "yazarlar" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "yorum" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "besteci" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "besteciler" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "beste" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "orkestra şefi" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "orkestra şefleri" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "orkestra şefi" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "iletişim" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "telif hakkı" #: quodlibet/util/tags.py:93 msgid "date" msgstr "tarih" #: quodlibet/util/tags.py:94 msgid "description" msgstr "açıklama" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "tür" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "türler" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "seslendiren" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "seslendirme" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "gruplama" #: quodlibet/util/tags.py:98 msgid "language" msgstr "dil" #: quodlibet/util/tags.py:99 msgid "license" msgstr "lisans" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "söz yazarı" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "söz yazarları" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "şarkı sözleri" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "organizasyon" #: quodlibet/util/tags.py:104 msgid "title" msgstr "başlık" #: quodlibet/util/tags.py:105 msgid "version" msgstr "sürüm" #: quodlibet/util/tags.py:106 msgid "website" msgstr "web sitesi" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "albüm sanatçısı" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "disk altyazısı" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "parça" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "yapımcı ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "asıl yayım tarihi" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "asıl albüm" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "asıl sanatçı" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "kayıt tarihi" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "yayımlandığı ülke" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "başlangıç anahtarı" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz kayıt kimliği" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz yayın parça kimliği" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz yayın kimliği" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz sanatçı kimliği" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz yayın sanatçı kimliği" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM Kimliği" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz albüm durumu" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz albüm türü" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz yayın grup kimliği" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "parça ses düzeltmesi" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "parça tepe ses seviyesi" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "albüm ses düzeltmesi" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "albüm tepe ses seviyesi" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "kaynak ses yüksekliği" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "diskler" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "parçalar" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "son başlatılan" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "tam ad" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "bağlama yeri" #: quodlibet/util/tags.py:166 msgid "people" msgstr "kişiler" #: quodlibet/util/tags.py:168 msgid "year" msgstr "yıl" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "özgün yayım yılı" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "yer imi" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bit derinliği" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "dosya biçimi" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "çalma listeleri" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "örnekleme oranı" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "kanal sayısı" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "sırala" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "görevler" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Müzik etiketi düzenleyici" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Ses dosyalarınızdaki etiketleri düzenler" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Müzik Çalar" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Müzik koleksiyonunuzu gezin, dinleyin, düzenleyin" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso, Quod Libet ile aynı etiket düzenleme arayüzüne sahip bir etiket " "düzenleyicidir. Desteklediği bütün dosya biçimleri için, dosyada istediğiniz " "bütün etiketleri görüntüleyip düzenlemenize izin verir." #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "Desteklenen dosya biçimleri; Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC ve MIDI içerir." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet bir müzik yönetim programıdır. Ses kitaplığınızı görmek için " "birçok farklı yol sağlar, ayrıca İnternet radyosu ve ses beslemelerini de " "destekler. Son derece esnek üstveri etiket düzenleme ve arama yeteneklerine " "sahiptir." #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Bir çalma listesini Sonos çalma listesine dışa aktarır ve böylece her " #~ "ikisinin bir dizin yapısını paylaşmasını sağlar." #~ msgid "Export to Sonos playlist" #~ msgstr "Sonos çalma listesine dışa aktar" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "<b>%s</b> eklenemedi" #~ msgid "Invalid tags" #~ msgstr "Geçersiz etiketler" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "<b>%s</b> etiketleri geçersiz\n" #~ "\n" #~ "Seçili dosyalar bu etiketleri değiştirmeyi desteklemiyor." #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "Çalındığında veya atlandığında şarkıları otomatik puanlar. Bu, Brian " #~ "Nelson'un vux kitaplığından 'hızlandırılmış' algoritma kullanır." #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f saniye" #~ msgid "Startup" #~ msgstr "Başlangıç" #~ msgid "Audio Feeds" #~ msgstr "Ses Beslemeleri" #~ msgid "_Audio Feeds" #~ msgstr "_Ses Beslemeleri" #~ msgid "New" #~ msgstr "Yeni" #~ msgid "Automatic Library Update" #~ msgstr "Otomatik Arşiv Güncelleme" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "Arşivinizi, uyarmadan güncel tutar. %s gerektirir." #, fuzzy #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "MPRIS 2 D-Bus Arayüz Özelleştirmesi kullanan Quod Libet'in denetimine " #~ "izin verir." #~ msgid "Searching for lyrics…" #~ msgstr "Şarkı sözleri aranıyor…" #, fuzzy #~ msgid "_Clear Queue" #~ msgstr "Hataları _Sil" #, fuzzy #~ msgid "<artist>" #~ msgstr "sanatçı" #, fuzzy #~ msgid "<album>" #~ msgstr "albüm" #, fuzzy #~ msgid "<title>" #~ msgstr "isim" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Çalma Listesi İçe Aktar" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Çalma Listesi İçe Aktar" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Bilgi" #~ msgid "Unsupported file type" #~ msgstr "Dosya türü desteklenmiyor" #~ msgid "Unable to add station" #~ msgstr "Kanal eklenemedi" #~ msgid "Device Properties" #~ msgstr "Aygıt Özellikleri" #~ msgid "Device:" #~ msgstr "Aygıt:" #~ msgid "Not mounted" #~ msgstr "Bağlanmamış" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Bağlama Yeri:" #~ msgid "Media Devices" #~ msgstr "Ortam Aygıtları" #~ msgid "_Media Devices" #~ msgstr "_Ortam Aygıtları" #~ msgid "_Eject" #~ msgstr "_Çıkart" #, fuzzy #~ msgid "_Properties" #~ msgstr "Özellikler" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> kullanılmış, <b>%s</b> boş" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "<b>%(song)s</b> Kopyalanıyor" #~ msgid "Unable to copy song" #~ msgstr "Şarkı kopyalanamadı" #~ msgid "There is not enough free space for this song." #~ msgstr "Bu şarkı için yeterli boş yer yok." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> kopyalanamadı." #~ msgid "Unable to delete songs" #~ msgstr "Şarkılar silinemiyor" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "<b>%(song)s</b> siliniyor" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> silinemedi." #~ msgid "Unable to delete song" #~ msgstr "Şarkı silinemedi" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "<b>%s</b> çıkartılamadı." #~ msgid "Unable to eject device" #~ msgstr "Aygıt çıkartılamadı" #~ msgid "Search Library" #~ msgstr "Arşivde Ara" #~ msgid "_Search Library" #~ msgstr "Arşivde _Ara" #~ msgid "Rate the playing song" #~ msgstr "Çalan şarkıya puan ver" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Şarkı listesini göster veya sakla" #~ msgid "Unknown Device" #~ msgstr "Bilinmeyen Aygıt" #~ msgid "%r is not a supported device." #~ msgstr "%r desteklenen bir aygıt değil." #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Ses altsistemi yükleniyor (%s)" #, fuzzy #~ msgid "Device backend initialized." #~ msgstr "%r ses altsistemi kurulu değil." #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Dosya Adı Süzgeci:" #, fuzzy #~ msgid "_Clear" #~ msgstr "Hataları _Sil" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Sözler" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Aramayı temizle" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Sözler" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Sözler" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Şarkı yok" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Geziciler" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Dizin yaratılamadı" #~ msgid "Audio device: %s" #~ msgstr "Ses aygıtı: %s" #~ msgid "Downloads" #~ msgstr "İndirilenler" #~ msgid "Size" #~ msgstr "Boyut" #~ msgid "_Download" #~ msgstr "_İndir" #~ msgid "_Copy to Device" #~ msgstr "Aygıta _Kopyala" #, fuzzy #~ msgid "browsers" #~ msgstr "Geziciler" #, fuzzy #~ msgid "" #~ "An exception has occured in Quod Libet. A dump file has been saved to <b >" #~ "%(dump-path)s</b> that will help us debug the crash. Please file a new " #~ "issue at %(new-issue-url)sand attach this file or include its contents. " #~ "This file may contain some identifying information about you or your " #~ "system, such as a list of recent files played. If this is unacceptable, " #~ "send <b>%(mini-dump-path)s</b> instead with a description of what you " #~ "were doing." #~ msgstr "" #~ "Quod Libet'te beklenmedik bir durum oluştu. Durumu çözümlememize yardımcı " #~ "olmak için <b>%s</b> adında bir döküm dosyası oluşturuldu. Lütfen http://" #~ "code.google.com/p/quodlibet/issues/list adresine döküm dosyasıyla beraber " #~ "bildirimde bulunun. Bu dosya son dinlediğiniz şarkılar gibi hakkınızda " #~ "bazı bilgiler içerebilir. Bunu uygun bulmuyorsanız yerine <b>%s</b> " #~ "dosyasını o anda ne yaptığınızın bir anlatımıyla beraber " #~ "gönderebilirsiniz.\n" #~ "\n" #~ "Quod Libet şimdi kararlı durumda olmayabilir. Kapatıp tekrar başlatmanız " #~ "Tavsiye edilir. Arşiviniz kaydedilecektir." #~ msgid "Unable to download lyrics." #~ msgstr "Şarkı sözleri indirilemedi." #~ msgid "Set or toggle the playback order" #~ msgstr "Çalma sıralamasını değiştir" #~ msgid "Uninitialized iPod" #~ msgstr "iPod'la bağlantı kurulmamış" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Bu iPod'da boş bir veritabanı yaratmak istiyor musunuz?" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Ses Düzeyi (dB)" #~ msgid "Combine tags with _multiple values" #~ msgstr "Birden _çok değeri olan etiketleri birleştir" #~ msgid "Capacity:" #~ msgstr "Kapasite:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "iPod veritabanı kaydedilemedi" #~ msgid "Unable to save iPod database" #~ msgstr "iPod veritabanı kaydedilemedi" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "şarkı tepe ses seviyesi" #~ msgid "Shuffle" #~ msgstr "Rastgele" #~ msgid "Weighted" #~ msgstr "Ağırlıklı" #~ msgid "_Weighted" #~ msgstr "_Ağırlıklı" #~ msgid "_One Song" #~ msgstr "_Bir Şarkı" #~ msgid "Restart the playlist when finished" #~ msgstr "Çalma listesi bitince başa dön" #~ msgid "Disable Browser" #~ msgstr "Geziciyi Gizle" #~ msgid "_Disable Browser" #~ msgstr "Geziciyi _Gizle" #, fuzzy #~ msgid "Force Write" #~ msgstr "Yaz" #~ msgid "Filter on _Genre" #~ msgstr "_Türe göre süz" #~ msgid "Filter on _Artist" #~ msgstr "_Sanatçıya göre süz" #~ msgid "Filter on Al_bum" #~ msgstr "_Albüme göre süz" #~ msgid "_Music" #~ msgstr "_Müzik" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Yer imleri" #~ msgid "Song _List" #~ msgstr "Şarkı _Listesi" #, fuzzy #~ msgid "D:" #~ msgstr "U:" #, fuzzy #~ msgid "W:" #~ msgstr "U:" #, fuzzy #~ msgid "E:" #~ msgstr "H:" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Bu şarkıdan sonra dur" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "ve %d tane daha..." #~ msgstr[1] "ve %d tane daha..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Diski _Albümden ayır" #, fuzzy #~ msgid "Timeout" #~ msgstr "Süre" #, fuzzy #~ msgid "Select an album" #~ msgstr "Hepsini _Seç" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s ve %(count)d tane daha" #~ msgstr[1] "%(title)s ve %(count)d tane daha" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Çalma Listeleri" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "Önizlemelerde _yuvarlatılmış köşeler kullan" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "albüm kapat resimlerinin kenarlarını yuvarlat. Tekrar başlatmayı " #~ "gerektirebilir." #~ msgid "Re_fresh Library" #~ msgstr "Arşivi _Yenile" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Puan" #~ msgid "" #~ "GStreamer has no element to handle reading files. Check your GStreamer " #~ "installation settings." #~ msgstr "" #~ "Gstreamer'da dosya okumayı sağlayacak bileşen yok. Gstreamer kurulum " #~ "ayarlarınızı kontrol edin." #~ msgid "Invalid audio backend" #~ msgstr "Geçersiz ses altsistemi" #, fuzzy #~ msgid "The audio backend '%(backend-name)s' could not be loaded." #~ msgstr "%r ses altsistemi kurulu değil." #, fuzzy #~ msgid "ql-revert" #~ msgstr "Arşivden _Çıkart" #~ msgid "command|filename" #~ msgstr "dosya adı" #~ msgid "command|tag" #~ msgstr "etiket" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Ara" #~ msgid "%d of %d" #~ msgstr "%d taneden %d tanesi" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Kullanım: %s %s" #~ msgid "_Download..." #~ msgstr "_İndir..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Yeni Kanal" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "<b>%s</b> dosyasının üstüne yazılsın mı?" #, fuzzy #~ msgid "Output Error" #~ msgstr "Çıktı Kaydı" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet zaten çalışıyor." #~ msgid "No song is currently playing." #~ msgstr "Şu anda çalmıyor." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Yazılamayan %s kaldırıldı." #~ msgid "_Edit Bookmarks..." #~ msgstr "Yer imlerini _değiştir" #~ msgid "_New Folder..." #~ msgstr "_Yeni Dizin..." #~ msgid "_Add to Playlist" #~ msgstr "Çalma Listesine _Ekle" #~ msgid "_Edit Display..." #~ msgstr "_Görünümü düzenle..." #~ msgid "Output Log" #~ msgstr "Çıktı Kaydı" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d kanal" #~ msgid "_Add a Location..." #~ msgstr "Adres _Ekle..." #~ msgid "_Output Log" #~ msgstr "_Çıktı Kayıtları" #~ msgid "Invalid command %r received." #~ msgstr "Geçersiz bir komut olan %r alındı." #~ msgid "Unknown browser %r." #~ msgstr "%r gezicisi bilinmiyor." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Etiketleri Özelleştir..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "Şarkı _Numarası Etiketleri" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Kişi Etiketleri" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Albüm Etiketleri" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Tarih Etiketleri" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Dosya Etiketleri" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Yapımcı Etiketleri" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Etiket:" #~ msgid "Too Many Errors" #~ msgstr "Çok Fazla Hata" #~ msgid "Stopping playback because there were %d errors in a row." #~ msgstr "Arka arkaya %d hata olduğu için çalma durduruldu." #, fuzzy #~ msgid "Warnings" #~ msgstr "_Puan" #~ msgid "album artist (sort)" #~ msgstr "albüm sanatçısı (sıralama)" #~ msgid "artist (sort)" #~ msgstr "sanatçı (sıralama)" #~ msgid "album (sort)" #~ msgstr "albüm (sıralama)" #~ msgid "performer (sort)" #~ msgstr "seslendiren (sıralama)" #~ msgid "performers (sort)" #~ msgstr "seslendirenler (sıralama)" #~ msgid "errors" #~ msgstr "hatalar" #~ msgid "Permanently delete this file?" #~ msgstr "Dosya geri dönüşü olmayacak şekilde silinsin mi?" #~ msgid "Permanently delete these files?" #~ msgstr "Dosyalar geri dönüşü olmayacak şekilde silinsin mi?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s ve %(count)d tane daha..." #~ msgstr[1] "%(title)s ve %(count)d tane daha..." #, fuzzy #~ msgid "Version:" #~ msgstr "versiyon" #~ msgid "_Cause an Error" #~ msgstr "Hata _Yüzünden" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s arşive eklenemedi.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Çıkartma komutu bulunamadı." #~ msgid "Unable to start web browser" #~ msgstr "İnternet gezicisi başlatılamadı" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Bir internet gezicisi bulunamadı. Lütfen $BROWSER değişkenini ayarlayın " #~ "veya /usr/bin/sensible-browser dosyasının var olduğundan emin olun." #, fuzzy #~ msgid "Library Error" #~ msgstr "Arşiv Gezici" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Çıktı Kayıtları" #~ msgid "translator-credits" #~ msgstr "Türerkan İnce (turerkan@gmail.com)" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Diğer gösterilecek sütunlar, boşluklarla ayrılmış olarak" #~ msgid "_Edit and Continue" #~ msgstr "_Düzenle ve Devam Et" #, fuzzy #~ msgid "Confirm rating" #~ msgstr "Bilgi" #~ msgid "Search your library" #~ msgstr "Arşivinizde arama yapın" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quod-libet-development@googlegroups.com>\n" #~ "Telif Hakkı 2004-2005 Joe Wreschnig, Michael Urman ve diğerleri\n" #~ "\n" #~ "Bu yazılım ücretsizdir; kopyalama koşulları için kaynak koda başvurun. " #~ "There is NO\n" #~ "Yazılımın hiçbir şekilde GARANTİSİ YOKTUR. Buna herhangi bir amaç için " #~ "kullanılabilirlik bile dahildir.\n" #~ msgid "%r doesn't contain any browsers." #~ msgstr "%r hiçbir gezici içermiyor." #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Toplam boyut:" #~ msgid "%r doesn't contain any devices." #~ msgstr "%r hiçbir aygıt içermiyor." #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet Eklentileri" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "basit aramalar mavi, gelişmiş aramalar yeşil, geçersiz aramalar kırmızı" #~ msgid "Separators for splitting tags" #~ msgstr "etiketler ayırıcıları" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet Ayarları" #~ msgid "Not Played To_day" #~ msgstr "_Bugün çalınmadı" #~ msgid "Not Played in a _Week" #~ msgstr "Bir _haftadır çalınmadı" #~ msgid "Not Played in a _Month" #~ msgstr "Bir _aydır çalınmadı" #~ msgid "B_ottom 40" #~ msgstr "_Dip 40" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "En az çaldığınız 40 şarkı (eşitlik varsa 40'tan fazla olabilir)" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "_Tarih" #~ msgid "Add" #~ msgstr "Ekle" #~ msgid "Bitrate" #~ msgstr "Bit oranı" #~ msgid "_Stations..." #~ msgstr "_Kanallar..." #~ msgid "Initializing audio backend (%s)" #~ msgstr "Ses altsistemi yükleniyor (%s)" #~ msgid "Initializing main library (%s)" #~ msgstr "Ana kitaplık yükleniyor (%s)" #~ msgid "Unable to save library" #~ msgstr "Arşiv kaydedilemedi" #~ msgid "" #~ "The audio output pipeline %r could not be created. Check your GStreamer " #~ "settings in ~/.quodlibet/config." #~ msgstr "" #~ "Ses çıkış hattı %r yaratılamadı. ~/.quodlibet/config dosyasındaki " #~ "Gstreamer ayarlarınızı kontrol ediniz." #~ msgid "Sort by title" #~ msgstr "İsime göre sırala" #~ msgid "Sort by artist" #~ msgstr "Sanatçıya göre sırala" #~ msgid "Lyrics provided by %s." #~ msgstr "Şarkı sözleri %s tarafından sağlanmıştır." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Şarkı sözleri bulunamadı.\n" #~ "\n" #~ "İndir'e basarak arama yaptırabilirsiniz veya kendinizi yazıp Kaydet'e " #~ "basabilirsiniz." �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/uk.po����������������������������������������������������������������������������0000644�0001750�0001750�00000745555�14436352625�013637� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Ukrainian translation of Quod Libet # Copyright (C) 2007'S THE quodlibet'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # Mykola Lynnyk <pydefiner@gmail.com>, 2007. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2022-05-29 08:23+0000\n" "Last-Translator: Andrij Mizyk <andmizyk@gmail.com>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/quodlibet/" "quodlibet/uk/>\n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.13-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "_Назва" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 #, fuzzy msgid "_People" msgstr "люди" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "_Дата" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "_Дата додавання" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "_Ориґінальна дата" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "_Жанр" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "О_цінка" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 #, fuzzy msgid "Play_count" msgstr "_Кількість відтворень" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "Сортувати _за…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "Нала_штування" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "Список альбомів" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "Список а_льбомів" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "Усі альбоми" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d альбом" msgstr[1] "%d альбоми" msgstr[2] "%d альбомів" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Перезавантажити о_бкладинку альбому" msgstr[1] "Перезавантажити о_бкладинки альбомів" msgstr[2] "Перезавантажити о_бкладинки альбомів" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Пісні, що не входять в альбом" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d доріжка" msgstr[1] "%d доріжки" msgstr[2] "%d доріжок" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d диск" msgstr[1] "%d диски" msgstr[2] "%d дисків" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "Зразок альбому" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Налаштування списку альбомів" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Показувати _обкладинки альбомів" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "Вбудований _пошук враховує людей" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "Параметри" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "Відображення альбомів" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_Закрити" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "Оглядач бібліотеки" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d пісня" msgstr[1] "%d пісні" msgstr[2] "%d пісень" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "Неправильний шаблон" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "Колекція альбомів" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "_Колекція альбомів" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "Невідомий %s" #: quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Декілька %s значень" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Власний" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "_Додати" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "Ви_лучити" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "Мітка" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "Обʼєднати" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "Налаштування колекції альбомів" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Застосувати" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Скасувати" #: quodlibet/browsers/covergrid/main.py:172 #, fuzzy msgid "Cover Grid" msgstr "Сітка обкладинки" #: quodlibet/browsers/covergrid/main.py:173 #, fuzzy msgid "_Cover Grid" msgstr "_Сітка обкладинки" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "Налаштування сітки обкладинки" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "Показувати _текст альбому" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "Показувати пункт „Усі альбоми“" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "Широкий режим" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 #, fuzzy msgid "Cover Magnification" msgstr "Збільшення обкладинки" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "Файлова система" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "_Файлова система" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Не вдалося скопіювати пісню" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Вибрані файли не можуть скопіюватися до іншого списку пісень або черги." #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "_Додати до бібліотеки" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "Списки станцій можуть містити лише адреси станцій, але не списки станцій або " "списки програвання. Не вдалося завантажити такі станції:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "Інтернет-радіо" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "Додати станцію" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "Завантаження списку станцій" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "Нова станція" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "Введіть адресу інтернет-радіостанції:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Електроніка" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Гіп Гоп / Реп" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Стара" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Японська" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Індійська" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Релігійна" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Чарти" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Турецька" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Реґі / Денсгол" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "Латинська" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "Коледжне радіо" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Розмови / Новини" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Навколишнє" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Джаз" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Класична" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Поп" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Альтернативна" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Метал" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Кантрі" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "Новини" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Шляґер" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Фанк" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Інді" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Блюз" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Соул" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Відпочинок" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "Панк" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Реґетон" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Словʼянська" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Грецька" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Ґотика" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Рок" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "Бажаєте завантажити список популярних радіо-станцій?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "_Завантажити станції" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "_Інтернет-радіо" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "Усі станції" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Відібрані" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "Без категорії" #: quodlibet/browsers/iradio.py:651 #, fuzzy msgid "_Add Station…" msgstr "_Нова станція…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "_Оновити станції" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "Станцій не знайдено" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "За адресою %s інтернет-радіостанцій не знайдено." #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "Нічого додавати" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "Усі перелічені станції вже є в бібліотеці." #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "Додати до відібраних" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "Вилучити з відібраних" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d станція" msgstr[1] "%(count)d станції" msgstr[2] "%(count)d станцій" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 #, fuzzy msgid "Paned Browser" msgstr "Панельний оглядач" #: quodlibet/browsers/paned/main.py:42 #, fuzzy msgid "_Paned Browser" msgstr "_Панельний оглядач" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "Вибрати _все" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Невідомо" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "Усі" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "Малий" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "Широкий" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "Стовпчатий" #: quodlibet/browsers/paned/prefs.py:109 #, fuzzy, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "Взірець мітки з необовʼязковою розміткою, напр. <tt>композитор</tt> або\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:230 #, fuzzy msgid "Paned Browser Preferences" msgstr "Налаштування панельного оглядача" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "Компонування стовпців" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "Вміст стовпців" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "Рівна ширина панелей" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "Списки відтворення" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Списки відтворення" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "_Вилучити зі списку відтворення" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Нова" #: quodlibet/browsers/playlists/main.py:214 #, fuzzy msgid "_Import…" msgstr "_Імпортувати" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "Не вдалося імпортувати список відтворення" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet здатне імпортувати списки відтворення лише у форматах M3U та PLS." #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "_Видалити" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "_Перейменувати" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "Не вдалося перейменувати список відтворення" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "Імпортувати список відтворення" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "_Імпортувати" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "_Новий список відтворення…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "Що ви хочете робити з цією %d піснею?" msgstr[1] "Що ви хочете робити з цими %d піснями?" msgstr[2] "Що ви хочете робити з цими %d піснями?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Підтвердіть дію для списку відтворення „%s“" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "порожньо" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "Зразок списку відтворення" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "Налаштування оглядача списків відтворення" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "Відображення списків відтворення" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Ви дійсно хочете видалити список відтворення '%s'?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Уся інформація про вибрані списки відтворення видалиться і не можливо буде " "відновити." #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/browsers/playlists/util.py:60 #, fuzzy msgid "_Add Tracks" msgstr "Трек" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "Новий список відтворення" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "Введіть назву нового списку відтворення:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Імпортується список відтворення.\n" "\n" "%(current)d/%(total)d пісень додано." #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "Нова стрічка" #: quodlibet/browsers/podcasts.py:241 #, fuzzy msgid "Enter the podcast / audio feed location:" msgstr "Введіть адресу авдіо-стрічки:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "" #: quodlibet/browsers/podcasts.py:412 #, fuzzy msgid "_Add Feed…" msgstr "_Додати файл..." #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "_Оновити" #: quodlibet/browsers/podcasts.py:480 #, fuzzy msgid "Search source for new episodes" msgstr "Слідкувати за появою нових пісень в цьому каталозі" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "Не вдалося додати стрічку" #: quodlibet/browsers/podcasts.py:547 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "" "Не вдається додати <b>%s</b>. Можливо, вказаний сервер не працює, або адреса " "не є авдіо-стрічкою." #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "_Обмежити результати" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "_Дозволити кілька запитів" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "Список доріжок" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "Список _доріжок" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 #, fuzzy msgid "Soundcloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Оглядач Soundcloud" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "Пошук" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Мої доріжки" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "Перейти до %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "Підʼєднано" #: quodlibet/browsers/soundcloud/main.py:445 #, fuzzy, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet зараз підʼєднано, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "Вийти з %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "Увести код…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "Увійти в %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Авторизація Soundcloud" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "Введіть код автентифікації Soundcloud:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet не запущено (щоб запустити додайте '--run')" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "музична бібліотека та програвач" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[параметр]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "Показати, яка пісня відтворюється, і вийти" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "Починати відтворення відразу" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "Не показувати жодних вікон на початку" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "Перейти до наступної пісні" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "Перейти до попередньої пісні або перезапустити, якщо біля початку" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "Перейти до попередньої пісні" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "Почати програвання" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "Призупинити програвання" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "Перемкнути режим грати/призупинити" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "Зупинити програвання" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "Збільшити гучність" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "Зменшити гучність" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "Збільшити оцінку граючої пісні на одну зірку" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "Зменшити оцінку граючої пісні на одну зірку" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "Показати стан програвача" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "Сховати головне вікно" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "Показати головне вікно" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "Показати/сховати головне вікно" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "Помістити фокус на запущеному програвачі" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "Вилучити активні фільтри оглядача" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "Оновити і пересканувати бібліотеку" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "Список доступних оглядачів" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "Показати поточний список відтворення" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "Показати вміст черги" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "Вивести текст активного запиту" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "Запустити без втулок" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "Запустити Quod Libet, якщо не запущено" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "Вийти з Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "Переміститись всередині відтворюваної пісні" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ГГ:]ХХ:СС" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "Задати або перемкнути перемішаний режим" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "Задати тип перемішаного режиму" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "Увімкнути/вимкнути/перемикнути повторення" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "Задати тип режиму повторення" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "Задати гучність" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "Шукати в бібліотеці" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "запит" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "Відтворити файл" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 #, fuzzy msgctxt "command" msgid "filename" msgstr "назва файлу" #: quodlibet/cli.py:133 #, fuzzy msgid "Set rating of playing song" msgstr "Переміститись всередині відтворюваної пісні" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "Встановити режим перегляду бібліотеки" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "Зупинити після відтворення пісні" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "Відкрити новий оглядач" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "Показати/сховати чергу" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "Фільтрувати за випадковим значенням" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "мітка" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "Фільтрувати за значенням мітки" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "мітка=значення" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "Додати в чергу файл або запит" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "Додати в чергу розділені комою файли" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "назва файлу" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "Виводити назви файлів з результатів запитів у буфер виводу" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "Видалити з черги файл або запит" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "Додати файл або каталог до бібліотеки" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "розташування" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 #, fuzzy msgid "pattern" msgstr "Неправильний шаблон" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "Неправильний арґумент для '%s'." #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "Спробуйте %s --help." #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "Відбулася помилка" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "Ви можете проіґнорувати цю помилку, але програма може бути нестабільною поки " "не перезапуститься. Надсилання звіту про помилку займе кілька секунд і може " "дуже нам допомогти." #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "Надіслати звіт про помилку" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "Перезапустити" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "Іґнорувати помилку" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "Деталі помилки:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "Різні деталі щодо помилки і вашої системи буде надіслано сторонньому сервісу " "в мережі (<a href='https://www.sentry.io'>www.sentry.io</a>). Можете " "переглянути дані перед надсиланням." #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(необовʼязково) Прохання надати короткий опис того, що трапилося під час " "помилки:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "_Надіслати" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Короткий опис…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Дані, що надсилаються:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "редактор авдіо-міток" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "каталог" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Редактор авдіо-метаданих" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "URL-джерело обкладинки" #: quodlibet/ext/covers/artwork_url.py:21 #, fuzzy msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Завантажує обкладинки і привʼязує її до мітки artwork_url. Це працює з " "оглядачем Soundcloud." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Джерело обкладинки Discogs" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "Завантажує обкладинки з Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Джерело обкладинки Last.fm" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Завантажує обкладинки з архіву Last.fm." #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "Джерело обкладинки MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Завантажує обкладинки з архіву MusicBrainz." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "Перетворити кодування" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "" "Виправляє неправильно визначене кодування значення мітки в редакторі міток." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "_Перетворити кодування…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "Романізувати _японський текст" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" #: quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Назва" #: quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Редактор аудіо-тегів" #: quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Замінити першу букву кожного слова великою" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "Розширені налаштування" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "Дозволити редагування розширених налаштувань." #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "Я знаю що роблю" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "" "Відображає інформацію про пісню на вашому екрані, коли вона змінюється." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "_Позиція:" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "Розмір _обкладинки:" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "Відображення" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "_Шрифт:" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "Зліва" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "По центру" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "Зправа" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "_Вирівнювання тексту:" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "Текст" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "_Текст:" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "Кольори" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "_Тіні" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "_Затримка:" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "Ефекти" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Змінити шаблон відображення…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Попередній вигляд" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Інформація про програму" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Різна інформація про програму та її середовище." #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "Підтримувані формати" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "Каталог конфіґурації" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "Каталог кешу" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "Авдіо-підписки" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "Після кожного програвання (типово)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "Після кожного програвання або пропускання" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "Раз, коли альбом повністю оцінено" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "Автоматично оновлювати мітки у файлах" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "Зберігати оцінки та _к-сть відтворень у мітках" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "Налаштування оновлено" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "Помилка в %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "_Оновити стратегію:" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "Налаштування" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "Автоматична оцінка" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Не вдалося імпортувати" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "Успішно імпортовано оцінки і статистику для %d пісні" msgstr[1] "Успішно імпортовано оцінки і статистику для %d пісень" msgstr[2] "Успішно імпортовано оцінки і статистику для %d пісень" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Імпортування з Banshee" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Імпортувати оцінки та статистику пісень із Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "_Шлях до бази даних:" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "Почати імпортування" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "Колискова" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "Затухає і призупиняє вашу музику." #: quodlibet/ext/events/discord_status.py:44 #, fuzzy msgid "Discord status message" msgstr "Повідомлення стану Gajim" #: quodlibet/ext/events/discord_status.py:45 #, fuzzy msgid "Discord Status Message" msgstr "Повідомлення стану Gajim" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "" #: quodlibet/ext/events/discord_status.py:85 #, fuzzy msgid "Paused" msgstr "Призупинено:" #: quodlibet/ext/events/discord_status.py:136 #, fuzzy msgid "Status Line #1" msgstr "Текст стану" #: quodlibet/ext/events/discord_status.py:147 #, fuzzy msgid "Status Line #2" msgstr "Текст стану" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Рівно" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "Наживо" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "Клуб" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "Великий зал" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "Вечірка" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "Легко" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "Повні баси" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "Реґі" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "Гарнітура" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "Легкий рок" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "Техно" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "Ска" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "Еквалайзер" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "Керуйте тонами вашої музики через еквалайзер.\n" "Клацніть або викор. клавіші, щоб пристосувати рівні (права клавіша миші " "скидає діапазон)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f кГц" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Гц" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f дБ" #: quodlibet/ext/events/equalizer.py:272 #, fuzzy msgid "Default presets" msgstr "Фільтрувати за _виконавцем" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "Вибрати…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "_Скинути EQ" #: quodlibet/ext/events/equalizer.py:299 #, fuzzy msgid "Custom presets" msgstr "_Інший" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "_Видалити вибране" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "_Зберегти" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "у мережі" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "поза мережею" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "чат" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Повідомлення стану Gajim" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "призупинено" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "Шаблон:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "Обліківки:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "Додати '[призупинено]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "Заборонити зберігач екрана/засинання" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "Грає музика" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "Режим:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "Заборонити зберігач екрана" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "Заборонити засинання" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "Журнал Інтернет-радіо" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "Змінити мову" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "Змінити мову користувацького інтерфейсу." #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Типово для системи" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "Потрібно перезапустити, щоб зміни мали ефект" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Переконайтеся, що наступне є у вашому файлі конфіґурації rygel (~/.config/" "rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "Сервер MPD" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "_Порт:" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "_Локальна IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "П_ароль:" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "Зʼєднання" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Пробні клієнти" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "Підтримка MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Ховати основне вікно при закритті" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Приймає шаблони QL, як-от %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "Публікатор MQTT" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Публікує повідомлення стану в темі MQTT." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "Тема" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "Грати шаблон" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Текст стану, коли почалася пісня." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "Шаблон призупинення" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Текст, коли пісню призупинено." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "Текст, коли нема пісні" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Простий текст, коли нема поточної пісні" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "Конфіґурація MQTT" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "Текст стану" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "Помилка зʼєднання" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "Синхронізація з MusicBrainz" #: quodlibet/ext/events/musicbrainzsync.py:37 #, fuzzy msgid "Syncs the rating of a song with MusicBrainz." msgstr "Синхронізує оцінки пісень із MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "_Імʼя користувача:" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "_Пароль:" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "Обліківка" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Текст сповіщення" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "_Назва:" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "Повернути до типового шаблона" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Тіло:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "_Показувати сповіщення" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "Показувати сповіщення" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Лише в <i>_ручних</i> змінах пісні" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Лише в <i>_автоматичних</i> змінах пісні" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "В <i>_усіх</i> змінах пісні" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Лише коли основне вікно не під _фокусом" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "Показувати кнопку „_Наступна“" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "Помилка зʼєднання" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "Не можливо зʼєднатися з демоном сповіщень." #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "Сповіщення пісні" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "Відображати сповіщення коли змінюється пісня." #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "Наступна" #: quodlibet/ext/events/notify_bookmarks.py:34 #, fuzzy msgid "Bookmark Notifications" msgstr "Сповіщення пісні" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Будь ласка, відвідайте вікно Втулки, щоб налаштувати QLScrobbler. До цього " "часу пісні не надсилатимуться." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "Не можливо звʼязатися з сервером '%s'." #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "Не вдалося автентифікуватися: неправильна URL." #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Не вдалося автентифікуватися: Неправильне імʼя користувача '%s' або пароль." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Неправильний системний час. Надсилання може не відбуватися поки це не " "виправиться." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "Автентифікація успішна." #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "_Сервіс:" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "Інші…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "_Перевірити дані обліківки" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "Шаблон _виконавця:" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "Шаблон _назви:" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Пісні, що відповідають цьому фільтру не надсилатимуться" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "Режим _Поза мережею (нічого не надсилається)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "Надсилання" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "Програвання випадкового альбому" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "Вища оцінка" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "Найчастіше відтворювалося" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "Найчастіше пропускалося" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "Найостанніше відтворене" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "Недавно грало" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "Останнє додане" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "Довгі альбоми" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "секунд перед початком наступного альбому" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "Вага" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "Грати деякі альбоми частіше за інші" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "уникати" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "надавати перевагу" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "Випадковий альбом" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "Очікування початку %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Успішно імпортовано оцінки і статистику для %d пісень" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Імпортувати з Rhythmbox" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Імпортує оцінки і статистику пісень із Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "Призупинити зберігач екрана" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Призупиняє програвання коли активний зберігач екрана GNOME." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "Дозволяє GNOME Shell шукати в бібліотеці." #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" #: quodlibet/ext/events/seekpoints.py:20 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Закладки" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "Назва закладки для точки A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "Назва закладки для точки B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Синхронізація з Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Помилка пошуку сервера Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Помилка пошуку %s. Перевірте налаштування" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "" #: quodlibet/ext/events/stop_on_pause.py:86 #, fuzzy msgid "Plugin Options" msgstr "Параметри" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "Очікує на копіювання" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "Очікує на видалення" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "видалити" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "Пропустити" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "ДУБЛІКАТ" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "Синхронізація" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "Видалення" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "Успішно" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "НЕ ВДАЛОСЯ" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "Пропущені існуючі файли" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "Не можливо задати назву файлу для пісні." #: quodlibet/ext/events/synchronize_to_device.py:86 #, fuzzy msgid "Synchronize to Device" msgstr "Синхронізовані тексти пісень" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "Синхронізує наступні збережені пошуки:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "Шлях розташування:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Шлях шаблонів" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Змінити збережені шаблони…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "Шаблон експортування:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "Зупинити передперегляд" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Стан" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "Джерельний файл" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "Шлях для експортування" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "Почати синхронізацію" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "Зупинити синхронізацію" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "Оберіть шлях розташування" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Шлях експортування змінено з [{old_path}] на [{new_path}] для файлу " "[{filename}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "Синхронізація буде:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, fuzzy, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "не вдалося синхронізувати {count} {file_str}" msgstr[1] "не вдалося синхронізувати {count} {file_str}" msgstr[2] "не вдалося синхронізувати {count} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:771 #, fuzzy, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "(пропущено {count} наявного {file_str})" msgstr[1] "(пропущено {count} наявного {file_str})" msgstr[2] "(пропущено {count} наявного {file_str})" #: quodlibet/ext/events/synchronize_to_device.py:781 #, fuzzy, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "видалено {count}/{total} {file_str}" msgstr[1] "видалено {count}/{total} {file_str}" msgstr[2] "видалено {count}/{total} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Будь ласка, вкажіть каталог куди експортувати пісні." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "Не надано шаблону експортування" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "Неабсолютний шлях експортування" #: quodlibet/ext/events/synchronize_to_device.py:851 #, fuzzy msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "Шаблон\n" "\n" "<b>{}</b>\n" "\n" "містить „/“, але починається не з кореневого каталогу. Для запобігання " "помилок в назвах каталогів, почніть шаблон з кореневого каталогу." #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "Не вибрано збережених пошуків" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Будь ласка, виберіть останній збережений пошук." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "Нема пісень у вибраному збереженому пошуку" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "Усі вибрані збережені пошуки порожні." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "Знайдено {} пісень для синхронізації" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "Не можливо синхронізувати" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Не можливо почати синхронізацію, коли відсортовано за <b>Станом</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "Початок синхронізації пісні" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "Синхронізація в процесі." #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "Завершено синхронізацію пісні" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "Зупинено синхронізацію пісні" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "Синхронізацію зупинено." #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "Синхронізацію завершено." #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "Зупинено синхронізацію пісні" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "Вилучення „{}“" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "Синхронізація має:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, fuzzy, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "записано {count}/{total} {file_str}" msgstr[1] "записано {count}/{total} {file_str}" msgstr[2] "записано {count}/{total} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, fuzzy, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(пропущено {count} наявного {file_str})" msgstr[1] "(пропущено {count} наявного {file_str})" msgstr[2] "(пропущено {count} наявного {file_str})" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, fuzzy, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "видалено {count}/{total} {file_str}" msgstr[1] "видалено {count}/{total} {file_str}" msgstr[2] "видалено {count}/{total} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, fuzzy, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "видалено {count}/{total} {file_str}" msgstr[1] "видалено {count}/{total} {file_str}" msgstr[2] "видалено {count}/{total} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, fuzzy, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "не вдалося синхронізувати {count} {file_str}" msgstr[1] "не вдалося синхронізувати {count} {file_str}" msgstr[2] "не вдалося синхронізувати {count} {file_str}" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "Синхронізовані тексти пісень" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "Текст:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "Шрифт" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "Розмір (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Повідомлення стану Telepathy" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "Грає:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "Призупинено:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Текст стану, коли пісню призупинено. Приймаються шаблони QL, як-от %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Простий текст для стану, коли нема поточної пісні" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "Нема пісні:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "Шаблони стану" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "Перемикач теми" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "_Тема:" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "Типова тема" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "Надавати перевагу темній версії теми" #: quodlibet/ext/events/thumbrating.py:89 #, fuzzy msgid "Thumb Rating" msgstr "_Рейтинг" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Не грає" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "Керувати Quod Libet із системного лотка." #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "_Показати %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 #, fuzzy msgid "_Play" msgstr "_Списки програвання" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 #, fuzzy msgid "P_ause" msgstr "Програвач" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 #, fuzzy msgid "Pre_vious" msgstr "_Попередній перегляд" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "_Наступна" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Випадково" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Повторювати" #: quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Зупинитись після цієї пісні" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 #, fuzzy msgid "Open _Browser" msgstr "Відкрити новий переглядач" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "Редагувати _теги" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "_Інформація" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 #, fuzzy msgid "Play_lists" msgstr "Списки програвання" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "_Вийти" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "Поведінка" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Коліщатко миші регулює гучність" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Коліщатко миші змінює пісню" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Коліщатко миші" #: quodlibet/ext/events/trayicon/prefs.py:92 #, fuzzy msgid "Tooltip Display" msgstr "Змінити зовнішній вигляд" #: quodlibet/ext/events/viewlyrics.py:25 #, fuzzy msgid "View Lyrics" msgstr "Текст пісні" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "" #: quodlibet/ext/events/viewlyrics.py:87 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Для цієї пісні текст не знайдено." #: quodlibet/ext/events/viewlyrics.py:117 #, fuzzy msgid "No active song" msgstr "Не вдалося зберегти пісню" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "Запустити візуалізацію" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "Запустити зовнішню візуалізацію." #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 #, fuzzy msgid "Error" msgstr "Помилки" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Перезавантажити" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "Показувати поточну позицію" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "Показувати позначки часу" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "Зберігач зображень" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "Зберігає зображення обкладинки поточної пісні у файл." #: quodlibet/ext/events/write_cover.py:67 #, fuzzy msgid "File:" msgstr "Файли" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Поріг:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "_Оцінка:" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "Ступінь стиснення" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "Стиснення звуку" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "_Preset:" msgstr "_Попередній перегляд" #: quodlibet/ext/gstreamer/crossfeed.py:20 #, fuzzy msgid "Filter preset" msgstr "Фільтрувати за _виконавцем" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom" msgstr "_Інший" #: quodlibet/ext/gstreamer/crossfeed.py:32 #, fuzzy msgid "Custom settings" msgstr "_Інший" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:21 #, fuzzy msgid "Filter _band:" msgstr "Фільтрувати за _жанром" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:23 #, fuzzy msgid "Filter _width:" msgstr "Фільтрувати за _виконавцем" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "_Рівень:" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "Рівень ефекту" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "Караоке" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "Вилучає основний вокал з авдіо." #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:96 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Аудіо-фіди" #: quodlibet/ext/gstreamer/pitch.py:97 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Введіть адресу аудіо-фіду" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 #, fuzzy msgid "Export Playlist to Folder" msgstr "Імпортувати список програвання" #: quodlibet/ext/playlist/export_to_folder.py:39 #, fuzzy msgid "_Export" msgstr "_Імпортувати" #: quodlibet/ext/playlist/export_to_folder.py:44 #, fuzzy msgid "Destination folder:" msgstr "Станцій не знайдено" #: quodlibet/ext/playlist/export_to_folder.py:59 #, fuzzy msgid "Filename pattern:" msgstr "_Шаблон назви файлу:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 #, fuzzy msgid "Unable to export playlist" msgstr "Не вдалося імпортувати список програвання" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:164 #, fuzzy msgid "Default filename pattern:" msgstr "_Шаблон назви файлу:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Гаразд" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:132 #, fuzzy msgid "Export to Sonos Playlist" msgstr "Імпортувати список програвання" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "Назва списку відтворення (перезапише наявну)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "" #: quodlibet/ext/playlist/remove_duplicates.py:20 #, fuzzy msgid "Remove Playlist Duplicates" msgstr "_Вилучити зі cписку програвання" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Вилучає однакові записи в списку відтворення." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "" #: quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Новий список програвання" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "Перемішує список відтворення." #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "" #: quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "востаннє відтворено" #: quodlibet/ext/playorder/playcounteq.py:26 #, fuzzy msgid "Prefer _less played" msgstr "востаннє відтворено" #: quodlibet/ext/playorder/queue.py:23 #, fuzzy msgid "Queue Only" msgstr "_Черга" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/queue.py:29 #, fuzzy msgid "Queue only" msgstr "_Черга" #: quodlibet/ext/playorder/queue.py:30 #, fuzzy msgid "_Queue only" msgstr "_Черга" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 #, fuzzy msgid "Reverse" msgstr "Ніколи" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "" #: quodlibet/ext/playorder/reverse.py:19 #, fuzzy msgid "Re_verse" msgstr "Ніколи" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:146 #, fuzzy msgid "Grouping tag:" msgstr "групування" #: quodlibet/ext/playorder/shufflebygrouping.py:150 #, fuzzy msgid "Tag to group songs by" msgstr "Не вдалося скопіювати пісню" #: quodlibet/ext/playorder/shufflebygrouping.py:152 #, fuzzy msgid "Filter tag:" msgstr "Фільтрувати за _жанром" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "Скинути до типових" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:36 #, fuzzy msgid "Include empty tags" msgstr "Неправильні теги" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" #: quodlibet/ext/query/savedsearch.py:20 #, fuzzy msgid "Include Saved Search" msgstr "Збережені значення" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "" #: quodlibet/ext/query/savedsearch.py:24 #, fuzzy msgid "@(saved: search-name)" msgstr "Збережені значення" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "Не можливо зʼєднатися з %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "Назва хоста:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "Порт:" #: quodlibet/ext/_shared/squeezebox/base.py:125 #, fuzzy msgid "Username:" msgstr "_Перейменувати" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "Пароль:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:140 #, fuzzy msgid "Library path:" msgstr "Бібліотека" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "_Перевірити налаштування" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "Зневадження" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:227 #, fuzzy msgid "Fit image to _window" msgstr "Сховати головне вікно" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "_Програма:" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "_Змінити зображення після збереження" #: quodlibet/ext/songsmenu/albumart.py:246 #, fuzzy msgid "File_name:" msgstr "Назва файлу" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "Не вдалося зберегти" #: quodlibet/ext/songsmenu/albumart.py:363 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Не вдалося зберегти пісню" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:521 #, fuzzy msgid "Album Art Downloader" msgstr "Список альбомів" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:580 #, fuzzy, python-format msgid "Size: %s" msgstr "Розмір" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:636 #, fuzzy msgid "_Search" msgstr "_Пошук" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 #, fuzzy msgid "Searching…" msgstr "Пошук" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Готово" #: quodlibet/ext/songsmenu/albumart.py:903 #, fuzzy msgid "Download Album Art" msgstr "Список альбомів" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Завантажує обкладинки альбомів із різних вебсайтів." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "Джерела" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 в ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Перетворює ваші мітки APEv2 в мітки ID3v2. Це видалить мітки APEv2 після " "перетворення." #: quodlibet/ext/songsmenu/bookmarks.py:23 #, fuzzy msgid "Go to Bookmark" msgstr "_Редагувати закладки..." #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 #, fuzzy msgid "_Edit Bookmarks…" msgstr "_Редагувати закладки..." #: quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Закладки" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "Тип альбому MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "Використовувати лише рік для мітки „дата“" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "Назва файлу" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 #, fuzzy msgid "Disc" msgstr "_Диск" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Трек" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 #, fuzzy msgid "Title" msgstr "Назва" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Виконавець" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "Тип альбому MusicBrainz" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "запит" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Пошук" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "Введіть запит." #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "Завантаження результатів…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 #, fuzzy msgid "No results found." msgstr "Розширень не знайдено" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Консоль Python" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Інтерактивна консоль Python. Відкриває нове вікно." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} для {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Бічна панель консолі Python" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "Ваш поточний робочий каталог:" #: quodlibet/ext/songsmenu/console.py:617 #, fuzzy msgid "Completion" msgstr "Зʼєднання" #: quodlibet/ext/songsmenu/cover_download.py:53 #, fuzzy msgid "Download Cover Art" msgstr "Список альбомів" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:170 #, fuzzy msgid "Cover Art Download" msgstr "Список альбомів" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:299 #, fuzzy msgid "No covers found" msgstr "Розширень не знайдено" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:335 #, fuzzy msgid "Preview size" msgstr "_Попередній перегляд" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "Зберегти як JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "команда|тег" #: quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Перейменувати" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "Назва цієї команди" #: quodlibet/ext/songsmenu/custom_commands.py:46 #, fuzzy msgid "command" msgstr "команда|тег" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "параметр" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:69 #, fuzzy msgid "reverse" msgstr "Ніколи" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:95 #, fuzzy msgid "Input value" msgstr "Неправильне значення" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "Значення для %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 #, fuzzy msgid "Custom Commands" msgstr "_Інший" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "Змінити власні команди" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Не вдалося скопіювати пісню" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "Згорнути / Розгорнути все" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:358 #, fuzzy msgid "Duplicates Browser" msgstr "Вимкнути переглядач" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:409 #, fuzzy msgid "Remove _Diacritics" msgstr "_Рейтинг" #: quodlibet/ext/songsmenu/duplicates.py:410 #, fuzzy msgid "Remove _Punctuation" msgstr "_Рейтинг" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 #, fuzzy msgid "Edit Playcount" msgstr "Змінити зовнішній вигляд" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:85 #, fuzzy msgid "Multiple files selected." msgstr "Декілька %s значень" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/embedded.py:105 #, fuzzy msgid "_Remove all Images" msgstr "_Рейтинг" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "" #: quodlibet/ext/songsmenu/filterall.py:80 #, fuzzy msgid "Filter on Any Tag" msgstr "Фільтрувати за тегом" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "" #: quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Фільтрувати за _жанром" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "_Ключ API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 #, fuzzy msgid "Queued" msgstr "_Черга" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "Записати" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "Випуск" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 #, fuzzy msgid "Write MusicBrainz tags" msgstr "Ідентифікатор треку MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "каталог" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Альбом" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "_Деталі" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "_Надіслати" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "Пісні з MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "" #: quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Нова станція" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "Експортувати в HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:30 #, fuzzy msgid "No iFP device found" msgstr "Розширень не знайдено" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:39 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Перенесення %d/%d." #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 #, fuzzy msgid "Export User Data" msgstr "Шлях для експортування" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 #, fuzzy msgid "Export Tags" msgstr "Шлях для експортування" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 #, fuzzy msgid "Further information" msgstr "Немає інформації про час" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 #, fuzzy msgid "Album similarity:" msgstr "Список альбомів" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 #, fuzzy msgid "Export files" msgstr "Не вдалося імпортувати" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "Імпортувати" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 #, fuzzy msgid "Open Export Directory" msgstr "Фільтрувати за _жанром" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 #, fuzzy msgid "Discs" msgstr "_Диск" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 #, fuzzy msgid "Tracks" msgstr "Трек" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 #, fuzzy msgid "Artist(s)" msgstr "_Виконавець" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Match Albums" msgstr "альбоми" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 #, fuzzy msgid "Continue" msgstr "_Продовжити" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 #, fuzzy msgid "Nothing to import" msgstr "Нічого додавати" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, fuzzy, python-format msgid "Couldn't read %s" msgstr "Не можливо зʼєднатися з %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 #, fuzzy msgid "File name" msgstr "Назва файлу" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 #, fuzzy msgid "Match Tracks" msgstr "Мої доріжки" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Вже оновлено." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "Синхронізацію завершено." #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, fuzzy, python-format msgid "Error during sync (%s)" msgstr "Помилка під час синхронізації" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Синхронізація з Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:285 #, fuzzy msgid "_Username:" msgstr "_Перейменувати" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:36 #, fuzzy msgid "Export as M3U / PLS Playlist File" msgstr "Імпортувати список програвання" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:144 #, fuzzy, python-format msgid "Writing to %s failed." msgstr "Не вдалося витягнути <b>%s</b>." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "_Оновити бібліотеку" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" #: quodlibet/ext/songsmenu/refresh.py:31 #, fuzzy msgid "Rescan songs" msgstr "_Оновити бібліотеку" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 #, fuzzy msgctxt "track/title" msgid "Track" msgstr "Трек" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 #, fuzzy msgid "Existing Tags" msgstr "Редагувати теги" #: quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Редагувати теги" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" #: quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Всі альбоми" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Попередній перегляд" #: quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Тег" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 #, fuzzy msgid "🥁 Tap BPM for the selected song." msgstr "Не вдалося видалити пісні" #: quodlibet/ext/songsmenu/website_search.py:36 #, fuzzy msgid "Website Search" msgstr "Пошук" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:82 #, fuzzy msgid "Search URL patterns" msgstr "шаблон" #: quodlibet/ext/songsmenu/website_search.py:92 #, fuzzy msgid "Edit search URLs" msgstr "Редагувати збережені параметри..." #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 #, fuzzy msgid "Configure Searches…" msgstr "_Виділяти кольором критерій пошуку" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "Редагувати теги" #: quodlibet/ext/songsmenu/wikipedia.py:110 #, fuzzy msgid "Search failed" msgstr "Пошук" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "Мітку „%s“ не знайдено." #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "Бібліотека" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "Перевірка точок монтування" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "Сканування бібліотеки" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "Сканування %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "" #: quodlibet/library/file.py:357 #, fuzzy msgid "Moving library files" msgstr "Сканування бібліотеки" #: quodlibet/library/file.py:415 #, fuzzy msgid "Removing library files" msgstr "Видалити фільтри активного переглядача" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/main.py:48 #, fuzzy msgid "Music player and music library manager" msgstr "музична бібліотека та програвач" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Список міток" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 #, fuzzy msgid "Also list programmatic tags" msgstr "Показувати _програмні теги" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 #, fuzzy msgid "Description" msgstr "опис" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "Значення" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "" #: quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Редактор аудіо-тегів" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "" #: quodlibet/operon/commands.py:260 #, fuzzy msgid "No changes detected" msgstr "Не вибрано жодної пісні" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "Вилучити мітки" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "Значення є регулярним виразом" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "Вилучити всі мітки" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Не можливо вилучити {tagname} з {filename}" #: quodlibet/operon/commands.py:382 #, fuzzy msgid "Remove a tag value" msgstr "Фільтрувати за тегом" #: quodlibet/operon/commands.py:431 #, fuzzy msgid "Add a tag value" msgstr "Фільтрувати за тегом" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:459 #, fuzzy msgid "List file information" msgstr "Немає інформації про час" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:518 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Не вдалося перейменувати файл" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Файл" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:771 #, fuzzy msgid "Display help information" msgstr "Вивести коротку інформацію з користування" #: quodlibet/operon/util.py:41 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> не є правильною адресою." #: quodlibet/order/__init__.py:34 #, fuzzy msgid "_Unknown" msgstr "Невідомо" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "По порядку" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "_По порядку" #: quodlibet/order/reorder.py:22 #, fuzzy msgid "Random" msgstr "_Випадково" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "_Випадково" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/reorder.py:40 #, fuzzy msgid "Prefer _higher rated" msgstr "востаннє відтворено" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "" #: quodlibet/order/repeat.py:57 #, fuzzy msgid "Repeat all" msgstr "_Повторювати" #: quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat _all" msgstr "_Повторювати" #: quodlibet/order/repeat.py:73 #, fuzzy msgid "One song" msgstr "Одна пісня" #: quodlibet/order/repeat.py:74 #, fuzzy msgid "One _song" msgstr "Одна пісня" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "Потік" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "Буферизація" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, fuzzy, python-format msgid "%.1f s" msgstr "%.1f дБ" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "" #: quodlibet/player/gstbe/util.py:148 #, fuzzy, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "Станцій не знайдено" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, fuzzy msgid "Unable to create audio output" msgstr "Не вдалося створити каталог" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:356 #, fuzzy msgid "ListenBrainz Submission" msgstr "Надсилання" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:455 #, fuzzy msgid "User _token:" msgstr "_Назва:" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 #, fuzzy msgid "_Run Plugin" msgstr "_Розширення" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "Використання" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Початок" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "Немає" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "Час" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "Назва закладки" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "ХХ:СС" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "Закладки" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Фільтри" #: quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "Що _ніколи не відтворювались" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 _кращих" #: quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Нова станція" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "Випадковий _жанр" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Випадковий _виконавець" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "Випадковий _альбом" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "" "40 пісень, що відтворювались найчастіше (може бути вибрано більше 40,якщо є " "пісні, що відтворювались однакову кількість разів)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "_Назва:" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "_Значення:" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "Збережені значення" #: quodlibet/qltk/cbes.py:265 #, fuzzy msgid "Edit saved values…" msgstr "Редагувати збережені параметри..." #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "" #: quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Track Mode" msgstr "_Трек" #: quodlibet/qltk/controls.py:114 #, fuzzy msgid "_Album Mode" msgstr "_Альбом" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "" #: quodlibet/qltk/controls.py:129 #, fuzzy msgid "_Replay Gain Mode" msgstr "Корегування гучності Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:216 #, fuzzy msgid "(unknown)" msgstr "Невідомо" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 #, fuzzy msgid "_Add…" msgstr "_Додати" #: quodlibet/qltk/data_editors.py:319 #, fuzzy msgid "_Edit" msgstr "_Змінити зовнішній вигляд..." #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:396 #, fuzzy msgid "Enter new tag" msgstr "Фільтрувати за тегом" #: quodlibet/qltk/data_editors.py:406 #, fuzzy msgid "Edit tag expression" msgstr "Значення є регулярним виразом" #: quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Файли" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:91 #, fuzzy msgid "_Delete Files" msgstr "Видалення фалів" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Перемістити в Trash" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "Перенесення %d/%d." #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Не вдалося зберегти базу iPod" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Не вдалося витягнути <b>%s</b>." #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Видалення %d/%d." #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Не вдалося видалити файл" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Не вдалося видалити <b>%s</b>." #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Browser" msgstr "Вибір пісень" #: quodlibet/qltk/download.py:36 #, fuzzy msgid "Downloading files" msgstr "Завантажити файли" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "відсутнє у %d пісні" msgstr[1] "відсутнє у %d пісень" msgstr[2] "відсутнє у %d пісень" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "різне у %d пісні" msgstr[1] "різне у %d пісень" msgstr[2] "різне у %d пісень" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "_Розділити на кілька значень" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "Відділити номер диску від альбому" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "Відділити _версію від назви" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "Відділити аранжувальника від _виконавця" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "Відділити поле \"виконавець \" від поля \"артист\"" #: quodlibet/qltk/edittags.py:312 #, fuzzy msgid "Split _Performer out of Title" msgstr "Відділити поле \"виконавець \" від поля \"артист\"" #: quodlibet/qltk/edittags.py:318 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Відділити _версію від назви" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "Додати тег" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "_Тег" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "Показувати _програмні теги" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #: quodlibet/qltk/edittags.py:534 #, fuzzy msgid "Show _multi-line tags" msgstr "Показувати _програмні теги" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Ніколи" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "_Зберегти" #: quodlibet/qltk/edittags.py:713 #, fuzzy msgid "_Configure" msgstr "_Продовжити" #: quodlibet/qltk/edittags.py:728 #, fuzzy msgid "_Split Tag" msgstr "Редагувати теги" #: quodlibet/qltk/edittags.py:737 #, fuzzy msgid "_Copy Value(s)" msgstr "Копіювати обкладинки _альбомів" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "Не вдалося додати тег" #: quodlibet/qltk/edittags.py:769 #, fuzzy, python-format msgid "Unable to add %s" msgstr "Не вдається додати пісні" #: quodlibet/qltk/edittags.py:771 #, fuzzy, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "" "Не вдалося додати <b>%s</b>\n" "\n" "Вибрані файли не підтримують множинні значення." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 #, fuzzy msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "Неправильний тег" msgstr[1] "Неправильний тег" msgstr[2] "Неправильний тег" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, fuzzy, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "Неправильний тег <b>%s</b>\n" "\n" "Вибрані файли не підтримують редагування цього тега." msgstr[1] "" "Неправильний тег <b>%s</b>\n" "\n" "Вибрані файли не підтримують редагування цього тега." msgstr[2] "" "Неправильний тег <b>%s</b>\n" "\n" "Вибрані файли не підтримують редагування цього тега." #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "Неправильне значення" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, fuzzy, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "Неправильне значення: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "Тег може бути невірним" #: quodlibet/qltk/_editutils.py:34 #, fuzzy, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "<b>%s</b> змінився, поки ви працювали. Збереження змін без оновлення " "бібліотеки може призвести до перезапису інших змін. \n" "\n" "Зберегти пісню незважаючи на це?" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "Не вдалося зберегти пісню" #: quodlibet/qltk/_editutils.py:53 #, fuzzy, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "Не вдалося зберегти <b>%s</b>. Можливо, файл відкритий тільки для читання, " "зіпсовано, або у вас недостатньо прав на його зміну." #: quodlibet/qltk/_editutils.py:144 #, fuzzy msgid "_More options…" msgstr "_Додаткові параметри..." #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "_Про програму" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "_Розширення" #: quodlibet/qltk/exfalsowindow.py:266 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s та %(count)d інших" msgstr[1] "%(title)s та %(count)d інших" msgstr[2] "%(title)s та %(count)d інших" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Налаштування Ex Falso" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "Каталоги" #: quodlibet/qltk/filesel.py:254 #, fuzzy msgid "_New Folder…" msgstr "Створення каталогу" #: quodlibet/qltk/filesel.py:263 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Вибрати всі підкаталоги" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "Створення каталогу" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "Введіть назву нового каталоги" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "Не вдалося створити каталог" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "Не вдалося видалити каталог" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "Пісні" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "%s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "Диск %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "Трек %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:114 #, fuzzy msgid "_Edit Display…" msgstr "Змінити зовнішній вигляд" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "Не вибрано жодної пісні" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "Немає пісень" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "Інформація" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Текст пісні" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "Продюсер: %s" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "артист" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "виконавці" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "виконавці" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Ніколи" #: quodlibet/qltk/information.py:238 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d раз" msgstr[1] "%d рази" msgstr[2] "%d разів" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "доданий" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "востаннє відтворено" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "відтворень" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "перервано" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "рейтинг" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "шлях" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "тривалість" #: quodlibet/qltk/information.py:291 #, fuzzy msgid "format" msgstr "Інформація" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "кодек" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 #, fuzzy msgid "encoding" msgstr "[Неправильне кодування]" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "бітрейт" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "розмір файлу" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "змінено" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d вибрано" msgstr[1] "%d вибрано" msgstr[2] "%d вибрано" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "Трек недоступний" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d пісня з невказаним альбомом" msgstr[1] "%d пісні з невказаним альбомом" msgstr[2] "%d пісень з невказаним альбомом" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "Вибрані альбоми" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d пісня з невказаним виконавцем" msgstr[1] "%d пісні з невказаним виконавцем" msgstr[2] "%d пісень з невказаним виконавцем" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "альбоми" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "Загальна тривалість:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "Загальний розмір:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "Файли" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "Для цієї пісні текст не знайдено." #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "Скасувати зміни в тегу?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Теги було змінено, але зміни не були збережені. Зберегти їх чи повернути " "зміни?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 #, fuzzy msgid "_Revert" msgstr "Ніколи" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "Файл існує" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:116 #, fuzzy msgid "_Replace File" msgstr "Перейменувати файли" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:258 #, fuzzy msgid "Toggle shuffle mode" msgstr "Перемикнути режим програвання/паузи" #: quodlibet/qltk/playorder.py:274 #, fuzzy msgid "Toggle repeat mode" msgstr "Перемикнути режим програвання/паузи" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:39 #, fuzzy msgid "Play Order" msgstr "_Порядок:" #: quodlibet/qltk/pluginwin.py:40 #, fuzzy msgid "Editing" msgstr "Редагування тегів" #: quodlibet/qltk/pluginwin.py:41 #, fuzzy msgid "Renaming" msgstr "_Перейменувати" #: quodlibet/qltk/pluginwin.py:42 #, fuzzy msgid "Querying" msgstr "запит" #: quodlibet/qltk/pluginwin.py:44 #, fuzzy msgid "Covers" msgstr "Загальний розмір:" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "Помилки розширень" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:147 #, fuzzy msgid "Disabled" msgstr "Вимкнути переглядач" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:186 #, fuzzy msgid "Any category" msgstr "Без категорії" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "Розширень не знайдено" #: quodlibet/qltk/pluginwin.py:376 #, fuzzy msgid "Plugins" msgstr "_Розширення" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "_Помилки" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "_Диск" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "_Номер треку" #: quodlibet/qltk/prefs.py:51 #, fuzzy msgid "Grou_ping" msgstr "групування" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "_Виконавець" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "_Альбом" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "Назва _файлу" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "_Тривалість" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "" "Автоматично переходити _до відтворюваної \n" "пісні" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "При зміні пісні переходити до неї в списку програвання" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "_Інші:" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 #, fuzzy msgid "_Edit…" msgstr "_Змінити зовнішній вигляд..." #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "Стовпець" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "Назва включає _версію" #: quodlibet/qltk/prefs.py:139 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Альбом включає _частину" #: quodlibet/qltk/prefs.py:140 #, fuzzy msgid "Artist includes all _people" msgstr "Назва включає _версію" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "Назва файлу включає _каталог" #: quodlibet/qltk/prefs.py:142 #, fuzzy msgid "Column Preferences" msgstr "Налаштування" #: quodlibet/qltk/prefs.py:145 #, fuzzy msgid "_Update Columns" msgstr "Стовпець" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Список пісень" #: quodlibet/qltk/prefs.py:246 #, fuzzy msgid "Edit Columns" msgstr "Стовпець" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "_Загальний фільтр" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Пошук" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Вибір пісень" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:319 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "При зміні пісні переходити до неї в списку програвання" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 #, fuzzy msgid "Ratings" msgstr "_Рейтинг" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "" #: quodlibet/qltk/prefs.py:360 #, fuzzy msgid "Album Art" msgstr "Список альбомів" #: quodlibet/qltk/prefs.py:393 #, fuzzy msgid "Playback" msgstr "Призупинити програвання" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:410 #, fuzzy msgid "_Fall-back gain:" msgstr "Приріст гучності (дБ):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:422 #, fuzzy msgid "_Pre-amp gain:" msgstr "Приріст гучності (дБ):" #: quodlibet/qltk/prefs.py:428 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Корегування гучності Replay Gain" #: quodlibet/qltk/prefs.py:445 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Корегування гучності Replay Gain" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:525 #, fuzzy msgid "Rating _scale:" msgstr "_Рейтинг" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Електронна пошта:" #: quodlibet/qltk/prefs.py:594 #, fuzzy msgid "Ratings and play counts will be saved in tags for this email address" msgstr "Рейтинги та лічильники програвань будуть прив'язані до цієї адреси" #: quodlibet/qltk/prefs.py:612 #, fuzzy msgid "_Auto-save tag changes" msgstr "Скасувати зміни в тегу?" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "" #: quodlibet/qltk/prefs.py:632 #, fuzzy msgid "Split _tag on:" msgstr "_Розділяти по:" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" #: quodlibet/qltk/prefs.py:650 #, fuzzy msgid "Split _subtag on:" msgstr "_Розділяти по:" #: quodlibet/qltk/prefs.py:660 #, fuzzy msgid "Tags" msgstr "Редагувати теги" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "Редагування тегів" #: quodlibet/qltk/prefs.py:681 #, fuzzy msgid "Updating for new ratings" msgstr "_Нова станція" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 #, fuzzy msgid "_Scan Library" msgstr "_Пошук бібліотекою" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "Перевірити наявність змін в бібліотеці" #: quodlibet/qltk/prefs.py:701 #, fuzzy msgid "Re_build Library" msgstr "_Перезавантажити бібліотеку" #: quodlibet/qltk/prefs.py:704 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Перезавантажити всі пісні в бібліотеці (це може зайняти багато часу)" #: quodlibet/qltk/prefs.py:719 #, fuzzy msgid "Hidden Songs" msgstr "Немає пісень" #: quodlibet/qltk/prefs.py:727 #, fuzzy msgid "Scan library _on start" msgstr "_Оновити бібліотеку" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "" #: quodlibet/qltk/prefs.py:742 #, fuzzy msgid "Scan Directories" msgstr "_Сканувати каталоги" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, fuzzy, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s та %(count)d інших" msgstr[1] "%(title)s та %(count)d інших" msgstr[2] "%(title)s та %(count)d інших" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Властивості" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "_Черга" #: quodlibet/qltk/queue.py:130 #, fuzzy msgid "Clear Queue" msgstr "_Очистити помилки" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:151 #, fuzzy msgid "Remove songs from the queue after playing them" msgstr "Видалити всі пісні з черги" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:167 #, fuzzy msgid "Mode" msgstr "Модель:" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d пісня (%(time)s)" msgstr[1] "%(count)d пісні (%(time)s)" msgstr[2] "%(count)d пісень (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "_Переглянути бібліотеку" #: quodlibet/qltk/quodlibetwindow.py:349 #, fuzzy msgid "Toggle queue visibility" msgstr "Показати/сховати головне вікно" #: quodlibet/qltk/quodlibetwindow.py:377 #, fuzzy msgid "Playback Error" msgstr "Призупинити програвання" #: quodlibet/qltk/quodlibetwindow.py:385 #, fuzzy msgid "Set up library directories?" msgstr "Вибір каталогів" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "Не вдається додати пісні" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> використовує протокол, що не підтримується." #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "_Перейти до відтворюваної пісні" #: quodlibet/qltk/quodlibetwindow.py:891 #, fuzzy msgid "_File" msgstr "Файл" #: quodlibet/qltk/quodlibetwindow.py:892 #, fuzzy msgid "_Song" msgstr "Пісні" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "_Вигляд" #: quodlibet/qltk/quodlibetwindow.py:894 #, fuzzy msgid "_Browse" msgstr "Вибір пісень" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "_Керування" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "_Довідка" #: quodlibet/qltk/quodlibetwindow.py:902 #, fuzzy msgid "_Add a Folder…" msgstr "_Додати каталог..." #: quodlibet/qltk/quodlibetwindow.py:907 #, fuzzy msgid "_Add a File…" msgstr "_Додати файл..." #: quodlibet/qltk/quodlibetwindow.py:912 #, fuzzy msgid "_Add a Location…" msgstr "Додати адресу" #: quodlibet/qltk/quodlibetwindow.py:941 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Редагувати закладки..." #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:966 #, fuzzy msgid "Stop After This Song" msgstr "Зупинитись після цієї пісні" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:990 #, fuzzy msgid "Search Help" msgstr "Пошук" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "Додати адресу" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "Введіть адресу аудіо-файлу:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "Не вдалося додати адресу" #: quodlibet/qltk/quodlibetwindow.py:1309 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> не є правильною адресою." #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "Додати музику" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 #, fuzzy msgid "_Add Folders" msgstr "_Додати каталог..." #: quodlibet/qltk/quodlibetwindow.py:1328 #, fuzzy msgid "Music Files" msgstr "Музичний програвач" #: quodlibet/qltk/quodlibetwindow.py:1330 #, fuzzy msgid "_Add Files" msgstr "_Додати файл..." #: quodlibet/qltk/quodlibetwindow.py:1421 #, fuzzy, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "Ви дійсно хочете видалити список відтворення '%s'?" msgstr[1] "Ви дійсно хочете видалити список відтворення '%s'?" msgstr[2] "Ви дійсно хочете видалити список відтворення '%s'?" #: quodlibet/qltk/quodlibetwindow.py:1431 #, fuzzy msgid "_Enqueue" msgstr "_Черга" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 #, fuzzy msgid "_Remove Rating" msgstr "_Рейтинг" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "" #: quodlibet/qltk/ratingsmenu.py:34 #, fuzzy msgid "Change _Rating" msgstr "_Рейтинг" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "Замінити пробіли на підкреслення" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "Замінити _Windows-несумісні символи" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "Замінити _діакритичні знаки" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "Замінити не-_ASCII символи" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "Перейменувати файли" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Попередній перегляд" #: quodlibet/qltk/renamefiles.py:198 #, fuzzy msgid "File names" msgstr "Назва файлу" #: quodlibet/qltk/renamefiles.py:208 #, fuzzy msgid "_Move album art" msgstr "автор альбому" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "" #: quodlibet/qltk/renamefiles.py:224 #, fuzzy msgid "_Remove empty directories" msgstr "_Видалити невикористовувані обкладинки та каталоги" #: quodlibet/qltk/renamefiles.py:230 #, fuzzy msgid "Album art" msgstr "Список альбомів" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "Нова назва" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "Не вдалося перейменувати файл" #: quodlibet/qltk/renamefiles.py:338 #, fuzzy, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "Не вдалося перейменувати <b>%s</b> на <b>%s</b>. Можливо, цільовий файл вже " "існує, або ви не маєте прав для створення нового чи видалення старого файлу." #: quodlibet/qltk/renamefiles.py:346 #, fuzzy msgid "Ignore _All Errors" msgstr "_Помилки" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "_Продовжити" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "Неабсолютний шлях" #: quodlibet/qltk/renamefiles.py:464 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "містить /, але починається не з кореневого каталогу. Для запобігання помилок " "в назвах каталогів, почніть шаблон з кореневого каталогу." #: quodlibet/qltk/scanbox.py:49 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Пісні, розташовані в цих каталогах (розділені ':'), будуть додані до " "бібліотеки" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "" #: quodlibet/qltk/scanbox.py:115 #, fuzzy, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "W: видалення 'самотнього' треку iPod" #: quodlibet/qltk/scanbox.py:116 #, fuzzy msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "Бібліотека" msgstr[1] "Бібліотека" msgstr[2] "Бібліотека" #: quodlibet/qltk/scanbox.py:117 #, fuzzy msgid "Remove" msgstr "_Рейтинг" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "Вибір каталогів" #: quodlibet/qltk/scanbox.py:139 #, fuzzy msgid "Select This Directory" msgstr "Вибір каталогів" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Saved Searches" msgstr "Збережені значення" #: quodlibet/qltk/searchbar.py:59 #, fuzzy msgid "Edit saved searches…" msgstr "Редагувати збережені параметри..." #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:145 #, fuzzy msgid "Search after _typing" msgstr "Зупинитись після цієї пісні" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "_Обмеження:" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "За _оцінками" #: quodlibet/qltk/searchbar.py:356 #, fuzzy msgid "Add query" msgstr "запит" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Відображати час, що лишився" #: quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Текст пісні" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "" #: quodlibet/qltk/shortcuts.py:19 #, fuzzy msgid "Focus the search entry" msgstr "Помістити фокус на вікно Quod Libet" #: quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Переміститись всередині відтворюваної пісні" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "" #: quodlibet/qltk/shortcuts.py:28 #, fuzzy msgid "Queue the selected songs" msgstr "Не вдалося видалити пісні" #: quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Не вдалося видалити пісні" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "_Фільтрувати по %s" #: quodlibet/qltk/songlist.py:1193 #, fuzzy msgid "All _Headers" msgstr "_Альбом" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "_Трек" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "_Альбом" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "_Люди" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "_Дата" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "_Файл" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "_Виробництво" #: quodlibet/qltk/songlist.py:1214 #, fuzzy msgid "_Customize Headers…" msgstr "_Налаштувати заголовки..." #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:44 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "_Вилучити зі cписку програвання" #: quodlibet/qltk/songsmenu.py:47 #, fuzzy, python-format msgid "Remove %(count)d tracks from the library?" msgstr "_Вилучити зі cписку програвання" #: quodlibet/qltk/songsmenu.py:50 #, fuzzy msgid "Remove from Library" msgstr "_Вилучити зі cписку програвання" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:140 #, fuzzy msgid "Configure Plugins…" msgstr "_Виділяти кольором критерій пошуку" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "Додати до _черги" #: quodlibet/qltk/songsmenu.py:344 #, fuzzy msgid "_Remove from Library…" msgstr "_Вилучити зі cписку програвання" #: quodlibet/qltk/songsmenu.py:411 #, fuzzy msgid "Unable to show files" msgstr "Не вдалося видалити файл" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:436 #, fuzzy, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "_Завантажити" msgstr[1] "_Завантажити" msgstr[2] "_Завантажити" #: quodlibet/qltk/songsmenu.py:443 #, fuzzy msgid "successful" msgstr "Успішно" #: quodlibet/qltk/songsmenu.py:444 #, fuzzy msgid "failed" msgstr "Не вдалося зберегти" #: quodlibet/qltk/songsmenu.py:447 #, fuzzy msgid "Downloads complete" msgstr "Завантажити файл" #: quodlibet/qltk/songsmenu.py:453 #, fuzzy msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "Список альбомів" msgstr[1] "Список альбомів" msgstr[2] "Список альбомів" #: quodlibet/qltk/songsmenu.py:459 #, fuzzy msgid "Download here" msgstr "Завантажити файл" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Замінити підкреслення на пробіл" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "Замінити першу букву кожного слова великою" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "_Розділити на кілька значень" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "Теги з імен файлів" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "Теги замінять існуючі" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "Теги будуть додані до існуючих" #: quodlibet/qltk/tagsfrompath.py:194 #, fuzzy, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "є недопустимим. Можливо, він містить незакриті лапки (< / >) або " "повторений двічі тег." #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "Введений вами шаблон є невірним. Переконайтесь, що ви ввели < та > як " "\\< и \\>, а також що відкриті теги вже закриті.\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "Змінити зовнішній вигляд" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "Номери треків" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "Починати _з:" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "_Всього треків:" #: quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Програвач" #: quodlibet/qltk/unity.py:72 #, fuzzy msgid "Previous" msgstr "_Попередній перегляд" #: quodlibet/qltk/views.py:935 #, fuzzy, python-format msgid "and %d more…" msgstr "%d інших..." #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "Збереження змінених вами пісень." #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Перенесення %d/%d." #: quodlibet/update.py:90 #, fuzzy msgid "Checking for Updates" msgstr "Перевірка точок монтування" #: quodlibet/update.py:125 #, fuzzy msgid "Connection failed" msgstr "місце запису" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" #: quodlibet/util/collection.py:347 #, fuzzy msgid "Empty Playlist" msgstr "Імпортувати список програвання" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:649 #, fuzzy, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "Список програвання %s вже існує." #: quodlibet/util/cover/built_in.py:38 #, fuzzy msgid "Embedded album covers" msgstr "Показувати _обкладинки альбомів" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "" #: quodlibet/util/cover/built_in.py:61 #, fuzzy msgid "Filesystem cover" msgstr "Файлова система" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: quodlibet/util/cover/manager.py:230 #, fuzzy msgid "Cover Art" msgstr "Загальний розмір:" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "Вивести коротку інформацію з користування" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "Вивести версію та інформацію про авторські права" #: quodlibet/util/__init__.py:81 #, fuzzy msgid "Print debugging information" msgstr "Немає інформації про час" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[параметри]" #: quodlibet/util/__init__.py:167 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Невідомий параметр '%s'" #: quodlibet/util/__init__.py:170 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Параметр '%s' вимагає аргументу." #: quodlibet/util/__init__.py:173 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' неоднозначний" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d Кбіт/с" #: quodlibet/util/__init__.py:408 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" msgstr[2] "%d секунд" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "Немає інформації про час" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" msgstr[2] "%d секунд" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d хвилина" msgstr[1] "%d хвилини" msgstr[2] "%d хвилин" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d година" msgstr[1] "%d години" msgstr[2] "%d годин" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d день" msgstr[1] "%d дні" msgstr[2] "%d днів" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d рік" msgstr[1] "%d роки" msgstr[2] "%d років" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "check|titlecase?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Дату слід вводити в форматі 'РРРР', 'РРРР-ММ-ДД' або 'РРРР-ММ-ДД ГГ:ХХ:СС'" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Підсилення Replay Gain слід вводити в форматі 'x.yy dB'." #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Піки Replay Gain слід вводити в форматі 'x.yy'" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "" "Ідентифікатори MusicBrainz повинні бути в форматі UUID (унікальний " "ідентифікатор)." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Статус випуску MusicBrainz повинен бути 'official', 'promotional', або ж " "'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: quodlibet/util/songwrapper.py:112 #, fuzzy, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "Не вдалося зберегти" msgstr[1] "Не вдалося зберегти" msgstr[2] "Не вдалося зберегти" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "Не вдалося редагувати пісню" #: quodlibet/util/songwrapper.py:122 #, fuzzy, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "Не вдалося зберегти <b>%s</b>. Можливо, файл відкритий тільки для читання, " "зіпсовано, або у вас недостатньо прав на його зміну." #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[Неправильне кодування]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "альбом" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "аранжувальник" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "аранжувальники" #: quodlibet/util/tags.py:84 #, fuzzy msgid "arrangement" msgstr "аранжувальник" #: quodlibet/util/tags.py:86 msgid "author" msgstr "автор" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "автори" #: quodlibet/util/tags.py:87 #, fuzzy msgid "comment" msgstr "команда|тег" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "композитор" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "композитори" #: quodlibet/util/tags.py:88 #, fuzzy msgid "composition" msgstr "композитор" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "диригент" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "диригенти" #: quodlibet/util/tags.py:90 #, fuzzy msgid "conducting" msgstr "диригент" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "зв'язок" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "авторське право" #: quodlibet/util/tags.py:93 msgid "date" msgstr "дата" #: quodlibet/util/tags.py:94 msgid "description" msgstr "опис" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "жанр" #: quodlibet/util/tags.py:95 #, fuzzy msgid "genres" msgstr "жанр" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "виконавець" #: quodlibet/util/tags.py:96 #, fuzzy msgid "performance" msgstr "виконавець" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "групування" #: quodlibet/util/tags.py:98 msgid "language" msgstr "мова" #: quodlibet/util/tags.py:99 msgid "license" msgstr "ліцензія" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "автор слів" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "автори слів" #: quodlibet/util/tags.py:101 #, fuzzy msgid "lyrics" msgstr "автор слів" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "організація" #: quodlibet/util/tags.py:104 msgid "title" msgstr "назва" #: quodlibet/util/tags.py:105 msgid "version" msgstr "версія" #: quodlibet/util/tags.py:106 msgid "website" msgstr "вебсайт" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "автор альбому" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "ударів на хвилину" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "диск" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "трек" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "ID видавця" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "оригінальна дата випуску" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "оригінальний альбом" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "оригінальний виконавець" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "дата запису" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "країна випуску" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 #, fuzzy msgid "MusicBrainz recording ID" msgstr "Ідентифікатор треку MusicBrainz" #: quodlibet/util/tags.py:132 #, fuzzy msgid "MusicBrainz release track ID" msgstr "Ідентифікатор треку MusicBrainz" #: quodlibet/util/tags.py:133 #, fuzzy msgid "MusicBrainz release ID" msgstr "Ідентифікатор треку MusicBrainz" #: quodlibet/util/tags.py:134 #, fuzzy msgid "MusicBrainz artist ID" msgstr "Ідентифікатор виконавця MusicBrainz" #: quodlibet/util/tags.py:135 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "Ідентифікатор треку MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "Ідентифікатор TRM MusicBrainz" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "Статус альбому MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "Тип альбому MusicBrainz" #: quodlibet/util/tags.py:140 #, fuzzy msgid "MusicBrainz release group ID" msgstr "Ідентифікатор треку MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "підсилення треку" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "пік треку" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "підсилення альбому" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "пік альбому" #: quodlibet/util/tags.py:148 #, fuzzy msgid "reference loudness" msgstr "Налаштування" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "диски" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "треки" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "востаннє запущено" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "повна назва" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "точка монтування" #: quodlibet/util/tags.py:166 msgid "people" msgstr "люди" #: quodlibet/util/tags.py:168 msgid "year" msgstr "рік" #: quodlibet/util/tags.py:169 #, fuzzy msgid "original release year" msgstr "оригінальна дата випуску" #: quodlibet/util/tags.py:170 #, fuzzy msgid "bookmark" msgstr "Закладки" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "" #: quodlibet/util/tags.py:174 #, fuzzy msgid "file format" msgstr "формат" #: quodlibet/util/tags.py:177 #, fuzzy msgid "playlists" msgstr "Списки програвання" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Редактор аудіо-тегів" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "Програма для редагування тегів аудіо-файлів" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #, fuzzy msgid "Quod Libet" msgstr "Вийти з Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Музичний програвач" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "Програма для прослуховування і керування аудіо-колекцією" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "До підтримуваних форматів файлів входять Ogg Vorbis/Opus/Speex/FLAC, MP3, " "FLAC, MOD/XM/IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, " "MIDI." #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet — це програма керування музикою. Вона надає різні способи для " "перегляду вашої авдіо-бібліотеки, а також підтримку Інтернет-радіо та авдіо-" "підписки. Також має надзвичайно гнучкі можливості для редагування та пошуку " "міток метаданих." #, fuzzy #~ msgid "Export to Sonos playlist" #~ msgstr "Імпортувати список програвання" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "Не вдалося додати пісню" #~ msgid "Invalid tags" #~ msgstr "Неправильні теги" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "Недопустимі теги <b>%s</b>\n" #~ "\n" #~ "Вибрані файли не підтримують редагування цих тегів." #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d секунда" #, fuzzy #~ msgid "Startup" #~ msgstr "_Імпортувати" #~ msgid "Audio Feeds" #~ msgstr "Авідо-стрічки" #~ msgid "_Audio Feeds" #~ msgstr "_Авдіо-стрічки" #~ msgid "New" #~ msgstr "Новий" #~ msgid "Automatic Library Update" #~ msgstr "Автоматичне оновлення бібліотеки" #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "" #~ "Дозволяє керувати Quod Libet через специфікацію інтерфейса MPRIS 2 D-Bus." #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "Пошук тексту пісні..." #~ msgid "<artist>" #~ msgstr "<виконавець>" #~ msgid "<album>" #~ msgstr "<альбом>" #~ msgid "<title>" #~ msgstr "<назва>" #~ msgid "OK" #~ msgstr "Гаразд" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "Імпортувати список програвання" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "Імпортувати список програвання" #~ msgid "_Copy" #~ msgstr "_Копіювати" #~ msgid "_Paste" #~ msgstr "_Вставити" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "Інформація" #~ msgid "Unsupported file type" #~ msgstr "Непідтримуваний тип файлу" #~ msgid "Unable to add station" #~ msgstr "Не вдалося додати станцію" #~ msgid "Device Properties" #~ msgstr "Властивості пристрою" #~ msgid "Device:" #~ msgstr "Пристрій:" #~ msgid "Not mounted" #~ msgstr "Не змонтовано" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Точка монтування:" #~ msgid "Media Devices" #~ msgstr "Медіа-пристрої:" #~ msgid "_Media Devices" #~ msgstr "_Медіа-пристрої" #~ msgid "_Eject" #~ msgstr "_Витягнути" #, fuzzy #~ msgid "_Properties" #~ msgstr "Властивості" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> використано, <b>%s</b> наявно" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> не під'єднано" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Копіювання <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "Не вдалося скопіювати пісню" #~ msgid "There is not enough free space for this song." #~ msgstr "Недостатньо вільного місця для цієї пісні." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> не може бути скопійовано." #~ msgid "Unable to delete songs" #~ msgstr "Не вдалося видалити пісні" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Видалення <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> не може бути видалений." #~ msgid "Unable to delete song" #~ msgstr "Не вдалося видалити пісню" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Не вдалося витягнути <b>%s</b>." #~ msgid "Unable to eject device" #~ msgstr "Не вдалося витягнути пристрій" #~ msgid "Search Library" #~ msgstr "Пошук в бібліотеці" #~ msgid "_Search Library" #~ msgstr "_Пошук бібліотекою" #~ msgid "Rate the playing song" #~ msgstr "Оцінити відтворювану пісню" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Показати/сховати список пісень" #~ msgid "Unknown Device" #~ msgstr "Невідомий пристрій" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "E: '%s' неоднозначний" #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "Неправильне значення" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "_Шаблон назви файлу:" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Очистити помилки" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Текст пісні" #, fuzzy #~ msgid "Alternate search" #~ msgstr "Очистити поле пошуку" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Текст пісні" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Текст пісні" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "Немає пісень" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Вибір пісень" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Не вдалося створити каталог" #~ msgid "Audio device: %s" #~ msgstr "Аудіо-пристрій: %s" #~ msgid "Downloads" #~ msgstr "Завантаження" #~ msgid "Size" #~ msgstr "Розмір" #~ msgid "_Download" #~ msgstr "_Завантажити" #~ msgid "_Copy to Device" #~ msgstr "_Копіювати до пристрою" #, fuzzy #~ msgid "browsers" #~ msgstr "Вибір пісень" #~ msgid "Unable to download lyrics." #~ msgstr "Не вдалося завантажити текст пісні." #~ msgid "Set or toggle the playback order" #~ msgstr "Перемикнути порядок програвання" #~ msgid "Uninitialized iPod" #~ msgstr "Неініціалізований iPod" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "Бажаєте створити порожню базу на цьому iPod?" #~ msgid "_Volume Gain (dB):" #~ msgstr "Приріст гучності (дБ):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Комбінувати теги з _різними значеннями" #~ msgid "Capacity:" #~ msgstr "Ємність:" #~ msgid "Firmware:" #~ msgstr "Мікропрограми:" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "Не вдалося зберегти базу iPod" #~ msgid "Unable to save iPod database" #~ msgstr "Не вдалося зберегти базу iPod" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "пік треку" #~ msgid "Shuffle" #~ msgstr "Випадково" #~ msgid "Weighted" #~ msgstr "За оцінками" #~ msgid "_Weighted" #~ msgstr "_За оцінками" #~ msgid "_One Song" #~ msgstr "_Одна пісня" #~ msgid "Restart the playlist when finished" #~ msgstr "Почати спочатку після програвання всіх пісень" #~ msgid "Disable Browser" #~ msgstr "Вимкнути переглядач" #~ msgid "_Disable Browser" #~ msgstr "_Вимкнути переглядач" #, fuzzy #~ msgid "Force Write" #~ msgstr "Записати" #~ msgid "Filter on _Genre" #~ msgstr "Фільтрувати за _жанром" #~ msgid "Filter on _Artist" #~ msgstr "Фільтрувати за _виконавцем" #~ msgid "Filter on Al_bum" #~ msgstr "Фільтрувати за _альбомом" #~ msgid "_Music" #~ msgstr "_Музика" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Закладки" #~ msgid "Song _List" #~ msgstr "Список пісень" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "Зупинитись після цієї пісні" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "%d інших..." #~ msgstr[1] "%d інших..." #~ msgstr[2] "%d інших..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Відділити номер диску від альбому" #, fuzzy #~ msgid "Timeout" #~ msgstr "Час" #, fuzzy #~ msgid "Select an album" #~ msgstr "Вибрати _все" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s та %(count)d інших" #~ msgstr[1] "%(title)s та %(count)d інших" #~ msgstr[2] "%(title)s та %(count)d інших" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Списки програвання" #~ msgid "Re_fresh Library" #~ msgstr "_Оновити бібліотеку" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Рейтинг" #, fuzzy #~ msgid "Unable to open input files" #~ msgstr "Не вдалося відкрити файл" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "Неправильне значення" #, fuzzy #~ msgid "ql-revert" #~ msgstr "_Видалити з бібліотеки" #~ msgid "command|filename" #~ msgstr "команда|назва файлу" #~ msgid "command|tag" #~ msgstr "команда|тег" #, fuzzy #~ msgid "heading|Search" #~ msgstr "Пошук" #~ msgid "%d of %d" #~ msgstr "%d з %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "Використання: %s %s" #~ msgid "_Download..." #~ msgstr "_Завантажити..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "_Нова станція" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "Перезаписати <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet вже запущено." #~ msgid "No song is currently playing." #~ msgstr "На даний момент програвання не відбувається." #~ msgid "Unable to write to %s. Removing it." #~ msgstr "Запис в %s не є можливим, файл буде видалено." #~ msgid "_Edit Bookmarks..." #~ msgstr "_Редагувати закладки..." #~ msgid "_New Folder..." #~ msgstr "_Створити каталог..." #~ msgid "_Add to Playlist" #~ msgstr "_Додати до списку програвання" #~ msgid "_Edit Display..." #~ msgstr "_Змінити зовнішній вигляд..." #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d станція" #~ msgid "_Add a Location..." #~ msgstr "_Додати адресу..." #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "_Налаштувати заголовки..." #, fuzzy #~ msgid "Track Headers" #~ msgstr "_Трек" #, fuzzy #~ msgid "People Headers" #~ msgstr "_Люди" #, fuzzy #~ msgid "Album Headers" #~ msgstr "_Альбом" #, fuzzy #~ msgid "Date Headers" #~ msgstr "_Дата" #, fuzzy #~ msgid "File Headers" #~ msgstr "_Файл" #, fuzzy #~ msgid "Production Headers" #~ msgstr "_Виробництво" #, fuzzy #~ msgid "Tag:" #~ msgstr "_Тег" #, fuzzy #~ msgid "Warnings" #~ msgstr "_Рейтинг" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "автор альбому" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "виконавці" #, fuzzy #~ msgid "album (sort)" #~ msgstr "автор альбому" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "виконавці" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "виконавці" #~ msgid "MusicBrainz album artist ID" #~ msgstr "Ідентифікатор альбому MusicBrainz" #~ msgid "errors" #~ msgstr "помилки" #~ msgid "Permanently delete this file?" #~ msgstr "Назавжди видалити цей файл?" #~ msgid "Permanently delete these files?" #~ msgstr "Назавжди видалити ці файли?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s та %(count)d інших..." #~ msgstr[1] "%(title)s та %(count)d інших..." #~ msgstr[2] "%(title)s та %(count)d інших..." #, fuzzy #~ msgid "Version:" #~ msgstr "версія" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "_Очистити помилки" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "Не вдалося додати %s в бібліотеку.\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "Не знайдено команди для витягування" #~ msgid "Unable to start web browser" #~ msgstr "Не вдалося запустити веб-бровзер" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "Не вдалося знайти веб-бровзер. Присвойте змінній $BROWSER значення,або " #~ "переконайтесь, що /usr/bin/sensible-browser існує." #, fuzzy #~ msgid "Library Error" #~ msgstr "Перегляд бібліотеки" #, fuzzy #~ msgid "_Output device:" #~ msgstr "_Копіювати до пристрою" #~ msgid "translator-credits" #~ msgstr "Микола 'Cthulhu' Линник <pydefiner@gmail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "Інші стовпці до відображення, через пробіл" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "_Продовжити" #~ msgid "Search your library" #~ msgstr "Шукати в бібліотеці" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "Загальний розмір:" #~ msgid "Quod Libet Plugins" #~ msgstr "Розширення Quod Libet" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "" #~ "Виділяти простий пошук синім кольором, розширений - зеленим, неправильний " #~ "- червоним" #~ msgid "Separators for splitting tags" #~ msgstr "Символи розділення тегів" #~ msgid "Quod Libet Preferences" #~ msgstr "Налаштування Quod Libet" #~ msgid "Not Played To_day" #~ msgstr "Що не відтворювались _сьогодні" #~ msgid "Not Played in a _Week" #~ msgstr "Що не відтворювались _тиждень" #~ msgid "Not Played in a _Month" #~ msgstr "Що не відтворювались _місяць" #~ msgid "B_ottom 40" #~ msgstr "40 _гірших" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "" #~ "40 пісень, що відтворювались найрідше (може бути вибрано більше 40,якщо є " #~ "пісні, що відтворювались однакову кількість разів)" #, fuzzy #~ msgid "Date" #~ msgstr "_Дата" #~ msgid "Add" #~ msgstr "Додати" #, fuzzy #~ msgid "Bitrate" #~ msgstr "бітрейт" #~ msgid "_Stations..." #~ msgstr "_Станції..." #~ msgid "Unable to save library" #~ msgstr "Не вдалося зберегти бібліотеку" #~ msgid "Sort by title" #~ msgstr "За назвою" #~ msgid "Sort by artist" #~ msgstr "За виконавцем" #~ msgid "Lyrics provided by %s." #~ msgstr "Текст пісні наданий %s." #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "Текст пісні не знайдено.\n" #~ "\n" #~ "Ви можете натиснути кнопку Завантажити, щоб Quod Libet спробував знайти " #~ "текст пісні в Інтернеті. Також ви можете ввести текст самостійно, і потім " #~ "натиснути Зберегти." #~ msgid "part" #~ msgstr "частина" #~ msgid "Opening audio device." #~ msgstr "Відкриваю аудіо-пристрій" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d пісень збережено" #~ msgid "MusicBrainz album ID" #~ msgstr "Ідентифікатор альбому MusicBrainz" #~ msgid "Loaded song library." #~ msgstr "Бібліотеку пісень завантажено" #~ msgid "Unable to open audio device" #~ msgstr "Не вдалося відкрити аудіо-пристрої" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet спробував отримати доступ до драйверів 'autosink' та " #~ "'%(sink)s', але не зміг відкрити їх. Встановіть GStreamer pipeline, " #~ "змінивши рядок\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "в in ~/.quodlibet/config." #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet не зміг знайти елемент 'filesrc' GStramer. Перевірте вашу " #~ "інсталяцію GStramer." ���������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/zh_CN.po�������������������������������������������������������������������������0000644�0001750�0001750�00000723046�14470736246�014213� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Simplified Chinese (zh_CN) translation of Quod Libet. # Copyright (C) 2006 THE quodlibet'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # Emfox Zhou <EmfoxZhou@gmail.com>, 2006. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.21\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:48+0100\n" "PO-Revision-Date: 2023-06-28 08:47+0000\n" "Last-Translator: Eric <hamburger2048@users.noreply.hosted.weblate.org>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "quodlibet/quodlibet/zh_Hans/>\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=n<0;\n" "X-Generator: Weblate 4.18.1\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "标题(_T)" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "表演者(_P)" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "日期(_D)" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "添加日期" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "原始日期(_O)" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "流派(_G)" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "评分(_R)" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "播放次数(_C)" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "排序依据(_B) …" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "首选项(_P)" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "专辑列表" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "专辑列表(_A)" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "所有专辑" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d 专辑" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "重新加载专辑封面(_C)" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "不在专辑里的曲目" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d 音轨" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d 唱片" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "样例专辑" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "专辑列表首选项" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "显示专辑封面(_C)" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "搜索时包含 people 字段" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "选项" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "专辑显示" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "关闭(_C)" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "曲库浏览器" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d 首歌曲" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "非法参数" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "专辑集合" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "专辑集合(_C)" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "未知 %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "多个 %s 值" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "自定义(_C)" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "添加" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "删除 (_R)" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "标签" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "合并" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "专辑集合首选项" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "应用" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "取消" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "封面网格" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "封面网格(_C)" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "封面网格首选项" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "显示专辑文本(_T)" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "显示“所有专辑”项目" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "宽屏模式" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "封面放大" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "文件系统" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "文件系统(_F)" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "无法复制曲目" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "被选定的文件无法被复制到其它曲目列表或队列。" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "加入到曲库(_A)" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "站点列表只能包含站点的位置,不能包括其它的站点列表或播放列表。以下位置无法导" "入:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "网上广播" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "添加电台" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "正在下载电台列表" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "新站点" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "输入网上广播站点的位置:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "Electronic 电子乐" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "Hip Hop/Rap 嘻哈/说唱" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "Oldies 经典老歌" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B 节奏布鲁斯" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "Japanese 日系" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "Indian 印度" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "Religious 宗教" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "Charts 排行榜" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "Turkish 土耳其" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "Reggae/Dancehall 雷鬼/舞厅" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "拉丁" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "College Radio 校园电台" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "Talk/News 访谈/新闻" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "Ambient 氛围" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "Jazz 爵士" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Classical 古典" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop 流行" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "Alternative 另类" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "Metal 金属" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "Country 乡村" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "News 新闻" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "Schlager 德语流行" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "Funk 放克" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "Indie 独立" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "Blues 蓝调" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "Soul 灵魂乐" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "Lounge 休闲" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "朋克" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "Reggaeton 雷鬼舞曲" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "Slavic 斯拉夫语" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "Greek 希腊语" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "Gothic 哥特" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock 摇滚" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "你想现在就获取一份流行的电台列表吗?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "加载电台 (_L)" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "网上广播(_I)" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "所有电台" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "收藏夹" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "没有分类" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "添加电台(_A)…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "更新电台 (_U)" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "没有发现站点" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "没有在 %s 发现网络电台。" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "没有新源可添加" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "所有列出的站点都已经在您的曲库里。" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "加入收藏" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "从收藏中删除" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d 个电台" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "拼版式浏览器" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "分栏面板窗口" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "全选(_A)" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "未知" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "所有" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "小" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "宽" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "柱状" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "标签模式与可选的标记,例如 <tt>作曲家</tt> 或\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "分栏面板窗口设置" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "列布局" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "列内容" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "面板分栏等宽" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "播放列表" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "播放列表(_P)" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "从播放列表里删除(_R)" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "新建" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "导入(_I)…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "无法导入播放列表" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet 只能导入 M3U/M3U8 和 PLS 格式的播放列表。" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "删除(_D)" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "重命名(_R)" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "无法重命名播放列表" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "导入播放列表" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "导入(_I)" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "新播放列表(_N)…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "你想对这 %d 首歌做什么?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "确认播放列表 \"%s\" 的操作" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "空" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "播放列表示例" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "播放列表浏览器首选项" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "播放列表展示" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "确认删除播放列表 '%s' 吗?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "选中的播放列表即将被删除,并且无法复原。" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "使用 {num} 附加轨道扩展“{pl_name}”?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "添加曲目(_A)" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "新播放列表" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "输入新播放列表的名字:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "_创建" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "正在导入播放列表。\n" "\n" "已添加 %(current)d/%(total)d 首曲目。" #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "新的源" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "输入播客/音频源的位置:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "播客" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "_播客" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "添加源(_A)…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "刷新(_F)" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "搜索新节目源" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "_重建" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "删除所有现有剧集,然后从源代码重新加载" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "删除这个播客和它的剧集" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "无法加入源" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "%s 这个源无法添加。服务器可能宕机了,也可能这个地址并不是播客/音频源。" #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "目前的音频后端不支持 URL,音频源浏览器已禁用。" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "限制结果(_L)" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "允许多个查询(_A)" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "音轨列表" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "音轨列表(_T)" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud 浏览器" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Soundcloud 浏览器" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "搜索" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "我的音轨" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "前往 %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "已连接" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet 已连接,%s!" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "退出 %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "输入代码…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "登录 %s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "SoundCloud 登录验证" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "SoundCloud 验证码:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 没有在运行(使用 --run 参数来启动)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "一个曲库和播放器" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[选项]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "显示正在播放的曲目并退出" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "立即开始播放" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "启动时不显示任何窗口" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "跳到下一首曲目" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "跳到上一首曲目,或者重新播放当前曲目" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "跳到前一首曲目" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "开始回放" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "暂停回放" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "切换播放/暂停模式" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "结束回放" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "加大音量" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "减小音量" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "将正在播放歌曲的评分提高一星" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "将正在播放歌曲的评分降低一星" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "显示播放器状态" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "隐藏主窗口" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "显示主窗口" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "切换主窗口可见性" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "焦点移到运行中的播放器" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "移除浏览器过滤选项" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "刷新并重新扫描曲库" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "列出可用的浏览器" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "显示当前播放列表" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "显示队列内容" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "打印活动文本查询" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "不加载插件启动" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "如 Quod Libet 未在运行就启动它" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "退出 Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "在正在播放的曲目中定位" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "设置或切换随机播放模式" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "设置随机播放模式类型" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "开、关或切换重复播放" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "设置重复播放模式类型" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "设定音量" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "搜索您的曲库" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "查询" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "播放文件" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "文件名" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "设置播放中歌曲的评分" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "设定当前浏览器" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "当前歌曲结束后停止播放" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "打开新的浏览器" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "显示或隐藏队列" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "以随机值过滤" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "标签" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "以标签值过滤" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=value" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "将文件或查询结果加入队列" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "将CSV文件内容加入队列" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "文件名" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "将查询结果的文件名打印到标准输出设备" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "将文件或查询结果移出队列" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "添加文件或目录到曲库" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "位置" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "设置模版 --打印-* 命令" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "模式" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "%s 的无效参数。" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "尝试 %s --help。" #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "发生了错误" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "您可以忽略此错误,但应用程序在重新启动之前可能会不稳定。提交错误报告只需要几" "秒钟,但对我们帮助很大。" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "提交错误报告" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "重启" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "忽略错误" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "错误详情:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "有关错误和您的系统的各种细节将发送给第三方在线服务(<a href='https://www." "sentry.io'>www.sentry.io</a>) 发送前,您可以在下方查看这些数据。" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(可选) 请简单描述在错误发生之前您的操作过程:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "发送" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "简短描述…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "以下数据将被发送:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "音频标签编辑器" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "目录" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "音频元数据编辑器" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "图片URL封面来源" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "下载由<tt>artwork_url</tt>标签链接的封面。这适用于Soundcloud和Podcasts浏览" "器。" #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs 封面源" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "从 Discogs 下载封面。" #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm 封面来源" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "从 Last.fm 封面图存档下载封面。" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz 封面源" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "从 MusicBrainz 的专辑图存档下载封面。" #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "转换编码" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "修复标签编辑器中曲解的标签值编码。" #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "转换编码(_C)…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "日文字符转换程序" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "重命名前将日文假名/汉字转换为罗马拼音。" #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "将日文字符转换为罗马音" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "找不到“汉字假名简易转化器”(kakasi)。" #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "正则式替换" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "给文件打标签或重命名文件时,允许任意正则式替换(<tt>/from/to/</tt>)。" #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "标题首字母大写" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "对标签编辑器内的标签值进行大小写处理。" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "标题大小写标签(_C)" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "允许标签内全大写" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "适合阅读的标题大小写" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "按照常用的英语规则处理标题大小写,比如\"Dark Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "高级选项" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "允许编辑高级配置设置。" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "我知道我接下来要做什么" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "显示过程使用动画" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "当歌曲信息改变时,在屏幕上显示歌曲信息。" #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "位置(_P):" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "封面大小(_C):" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "显示" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "字体(_F):" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "左侧" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "中央" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "右侧" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "字体对齐(_A):" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "文字" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "文字(_T):" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "填充(_F):" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "颜色" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "阴影" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "边框" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "圆角" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "延时(_D):" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "效果" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "编辑显示模式(_i)…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "预览" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "程序信息" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "关于应用程序及其运行环境的各种信息。" #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "支持的格式" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "配置目录" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "缓存目录" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "音频后端" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "每次播放完之后(默认)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "每当一首歌完整地播放完后,插件将会写入标签到文件。快进到下一曲的次数不会被储" "存在文件中,避免了不必要的写入。" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "每次播放完或快进到下一曲之后" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "该插件会在播放或跳过一首歌曲时写入标签到文件中。如果你想确保因不喜欢而跳过的" "歌曲的评分被写到文件中,这会很有用。" #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "当专辑中的歌曲都已被评分后,立即" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "当播放或跳过一首歌时,将检查该歌曲的专辑。如果专辑中的每首歌都已被评级,并且" "至少有一首没有评级或播放计数存储在其文件中,插件将把标签写入歌曲的文件。\n" "\n" "使用这种方法可以避免文件的持续更新,但要注意,一旦专辑更新,当你想修改评级并" "把播放计数写入文件时,你必须使用“Update Tags in Files”插件。" #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "当插件写入一个专辑的标签时,它会首先设置歌曲的播放计数为0到1。\n" "有时你已经知道你不喜欢一首歌,所以在保存时将它设置为1,在以后搜索你已经完全听" "过的专辑时很有用 (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "无法写入 '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "自动更新文件中的标签" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "当歌曲被播放时,更新其文件中的标签。这将确保播放次数和评级是最新的。" #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "这个插件需要启用以下设置:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "在标签中保存评级和播放计数 (_C)" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "设置更改日期" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "同步时%s发生异常" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "确保保存时播放计数大于零" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "更新策略(_U):" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "首选项" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "自动加载/卸载设备" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "当驱动器卸载或挂载时,自动 mask 和 unmask 驱动器。" #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "自动评分" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "播放或跳过歌曲时,自动给歌曲评分。此功能使用了 Brain Nelson 所写程序 vux " "(Vacillating Utilitarian eXtemporizer) 的 'accelerated' 算法。" #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "指定的 Banshee 数据库损坏或丢失" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "导入失败" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "成功导入 %d 首歌曲的评分和统计数据" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee 导入" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "从 Banshee 导入评分和歌曲统计信息。" #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "数据库路径(_D):" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "开始导入" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "闹钟" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "用吵闹的音乐把你叫醒。" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "摇篮曲" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "淡出并暂停播放音乐。" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "Discord 状态消息" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "Dscord 状态消息" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "根据您当前正在收听的内容更改 Discord 状态消息。" #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "暂停" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "状态行 #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "状态行 #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "平坦" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "现场" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "突出低音和高音" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "俱乐部" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "大厅" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "聚会" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "轻柔" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "突出低音" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "雷鬼" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "头戴式耳机" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "轻摇滚" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "突出高音" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "舞曲" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "科技舞曲" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "斯卡" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "笔记本音响" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "均衡器" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "使用均衡器来控制音乐的音色\n" "鼠标和方向键都可以操作控制条 (鼠标右键点击重置)." #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "当前后端不支持均衡器设置。" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "默认预设" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "选择…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "重置 EQ(_R)" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "自定义预设" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "删除选中的曲目(_D)" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "用于保存的预设名称:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "保存" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "在线" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "离线" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "聊天" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "离开" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "不可用" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "不可见" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim 状态消息" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "根据您当前正在收听的内容更改 Gajim 状态。" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "暂停" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "非法参数:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "列出用于更改状态消息的帐户,以空格分隔。如果不指定,所有帐户的状态信息都将被" "更改。" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "帐号:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "暂停时显示 [paused]" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "选中后,暂停时 [paused] 将会显示在状态消息中" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "更改消息的状态" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "耳机拔出时暂停音乐" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "耳机拔出时暂停曲目播放,耳机插入时恢复曲目播放。" #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "阻止屏幕保护程序或睡眠" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "在GNOME桌面上,当播放歌曲时,会阻止屏幕保护程序激活,或阻止计算机挂起。" #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "音乐播放中" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "模式:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "禁止屏保" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "阻止睡眠" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "互联网广播日志" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "记录广播电台播放的最后10首歌曲,并在寻找上下文菜单中列出它们。" #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "输出一个 Jabber 用户调音文件到%(path)s 。" #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "更改语言" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "更改用户界面语言。" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "系统默认" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "需要重启程序才能使更改生效" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Media 服务" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "通过MediaServer2 D-Bus接口向Rygel UPnP媒体服务器公开所有专辑。" #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "确保以下内容包含在你的rygel配置文件中(~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD 服务器" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "允许使用 MPD 客户端来控制 Quod Libet。不支持串流、播放列表和曲库管理。" #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "端口(_P):" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "本地 IP(_I):" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "密码(_P):" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "连接" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "经测试的客户端" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus 支持" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "允许使用 <a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a> D-" "Bus 规范控制Quod Libet。 这允许各种Linux桌面集成(如多媒体键)。" #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "关闭时隐藏主窗口" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "接受QL模式,例如 %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT 发布者" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "将状态消息发布到MQTT主题。" #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Broker 主机名 / IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "默认为 localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Broker 端口" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "默认为 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Broker 用户名" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Broker 密码" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "主题" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "播放模式" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "歌曲开始时的状态文本。" #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "暂停模式" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "歌曲暂停播放时的文本。" #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "无播放曲目时的文本" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "没有正在播放的歌曲时显示的纯文本内容" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT 配置" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "状态文本" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "已连接到broker %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "无法连接到 %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "连接错误" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz 同步" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "将歌曲的评级与 MusicBrainz 同步。" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "用户名(_N):" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "密码 (_P):" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "帐户" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "通知文本" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "标题(_T):" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "重置为默认模式" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "主体(_B):" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "显示通知(_S)" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "显示通知" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "仅当 <i>手工</i> 切换歌曲时" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "仅当 <i>自动</i> 切换歌曲时" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "在<i>所有</i>歌曲切换时" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "仅当主窗口失去焦点时(_F)" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "显示 \"_Next\" 按钮" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "连接错误" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "无法连接到通知后台程序。" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "歌曲通知" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "当歌曲切换时显示一条通知。" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "下一首" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "书签通知" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "使用实时通知显示书签/评论。适用于 Soundcloud 浏览器。" #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "请访问插件窗口以设置 QLScrobler。在此之前,歌曲将不会被提交。" #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "无法联系服务“%s”。" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "身份验证失败:URL无效。" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "身份验证失败:用户名“%s”无效或密码错误。" #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "客户端被禁止。联系作者。" #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "系统时间错误。提交可能会失败,直到它被更正。" #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler 提交" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "用于 Last.fm、Libre.fm 和其他 Audioscrobbler 服务的 Audioscrrobbler 客户端。" #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "身份验证成功。" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "服务(_S):" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "URL(_U):" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "其它服务(_O)…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "验证帐号数据(_V)" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "歌手(_A):" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "文件名(_F):" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "排除过滤器(_F):" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "用于格式化提交的艺术家名称的模式。默认为空白。" #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "用于格式化提交标题的模式。默认为空白。" #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "与此筛选器匹配的歌曲将不会提交" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "离线模式(不提交任何内容)(_O)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "提交" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "静音广播广告" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "播放广播广告时将输出静音。\n" "电台:di.fm" #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "随机专辑播放" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "在播放列表结束时随机开始一个专辑。它要求你的活动浏览器支持按专辑过滤。" #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "评价高" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "播放次数多" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "跳过次数多" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "最近播放过" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "最近开始播放" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "最近添加" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "更长的专辑" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "开始下一张专辑前等待的秒数" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "权重" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "播放某些专辑比其他专辑多" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "避免" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "偏爱" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "随机专辑" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "等待开始 %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "成功地导入了%d 歌曲的评级和统计信息" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox 导入" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "从Rhythmbox导入评分和歌曲统计信息。" #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "屏幕保护程序暂停" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "在 GNOME 屏幕保护程序处于活动状态时暂停播放。" #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "没有安装 Quod Libet 的 GNOME Shell 搜索提供程序。" #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "您是否已将 ini 文件复制到 %s(或类似文件)?" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME 搜索提供程序" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "允许 GNOME Shell 搜索曲库。" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "切换进度条" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "替代搜索栏,始终可见并跨越整个窗口宽度。" #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "查找点书签" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "存储轨道的寻道点 A 和/或 B。在播放轨道时,跳到时间A,并在时间B后停止。\n" "\n" "ℹ 请注意,更改以下点的名称不会更新实际的书签名称,它只会更改插件在决定是否查" "找时查找的书签名称。" #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "A 的书签名" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "用于检查曲目何时开始的书签名称,如果找到,播放器将寻找该时间戳" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "B 的书签名" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "在曲目播放期间使用每个刻度的书签名称(如果存在)。如果当前位置超过时间戳,则" "寻找到曲目的结尾。" #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox同步" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "使 Logitech Squeezebox 镜像 Quod Libet 输出,前提是两者都从相同的曲库中读取。" #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "通过 <a href=\"%(plugin_link)s\">导出到 Squeezebox 插件</a> 共享配置。" #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "查找 Squeezebox 服务器时出错" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "查找 %s 时出错。请检查设置" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "暂停时停止" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "此插件将暂停更改为停止/播放/搜索。\n" "\n" "如果一个新的音频设备(蓝牙音箱、USB DAC 等)被添加到系统中时, Quod Libet 无" "法切换音频设备,那么这个插件就很有用。\n" "\n" "只要“仅可搜索的来源”处于关闭状态,就能确保当前音源中的位置不变。否则,回放将" "停止并且必须从头重新开始。" #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "仅可搜索的来源" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "插件选项" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "复制操作暂停" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "删除操作暂停" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "删除" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "跳过" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "复制一份" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "歌词同步" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "删除中" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "成功" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "失败" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "跳过现有文件" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "未能设置这首歌的文件名。" #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "与设备同步" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "将选定的已保存搜索结果中的所有歌曲与指定文件夹同步。" #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "同步下列已保存的搜索:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "导出位置的绝对路径" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "目标文件夹中所有已存在但不在已保存搜索结果中的文件都将被删除。" #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "对于挂载了 MTP 的设备,请导出到本地目标文件夹,然后使用 rsync 将其传输到您的" "设备。或者,将许多文件同步到 Android 设备时,请使用adb-sync,这要快得多。" #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "目标路径:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "路径参数" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "编辑已保存的模式…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "导出文件名的结构(基于其标签)" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "导出模式:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "停止预览" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "状态" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "源文件" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "导出路径" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "检测到重复的导出路径!可以在开始同步之前编辑上面的导出路径。" #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "目标路径中的现有文件将被删除(名为 'cover.jpg' 的文件除外)!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "开始同步" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "停止同步" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "还没有保存的搜索结果,创建一些然后再回来!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "选择目的路径" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "文件 [{filename}] 的导出路径从 [{old_path}] 更改为 [{new_path}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "启动同步预览" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "正在进行同步预览。" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "已完成同步预览" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "停止同步预览" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "同步预览已停止。" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "同步预览已完成。" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "停止同步预览" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "选择了一个不同的插件 - 停止预览" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "将同步至:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "尝试写入 {count} 文件" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "跳过 {count} 个重复的文件" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "删除 {count} 个文件" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "未提供目标路径" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "请指定歌曲应被导出的目录。" #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "未提供导出模式" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "请为导出的歌曲名称指定一个导出模式。" #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "导出路径不是绝对路径" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "模式\n" "\n" "{}\n" "\n" "包含\"/\",但不是从根开始。请提供一个绝对的目标路径,确保它以/或~/开始。" #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "没有保存的搜索" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "请至少选中一个保存的搜索。" #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "保存的搜索中没有曲目" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "所有选中的已保存的搜索均为空。" #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "找到 {} 首要同步的歌曲" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "目标路径和导出模式不匹配" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "导出模式以一个与目标路径不同的路径开始。请纠正该模式。\n" "\n" "错误:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "无法同步" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "按 <b>状态</b> 排序时无法开始同步。" #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "开始歌曲同步" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "正在进行同步。" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "完成歌曲同步" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "停止歌曲同步" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "同步已停止。" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "同步已完成。" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "停止歌曲同步" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "选择了一个不同的插件 - 停止同步" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "删除“{}”" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "已同步至:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "写入 {count}/{total} 个文件" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(跳过 {count} 个已存在的文件)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "跳过 {count}/{total} 个重复的文件" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "删除了 {count}/{total} 个文件" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "未能同步 {count} 个文件" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "跳过之前同步的 {count} 个文件" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "已同步歌词" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "显示与曲目同名(或类似)的 .lrc 文件中的同步歌词。" #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "文字:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "背景:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "字体" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "字号(px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy 状态消息" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "使用基于当前歌曲的状态消息更新所有基于 Telepathy 的 IM 帐户(如在 Empathy 等" "中配置的)。" #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "正在播放:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "歌曲开始时的状态文本。接受 QL 模式,例如 %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "已暂停:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "歌曲暂停时的状态文本。接受 QL 模式,例如 %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "没有当前歌曲时的纯文本状态" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "没有歌曲:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "状态参数" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "主题切换" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "切换所使用的 GTK+ 主题。" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "主题(_T):" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "默认主题" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "优先使用暗色版本" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "赞/踩式评分" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "添加一个拇指向上/拇指向下的评分系统,它被转换为一个评分值。对保持运行中的投票" "总数和按 <b><tt>~#score</tt></b> 进行排序很有用。" #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "切换是否显示菜单栏" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "按 Alt 切换是否显示菜单栏。" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "未播放" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "系统托盘图标" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "从系统托盘控制 Quod Libet。" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "显示(_S) %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "播放 (_P)" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "暂停(_P)" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "上一首(_V)" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "下一首(_N)" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "随机播放(_S)" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "重复(_R)" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "这首曲目放完后就停止(_A)" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "打开新的浏览器(_B)" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "编辑标签(_T)" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "信息(_I)" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "播放列表(_L)" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "退出(_Q)" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "行为" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "滚轮调节音量" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "滚轮改变歌曲" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "滚轮(_W)" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "工具条显示" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "查看歌词" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "在侧边栏中自动显示基于标签或文件的歌词。" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "没有找到以下曲目的歌词\n" "%s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "没有正在播放的曲目" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "启动可视化" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "启动外部可视化。" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "无法使用“%s”运行可视化" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "错误" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "可视化可执行文件:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "重新载入" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "波形进度条" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ 当前歌曲波形形状的搜索栏。" #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "覆盖前景颜色:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "覆盖悬停时的颜色:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "覆盖其余颜色:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "显示当前位置" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "显示时间标签" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "在进度条处滚动滚轮时前进/后退的毫秒数:" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "图片保存器" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "将当前歌曲的封面图像保存到文件。" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "文件:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "阈值(_T):" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "激活筛选器之前的阈值" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "比例(_R):" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "压缩比" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "音频压缩器" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "用一个特定的比例改变所有高于特定阈值的样本的振幅。" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "预设(_P):" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "预设过滤" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "频率切割(_F):" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "低通滤波器截止频率" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "提要级别(_L):" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "提要级别" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "默认" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "最接近虚拟扬声器的位置(30°,3 米)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "接近 Chu Moy 的交叉馈给器(流行)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "接近 Jan Meier 的 CORDA 放大器(变化不大)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "自定义" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "自定义设置" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "交叉馈送" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "在使用耳机时,以模拟扬声器设置的方式混合左、右声道,或针对早期的立体声录音进" "行调整。" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "过滤频段(_B):" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "所要过滤的频段" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "过滤频段宽度(_W):" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "所要过滤的频段宽度" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "过滤强度(_L):" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "去人声效果的强度" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "去人声" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "从音频中去除主要的人声。" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "单声道下混" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "将音频通道下混为单声道。" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "速度(_R):" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "节奏(_T):" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "音高(_P):" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "音频音调/速度" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "控制音频流的音调。" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "导出播放列表到文件夹" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "导出(_E)" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "目标文件夹:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "文件名格式:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "通过将文件复制到文件夹来导出播放列表。" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "无法导出播放列表" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "确保您对目标具有写入权限。" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "默认文件名模式:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "确定(_O)" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "输入新的播放列表名称,\n" "或选择现有的 Sonos 播放列表进行覆盖" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "导出到 Sonos 播放列表" #: quodlibet/ext/playlist/export_to_sonos.py:133 msgid "Exports a playlist to Sonos by matching tracks." msgstr "通过匹配曲目将播放列表导出到 Sonos。" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "查找 Sonos 设备时出错" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "查找 Sonos 时出错。请检查设置" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "无法删除现有的 Sonos 播放列表 %s:" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "导出到播放列表 %(playlist)r(%(total)d 曲目)" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "导出到 Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "将播放列表动态导出到 Logitech Squeezebox 播放列表,前提是两者共享一个目录结" "构。" #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "与 <a href=\"%(plugin_link)s\">Squeezebox Sync 插件</a> 共享配置。" #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "导出播放列表到 Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "播放列表名称(将覆盖现有的)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "导出到 Squeezebox 播放列表" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "从播放列表里删除重复项" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "删除播放列表中的重复条目。" #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "您确定要删除 %d 首重复的歌曲吗?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "重复的歌曲将从播放列表“%s”中删除。" #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "随机打乱播放列表顺序" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "将播放列表的顺序随机打乱。" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "跟随光标" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "根据您的选择添加播放顺序模式,或者在播放完后添加列表中的下一首歌曲。" #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "跟随光标" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "跟随光标(_F)" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "使播放次数均匀" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "在随机播放中增加一个使播放更少的歌曲优先播放的模式。" #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "播放更少优先" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "播放更少优先(_L)" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "仅队列" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "将歌曲的播放限制在队列中。\n" "\n" "在主窗口中选择此播放顺序,然后双击任何歌曲都会将其加入队列而不是播放。" #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "仅队列" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "仅队列" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "自动开始播放双击的歌曲" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "倒序播放" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "在随机播放中增加一个颠倒播放顺序的模式。" #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "倒序播放(_V)" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "按分组随机播放" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "添加随机播放模式,该模式使用通用标签对歌曲进行分组 - 类似于专辑随机播放。\n" "\n" "这对于随机排列多乐章古典乐曲很有用,在随机选择下一首乐曲之前,确保所有乐章按" "顺序播放。" #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "按分组随机播放" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "按分组随机播放(_G)" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "等待开始新组…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "将标签分组:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "用来分组的标签" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "过滤标签:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "仅当定义了筛选器标记时,才应用分组。\n" "具有未定义筛选器标签的歌曲将被视为一\n" "个只由它自己组成的组。通常是筛选器\n" "标记应与分组标记匹配或部分匹配。" #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "延时:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "开始下一组之前的时间延迟(以秒为单位)" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "重置为默认" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "跳过标记不喜欢的歌曲" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "添加按顺序播放的播放顺序(随机播放)模式,但跳过评分低于(或等于)给定阈值的" "曲目。" #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "跳过标记不喜欢的歌曲" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "跳过标记不喜欢的歌曲" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "重复播放每首歌曲" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "在随机播放中增加一个按原来顺序播放,但每首歌曲重复固定次数的模式。" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "重复播放每首歌曲" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "重复播放每首歌曲(_E)" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "每首歌曲播放次数:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "条件查询" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "根据条件查询选择要匹配的查询。" #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: 条件-查询, 然后-查询, 否则-查询)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "缺失查询" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "匹配没有给定标签的歌曲。" #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "包括空白标签" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python查询" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍在查询中使用 Python 表达式。" #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: expression)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "变量 <tt>s</tt>(或 <tt>a</tt>)是匹配的歌曲/专辑。\n" "\n" "<tt>_ts</tt> 是查询开始时的(实数)时间戳。\n" "\n" "模块 <tt>time</tt> 和 <tt>random</tt> 是可用的,类 <tt>Random</tt> " "(==<tt>random.Random</tt>) 也可用。" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "包括已保存的搜索" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 将保存的搜索结果作为另一个查询的一部分。" #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: search-name)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "唯一查询" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "按唯一标签过滤搜索结果。" #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: 标签)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK。使用唯一的播放器(%s)。" #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "无法连接到 %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "主机名:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "端口:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "用户名:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "密码:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "服务器连接的曲库目录" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "曲库的路径:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "验证设置(_V)" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox 服务器" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "调试" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox 服务器在 {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "未知的 Squeezebox 服务器" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "未知的 Squeezebox 播放器:%r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "选择 Squeezebox 播放器" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "找到 Squeezebox 服务器。\n" "请选择播放器" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "图片大小适应窗口(_W)" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "查看图像文件名字符串的“[plugins] cover_filenames”配置条目" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "程序(_P):" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "保存后编辑图像(_E)" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "文件名(_N):" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "保存失败" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "无法保存\"%s\"。" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[专辑封面] HTTP 错误:%s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "专辑封面下载器" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "从 %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "分辨率:%s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "大小:%s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "每个引擎“最佳”结果限制" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "搜索(_S)" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "搜索中…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "完成" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "下载专辑封面" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "从各个网站下载专辑封面。" #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "来源" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 转换为 ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "将您的 APEv2 标签转换为 ID3v2 标签。这将在转换后删除 APEv2 标签。" #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "转到书签" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "管理选定文件中的书签。" #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "编辑书签(_E)…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "无书签" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz 查询" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "根据 MusicBrainz 搜索重新标记专辑。" #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "在“date”标签中只使用年份" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "需要时写“_albumartist”" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "为艺术家姓名编写排序标签" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "编写标准的 MusicBrainz 标签(_S)" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "编写“labelid”标签" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "文件名" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "唱片" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "音轨" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "标题" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "歌手" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz 查询" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "查询(_Q):" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "搜索(_E)" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "结果<i>(拖动以重新排序)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "请输入查询。" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "遇到错误。请重试。" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "载入结果…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "没有找到结果。" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python 控制台" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "交互式 Python 控制台。打开一个新窗口。" #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{songs} 使用 {plugin_name}({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python 控制台侧边栏" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "交互式 Python 控制台侧边栏,在主窗口中跟随所选歌曲。" #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "默认情况下,您可以访问以下对象:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "您当前的工作目录是:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "完成" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "下载专辑封面" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "使用 Quod Libet 封面插件下载高质量专辑封面。" #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "古典" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "大" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "全高清" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "封面图下载" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "正在加载 %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "没有找到专辑:\n" "%(albums)s。\n" "\n" "使用的提供程序:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "没有找到封面" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} 像素" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "预览尺寸" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "保存目的地" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "如果还不是 JPEG,请将图像转换为相同大小的高质量 JPEG" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "另存为 JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "命令" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "名称" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "此命令的名称" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "命令" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "要运行的 shell 命令语法" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "参数" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "如果指定,则在命令中出现的参数将替换为用户提供的值,例如通过在命令中使" "用“PARAM”,所有“{PARAM}”实例都将在运行时提示输入值" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "QL 模式,例如<~filename>,用于计算命令的值。对于播放列表,这也支持虚拟标签 " "<~playlistname> 和 <~#playlistindex>。" #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "独特的" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "如果设置,这将删除模式的重复计算值" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "最大参数" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "一次传递给命令的最大参数数量(如 xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "颠倒" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "如果设置,参数列表将被反转" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "输入值" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "%s 的值?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "自定义命令" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "使用任何标签对歌曲运行自定义命令(如果需要,可以分批执行)。" #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "编辑自定义命令" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "无法运行自定义命令 %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d 个重复的组" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "全部折叠/展开" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "重复的键表达式是“%s”" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "重复浏览器" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "查找并显示带有相似标签的歌曲版本。" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "接受 QL 标签表达式,如 <tt>~artist~title</tt> 或 <tt>musicbrainz_track_id</" "tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "重复项分组依据(_G):" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "重复 Key" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "删除空白(_W)" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "删除变音符号(_D)" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "删除标点(_P)" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "不区分大小写" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "匹配选项" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "编辑播放次数" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "编辑歌曲的 <tt>~#playcount</tt> 和 <tt>~#skipcount</tt>。\n" "\n" "选择多首歌曲时,计数将递增,而不是设置。\n" "\n" "将歌曲的 <tt>~#playcount</tt> 设置为 0 时,将清除 <tt>~#lastplayed</tt> 和 " "<tt>~#laststarted</tt> 条目。但是,将 0 播放歌曲设置为正播放计数时,不会创建" "播放次数。" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "播放计数" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "跳过计数" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "选中了多个文件。" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "计数将递增。" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "删除内嵌图片" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "添加、删除或替换内嵌图片。" #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "嵌入(_E)" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "选择要嵌入 %d 曲目的图像" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "删除所有图片(_R)" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "嵌入当前图片(_E)" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "选择图片(_C)…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "设置精确评级" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "允许用数字设置歌曲的评级。" #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "请在 0.0 至 1.0 的范围内给出您期望的评分" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "根据任意标签过滤" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "根据所选歌曲的标签创建搜索查询。" #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "根据目录过滤" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "在新的浏览器窗口中筛选目录。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "声学指纹查找" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "通过声学指纹查找歌曲元数据。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "提交声学指纹" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "使用 chromaprint 生成声学指纹并将其提交给 acoustid.org。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "缺少 API 密钥" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "在提交指纹之前,您必须在插件首选项中指定 acoustid.org API 密钥。" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "请求 API 密钥" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API 密钥(_K):" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID 网络服务" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "已加入队列" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "分析" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "查找" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "写入" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "发行" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "写入 MusicBrainz 标签" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "按目录分组" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "专辑模式" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "编写专辑相关的标签,尽量减少不同专辑的发行数量" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "生成指纹:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "细节(_D)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "提交(_S)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "歌曲需要 <i><b>musicbrainz_trackid</b></i>,或 <i><b>artist</b></i> / " "<i><b>title</b></i> / <i> <b>album</b></i> 标签提交。" #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "指纹:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "带有 MBID 的歌曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "具有足够标签的歌曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "要提交的歌曲:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "完成。提交了 %(to-send)d/%(all)d 首歌曲。" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "提交指纹:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "提交中……" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "更新文件标签" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "更新文件中修改的标签。这将确保播放计数和评级是最新的。" #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "导出为 HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "将选中曲目列表导出为 HTML。" #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "发送到 iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "上传歌曲到 iRiver iFP 设备。" #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "未找到 iFP 设备" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "无法联系您的 iFP 设备。检查设备是否已通电并接通电源,以及是否安装了 ifp 线 " "(http://ifp-driver.sf.net)。" #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "正在上传 %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "无法上传 %s。设备可能空间不足或已关闭。" #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "上传时发生错误" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "导出用户数据" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "导出标签" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "导出标签和用户数据" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "导出文件 Stem 和用户数据" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "导出文件主干和标签" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "导出文件主干、标签和用户数据" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "导入/导出" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "导入和导出标签并跟踪用户数据。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "进一步信息" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "术语“跟踪用户数据”包括所选曲目所在的播放列表以及以下元数据:\n" "\n" "%s\n" "\n" "请注意,您选择导出的任何内容都将被导入。如果导出了文件主干(不带扩展名的文件" "名),则在导入时,选定的文件将被重命名。\n" "\n" "导出专辑后,您可以导入另一个版本的转辑数据。轨道的顺序和数量可能不同。该插件" "将导出的数据与新曲目相匹配,即使曲目的名称略有不同。自动匹配并不总是正确的," "因此最好不要过多地减少以下相似性值。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "导入时的用户交互" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "如果曲目数量不同,则需要确认" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "如果专辑数量不同,则需要确认" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "低于此百分比,用户将不得不手动检查并有选择地更改哪个曲目与哪个曲目匹配。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "轨迹相似度:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "专辑相似度:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "导出文件" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "编写漂亮清晰的 JSON(较慢)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "导入后删除导出文件" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "导入" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "打开导出目录" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "唱片" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "歌曲" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "歌手" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "路径结束" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "匹配专辑" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "继续" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "没有什么可导入的" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "您必须先导出某些内容,然后才能导入。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "索引已损坏。" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "无法解析 %s 中的 JSON" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "无法读取 %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "文件名" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "匹配歌曲" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "更新图表列表。" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "已是最新。" #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "获取 %s 周的图表。" #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "同步完成。" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "同步时发生异常(%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "同步Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "从您的 Last.fm 个人资料更新您曲库的统计数据。" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "用户名(_U):" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "创建排序标签" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "将专辑和艺术家姓名转换为排序名称,效果不佳。" #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "导出为 M3U / PLS 播放列表文件" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "将歌曲导出为 M3U 或者 PLS 播放列表。" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "使用相对路径" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "使用绝对路径" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "写入 %s 失败了。" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "重新扫描歌曲" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "检查文件更改并在需要时重新加载/删除歌曲。" #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "重新扫描歌曲" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "回放增益分析器" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "歌曲" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "进度" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "增益" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "峰值" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "有 %(to-process)s 个专辑要更新(共 %(all)s 个)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "回放增益" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "使用 GStreamer 分析和更新 <a href=\"%(rg_link)s\">ReplayGain</a> 信息。结果按" "专辑分组。" #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://zh.wikipedia.org/wiki/%E5%9B%9E%E6%94%BE%E5%A2%9E%E7%9B%8A" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "总是" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "如果缺少<b>任何</b>RG标签" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "如果缺少<b>专辑</b>RG标签" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "处理专辑(_P):" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "现有标签" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "分割标签" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "同时拆分专辑中的光盘编号和标题中的版本。" #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "分割专辑" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "拆分光盘编号。" #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "无" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "重置" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "轻敲" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "BPM测速" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 为所选歌曲轻按 BPM。" #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "网站搜索" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "使用任何歌曲标签搜索您选择的网站。\n" "支持模式,例如 %(pattern)s。" #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "搜索 URL 模式" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "编辑搜索 URL" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "配置搜索…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "在 Wikipedia 上搜索标签" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "打开一个浏览器窗口,其中包含选定歌曲对应标签上的维基百科文章。" #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "在 %(website)s 上搜索" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "编辑标签" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "搜索失败" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "标签 \"%s\" 未找到。" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "曲库" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "检查挂载点" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "正在扫描曲库" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "正在扫描 %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "加载文件" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "正在移动曲库文件" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "正在删除曲库文件" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "为 %s 添加手表" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "在传统播放列表 %(filename)r(大小 %(size).1fkB)中找不到曲库歌曲。" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "您是否更改了曲库的根目录,但没有更改此播放列表?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d 个播放列表转换失败" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "音乐播放器和曲库管理器" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "无法加载文件 %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "列表标签" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "打印简洁输出" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "以简洁模式显示和排序的列 (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "同时列出程序化的标签" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "参数过少" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "参数过多" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "描述" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "值" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "显示所有常用标签" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "从一个文件复制标签到另一个文件" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "显示修改变化,但是不要让修改生效" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "跳过无法写入的标签" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "无法复制标签 {tagname} 到文件 {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "在文本编辑器中编辑标签" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "取消编辑" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "未能启动文本编辑器 '%(editor-name)s'。" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "未检测到更改" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "输入标签,替换原有标签" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "无法为 %(format)s 文件 %(file)r 设置 %(tag)r 标签" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "移除标签" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "这是个正则表达式" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "移除所有标签" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "无法使用组合参数 '--all' '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "无法从 {filename} 删除标签 {tagname}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "移除标签值" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "添加标签值" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "无法设置 %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "列出文件信息" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "将提供的图像设置为主要的嵌入图像,并删除所有其他的嵌入图像" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "未能加载图像文件:%r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "无法编辑图片 %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "删除所有内嵌图片" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "将嵌入的图片导出到路径 %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "图片保存的路径(默认为工作目录)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "根据标签重命名文件" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "根据文件路径填充标签" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "文件" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "为所有文件填写曲目编号" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "根据给定的模式打印标签" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "显示帮助信息" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' 不是有效的列名 (%(all-column-ids)s)。" #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "未知(_U)" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "顺序" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "顺序(_I)" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "随机" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "随机(_R)" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "优先播放高评分曲目" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "优先播放高评分曲目(_h)" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "重复当前曲目" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "重复此曲目(_t)" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "重复所有" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "重复所有(_a)" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "单曲" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "单曲(_s)" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "流" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "缓冲" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "无法创建 GStreamer 管道 (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "未找到用于处理媒体格式的 GStreamer 元素" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "媒体格式:%(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "无法初始化 GStreamer 插件“%(name)s”" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "用于播放的 GStreamer 输出管道。如果管道包含接收器,则将使用它而不是默认接收" "器。" #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "输出管道(_O):" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f 秒" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "缓冲持续时间(_B):" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "禁用无间隙播放(_G)" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "禁用无间隙播放可以避免某些GStreamer版本的轨道变化问题" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "如果可用,使用 JACK 进行播放" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "如果可以检测到,则使用 `jackaudiosink` 作为 playbin sink" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "自动连接到 JACK 输出设备" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "告诉 `jackaudiosink` 自动连接" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "没有找到 GStreamer 音频 sink。尝试了:%s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "无效的 GStreamer 输出管道" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "无法创建音频输出" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "找不到音频设备 %r。检查 ~/.quodlibet/config 中的 Xine 设置。" #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "找不到模块 '{module}'。也许您需要安装此软件包?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "找不到 GStreamer 元素 '{element}'。" #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "请访问插件窗口来设置 ListenBrainz。在此之前,不会提交收听。" #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "连续提交失败次数过多(%d)。设置为脱机模式。请访问插件窗口重置 ListenBrainz。" "在此之前,不会提交收听。" #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz 提交" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "将收听提交到 ListenBrainz。" #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "用户令牌(_t):" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "标签(_T):" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "要包含在提交中的标签列表。逗号分隔,必要时使用双引号。" #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "不会提交符合此过滤器的歌曲。" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "在 %(count)s 播放列表上运行插件“%(name)s”?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "运行插件(_R)" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "用法" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "开头" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "无" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "时间" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "书签名" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "书签" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "过滤器(_F)" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "最近播放(_P)" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "最近添加" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "前40(_T)" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "全部歌曲(_S)" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "根据当前风格" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "根据当前表演者" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "根据当前专辑" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "随机流派(_G)" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "随机歌手(_A)" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "随机专辑(_B)" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "40首您播放得最多的歌(如果有绑定的话,可能会多于40首)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "名字(_N):" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "值(_V):" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "已保存值" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "编辑已保存的值…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "自动(_M)" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "音轨模式(_T)" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "专辑模式(_A)" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "静音" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "回放增益模式(_R)" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "新 %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(未知)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "添加(_A)…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "编辑(_E)" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "标签表达式" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "标签表达式,比如 people:real or ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "输入新标签" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "编辑标签表达式" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "文件:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "选中的歌曲将从曲库中删除,对应文件将从磁盘中删除。" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "选中的文件将被删除。" #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "永久删除这 %(file_count)d 个文件?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "删除文件(_D)" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "选中的曲目将从曲库中移除,对应的音频文件将被移到回收站。" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "选中的文件将被移到回收站。" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "移动 %(file_count)d 个文件到回收站?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "移到回收站(_M)" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "正在移动 %(current)d/%(total)d。" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "无法移动到回收站" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "未能将一个或多个文件移到回收站。" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "正在删除 %(current)d/%(total)d。" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "无法删除文件" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "未能删除一个或多个文件。" #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "浏览器" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "下载文件中" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "缺少 %d 首歌曲" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d 首歌曲不同" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "拆分为多个值(_M)" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "从专辑中拆分光盘(_A)" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "从标题分离版本(_V)" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "从艺术家中拆分作曲(_T)" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "从艺术家中拆分表演者(_P)" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "从标题中拆分表演者(_P)" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "从标题中拆分原创者(_O)" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "增加一个标签" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "标签(_T):" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "显示程序化标签(_P)" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "访问所有标签,包括机器生成的标签,例如MusicBrainz 或 Replay Gain 标签" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "显示多行标签(_M)" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "在此处也显示潜在的多行标签(例如歌词标签“lyrics”)" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "恢复(_R)" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "保存(_S)" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "配置(_C)" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "分割标签(_S)" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "复制一个或多个值(_C)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "无法增加标签" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "无法添加 %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "当前所选文件不支持多个 %s 值。" #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "无效标签" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "无效标签 %s\n" "\n" "当前选中的文件不支持编辑这些标签。" #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "非法的值" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "无效值:%(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "标签可能不准确" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "%(file-name)s 在程序运行时发生了改变。不更新曲库就直接保存,可能会导致其他的" "修改操作无法生效。" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "无法保存曲目" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "" "保存 %(file-name)s 失败了。可能原因是该文件为只读文件,文件损坏,或者你没有权" "限编辑它。" #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "更多选项(_M)…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "撤销" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "重做" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "关于" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "检查更新(_C)…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "插件(_P)" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s 和 %(count)s 个以上" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso 首选项" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "文件夹" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "新文件夹(_N)…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "全选所有子文件夹(_S)" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "新文件夹" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "输入新文件夹的名字:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "无法创建文件夹" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "无法删除文件夹" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "曲目" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "由 %s 制作" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "唱片 %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "音轨 %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "根据歌曲(_S)" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "编辑显示(_E)…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "没有选中曲目。" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "没有曲目" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "信息" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "歌词" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "%s 制造" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "歌手" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "歌手" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "演员" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "从来没有" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d 次" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "加入" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "最近一次播放" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "播放次数" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "跳过播放次数" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "评分" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "路径" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "长度" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "格式" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "解码" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "编码" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "比特率" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "文件大小" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "修改" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "额外信息" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 选中" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "音轨不可用" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d 首曲目没有专辑信息" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "精选唱片" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d 首没有艺术家的歌曲" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "专辑" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "总长度:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "总大小:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "文件" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "线上查看(_V)" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "没有找到此歌曲的歌词。" #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "确认要移除所有的曲目吗?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "将从曲库中移除选中的歌曲。" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "取消隐藏" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "取消隐藏" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "检查左边的列是否与右边的列大致匹配。如果不匹配,你可以在这里改变顺序(对于不" "应该被匹配的行使用)(_F):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "右侧顺序:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "放弃修改标签吗?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "标签已经修改但是尚未保存。现在保存,还是重置回原状态,还是放弃修改?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "恢复(_R)" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "文件存在" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "替换 %(file-name)s ?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "替换文件(_R)" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "激活的任务" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d 项任务正在进行" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "开/关随机播放模式" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "开/关重复播放模式" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "事件" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "播放次序" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "编辑" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "重命名" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "查询" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "封面" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "插件错误" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "任意状态" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "已启用" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "已禁用" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "没有分类" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "任何分类" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "没有找到插件。" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "插件" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "按插件状态/标签筛选" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "按插件类型筛选" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "按插件名称或描述筛选" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "显示错误(_E)" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "唱片(_D)" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "音轨(_T)" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "分组中(_p)" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "歌手(_A)" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "专辑(_B)" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "文件名(_F)" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "长度(_L)" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "自动跳到正在播放的曲目" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "当正在播放的曲目改变的时候,在曲目列表里相应跳过去" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "当标签被修改时对歌曲进行排序(_S)" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "修改标签时自动重新排序歌曲列表中的歌曲" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "始终允许排序" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "允许按列标题排序,即使是播放列表等" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "其它(_O):" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "编辑(_E)…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "添加或者删除额外的表头" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "可见的栏" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "标题包含版本(_V)" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "专辑包含唱片副标题(_d)" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "歌手包含所有人(_p)" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "文件名包含文件夹(_F)" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "列首选项" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "更新列 (_U)" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "将当前配置应用于歌曲列表,将新列添加到末尾" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "曲目列表" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "编辑列" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "时长总计" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "全局过滤器:" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "将此查询应用于所有其他查询" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "搜索" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "浏览器" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "确认多个评级(_M)" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "在一次更改多首歌曲的评级之前要求确认" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "允许一键评分" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "通过单击歌曲列表中的评级列来启用评级" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "评分" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "更喜欢嵌入式艺术(_E)" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "选择使用音频中嵌入的艺术作品(如果可用)而不是其他来源" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "" "可用时使用的专辑封面图像文件(支持通配符)。如果您想提供多个,请用逗号分隔它" "们。" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "首选固定的图像文件名(_P)" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "专辑封面" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "回放" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "输出设置" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "如果歌曲没有重播增益信息可用,则按此值调整音量" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "回退增益 (_F):" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "所有歌曲的音量按这个值调整,只要结果不会被削波" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "前置放大器增益(_P):" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "启用回放增益音量调节(_E)" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "回放增益音量调整" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "启动时继续播放(_C)" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "如果关机时正在播放音乐,则在下次启动时自动开始播放" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "默认评分(_D):" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "评分范围 (_s):" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "聚合评级的贝叶斯平均因子 (C)。\n" "0 表示常规平均值,较高的数值意味着曲目少的专辑会有较少的极端评分。改变这个值" "会触发对所有专辑的重新计算。" #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "贝叶斯平均量(_B):" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "电子邮件(_E):" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "评分和播放次数将保存在此电子邮件地址的标签中" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "自动保存标签变化 (_A)" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "编辑多个文件时,标签更改不需要确认" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "在标记编辑器中分割标记值时使用的一组分隔符。此列表由空格分隔。" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "分割标签条件(_t):" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "在标记编辑器中从标记中提取子标记时使用的一组分隔符。此列表由空格分隔,每个条" "目只能包含两个字符。" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "子标签拆分字符(_S):" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "标签" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "标签编辑" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "更新新评分" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "扫描曲库(_S)" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "检查您曲库的更改" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "重建曲库(_B)" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "重新加载你的曲库中的所有歌曲。这可能需要很长时间。" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "隐藏的曲目" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "启动时扫描曲库(_O)" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "监视目录变化(_W)" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "监视曲库目录以了解外部文件的添加、删除和重命名。" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "扫描目录" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s 和 %(count)d 个以上" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "属性" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "队列(_Q)" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "清除队列" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "禁用队列 - 播放时将忽略队列" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "短暂的" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "播放后删除队列里的所有歌曲" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "持久性" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "播放后将歌曲保留在队列中" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "模式" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "在结尾处停止" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d 首歌曲 (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "浏览曲库(_B)" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "切换队列可见性" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "播放错误" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "设置曲库目录?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "您还没有设置曲库,需要现在设置吗?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "暂时不要" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "现在设置" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "无法添加曲目信息" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s 使用不受支持的协议。" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "跳到正在播放的曲目(_J)" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "文件(_F)" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "歌曲(_S)" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "查看(_V)" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "浏览(_B)" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "控制(_C)" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "帮助(_H)" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "添加一个文件夹(_A)…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "加入文件(_A)…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "加入位置(_A)…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "编辑书签…" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Stop" msgstr "停止" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "当前歌曲结束后停止播放" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "快捷键" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "在线手册" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "搜索帮助文件" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "加入位置" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "输入音频文件的位置:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "无法添加位置" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s 不是有效位置。" #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "添加音乐" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "加入文件夹(_A)" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "音乐文件" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "加入文件(_A)" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "确认要将 %d 首歌加入队列吗?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "加入队列(_E)" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "你确认要把以上 %d 首曲目的评分修改吗?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "已有的评分将被删除" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "删除评分(_R)" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "选中曲目的评分都将被更改为 %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "修改评分(_R)" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "用下划线替换空格" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "将[分号]分隔符替换为连字符" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "例如 \"iv: allegro.flac\" → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "过滤不兼容Windows的字符" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "过滤不可识别的标记" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "过滤非ASCII字符" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "使用全小写字符" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "重命名文件" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "预览(_P)" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "文件名" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "移动专辑封面(_M)" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "参见\"[albumart] filenames\"配置条目,了解图像搜索字符串" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "覆盖目标专辑封面(_O)" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "删除空目录(_R)" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "专辑封面" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "新的名字" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "无法重命名文件" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "重命名 %(old-name)s 为 %(new-name)s 失败了。可能原因是目标文件已存在,或者你" "没有权限创建新文件或删除旧文件。" #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "忽略所有错误(_A)" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "停止(_S)" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "继续(_C)" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "路径不是绝对的" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "模式\n" "\t%s\n" "包含 / 但不从根开始。为避免文件夹命名错误,请使用以 / 或 ~/ 开头的绝对路径模" "式。" #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "在曲库刷新期间,列表文件夹中的歌曲将被添加到库中" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "新目录将在添加后进行扫描" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "所有选定目录中的歌曲将从曲库中删除" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "移动(_M)" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "移动一个扫描根(但不是文件),迁移所有包含的轨道的元数据。" #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "删除 {dir!r} 及其所有曲目?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "是否删除 {n} 个曲库路径及其曲目?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "删除曲库路径?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "删除" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "选择目录" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "选择此目录" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "为 {dir!r} 选择现有(或新建)目录" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "这将移动 QL 元数据:\n" "\n" "{old!r} → {new!r}\n" "\n" "音频文件本身不会因此而移动。\n" "尽管如此,还是建议备份(包括 Quod Libet 的“歌曲”文件)。" #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "移动扫描根 {dir!r} ?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "好的,移动它!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "已保存的搜索" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "编辑已保存的搜索…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "使用自由文本或 QL 查询搜索您的曲库" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "输入后开始搜索(_t)" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "用户停止输入后显示搜索结果" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "限制(_L):" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "权重(_W)" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "添加查询" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "添加要一起编辑的 QL 查询或自由文本" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "显示剩下的时间" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "主窗口" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "后退10秒" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "前进10秒" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "聚焦搜索条目" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "重置过滤器并跳转到正在播放的歌曲" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "显示选中曲目的信息窗口" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "用标签编辑器打开选中的曲目" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "将选中的曲目加入队列" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "删除选中歌曲" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "显示内联搜索条目" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "左键单击列标题" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "将该列添加到要排序的列的列表中" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "树形视图" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "折叠元素或选择父元素" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "展开元素" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "文本条目" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "撤销上一次修改" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "重做上次撤消的更改" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "选中所有面板中的曲目" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "以 %s 过滤(_F)" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "所有标题(_H)" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "音轨信息(_T)" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "专辑信息(_A)" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "表演者信息" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "日期信息" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "文件信息(_F)" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "制作信息" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "定制表头(_C)…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "扩展列宽" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "从曲库当中删除曲目 “%(title)s”?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "从曲库中删除 %(count)d 首曲目吗?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "从曲库中删除" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "在 %(count)d 首歌曲上运行插件“%(name)s”?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "在 %(count)d 个专辑上运行插件“%(name)s”?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "配置插件…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "加入到队列(_Q)" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "从曲库中删除(_R)…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "无法显示文件" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "显示文件时出错,或没有可用于显示文件的程序。" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "在文件管理器中显示 %(total)d 文件(_S)" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "下载 %(total)d 个文件(_D)…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "成功" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "失败" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "下载完成" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "下载 {total} 个文件到" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "下载到此处" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "用空格替换下划线(_U)" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "标题大小写标签(_T)" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "分解成多个标签" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "从路径获取标签" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "替换现有的标签" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "添加到现有标签" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "模式\n" "\t%s\n" "无效。它可能包含两次相同的标签,或者它有不配对的括号(< / >)。" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "您输入的模式无效。请确保将 < 和 > 输入为 \\< 和 \\>,并且标签是平" "衡的。\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "编辑显示" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "音轨号" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "开始于(_M):" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "总音轨数:" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "播放/暂停" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "上一首" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "及另外 %d …" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "正在保存改变过的曲目。" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d 首歌曲已经保存\n" "(%(remaining)s 正在处理)" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(all)s 中的 %(current)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "检查更新" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "连接失败" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "您已经在使用最新的版本 %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "已经有可用的新版本 %(new-version)s\n" "\n" "您现在使用的版本是 %(old-version)s\n" "\n" "请访问官网下载 <a href='%(url)s'>website</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "空播放列表" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "播放列表必须有名称" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "名为 %(name)s 的播放列表存在于 %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "内嵌专辑封面" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "使用音频文件内嵌的封面图。" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "文件系统封面" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "使用在常见目录中与歌曲一起找到的常用名称的图像。" #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "封面图" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "查询专辑封面提供者" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "显示摘要信息" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "显示版本和版权" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "打印调试信息" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "使用方式: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[选项]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "无法识别 %r 选项。" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "%r 选项需要参数。" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "%r 不是唯一前缀。" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s 秒" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "没有时间信息" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 小时" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 天" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d 年" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "是否只大写专辑名称的第一个字母?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "日期必须以“YYYY”、“YYYY-MM-DD”或“YYYY-MM-DD HH:MM:SS”格式输入。" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "回放增益必须以“x.yy dB”格式输入。" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "回放增益峰值必须以“x.yy”格式输入。" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz ID 必须是 UUID 格式." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "MusicBrainz 状态必须是 'official', 'promotional', 或者 'bootleg'." #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "当前语言必须是ISO 639-2 三字符编码" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "正在保存 %d 个文件" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "自动保存" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "无法编辑曲目" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "" "保存 %s 失败了。可能原因该文件是只读文件,文件损坏,或者你没有权限编辑它。" #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[非法编码]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "专辑" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "编曲" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "编曲" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "编曲" #: quodlibet/util/tags.py:86 msgid "author" msgstr "作者" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "作者" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "评论" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "作曲" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "作曲" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "作曲" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "执导" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "执导" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "执导" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "联系" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "版权" #: quodlibet/util/tags.py:93 msgid "date" msgstr "日期" #: quodlibet/util/tags.py:94 msgid "description" msgstr "描述" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "流派" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "流派" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "表演" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "表演" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "组合" #: quodlibet/util/tags.py:98 msgid "language" msgstr "语言" #: quodlibet/util/tags.py:99 msgid "license" msgstr "许可" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "作词" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "作词" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "作词" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "组织" #: quodlibet/util/tags.py:104 msgid "title" msgstr "标题" #: quodlibet/util/tags.py:105 msgid "version" msgstr "版本" #: quodlibet/util/tags.py:106 msgid "website" msgstr "网站" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "专辑歌手" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "每分钟拍数" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "唱片标题" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "唱片" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "音轨" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "标签编号" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "原始发行日期" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "原始专辑" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "原始歌手" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "录制日期" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "发行国家/地区" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "初始密钥" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz 音轨 ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz 发行曲目 ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz 发行 ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz 歌手 ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz 发行歌手 ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz 专辑状态" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz 专辑类型" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz 发行团体 ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "音轨调整" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "轨道峰值" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "专辑调整" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "专辑峰值" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "参考响度" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "唱片" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "音轨" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "最近一次播放" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "全名" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "挂载点" #: quodlibet/util/tags.py:166 msgid "people" msgstr "表演者" #: quodlibet/util/tags.py:168 msgid "year" msgstr "年份" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "原始发行年份" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "书签" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "位深" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "文件格式" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "播放列表" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "采样率" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "通道数" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "排序" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "角色" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "音频标签编辑器" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "编辑您的音频文件里的标签" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "音乐播放器" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "收听、浏览或者编辑您的音频收藏" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso 是一款和 Quod Libet 使用了相同标签编辑界面的标签编辑器。它允许你在显" "示和编辑任何您想要的受支持的音频格式文件的标签。" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "支持的文件格式包括 Ogg Vorbis/Opus/Speex/FLAC、MP3、FLAC、MOD/XM/IT、" "Musepack、Wavpack、MPEG-4 AAC、Monkeys Audio、WMA、SPC、MIDI。" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet 是一个音乐曲库管理程序。它有多重不同的方式可以管理您的曲库,并且支" "持网络电台和音频源。此外它还有非常灵活的标签编辑以及搜索功能。" #~ msgid "Export to Sonos playlist" #~ msgstr "导出为 Sonos 播放列表" #, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "无法添加 <b>%s</b>" #~ msgid "Invalid tags" #~ msgstr "非法标签" #~ msgid "" #~ "Rates songs automatically when they are played or skipped. This uses the " #~ "'accelerated' algorithm from vux by Brian Nelson." #~ msgstr "" #~ "当歌曲被播放或跳过时,自动给歌曲评分。此功能使用了 Brain Nelson 的 " #~ "'accelerated' 算法。" #, python-format #~ msgid "%.1f seconds" #~ msgstr "%.1f 秒" #~ msgid "Startup" #~ msgstr "启动" #~ msgid "Audio Feeds" #~ msgstr "音频流" #~ msgid "_Audio Feeds" #~ msgstr "音频源" #~ msgid "New" #~ msgstr "新建" #~ msgid "Automatic Library Update" #~ msgstr "自动更新库" #, python-format #~ msgid "Keeps your library up to date with inotify. Requires %s." #~ msgstr "使用 inotify 使您的库保持最新。需要 %s。" #~ msgid "" #~ "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface " #~ "Specification." #~ msgstr "允许通过 MPRIS 2 D-Bus 接口标准来控制 Quod Libet。" #~ msgid "Searching for lyrics…" #~ msgstr "搜索歌词…" #, fuzzy #~ msgid "<artist>" #~ msgstr "歌手" #, fuzzy #~ msgid "<album>" #~ msgstr "专辑" #, fuzzy #~ msgid "<title>" #~ msgstr "标题" #~ msgid "Exports metadata of selected songs as a .tags file." #~ msgstr "将选中曲目的元数据导出为 .tags 文件" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "导入元数据" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "整合元数据" #~ msgid "_Copy" #~ msgstr "复制" #~ msgid "_Paste" #~ msgstr "粘贴" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "信息" #~ msgid "Vertical Split" #~ msgstr "竖直分隔" #~ msgid "Unsupported file type" #~ msgstr "不支持的文件类型" #~ msgid "Unable to add station" #~ msgstr "无法加入站点" #, fuzzy #~ msgid "Device Properties" #~ msgstr "属性" #~ msgid "Device:" #~ msgstr "设备" #~ msgid "Not mounted" #~ msgstr "尚未挂载" #, fuzzy #~ msgid "Mount point:" #~ msgstr "挂载点" #, fuzzy #~ msgid "Media Devices" #~ msgstr "音频设备:%s" #, fuzzy #~ msgid "_Media Devices" #~ msgstr "音频设备:%s" #, fuzzy #~ msgid "_Eject" #~ msgstr "选择(_S)" #, fuzzy #~ msgid "_Properties" #~ msgstr "属性" #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "已使用 %(used-size)s, 还剩余 %(free-size)s" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> 不是合法的位置。" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "删除 <b>%s</b> 失败。" #, fuzzy #~ msgid "Unable to copy song" #~ msgstr "无法复制曲目" #~ msgid "There is not enough free space for this song." #~ msgstr "没有足够的空间" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> 不是合法的位置。" #, fuzzy #~ msgid "Unable to delete songs" #~ msgstr "无法添加曲目信息" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "删除 <b>%s</b> 失败。" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> 不是合法的位置。" #, fuzzy #~ msgid "Unable to delete song" #~ msgstr "无法编辑曲目" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "删除 <b>%s</b> 失败。" #, fuzzy #~ msgid "Unable to eject device" #~ msgstr "无法删除文件" #~ msgid "No device backend, Media Devices browser disabled." #~ msgstr "没有加载媒体设备,媒体设备浏览器无法启动" #~ msgid "Search Library" #~ msgstr "搜索库" #~ msgid "_Search Library" #~ msgstr "搜索库(_S)" #~ msgid "Rate the playing song" #~ msgstr "评估正在播放的曲目" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "显示或隐藏主曲目列表" #, fuzzy #~ msgid "Unknown Device" #~ msgstr "未知设备" #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "无法导入 %s, 需要设备支持" #~ msgid "%r is not a supported device." #~ msgstr "当前设备无法运行 %r" #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "设备正在初始化" #~ msgid "Trying '%s'" #~ msgstr "正在连接 '%s'" #~ msgid "Couldn't connect to a device backend." #~ msgstr "无法连接到设备" #~ msgid "Device backend initialized." #~ msgstr "设备已经完成初始化" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "文件名(_F)" #~ msgid "Quit Program" #~ msgstr "退出程序" #~ msgid "Top of screen" #~ msgstr "屏幕最上方" #~ msgid "Middle of screen" #~ msgstr "屏幕中央" #~ msgid "Bottom of screen" #~ msgstr "屏幕最下方" #, fuzzy #~ msgid "_Clear" #~ msgstr "清除" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "歌词" #~ msgid "_Zoom level:" #~ msgstr "缩放" #~ msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." #~ msgstr "在 LyricsWikia 上没有匹配歌词时通过以上链接搜索歌词" #, fuzzy #~ msgid "Alternate search" #~ msgstr "清空搜索" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "歌词窗口" #~ msgid "Shows a window containing lyrics of the playing song." #~ msgstr "在窗口内显示当前曲目的歌词" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "歌词" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "没有曲目" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "浏览器" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "无法创建文件夹" #~ msgid "Search Artist in Wikipedia" #~ msgstr "在 Wikipedia 上搜索表演者" #~ msgid "Audio device: %s" #~ msgstr "音频设备:%s" #~ msgid "Downloads" #~ msgstr "下载" #~ msgid "Size" #~ msgstr "大小" #~ msgid "_Download" #~ msgstr "下载(_D)" #~ msgid "Stop Once Empty" #~ msgstr "队列清空后停止播放曲目" #~ msgid "_Copy to Device" #~ msgstr "拷贝到设备" #~ msgid "Save" #~ msgstr "保存" #, fuzzy #~ msgid "browsers" #~ msgstr "浏览器" #~ msgid "Set or toggle the playback order" #~ msgstr "设定或切换回放顺序" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "无法保存库" #, fuzzy #~ msgid "Unable to save iPod database" #~ msgstr "无法保存库" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "音轨号" #~ msgid "Shuffle" #~ msgstr "Shuffle" #~ msgid "Weighted" #~ msgstr "权重" #~ msgid "_Weighted" #~ msgstr "权重(_W)" #~ msgid "_One Song" #~ msgstr "单曲(_O)" #~ msgid "Restart the playlist when finished" #~ msgstr "完成后重新开始播放列表" #~ msgid "Disable Browser" #~ msgstr "关掉浏览器" #~ msgid "_Disable Browser" #~ msgstr "关掉浏览器" #, fuzzy #~ msgid "Force Write" #~ msgstr "写入" #~ msgid "Filter on _Genre" #~ msgstr "以流派过滤(_G)" #~ msgid "Filter on _Artist" #~ msgstr "以歌手过滤(_A)" #~ msgid "Filter on Al_bum" #~ msgstr "以专辑过滤(_B)" #~ msgid "_Music" #~ msgstr "音乐(_M)" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "书签" #~ msgid "Song _List" #~ msgstr "曲目列表(_L)" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "这首曲目放完后就停止" #, fuzzy #~ msgid "Timeout" #~ msgstr "时间" #, fuzzy #~ msgid "Select an album" #~ msgstr "全选(_A)" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "播放列表" #~ msgid "Re_fresh Library" #~ msgstr "刷新库(_F)" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "删除站点(_R)" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "非法的值" #, fuzzy #~ msgid "ql-revert" #~ msgstr "移除" #, fuzzy #~ msgid "command|filename" #~ msgstr "文件名" #, fuzzy #~ msgid "heading|Search" #~ msgstr "搜索" #~ msgid "_Download..." #~ msgstr "下载(_D)..." #, fuzzy #~ msgid "_New Station..." #~ msgstr "新站点(_N)" #, fuzzy #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "删除 <b>%s</b> 失败。" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet 已经在运行。" #~ msgid "No song is currently playing." #~ msgstr "当前没有曲目在播放。" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "无法写入到 %s。正在删除。" #~ msgid "_Edit Bookmarks..." #~ msgstr "编辑书签(_E)..." #, fuzzy #~ msgid "_New Folder..." #~ msgstr "新文件夹..." #~ msgid "_Add to Playlist" #~ msgstr "加入到播放列表(_A)" #~ msgid "_Order:" #~ msgstr "顺序(_O):" #~ msgid "_Add a Location..." #~ msgstr "加入位置(_A)..." #, fuzzy #~ msgid "People Headers" #~ msgstr "过滤器(_F)" #, fuzzy #~ msgid "Album Headers" #~ msgstr "专辑列表(_A)" #, fuzzy #~ msgid "Date Headers" #~ msgstr "过滤器(_F)" #, fuzzy #~ msgid "File Headers" #~ msgstr "过滤器(_F)" #, fuzzy #~ msgid "Production Headers" #~ msgstr "音轨号" #, fuzzy #~ msgid "Tag:" #~ msgstr "标签(_T):" #, fuzzy #~ msgid "Warnings" #~ msgstr "评分(_R)" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "专辑歌手" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "歌手" #, fuzzy #~ msgid "album (sort)" #~ msgstr "专辑歌手" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "演员" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "演员" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz 专辑歌手 ID" #, fuzzy #~ msgid "errors" #~ msgstr "演员" #~ msgid "Permanently delete this file?" #~ msgstr "永远删除这个文件?" #~ msgid "Permanently delete these files?" #~ msgstr "永远删除这些文件?" #, fuzzy #~ msgid "Version:" #~ msgstr "版本" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "插件错误" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s 无法添加到您的库。\n" #~ "\n" #, fuzzy #~ msgid "No eject command found." #~ msgstr "没有发现站点" #~ msgid "Unable to start web browser" #~ msgstr "无法启动网页浏览器" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "无法找到网页浏览器。请设定好您的 $BROWSER 变量,或者确保存在 /usr/bin/" #~ "sensible-browser。" #, fuzzy #~ msgid "Library Error" #~ msgstr "库浏览器" #~ msgid "translator-credits" #~ msgstr "Emfox Zhou <EmfoxZhou@gmail.com>" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "其它要显示的栏,以空格分隔" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "继续(_C)" #~ msgid "Search your library" #~ msgstr "搜索您的库" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "总大小:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet 插件" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "简单搜索显示成蓝色,高级搜索绿色,非法搜索则是红色" #~ msgid "Separators for splitting tags" #~ msgstr "切分标签的分隔符" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet 首选项" #~ msgid "Not Played To_day" #~ msgstr "今天没有播放过(_D)" #~ msgid "Not Played in a _Week" #~ msgstr "一星期没有播放过(_W)" #~ msgid "Not Played in a _Month" #~ msgstr "一个月没有播放过(_M)" #~ msgid "B_ottom 40" #~ msgstr "后40(_O)" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "40首您播放得最少的歌(如果有绑定的话,可能会多于40首)" #, fuzzy #~ msgid "Date" #~ msgstr "日期(_D)" #~ msgid "Add" #~ msgstr "加入" #, fuzzy #~ msgid "Bitrate" #~ msgstr "比特率" #~ msgid "_Stations..." #~ msgstr "站点(_S)..." #~ msgid "Unable to save library" #~ msgstr "无法保存库" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "无法播放曲目" #~ msgid "Sort by title" #~ msgstr "按标题排序" #~ msgid "Sort by artist" #~ msgstr "按歌手排序" #~ msgid "Lyrics provided by %s." #~ msgstr "由 %s 提供的歌词。" #~ msgid "part" #~ msgstr "部分" #~ msgid "Opening audio device." #~ msgstr "正在打开音频设备。" #~ msgid "%d/%d songs saved" #~ msgstr "已保存 %d/%d 首曲目" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz 专辑 ID" #~ msgid "Loaded song library." #~ msgstr "已导入曲目库。" #~ msgid "Unable to open audio device" #~ msgstr "无法打开音频设备" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet 无法找到 Gstreamer 元素“filesrc”。检查您的 GStreamer 安装。" #, fuzzy #~ msgid "C_opy album covers" #~ msgstr "显示专辑封面(_C)" #~ msgid "W: %s is not a QL song database." #~ msgstr "警告:%s 不是 QL 的曲目数据库。" #~ msgid "Per-song (\"Radio\") volume adjustment" #~ msgstr "单曲(“广播”)音量调整" #~ msgid "Per-album (\"Audiophile\") volume adjustment" #~ msgstr "专辑(“Audiophile”)音量调整" #~ msgid "_Volume Normalization" #~ msgstr "音量整定" #~ msgid "" #~ "Scanning your library. This may take several minutes.\n" #~ "\n" #~ "%d songs reloaded\n" #~ "%d songs removed" #~ msgstr "" #~ "正在扫描您的库。这可能要进行数分钟。\n" #~ "\n" #~ "重新导入了%d首曲目\n" #~ "删除了%d首曲目" #~ msgid "" #~ "Scanning for new songs and adding them to your library.\n" #~ "\n" #~ "%d songs added" #~ msgstr "" #~ "扫描新曲目并把它们添加到您的库里。\n" #~ "\n" #~ "加入了%d首曲目" #~ msgid "M3U playlists cannot be loaded." #~ msgstr "M3U 播放列表无法导入。" #~ msgid "This station is already in your library." #~ msgstr "这个站点已经在您的库里。" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1685706133.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/po/zh_TW.po�������������������������������������������������������������������������0000644�0001750�0001750�00000725624�14436352625�014246� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Traditional Chinese (zh_TW) translations for Quod Libet. # Copyright (C) 2006 THE Quod Libet'S COPYRIGHT HOLDER # This file is distributed under the same license as the Quod Libet package. # Hsin-lin Cheng <lancetw@gmail.com>, 2006. # msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.24\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-04-25 11:38+0100\n" "PO-Revision-Date: 2023-04-11 16:59+0000\n" "Last-Translator: 麋悟BigELK176 <bigelk176@gmail.com>\n" "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/" "quodlibet/quodlibet/zh_Hant/>\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Weblate 4.17-dev\n" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:58 msgid "_Title" msgstr "標題 (_T)" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:59 msgid "_People" msgstr "人員 (_P)" #: quodlibet/browsers/albums/main.py:225 #: quodlibet/browsers/covergrid/main.py:60 quodlibet/qltk/prefs.py:58 msgid "_Date" msgstr "日期 (_D)" #: quodlibet/browsers/albums/main.py:226 #: quodlibet/browsers/covergrid/main.py:61 msgid "_Date Added" msgstr "日期已加入 (_D)" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:62 msgid "_Original Date" msgstr "原版日期 (_O)" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:63 quodlibet/qltk/prefs.py:57 msgid "_Genre" msgstr "風格 (_G)" #: quodlibet/browsers/albums/main.py:229 #: quodlibet/browsers/covergrid/main.py:64 quodlibet/qltk/prefs.py:62 #: quodlibet/qltk/ratingsmenu.py:45 msgid "_Rating" msgstr "評分 (_R)" #: quodlibet/browsers/albums/main.py:230 #: quodlibet/browsers/covergrid/main.py:65 msgid "Play_count" msgstr "播放計數 (_c)" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:71 msgid "Sort _by…" msgstr "排序依照 (_b)…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:92 #: quodlibet/browsers/paned/prefs.py:202 #: quodlibet/browsers/playlists/main.py:704 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:360 quodlibet/qltk/quodlibetwindow.py:921 msgid "_Preferences" msgstr "偏好設定 (_P)" #: quodlibet/browsers/albums/main.py:430 msgid "Album List" msgstr "專輯清單" #: quodlibet/browsers/albums/main.py:431 msgid "_Album List" msgstr "專輯清單 (_A)" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/models.py:78 msgid "All Albums" msgstr "全部專輯" #: quodlibet/browsers/albums/main.py:547 #: quodlibet/browsers/covergrid/models.py:79 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d 專輯" #: quodlibet/browsers/albums/main.py:730 #: quodlibet/browsers/covergrid/main.py:388 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "載入專輯封面 (_c)" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "專輯中沒有曲目" #: quodlibet/browsers/albums/prefs.py:41 #: quodlibet/browsers/covergrid/prefs.py:43 #: quodlibet/browsers/playlists/prefs.py:35 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:266 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d 音軌" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/ext/songsmenu/brainz/widgets.py:97 #: quodlibet/qltk/information.py:381 quodlibet/util/collection.py:270 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d 碟片" #: quodlibet/browsers/albums/prefs.py:44 #: quodlibet/browsers/covergrid/prefs.py:46 msgid "An Example Album" msgstr "樣本專輯" #: quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "專輯清單偏好設定" #: quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "顯示專輯封面 (_c)" #: quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "文內搜尋包括人員 (_s)" #: quodlibet/browsers/albums/prefs.py:71 #: quodlibet/browsers/covergrid/prefs.py:103 #: quodlibet/ext/songsmenu/cover_download.py:310 msgid "Options" msgstr "選項" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:106 msgid "Album Display" msgstr "專輯顯示" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:110 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:224 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:96 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:329 quodlibet/qltk/pluginwin.py:101 #: quodlibet/qltk/pluginwin.py:443 quodlibet/qltk/prefs.py:775 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "關閉 (_C)" #: quodlibet/browsers/_base.py:151 quodlibet/browsers/_base.py:154 msgid "Library Browser" msgstr "音樂庫瀏覽窗" #: quodlibet/browsers/_base.py:278 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:551 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:560 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d 曲目" #: quodlibet/browsers/_base.py:406 quodlibet/browsers/_base.py:411 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:579 msgid "Invalid pattern" msgstr "無效的型式" #: quodlibet/browsers/collection/main.py:79 msgid "Album Collection" msgstr "專輯收藏" #: quodlibet/browsers/collection/main.py:80 msgid "Album _Collection" msgstr "專輯收藏 (_C)" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Unknown %s" msgstr "不明 %s" #: quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "多重 %s 設定值" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "自訂 (_C)" #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:368 #: quodlibet/browsers/paned/prefs.py:119 #: quodlibet/browsers/playlists/menu.py:88 quodlibet/browsers/podcasts.py:242 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:57 #: quodlibet/qltk/edittags.py:330 quodlibet/qltk/quodlibetwindow.py:1304 #: quodlibet/qltk/scanbox.py:63 msgid "_Add" msgstr "增加 (_A)" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:123 #: quodlibet/browsers/playlists/menu.py:89 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:85 quodlibet/qltk/cbes.py:92 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:303 quodlibet/qltk/data_editors.py:316 #: quodlibet/qltk/data_editors.py:327 quodlibet/qltk/edittags.py:554 #: quodlibet/qltk/edittags.py:742 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:506 #: quodlibet/qltk/scanbox.py:38 quodlibet/qltk/scanbox.py:66 msgid "_Remove" msgstr "移除 (_R)" #: quodlibet/browsers/collection/prefs.py:121 #: quodlibet/ext/songsmenu/filterall.py:34 quodlibet/operon/commands.py:55 #: quodlibet/operon/commands.py:91 quodlibet/qltk/edittags.py:480 msgid "Tag" msgstr "標籤" #: quodlibet/browsers/collection/prefs.py:127 msgid "Merge" msgstr "合併" #: quodlibet/browsers/collection/prefs.py:187 msgid "Album Collection Preferences" msgstr "專輯收藏偏好設定" #: quodlibet/browsers/collection/prefs.py:194 #: quodlibet/browsers/paned/prefs.py:246 #: quodlibet/ext/songsmenu/editplaycount.py:47 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:42 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "套用 (_A)" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:250 #: quodlibet/browsers/playlists/menu.py:87 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/events/synchronize_to_device.py:390 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/export_to_sonos.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:59 #: quodlibet/ext/_shared/squeezebox/util.py:19 #: quodlibet/ext/songsmenu/brainz/widgets.py:354 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/embedded.py:77 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/lastfmsync.py:203 #: quodlibet/ext/songsmenu/playlist.py:55 #: quodlibet/ext/songsmenu/replaygain.py:353 #: quodlibet/ext/songsmenu/tapbpm.py:186 quodlibet/qltk/chooser.py:188 #: quodlibet/qltk/chooser.py:209 quodlibet/qltk/chooser.py:233 #: quodlibet/qltk/chooser.py:257 quodlibet/qltk/delete.py:90 #: quodlibet/qltk/delete.py:133 quodlibet/qltk/edittags.py:329 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/matchdialog.py:69 #: quodlibet/qltk/msg.py:59 quodlibet/qltk/msg.py:98 quodlibet/qltk/msg.py:115 #: quodlibet/qltk/quodlibetwindow.py:1430 quodlibet/qltk/ratingsmenu.py:39 #: quodlibet/qltk/scanbox.py:139 quodlibet/update.py:95 msgid "_Cancel" msgstr "取消 (_C)" #: quodlibet/browsers/covergrid/main.py:172 msgid "Cover Grid" msgstr "封面列示" #: quodlibet/browsers/covergrid/main.py:173 msgid "_Cover Grid" msgstr "封面列示 (_C)" #: quodlibet/browsers/covergrid/prefs.py:54 msgid "Cover Grid Preferences" msgstr "封面列示偏好設定" #: quodlibet/browsers/covergrid/prefs.py:64 msgid "Show album _text" msgstr "顯示專輯文字 (_t)" #: quodlibet/browsers/covergrid/prefs.py:70 msgid "Show \"All Albums\" Item" msgstr "顯示 \"全部專輯\" 項目" #: quodlibet/browsers/covergrid/prefs.py:75 msgid "Wide Mode" msgstr "寬幅模式" #: quodlibet/browsers/covergrid/prefs.py:95 #: quodlibet/browsers/covergrid/prefs.py:96 msgid "Cover Magnification" msgstr "封面放大" #: quodlibet/browsers/filesystem.py:42 msgid "File System" msgstr "檔案系統" #: quodlibet/browsers/filesystem.py:43 msgid "_File System" msgstr "檔案系統 (_F)" #: quodlibet/browsers/filesystem.py:130 quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "無法複製曲目" #: quodlibet/browsers/filesystem.py:131 quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "選取的檔案無法被複製到其他曲目清單或佇列。" #: quodlibet/browsers/filesystem.py:203 msgid "_Add to Library" msgstr "加入音樂庫 (_A)" #: quodlibet/browsers/iradio.py:188 #, python-format msgid "" "Station lists can only contain locations of stations, not other station " "lists or playlists. The following locations cannot be loaded:\n" "%s" msgstr "" "站台清單僅能是站台位置,而非其他站台清單或播放清單。以下的位置無法被載入:\n" "%s" #: quodlibet/browsers/iradio.py:224 quodlibet/browsers/iradio.py:265 #: quodlibet/browsers/iradio.py:497 msgid "Internet Radio" msgstr "網路電台" #: quodlibet/browsers/iradio.py:224 msgid "Add stations" msgstr "增加站台" #: quodlibet/browsers/iradio.py:265 msgid "Downloading station list" msgstr "下載站台清單" #: quodlibet/browsers/iradio.py:366 msgid "New Station" msgstr "新增站台" #: quodlibet/browsers/iradio.py:367 msgid "Enter the location of an Internet radio station:" msgstr "輸入網路電台位置:" #: quodlibet/browsers/iradio.py:385 msgid "Electronic" msgstr "電子音樂" #: quodlibet/browsers/iradio.py:388 msgid "Hip Hop / Rap" msgstr "嘻哈/饒舌" #: quodlibet/browsers/iradio.py:389 msgid "Oldies" msgstr "懷舊" #: quodlibet/browsers/iradio.py:390 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:391 msgid "Japanese" msgstr "日本風" #: quodlibet/browsers/iradio.py:392 msgid "Indian" msgstr "印度風" #: quodlibet/browsers/iradio.py:394 msgid "Religious" msgstr "宗教樂曲" #: quodlibet/browsers/iradio.py:396 msgid "Charts" msgstr "排行榜" #: quodlibet/browsers/iradio.py:397 msgid "Turkish" msgstr "土耳其風" #: quodlibet/browsers/iradio.py:398 msgid "Reggae / Dancehall" msgstr "雷鬼/舞廳" #: quodlibet/browsers/iradio.py:399 msgid "Latin" msgstr "拉丁風" #: quodlibet/browsers/iradio.py:400 msgid "College Radio" msgstr "校園廣播" #: quodlibet/browsers/iradio.py:401 msgid "Talk / News" msgstr "談話/新聞" #: quodlibet/browsers/iradio.py:402 msgid "Ambient" msgstr "節日氛圍" #: quodlibet/browsers/iradio.py:403 msgid "Jazz" msgstr "爵士" #: quodlibet/browsers/iradio.py:404 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "古典" #: quodlibet/browsers/iradio.py:405 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "流行" #: quodlibet/browsers/iradio.py:406 msgid "Alternative" msgstr "另類" #: quodlibet/browsers/iradio.py:407 msgid "Metal" msgstr "金屬" #: quodlibet/browsers/iradio.py:408 msgid "Country" msgstr "鄉村" #: quodlibet/browsers/iradio.py:409 msgid "News" msgstr "新聞" #: quodlibet/browsers/iradio.py:410 msgid "Schlager" msgstr "施拉格" #: quodlibet/browsers/iradio.py:411 msgid "Funk" msgstr "放克" #: quodlibet/browsers/iradio.py:412 msgid "Indie" msgstr "獨立" #: quodlibet/browsers/iradio.py:413 msgid "Blues" msgstr "藍調" #: quodlibet/browsers/iradio.py:414 msgid "Soul" msgstr "靈魂" #: quodlibet/browsers/iradio.py:415 msgid "Lounge" msgstr "酒廊" #: quodlibet/browsers/iradio.py:416 msgid "Punk" msgstr "龐克" #: quodlibet/browsers/iradio.py:417 msgid "Reggaeton" msgstr "雷鬼" #: quodlibet/browsers/iradio.py:419 msgid "Slavic" msgstr "斯拉夫" #: quodlibet/browsers/iradio.py:421 msgid "Greek" msgstr "希希臘" #: quodlibet/browsers/iradio.py:422 msgid "Gothic" msgstr "哥特" #: quodlibet/browsers/iradio.py:423 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "搖滾" #: quodlibet/browsers/iradio.py:476 msgid "Would you like to load a list of popular radio stations?" msgstr "想要載入知名廣播電台清單嗎?" #: quodlibet/browsers/iradio.py:482 msgid "_Load Stations" msgstr "載入站台 (_L)" #: quodlibet/browsers/iradio.py:498 msgid "_Internet Radio" msgstr "網路廣播電台 (_I)" #: quodlibet/browsers/iradio.py:587 msgid "All Stations" msgstr "全部站台" #. Translators: Favorite radio stations #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:590 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "最喜愛" #: quodlibet/browsers/iradio.py:598 msgid "No Category" msgstr "無分類" #: quodlibet/browsers/iradio.py:651 msgid "_Add Station…" msgstr "增加站台 (_A)…" #: quodlibet/browsers/iradio.py:653 msgid "_Update Stations" msgstr "更新站台 (_U)" #: quodlibet/browsers/iradio.py:833 msgid "No stations found" msgstr "未找到站台" #: quodlibet/browsers/iradio.py:834 #, python-format msgid "No Internet radio stations were found at %s." msgstr "在 %s 沒有網路電台被找到。" #: quodlibet/browsers/iradio.py:847 msgid "Nothing to add" msgstr "沒有增加" #: quodlibet/browsers/iradio.py:848 msgid "All stations listed are already in your library." msgstr "全部列出的站台已經在您的音樂庫之中了。" #: quodlibet/browsers/iradio.py:869 msgid "Add to Favorites" msgstr "加入至最喜愛" #: quodlibet/browsers/iradio.py:873 msgid "Remove from Favorites" msgstr "從最喜愛中移除" #: quodlibet/browsers/iradio.py:973 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d 站台" #: quodlibet/browsers/paned/main.py:41 quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "窗格瀏覽窗" #: quodlibet/browsers/paned/main.py:42 msgid "_Paned Browser" msgstr "窗格瀏覽窗 (_P)" #: quodlibet/browsers/paned/main.py:92 msgid "Select _All" msgstr "全選 (_A)" #: quodlibet/browsers/paned/models.py:88 quodlibet/browsers/podcasts.py:55 #: quodlibet/browsers/podcasts.py:67 quodlibet/browsers/podcasts.py:69 #: quodlibet/browsers/podcasts.py:179 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/order/__init__.py:31 quodlibet/qltk/information.py:242 #: quodlibet/qltk/information.py:249 quodlibet/qltk/information.py:275 #: quodlibet/qltk/pluginwin.py:53 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "不明" #: quodlibet/browsers/paned/models.py:106 msgid "All" msgstr "全部" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:158 msgid "Small" msgstr "小型" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "寬型" #: quodlibet/browsers/paned/prefs.py:43 msgid "Columnar" msgstr "欄位" #: quodlibet/browsers/paned/prefs.py:109 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "%s" msgstr "" "標籤型式附帶選項標記,例如 <tt>作曲者</tt> 或\n" "%s" #: quodlibet/browsers/paned/prefs.py:230 msgid "Paned Browser Preferences" msgstr "窗格瀏覽窗偏好設定" #: quodlibet/browsers/paned/prefs.py:235 msgid "Column layout" msgstr "欄位設計" #: quodlibet/browsers/paned/prefs.py:239 msgid "Column content" msgstr "欄位內容" #: quodlibet/browsers/paned/prefs.py:241 msgid "Equal pane width" msgstr "窗格均等寬度" #: quodlibet/browsers/playlists/main.py:50 #: quodlibet/browsers/playlists/main.py:634 quodlibet/qltk/pluginwin.py:37 msgid "Playlists" msgstr "播放清單" #: quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "播放清單 (_P)" #: quodlibet/browsers/playlists/main.py:168 msgid "_Remove from Playlist" msgstr "從播放清單中移除 (_R)" #: quodlibet/browsers/playlists/main.py:212 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "新建 (_N)" #: quodlibet/browsers/playlists/main.py:214 msgid "_Import…" msgstr "匯入 (_I)…" #: quodlibet/browsers/playlists/main.py:471 msgid "Unable to import playlist" msgstr "無法匯入播放清單" #: quodlibet/browsers/playlists/main.py:472 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "Quod Libet 僅能匯入 M3U/M3U8 及 PLS 格式的播放清單。" #: quodlibet/browsers/playlists/main.py:514 #: quodlibet/browsers/playlists/util.py:38 quodlibet/browsers/podcasts.py:485 #: quodlibet/qltk/delete.py:143 quodlibet/qltk/filesel.py:257 #: quodlibet/qltk/lyrics.py:33 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:359 msgid "_Delete" msgstr "刪除 (_D)" #: quodlibet/browsers/playlists/main.py:521 msgid "_Rename" msgstr "重新命名 (_R)" #: quodlibet/browsers/playlists/main.py:620 msgid "Unable to rename playlist" msgstr "無法重新命名播放清單" #: quodlibet/browsers/playlists/main.py:635 msgid "Import Playlist" msgstr "匯入播放清單" #: quodlibet/browsers/playlists/main.py:635 msgid "_Import" msgstr "匯入 (_I)" #: quodlibet/browsers/playlists/menu.py:24 msgid "_New Playlist…" msgstr "新建播放清單 (_N)…" #: quodlibet/browsers/playlists/menu.py:78 #, python-format msgid "What do you want to do with that %d song?" msgid_plural "What do you want to do with those %d songs?" msgstr[0] "對這些 %d 曲目想要如何操作?" #: quodlibet/browsers/playlists/menu.py:82 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "確認動作用於播放清單 \"%s\"" #: quodlibet/browsers/playlists/prefs.py:21 msgid "empty" msgstr "空白" #: quodlibet/browsers/playlists/prefs.py:39 msgid "Example Playlist" msgstr "樣本播放清單" #: quodlibet/browsers/playlists/prefs.py:47 msgid "Playlist Browser Preferences" msgstr "播放清單瀏覽窗偏好設定" #: quodlibet/browsers/playlists/prefs.py:52 msgid "Playlist display" msgstr "播放清單顯示" #: quodlibet/browsers/playlists/util.py:34 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "確定要刪除播放清單 '%s' ?" #: quodlibet/browsers/playlists/util.py:36 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "所選的播放清單的全部資資訊將被刪除,且無法復原。" #: quodlibet/browsers/playlists/util.py:54 #, python-brace-format msgid "Extend \"{pl_name}\" with {num} additional track?" msgid_plural "Extend \"{pl_name}\" with {num} additional tracks?" msgstr[0] "擴增 \"{pl_name}\" 用 {num} 個外加音軌?" #: quodlibet/browsers/playlists/util.py:60 msgid "_Add Tracks" msgstr "增加音軌 (_A)" #: quodlibet/browsers/playlists/util.py:71 #: quodlibet/browsers/playlists/util.py:157 quodlibet/util/collection.py:611 msgid "New Playlist" msgstr "新建播放清單" #: quodlibet/browsers/playlists/util.py:72 msgid "Enter a name for the new playlist:" msgstr "輸入新建播放清單的名稱:" #: quodlibet/browsers/playlists/util.py:73 msgid "_Create" msgstr "建立 (_C)" #: quodlibet/browsers/playlists/util.py:108 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "匯入播放清單。\n" "\n" "%(current)d/%(total)d 曲目已經加入。" #: quodlibet/browsers/podcasts.py:240 msgid "New Feed" msgstr "新建播送 Feed" #: quodlibet/browsers/podcasts.py:241 msgid "Enter the podcast / audio feed location:" msgstr "輸入廣播 Potcast/播送 Feed 位置:" #: quodlibet/browsers/podcasts.py:309 msgid "Podcasts" msgstr "Poscast 播客" #: quodlibet/browsers/podcasts.py:310 msgid "_Podcasts" msgstr "Poscast 播客 (_P)" #: quodlibet/browsers/podcasts.py:412 msgid "_Add Feed…" msgstr "增加播送 Feed (_A)…" #: quodlibet/browsers/podcasts.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:426 msgid "_Refresh" msgstr "重新整理 (_R)" #: quodlibet/browsers/podcasts.py:480 msgid "Search source for new episodes" msgstr "搜尋來源的新進插播" #: quodlibet/browsers/podcasts.py:482 msgid "_Rebuild" msgstr "重新建立 (_R)" #: quodlibet/browsers/podcasts.py:484 msgid "Remove all existing episodes then reload from source" msgstr "移除現存全部插播,然後從來源重新載入" #: quodlibet/browsers/podcasts.py:486 msgid "Remove this podcast and its episodes" msgstr "移除此播客及其插播" #: quodlibet/browsers/podcasts.py:546 msgid "Unable to add feed" msgstr "無法增加 Feed" #: quodlibet/browsers/podcasts.py:547 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be a " "podcast / audio feed." msgstr "%s 無法加入。伺服器可能關機中,或是此位置可能不是播客/音訊 Feed。" #: quodlibet/browsers/podcasts.py:564 msgid "" "The current audio backend does not support URLs, Podcast browser disabled." msgstr "目前音訊後端不支援 URLs, Podcast 播客瀏覽窗已停用。" #: quodlibet/browsers/tracks.py:34 msgid "_Limit Results" msgstr "搜尋結果限制 (_L)" #: quodlibet/browsers/tracks.py:39 msgid "_Allow multiple queries" msgstr "允許多重查詢 (_A)" #: quodlibet/browsers/tracks.py:53 quodlibet/qltk/information.py:465 msgid "Track List" msgstr "音軌清單" #: quodlibet/browsers/tracks.py:54 msgid "_Track List" msgstr "音軌清單 (_T)" #. Pre-cache. It's horrible, but at least you can play things immediately #: quodlibet/browsers/soundcloud/library.py:71 msgid "Soundcloud" msgstr "Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Soundcloud Browser" msgstr "Soundcloud 瀏覽窗" #: quodlibet/browsers/soundcloud/main.py:41 msgid "Sound_cloud" msgstr "Soundcloud (_c)" #: quodlibet/browsers/soundcloud/main.py:61 quodlibet/qltk/searchbar.py:82 msgid "Search" msgstr "搜尋" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "我的音軌" #: quodlibet/browsers/soundcloud/main.py:143 #, python-format msgid "Go to %s" msgstr "跳至 %s" #: quodlibet/browsers/soundcloud/main.py:444 msgid "Connected" msgstr "已連線" #: quodlibet/browsers/soundcloud/main.py:445 #, python-format msgid "Quod Libet is now connected, %s!" msgstr "Quod Libet 現已連線, %s !" #: quodlibet/browsers/soundcloud/main.py:457 #, python-format msgid "Log out of %s" msgstr "登出自 %s" #: quodlibet/browsers/soundcloud/main.py:459 msgid "Enter code…" msgstr "輸入代碼…" #: quodlibet/browsers/soundcloud/main.py:460 #, python-format msgid "Log in to %s" msgstr "登入至%s" #: quodlibet/browsers/soundcloud/util.py:94 msgid "Soundcloud authorisation" msgstr "Soundcloud 授權" #: quodlibet/browsers/soundcloud/util.py:95 msgid "Enter Soundcloud auth code:" msgstr "輸入 Soundcloud 授權碼:" #: quodlibet/cli.py:51 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 並未執行。(加上 '--run' 來啟動程式)" #: quodlibet/cli.py:87 msgid "a music library and player" msgstr "一個歌曲音樂庫與播放器" #: quodlibet/cli.py:88 msgid "[option]" msgstr "[選項]" #: quodlibet/cli.py:90 msgid "Print the playing song and exit" msgstr "顯示播放中的曲目並離開" #: quodlibet/cli.py:91 msgid "Begin playing immediately" msgstr "立即開始播放" #: quodlibet/cli.py:92 msgid "Don't show any windows on start" msgstr "在啟動時不要顯示任何視窗" #: quodlibet/cli.py:95 msgid "Jump to next song" msgstr "跳到下一個曲目" #: quodlibet/cli.py:97 msgid "Jump to previous song or restart if near the beginning" msgstr "跳至前一首曲目,或是重新開始如果剛剛開頭" #: quodlibet/cli.py:98 msgid "Jump to previous song" msgstr "跳到上一個曲目" #: quodlibet/cli.py:99 msgid "Start playback" msgstr "開始播放" #: quodlibet/cli.py:100 msgid "Pause playback" msgstr "暫停播放" #: quodlibet/cli.py:101 msgid "Toggle play/pause mode" msgstr "切換 播放/暫停 模式" #: quodlibet/cli.py:102 msgid "Stop playback" msgstr "停止播放" #: quodlibet/cli.py:103 msgid "Turn up volume" msgstr "調高音量" #: quodlibet/cli.py:104 msgid "Turn down volume" msgstr "調低音量" #: quodlibet/cli.py:105 msgid "Increase rating of playing song by one star" msgstr "現播曲目提高評分加一顆星" #: quodlibet/cli.py:106 msgid "Decrease rating of playing song by one star" msgstr "現播曲目降低評分減一顆星" #: quodlibet/cli.py:107 msgid "Print player status" msgstr "顯示播放器狀態" #: quodlibet/cli.py:108 msgid "Hide main window" msgstr "隱藏主視窗" #: quodlibet/cli.py:109 msgid "Show main window" msgstr "顯示主視窗" #: quodlibet/cli.py:110 msgid "Toggle main window visibility" msgstr "切換主視窗可見性" #: quodlibet/cli.py:111 msgid "Focus the running player" msgstr "焦點移到執行中的播放器" #: quodlibet/cli.py:112 msgid "Remove active browser filters" msgstr "移除現行瀏覽窗篩選" #: quodlibet/cli.py:113 msgid "Refresh and rescan library" msgstr "重新整理重新掃瞄音樂庫" #: quodlibet/cli.py:114 msgid "List available browsers" msgstr "列出可用的瀏覽窗" #: quodlibet/cli.py:115 msgid "Print the current playlist" msgstr "顯示當前的播放清單" #: quodlibet/cli.py:116 msgid "Print the contents of the queue" msgstr "顯示佇列的內容" #: quodlibet/cli.py:117 msgid "Print the active text query" msgstr "顯示現行查詢文字" #: quodlibet/cli.py:118 msgid "Start without plugins" msgstr "啟動無外掛" #: quodlibet/cli.py:119 msgid "Start Quod Libet if it isn't running" msgstr "啟動 Quod Libet 如果尚未執行" #: quodlibet/cli.py:120 msgid "Exit Quod Libet" msgstr "離開 Quod Libet" #: quodlibet/cli.py:125 msgid "Seek within the playing song" msgstr "在其中找尋播放中的曲目" #: quodlibet/cli.py:125 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:126 msgid "Set or toggle shuffle mode" msgstr "設定或切換隨機模式" #: quodlibet/cli.py:127 msgid "Set shuffle mode type" msgstr "設定隨機模式形式" #: quodlibet/cli.py:128 msgid "Turn repeat off, on, or toggle it" msgstr "開關重複播放,或是切換" #: quodlibet/cli.py:129 msgid "Set repeat mode type" msgstr "設定重複播放形式" #: quodlibet/cli.py:130 msgid "Set the volume" msgstr "設定音量" #: quodlibet/cli.py:131 msgid "Search your audio library" msgstr "搜尋您的歌曲音樂庫" #: quodlibet/cli.py:131 quodlibet/cli.py:141 quodlibet/cli.py:145 #: quodlibet/cli.py:147 msgid "query" msgstr "查詢" #: quodlibet/cli.py:132 msgid "Play a file" msgstr "播放檔案" #: quodlibet/cli.py:132 quodlibet/cli.py:141 quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "檔名" #: quodlibet/cli.py:133 msgid "Set rating of playing song" msgstr "播放中曲目設定評分" #: quodlibet/cli.py:134 msgid "Set the current browser" msgstr "設定當前的瀏覽窗" #: quodlibet/cli.py:135 msgid "Stop after the playing song" msgstr "播放曲目完結後停止" #: quodlibet/cli.py:136 msgid "Open a new browser" msgstr "開啟新的瀏覽窗" #: quodlibet/cli.py:137 msgid "Show or hide the queue" msgstr "顯示或隱藏佇列" #: quodlibet/cli.py:138 msgid "Filter on a random value" msgstr "以亂數篩選" #: quodlibet/cli.py:138 msgctxt "command" msgid "tag" msgstr "標籤" #: quodlibet/cli.py:139 msgid "Filter on a tag value" msgstr "以標籤值篩選" #: quodlibet/cli.py:139 msgid "tag=value" msgstr "tag=value" #: quodlibet/cli.py:140 msgid "Enqueue a file or query" msgstr "佇列檔案或查詢" #: quodlibet/cli.py:142 msgid "Enqueue comma-separated files" msgstr "佇例檔案(逗號分開)" #: quodlibet/cli.py:143 quodlibet/util/tags.py:158 msgid "filename" msgstr "檔名" #: quodlibet/cli.py:144 msgid "Print filenames of results of query to stdout" msgstr "列印查詢結果的檔名至標準輸出" #: quodlibet/cli.py:146 msgid "Unqueue a file or query" msgstr "非佇列檔案或查詢" #: quodlibet/cli.py:148 msgid "Add a file or directory to the library" msgstr "增加檔案或目錄至音樂庫" #: quodlibet/cli.py:149 quodlibet/util/tags.py:100 msgid "location" msgstr "位置" #: quodlibet/cli.py:150 msgid "Set template for --print-* commands" msgstr "設定範本用於 --print-* 指令" #: quodlibet/cli.py:151 quodlibet/ext/songsmenu/custom_commands.py:55 msgid "pattern" msgstr "型式" #: quodlibet/cli.py:216 #, python-format msgid "Invalid argument for '%s'." msgstr "無效的參數 ' %s' 。" #: quodlibet/cli.py:217 quodlibet/util/__init__.py:175 #, python-format msgid "Try %s --help." msgstr "試試 %s --help。" #: quodlibet/errorreport/ui.py:58 msgid "An Error Occurred" msgstr "錯誤發生" #: quodlibet/errorreport/ui.py:60 msgid "" "You can ignore this error, but the application might be unstable until it is " "restarted. Submitting an error report will only take a few seconds and would " "help us a lot." msgstr "" "您可以忽略錯誤,但程式會變得不穩定直到重新啟動。提交錯誤報告只花幾秒時間,對" "我們極有幫助。" #: quodlibet/errorreport/ui.py:69 quodlibet/errorreport/ui.py:85 msgid "Submit Error Report" msgstr "提交錯誤報告" #: quodlibet/errorreport/ui.py:70 msgid "Restart" msgstr "重新啟動" #: quodlibet/errorreport/ui.py:71 msgid "Ignore Error" msgstr "忽視錯誤" #: quodlibet/errorreport/ui.py:75 msgid "Error details:" msgstr "錯誤詳細:" #: quodlibet/errorreport/ui.py:87 msgid "" "Various details regarding the error and your system will be send to a third " "party online service (<a href='https://www.sentry.io'>www.sentry.io</a>). " "You can review the data before sending it below." msgstr "" "有關錯誤及系統各式細節將會傳送至第三方線上服務 (<a href='https://www.sentry." "io'>www.sentry.io</a>),傳送之前您可以查看資料。" #: quodlibet/errorreport/ui.py:95 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "(選用)請提供簡短描述錯誤發生狀況:" #: quodlibet/errorreport/ui.py:104 msgid "_Send" msgstr "發送 (_S)" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "簡短描述…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "資料被發送:" #: quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "一個音樂檔案標籤編輯器" #: quodlibet/exfalso.py:35 quodlibet/util/tags.py:159 msgid "directory" msgstr "目錄" #: quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "音檔標籤編輯器" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "藝術設計 URL 封面來源" #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." msgstr "" "Downloads covers linked to by the <tt>artwork_url</tt> tag. This works with " "the Soundcloud and Podcasts browsers." #: quodlibet/ext/covers/discogs.py:28 msgid "Discogs Cover Source" msgstr "Discogs 封面資源" #: quodlibet/ext/covers/discogs.py:29 msgid "Downloads covers from Discogs." msgstr "下載封面來自 Discogs." #: quodlibet/ext/covers/lastfm.py:20 msgid "Last.fm Cover Source" msgstr "Last.fm 封面資源" #: quodlibet/ext/covers/lastfm.py:21 msgid "Downloads covers from Last.fm's cover art archive." msgstr "下載封面來自 Last.fm's 封面藝術庫。" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz 封面資源" #: quodlibet/ext/covers/musicbrainz.py:22 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "下載封面來自 MusicBrainz's 封面藝術庫." #: quodlibet/ext/editing/iconv.py:26 msgid "Convert Encodings" msgstr "轉換編碼" #: quodlibet/ext/editing/iconv.py:27 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Fixes misinterpreted tag value encodings in the tag editor." #: quodlibet/ext/editing/iconv.py:33 msgid "_Convert Encoding…" msgstr "轉換編碼 (_C)…" #: quodlibet/ext/editing/kakasi.py:26 msgid "Kana/Kanji Simple Inverter" msgstr "假名/漢字簡單反轉" #: quodlibet/ext/editing/kakasi.py:27 msgid "Converts kana/kanji to romaji before renaming." msgstr "Converts kana/kanji to romaji before renaming." #: quodlibet/ext/editing/kakasi.py:36 msgid "Romanize _Japanese text" msgstr "羅馬字母化日文字 (_J)" #: quodlibet/ext/editing/kakasi.py:68 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." #: quodlibet/ext/editing/resub.py:18 msgid "Regex Substitution" msgstr "表達式替換" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." msgstr "" "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) when tagging or " "renaming files." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "標題大小寫" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "標題大小寫標籤設定值於標籤編輯器。" #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "標題大小寫設定值 (_c)" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "允許標籤全部大寫 (_A)" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "人類寫法標題大小寫" #: quodlibet/ext/editing/titlecase.py:53 msgid "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" msgstr "" "Uses common English rules for title casing, as in \"Dark Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Advanced Preferences" msgstr "進階偏好設定" #: quodlibet/ext/events/advanced_preferences.py:120 msgid "Allow editing of advanced config settings." msgstr "允許進階設定編輯。" #: quodlibet/ext/events/advanced_preferences.py:262 msgid "I know what I'm doing" msgstr "我明白現在所作所為" #: quodlibet/ext/events/animosd/main.py:27 msgid "Animated On-Screen Display" msgstr "動畫式呈現螢幕顯示" #: quodlibet/ext/events/animosd/main.py:28 msgid "Displays song information on your screen when it changes." msgstr "Displays song information on your screen when it changes." #: quodlibet/ext/events/animosd/prefs.py:177 msgid "_Position:" msgstr "位置 (_P):" #: quodlibet/ext/events/animosd/prefs.py:189 msgid "_Cover size:" msgstr "封面大小 (_C):" #: quodlibet/ext/events/animosd/prefs.py:195 quodlibet/qltk/prefs.py:290 msgid "Display" msgstr "顯示" #: quodlibet/ext/events/animosd/prefs.py:208 msgid "_Font:" msgstr "字型 (_F):" #: quodlibet/ext/events/animosd/prefs.py:213 msgid "Left" msgstr "靠左" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Center" msgstr "置中" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Right" msgstr "靠右" #: quodlibet/ext/events/animosd/prefs.py:218 msgid "_Align text:" msgstr "對齊文字 (_A):" #: quodlibet/ext/events/animosd/prefs.py:224 msgid "Text" msgstr "文字" #: quodlibet/ext/events/animosd/prefs.py:235 msgid "_Text:" msgstr "文字 (_T):" #: quodlibet/ext/events/animosd/prefs.py:245 msgid "_Fill:" msgstr "填滿 (_F):" #: quodlibet/ext/events/animosd/prefs.py:250 #: quodlibet/ext/events/synchronizedlyrics.py:65 msgid "Colors" msgstr "顏色" #: quodlibet/ext/events/animosd/prefs.py:258 msgid "_Shadows" msgstr "陰影 (_S)" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Outline" msgstr "框線 (_O)" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "Rou_nded Corners" msgstr "圓角 (_n)" #: quodlibet/ext/events/animosd/prefs.py:276 msgid "_Delay:" msgstr "延遲 (_D):" #: quodlibet/ext/events/animosd/prefs.py:282 quodlibet/qltk/pluginwin.py:43 msgid "Effects" msgstr "效果" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "編輯顯示型式 (_i)…" #. Start preview button #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/synchronize_to_device.py:200 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "預覽" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "憗用程式資訊" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "應用程式各項資訊及其環境。" #: quodlibet/ext/events/appinfo.py:62 msgid "Supported Formats" msgstr "支援格式" #: quodlibet/ext/events/appinfo.py:70 msgid "Configuration Directory" msgstr "設定目錄" #: quodlibet/ext/events/appinfo.py:77 msgid "Cache Directory" msgstr "暫存目錄" #: quodlibet/ext/events/appinfo.py:84 msgid "Audio Backend" msgstr "音檔後端" #: quodlibet/ext/events/auto_update_tags_in_files.py:35 msgid "After every play (default)" msgstr "每次播放之後(預設)" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:36 msgid "" "Whenever a song was played but not skipped, the plugin will write the tags " "to the file. Skip counts aren't stored in files at all, so this avoids " "unnecessary writes." msgstr "" "每當一首歌曲播放過了但未跳過時,外掛會將標籤寫入檔案。 跳過計數並未存入檔案" "中,如此可以避免不必要的寫入。" #: quodlibet/ext/events/auto_update_tags_in_files.py:40 msgid "After every play or skip" msgstr "每次播放或跳過之後" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:41 msgid "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." msgstr "" "Whenever a song was played or skipped, the plugin will write the tags to the " "file. Can be useful if you want to make sure that ratings of songs you " "dislike and thus skipped are written to the files." #: quodlibet/ext/events/auto_update_tags_in_files.py:46 msgid "Once, when album fully rated" msgstr "整張轉輯一次評分" #. #: quodlibet/ext/events/auto_update_tags_in_files.py:47 msgid "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." msgstr "" "When a song was played or skipped, the album of that song will be checked. " "If every song in the album has been rated and at least one has no ratings or " "play counts stored in its file, the plugin will write the tags to the songs' " "files.\n" "\n" "Use this to avoid constant file updates, but be aware that once an album was " "updated, you'll have to use the 'Update Tags in Files' plugin whenever you " "want modified ratings and play counts to be written to the files." #: quodlibet/ext/events/auto_update_tags_in_files.py:57 #, python-format msgid "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." msgstr "" "When the plugin writes the tags of an album, it will first set the play " "count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so setting it to one " "when saving can be useful later on, when searching for albums you have fully " "listened to (%s)." #: quodlibet/ext/events/auto_update_tags_in_files.py:63 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:543 #, python-format msgid "Couldn't write '%s'" msgstr "無法寫上 '%s'" #: quodlibet/ext/events/auto_update_tags_in_files.py:80 msgid "Auto Update Tags in Files" msgstr "自動更新檔案中的標籤" #: quodlibet/ext/events/auto_update_tags_in_files.py:81 msgid "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." msgstr "" "When songs were played, update the tags in their files. This will ensure " "play counts and ratings are up to date." #: quodlibet/ext/events/auto_update_tags_in_files.py:92 #, python-format msgid "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" msgstr "" "The following setting was enabled as it's required for this plugin to work:\n" "\n" "%s" #: quodlibet/ext/events/auto_update_tags_in_files.py:94 #: quodlibet/qltk/prefs.py:585 msgid "Save ratings and play _counts in tags" msgstr "儲存評分及播放次數於標籤 (_c)" #: quodlibet/ext/events/auto_update_tags_in_files.py:96 msgid "Settings updated" msgstr "設定已更新" #: quodlibet/ext/events/auto_update_tags_in_files.py:122 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:344 #, python-format msgid "Error in %s" msgstr "錯誤於 %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:181 msgid "Ensure play counts are above zero when saving" msgstr "儲存時確使播放計次大於零" #: quodlibet/ext/events/auto_update_tags_in_files.py:215 msgid "_Update strategy:" msgstr "更新策略 (_U):" #: quodlibet/ext/events/auto_update_tags_in_files.py:229 #: quodlibet/ext/events/mpris/__init__.py:51 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:100 #: quodlibet/ext/gstreamer/crossfeed.py:137 #: quodlibet/ext/gstreamer/karaoke.py:100 quodlibet/ext/gstreamer/pitch.py:90 #: quodlibet/ext/playorder/queue.py:39 quodlibet/ext/query/missing.py:39 #: quodlibet/qltk/prefs.py:750 msgid "Preferences" msgstr "偏好設定" #: quodlibet/ext/events/automask.py:22 msgid "Automatic Masking" msgstr "自動庶罩" #: quodlibet/ext/events/automask.py:23 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Automatically masks and unmasks drives when they are unmounted or mounted." #: quodlibet/ext/events/autorating.py:15 msgid "Automatic Rating" msgstr "自動評分" #: quodlibet/ext/events/autorating.py:16 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." msgstr "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux (Vacillating Utilitarian eXtemporizer) by " "Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:107 msgid "Specified Banshee database is malformed or missing" msgstr "Specified Banshee database is malformed or missing" #: quodlibet/ext/events/bansheeimport.py:112 #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "匯入失敗" #: quodlibet/ext/events/bansheeimport.py:118 #, python-format msgid "Successfully imported ratings and statistics for %d song" msgid_plural "Successfully imported ratings and statistics for %d songs" msgstr[0] "成功匯入評分與統計資料 %d 曲目" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Banshee Import" msgstr "Banshee 匯入" #: quodlibet/ext/events/bansheeimport.py:128 msgid "Imports ratings and song statistics from Banshee." msgstr "Imports ratings and song statistics from Banshee." #: quodlibet/ext/events/bansheeimport.py:137 msgid "_Database path:" msgstr "資料庫路徑 (_D):" #: quodlibet/ext/events/bansheeimport.py:165 #: quodlibet/ext/events/rbimport.py:133 msgid "Start Import" msgstr "開始匯入" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "鬧鐘提醒" #: quodlibet/ext/events/clock.py:25 msgid "Wakes you up with loud music." msgstr "用巨大音量把你喚醒。" #: quodlibet/ext/events/clock.py:119 msgid "Lullaby" msgstr "催眠曲" #: quodlibet/ext/events/clock.py:120 msgid "Fades out and pauses your music." msgstr "漸漸淡出音響並暫止音樂。" #: quodlibet/ext/events/discord_status.py:44 msgid "Discord status message" msgstr "放棄狀態訊息" #: quodlibet/ext/events/discord_status.py:45 msgid "Discord Status Message" msgstr "放棄狀態訊息" #: quodlibet/ext/events/discord_status.py:46 msgid "" "Change your Discord status message according to what you're currently " "listening to." msgstr "變更您的放棄狀態訊息,根據您目前所收聽的。" #: quodlibet/ext/events/discord_status.py:85 msgid "Paused" msgstr "暫停" #: quodlibet/ext/events/discord_status.py:136 msgid "Status Line #1" msgstr "狀態線 #1" #: quodlibet/ext/events/discord_status.py:147 msgid "Status Line #2" msgstr "狀態線 #2" #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "平坦" #: quodlibet/ext/events/equalizer.py:27 msgid "Live" msgstr "現場" #: quodlibet/ext/events/equalizer.py:29 msgid "Full Bass & Treble" msgstr "重低音及高音" #: quodlibet/ext/events/equalizer.py:32 msgid "Club" msgstr "俱樂部" #: quodlibet/ext/events/equalizer.py:34 msgid "Large Hall" msgstr "大廳" #: quodlibet/ext/events/equalizer.py:36 msgid "Party" msgstr "派對" #: quodlibet/ext/events/equalizer.py:40 msgid "Soft" msgstr "輕柔" #: quodlibet/ext/events/equalizer.py:42 msgid "Full Bass" msgstr "重低音" #: quodlibet/ext/events/equalizer.py:48 msgid "Reggae" msgstr "雷鬼" #: quodlibet/ext/events/equalizer.py:50 msgid "Headphones" msgstr "耳機" #: quodlibet/ext/events/equalizer.py:53 msgid "Soft Rock" msgstr "輕柔搖滾" #: quodlibet/ext/events/equalizer.py:55 msgid "Full Treble" msgstr "重高音" #: quodlibet/ext/events/equalizer.py:58 msgid "Dance" msgstr "舞曲" #: quodlibet/ext/events/equalizer.py:62 msgid "Techno" msgstr "電子舞曲" #: quodlibet/ext/events/equalizer.py:64 msgid "Ska" msgstr "斯卡" #: quodlibet/ext/events/equalizer.py:66 msgid "Laptop" msgstr "筆記電腦" #: quodlibet/ext/events/equalizer.py:112 msgid "Equalizer" msgstr "等化器" #: quodlibet/ext/events/equalizer.py:113 msgid "" "Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels (right-click resets the band)." msgstr "" "用等化器進行音樂聲調的調控。\n" "點按一下或是使用按鍵來訂定層次 (右鍵則是重設樂曲)。" #: quodlibet/ext/events/equalizer.py:150 msgid "The current backend does not support equalization." msgstr "目前後端不支援等化器。" #: quodlibet/ext/events/equalizer.py:156 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: quodlibet/ext/events/equalizer.py:157 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: quodlibet/ext/events/equalizer.py:272 msgid "Default presets" msgstr "預設音色等化器" #: quodlibet/ext/events/equalizer.py:278 quodlibet/ext/events/equalizer.py:305 msgid "Select…" msgstr "選取…" #: quodlibet/ext/events/equalizer.py:293 msgid "_Reset EQ" msgstr "重設 EQ (_R)" #: quodlibet/ext/events/equalizer.py:299 msgid "Custom presets" msgstr "自訂音效等化器" #: quodlibet/ext/events/equalizer.py:315 msgid "_Delete selected" msgstr "刪除所選 (_D)" #: quodlibet/ext/events/equalizer.py:326 msgid "Preset name for saving:" msgstr "音效名稱用於儲存:" #. Save button #: quodlibet/ext/events/equalizer.py:336 #: quodlibet/ext/events/synchronize_to_device.py:391 #: quodlibet/ext/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:220 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:386 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:204 #: quodlibet/ext/songsmenu/playlist.py:56 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:32 quodlibet/qltk/msg.py:57 #: quodlibet/qltk/renamefiles.py:237 quodlibet/qltk/tagsfrompath.py:152 #: quodlibet/qltk/tracknumbers.py:112 msgid "_Save" msgstr "儲存 (_S)" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:28 msgid "online" msgstr "線上" #: quodlibet/ext/events/gajim_status.py:29 msgid "offline" msgstr "離線" #: quodlibet/ext/events/gajim_status.py:30 msgid "chat" msgstr "聊天" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "離開" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:33 msgid "invisible" msgstr "隱身" #: quodlibet/ext/events/gajim_status.py:38 msgid "Gajim Status Message" msgstr "Gajim 狀態訊息" #: quodlibet/ext/events/gajim_status.py:39 msgid "" "Changes Gajim status message according to what you are currently listening " "to." msgstr "更改 Gajim 狀態訊息依據你目前所聆聽的樂曲。" #: quodlibet/ext/events/gajim_status.py:114 quodlibet/ext/events/mqtt.py:47 #: quodlibet/ext/events/telepathy_status.py:75 msgid "paused" msgstr "暫停" #: quodlibet/ext/events/gajim_status.py:145 msgid "Pattern:" msgstr "型式:" #: quodlibet/ext/events/gajim_status.py:154 msgid "" "List accounts, separated by spaces, for changing status message. If none are " "specified, status message of all accounts will be changed." msgstr "" "列示帳號,以空格分開,用於更改狀態訊息。若未指定,全部帳號的狀態訊息均會變" "更。" #: quodlibet/ext/events/gajim_status.py:157 msgid "Accounts:" msgstr "帳號:" #: quodlibet/ext/events/gajim_status.py:161 msgid "Add '[paused]'" msgstr "加上 '[暫停]'" #: quodlibet/ext/events/gajim_status.py:164 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "如果勾選, '[暫停]' 將會在暫時加入狀態訊息" #: quodlibet/ext/events/gajim_status.py:188 msgid "Statuses for which message will be changed" msgstr "所用訊息的狀態將會變更" #: quodlibet/ext/events/headphonemon.py:157 msgid "Pause on Headphone Unplug" msgstr "耳機拔開即刻暫停" #: quodlibet/ext/events/headphonemon.py:158 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." #: quodlibet/ext/events/inhibit.py:50 msgid "Inhibit Screensaver/Suspend" msgstr "停用螢幕保護/暫停休眠" #: quodlibet/ext/events/inhibit.py:51 msgid "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." msgstr "" "On a GNOME desktop, when a song is playing, prevents either the screensaver " "from activating, or prevents the computer from suspending." #: quodlibet/ext/events/inhibit.py:63 msgid "Music is playing" msgstr "音樂播放中" #. Translators: Inhibiting Mode #: quodlibet/ext/events/inhibit.py:123 msgid "Mode:" msgstr "模式:" #: quodlibet/ext/events/inhibit.py:125 msgid "Inhibit Screensaver" msgstr "停用螢幕保護" #: quodlibet/ext/events/inhibit.py:126 msgid "Inhibit Suspend" msgstr "停用暫停休眠" #: quodlibet/ext/events/iradiolog.py:17 msgid "Internet Radio Log" msgstr "網路廣播電台記錄" #: quodlibet/ext/events/iradiolog.py:18 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." #: quodlibet/ext/events/jep118.py:30 msgid "JEP-118" msgstr "JEP-118" #: quodlibet/ext/events/jep118.py:32 #, python-format msgid "Outputs a Jabber User Tunes file to %(path)s." msgstr "Outputs a Jabber User Tunes file to %(path)s." #: quodlibet/ext/events/language.py:21 msgid "Change Language" msgstr "變更語言" #: quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "變更使用者介面語言。" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "系統預設" #: quodlibet/ext/events/language.py:70 quodlibet/qltk/prefs.py:729 msgid "A restart is required for any changes to take effect" msgstr "A restart is required for any changes to take effect" #: quodlibet/ext/events/mediaserver.py:36 msgid "UPnP AV Media Server" msgstr "UPnP AV Media Server" #: quodlibet/ext/events/mediaserver.py:37 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." msgstr "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." #: quodlibet/ext/events/mediaserver.py:44 msgid "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" msgstr "" "Ensure the following is in your rygel config file (~/.config/rygel.conf):" #: quodlibet/ext/events/mpdserver/__init__.py:61 msgid "MPD Server" msgstr "MPD Server" #: quodlibet/ext/events/mpdserver/__init__.py:62 msgid "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." msgstr "" "Allows remote control of Quod Libet using an MPD Client. Streaming, playlist " "and library management are not supported." #: quodlibet/ext/events/mpdserver/__init__.py:76 msgid "_Port:" msgstr "連接埠 (_P):" #: quodlibet/ext/events/mpdserver/__init__.py:119 msgid "Local _IP:" msgstr "本地 _IP:" #: quodlibet/ext/events/mpdserver/__init__.py:125 msgid "P_assword:" msgstr "密碼 (_P):" #: quodlibet/ext/events/mpdserver/__init__.py:161 msgid "Connection" msgstr "連線" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "測試用戶端" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus 支援" #: quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." msgstr "" "Allows control of Quod Libet using the <a href=\"https://mpris2.readthedocs." "io/en/latest/\">MPRIS 2</a> D-Bus Interface Specification. This allows " "various Linux desktop integrations (e.g. multimedia keys)." #: quodlibet/ext/events/mpris/__init__.py:48 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "關閉時隱藏主視窗" #: quodlibet/ext/events/mqtt.py:56 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Accepts QL Patterns e.g. %s" #: quodlibet/ext/events/mqtt.py:62 msgid "MQTT Publisher" msgstr "MQTT Publisher" #: quodlibet/ext/events/mqtt.py:63 msgid "Publishes status messages to an MQTT topic." msgstr "Publishes status messages to an MQTT topic." #: quodlibet/ext/events/mqtt.py:137 msgid "Broker hostname / IP" msgstr "Broker hostname / IP" #: quodlibet/ext/events/mqtt.py:138 msgid "Defaults to localhost" msgstr "Defaults to localhost" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Broker port" #: quodlibet/ext/events/mqtt.py:140 msgid "Defaults to 1883" msgstr "Defaults to 1883" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Broker 使用者名稱" #: quodlibet/ext/events/mqtt.py:144 msgid "Broker password" msgstr "Broker 密碼" #: quodlibet/ext/events/mqtt.py:146 msgid "Topic" msgstr "主旨" #: quodlibet/ext/events/mqtt.py:148 msgid "Playing Pattern" msgstr "播放型式" #: quodlibet/ext/events/mqtt.py:150 msgid "Status text when a song is started." msgstr "Status text when a song is started." #: quodlibet/ext/events/mqtt.py:152 msgid "Paused Pattern" msgstr "暫停型式" #: quodlibet/ext/events/mqtt.py:154 msgid "Text when a song is paused." msgstr "Text when a song is paused." #: quodlibet/ext/events/mqtt.py:156 msgid "No-song Text" msgstr "無曲目時的文字" #: quodlibet/ext/events/mqtt.py:158 msgid "Plain text for when there is no current song" msgstr "Plain text for when there is no current song" #: quodlibet/ext/events/mqtt.py:169 msgid "MQTT Configuration" msgstr "MQTT 設定" #: quodlibet/ext/events/mqtt.py:173 msgid "Status Text" msgstr "狀態文字" #: quodlibet/ext/events/mqtt.py:206 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Connected to broker at %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:210 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "無法連線至 %(host)s:%(port)d (%(msg)s)" #: quodlibet/ext/events/mqtt.py:213 msgid "Connection error" msgstr "連線錯誤" #: quodlibet/ext/events/musicbrainzsync.py:36 msgid "MusicBrainz Sync" msgstr "MusicBrainz 同步" #: quodlibet/ext/events/musicbrainzsync.py:37 msgid "Syncs the rating of a song with MusicBrainz." msgstr "Syncs the rating of a song with MusicBrainz." #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "User_name:" msgstr "使用者名稱 (_n):" #: quodlibet/ext/events/musicbrainzsync.py:84 #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Password:" msgstr "密碼 (_P):" #. verify data #. button = qltk.Button(_("_Verify account data"), #. Icons.DIALOG_INFORMATION) #. button.connect('clicked', check_login) #. table.attach(button, 0, 2, 4, 5) #: quodlibet/ext/events/musicbrainzsync.py:113 #: quodlibet/ext/events/qlscrobbler.py:546 #: quodlibet/ext/songsmenu/lastfmsync.py:296 #: quodlibet/ext/events/listenbrainz/__init__.py:489 msgid "Account" msgstr "帳號" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "通知簡訊" #: quodlibet/ext/events/notify.py:65 msgid "_Title:" msgstr "標題 (_T):" #: quodlibet/ext/events/notify.py:76 quodlibet/ext/events/notify.py:112 msgid "Revert to default pattern" msgstr "還原至預設型式" #: quodlibet/ext/events/notify.py:102 msgid "_Body:" msgstr "_Body:" #: quodlibet/ext/events/notify.py:122 msgid "_Show notification" msgstr "顯示通知 (_S)" #: quodlibet/ext/events/notify.py:140 msgid "Show notifications" msgstr "顯示通知" #: quodlibet/ext/events/notify.py:146 msgid "Only on <i>_manual</i> song changes" msgstr "Only on <i>_manual</i> song changes" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Only on <i>_automatic</i> song changes" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "On <i>a_ll</i> song changes" #: quodlibet/ext/events/notify.py:177 msgid "Only when the main window is not _focused" msgstr "Only when the main window is not _focused" #: quodlibet/ext/events/notify.py:185 msgid "Show \"_Next\" button" msgstr "顯示 \"下一個\" 按鈕 (_N)" #: quodlibet/ext/events/notify.py:207 msgid "Connection Error" msgstr "連線錯誤" #: quodlibet/ext/events/notify.py:208 quodlibet/ext/events/notify.py:368 #: quodlibet/ext/events/notify.py:410 msgid "Couldn't connect to notification daemon." msgstr "無法連線至通知台。" #: quodlibet/ext/events/notify.py:222 msgid "Song Notifications" msgstr "曲目通知" #: quodlibet/ext/events/notify.py:223 msgid "Displays a notification when the song changes." msgstr "當曲目變更時顯示通知。" #: quodlibet/ext/events/notify.py:392 quodlibet/qltk/unity.py:62 msgid "Next" msgstr "下一個" #: quodlibet/ext/events/notify_bookmarks.py:34 msgid "Bookmark Notifications" msgstr "書籤通知" #: quodlibet/ext/events/notify_bookmarks.py:35 msgid "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." msgstr "" "Uses notifications to display bookmarks / comments in real-time. Works well " "for the Soundcloud browser." #: quodlibet/ext/events/qlscrobbler.py:183 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." #: quodlibet/ext/events/qlscrobbler.py:260 #, python-format msgid "Could not contact service '%s'." msgstr "無法聯繫服務 '%s' 。" #: quodlibet/ext/events/qlscrobbler.py:266 msgid "Authentication failed: invalid URL." msgstr "授權失敗:無效的 URL 。" #: quodlibet/ext/events/qlscrobbler.py:283 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Authentication failed: Invalid username '%s' or bad password." #: quodlibet/ext/events/qlscrobbler.py:288 msgid "Client is banned. Contact the author." msgstr "Client is banned. Contact the author." #: quodlibet/ext/events/qlscrobbler.py:292 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "Wrong system time. Submissions may fail until it is corrected." #: quodlibet/ext/events/qlscrobbler.py:356 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler Submission" #: quodlibet/ext/events/qlscrobbler.py:357 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." #: quodlibet/ext/events/qlscrobbler.py:475 msgid "Authentication successful." msgstr "授權成功。" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_Service:" msgstr "服務 (_S):" #: quodlibet/ext/events/qlscrobbler.py:487 msgid "_URL:" msgstr "_URL網址:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:503 msgid "Other…" msgstr "其他…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:541 msgid "_Verify account data" msgstr "驗證帳號資料 (_V)" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Artist pattern:" msgstr "藝人型式 (_A):" #: quodlibet/ext/events/qlscrobbler.py:554 #: quodlibet/ext/events/listenbrainz/__init__.py:497 msgid "_Title pattern:" msgstr "標題型式 (_T):" #: quodlibet/ext/events/qlscrobbler.py:555 #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "Exclude _filter:" msgstr "不含篩選 (_f):" #: quodlibet/ext/events/qlscrobbler.py:573 #: quodlibet/ext/events/listenbrainz/__init__.py:516 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "The pattern used to format the artist name for submission. Leave blank for " "default." #: quodlibet/ext/events/qlscrobbler.py:584 #: quodlibet/ext/events/listenbrainz/__init__.py:526 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "The pattern used to format the title for submission. Leave blank for default." #: quodlibet/ext/events/qlscrobbler.py:593 msgid "Songs matching this filter will not be submitted" msgstr "Songs matching this filter will not be submitted" #: quodlibet/ext/events/qlscrobbler.py:601 #: quodlibet/ext/events/listenbrainz/__init__.py:553 msgid "_Offline mode (don't submit anything)" msgstr "_Offline mode (don't submit anything)" #: quodlibet/ext/events/qlscrobbler.py:605 #: quodlibet/ext/events/listenbrainz/__init__.py:557 msgid "Submission" msgstr "提交" #: quodlibet/ext/events/radioadmute.py:20 msgid "Mute Radio Ads" msgstr "靜音電台廣告" #: quodlibet/ext/events/radioadmute.py:21 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." #: quodlibet/ext/events/randomalbum.py:26 msgid "Random Album Playback" msgstr "隨機專輯播放" #: quodlibet/ext/events/randomalbum.py:27 msgid "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." msgstr "" "Starts a random album when your playlist reaches its end. It requires that " "your active browser supports filtering by album." #: quodlibet/ext/events/randomalbum.py:37 msgid "Rated higher" msgstr "評分較高的" #: quodlibet/ext/events/randomalbum.py:38 msgid "Played more often" msgstr "較常播放的" #: quodlibet/ext/events/randomalbum.py:39 msgid "Skipped more often" msgstr "跳過常播的" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more recently" msgstr "播放最近常用" #: quodlibet/ext/events/randomalbum.py:41 msgid "Started more recently" msgstr "開始最近常用" #: quodlibet/ext/events/randomalbum.py:42 msgid "Added more recently" msgstr "增加最近常用" #: quodlibet/ext/events/randomalbum.py:43 msgid "Longer albums" msgstr "較長專輯" #: quodlibet/ext/events/randomalbum.py:82 msgid "seconds before starting next album" msgstr "開始播放下個專輯之前秒數" #: quodlibet/ext/events/randomalbum.py:86 msgid "Weights" msgstr "加權" #: quodlibet/ext/events/randomalbum.py:88 msgid "Play some albums more than others" msgstr "播放某些專輯更加常用" #: quodlibet/ext/events/randomalbum.py:102 msgid "avoid" msgstr "避開" #: quodlibet/ext/events/randomalbum.py:113 msgid "prefer" msgstr "偏好" #: quodlibet/ext/events/randomalbum.py:215 msgid "Random Album" msgstr "隨機專輯" #: quodlibet/ext/events/randomalbum.py:216 #, python-format msgid "Waiting to start %s" msgstr "等待啟動 %s" #: quodlibet/ext/events/rbimport.py:120 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "成功匯入評分及統計資料 %d 曲目" #: quodlibet/ext/events/rbimport.py:128 msgid "Rhythmbox Import" msgstr "Rhythmbox 匯入" #: quodlibet/ext/events/rbimport.py:129 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Imports ratings and song statistics from Rhythmbox." #: quodlibet/ext/events/screensaver.py:26 msgid "Screensaver Pause" msgstr "螢幕保護暫停" #: quodlibet/ext/events/screensaver.py:27 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Pauses playback while the GNOME screensaver is active." #: quodlibet/ext/events/searchprovider.py:70 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "No GNOME Shell search provider for Quod Libet installed." #: quodlibet/ext/events/searchprovider.py:71 #, python-format msgid "Have you copied the ini file to %s (or similar)?" msgstr "" #: quodlibet/ext/events/searchprovider.py:77 msgid "GNOME Search Provider" msgstr "GNOME Search Provider" #: quodlibet/ext/events/searchprovider.py:78 msgid "Allows GNOME Shell to search the library." msgstr "允許 GNOME Shell 去搜尋音樂庫。" #: quodlibet/ext/events/seekbar.py:122 msgid "Alternative Seek Bar" msgstr "替用尋找列" #: quodlibet/ext/events/seekbar.py:123 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Alternative seek bar which is always visible and spans the whole window " "width." #: quodlibet/ext/events/seekpoints.py:20 msgid "Seekpoint Bookmarks" msgstr "Seekpoint 書籤" #: quodlibet/ext/events/seekpoints.py:24 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." msgstr "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\n" "\n" "ℹ Note that changing the names of the points below does not update the " "actual bookmark names, it only changes which bookmark names the plugin looks " "for when deciding whether to seek." #: quodlibet/ext/events/seekpoints.py:108 msgid "Bookmark name for point A" msgstr "書籤名稱 用於 point A" #: quodlibet/ext/events/seekpoints.py:109 msgid "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" msgstr "" "Bookmark name to check for when a track is started, and if found the player " "seeks to that timestamp" #: quodlibet/ext/events/seekpoints.py:124 msgid "Bookmark name for point B" msgstr "書籤名稱 用於 point B" #: quodlibet/ext/events/seekpoints.py:125 msgid "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." msgstr "" "Bookmark name to use each tick during play of a track if it exist. If the " "current position exceeds the timestamp, seek to the end of the track." #: quodlibet/ext/events/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Squeezebox 同步" #: quodlibet/ext/events/squeezebox_sync.py:30 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." #: quodlibet/ext/events/squeezebox_sync.py:32 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." msgstr "" "Shares configuration with <a href=\"%(plugin_link)s\">Export to Squeezebox " "plugin</a>." #: quodlibet/ext/events/squeezebox_sync.py:61 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Error finding Squeezebox server" #: quodlibet/ext/events/squeezebox_sync.py:62 #: quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Error finding %s. 請檢查設定" #: quodlibet/ext/events/stop_on_pause.py:22 msgid "Stop on Pause" msgstr "暫停時停止" #: quodlibet/ext/events/stop_on_pause.py:24 msgid "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." msgstr "" "This plugin changes Pause to Stop/Play/Seek.\n" "\n" "Useful if Quod Libet can't switch audio devices when a new one (Bluetooth " "speaker, USB DAC, etc.) is added to the system.\n" "\n" "Ensures position in the current source is maintained so long as 'Only " "Seekable Sources' is off. Otherwise, playback is left stopped and must be " "restarted from the beginning." #: quodlibet/ext/events/stop_on_pause.py:75 msgid "Only Seekable Sources" msgstr "Only Seekable Sources" #: quodlibet/ext/events/stop_on_pause.py:86 msgid "Plugin Options" msgstr "外掛選項" #: quodlibet/ext/events/synchronize_to_device.py:51 msgid "Pending copy" msgstr "有待複製" #: quodlibet/ext/events/synchronize_to_device.py:52 msgid "Pending delete" msgstr "有待刪除" #: quodlibet/ext/events/synchronize_to_device.py:53 msgid "delete" msgstr "刪除" #: quodlibet/ext/events/synchronize_to_device.py:54 msgid "Skip" msgstr "跳過" #: quodlibet/ext/events/synchronize_to_device.py:55 msgid "DUPLICATE" msgstr "重複" #: quodlibet/ext/events/synchronize_to_device.py:56 msgid "Synchronizing" msgstr "同步" #: quodlibet/ext/events/synchronize_to_device.py:57 msgid "Deleting" msgstr "刪除中" #: quodlibet/ext/events/synchronize_to_device.py:58 msgid "Success" msgstr "成功" #: quodlibet/ext/events/synchronize_to_device.py:59 msgid "FAILURE" msgstr "失敗" #: quodlibet/ext/events/synchronize_to_device.py:60 msgid "Skipped existing file" msgstr "跳過現有檔案" #: quodlibet/ext/events/synchronize_to_device.py:80 msgid "Cannot set the filename of a song." msgstr "無法設定曲目檔名。" #: quodlibet/ext/events/synchronize_to_device.py:86 msgid "Synchronize to Device" msgstr "同步至裝置" #: quodlibet/ext/events/synchronize_to_device.py:87 msgid "" "Synchronizes all songs from the selected saved searches with the specified " "folder." msgstr "" "Synchronizes all songs from the selected saved searches with the specified " "folder." #: quodlibet/ext/events/synchronize_to_device.py:140 msgid "Synchronize the following saved searches:" msgstr "同步以下已存的搜尋:" #: quodlibet/ext/events/synchronize_to_device.py:146 msgid "The absolute path to your export location" msgstr "The absolute path to your export location" #: quodlibet/ext/events/synchronize_to_device.py:163 msgid "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." msgstr "" "All pre-existing files in the destination folder that aren't in the saved " "searches will be deleted." #: quodlibet/ext/events/synchronize_to_device.py:167 msgid "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." msgstr "" "For devices mounted with MTP, export to a local destination folder, then " "transfer it to your device with rsync. Or, when syncing many files to an " "Android Device, use adb-sync, which is much faster." #: quodlibet/ext/events/synchronize_to_device.py:178 msgid "Destination path:" msgstr "目的路徑:" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "路徑型式" #: quodlibet/ext/events/synchronize_to_device.py:184 #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "編輯已存型式…" #: quodlibet/ext/events/synchronize_to_device.py:189 msgid "The structure of the exported filenames, based on their tags" msgstr "The structure of the exported filenames, based on their tags" #: quodlibet/ext/events/synchronize_to_device.py:195 msgid "Export pattern:" msgstr "匯出型式:" #. Stop preview button #: quodlibet/ext/events/synchronize_to_device.py:207 msgid "Stop preview" msgstr "停止預覽" #: quodlibet/ext/events/synchronize_to_device.py:226 #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "狀態" #: quodlibet/ext/events/synchronize_to_device.py:233 msgid "Source File" msgstr "來源檔案" #: quodlibet/ext/events/synchronize_to_device.py:242 msgid "Export Path" msgstr "匯出路徑" #: quodlibet/ext/events/synchronize_to_device.py:252 msgid "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." msgstr "" "Duplicate export paths detected! The export paths above can be edited before " "starting the synchronization." #: quodlibet/ext/events/synchronize_to_device.py:256 msgid "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" msgstr "" "Existing files in the destination path will be deleted (except files named " "'cover.jpg')!" #. Start sync button #: quodlibet/ext/events/synchronize_to_device.py:272 msgid "Start synchronization" msgstr "開始同步" #. Stop sync button #: quodlibet/ext/events/synchronize_to_device.py:280 msgid "Stop synchronization" msgstr "停止同步" #: quodlibet/ext/events/synchronize_to_device.py:303 msgid "No saved searches yet, create some and come back!" msgstr "No saved searches yet, create some and come back!" #: quodlibet/ext/events/synchronize_to_device.py:385 msgid "Choose destination path" msgstr "選擇目的路徑" #: quodlibet/ext/events/synchronize_to_device.py:537 #, python-brace-format msgid "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" msgstr "" "Export path changed from [{old_path}] to [{new_path}] for file [{filename}]" #: quodlibet/ext/events/synchronize_to_device.py:651 msgid "Starting synchronization preview" msgstr "開始同步預覽" #: quodlibet/ext/events/synchronize_to_device.py:656 msgid "Synchronization preview in progress." msgstr "同步預覽進行中。" #: quodlibet/ext/events/synchronize_to_device.py:672 msgid "Finished synchronization preview" msgstr "結束同步預覽" #: quodlibet/ext/events/synchronize_to_device.py:681 msgid "Stopping synchronization preview" msgstr "停止同步預覽" #: quodlibet/ext/events/synchronize_to_device.py:683 msgid "Synchronization preview was stopped." msgstr "同步預覽已被停止。" #: quodlibet/ext/events/synchronize_to_device.py:686 msgid "Synchronization preview has finished." msgstr "同步預覽已經停止。" #: quodlibet/ext/events/synchronize_to_device.py:716 msgid "Stopped synchronization preview" msgstr "停止同步預覽" #: quodlibet/ext/events/synchronize_to_device.py:720 msgid "A different plugin was selected - stop preview" msgstr "A different plugin was selected - stop preview" #: quodlibet/ext/events/synchronize_to_device.py:758 msgid "Synchronization will:" msgstr "同步將要:" #: quodlibet/ext/events/synchronize_to_device.py:764 #, python-brace-format msgid "attempt to write {count} file" msgid_plural "attempt to write {count} files" msgstr[0] "寫入 {count} 檔案" #: quodlibet/ext/events/synchronize_to_device.py:771 #, python-brace-format msgid "skip {count} duplicate file" msgid_plural "skip {count} duplicate files" msgstr[0] "跳過 {count} 重複檔案" #: quodlibet/ext/events/synchronize_to_device.py:781 #, python-brace-format msgid "delete {count} file" msgid_plural "delete {count} files" msgstr[0] "刪除 {count} 檔案" #: quodlibet/ext/events/synchronize_to_device.py:831 msgid "No destination path provided" msgstr "No destination path provided" #: quodlibet/ext/events/synchronize_to_device.py:832 msgid "Please specify the directory where songs should be exported." msgstr "Please specify the directory where songs should be exported." #: quodlibet/ext/events/synchronize_to_device.py:839 msgid "No export pattern provided" msgstr "No export pattern provided" #: quodlibet/ext/events/synchronize_to_device.py:840 msgid "Please specify an export pattern for the names of the exported songs." msgstr "Please specify an export pattern for the names of the exported songs." #: quodlibet/ext/events/synchronize_to_device.py:850 msgid "Export path is not absolute" msgstr "匯出不是絕對路徑" #: quodlibet/ext/events/synchronize_to_device.py:851 msgid "" "The pattern\n" "\n" "{}\n" "\n" "contains \"/\" but does not start from root. Please provide an absolute " "destination path by making sure it starts with / or ~/." msgstr "" "這個型式\n" "\n" "{}\n" "\n" "包含 / 但不是以根目錄為起始。要避免呼叫錯誤的資料夾,您的起始目錄格式應為 / " "或 ~/。" #: quodlibet/ext/events/synchronize_to_device.py:873 msgid "No saved searches selected" msgstr "沒有已存搜尋被選取" #: quodlibet/ext/events/synchronize_to_device.py:874 msgid "Please select at least one saved search." msgstr "Please select at least one saved search." #: quodlibet/ext/events/synchronize_to_device.py:883 msgid "No songs in the selected saved searches" msgstr "No songs in the selected saved searches" #: quodlibet/ext/events/synchronize_to_device.py:884 msgid "All selected saved searches are empty." msgstr "All selected saved searches are empty." #: quodlibet/ext/events/synchronize_to_device.py:887 msgid "Found {} songs to synchronize" msgstr "找到 {} 曲目進行同步" #: quodlibet/ext/events/synchronize_to_device.py:906 msgid "Mismatch between destination path and export pattern" msgstr "Mismatch between destination path and export pattern" #: quodlibet/ext/events/synchronize_to_device.py:908 msgid "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" msgstr "" "The export pattern starts with a path that differs from the destination " "path. Please correct the pattern.\n" "\n" "Error:\n" "{}" #: quodlibet/ext/events/synchronize_to_device.py:946 msgid "Unable to sync" msgstr "無法進行同步" #: quodlibet/ext/events/synchronize_to_device.py:947 msgid "Cannot start synchronization while sorting by <b>Status</b>." msgstr "Cannot start synchronization while sorting by <b>Status</b>." #: quodlibet/ext/events/synchronize_to_device.py:951 msgid "Starting song synchronization" msgstr "開始曲目同步" #. Summary labels #: quodlibet/ext/events/synchronize_to_device.py:955 msgid "Synchronization in progress." msgstr "同步進行中。" #: quodlibet/ext/events/synchronize_to_device.py:967 msgid "Finished song synchronization" msgstr "結束曲目同步" #: quodlibet/ext/events/synchronize_to_device.py:976 msgid "Stopping song synchronization" msgstr "停止曲目同步" #: quodlibet/ext/events/synchronize_to_device.py:977 msgid "Synchronization was stopped." msgstr "曲目同步已補停止。" #: quodlibet/ext/events/synchronize_to_device.py:979 msgid "Synchronization has finished." msgstr "曲目同步已結束。" #: quodlibet/ext/events/synchronize_to_device.py:1012 msgid "Stopped song synchronization" msgstr "已停止曲目同步" #: quodlibet/ext/events/synchronize_to_device.py:1016 msgid "A different plugin was selected - stop synchronization" msgstr "A different plugin was selected - stop synchronization" #: quodlibet/ext/events/synchronize_to_device.py:1019 #, python-brace-format msgid "{tag} - \"{filename}\"" msgstr "{tag} - \"{filename}\"" #: quodlibet/ext/events/synchronize_to_device.py:1089 msgid "Removing \"{}\"" msgstr "正在移除 \"{}\"" #: quodlibet/ext/events/synchronize_to_device.py:1110 msgid "Synchronization has:" msgstr "同步已經:" #: quodlibet/ext/events/synchronize_to_device.py:1118 #, python-brace-format msgid "written {count}/{total} file" msgid_plural "written {count}/{total} files" msgstr[0] "寫入 {count}/{total} 檔案" #: quodlibet/ext/events/synchronize_to_device.py:1125 #, python-brace-format msgid "(skipped {count} existing file)" msgid_plural "(skipped {count} existing files)" msgstr[0] "(跳過 {count} 現有檔案)" #: quodlibet/ext/events/synchronize_to_device.py:1134 #, python-brace-format msgid "skipped {count}/{total} duplicate file" msgid_plural "skipped {count}/{total} duplicate files" msgstr[0] "跳過 {count}/{total} 重複檔案" #: quodlibet/ext/events/synchronize_to_device.py:1141 #, python-brace-format msgid "deleted {count}/{total} file" msgid_plural "deleted {count}/{total} files" msgstr[0] "刪除 {count}/{total} 重複檔案" #: quodlibet/ext/events/synchronize_to_device.py:1148 #, python-brace-format msgid "failed to sync {count} file" msgid_plural "failed to sync {count} files" msgstr[0] "無法同步 {count} 檔案" #: quodlibet/ext/events/synchronize_to_device.py:1155 #, python-brace-format msgid "skipped {count} file synchronized previously" msgid_plural "skipped {count} files synchronized previously" msgstr[0] "跳過 {count} 檔案先前已同步過" #: quodlibet/ext/events/synchronizedlyrics.py:29 msgid "Synchronized Lyrics" msgstr "同步歌詞" #: quodlibet/ext/events/synchronizedlyrics.py:30 msgid "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." msgstr "" "Shows synchronized lyrics from an .lrc file with same name as the track (or " "similar)." #: quodlibet/ext/events/synchronizedlyrics.py:68 msgid "Text:" msgstr "文字:" #: quodlibet/ext/events/synchronizedlyrics.py:78 msgid "Background:" msgstr "背景:" #: quodlibet/ext/events/synchronizedlyrics.py:89 msgid "Font" msgstr "字型" #: quodlibet/ext/events/synchronizedlyrics.py:92 msgid "Size (px):" msgstr "大小 (px):" #: quodlibet/ext/events/telepathy_status.py:68 msgid "Telepathy Status Messages" msgstr "Telepathy 狀態訊息" #: quodlibet/ext/events/telepathy_status.py:69 msgid "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." msgstr "" "Updates all Telepathy-based IM accounts (as configured in Empathy etc) with " "a status message based on current song." #: quodlibet/ext/events/telepathy_status.py:128 msgid "Playing:" msgstr "播放中:" #: quodlibet/ext/events/telepathy_status.py:129 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "Status text when a song is started. Accepts QL Patterns e.g. %s" #: quodlibet/ext/events/telepathy_status.py:144 msgid "Paused:" msgstr "暫停:" #: quodlibet/ext/events/telepathy_status.py:145 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "Status text when a song is paused. Accepts QL Patterns e.g. %s" #: quodlibet/ext/events/telepathy_status.py:160 msgid "Plain text for status when there is no current song" msgstr "Plain text for status when there is no current song" #: quodlibet/ext/events/telepathy_status.py:161 msgid "No song:" msgstr "無曲目:" #. Frame #: quodlibet/ext/events/telepathy_status.py:168 msgid "Status Patterns" msgstr "狀態型式" #: quodlibet/ext/events/themeswitcher.py:25 msgid "Theme Switcher" msgstr "主題切換" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Changes the active GTK+ theme." msgstr "更改現行 GTK+ 主題。" #: quodlibet/ext/events/themeswitcher.py:49 msgid "_Theme:" msgstr "主題 (_T):" #: quodlibet/ext/events/themeswitcher.py:54 msgid "Default Theme" msgstr "預設主題" #: quodlibet/ext/events/themeswitcher.py:66 msgid "Prefer dark theme version" msgstr "偏好暗色主題版本" #: quodlibet/ext/events/thumbrating.py:89 msgid "Thumb Rating" msgstr "姆指評分" #: quodlibet/ext/events/thumbrating.py:90 msgid "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." msgstr "" "Adds a thumb-up / thumb-down scoring system which is converted to a rating " "value. Useful for keeping running vote totals and sorting by <b><tt>~#score</" "tt></b>." #: quodlibet/ext/events/toggle_menu.py:18 msgid "Toggle Menu Bar" msgstr "切換功能表" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle the menu bar by pressing the Alt key." msgstr "按壓 Alt 鍵來切換功能表。" #: quodlibet/ext/events/trayicon/appindicator.py:76 #: quodlibet/ext/events/trayicon/prefs.py:106 #: quodlibet/ext/events/trayicon/systemtray.py:177 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "尚未播放" #: quodlibet/ext/events/trayicon/__init__.py:52 msgid "Tray Icon" msgstr "系統匣圖示" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Controls Quod Libet from the system tray." msgstr "調控 Quod Libet 從系統匣。" #: quodlibet/ext/events/trayicon/menu.py:41 #, python-format msgid "_Show %(application-name)s" msgstr "顯示 (_S) %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:60 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:951 #: quodlibet/qltk/quodlibetwindow.py:1167 msgid "_Play" msgstr "播放 (_P)" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1169 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "暫停 (_a)" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:946 msgid "Pre_vious" msgstr "前一首 (_v)" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:956 msgid "_Next" msgstr "下一首 (_N)" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "隨機 (_S)" #: quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "重覆播放 (_R)" #: quodlibet/ext/events/trayicon/menu.py:86 msgid "Stop _After This Song" msgstr "在這首歌播完之後停止 (_A)" #: quodlibet/ext/events/trayicon/menu.py:92 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "Open _Browser" msgstr "開啟瀏覽窗 (_B)" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/songsmenu.py:378 msgid "Edit _Tags" msgstr "編輯標籤 (_T)" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:879 quodlibet/qltk/songsmenu.py:392 msgid "_Information" msgstr "資訊 (_I)" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:319 msgid "Play_lists" msgstr "播放清單 (_l)" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "_Quit" msgstr "停止 (_Q)" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:87 #: quodlibet/qltk/prefs.py:459 quodlibet/qltk/prefs.py:736 msgid "Behavior" msgstr "動作" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "滾輪調整音量" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "滾輪變換曲目" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "滾輪 (_W)" #: quodlibet/ext/events/trayicon/prefs.py:92 msgid "Tooltip Display" msgstr "顯示提示" #: quodlibet/ext/events/viewlyrics.py:25 msgid "View Lyrics" msgstr "查看歌詞" #: quodlibet/ext/events/viewlyrics.py:26 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "在側邊欄自動顯示標籤或檔案內歌詞。" #: quodlibet/ext/events/viewlyrics.py:87 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "找不到歌詞\n" " %s" #: quodlibet/ext/events/viewlyrics.py:117 msgid "No active song" msgstr "無法作用此曲" #: quodlibet/ext/events/visualisations.py:36 msgid "Launch Visualisations" msgstr "啟動視覺化" #: quodlibet/ext/events/visualisations.py:38 msgid "Launch external visualisations." msgstr "啟動外部視覺化。" #: quodlibet/ext/events/visualisations.py:55 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "無法執行視覺化使用 '%s'" #: quodlibet/ext/events/visualisations.py:57 #: quodlibet/ext/songsmenu/fingerprint/search.py:44 msgid "Error" msgstr "錯誤" #: quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "視覺化可執行:" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "重新載入" #: quodlibet/ext/events/waveformseekbar.py:602 msgid "Waveform Seek Bar" msgstr "定位列波形狀" #: quodlibet/ext/events/waveformseekbar.py:605 msgid "∿ A seekbar in the shape of the waveform of the current song." msgstr "∿ A seekbar in the shape of the waveform of the current song." #: quodlibet/ext/events/waveformseekbar.py:674 msgid "Override foreground color:" msgstr "改寫前景顏色:" #: quodlibet/ext/events/waveformseekbar.py:678 msgid "Override hover color:" msgstr "改寫浮標顏色:" #: quodlibet/ext/events/waveformseekbar.py:682 msgid "Override remaining color:" msgstr "改寫其他顏色:" #: quodlibet/ext/events/waveformseekbar.py:686 msgid "Show current position" msgstr "顯示目前位置" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show time labels" msgstr "顯示時間" #: quodlibet/ext/events/waveformseekbar.py:698 msgid "Seek amount when scrolling (milliseconds):" msgstr "滾輪定位值量(毫秒):" #: quodlibet/ext/events/write_cover.py:33 msgid "Picture Saver" msgstr "圖片存入檔案" #: quodlibet/ext/events/write_cover.py:34 msgid "Saves the cover image of the current song to a file." msgstr "儲存封面圖片至目前歌曲檔案。" #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "檔案:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "_Threshold:" msgstr "_Threshold:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Threshold until the filter is activated" msgstr "Threshold until the filter is activated" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "R_atio:" msgstr "比例 (_a):" #: quodlibet/ext/gstreamer/compressor.py:23 msgid "Compression ratio" msgstr "壓縮比例" #: quodlibet/ext/gstreamer/compressor.py:75 #: quodlibet/ext/gstreamer/karaoke.py:92 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:236 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Audio Compressor" msgstr "音樂作曲" #: quodlibet/ext/gstreamer/compressor.py:107 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Preset:" msgstr "_Preset:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Filter preset" msgstr "篩選 preset" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "_Frequency cut:" msgstr "_Frequency cut:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Low-pass filter cut frequency" msgstr "Low-pass filter cut frequency" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed _level:" msgstr "Feed _level:" #: quodlibet/ext/gstreamer/crossfeed.py:22 msgid "Feed level" msgstr "Feed level" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Default" msgstr "預設" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Closest to virtual speaker placement (30°, 3 meter)" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Close to Chu Moy's crossfeeder (popular)" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Close to Jan Meier's CORDA amplifiers (little change)" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "自訂" #: quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom settings" msgstr "自訂設定" #: quodlibet/ext/gstreamer/crossfeed.py:153 msgid "Crossfeed" msgstr "混合 Feed" #: quodlibet/ext/gstreamer/crossfeed.py:154 msgid "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." msgstr "" "Mixes the left and right channel in a way that simulates a speaker setup " "while using headphones, or to adjust for early Stereo recordings." #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "Filter _band:" msgstr "篩選樂團 (_b):" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "The Frequency band of the filter" msgstr "The Frequency band of the filter" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "Filter _width:" msgstr "篩選寬度 (_w):" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "The Frequency width of the filter" msgstr "The Frequency width of the filter" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "_Level:" msgstr "層級 (_L):" #: quodlibet/ext/gstreamer/karaoke.py:25 msgid "Level of the effect" msgstr "效果層度" #: quodlibet/ext/gstreamer/karaoke.py:106 msgid "Karaoke" msgstr "卡拉OK" #: quodlibet/ext/gstreamer/karaoke.py:107 msgid "Removes main vocals from audio." msgstr "消除主要人聲。" #: quodlibet/ext/gstreamer/mono.py:16 msgid "Mono Downmix" msgstr "調降平板聲調" #: quodlibet/ext/gstreamer/mono.py:17 msgid "Downmixes audio channels to mono." msgstr "Downmixes audio channels to mono." #: quodlibet/ext/gstreamer/pitch.py:22 msgid "R_ate:" msgstr "R_ate:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "_Pitch:" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Audio Pitch / Speed" msgstr "音訊投放 / 速度" #: quodlibet/ext/gstreamer/pitch.py:97 msgid "Controls the pitch of an audio stream." msgstr "控制音訊串流投放。" #: quodlibet/ext/playlist/export_to_folder.py:30 #: quodlibet/ext/playlist/export_to_folder.py:98 #: quodlibet/ext/playlist/export_to_folder.py:146 msgid "Export Playlist to Folder" msgstr "匯出播放清單至資料夾" #: quodlibet/ext/playlist/export_to_folder.py:39 msgid "_Export" msgstr "匯出 (_E)" #: quodlibet/ext/playlist/export_to_folder.py:44 msgid "Destination folder:" msgstr "目的資料夾:" #: quodlibet/ext/playlist/export_to_folder.py:59 msgid "Filename pattern:" msgstr "檔名型態:" #: quodlibet/ext/playlist/export_to_folder.py:99 msgid "Exports a playlist by copying files to a folder." msgstr "匯出播放清單是複製檔案至資料夾。" #: quodlibet/ext/playlist/export_to_folder.py:120 #: quodlibet/ext/songsmenu/playlist.py:143 msgid "Unable to export playlist" msgstr "無法匯出播放清單" #: quodlibet/ext/playlist/export_to_folder.py:121 msgid "Ensure you have write access to the destination." msgstr "確定您可以讀寫目的資料夾。" #: quodlibet/ext/playlist/export_to_folder.py:164 msgid "Default filename pattern:" msgstr "預設檔名型式:" #: quodlibet/ext/playlist/export_to_sonos.py:98 #: quodlibet/ext/_shared/squeezebox/util.py:20 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: quodlibet/ext/playlist/export_to_sonos.py:104 msgid "" "Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite" msgstr "" "輸入新的播放清單名稱,\n" "或是選擇現有的 Sonos 播放清單來覆寫" #: quodlibet/ext/playlist/export_to_sonos.py:132 msgid "Export to Sonos Playlist" msgstr "匯出至 Sonos 播放清單" #: quodlibet/ext/playlist/export_to_sonos.py:133 #, fuzzy msgid "Exports a playlist to Sonos by matching tracks." msgstr "匯出播放清單是複製檔案至資料夾。" #: quodlibet/ext/playlist/export_to_sonos.py:246 msgid "Error finding Sonos device(s)" msgstr "Error finding Sonos device(s)" #: quodlibet/ext/playlist/export_to_sonos.py:247 msgid "Error finding Sonos. Please check settings" msgstr "Error finding Sonos. Please check settings" #: quodlibet/ext/playlist/export_to_sonos.py:264 #, python-format msgid "Failed to delete existing Sonos playlist %s:" msgstr "" #: quodlibet/ext/playlist/export_to_sonos.py:275 #, python-format msgid "Export to playlist %(playlist)r (%(total)d tracks)" msgstr "" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "匯出至 Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 msgid "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." msgstr "" "Dynamically exports a playlist to Logitech Squeezebox playlist, provided " "both share a directory structure." #: quodlibet/ext/playlist/export_to_squeezebox.py:26 #, python-format msgid "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." msgstr "" "Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox Sync " "plugin</a>." #: quodlibet/ext/playlist/export_to_squeezebox.py:78 msgid "Export playlist to Squeezebox" msgstr "匯出播放清單至 Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Playlist name (will overwrite existing)" msgstr "播放清單加稱 (將會改寫現有的)" #: quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "匯出至 Squeezebox 播放清單" #: quodlibet/ext/playlist/remove_duplicates.py:20 msgid "Remove Playlist Duplicates" msgstr "移除從播放清單中重複的" #: quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Removes duplicate entries in a playlist." msgstr "Removes duplicate entries in a playlist." #: quodlibet/ext/playlist/remove_duplicates.py:49 #, python-format msgid "Are you sure you want to remove %d duplicate song?" msgid_plural "Are you sure you want to remove %d duplicate songs?" msgstr[0] "確定要移除 %d 重複曲目?" #: quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "The duplicate songs will be removed from the playlist '%s'." #: quodlibet/ext/playlist/shuffle.py:15 msgid "Shuffle Playlist" msgstr "隨機播放清單" #: quodlibet/ext/playlist/shuffle.py:16 msgid "Randomly shuffles a playlist." msgstr "隨機產生播放清單。" #: quodlibet/ext/playorder/follow.py:18 msgid "Follow Cursor" msgstr "跟隨游標" #: quodlibet/ext/playorder/follow.py:20 msgid "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." msgstr "" "Adds a play order mode that follows your selection, or the next song in the " "list once exhausted." #: quodlibet/ext/playorder/follow.py:22 msgid "Follow cursor" msgstr "跟隨游標" #: quodlibet/ext/playorder/follow.py:23 msgid "_Follow cursor" msgstr "跟隨游標 (_F)" #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "播放計次等化器" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Adds a shuffle mode that prefers songs with fewer total plays." msgstr "Adds a shuffle mode that prefers songs with fewer total plays." #: quodlibet/ext/playorder/playcounteq.py:25 msgid "Prefer less played" msgstr "偏好較少播放的" #: quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer _less played" msgstr "偏好較少播放的 (_l)" #: quodlibet/ext/playorder/queue.py:23 msgid "Queue Only" msgstr "僅限佇列" #: quodlibet/ext/playorder/queue.py:25 msgid "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" "Limits playing of songs to the queue.\n" "\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." #: quodlibet/ext/playorder/queue.py:29 msgid "Queue only" msgstr "僅限佇列" #: quodlibet/ext/playorder/queue.py:30 msgid "_Queue only" msgstr "僅限佇列 (_Q)" #: quodlibet/ext/playorder/queue.py:34 msgid "Automatically start playing double-clicked songs" msgstr "Automatically start playing double-clicked songs" #: quodlibet/ext/playorder/reverse.py:14 quodlibet/ext/playorder/reverse.py:18 msgid "Reverse" msgstr "還原" #: quodlibet/ext/playorder/reverse.py:16 msgid "Adds a shuffle mode that reverses the play order of songs." msgstr "Adds a shuffle mode that reverses the play order of songs." #: quodlibet/ext/playorder/reverse.py:19 msgid "Re_verse" msgstr "還原 (_v)" #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:95 msgid "Shuffle by Grouping" msgstr "依照群組隨機" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." msgstr "" "Adds a shuffle mode that groups songs with a common tag – similar to album " "shuffles.\n" "\n" "This is useful for shuffling multi-movement classical pieces, making sure " "all movements play in order before shuffling to the next piece." #: quodlibet/ext/playorder/shufflebygrouping.py:39 msgid "Shuffle by grouping" msgstr "依照群組隨機" #: quodlibet/ext/playorder/shufflebygrouping.py:40 msgid "Shuffle by _grouping" msgstr "依照群組隨機 (_g)" #: quodlibet/ext/playorder/shufflebygrouping.py:96 msgid "Waiting to start new group…" msgstr "等待去啟動新的群組…" #: quodlibet/ext/playorder/shufflebygrouping.py:146 msgid "Grouping tag:" msgstr "群組標籤:" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Tag to group songs by" msgstr "標籤至群組曲目依照" #: quodlibet/ext/playorder/shufflebygrouping.py:152 msgid "Filter tag:" msgstr "篩選標籤:" #: quodlibet/ext/playorder/shufflebygrouping.py:157 msgid "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." msgstr "" "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag." #: quodlibet/ext/playorder/shufflebygrouping.py:162 msgid "Delay:" msgstr "間隔延遲:" #: quodlibet/ext/playorder/shufflebygrouping.py:168 msgid "Time delay in seconds before starting next group" msgstr "Time delay in seconds before starting next group" #: quodlibet/ext/playorder/shufflebygrouping.py:184 msgid "Reset to defaults" msgstr "重設至預設" #: quodlibet/ext/playorder/skip_disliked.py:24 msgid "Skip Disliked Tracks" msgstr "跳過不喜歡的音軌" #: quodlibet/ext/playorder/skip_disliked.py:26 msgid "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." msgstr "" "Adds a play order (shuffle) mode that plays in order, but skips tracks with " "a rating below (or equal to) a given threshold." #: quodlibet/ext/playorder/skip_disliked.py:29 msgid "Skip disliked tracks" msgstr "跳過不喜歡的音軌" #: quodlibet/ext/playorder/skip_disliked.py:30 msgid "Skip _disliked tracks" msgstr "跳過不喜歡的音軌 (_d)" #: quodlibet/ext/playorder/track_repeat.py:28 msgid "Repeat Each Track" msgstr "重複每個音軌" #: quodlibet/ext/playorder/track_repeat.py:30 msgid "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." msgstr "" "Adds a shuffle mode that plays tracks in order, but repeating every track a " "set number of times." #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Repeat each track" msgstr "重複每個音軌" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Repeat _each track" msgstr "重複每個音軌 (_e)" #: quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "每首曲目播放次數:" #: quodlibet/ext/query/conditional.py:15 msgid "Conditional Query" msgstr "條件查詢" #: quodlibet/ext/query/conditional.py:16 msgid "Chooses the query to match based on a condition query." msgstr "Chooses the query to match based on a condition query." #: quodlibet/ext/query/conditional.py:18 msgid "@(if: condition-query, then-query, else-query)" msgstr "@(if: condition-query, then-query, else-query)" #: quodlibet/ext/query/missing.py:17 msgid "Missing Query" msgstr "遺失查詢" #: quodlibet/ext/query/missing.py:18 msgid "Matches songs without the given tag." msgstr "Matches songs without the given tag." #: quodlibet/ext/query/missing.py:36 msgid "Include empty tags" msgstr "包括空白標籤" #: quodlibet/ext/query/pythonexpression.py:18 msgid "Python Query" msgstr "Python 查詢" #: quodlibet/ext/query/pythonexpression.py:19 msgid "🐍Use Python expressions in queries." msgstr "🐍Use Python expressions in queries." #: quodlibet/ext/query/pythonexpression.py:21 msgid "@(python: expression)" msgstr "@(python: expression)" #: quodlibet/ext/query/pythonexpression.py:23 msgid "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." msgstr "" "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched.\n" "\n" "<tt>_ts</tt> is a (real number) timestamp at start of query.\n" "\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the class " "<tt>Random</tt> (==<tt>random.Random</tt>) too." #: quodlibet/ext/query/savedsearch.py:20 msgid "Include Saved Search" msgstr "包括已儲存搜尋" #: quodlibet/ext/query/savedsearch.py:21 msgid "💾 Include the results of a saved search as part of another query." msgstr "💾 Include the results of a saved search as part of another query." #: quodlibet/ext/query/savedsearch.py:24 msgid "@(saved: search-name)" msgstr "@(saved: search-name)" #: quodlibet/ext/query/unique.py:16 msgid "Unique Query" msgstr "獨特查詢" #: quodlibet/ext/query/unique.py:17 msgid "Filter search results by unique tags." msgstr "Filter search results by unique tags." #: quodlibet/ext/query/unique.py:19 msgid "@(unique: tag)" msgstr "@(unique: tag)" #: quodlibet/ext/_shared/squeezebox/base.py:77 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Using the only player (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:86 #, python-format msgid "Couldn't connect to %s" msgstr "無法連線至 %s" #: quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "主機名稱:" #: quodlibet/ext/_shared/squeezebox/base.py:118 msgid "Port:" msgstr "連接埠:" #: quodlibet/ext/_shared/squeezebox/base.py:125 msgid "Username:" msgstr "使用者名稱:" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Password:" msgstr "密碼:" #: quodlibet/ext/_shared/squeezebox/base.py:138 msgid "Library directory the server connects to" msgstr "音樂庫目錄伺服主機連線至" #: quodlibet/ext/_shared/squeezebox/base.py:140 msgid "Library path:" msgstr "音樂庫路徑:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:151 msgid "_Verify settings" msgstr "驗證設定 (_V)" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:157 msgid "Squeezebox Server" msgstr "Squeezebox 伺服器" #: quodlibet/ext/_shared/squeezebox/base.py:160 msgid "Debug" msgstr "除錯" #: quodlibet/ext/_shared/squeezebox/server.py:27 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox server at {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:29 msgid "unidentified Squeezebox server" msgstr "unidentified Squeezebox server" #: quodlibet/ext/_shared/squeezebox/server.py:38 #, python-format msgid "unidentified Squeezebox player: %r" msgstr "unidentified Squeezebox player: %r" #: quodlibet/ext/_shared/squeezebox/util.py:15 msgid "Choose Squeezebox player" msgstr "Choose Squeezebox player" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Found Squeezebox server.\n" "Please choose the player" #: quodlibet/ext/songsmenu/albumart.py:227 msgid "Fit image to _window" msgstr "圖片符合視窗 (_w)" #: quodlibet/ext/songsmenu/albumart.py:233 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "See '[plugins] cover_filenames' config entry for image filename strings" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:239 msgid "_Program:" msgstr "程式 (_P):" #: quodlibet/ext/songsmenu/albumart.py:244 msgid "_Edit image after saving" msgstr "儲存之後編輯圖片 (_E)" #: quodlibet/ext/songsmenu/albumart.py:246 msgid "File_name:" msgstr "檔案名稱 (_n):" #: quodlibet/ext/songsmenu/albumart.py:362 msgid "Saving failed" msgstr "存檔失敗" #: quodlibet/ext/songsmenu/albumart.py:363 #, python-format msgid "Unable to save \"%s\"." msgstr "無法儲存 \"%s\" 。" #: quodlibet/ext/songsmenu/albumart.py:463 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP 錯誤: %s" #: quodlibet/ext/songsmenu/albumart.py:521 msgid "Album Art Downloader" msgstr "專輯藝術設計下載器" #: quodlibet/ext/songsmenu/albumart.py:574 #, python-format msgid "from %(source)s" msgstr "來自 %(source)s" #: quodlibet/ext/songsmenu/albumart.py:577 #, python-format msgid "Resolution: %s" msgstr "解析度: %s" #: quodlibet/ext/songsmenu/albumart.py:580 #, python-format msgid "Size: %s" msgstr "大小: %s" #: quodlibet/ext/songsmenu/albumart.py:626 msgid "Per engine 'at best' results limit" msgstr "Per engine 'at best' results limit" #: quodlibet/ext/songsmenu/albumart.py:636 msgid "_Search" msgstr "搜尋 (_S)" #: quodlibet/ext/songsmenu/albumart.py:720 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "搜尋中…" #: quodlibet/ext/songsmenu/albumart.py:787 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "完成" #: quodlibet/ext/songsmenu/albumart.py:903 msgid "Download Album Art" msgstr "下載專輯藝術設計" #: quodlibet/ext/songsmenu/albumart.py:904 msgid "Downloads album covers from various websites." msgstr "Downloads album covers from various websites." #: quodlibet/ext/songsmenu/albumart.py:917 msgid "Sources" msgstr "來源" #: quodlibet/ext/songsmenu/ape2id3.py:26 msgid "APEv2 to ID3v2" msgstr "APEv2 to ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." msgstr "" "Converts your APEv2 tags to ID3v2 tags. This will delete the APEv2 tags " "after conversion." #: quodlibet/ext/songsmenu/bookmarks.py:23 msgid "Go to Bookmark" msgstr "前往書籤" #: quodlibet/ext/songsmenu/bookmarks.py:24 msgid "Manages bookmarks in the selected files." msgstr "Manages bookmarks in the selected files." #: quodlibet/ext/songsmenu/bookmarks.py:63 quodlibet/qltk/seekbutton.py:244 msgid "_Edit Bookmarks…" msgstr "編輯書籤 (_E)…" #: quodlibet/ext/songsmenu/bookmarks.py:73 msgid "No Bookmarks" msgstr "沒有書籤" #: quodlibet/ext/songsmenu/brainz/__init__.py:24 msgid "MusicBrainz Lookup" msgstr "MusicBrainz Lookup" #: quodlibet/ext/songsmenu/brainz/__init__.py:26 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Re-tags an album based on a MusicBrainz search." #: quodlibet/ext/songsmenu/brainz/__init__.py:50 msgid "Only use year for \"date\" tag" msgstr "僅使用年度作為\"日期\" 標籤" #: quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Write \"_albumartist\" when needed" msgstr "寫入 \"_albumartist\" 專輯藝人當有需要時" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write sort tags for artist names" msgstr "寫入排序標籤用於藝賴名稱" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write _standard MusicBrainz tags" msgstr "寫入 _standard MusicBrainz 標籤" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write \"labelid\" tag" msgstr "寫入 \"labelid\" 標籤" #: quodlibet/ext/songsmenu/brainz/widgets.py:129 msgid "Filename" msgstr "檔案名稱" #. #: quodlibet/ext/songsmenu/brainz/widgets.py:130 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:562 msgid "Disc" msgstr "碟片" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:563 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "音軌" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:386 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:564 msgid "Title" msgstr "標題" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Artist" msgstr "藝人" #: quodlibet/ext/songsmenu/brainz/widgets.py:352 msgid "MusicBrainz lookup" msgstr "MusicBrainz lookup" #: quodlibet/ext/songsmenu/brainz/widgets.py:375 msgid "_Query:" msgstr "查詢 (_Q):" #: quodlibet/ext/songsmenu/brainz/widgets.py:378 msgid "S_earch" msgstr "搜尋 (_e)" #: quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "結果 <i>(拖放至錄音)</i>" #: quodlibet/ext/songsmenu/brainz/widgets.py:448 msgid "Please enter a query." msgstr "請輸入一個佇列。" #: quodlibet/ext/songsmenu/brainz/widgets.py:466 #: quodlibet/ext/songsmenu/brainz/widgets.py:497 msgid "Error encountered. Please retry." msgstr "發生錯誤。請重新輸入。" #: quodlibet/ext/songsmenu/brainz/widgets.py:473 #: quodlibet/ext/songsmenu/brainz/widgets.py:489 msgid "Loading result…" msgstr "載入結果…" #: quodlibet/ext/songsmenu/brainz/widgets.py:476 msgid "No results found." msgstr "查無結果。" #: quodlibet/ext/songsmenu/console.py:41 msgid "Python Console" msgstr "Python 控表" #: quodlibet/ext/songsmenu/console.py:42 msgid "Interactive Python console. Opens a new window." msgstr "Interactive Python console. Opens a new window." #: quodlibet/ext/songsmenu/console.py:50 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} for {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:57 msgid "Python Console Sidebar" msgstr "Python Console 側邊欄" #: quodlibet/ext/songsmenu/console.py:58 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." #: quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "You can access the following objects by default:" #: quodlibet/ext/songsmenu/console.py:86 msgid "Your current working directory is:" msgstr "您目前工作目錄是:" #: quodlibet/ext/songsmenu/console.py:617 msgid "Completion" msgstr "完整" #: quodlibet/ext/songsmenu/cover_download.py:53 msgid "Download Cover Art" msgstr "下載封面設計" #: quodlibet/ext/songsmenu/cover_download.py:54 msgid "Downloads high-quality album covers using Quod Libet cover plugins." msgstr "Downloads high-quality album covers using Quod Libet cover plugins." #: quodlibet/ext/songsmenu/cover_download.py:159 msgid "Classic" msgstr "古典" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Large" msgstr "大型" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:170 msgid "Cover Art Download" msgstr "封面設計下載" #: quodlibet/ext/songsmenu/cover_download.py:233 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "載入 %(source)s - %(dimensions)s …" #: quodlibet/ext/songsmenu/cover_download.py:296 #, python-format msgid "" "Nothing found for albums:\n" "%(albums)s.\n" "\n" "Providers used:\n" "%(providers)s" msgstr "" "找不到可用於此專輯:\n" "%(albums)s.\n" "\n" "提供者使用:\n" "%(providers)s" #: quodlibet/ext/songsmenu/cover_download.py:299 msgid "No covers found" msgstr "找不到封面" #: quodlibet/ext/songsmenu/cover_download.py:322 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "{size} ✕ {size} px" #: quodlibet/ext/songsmenu/cover_download.py:335 msgid "Preview size" msgstr "預覽大小" #: quodlibet/ext/songsmenu/cover_download.py:344 msgid "Save destination" msgstr "儲存目的" #: quodlibet/ext/songsmenu/cover_download.py:375 msgid "" "If not already a JPEG, convert the image to a high-quality JPEG of the same " "size" msgstr "若無 JPEG,轉換圖片為相同大小的高品質 JPEG 圖檔" #: quodlibet/ext/songsmenu/cover_download.py:377 msgid "Save as JPEG" msgstr "存檔為 JPEG" #: quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "指令" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "name" msgstr "名稱" #: quodlibet/ext/songsmenu/custom_commands.py:44 msgid "The name of this command" msgstr "指令的名稱" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "command" msgstr "指令" #: quodlibet/ext/songsmenu/custom_commands.py:46 msgid "The shell command syntax to run" msgstr "外裝指令語法執行" #: quodlibet/ext/songsmenu/custom_commands.py:48 msgid "parameter" msgstr "參數" #: quodlibet/ext/songsmenu/custom_commands.py:49 #, python-brace-format msgid "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" msgstr "" "If specified, a parameter whose occurrences in the command will be " "substituted with a user-supplied value, e.g. by using 'PARAM' all instances " "of '{PARAM}' in your command will have the value prompted for when run" #: quodlibet/ext/songsmenu/custom_commands.py:56 msgid "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." msgstr "" "The QL pattern, e.g. <~filename>, to use to compute a value for the command. " "For playlists, this also supports virtual tags <~playlistname> and " "<~#playlistindex>." #: quodlibet/ext/songsmenu/custom_commands.py:61 msgid "unique" msgstr "獨特性" #: quodlibet/ext/songsmenu/custom_commands.py:62 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "If set, this will remove duplicate computed values of the pattern" #: quodlibet/ext/songsmenu/custom_commands.py:65 msgid "max args" msgstr "最大參數" #: quodlibet/ext/songsmenu/custom_commands.py:66 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "The maximum number of argument to pass to the command at one time (like " "xargs)" #: quodlibet/ext/songsmenu/custom_commands.py:69 msgid "reverse" msgstr "還原" #: quodlibet/ext/songsmenu/custom_commands.py:70 msgid "If set, the argument list will be reversed" msgstr "If set, the argument list will be reversed" #: quodlibet/ext/songsmenu/custom_commands.py:95 msgid "Input value" msgstr "輸入值" #: quodlibet/ext/songsmenu/custom_commands.py:96 #, python-format msgid "Value for %s?" msgstr "設定值用於 %s?" #: quodlibet/ext/songsmenu/custom_commands.py:145 msgid "Custom Commands" msgstr "自訂指令" #: quodlibet/ext/songsmenu/custom_commands.py:146 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Runs custom commands (in batches if required) on songs using any of their " "tags." #: quodlibet/ext/songsmenu/custom_commands.py:211 #: quodlibet/ext/songsmenu/custom_commands.py:221 #: quodlibet/ext/songsmenu/custom_commands.py:273 msgid "Edit Custom Commands" msgstr "編頟自訂指令" #: quodlibet/ext/songsmenu/custom_commands.py:304 #, python-format msgid "Unable to run custom command %s" msgstr "無法執行自訂指令 %s" #: quodlibet/ext/songsmenu/duplicates.py:285 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d 重複群組" #: quodlibet/ext/songsmenu/duplicates.py:338 msgid "Collapse / Expand all" msgstr "縮合 / 展開全部" #: quodlibet/ext/songsmenu/duplicates.py:342 #, python-format msgid "Duplicate key expression is '%s'" msgstr "重複 key expression 是 '%s'" #: quodlibet/ext/songsmenu/duplicates.py:358 msgid "Duplicates Browser" msgstr "重複瀏覽窗" #: quodlibet/ext/songsmenu/duplicates.py:359 msgid "Finds and displays similarly tagged versions of songs." msgstr "找出並顯示相類似已標籤的曲目版本。" #: quodlibet/ext/songsmenu/duplicates.py:396 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:398 msgid "_Group duplicates by:" msgstr "群組重複依照 (_G):" #: quodlibet/ext/songsmenu/duplicates.py:403 msgid "Duplicate Key" msgstr "重複 Key" #: quodlibet/ext/songsmenu/duplicates.py:408 msgid "Remove _Whitespace" msgstr "移除空白格 (_W)" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Diacritics" msgstr "移除讀符號 (_D)" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Punctuation" msgstr "移除標點符號 (_P)" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Case _Insensitive" msgstr "大小寫區別 (_i)" #: quodlibet/ext/songsmenu/duplicates.py:419 msgid "Matching options" msgstr "符合選項" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:43 msgid "Edit Playcount" msgstr "編輯播放計次" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." msgstr "" "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's <tt>~#playcount</tt> to 0, the <tt>~#lastplayed</tt> " "and <tt>~#laststarted</tt> entries will be cleared. However, when setting a " "0-play song to a positive play count, no play times will be created." #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Play Count" msgstr "播放計次" #: quodlibet/ext/songsmenu/editplaycount.py:71 msgid "Skip Count" msgstr "忽略計次" #: quodlibet/ext/songsmenu/editplaycount.py:85 msgid "Multiple files selected." msgstr "多重檔案選取。" #: quodlibet/ext/songsmenu/editplaycount.py:86 msgid "Counts will be incremented." msgstr "計次將會累進。" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "編輯內嵌圖片" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Adds, removes or replaces embedded images." msgstr "Adds, removes or replaces embedded images." #: quodlibet/ext/songsmenu/embedded.py:77 msgid "_Embed" msgstr "內嵌 (_E)" #: quodlibet/ext/songsmenu/embedded.py:79 #, python-format msgid "Choose image to embed in the %d track" msgid_plural "Choose image to embed in %d tracks" msgstr[0] "選取圖片要內嵌至 %d 音軌" #: quodlibet/ext/songsmenu/embedded.py:105 msgid "_Remove all Images" msgstr "移除全部圖片 (_R)" #: quodlibet/ext/songsmenu/embedded.py:110 msgid "_Embed Current Image" msgstr "內嵌目前圖片 (_E)" #: quodlibet/ext/songsmenu/embedded.py:114 msgid "_Choose Image…" msgstr "選取圖片 (_C)…" #: quodlibet/ext/songsmenu/exact_rating.py:23 msgid "Set Exact Rating" msgstr "設定取用評分" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Allows setting the rating of songs with a number." msgstr "Allows setting the rating of songs with a number." #: quodlibet/ext/songsmenu/exact_rating.py:36 msgid "Please give your desired rating on a scale from 0.0 to 1.0" msgstr "Please give your desired rating on a scale from 0.0 to 1.0" #: quodlibet/ext/songsmenu/filterall.py:80 msgid "Filter on Any Tag" msgstr "篩選於任何標籤" #: quodlibet/ext/songsmenu/filterall.py:81 msgid "Creates a search query based on tags of the selected songs." msgstr "Creates a search query based on tags of the selected songs." #: quodlibet/ext/songsmenu/filterbrowser.py:19 msgid "Filter on Directory" msgstr "篩選於目錄" #: quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filters on directory in a new browser window." msgstr "Filters on directory in a new browser window." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:30 msgid "Acoustic Fingerprint Lookup" msgstr "Acoustic Fingerprint Lookup" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Looks up song metadata through acoustic fingerprinting." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:51 #: quodlibet/ext/songsmenu/fingerprint/submit.py:40 msgid "Submit Acoustic Fingerprints" msgstr "提交 Acoustic Fingerprints" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:60 msgid "API Key Missing" msgstr "API Key 遺失" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:75 msgid "Request API key" msgstr "請求 API key" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:82 msgid "API _key:" msgstr "API _key:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:89 msgid "AcoustID Web Service" msgstr "AcoustID Web Service" #: quodlibet/ext/songsmenu/fingerprint/search.py:36 msgid "Queued" msgstr "佇列" #: quodlibet/ext/songsmenu/fingerprint/search.py:38 msgid "Analyzing" msgstr "分析" #: quodlibet/ext/songsmenu/fingerprint/search.py:40 msgid "Lookup" msgstr "Lookup" #: quodlibet/ext/songsmenu/fingerprint/search.py:116 msgid "Write" msgstr "寫入" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:158 msgid "Release" msgstr "發行" #: quodlibet/ext/songsmenu/fingerprint/search.py:290 msgid "Write MusicBrainz tags" msgstr "寫入 MusicBrainz 標籤" #: quodlibet/ext/songsmenu/fingerprint/search.py:296 msgid "Group by directory" msgstr "依目錄來群組" #: quodlibet/ext/songsmenu/fingerprint/search.py:305 msgid "Album Mode" msgstr "專輯模式" #: quodlibet/ext/songsmenu/fingerprint/search.py:307 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Write album related tags and try to reduce the number of different album " "releases" #: quodlibet/ext/songsmenu/fingerprint/submit.py:48 msgid "Generating fingerprints:" msgstr "Generating fingerprints:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:64 msgid "_Details" msgstr "詳細 (_D)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:87 msgid "_Submit" msgstr "提交 (_S)" #: quodlibet/ext/songsmenu/fingerprint/submit.py:117 msgid "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." msgstr "" "Songs either need a <i><b>musicbrainz_trackid</b></i>, or <i><b>artist</b></" "i> / <i><b>title</b></i> / <i><b>album</b></i> tags to get submitted." #: quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Fingerprints:" msgstr "Fingerprints:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with MBIDs:" msgstr "曲目有 MBIDs:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with sufficient tags:" msgstr "曲目有足夠標籤:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs to submit:" msgstr "曲目提交:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:164 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "完成, %(to-send)d/%(all)d 曲目提交。" #: quodlibet/ext/songsmenu/fingerprint/submit.py:180 msgid "Submitting fingerprints:" msgstr "提交 fingerprints:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:188 msgid "Submitting…" msgstr "提交…" #: quodlibet/ext/songsmenu/forcewrite.py:17 msgid "Update Tags in Files" msgstr "更新檔案中的標籤" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." #: quodlibet/ext/songsmenu/html.py:66 quodlibet/ext/songsmenu/html.py:76 msgid "Export to HTML" msgstr "匯出至 HTML" #: quodlibet/ext/songsmenu/html.py:67 msgid "Exports the selected song list to HTML." msgstr "Exports the selected song list to HTML." #: quodlibet/ext/songsmenu/ifp.py:21 msgid "Send to iFP" msgstr "發送至 iFP" #: quodlibet/ext/songsmenu/ifp.py:22 msgid "Uploads songs to an iRiver iFP device." msgstr "Uploads songs to an iRiver iFP device." #: quodlibet/ext/songsmenu/ifp.py:30 msgid "No iFP device found" msgstr "找不到 iFP 裝置" #: quodlibet/ext/songsmenu/ifp.py:31 msgid "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." msgstr "" "Unable to contact your iFP device. Check that the device is powered on and " "plugged in, and that you have ifp-line (http://ifp-driver.sf.net) installed." #: quodlibet/ext/songsmenu/ifp.py:39 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "上傳 %(current)d/%(total)d" #: quodlibet/ext/songsmenu/ifp.py:61 #, python-format msgid "Unable to upload %s.The device may be out of space, or turned off." msgstr "Unable to upload %s.The device may be out of space, or turned off." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "錯誤上傳" #. Could be made configurable in the future, but these likely suffice #. "tag1 tag2" will result in only tag1 and tag2 being exported #. * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) #. * tag1 tag2 means all except tag1 and tag2 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:59 msgid "Export User Data" msgstr "匯出使用者資料" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:60 msgid "Export Tags" msgstr "匯出標籤" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:61 msgid "Export Tags and User Data" msgstr "匯出標籤及使用者資料" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:62 msgid "Export File Stems and User Data" msgstr "匯出檔案出處及使用者資料" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:64 msgid "Export File Stems and Tags" msgstr "匯出檔案出處及標籤" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:65 msgid "Export File Stems, Tags and User Data" msgstr "匯出檔案出處、標籤及使用者資料" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:162 msgid "Import / Export" msgstr "匯入 / 匯出" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:163 msgid "Imports and exports tags and track user data." msgstr "Imports and exports tags and track user data." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:192 msgid "Further information" msgstr "進一步資訊" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:196 #, python-format msgid "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." msgstr "" "The term 'track user data' includes the playlists in which the selected " "tracks are and the following metadata:\n" "\n" "%s\n" "\n" "Be aware that whatever you chose to export will be imported. If you exported " "the file stems (file names without extension), then, on import, the selected " "files will be renamed.\n" "\n" "After exporting an album you can import the data into another version of the " "album. Order and number of tracks can be different. The plugin matches the " "exported data to the new tracks, even if the names of the tracks are " "slightly different. The automatic matching is not always correct, so it is " "better to not reduce the following similarity values too much." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:212 msgid "User interaction on import" msgstr "User interaction on import" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:216 msgid "Require confirmation if number of tracks differs" msgstr "Require confirmation if number of tracks differs" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:222 msgid "Require confirmation if number of albums differs" msgstr "Require confirmation if number of albums differs" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:227 msgid "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." msgstr "" "Percentage below which the user will have to manually check and optionally " "change which track is matched with which." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:257 msgid "Track similarity:" msgstr "音軌類似:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:260 msgid "Album similarity:" msgstr "專輯類似:" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:263 msgid "Export files" msgstr "匯出檔案" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:266 msgid "Write pretty and clear JSON (slower)" msgstr "Write pretty and clear JSON (較慢)" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:271 msgid "Delete export files after they've been imported" msgstr "Delete export files after they've been imported" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:316 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Import" msgstr "匯入" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:331 msgid "Open Export Directory" msgstr "開啟匯入目錄" #. #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:384 msgid "Discs" msgstr "碟片" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:385 msgid "Tracks" msgstr "音軌" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:387 #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:565 msgid "Artist(s)" msgstr "藝人" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:388 msgid "End of path" msgstr "路徑結尾" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Match Albums" msgstr "符合專輯" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:391 msgid "Continue" msgstr "繼續" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:423 msgid "Nothing to import" msgstr "無任何匯入" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:424 msgid "You have to export something before you can import." msgstr "You have to export something before you can import." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:447 msgid "The index was corrupt." msgstr "The index was corrupt." #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:502 #, python-format msgid "Couldn't parse JSON in %s" msgstr "無法解析 JSON 於 %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:506 #, python-format msgid "Couldn't read %s" msgstr "無法讀取 %s" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:566 msgid "File name" msgstr "檔案名稱" #: quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py:569 msgid "Match Tracks" msgstr "符合音軌" #: quodlibet/ext/songsmenu/lastfmsync.py:86 msgid "Updating chart list." msgstr "Updating chart list." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:104 msgid "Already up-to-date." msgstr "Already up-to-date." #: quodlibet/ext/songsmenu/lastfmsync.py:111 #, python-format msgid "Fetching chart for week of %s." msgstr "Fetching chart for week of %s." #: quodlibet/ext/songsmenu/lastfmsync.py:133 msgid "Sync complete." msgstr "同步完成。" #: quodlibet/ext/songsmenu/lastfmsync.py:139 #, python-format msgid "Error during sync (%s)" msgstr "同步期間錯誤 (%s)" #: quodlibet/ext/songsmenu/lastfmsync.py:202 #: quodlibet/ext/songsmenu/lastfmsync.py:231 msgid "Last.fm Sync" msgstr "Last.fm 同步" #: quodlibet/ext/songsmenu/lastfmsync.py:232 msgid "Updates your library's statistics from your Last.fm profile." msgstr "從您的 Last.fm 檔案來更新您的音樂庫統計。" #: quodlibet/ext/songsmenu/lastfmsync.py:285 msgid "_Username:" msgstr "使用者名稱 (_U):" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "建立排序標籤" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Converts album and artist names to sort names, poorly." msgstr "Converts album and artist names to sort names, poorly." #: quodlibet/ext/songsmenu/playlist.py:36 msgid "Export as M3U / PLS Playlist File" msgstr "匯出為 M3U / PLS 播放清單" #: quodlibet/ext/songsmenu/playlist.py:37 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exports songs to an M3U or PLS playlist." #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use relative paths" msgstr "使用相對路徑" #: quodlibet/ext/songsmenu/playlist.py:82 msgid "Use absolute paths" msgstr "使用絕對路徑" #: quodlibet/ext/songsmenu/playlist.py:144 #, python-format msgid "Writing to %s failed." msgstr "寫入%s 失敗。" #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:22 msgid "Rescan Songs" msgstr "重新掃瞄曲目" #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "Checks for file changes and reloads / removes the songs if needed." #: quodlibet/ext/songsmenu/refresh.py:31 msgid "Rescan songs" msgstr "重新掃瞄曲目" #: quodlibet/ext/songsmenu/replaygain.py:351 msgid "ReplayGain Analyzer" msgstr "播放增益分析" #. Translators: Combined track number/title column heading #: quodlibet/ext/songsmenu/replaygain.py:394 msgctxt "track/title" msgid "Track" msgstr "音軌" #: quodlibet/ext/songsmenu/replaygain.py:408 msgid "Progress" msgstr "進程" #: quodlibet/ext/songsmenu/replaygain.py:423 msgid "Gain" msgstr "增益" #: quodlibet/ext/songsmenu/replaygain.py:438 msgid "Peak" msgstr "峰值" #: quodlibet/ext/songsmenu/replaygain.py:453 #, python-format msgid "There is %(to-process)s album to update (of %(all)s)" msgid_plural "There are %(to-process)s albums to update (of %(all)s)" msgstr[0] "There are %(to-process)s albums to update (of %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Replay Gain" msgstr "播放增益" #: quodlibet/ext/songsmenu/replaygain.py:571 #, python-format msgid "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." msgstr "" "Analyzes and updates <a href=\"%(rg_link)s\">ReplayGain</a> information, " "using GStreamer. Results are grouped by album." #: quodlibet/ext/songsmenu/replaygain.py:573 msgid "https://en.wikipedia.org/wiki/ReplayGain" msgstr "https://en.wikipedia.org/wiki/ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "always" msgstr "永遠" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>any</b> RG tags are missing" msgstr "if <b>any</b> RG tags are missing" #: quodlibet/ext/songsmenu/replaygain.py:613 msgid "if <b>album</b> RG tags are missing" msgstr "if <b>album</b> RG tags are missing" #: quodlibet/ext/songsmenu/replaygain.py:630 msgid "_Process albums:" msgstr "處理專輯 (_P):" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:642 msgid "Existing Tags" msgstr "現有標籤" #: quodlibet/ext/songsmenu/splitting.py:31 msgid "Split Tags" msgstr "分割標籤" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Splits the disc number from the album and the version from the title at the " "same time." #: quodlibet/ext/songsmenu/splitting.py:56 msgid "Split Album" msgstr "分割專輯" #: quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "Split out disc number." #: quodlibet/ext/songsmenu/tapbpm.py:23 quodlibet/ext/songsmenu/tapbpm.py:32 #: quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "n/a" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "BPM:" #: quodlibet/ext/songsmenu/tapbpm.py:36 msgid "Reset" msgstr "重設" #: quodlibet/ext/songsmenu/tapbpm.py:42 msgid "Tap" msgstr "點按" #: quodlibet/ext/songsmenu/tapbpm.py:177 quodlibet/ext/songsmenu/tapbpm.py:184 msgid "Tap BPM" msgstr "點按 BPM" #: quodlibet/ext/songsmenu/tapbpm.py:178 msgid "🥁 Tap BPM for the selected song." msgstr "🥁 Tap BPM for the selected song." #: quodlibet/ext/songsmenu/website_search.py:36 msgid "Website Search" msgstr "網站搜尋" #: quodlibet/ext/songsmenu/website_search.py:38 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." msgstr "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s." #: quodlibet/ext/songsmenu/website_search.py:82 msgid "Search URL patterns" msgstr "搜尋 URL 型式" #: quodlibet/ext/songsmenu/website_search.py:92 msgid "Edit search URLs" msgstr "編輯搜尋 URLs" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:118 msgid "Configure Searches…" msgstr "設定搜尋…" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Search Tag in Wikipedia" msgstr "搜尋標籤於Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:37 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." #: quodlibet/ext/songsmenu/wikipedia.py:57 #, python-format msgid "Search at %(website)s" msgstr "搜尋於 %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:75 quodlibet/qltk/edittags.py:451 msgid "Edit Tags" msgstr "編輯標籤" #: quodlibet/ext/songsmenu/wikipedia.py:110 msgid "Search failed" msgstr "搜尋失敗" #: quodlibet/ext/songsmenu/wikipedia.py:111 #, python-format msgid "Tag \"%s\" not found." msgstr "標籤\"%s\" 未找到。" #. then (try to) load all new files #: quodlibet/library/file.py:156 quodlibet/library/file.py:166 #: quodlibet/library/file.py:231 quodlibet/library/file.py:250 #: quodlibet/library/file.py:357 quodlibet/library/file.py:415 #: quodlibet/library/file.py:570 quodlibet/qltk/information.py:270 #: quodlibet/qltk/prefs.py:689 quodlibet/util/library.py:122 msgid "Library" msgstr "音樂庫" #: quodlibet/library/file.py:156 msgid "Checking mount points" msgstr "正在檢查掛載點" #: quodlibet/library/file.py:166 msgid "Scanning library" msgstr "掃瞄音樂庫中" #: quodlibet/library/file.py:230 #, python-format msgid "Scanning %s" msgstr "正在掃瞄 %s" #: quodlibet/library/file.py:250 msgid "Loading files" msgstr "載入檔案" #: quodlibet/library/file.py:357 msgid "Moving library files" msgstr "正在移動音樂庫檔案" #: quodlibet/library/file.py:415 msgid "Removing library files" msgstr "正在移除音樂庫檔案" #: quodlibet/library/file.py:569 #, python-format msgid "Adding watches for %s" msgstr "加入監視用於 %s" #: quodlibet/library/playlist.py:79 #, python-format msgid "" "No library songs found in legacy playlist %(filename)r (of size %(size).1f " "kB)." msgstr "在接續播放清單 %(filename)r (of size %(size).1f kB) 找不到音樂庫曲目。" #: quodlibet/library/playlist.py:82 msgid "Have you changed library root dir(s), but not this playlist?" msgstr "您曾有變更音樂庫根目錄,但非此播放清單?" #: quodlibet/library/playlist.py:97 #, python-format msgid "%d playlist failed to convert" msgid_plural "%d playlists failed to convert" msgstr[0] "%d 播放清單轉換失敗" #: quodlibet/main.py:48 msgid "Music player and music library manager" msgstr "音樂播放器暨歌曲音樂庫管理器" #: quodlibet/operon/base.py:71 #, python-format msgid "Failed to load file: %r" msgstr "失敗載入檔案: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "列示標籤" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:464 msgid "Print terse output" msgstr "列印簡潔輸出" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:466 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Columns to display and order in terse mode (%s)" #: quodlibet/operon/commands.py:46 quodlibet/operon/commands.py:85 msgid "Also list programmatic tags" msgstr "也列示 programmatic 標籤" #: quodlibet/operon/commands.py:50 quodlibet/operon/commands.py:128 #: quodlibet/operon/commands.py:220 quodlibet/operon/commands.py:293 #: quodlibet/operon/commands.py:338 quodlibet/operon/commands.py:342 #: quodlibet/operon/commands.py:394 quodlibet/operon/commands.py:397 #: quodlibet/operon/commands.py:436 quodlibet/operon/commands.py:471 #: quodlibet/operon/commands.py:511 quodlibet/operon/commands.py:546 #: quodlibet/operon/commands.py:588 msgid "Not enough arguments" msgstr "沒有足夠參數" #: quodlibet/operon/commands.py:52 quodlibet/operon/commands.py:89 #: quodlibet/operon/commands.py:130 quodlibet/operon/commands.py:222 #: quodlibet/operon/commands.py:473 msgid "Too many arguments" msgstr "太多參數" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:478 quodlibet/qltk/data_editors.py:374 msgid "Description" msgstr "描述" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:478 #: quodlibet/qltk/edittags.py:503 msgid "Value" msgstr "設定值" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "列示一般標籤" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "複製標籤從檔案至另一檔案" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:326 #: quodlibet/operon/commands.py:387 msgid "Show changes, don't apply them" msgstr "顯示變更,不要套用" #: quodlibet/operon/commands.py:124 msgid "Skip tags that can't be written" msgstr "跳過無法寫入的標籤" #: quodlibet/operon/commands.py:145 #, python-brace-format msgid "Can't copy tag {tagname} to file: {filename}" msgstr "無法複製標籤 {tagname} 至檔案: {filename}" #: quodlibet/operon/commands.py:157 msgid "Edit tags in a text editor" msgstr "在文字編輯器編輯標籤" #: quodlibet/operon/commands.py:251 msgid "Editing aborted" msgstr "編蜈取消" #: quodlibet/operon/commands.py:255 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "啟動文字編輯器 '%(editor-name)s' 失敗。" #: quodlibet/operon/commands.py:260 msgid "No changes detected" msgstr "沒有發現更改" #: quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "設定標籤並移除現存數值" #: quodlibet/operon/commands.py:306 #, python-format msgid "Can not set %(tag)r for %(format)s file %(file)r" msgstr "無法設定 %(tag)r 於 %(format)s 檔案 %(file)r" #: quodlibet/operon/commands.py:321 msgid "Remove tags" msgstr "移除標籤" #: quodlibet/operon/commands.py:328 quodlibet/operon/commands.py:389 msgid "Value is a regular expression" msgstr "數值是一個常態表達式" #: quodlibet/operon/commands.py:330 msgid "Remove all tags" msgstr "移除全部標籤" #: quodlibet/operon/commands.py:334 msgid "Can't combine '--all' with '--regexp'" msgstr "Can't combine '--all' with '--regexp'" #: quodlibet/operon/commands.py:368 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Can't remove {tagname} from {filename}" #: quodlibet/operon/commands.py:382 msgid "Remove a tag value" msgstr "移除標籤設定" #: quodlibet/operon/commands.py:431 msgid "Add a tag value" msgstr "增加標籤設定值" #: quodlibet/operon/commands.py:447 quodlibet/operon/commands.py:679 #, python-format msgid "Can not set %r" msgstr "無法設定 %r" #: quodlibet/operon/commands.py:459 msgid "List file information" msgstr "列示檔案資訊" #: quodlibet/operon/commands.py:505 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Set the provided image as primary embedded image and remove all other " "embedded images" #: quodlibet/operon/commands.py:518 #, python-format msgid "Failed to load image file: %r" msgstr "載入圖檔失敗:%r" #: quodlibet/operon/commands.py:525 quodlibet/operon/commands.py:554 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "圖片編輯不支援於 %(file_name)s (%(file_format)s)" #: quodlibet/operon/commands.py:541 msgid "Remove all embedded images" msgstr "移除全部內嵌圖片" #: quodlibet/operon/commands.py:571 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "取出內嵌圖片至 %(filepath)s" #: quodlibet/operon/commands.py:583 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Path to where the images will be saved to (defaults to the working directory)" #: quodlibet/operon/commands.py:642 msgid "Rename files based on tags" msgstr "依照標籤更改檔案名稱" #: quodlibet/operon/commands.py:657 msgid "Fill tags based on the file path" msgstr "按照檔案路徑更改標籤" #: quodlibet/operon/commands.py:707 quodlibet/qltk/information.py:307 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:226 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "檔案" #: quodlibet/operon/commands.py:715 msgid "Fill tracknumbers for all files" msgstr "全部檔案填入音軌編號" #: quodlibet/operon/commands.py:734 msgid "Print tags based on the given pattern" msgstr "Print tags based on the given pattern" #: quodlibet/operon/commands.py:771 msgid "Display help information" msgstr "顯示輔助資訊" #: quodlibet/operon/util.py:41 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." #: quodlibet/order/__init__.py:34 msgid "_Unknown" msgstr "不明 (_U)" #: quodlibet/order/__init__.py:149 msgid "In Order" msgstr "順序" #: quodlibet/order/__init__.py:150 msgid "_In Order" msgstr "順序 (_I)" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "隨機" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:172 msgid "_Random" msgstr "隨機 (_R)" #: quodlibet/order/reorder.py:39 msgid "Prefer higher rated" msgstr "偏好較高評分" #: quodlibet/order/reorder.py:40 msgid "Prefer _higher rated" msgstr "偏好較高評分 (_h)" #: quodlibet/order/repeat.py:43 msgid "Repeat this track" msgstr "重覆這首音軌" #: quodlibet/order/repeat.py:44 msgid "Repeat _this track" msgstr "重覆這首音軌 (_t)" #: quodlibet/order/repeat.py:57 msgid "Repeat all" msgstr "重覆全部" #: quodlibet/order/repeat.py:58 msgid "Repeat _all" msgstr "重覆全部 (_a)" #: quodlibet/order/repeat.py:73 msgid "One song" msgstr "單曲" #: quodlibet/order/repeat.py:74 msgid "One _song" msgstr "單曲 (_s)" #: quodlibet/player/gstbe/player.py:100 msgid "Stream" msgstr "串流" #: quodlibet/player/gstbe/player.py:100 msgid "Buffering" msgstr "緩衝" #: quodlibet/player/gstbe/player.py:463 #, python-format msgid "Could not create GStreamer pipeline (%s)" msgstr "Could not create GStreamer pipeline (%s)" #: quodlibet/player/gstbe/player.py:666 msgid "No GStreamer element found to handle media format" msgstr "No GStreamer element found to handle media format" #: quodlibet/player/gstbe/player.py:667 #, python-format msgid "Media format: %(format-description)s" msgstr "Media format: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:35 #, python-format msgid "GStreamer plugin '%(name)s' could not be initialized" msgstr "GStreamer plugin '%(name)s' could not be initialized" #: quodlibet/player/gstbe/prefs.py:26 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." msgstr "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. If the pipeline contains a sink, it will be used instead of the " "default one." #: quodlibet/player/gstbe/prefs.py:38 msgid "_Output pipeline:" msgstr "_Output pipeline:" #. Translators: s = seconds #: quodlibet/player/gstbe/prefs.py:46 #, python-format msgid "%.1f s" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:59 msgid "_Buffer duration:" msgstr "_Buffer duration:" #: quodlibet/player/gstbe/prefs.py:69 msgid "Disable _gapless playback" msgstr "停用無縫播放 (_g)" #: quodlibet/player/gstbe/prefs.py:71 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" #: quodlibet/player/gstbe/prefs.py:74 msgid "Use JACK for playback if available" msgstr "使用 JACK 作為播放(若是可用)" #: quodlibet/player/gstbe/prefs.py:76 msgid "Uses `jackaudiosink` for playbin sink if it can be detected" msgstr "Uses `jackaudiosink` for playbin sink if it can be detected" #: quodlibet/player/gstbe/prefs.py:78 msgid "Auto-connect to JACK output devices" msgstr "自動連接至 JACK 輸出裝置" #: quodlibet/player/gstbe/prefs.py:80 msgid "Tells `jackaudiosink` to auto-connect" msgstr "告之 `jackaudiosink` 至自動連接" #: quodlibet/player/gstbe/util.py:148 #, python-format msgid "No GStreamer audio sink found. Tried: %s" msgstr "No GStreamer audio sink found. Tried: %s" #: quodlibet/player/gstbe/util.py:167 msgid "Invalid GStreamer output pipeline" msgstr "Invalid GStreamer output pipeline" #: quodlibet/player/xinebe/player.py:91 msgid "Unable to create audio output" msgstr "無法建立音訊檔輸出" #: quodlibet/player/xinebe/player.py:92 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." #: quodlibet/plugins/__init__.py:64 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Couldn't find module '{module}'. Perhaps you need to install the package?" #: quodlibet/plugins/__init__.py:73 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Couldn't find GStreamer element '{element}'." #: quodlibet/ext/events/listenbrainz/__init__.py:229 msgid "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." msgstr "" "Please visit the Plugins window to set ListenBrainz up. Until then, listens " "will not be submitted." #: quodlibet/ext/events/listenbrainz/__init__.py:301 #, python-format msgid "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." msgstr "" "Too many consecutive submission failures (%d). Setting to offline mode. " "Please visit the Plugins window to reset ListenBrainz. Until then, listens " "will not be submitted." #: quodlibet/ext/events/listenbrainz/__init__.py:356 msgid "ListenBrainz Submission" msgstr "ListenBrainz 提交" #: quodlibet/ext/events/listenbrainz/__init__.py:357 msgid "Submit listens to ListenBrainz." msgstr "Submit listens to ListenBrainz." #: quodlibet/ext/events/listenbrainz/__init__.py:455 msgid "User _token:" msgstr "使用者標記 (_t):" #: quodlibet/ext/events/listenbrainz/__init__.py:498 msgid "T_ags:" msgstr "標籤 (_T):" #: quodlibet/ext/events/listenbrainz/__init__.py:536 msgid "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." msgstr "" "List of tags to include in the submission. Comma-separated, use double-" "quotes if necessary." #: quodlibet/ext/events/listenbrainz/__init__.py:545 msgid "Songs matching this filter will not be submitted." msgstr "符合篩選的曲目將不會提交。" #: quodlibet/plugins/playlist.py:23 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)s playlist?" msgid_plural "Run the plugin \"%(name)s\" on %(count)s playlists?" msgstr[0] "執行外掛 \"%(name)s\" 於此 %(count)s 播放清單?" #: quodlibet/plugins/playlist.py:27 quodlibet/qltk/songsmenu.py:61 #: quodlibet/qltk/songsmenu.py:72 msgid "_Run Plugin" msgstr "執行外掛 (_R)" #: quodlibet/plugins/query.py:73 msgid "Usage" msgstr "用途" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "開頭" #: quodlibet/qltk/bookmarks.py:38 quodlibet/qltk/bookmarks.py:78 msgid "N/A" msgstr "N/A" #: quodlibet/qltk/bookmarks.py:83 msgid "Time" msgstr "時間" #: quodlibet/qltk/bookmarks.py:89 quodlibet/qltk/bookmarks.py:124 msgid "Bookmark Name" msgstr "書籤名稱" #: quodlibet/qltk/bookmarks.py:122 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:210 quodlibet/qltk/information.py:132 msgid "Bookmarks" msgstr "書籤" #: quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "篩選 (_F)" #: quodlibet/qltk/browser.py:57 msgid "Recently _Played" msgstr "新近播放過 (_P)" #: quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "新近已加入 (_A)" #: quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "前 40 名 (_T)" #: quodlibet/qltk/browser.py:63 msgid "All _Songs" msgstr "全部曲目 (_S)" #: quodlibet/qltk/browser.py:71 msgid "On Current _Genre(s)" msgstr "於目前曲風 (_G)" #: quodlibet/qltk/browser.py:72 msgid "On Current _Artist(s)" msgstr "於目前藝人 (_A)" #: quodlibet/qltk/browser.py:73 msgid "On Current Al_bum" msgstr "於目前專輯 (_b)" #: quodlibet/qltk/browser.py:81 msgid "Random _Genre" msgstr "隨機曲風 (_G)" #: quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "隨機藝人 (_A)" #: quodlibet/qltk/browser.py:83 msgid "Random Al_bum" msgstr "隨機專輯 (_b)" #: quodlibet/qltk/browser.py:96 msgid "" "The 40 songs you've played most (more than 40 may be chosen if there are " "ties)" msgstr "這是您播放最多次的 40 首曲目 (排名平手的話或許會超出 40 首)" #: quodlibet/qltk/cbes.py:42 msgid "_Name:" msgstr "名稱 (_N):" #: quodlibet/qltk/cbes.py:50 quodlibet/qltk/edittags.py:353 msgid "_Value:" msgstr "設定值 (_V):" #: quodlibet/qltk/cbes.py:264 msgid "Saved Values" msgstr "已儲存設定值" #: quodlibet/qltk/cbes.py:265 msgid "Edit saved values…" msgstr "編輯已儲存設定值…" #: quodlibet/qltk/controls.py:112 msgid "Auto_matic" msgstr "自動 (_m)" #: quodlibet/qltk/controls.py:113 msgid "_Track Mode" msgstr "音軌模式 (_T)" #: quodlibet/qltk/controls.py:114 msgid "_Album Mode" msgstr "專輯模式 (_A)" #. Translators: player state, no action #: quodlibet/qltk/controls.py:123 msgid "_Mute" msgstr "靜音 (_M)" #: quodlibet/qltk/controls.py:129 msgid "_Replay Gain Mode" msgstr "播放增益模式 (_R)" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:117 #, python-format msgid "New %s" msgstr "新建 %s" #: quodlibet/qltk/data_editors.py:216 msgid "(unknown)" msgstr "(不明)" #: quodlibet/qltk/data_editors.py:313 quodlibet/qltk/edittags.py:548 msgid "_Add…" msgstr "加入 (_A)…" #: quodlibet/qltk/data_editors.py:319 msgid "_Edit" msgstr "編輯 (_E)" #: quodlibet/qltk/data_editors.py:365 msgid "Tag expression" msgstr "標籤描述" #: quodlibet/qltk/data_editors.py:395 quodlibet/qltk/data_editors.py:405 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tag expression e.g. people:real or ~album~year" #: quodlibet/qltk/data_editors.py:396 msgid "Enter new tag" msgstr "輸入新建標籤" #: quodlibet/qltk/data_editors.py:406 msgid "Edit tag expression" msgstr "編輯標籤描述" #: quodlibet/qltk/delete.py:37 msgid "Files:" msgstr "檔案:" #: quodlibet/qltk/delete.py:63 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "所選曲目將會從音樂庫中移除,且檔案會被在磁碟中刪除。" #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "The selected files will be deleted from disk." #: quodlibet/qltk/delete.py:76 #, python-format msgid "Delete %(file_count)d file permanently?" msgid_plural "Delete %(file_count)d files permanently?" msgstr[0] "永久刪除 %(file_count)d 檔案?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "刪除檔案 (_D)" #: quodlibet/qltk/delete.py:106 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "所選曲目將會從音樂庫中移除,且檔案會被移至垃圾桶。" #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "所選曲目將會被移至垃圾桶。" #: quodlibet/qltk/delete.py:120 #, python-format msgid "Move %(file_count)d file to the trash?" msgid_plural "Move %(file_count)d files to the trash?" msgstr[0] "移動 %(file_count)d 檔案至垃圾桶?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "移動到垃圾桶 (_M)" #: quodlibet/qltk/delete.py:152 quodlibet/qltk/delete.py:187 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "正在移動 %(current)d/%(total)d 。" #: quodlibet/qltk/delete.py:173 quodlibet/qltk/delete.py:205 msgid "Unable to move to trash" msgstr "無法移動到垃圾桶" #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Moving one or more files to the trash failed." msgstr "移動檔案到垃圾筒失敗。" #: quodlibet/qltk/delete.py:216 quodlibet/qltk/delete.py:250 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "正在刪除 %(current)d/%(total)d 。" #: quodlibet/qltk/delete.py:236 quodlibet/qltk/delete.py:269 msgid "Unable to delete files" msgstr "無法刪除檔案" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "刪除檔案失敗。" #: quodlibet/qltk/download.py:36 msgid "Browser" msgstr "瀏覽窗" #: quodlibet/qltk/download.py:36 msgid "Downloading files" msgstr "正在下載檔案" #: quodlibet/qltk/edittags.py:62 quodlibet/qltk/edittags.py:73 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "遺失 %d 曲目" #: quodlibet/qltk/edittags.py:66 quodlibet/qltk/edittags.py:70 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "曲目 %d 首有差異" #: quodlibet/qltk/edittags.py:198 msgid "Split into _Multiple Values" msgstr "分割成多重設定值 (_M)" #: quodlibet/qltk/edittags.py:220 msgid "Split Disc out of _Album" msgstr "分割專輯碟片 (_A)" #: quodlibet/qltk/edittags.py:244 msgid "Split _Version out of Title" msgstr "分割標題版本 (_V)" #: quodlibet/qltk/edittags.py:301 msgid "Split Arranger out of Ar_tist" msgstr "分割藝人列出編排者 (_t)" #: quodlibet/qltk/edittags.py:306 msgid "Split _Performer out of Artist" msgstr "分割藝人列出演出者 (_P)" #: quodlibet/qltk/edittags.py:312 msgid "Split _Performer out of Title" msgstr "分割標題列出演出者 (_P)" #: quodlibet/qltk/edittags.py:318 msgid "Split _Originalartist out of Title" msgstr "分割標題列出原版藝人 (_O)" #: quodlibet/qltk/edittags.py:325 msgid "Add a Tag" msgstr "增加標籤" #: quodlibet/qltk/edittags.py:344 msgid "_Tag:" msgstr "標籤 (_T):" #: quodlibet/qltk/edittags.py:526 msgid "Show _programmatic tags" msgstr "顯示生成器 (programmatic) 標籤 (_p)" #: quodlibet/qltk/edittags.py:527 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" #: quodlibet/qltk/edittags.py:534 msgid "Show _multi-line tags" msgstr "顯示多重行列標籤 (_p)" #: quodlibet/qltk/edittags.py:538 msgid "Show potentially multi-line tags (e.g 'lyrics') here too" msgstr "Show potentially multi-line tags (e.g 'lyrics') here too" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:568 msgctxt "edittags" msgid "_Revert" msgstr "還原 (_R)" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:573 msgctxt "edittags" msgid "_Save" msgstr "儲存 (_S)" #: quodlibet/qltk/edittags.py:713 msgid "_Configure" msgstr "設定 (_C)" #: quodlibet/qltk/edittags.py:728 msgid "_Split Tag" msgstr "分割標籤 (_S)" #: quodlibet/qltk/edittags.py:737 msgid "_Copy Value(s)" msgstr "複製設定值 (_C)" #: quodlibet/qltk/edittags.py:768 msgid "Unable to add tag" msgstr "無法增加標籤" #: quodlibet/qltk/edittags.py:769 #, python-format msgid "Unable to add %s" msgstr "無法增加 %s" #: quodlibet/qltk/edittags.py:771 #, python-format msgid "The files currently selected do not support multiple values for %s." msgstr "The files currently selected do not support multiple values for %s." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:798 quodlibet/qltk/edittags.py:981 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:511 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgid_plural "Invalid tags" msgstr[0] "無效標籤" #: quodlibet/qltk/edittags.py:799 quodlibet/qltk/edittags.py:982 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag %s\n" "\n" "The files currently selected do not support editing this tag." msgid_plural "" "Invalid tags %s\n" "\n" "The files currently selected do not support editing these tags." msgstr[0] "" "無效標籤 %s\n" "\n" "當前選取的檔案不支援標籤編輯。" #: quodlibet/qltk/edittags.py:952 quodlibet/qltk/edittags.py:995 msgid "Invalid value" msgstr "無效設定值" #: quodlibet/qltk/edittags.py:953 quodlibet/qltk/edittags.py:996 #, python-format msgid "" "Invalid value: %(value)s\n" "\n" "%(error)s" msgstr "" "無效設定值: %(value)s\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:31 msgid "Tag may not be accurate" msgstr "標籤可能不正確" #: quodlibet/qltk/_editutils.py:34 #, python-format msgid "" "%(file-name)s changed while the program was running. Saving without " "refreshing your library may overwrite other changes to the song." msgstr "" "當程式執行時 %(file-name)s 已經被改變了。沒有更新音樂庫就進行儲存,其它變更可" "能會寫入這首曲目。" #: quodlibet/qltk/_editutils.py:50 msgid "Unable to save song" msgstr "無法儲存曲目" #: quodlibet/qltk/_editutils.py:53 #, python-format msgid "" "Saving %(file-name)s failed.The file may be read-only, corrupted, or you do " "not have permission to edit it." msgstr "儲存 %(file-name)s 失敗。這個檔案可能是唯讀、損毀或是沒有編輯權限。" #: quodlibet/qltk/_editutils.py:144 msgid "_More options…" msgstr "更多選項 (_M)…" #: quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "還原動作 (_U)" #: quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "重複動作 (_R)" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:976 msgid "_About" msgstr "關於 (_A)" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:998 msgid "_Check for Updates…" msgstr "檢查更新 (_C)…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:926 #: quodlibet/qltk/songsmenu.py:295 msgid "_Plugins" msgstr "外掛 (_P)" #: quodlibet/qltk/exfalsowindow.py:266 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s 及還有 %(count)s 更多" #: quodlibet/qltk/exfalsowindow.py:280 msgid "Ex Falso Preferences" msgstr "Ex Falso 偏好設定" #: quodlibet/qltk/filesel.py:199 msgid "Folders" msgstr "資料夾" #: quodlibet/qltk/filesel.py:254 msgid "_New Folder…" msgstr "新資料夾 (_N)…" #: quodlibet/qltk/filesel.py:263 msgid "_Select all Sub-Folders" msgstr "選取全部下層資料夾 (_S)" #: quodlibet/qltk/filesel.py:373 msgid "New Folder" msgstr "新建資料夾" #: quodlibet/qltk/filesel.py:373 msgid "Enter a name for the new folder:" msgstr "輸入新建資料夾的名稱:" #: quodlibet/qltk/filesel.py:385 msgid "Unable to create folder" msgstr "無法建立資料夾" #: quodlibet/qltk/filesel.py:402 msgid "Unable to delete folder" msgstr "無法刪除資料夾" #: quodlibet/qltk/filesel.py:518 quodlibet/qltk/pluginwin.py:36 msgid "Songs" msgstr "曲目" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:43 #, python-format msgid "by %s" msgstr "由 %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:170 #: quodlibet/qltk/information.py:450 #, python-format msgid "Disc %s" msgstr "碟片 %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:174 #, python-format msgid "Track %s" msgstr "音軌 %s" #: quodlibet/qltk/info.py:104 msgid "Current _Song" msgstr "目前曲目 (_S)" #: quodlibet/qltk/info.py:114 msgid "_Edit Display…" msgstr "編輯顯示 (_E)…" #: quodlibet/qltk/information.py:106 msgid "No songs are selected." msgstr "沒有曲目被選取。" #: quodlibet/qltk/information.py:107 msgid "No Songs" msgstr "無曲目" #: quodlibet/qltk/information.py:122 quodlibet/qltk/information.py:340 #: quodlibet/qltk/information.py:472 quodlibet/qltk/information.py:540 msgid "Information" msgstr "資訊" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "歌詞" #: quodlibet/qltk/information.py:186 quodlibet/qltk/information.py:398 #, python-format msgid "Produced by %s" msgstr "由 %s 製作" #: quodlibet/qltk/information.py:201 quodlibet/util/tags.py:85 msgid "artist" msgstr "藝人" #: quodlibet/qltk/information.py:202 quodlibet/qltk/information.py:570 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "藝人" #. for backwards compat #: quodlibet/qltk/information.py:223 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "演出者" #: quodlibet/qltk/information.py:237 quodlibet/qltk/information.py:250 #: quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "從未" #: quodlibet/qltk/information.py:238 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d 次" #: quodlibet/qltk/information.py:256 quodlibet/util/tags.py:150 msgid "added" msgstr "已加入" #: quodlibet/qltk/information.py:257 quodlibet/util/tags.py:151 msgid "last played" msgstr "上次播放" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:161 msgid "plays" msgstr "播放" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:162 msgid "skips" msgstr "跳過" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:167 msgid "rating" msgstr "評分" #: quodlibet/qltk/information.py:289 msgid "path" msgstr "路徑" #: quodlibet/qltk/information.py:290 quodlibet/util/tags.py:165 msgid "length" msgstr "長度" #: quodlibet/qltk/information.py:291 msgid "format" msgstr "格式" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:175 msgid "codec" msgstr "解碼" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:176 msgid "encoding" msgstr "編碼" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "位元率" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:173 msgid "file size" msgstr "檔案大小" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:160 msgid "modified" msgstr "修改時間" #: quodlibet/qltk/information.py:333 msgid "Additional" msgstr "額外加入" #: quodlibet/qltk/information.py:385 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 已選取" #: quodlibet/qltk/information.py:460 msgid "Track unavailable" msgstr "無效的音軌" #: quodlibet/qltk/information.py:497 quodlibet/qltk/information.py:587 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d 曲目無專輯資訊" #: quodlibet/qltk/information.py:500 msgid "Selected Discography" msgstr "已選擇音樂碟片分類" #: quodlibet/qltk/information.py:567 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d 曲目無藝人資訊" #: quodlibet/qltk/information.py:594 quodlibet/util/tags.py:83 msgid "albums" msgstr "專輯" #: quodlibet/qltk/information.py:607 msgid "Total length:" msgstr "總計長度:" #: quodlibet/qltk/information.py:611 msgid "Total size:" msgstr "合計大小:" #: quodlibet/qltk/information.py:614 msgid "Files" msgstr "檔案" #: quodlibet/qltk/lyrics.py:34 msgid "_View online" msgstr "線上檢視 (_V)" #: quodlibet/qltk/lyrics.py:61 msgid "No lyrics found for this song." msgstr "找不到這首曲目的歌詞。" #: quodlibet/qltk/maskedbox.py:20 msgid "Are you sure you want to remove all songs?" msgstr "確定要移除全部曲目?" #: quodlibet/qltk/maskedbox.py:21 msgid "The selected songs will be removed from the library." msgstr "所選曲目將從音樂庫中移除。" #: quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "不隱藏" #: quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "不隱藏 (_U)" #: quodlibet/qltk/matchdialog.py:23 msgid "" "Check if the columns on the left side approximately match the ones on the " "right side. If they don't, you can change the order here (use _ for rows " "that shouldn't be matched):" msgstr "" "檢查左側列示是否與右側相對稱。如果不是,您可以在此改變順序(對於不相對稱的):" #: quodlibet/qltk/matchdialog.py:74 msgid "Right side order:" msgstr "右側順序:" #: quodlibet/qltk/msg.py:46 msgid "Discard tag changes?" msgstr "放棄標籤的變更?" #: quodlibet/qltk/msg.py:47 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "標籤已被改變但尚未儲存。要儲存檔案或是還原並放棄變更?" #: quodlibet/qltk/msg.py:60 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "還原 (_R)" #: quodlibet/qltk/msg.py:108 msgid "File exists" msgstr "檔案存在" #: quodlibet/qltk/msg.py:110 #, python-format msgid "Replace %(file-name)s?" msgstr "取代 %(file-name)s ?" #: quodlibet/qltk/msg.py:116 msgid "_Replace File" msgstr "取代檔案 (_R)" #: quodlibet/qltk/notif.py:183 msgid "Active tasks" msgstr "執行任務" #: quodlibet/qltk/notif.py:189 #, python-format msgid "%d tasks running" msgstr "%d 任務執行中" #: quodlibet/qltk/playorder.py:258 msgid "Toggle shuffle mode" msgstr "切換隨機模式" #: quodlibet/qltk/playorder.py:274 msgid "Toggle repeat mode" msgstr "切換重複模式" #: quodlibet/qltk/pluginwin.py:38 msgid "Events" msgstr "事件" #: quodlibet/qltk/pluginwin.py:39 msgid "Play Order" msgstr "播放順序" #: quodlibet/qltk/pluginwin.py:40 msgid "Editing" msgstr "編輯中" #: quodlibet/qltk/pluginwin.py:41 msgid "Renaming" msgstr "重新命名" #: quodlibet/qltk/pluginwin.py:42 msgid "Querying" msgstr "查詢中" #: quodlibet/qltk/pluginwin.py:44 msgid "Covers" msgstr "封面" #: quodlibet/qltk/pluginwin.py:66 msgid "Plugin Errors" msgstr "外掛錯誤" #: quodlibet/qltk/pluginwin.py:144 msgid "Any state" msgstr "任何統計" #: quodlibet/qltk/pluginwin.py:146 msgid "Enabled" msgstr "啟用" #: quodlibet/qltk/pluginwin.py:147 msgid "Disabled" msgstr "停用" #: quodlibet/qltk/pluginwin.py:153 msgid "No category" msgstr "無分類" #: quodlibet/qltk/pluginwin.py:186 msgid "Any category" msgstr "任何分類" #: quodlibet/qltk/pluginwin.py:323 msgid "No plugins found." msgstr "找不到外掛。" #: quodlibet/qltk/pluginwin.py:376 msgid "Plugins" msgstr "外掛" #: quodlibet/qltk/pluginwin.py:400 msgid "Filter by plugin state / tag" msgstr "以外掛狀態/標籤來篩選" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin type" msgstr "以外掛型態來篩選" #: quodlibet/qltk/pluginwin.py:411 msgid "Filter by plugin name or description" msgstr "以外掛名稱或描述來篩選" #: quodlibet/qltk/pluginwin.py:414 msgid "Show _Errors" msgstr "顯示錯誤 (_E)" #: quodlibet/qltk/prefs.py:49 msgid "_Disc" msgstr "碟片 (_D)" #: quodlibet/qltk/prefs.py:50 msgid "_Track" msgstr "音軌 (_T)" #: quodlibet/qltk/prefs.py:51 msgid "Grou_ping" msgstr "團體 (p)" #: quodlibet/qltk/prefs.py:53 msgid "_Artist" msgstr "藝人 (_A)" #: quodlibet/qltk/prefs.py:54 msgid "Al_bum" msgstr "專輯 (_b)" #: quodlibet/qltk/prefs.py:59 msgid "_Filename" msgstr "檔名 (_F)" #: quodlibet/qltk/prefs.py:61 msgid "_Length" msgstr "長度 (_L)" #: quodlibet/qltk/prefs.py:68 msgid "_Jump to playing song automatically" msgstr "自動跳到播放中的曲目 (_J)" #: quodlibet/qltk/prefs.py:70 msgid "When the playing song changes, scroll to it in the song list" msgstr "當變更播放中的曲目時,捲動清單到該曲目位置" #: quodlibet/qltk/prefs.py:72 msgid "_Sort songs when tags are modified" msgstr "當標籤更改後排序曲目 (_S)" #: quodlibet/qltk/prefs.py:74 msgid "Automatically re-sort songs in the song list when tags are modified" msgstr "當標籤更改後,曲目列表自動重新排序" #: quodlibet/qltk/prefs.py:76 msgid "Always allow sorting" msgstr "總是允許排序" #: quodlibet/qltk/prefs.py:78 msgid "Allow sorting by column headers, even for playlists etc" msgstr "允許排序,依照欄位標頭,用於播放清單等" #: quodlibet/qltk/prefs.py:99 msgid "_Others:" msgstr "其他 (_O):" #. Stock edit doesn't have ellipsis chars. #: quodlibet/qltk/prefs.py:104 msgid "_Edit…" msgstr "編輯 (_E)…" #: quodlibet/qltk/prefs.py:107 msgid "Add or remove additional column headers" msgstr "增加或移除外加的欄位標頭" #: quodlibet/qltk/prefs.py:116 msgid "Visible Columns" msgstr "可見欄位" #: quodlibet/qltk/prefs.py:138 msgid "Title includes _version" msgstr "標題包含版本 (_v)" #: quodlibet/qltk/prefs.py:139 msgid "Album includes _disc subtitle" msgstr "專輯包含碟片副標題 (_d)" #: quodlibet/qltk/prefs.py:140 msgid "Artist includes all _people" msgstr "藝人包含全部人員 (_p)" #: quodlibet/qltk/prefs.py:141 msgid "Filename includes _folder" msgstr "檔案名稱包含資料夾 (_f)" #: quodlibet/qltk/prefs.py:142 msgid "Column Preferences" msgstr "欄位設定" #: quodlibet/qltk/prefs.py:145 msgid "_Update Columns" msgstr "更新欄位 (_U)" #: quodlibet/qltk/prefs.py:147 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "套用目前設定至曲目清單,在末端加上新的欄位" #: quodlibet/qltk/prefs.py:161 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "曲目清單" #: quodlibet/qltk/prefs.py:246 msgid "Edit Columns" msgstr "編輯欄位" #: quodlibet/qltk/prefs.py:283 msgid "Duration totals" msgstr "期間總計" #: quodlibet/qltk/prefs.py:294 msgid "_Global filter:" msgstr "通用篩選 (_G):" #: quodlibet/qltk/prefs.py:299 msgid "Apply this query in addition to all others" msgstr "套用此查詢,加進其他全部" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:303 msgctxt "heading" msgid "Search" msgstr "搜尋" #: quodlibet/qltk/prefs.py:307 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "瀏覽窗" #. Ratings #: quodlibet/qltk/prefs.py:312 msgid "Confirm _multiple ratings" msgstr "確認多項評分 (_m)" #: quodlibet/qltk/prefs.py:314 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "多項曲目評分一次更改之前要求確認" #: quodlibet/qltk/prefs.py:317 msgid "Enable _one-click ratings" msgstr "啟用一鍵評分 (_o)" #: quodlibet/qltk/prefs.py:319 msgid "Enable rating by clicking on the rating column in the song list" msgstr "在曲目清單中點按評分欄位即可啟用評分" #: quodlibet/qltk/prefs.py:325 quodlibet/qltk/prefs.py:666 msgid "Ratings" msgstr "評分" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:331 msgid "Prefer _embedded art" msgstr "偏好內嵌藝術圖案 (_m)" #: quodlibet/qltk/prefs.py:333 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "選用在音檔(存在可用)中內嵌的圖案,而非其他來源" #: quodlibet/qltk/prefs.py:338 msgid "" "The album art image file(s) to use when available (supports wildcards). If " "you want to supply more than one, separate them with commas." msgstr "專輯藝術圖檔存在即可使用(支援萬用字元)。如果提供不只一件,用逗號隔開。" #: quodlibet/qltk/prefs.py:342 msgid "_Preferred fixed image filename(s)" msgstr "偏好固定的圖案檔名 (_P)" #: quodlibet/qltk/prefs.py:360 msgid "Album Art" msgstr "專輯藝術設計" #: quodlibet/qltk/prefs.py:393 msgid "Playback" msgstr "回復播放" #: quodlibet/qltk/prefs.py:400 msgid "Output Configuration" msgstr "輸出設定" #: quodlibet/qltk/prefs.py:407 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "如果曲目檔案中沒有播放增益資訊,就依此值為音量大小" #: quodlibet/qltk/prefs.py:410 msgid "_Fall-back gain:" msgstr "_Fall-back增益:" #: quodlibet/qltk/prefs.py:419 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Scale volume for all songs by this value, as long as the result will not clip" #: quodlibet/qltk/prefs.py:422 msgid "_Pre-amp gain:" msgstr "_Pre-amp 增益:" #: quodlibet/qltk/prefs.py:428 msgid "_Enable Replay Gain volume adjustment" msgstr "回放增益音量調整 (_R)" #: quodlibet/qltk/prefs.py:445 msgid "Replay Gain Volume Adjustment" msgstr "回放增益音量調整 (_R)" #: quodlibet/qltk/prefs.py:453 msgid "_Continue playback on startup" msgstr "在啟動時繼續播放 (_C)" #: quodlibet/qltk/prefs.py:456 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "如果播放時停止軟體,在下次啟動時自動開始播放" #: quodlibet/qltk/prefs.py:482 msgid "_Default rating:" msgstr "預設評分 (_D):" #: quodlibet/qltk/prefs.py:525 msgid "Rating _scale:" msgstr "評分範圍 (_s):" #: quodlibet/qltk/prefs.py:574 msgid "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." msgstr "" "Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that albums with few " "tracks will have less extreme ratings. Changing this value triggers a re-" "calculation for all albums." #: quodlibet/qltk/prefs.py:579 msgid "_Bayesian averaging amount:" msgstr "_Bayesian 統計平均值:" #: quodlibet/qltk/prefs.py:592 msgid "_Email:" msgstr "_Email 電子信箱:" #: quodlibet/qltk/prefs.py:594 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "評分和播放計次將會被存入標籤於此電子信箱網址" #: quodlibet/qltk/prefs.py:612 msgid "_Auto-save tag changes" msgstr "自動儲存標籤變更 (_A)" #: quodlibet/qltk/prefs.py:614 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "當編輯多重檔案時,要儲存標籤變更不用確認" #: quodlibet/qltk/prefs.py:629 msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated." msgstr "在標籤編輯器中,分割標籤數值,可以使用分隔字元。此清單以空白分隔。" #: quodlibet/qltk/prefs.py:632 msgid "Split _tag on:" msgstr "分割標籤於 (_t):" #: quodlibet/qltk/prefs.py:645 msgid "" "A set of separators to use when extracting subtags from tags in the tag " "editor. The list is space-separated, and each entry must only contain two " "characters." msgstr "" "在標籤編輯器中,從標籤分割出次標籤,可以使用分隔字元。此清單以空白分隔,每次" "輸入必須只有兩個字元。" #: quodlibet/qltk/prefs.py:650 msgid "Split _subtag on:" msgstr "分割次標籤於 (_s):" #: quodlibet/qltk/prefs.py:660 msgid "Tags" msgstr "標籤" #: quodlibet/qltk/prefs.py:663 msgid "Tag Editing" msgstr "標籤編輯" #: quodlibet/qltk/prefs.py:681 msgid "Updating for new ratings" msgstr "更新新的評分" #: quodlibet/qltk/prefs.py:694 quodlibet/qltk/quodlibetwindow.py:1010 msgid "_Scan Library" msgstr "掃瞄音樂庫 (_S)" #: quodlibet/qltk/prefs.py:696 quodlibet/qltk/quodlibetwindow.py:1072 msgid "Check for changes in your library" msgstr "檢查您的音樂庫變更" #: quodlibet/qltk/prefs.py:701 msgid "Re_build Library" msgstr "重新建立音纅庫 (_b)" #: quodlibet/qltk/prefs.py:704 msgid "Reload all songs in your library. This can take a long time." msgstr "重新載入您的音樂庫中全部曲目。這可能會花一些時間。" #: quodlibet/qltk/prefs.py:719 msgid "Hidden Songs" msgstr "隱藏曲目" #: quodlibet/qltk/prefs.py:727 msgid "Scan library _on start" msgstr "掃瞄音樂庫於啟動時 (_o)" #: quodlibet/qltk/prefs.py:731 msgid "_Watch directories for changes" msgstr "觀注音樂庫更改 (_W)" #: quodlibet/qltk/prefs.py:732 msgid "" "Watch library directories for external file additions, deletions and renames." msgstr "監視音樂庫目錄增刪修改。" #: quodlibet/qltk/prefs.py:742 msgid "Scan Directories" msgstr "掃瞄目錄" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:352 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "%(title)s 還有其他 %(count)d 更多" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "屬性" #: quodlibet/qltk/queue.py:109 msgid "_Queue" msgstr "佇列 (_Q)" #: quodlibet/qltk/queue.py:130 msgid "Clear Queue" msgstr "清除佇列" #: quodlibet/qltk/queue.py:139 msgid "Disable queue - the queue will be ignored when playing" msgstr "停用佇列 - 當播放時會忽略佇列" #: quodlibet/qltk/queue.py:150 msgid "Ephemeral" msgstr "短暫的" #: quodlibet/qltk/queue.py:151 msgid "Remove songs from the queue after playing them" msgstr "移除佇列中曲目在播放之後" #: quodlibet/qltk/queue.py:158 msgid "Persistent" msgstr "持續的" #: quodlibet/qltk/queue.py:159 msgid "Keep songs in the queue after playing them" msgstr "保留佇列中曲目在播放之後" #: quodlibet/qltk/queue.py:167 msgid "Mode" msgstr "模式" #: quodlibet/qltk/queue.py:178 msgid "Stop at End" msgstr "終曲播完後停止" #: quodlibet/qltk/queue.py:298 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d 曲目 (%(time)s)" #: quodlibet/qltk/quodlibetwindow.py:199 msgid "_Browse Library" msgstr "瀏覽音樂庫 (_B)" #: quodlibet/qltk/quodlibetwindow.py:349 msgid "Toggle queue visibility" msgstr "切換可見的佇列" #: quodlibet/qltk/quodlibetwindow.py:377 msgid "Playback Error" msgstr "播放錯誤" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "Set up library directories?" msgstr "設定音樂庫路徑?" #: quodlibet/qltk/quodlibetwindow.py:386 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "您尚未設置音樂庫。現在進行?" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Not Now" msgstr "不要現在 (_N)" #: quodlibet/qltk/quodlibetwindow.py:393 msgid "_Set Up" msgstr "設置 (_S)" #: quodlibet/qltk/quodlibetwindow.py:859 msgid "Unable to add songs" msgstr "無法增加曲目" #: quodlibet/qltk/quodlibetwindow.py:860 quodlibet/qltk/quodlibetwindow.py:1313 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s 使用了未支援的通訊協定。" #: quodlibet/qltk/quodlibetwindow.py:884 msgid "_Jump to Playing Song" msgstr "跳到播放中的曲目 (_J)" #: quodlibet/qltk/quodlibetwindow.py:891 msgid "_File" msgstr "檔案 (_F)" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Song" msgstr "曲目 (_S)" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_View" msgstr "檢視 (_V)" #: quodlibet/qltk/quodlibetwindow.py:894 msgid "_Browse" msgstr "瀏覽窗 (_B)" #: quodlibet/qltk/quodlibetwindow.py:895 msgid "_Control" msgstr "控制 (_C)" #: quodlibet/qltk/quodlibetwindow.py:896 msgid "_Help" msgstr "說明 (_H)" #: quodlibet/qltk/quodlibetwindow.py:902 msgid "_Add a Folder…" msgstr "加入資料夾 (_A)…" #: quodlibet/qltk/quodlibetwindow.py:907 msgid "_Add a File…" msgstr "加入檔案 (_A)…" #: quodlibet/qltk/quodlibetwindow.py:912 msgid "_Add a Location…" msgstr "加入位置 (_A)…" #: quodlibet/qltk/quodlibetwindow.py:941 msgid "Edit Bookmarks…" msgstr "編輯書籤…" #: quodlibet/qltk/quodlibetwindow.py:961 #, fuzzy msgid "Stop" msgstr "停止 (_S)" #: quodlibet/qltk/quodlibetwindow.py:966 msgid "Stop After This Song" msgstr "此首歌曲播完之後停止" #: quodlibet/qltk/quodlibetwindow.py:972 msgid "_Keyboard Shortcuts" msgstr "快速鍵 (_K)" #: quodlibet/qltk/quodlibetwindow.py:981 msgid "Online Help" msgstr "線上輔助" #: quodlibet/qltk/quodlibetwindow.py:990 msgid "Search Help" msgstr "搜尋輔助" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add a Location" msgstr "加入位置" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Enter the location of an audio file:" msgstr "輸入音訊檔案位置:" #: quodlibet/qltk/quodlibetwindow.py:1308 #: quodlibet/qltk/quodlibetwindow.py:1312 msgid "Unable to add location" msgstr "無法加入位置" #: quodlibet/qltk/quodlibetwindow.py:1309 #, python-format msgid "%s is not a valid location." msgstr "%s 不是有效的位置。" #: quodlibet/qltk/quodlibetwindow.py:1321 #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "Add Music" msgstr "增加音樂" #: quodlibet/qltk/quodlibetwindow.py:1321 quodlibet/qltk/scanbox.py:124 msgid "_Add Folders" msgstr "加入資料夾 (_A)" #: quodlibet/qltk/quodlibetwindow.py:1328 msgid "Music Files" msgstr "音樂檔案" #: quodlibet/qltk/quodlibetwindow.py:1330 msgid "_Add Files" msgstr "加入檔案 (_A)" #: quodlibet/qltk/quodlibetwindow.py:1421 #, python-format msgid "Are you sure you want to enqueue %d song?" msgid_plural "Are you sure you want to enqueue %d songs?" msgstr[0] "鄗定要佇列 %d 曲目?" #: quodlibet/qltk/quodlibetwindow.py:1431 msgid "_Enqueue" msgstr "佇列 (_E)" #: quodlibet/qltk/ratingsmenu.py:26 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "確定要更改全部l %d 曲目的評分?" #: quodlibet/qltk/ratingsmenu.py:29 msgid "The saved ratings will be removed" msgstr "已存的評分將會被移除" #: quodlibet/qltk/ratingsmenu.py:30 quodlibet/qltk/ratingsmenu.py:63 msgid "_Remove Rating" msgstr "移除評分 (_R)" #: quodlibet/qltk/ratingsmenu.py:32 #, python-format msgid "The rating of all selected songs will be changed to %s" msgstr "所選曲目的評分全部更改為 %s" #: quodlibet/qltk/ratingsmenu.py:34 msgid "Change _Rating" msgstr "變更評分 (_R)" #: quodlibet/qltk/renamefiles.py:52 msgid "Replace spaces with _underscores" msgstr "以底線替換空白 (_u)" #: quodlibet/qltk/renamefiles.py:62 msgid "Replace [semi]colon delimiting with hyphens" msgstr "用連接字符取代分隔字符" #: quodlibet/qltk/renamefiles.py:63 msgid "e.g. \"iv: allegro.flac\" → \"iv - allegro.flac\"" msgstr "例如 \"iv: allegro.flac\" → \"iv - allegro.flac\"" #: quodlibet/qltk/renamefiles.py:82 msgid "Strip _Windows-incompatible characters" msgstr "抹除不相容 Windows 的字元 (_W)" #: quodlibet/qltk/renamefiles.py:100 msgid "Strip _diacritical marks" msgstr "抹除發音標記 (_D)" #: quodlibet/qltk/renamefiles.py:111 msgid "Strip non-_ASCII characters" msgstr "抹除非 ASCII 字元 (_A)" #: quodlibet/qltk/renamefiles.py:121 msgid "Use only _lowercase characters" msgstr "僅使用小寫字母 (_l)" #: quodlibet/qltk/renamefiles.py:149 msgid "Rename Files" msgstr "重新命名檔案" #: quodlibet/qltk/renamefiles.py:171 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "預覽 (_P)" #: quodlibet/qltk/renamefiles.py:198 msgid "File names" msgstr "檔案名稱" #: quodlibet/qltk/renamefiles.py:208 msgid "_Move album art" msgstr "移動專輯演藝 (_M)" #: quodlibet/qltk/renamefiles.py:211 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "See '[albumart] filenames' config entry for image search strings" #: quodlibet/qltk/renamefiles.py:216 msgid "_Overwrite album art at target" msgstr "覆寫專輯演藝 (_O)" #: quodlibet/qltk/renamefiles.py:224 msgid "_Remove empty directories" msgstr "移除空的目錄 (_R)" #: quodlibet/qltk/renamefiles.py:230 msgid "Album art" msgstr "專輯演藝" #: quodlibet/qltk/renamefiles.py:259 msgid "New Name" msgstr "新建名稱" #: quodlibet/qltk/renamefiles.py:337 msgid "Unable to rename file" msgstr "無法重新命名檔案" #: quodlibet/qltk/renamefiles.py:338 #, python-format msgid "" "Renaming %(old-name)s to %(new-name)s failed. Possibly the target file " "already exists, or you do not have permission to make the new file or remove " "the old one." msgstr "" "重新命名 %(old-name)s 成 %(new-name)s 時失敗。可能目標檔案已存在,或者是您沒" "有足夠的權限來建立新檔案或移除舊檔案。" #: quodlibet/qltk/renamefiles.py:346 msgid "Ignore _All Errors" msgstr "忽略全部錯誤 (_A)" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:347 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "停止 (_S)" #: quodlibet/qltk/renamefiles.py:349 msgid "_Continue" msgstr "繼續 (_C)" #: quodlibet/qltk/renamefiles.py:463 msgid "Path is not absolute" msgstr "此非絕對路徑" #: quodlibet/qltk/renamefiles.py:464 #, python-format msgid "" "The pattern\n" "\t%s\n" "contains / but does not start from root. To avoid misnamed folders, root " "your pattern by starting it with / or ~/." msgstr "" "這個模式\n" "\t%s\n" "包含 / 但不是以根目錄為起始。要避免呼叫錯誤的資料夾,您的起始目錄格式應為 / " "或 ~/。" #: quodlibet/qltk/scanbox.py:49 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "重新整理時,所列資料夾中的樂曲檔案將會加入到音樂庫中" #: quodlibet/qltk/scanbox.py:64 msgid "The new directory will be scanned after adding" msgstr "在加入之後,新的資料夾將會被掃瞄" #: quodlibet/qltk/scanbox.py:67 msgid "" "All songs in the selected directories will also be removed from the library" msgstr "所選取目錄中的樂曲檔案將會全部從音樂庫移除" #: quodlibet/qltk/scanbox.py:70 msgid "_Move" msgstr "移動 (_M)" #: quodlibet/qltk/scanbox.py:72 msgid "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." msgstr "" "Move a scan root (but not the files), migrating metadata for all included " "tracks." #: quodlibet/qltk/scanbox.py:113 msgid "Remove {dir!r} and all its tracks?" msgstr "移除 {dir!r} 及其全部音軌?" #: quodlibet/qltk/scanbox.py:115 #, python-brace-format msgid "Remove {n} library paths and their tracks?" msgstr "移除 {n} 音樂庫路徑及其音軌?" #: quodlibet/qltk/scanbox.py:116 msgid "Remove library path?" msgid_plural "Remove library paths?" msgstr[0] "移除音樂庫路徑?" #: quodlibet/qltk/scanbox.py:117 msgid "Remove" msgstr "移除" #: quodlibet/qltk/scanbox.py:124 msgid "Select Directories" msgstr "選取目錄" #: quodlibet/qltk/scanbox.py:139 msgid "Select This Directory" msgstr "選取此目錄" #: quodlibet/qltk/scanbox.py:141 msgid "Select Actual / New Directory for {dir!r}" msgstr "取消實際 / 新建 目錄於 {dir!r}" #: quodlibet/qltk/scanbox.py:149 msgid "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." msgstr "" "This will move QL metadata:\n" "\n" "{old!r} → {new!r}\n" "\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended (including the Quod Libet 'songs' file)." #: quodlibet/qltk/scanbox.py:155 msgid "Move scan root {dir!r}?" msgstr "移動掃瞄根目錄 {dir!r}?" #: quodlibet/qltk/scanbox.py:157 msgid "OK, move it!" msgstr "好的,進行移動!" #: quodlibet/qltk/searchbar.py:59 msgid "Saved Searches" msgstr "已儲存搜尋值" #: quodlibet/qltk/searchbar.py:59 msgid "Edit saved searches…" msgstr "編輯已儲存搜尋…" #: quodlibet/qltk/searchbar.py:83 msgid "Search your library, using free text or QL queries" msgstr "搜尋您的音樂庫,使用自由文字 或 QL 查詢" #: quodlibet/qltk/searchbar.py:145 msgid "Search after _typing" msgstr "在打字完之後搜尋" #: quodlibet/qltk/searchbar.py:148 msgid "Show search results after the user stops typing" msgstr "Show search results after the user stops typing" #: quodlibet/qltk/searchbar.py:216 msgid "_Limit:" msgstr "限制 (_L):" #: quodlibet/qltk/searchbar.py:229 msgid "_Weight" msgstr "加權 (_W)" #: quodlibet/qltk/searchbar.py:356 msgid "Add query" msgstr "增加查詢" #: quodlibet/qltk/searchbar.py:357 msgid "Add a QL query or free text to be &ed together" msgstr "Add a QL query or free text to be &ed together" #: quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "顯示剩餘時間" #: quodlibet/qltk/shortcuts.py:16 msgid "Main Window" msgstr "主要視窗" #: quodlibet/qltk/shortcuts.py:17 msgid "Seek backwards by 10 seconds" msgstr "倒回10 秒" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek forward by 10 seconds" msgstr "前推10秒" #: quodlibet/qltk/shortcuts.py:19 msgid "Focus the search entry" msgstr "焦點移到搜尋輸入" #: quodlibet/qltk/shortcuts.py:22 msgid "Reset filters and jump to the playing song" msgstr "重設篩選並跳到播放曲目" #: quodlibet/qltk/shortcuts.py:26 msgid "Open the information window for the selected songs" msgstr "開啟資訊視窗來選取曲目" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the tag editor for the selected songs" msgstr "針對所選曲目開啟標籤編輯器" #: quodlibet/qltk/shortcuts.py:28 msgid "Queue the selected songs" msgstr "佇列所選曲目" #: quodlibet/qltk/shortcuts.py:29 msgid "Delete the selected songs" msgstr "刪除所選曲目" #: quodlibet/qltk/shortcuts.py:30 msgid "Show the inline search entry" msgstr "顯示搜尋輸入" #: quodlibet/qltk/shortcuts.py:31 msgid "Left click on a column header" msgstr "左鍵點按欄位檔頭" #: quodlibet/qltk/shortcuts.py:32 msgid "Add the column to the list of columns to sort by" msgstr "增加欄位用以排序" #: quodlibet/qltk/shortcuts.py:34 msgid "Tree View" msgstr "樹狀檢視" #: quodlibet/qltk/shortcuts.py:36 msgid "Collapses the element or select the parent element" msgstr "縮合元件或是選擇上層元件" #: quodlibet/qltk/shortcuts.py:37 msgid "Expands the element" msgstr "擴大元件" #: quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" msgstr "文字輸入" #: quodlibet/qltk/shortcuts.py:41 msgid "Undo the last change" msgstr "復原最後動作" #: quodlibet/qltk/shortcuts.py:42 msgid "Redo the last undone change" msgstr "重複復原動作" #: quodlibet/qltk/shortcuts.py:45 msgid "Select all songs in all panes" msgstr "在全部盤中選擇全部歌曲" #: quodlibet/qltk/songlist.py:389 #, python-format msgid "_Filter on %s" msgstr "以 %s 篩選 (_F)" #: quodlibet/qltk/songlist.py:1193 msgid "All _Headers" msgstr "全部檔頭 (_A)" #: quodlibet/qltk/songlist.py:1194 msgid "_Track Headers" msgstr "音軌檔頭 (_T)" #: quodlibet/qltk/songlist.py:1195 msgid "_Album Headers" msgstr "專輯檔頭 (_A)" #: quodlibet/qltk/songlist.py:1196 msgid "_People Headers" msgstr "人員檔頭 (_P)" #: quodlibet/qltk/songlist.py:1197 msgid "_Date Headers" msgstr "日期檔頭 (_D)" #: quodlibet/qltk/songlist.py:1198 msgid "_File Headers" msgstr "檔案檔頭 (_F)" #: quodlibet/qltk/songlist.py:1199 msgid "_Production Headers" msgstr "產出檔頭 (_P)" #: quodlibet/qltk/songlist.py:1214 msgid "_Customize Headers…" msgstr "自訂檔頭 (_C)…" #: quodlibet/qltk/songlist.py:1219 msgid "_Expand Column" msgstr "擴展橫列 (_E)" #: quodlibet/qltk/songsmenu.py:44 #, python-format msgid "Remove track: \"%(title)s\" from the library?" msgstr "移除音軌:: \"%(title)s\" 從音樂庫?" #: quodlibet/qltk/songsmenu.py:47 #, python-format msgid "Remove %(count)d tracks from the library?" msgstr "從音樂庫中移除 %(count)d 音軌?" #: quodlibet/qltk/songsmenu.py:50 msgid "Remove from Library" msgstr "從音樂庫中移除" #: quodlibet/qltk/songsmenu.py:57 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d song?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d songs?" msgstr[0] "執行外掛 \"%(name)s\" 於 %(count)d 歌曲?" #: quodlibet/qltk/songsmenu.py:68 #, python-format msgid "Run the plugin \"%(name)s\" on %(count)d album?" msgid_plural "Run the plugin \"%(name)s\" on %(count)d albums?" msgstr[0] "執行外掛 \"%(name)s\" 於 %(count)d 專輯?" #: quodlibet/qltk/songsmenu.py:140 msgid "Configure Plugins…" msgstr "設定外掛…" #: quodlibet/qltk/songsmenu.py:324 msgid "Add to _Queue" msgstr "加入佇列 (_Q)" #: quodlibet/qltk/songsmenu.py:344 msgid "_Remove from Library…" msgstr "從音樂庫中移除 (_R)…" #: quodlibet/qltk/songsmenu.py:411 msgid "Unable to show files" msgstr "無法顯示檔案" #: quodlibet/qltk/songsmenu.py:412 msgid "Error showing files, or no program available to show them." msgstr "無法顯示檔案,或是沒有適用程式來顯示。" #: quodlibet/qltk/songsmenu.py:419 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "檔案總管顯示 %(total)d 檔案(_S)" #: quodlibet/qltk/songsmenu.py:436 #, python-format msgid "_Download file…" msgid_plural "_Download %(total)d files…" msgstr[0] "下載 %(total)d 檔案 (_D)…" #: quodlibet/qltk/songsmenu.py:443 msgid "successful" msgstr "成功" #: quodlibet/qltk/songsmenu.py:444 msgid "failed" msgstr "失敗" #: quodlibet/qltk/songsmenu.py:447 msgid "Downloads complete" msgstr "下載完成" #: quodlibet/qltk/songsmenu.py:453 msgid "Download {name!r} to" msgid_plural "Download {total} files to" msgstr[0] "下載 {total} 檔案至" #: quodlibet/qltk/songsmenu.py:459 msgid "Download here" msgstr "下載檔案" #: quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "以空白替換底線 (_u)" #: quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "標籤英文字首大寫 (_T)" #: quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "分割成多重設定值 (_v)" #: quodlibet/qltk/tagsfrompath.py:100 msgid "Tags From Path" msgstr "從路徑名設定標籤" #: quodlibet/qltk/tagsfrompath.py:137 msgid "Tags replace existing ones" msgstr "替換現有的標籤" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags are added to existing ones" msgstr "加入現有的標籤中" #: quodlibet/qltk/tagsfrompath.py:194 #, python-format msgid "" "The pattern\n" "\t%s\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "格式\n" "\t%s\n" "無效。可能是包含兩次同樣的標籤或是括號內不相稱 (< / >)。" #: quodlibet/qltk/textedit.py:141 #, python-format msgid "" "The pattern you entered was invalid. Make sure you enter < and > as " "\\< and \\> and that your tags are balanced.\n" "\n" "%s" msgstr "" "您所輸入的格式無效。確定您輸入 < 和 > 以及 \\< 和 \\> 並且您所輸" "入標籤均相對稱。\n" "\n" "%s" #: quodlibet/qltk/textedit.py:157 msgid "Edit Display" msgstr "編輯顯示" #: quodlibet/qltk/tracknumbers.py:38 msgid "Track Numbers" msgstr "音軌編號" #: quodlibet/qltk/tracknumbers.py:41 msgid "Start fro_m:" msgstr "起始編號 (_m):" #: quodlibet/qltk/tracknumbers.py:50 msgid "_Total tracks:" msgstr "音軌總數 (_T):" #: quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "播放/暫停" #: quodlibet/qltk/unity.py:72 msgid "Previous" msgstr "前一個" #: quodlibet/qltk/views.py:935 #, python-format msgid "and %d more…" msgstr "以及還有 %d 之多…" #: quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "正在儲存所變更的曲目。" #: quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d 歌曲已經儲存\n" "(尚有 %(remaining)s )" #: quodlibet/qltk/wlw.py:234 #, python-format msgid "%(current)s of %(all)s" msgstr "%(all)s 之 %(current)s" #: quodlibet/update.py:90 msgid "Checking for Updates" msgstr "檢查更新" #: quodlibet/update.py:125 msgid "Connection failed" msgstr "連線失敗" #: quodlibet/update.py:134 #, python-format msgid "You are already using the newest version %(version)s" msgstr "您目前使用是最新版本 %(version)s" #: quodlibet/update.py:137 #, python-format msgid "" "A new version %(new-version)s is available\n" "\n" "You are currently using version %(old-version)s\n" "\n" "Visit the <a href='%(url)s'>website</a>" msgstr "" "更新版本 %(new-version)s 現已推出\n" "\n" "您目使用版本 %(old-version)s\n" "\n" "請前往 <a href='%(url)s'>網站</a>" #: quodlibet/util/collection.py:347 msgid "Empty Playlist" msgstr "清空播放清單" #: quodlibet/util/collection.py:445 msgid "Playlists must have a name" msgstr "播放清單必須設置名稱" #: quodlibet/util/collection.py:649 #, python-format msgid "A playlist named %(name)s already exists at %(path)s" msgstr "名為 %(name)s 的播放清單已存在於 %(path)s" #: quodlibet/util/cover/built_in.py:38 msgid "Embedded album covers" msgstr "內嵌的專輯封面" #: quodlibet/util/cover/built_in.py:39 msgid "Uses covers embedded into audio files." msgstr "使用聲音檔案內嵌的封面圖案。" #: quodlibet/util/cover/built_in.py:61 msgid "Filesystem cover" msgstr "檔案系統封面" #: quodlibet/util/cover/built_in.py:62 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "使用歌曲所在路徑資料夾中所找到有名稱的圖檔。" #: quodlibet/util/cover/manager.py:230 msgid "Cover Art" msgstr "封面設計" #: quodlibet/util/cover/manager.py:230 msgid "Querying album art providers" msgstr "查詢專輯封面提供者" #: quodlibet/util/__init__.py:78 msgid "Display brief usage information" msgstr "顯示簡易使用資訊" #: quodlibet/util/__init__.py:80 msgid "Display version and copyright" msgstr "顯示版本與版權" #: quodlibet/util/__init__.py:81 msgid "Print debugging information" msgstr "列印除錯中的資訊" #: quodlibet/util/__init__.py:120 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "使用: %(program)s %(usage)s" #: quodlibet/util/__init__.py:122 msgid "[options]" msgstr "[選項]" #: quodlibet/util/__init__.py:167 #, python-format msgid "Option %r not recognized." msgstr "選項 %r 無法辨識。" #: quodlibet/util/__init__.py:170 #, python-format msgid "Option %r requires an argument." msgstr "選項 %r 需要設置參數。" #: quodlibet/util/__init__.py:173 #, python-format msgid "%r is not a unique prefix." msgstr "此 %r 並非是特定前綴字。" #: quodlibet/util/__init__.py:353 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:408 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s 秒" #: quodlibet/util/__init__.py:421 msgid "No time information" msgstr "無時間資訊" #: quodlibet/util/__init__.py:424 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" #: quodlibet/util/__init__.py:425 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" #: quodlibet/util/__init__.py:426 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 時" #: quodlibet/util/__init__.py:427 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 日" #: quodlibet/util/__init__.py:428 #, python-format msgid "%d year" msgid_plural "%d years" msgstr[0] "%d 年" #. Translators: If tag names, when capitalized, should not #. be title-cased ("Looks Like This"), but rather only have #. the first letter capitalized, translate this string as #. something non-empty other than "titlecase?". #: quodlibet/util/__init__.py:520 msgctxt "check" msgid "titlecase?" msgstr "標題字母大小寫?" #: quodlibet/util/massagers.py:115 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "日期輸入必須以 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' 格式。" #: quodlibet/util/massagers.py:130 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "回放增益增益輸入必須是 'x.yy dB' 格式。" #: quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "回放增益高峰值輸入必須是 'x.yy' 格式。" #: quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "MusicBrainz IDs 必須是 UUID 格式。" #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: quodlibet/util/massagers.py:195 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz 發行狀態必須是 'official' 正式的, 'promotional'提議的, or " "'bootleg' 註腳。" #: quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "語言必須符合 ISO 639-2 three-letter 字碼" #: quodlibet/util/songwrapper.py:112 #, python-format msgid "Saving %d file" msgid_plural "Saving %d files" msgstr[0] "儲存 %d 檔案" #: quodlibet/util/songwrapper.py:113 msgid "Auto-Saving" msgstr "自動-存檔" #: quodlibet/util/songwrapper.py:121 msgid "Unable to edit song" msgstr "無法編輯曲目" #: quodlibet/util/songwrapper.py:122 #, python-format msgid "" "Saving %s failed. The file may be read-only, corrupted, or you do not have " "permission to edit it." msgstr "儲存 %s 時發生錯誤。這個檔案可能唯讀、損壞或是無編輯權限。" #: quodlibet/util/string/__init__.py:32 quodlibet/util/string/__init__.py:42 msgid "[Invalid Encoding]" msgstr "[無效的編碼]" #: quodlibet/util/tags.py:83 msgid "album" msgstr "專輯" #: quodlibet/util/tags.py:84 msgid "arranger" msgstr "編排者" #: quodlibet/util/tags.py:84 msgid "arrangers" msgstr "編排者" #: quodlibet/util/tags.py:84 msgid "arrangement" msgstr "編排者" #: quodlibet/util/tags.py:86 msgid "author" msgstr "作者" #: quodlibet/util/tags.py:86 msgid "authors" msgstr "作者" #: quodlibet/util/tags.py:87 msgid "comment" msgstr "標註" #: quodlibet/util/tags.py:88 msgid "composer" msgstr "作曲" #: quodlibet/util/tags.py:88 msgid "composers" msgstr "作曲" #: quodlibet/util/tags.py:88 msgid "composition" msgstr "作曲" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:90 msgid "conductor" msgstr "指揮" #: quodlibet/util/tags.py:90 msgid "conductors" msgstr "指揮" #: quodlibet/util/tags.py:90 msgid "conducting" msgstr "指揮" #: quodlibet/util/tags.py:91 msgid "contact" msgstr "聯絡" #: quodlibet/util/tags.py:92 msgid "copyright" msgstr "版權" #: quodlibet/util/tags.py:93 msgid "date" msgstr "日期" #: quodlibet/util/tags.py:94 msgid "description" msgstr "描述" #: quodlibet/util/tags.py:95 msgid "genre" msgstr "風格" #: quodlibet/util/tags.py:95 msgid "genres" msgstr "風格" #: quodlibet/util/tags.py:96 msgid "performer" msgstr "演出者" #: quodlibet/util/tags.py:96 msgid "performance" msgstr "演出者" #: quodlibet/util/tags.py:97 msgid "grouping" msgstr "組合" #: quodlibet/util/tags.py:98 msgid "language" msgstr "語言" #: quodlibet/util/tags.py:99 msgid "license" msgstr "許可" #: quodlibet/util/tags.py:101 msgid "lyricist" msgstr "作詞" #: quodlibet/util/tags.py:101 msgid "lyricists" msgstr "作詞" #: quodlibet/util/tags.py:101 msgid "lyrics" msgstr "歌詞" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:103 msgid "organization" msgstr "團體" #: quodlibet/util/tags.py:104 msgid "title" msgstr "標題" #: quodlibet/util/tags.py:105 msgid "version" msgstr "版本" #: quodlibet/util/tags.py:106 msgid "website" msgstr "網站" #: quodlibet/util/tags.py:108 msgid "album artist" msgstr "專輯藝人" #: quodlibet/util/tags.py:109 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:112 quodlibet/util/tags.py:113 msgid "disc subtitle" msgstr "碟片副題" #: quodlibet/util/tags.py:114 quodlibet/util/tags.py:152 msgid "disc" msgstr "碟片" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:154 msgid "track" msgstr "音軌" #: quodlibet/util/tags.py:116 msgid "label ID" msgstr "標籤 ID" #: quodlibet/util/tags.py:117 msgid "original release date" msgstr "原版發行日期" #: quodlibet/util/tags.py:118 msgid "original album" msgstr "原版專輯" #: quodlibet/util/tags.py:119 msgid "original artist" msgstr "原版藝人" #: quodlibet/util/tags.py:120 msgid "recording date" msgstr "錄製日期" #: quodlibet/util/tags.py:121 msgid "release country" msgstr "發行國家" #: quodlibet/util/tags.py:122 msgid "initial key" msgstr "起始音鍵" #. http://musicbrainz.org/doc/MusicBrainzTag #. Note: picard has changed musicbrainz_trackid to mean release track. #. We can't do that because of existing libraries, so use a new #. musicbrainz_releastrackid instead. #: quodlibet/util/tags.py:131 msgid "MusicBrainz recording ID" msgstr "MusicBrainz 錄製音軌 ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release track ID" msgstr "MusicBrainz 發行音軌 ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz release ID" msgstr "MusicBrainz 發行 ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz artist ID" msgstr "MusicBrainz 藝人 ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz 發行藝人 ID" #: quodlibet/util/tags.py:136 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:137 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album status" msgstr "MusicBrainz 專輯狀態" #: quodlibet/util/tags.py:139 msgid "MusicBrainz album type" msgstr "MusicBrainz 專輯類型" #: quodlibet/util/tags.py:140 msgid "MusicBrainz release group ID" msgstr "MusicBrainz 發行分類 ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:143 msgid "track gain" msgstr "音軌增益" #: quodlibet/util/tags.py:144 msgid "track peak" msgstr "音軌高峰值" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:146 msgid "album gain" msgstr "專輯增益" #: quodlibet/util/tags.py:147 msgid "album peak" msgstr "專輯高峰值" #: quodlibet/util/tags.py:148 msgid "reference loudness" msgstr "偏好設定" #: quodlibet/util/tags.py:153 msgid "discs" msgstr "碟片" #: quodlibet/util/tags.py:155 msgid "tracks" msgstr "音軌" #: quodlibet/util/tags.py:156 msgid "last started" msgstr "上次開動" #: quodlibet/util/tags.py:157 msgid "full name" msgstr "全名" #: quodlibet/util/tags.py:164 msgid "mount point" msgstr "掛載點" #: quodlibet/util/tags.py:166 msgid "people" msgstr "個人或團體" #: quodlibet/util/tags.py:168 msgid "year" msgstr "年份" #: quodlibet/util/tags.py:169 msgid "original release year" msgstr "原版發行年份" #: quodlibet/util/tags.py:170 msgid "bookmark" msgstr "書籤" #: quodlibet/util/tags.py:171 msgid "bitdepth" msgstr "bit深度" #: quodlibet/util/tags.py:174 msgid "file format" msgstr "檔案格式" #: quodlibet/util/tags.py:177 msgid "playlists" msgstr "播放清單" #: quodlibet/util/tags.py:178 msgid "sample rate" msgstr "樣本頻率" #: quodlibet/util/tags.py:179 msgid "channel count" msgstr "頻道計數" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:269 msgid "sort" msgstr "排序" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:277 msgid "roles" msgstr "角色" #: data/io.github.quodlibet.ExFalso.desktop.in:3 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "音效標籤編輯器" #: data/io.github.quodlibet.ExFalso.desktop.in:5 #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 msgid "Edit tags in your audio files" msgstr "編輯您的音訊標籤" #: data/io.github.quodlibet.QuodLibet.desktop.in:3 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "音樂播放器" #: data/io.github.quodlibet.QuodLibet.desktop.in:5 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 msgid "Listen to, browse, or edit your audio collection" msgstr "收聽、瀏覽,或編輯您的音訊收藏" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:17 msgid "" "Ex Falso is a tag editor with the same tag editing interface as Quod Libet. " "It lets you display and edit any tags you want in the file, for all the file " "formats it supports." msgstr "" "Ex Falso 是一套音檔資料編輯器,編輯介面如同 Quod Libet 工具,對於所支援的音檔" "格式,讓您可以顯示並編輯檔案內含資料。" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:22 #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:24 msgid "" "Supported file formats include Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/" "IT, Musepack, Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI." msgstr "" "支援檔案格式包括 Ogg Vorbis/Opus/Speex/FLAC, MP3, FLAC, MOD/XM/IT, Musepack, " "Wavpack, MPEG-4 AAC, Monkeys Audio, WMA, SPC, MIDI.。" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:18 msgid "" "Quod Libet is a music management program. It provides several different ways " "to view your audio library, as well as support for Internet radio and audio " "feeds. It has extremely flexible metadata tag editing and searching " "capabilities." msgstr "" "Quod Libet 是一套音樂管理工具程式,提供多種不同方式來呈現音樂庫,以及支援網路" "廣播及音檔播送。擁有極為彈性操作的資料標籤編輯及搜尋能力。" #~ msgid "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgstr "" #~ "Exports a playlist to Sonos playlist, provided both share a directory " #~ "structure." #~ msgid "Export to Sonos playlist" #~ msgstr "匯出至 Sonos 播放清單" #, fuzzy, python-format #~ msgid "Unable to add <b>%s</b>" #~ msgstr "無法加入曲目" #~ msgid "Invalid tags" #~ msgstr "無效的標籤" #, python-format #~ msgid "" #~ "Invalid tags <b>%s</b>\n" #~ "\n" #~ "The files currently selected do not support editing these tags." #~ msgstr "" #~ "無效的標籤 <b>%s</b>\n" #~ "\n" #~ "當前選取的檔案不支援標籤編輯。" #, fuzzy, python-format #~ msgid "%.1f seconds" #~ msgstr "%d 秒" #, fuzzy #~ msgid "Startup" #~ msgstr "匯入 (_I)" #~ msgid "Audio Feeds" #~ msgstr "音訊饋流" #~ msgid "_Audio Feeds" #~ msgstr "音訊饋流 (_A)" #, fuzzy #~ msgid "Searching for lyrics…" #~ msgstr "正在搜尋歌詞..." #, fuzzy #~ msgid "<artist>" #~ msgstr "演出者" #, fuzzy #~ msgid "<album>" #~ msgstr "專輯" #, fuzzy #~ msgid "<title>" #~ msgstr "標題" #, fuzzy #~ msgid "Import Metadata" #~ msgstr "匯入播放清單" #, fuzzy #~ msgid "Migrate Metadata" #~ msgstr "匯入播放清單" #, fuzzy #~ msgid "Information to copy/paste" #~ msgstr "資訊" #~ msgid "Unsupported file type" #~ msgstr "未支援的檔案格式" #~ msgid "Unable to add station" #~ msgstr "無法加入站台" #~ msgid "Device Properties" #~ msgstr "裝置屬性" #~ msgid "Device:" #~ msgstr "裝置:" #~ msgid "Not mounted" #~ msgstr "未掛載" #, fuzzy #~ msgid "Mount point:" #~ msgstr "掛載點:" #~ msgid "Media Devices" #~ msgstr "媒體裝置" #~ msgid "_Media Devices" #~ msgstr "媒體裝置 (_M)" #~ msgid "_Eject" #~ msgstr "退出 (_E)" #, fuzzy #~ msgid "_Properties" #~ msgstr "屬性" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> 已使用,<b>%s</b> 可用" #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "正在複製 <b>%s</b>" #~ msgid "Unable to copy song" #~ msgstr "無法複製曲目" #~ msgid "There is not enough free space for this song." #~ msgstr "沒有足夠的空間給這首曲目。" #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "無法複製 <b>%s</b>。" #~ msgid "Unable to delete songs" #~ msgstr "無法刪除曲目" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "正在刪除 <b>%s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "無法刪除 <b>%s</b>。" #~ msgid "Unable to delete song" #~ msgstr "無法刪除曲目" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "退出 <b>%s</b> 失敗。" #~ msgid "Unable to eject device" #~ msgstr "無法退出裝置" #~ msgid "Search Library" #~ msgstr "搜尋資料庫" #~ msgid "_Search Library" #~ msgstr "搜尋資料庫 (_S)" #~ msgid "Rate the playing song" #~ msgstr "評等播放中的曲目" #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "顯示或隱藏主要曲目清單" #~ msgid "Unknown Device" #~ msgstr "未知的裝置" #, fuzzy #~ msgid "%r is not a supported device." #~ msgstr "錯誤:「%s」不是一個獨特的前綴 (prefix)。" #, fuzzy #~ msgid "Initializing device backend." #~ msgstr "無效的設定值" #, fuzzy #~ msgid "_Filename pattern:" #~ msgstr "檔名型態 (_F)" #, fuzzy #~ msgid "_Clear" #~ msgstr "外掛程式錯誤" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "歌詞" #, fuzzy #~ msgid "Alternate search" #~ msgstr "清除搜尋紀錄" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "歌詞" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "歌詞" #, fuzzy #~ msgid "Skip Songs" #~ msgstr "無曲目" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "瀏覽器" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "無法建立資料夾" #~ msgid "Audio device: %s" #~ msgstr "音訊裝置:%s" #~ msgid "Downloads" #~ msgstr "下載" #~ msgid "Size" #~ msgstr "大小" #~ msgid "_Download" #~ msgstr "下載 (_D)" #~ msgid "_Copy to Device" #~ msgstr "複製到裝置 (_C)" #, fuzzy #~ msgid "browsers" #~ msgstr "瀏覽器" #~ msgid "Unable to download lyrics." #~ msgstr "無法下載歌詞。" #~ msgid "Set or toggle the playback order" #~ msgstr "設定或切換播放順序" #~ msgid "Uninitialized iPod" #~ msgstr "iPod 尚未初始化" #~ msgid "Do you want to create an empty database on this iPod?" #~ msgstr "您是否要在這 iPod 上建立一個空的資料庫?" #~ msgid "_Volume Gain (dB):" #~ msgstr "音量增益 (dB):(_V)" #~ msgid "Combine tags with _multiple values" #~ msgstr "以多個設定值合併標籤" #~ msgid "Capacity:" #~ msgstr "容量:" #~ msgid "Firmware:" #~ msgstr "韌體" #, fuzzy #~ msgid "Saving iPod database…" #~ msgstr "無法儲存 iPod 資料庫" #~ msgid "Unable to save iPod database" #~ msgstr "無法儲存 iPod 資料庫" #, fuzzy #~ msgid "Track Repeat" #~ msgstr "音軌高峰值" #~ msgid "Shuffle" #~ msgstr "洗牌" #~ msgid "Weighted" #~ msgstr "加權" #~ msgid "_Weighted" #~ msgstr "加權 (_W)" #~ msgid "_One Song" #~ msgstr "單曲 (_O)" #~ msgid "Restart the playlist when finished" #~ msgstr "當結束時重新開始這個播放清單" #~ msgid "Disable Browser" #~ msgstr "停用瀏覽器" #~ msgid "_Disable Browser" #~ msgstr "停用瀏覽器 (_D)" #, fuzzy #~ msgid "Force Write" #~ msgstr "寫入" #~ msgid "Filter on _Genre" #~ msgstr "依風格篩選 (_G)" #~ msgid "Filter on _Artist" #~ msgstr "依演出者篩選 (_A)" #~ msgid "Filter on Al_bum" #~ msgstr "依專輯篩選 (_B)" #~ msgid "_Music" #~ msgstr "音樂 (_M)" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "書籤" #~ msgid "Song _List" #~ msgstr "曲目排序 (_L)" #, fuzzy #~ msgid "Stop _after this song" #~ msgstr "在這首歌之後停止" #, fuzzy #~ msgid "Found %d result." #~ msgid_plural "Found %d results." #~ msgstr[0] "與其他 %d 首..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "從專輯分離唱片 (_A)" #, fuzzy #~ msgid "Timeout" #~ msgstr "時間" #, fuzzy #~ msgid "Select an album" #~ msgstr "全選 (_A)" #, fuzzy #~ msgid "%(title)s and %(count)d more…" #~ msgid_plural "%(title)s and %(count)d more…" #~ msgstr[0] "%(title)s 與其他 %(count)d 首..." #, fuzzy #~ msgid "Playlist Export" #~ msgstr "播放清單" #~ msgid "Re_fresh Library" #~ msgstr "重新整理資料庫 (_F)" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "評等 (_R)" #, fuzzy #~ msgid "Invalid audio backend" #~ msgstr "無效的設定值" #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ msgid "command|filename" #~ msgstr "command|filename" #~ msgid "command|tag" #~ msgstr "command|tag" #, fuzzy #~ msgid "heading|Search" #~ msgstr "搜尋" #~ msgid "%d of %d" #~ msgstr "%d 之 %d" #, fuzzy #~ msgid "Usage: %s %s\n" #~ msgstr "使用方法:%s %s" #~ msgid "_Download..." #~ msgstr "下載... (_D)" #, fuzzy #~ msgid "_New Station..." #~ msgstr "新的站台 (_N)" #~ msgid "Overwrite <b>%s</b>?" #~ msgstr "是否複寫 <b>%s</b>?" #~ msgid "Quod Libet is already running." #~ msgstr "Quod Libet 已經在執行了。" #~ msgid "No song is currently playing." #~ msgstr "當前沒有播放中的曲目。" #~ msgid "Unable to write to %s. Removing it." #~ msgstr "無法寫入 %s。正在移除。" #~ msgid "_Edit Bookmarks..." #~ msgstr "編輯書籤... (_E)" #~ msgid "_New Folder..." #~ msgstr "新資料夾... (_N)" #~ msgid "_Add to Playlist" #~ msgstr "加入播放清單 (_A)" #~ msgid "_Edit Display..." #~ msgstr "編輯顯示... (_E)" #, fuzzy #~ msgid "%(song_count)d songs" #~ msgstr "%(count)d 站台" #~ msgid "_Add a Location..." #~ msgstr "加入位置... (_A)" #, fuzzy #~ msgid "Custom _Sort..." #~ msgstr "設置檔頭... (_C)" #, fuzzy #~ msgid "Track Headers" #~ msgstr "音軌檔頭 (_T)" #, fuzzy #~ msgid "People Headers" #~ msgstr "個人或團體檔頭 (_P)" #, fuzzy #~ msgid "Album Headers" #~ msgstr "專輯檔頭 (_A)" #, fuzzy #~ msgid "Date Headers" #~ msgstr "日期檔頭 (_D)" #, fuzzy #~ msgid "File Headers" #~ msgstr "檔案檔頭 (_F)" #, fuzzy #~ msgid "Production Headers" #~ msgstr "出版檔頭 (_P)" #, fuzzy #~ msgid "Tag:" #~ msgstr "標籤:(_T)" #, fuzzy #~ msgid "Warnings" #~ msgstr "評等 (_R)" #, fuzzy #~ msgid "album artist (sort)" #~ msgstr "專輯演出者" #, fuzzy #~ msgid "artist (sort)" #~ msgstr "演出者" #, fuzzy #~ msgid "album (sort)" #~ msgstr "專輯演出者" #, fuzzy #~ msgid "performer (sort)" #~ msgstr "表演者" #, fuzzy #~ msgid "performers (sort)" #~ msgstr "表演者" #~ msgid "MusicBrainz album artist ID" #~ msgstr "MusicBrainz 專輯演出者 ID" #, fuzzy #~ msgid "errors" #~ msgstr "表演者" #~ msgid "Permanently delete this file?" #~ msgstr "永久刪除這個檔案?" #~ msgid "Permanently delete these files?" #~ msgstr "永久刪除這些檔案?" #~ msgid "%(title)s and %(count)d more..." #~ msgid_plural "%(title)s and %(count)d more..." #~ msgstr[0] "%(title)s 與其他 %(count)d 首..." #, fuzzy #~ msgid "Version:" #~ msgstr "版本" #, fuzzy #~ msgid "_Cause an Error" #~ msgstr "外掛程式錯誤" #~ msgid "" #~ "%s could not be added to your library.\n" #~ "\n" #~ msgstr "" #~ "%s 不能被加到您的資料庫。\n" #~ "\n" #~ msgid "No eject command found." #~ msgstr "未發現退出(裝置)指令。" #~ msgid "Unable to start web browser" #~ msgstr "無法啟動網頁瀏覽器" #~ msgid "" #~ "A web browser could not be found. Please set your $BROWSER variable, or " #~ "make sure /usr/bin/sensible-browser exists." #~ msgstr "" #~ "無法找到網頁瀏覽器。請設定您的 $BROWSER 變數,或是確定/usr/bin/sensible-" #~ "browser 是否存在。" #, fuzzy #~ msgid "Library Error" #~ msgstr "資料庫瀏覽器" #, fuzzy #~ msgid "_Output device:" #~ msgstr "複製到裝置 (_C)" #~ msgid "translator-credits" #~ msgstr "" #~ "翻譯者資訊\n" #~ "繁體中文翻譯:\n" #~ "Hsin-lin Cheng <lancetw@gmail.com>\n" #~ "若有任何關於本軟體的繁體中文翻譯問題,歡迎不吝指教。" #~ msgid "Other columns to display, separated by spaces" #~ msgstr "顯示其他欄位,以空白隔開" #, fuzzy #~ msgid "_Edit and Continue" #~ msgstr "繼續 (_C)" #~ msgid "Search your library" #~ msgstr "搜尋您的資料庫" #, fuzzy #~ msgid "" #~ "{title} {version}\n" #~ "<{email}>\n" #~ "Copyright {dates}\t{authors}\n" #~ "\n" #~ "This is free software; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #~ msgstr "" #~ "%s %s - <quodlibet@lists.sacredchao.net>\n" #~ "Copyright 2004-2005 Joe Wreschnig, Michael Urman, and others\n" #~ "\n" #~ "This is free softwae; see the source for copying conditions. There is " #~ "NO\n" #~ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR " #~ "PURPOSE.\n" #, fuzzy #~ msgid "Total size unknown" #~ msgstr "合計大小:" #~ msgid "Quod Libet Plugins" #~ msgstr "Quod Libet 外掛" #~ msgid "" #~ "Display simple searches in blue, advanced ones in green, and invalid ones " #~ "in red" #~ msgstr "用藍色顯示簡單的搜尋,用綠色顯示進階搜尋,用紅色顯示無效的搜尋。" #~ msgid "Separators for splitting tags" #~ msgstr "以分隔符號分開標籤" #~ msgid "Quod Libet Preferences" #~ msgstr "Quod Libet 偏好設定" #~ msgid "Not Played To_day" #~ msgstr "本日沒有播放紀錄 (_D)" #~ msgid "Not Played in a _Week" #~ msgstr "本星期沒有播放紀錄 (_W)" #~ msgid "Not Played in a _Month" #~ msgstr "本月沒有播放紀錄 (_M)" #~ msgid "B_ottom 40" #~ msgstr "倒數 40 名 (_O)" #~ msgid "" #~ "The 40 songs you've played least (more than 40 may be chosen if there are " #~ "ties)" #~ msgstr "這是您播放最少次的 40 首曲目 (排名平手的話或許會超出 40 首)" #~ msgid "gtk-media-next" #~ msgstr "gtk-media-next" #~ msgid "gtk-media-previous" #~ msgstr "gtk-media-previous" #~ msgid "gtk-media-play" #~ msgstr "gtk-media-play" #~ msgid "gtk-media-pause" #~ msgstr "gtk-media-pause" #~ msgid "[ --print-playing | control ]" #~ msgstr "[ --print-playing | control ]" #, fuzzy #~ msgid "Date" #~ msgstr "日期 (_D)" #~ msgid "Add" #~ msgstr "加入" #, fuzzy #~ msgid "Bitrate" #~ msgstr "位元率" #~ msgid "_Stations..." #~ msgstr "站台... (_S)" #~ msgid "Unable to save library" #~ msgstr "無法儲存到資料庫" #, fuzzy #~ msgid "Unable to dump logs, you're boned." #~ msgstr "無法播放曲目" #~ msgid "Sort by title" #~ msgstr "依標題排序" #~ msgid "Sort by artist" #~ msgstr "依演出者排序" #~ msgid "Lyrics provided by %s." #~ msgstr "歌詞是由「%s」所提供。" #~ msgid "" #~ "No lyrics found.\n" #~ "\n" #~ "You can click the Download button to have Quod Libet search for lyrics " #~ "online. You can also enter them yourself and click save." #~ msgstr "" #~ "找不到歌詞。\n" #~ "\n" #~ "您可以按下載按鈕讓 Quod Libet 線上搜尋歌詞。您也可以自行輸入歌詞,然後按儲" #~ "存。" #~ msgid "part" #~ msgstr "部份" #~ msgid "Opening audio device." #~ msgstr "正在開啟音效裝置。" #~ msgid "%d/%d songs saved" #~ msgstr "%d/%d 曲目已儲存" #~ msgid "MusicBrainz album ID" #~ msgstr "MusicBrainz 專輯 ID" #~ msgid "Loaded song library." #~ msgstr "已載入曲目資料庫。" #~ msgid "Unable to open audio device" #~ msgstr "無法開啟音訊狀置" #~ msgid "" #~ "Quod Libet tried to access the 'autosink' and '%(sink)s' drivers but " #~ "could not open them. Set your GStreamer pipeline by changing the\n" #~ " <b>pipeline = %(sink)s</b>\n" #~ "line in ~/.quodlibet/config." #~ msgstr "" #~ "Quod Libet 已嘗試存取「autosink」與「%(sink)s」驅動但無法開啟。設定您的 " #~ "GStreamer 管線,修改 ~/.quodlibet/config 中的\n" #~ " <b>pipeline = %(sink)s</b> 這行。" #~ msgid "" #~ "Quod Libet could not find the 'filesrc' GStreamer element. Check your " #~ "GStreamer installation." #~ msgstr "" #~ "Quod Libet 不能找到 GStreamer 的元件「filesrc」。檢查您的 GStreamer 設置。" #~ msgid "Unable to retag multiple values" #~ msgstr "無法重新標籤多重設定值" #~ msgid "Changing the name of a tag with multiple values is not supported." #~ msgstr "不支援以多重設定值變更標籤名稱。" ������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/poetry.lock�������������������������������������������������������������������������0000644�0001750�0001750�00000201551�14455205526�014413� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" optional = false python-versions = ">=3.6" files = [ {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, ] [[package]] name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = true python-versions = "*" files = [ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] [[package]] name = "babel" version = "2.12.1" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [[package]] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, ] [[package]] name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] name = "coverage" version = "7.2.6" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.7" files = [ {file = "coverage-7.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:496b86f1fc9c81a1cd53d8842ef712e950a4611bba0c42d33366a7b91ba969ec"}, {file = "coverage-7.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fbe6e8c0a9a7193ba10ee52977d4d5e7652957c1f56ccefed0701db8801a2a3b"}, {file = "coverage-7.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d06b721c2550c01a60e5d3093f417168658fb454e5dfd9a23570e9bffe39a1"}, {file = "coverage-7.2.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77a04b84d01f0e12c66f16e69e92616442dc675bbe51b90bfb074b1e5d1c7fbd"}, {file = "coverage-7.2.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35db06450272473eab4449e9c2ad9bc6a0a68dab8e81a0eae6b50d9c2838767e"}, {file = "coverage-7.2.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6727a0d929ff0028b1ed8b3e7f8701670b1d7032f219110b55476bb60c390bfb"}, {file = "coverage-7.2.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aac1d5fdc5378f6bac2c0c7ebe7635a6809f5b4376f6cf5d43243c1917a67087"}, {file = "coverage-7.2.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c9e4a5eb1bbc3675ee57bc31f8eea4cd7fb0cbcbe4912cf1cb2bf3b754f4a80"}, {file = "coverage-7.2.6-cp310-cp310-win32.whl", hash = "sha256:71f739f97f5f80627f1fee2331e63261355fd1e9a9cce0016394b6707ac3f4ec"}, {file = "coverage-7.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:fde5c7a9d9864d3e07992f66767a9817f24324f354caa3d8129735a3dc74f126"}, {file = "coverage-7.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc7b667f8654376e9353dd93e55e12ce2a59fb6d8e29fce40de682273425e044"}, {file = "coverage-7.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:697f4742aa3f26c107ddcb2b1784a74fe40180014edbd9adaa574eac0529914c"}, {file = "coverage-7.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:541280dde49ce74a4262c5e395b48ea1207e78454788887118c421cb4ffbfcac"}, {file = "coverage-7.2.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7f1a8328eeec34c54f1d5968a708b50fc38d31e62ca8b0560e84a968fbf9a9"}, {file = "coverage-7.2.6-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bbd58eb5a2371bf160590f4262109f66b6043b0b991930693134cb617bc0169"}, {file = "coverage-7.2.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae82c5f168d2a39a5d69a12a69d4dc23837a43cf2ca99be60dfe59996ea6b113"}, {file = "coverage-7.2.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f5440cdaf3099e7ab17a5a7065aed59aff8c8b079597b61c1f8be6f32fe60636"}, {file = "coverage-7.2.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a6f03f87fea579d55e0b690d28f5042ec1368650466520fbc400e7aeaf09e995"}, {file = "coverage-7.2.6-cp311-cp311-win32.whl", hash = "sha256:dc4d5187ef4d53e0d4c8eaf530233685667844c5fb0b855fea71ae659017854b"}, {file = "coverage-7.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:c93d52c3dc7b9c65e39473704988602300e3cc1bad08b5ab5b03ca98bbbc68c1"}, {file = "coverage-7.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:42c692b55a647a832025a4c048007034fe77b162b566ad537ce65ad824b12a84"}, {file = "coverage-7.2.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7786b2fa7809bf835f830779ad285215a04da76293164bb6745796873f0942d"}, {file = "coverage-7.2.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25bad4196104761bc26b1dae9b57383826542ec689ff0042f7f4f4dd7a815cba"}, {file = "coverage-7.2.6-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2692306d3d4cb32d2cceed1e47cebd6b1d2565c993d6d2eda8e6e6adf53301e6"}, {file = "coverage-7.2.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:392154d09bd4473b9d11351ab5d63391f3d5d24d752f27b3be7498b0ee2b5226"}, {file = "coverage-7.2.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fa079995432037b5e2ef5ddbb270bcd2ded9f52b8e191a5de11fe59a00ea30d8"}, {file = "coverage-7.2.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d712cefff15c712329113b01088ba71bbcef0f7ea58478ca0bbec63a824844cb"}, {file = "coverage-7.2.6-cp37-cp37m-win32.whl", hash = "sha256:004948e296149644d208964300cb3d98affc5211e9e490e9979af4030b0d6473"}, {file = "coverage-7.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:c1d7a31603c3483ac49c1726723b0934f88f2c011c660e6471e7bd735c2fa110"}, {file = "coverage-7.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3436927d1794fa6763b89b60c896f9e3bd53212001026ebc9080d23f0c2733c1"}, {file = "coverage-7.2.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44c9b9f1a245f3d0d202b1a8fa666a80b5ecbe4ad5d0859c0fb16a52d9763224"}, {file = "coverage-7.2.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e3783a286d5a93a2921396d50ce45a909aa8f13eee964465012f110f0cbb611"}, {file = "coverage-7.2.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cff6980fe7100242170092bb40d2b1cdad79502cd532fd26b12a2b8a5f9aee0"}, {file = "coverage-7.2.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c534431153caffc7c495c3eddf7e6a6033e7f81d78385b4e41611b51e8870446"}, {file = "coverage-7.2.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3062fd5c62df988cea9f2972c593f77fed1182bfddc5a3b12b1e606cb7aba99e"}, {file = "coverage-7.2.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6284a2005e4f8061c58c814b1600ad0074ccb0289fe61ea709655c5969877b70"}, {file = "coverage-7.2.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:97729e6828643f168a2a3f07848e1b1b94a366b13a9f5aba5484c2215724edc8"}, {file = "coverage-7.2.6-cp38-cp38-win32.whl", hash = "sha256:dc11b42fa61ff1e788dd095726a0aed6aad9c03d5c5984b54cb9e1e67b276aa5"}, {file = "coverage-7.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:cbcc874f454ee51f158afd604a315f30c0e31dff1d5d5bf499fc529229d964dd"}, {file = "coverage-7.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d3cacc6a665221108ecdf90517a8028d07a2783df3417d12dcfef1c517e67478"}, {file = "coverage-7.2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:272ab31228a9df857ab5df5d67936d8861464dc89c5d3fab35132626e9369379"}, {file = "coverage-7.2.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a8723ccec4e564d4b9a79923246f7b9a8de4ec55fa03ec4ec804459dade3c4f"}, {file = "coverage-7.2.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5906f6a84b47f995cd1bf0aca1c72d591c55ee955f98074e93660d64dfc66eb9"}, {file = "coverage-7.2.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52c139b7ab3f0b15f9aad0a3fedef5a1f8c0b2bdc291d88639ca2c97d3682416"}, {file = "coverage-7.2.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a5ffd45c6b93c23a8507e2f436983015c6457aa832496b6a095505ca2f63e8f1"}, {file = "coverage-7.2.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4f3c7c19581d471af0e9cb49d928172cd8492cd78a2b7a4e82345d33662929bb"}, {file = "coverage-7.2.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e8c0e79820cdd67978e1120983786422d279e07a381dbf89d03bbb23ec670a6"}, {file = "coverage-7.2.6-cp39-cp39-win32.whl", hash = "sha256:13cde6bb0e58fb67d09e2f373de3899d1d1e866c5a9ff05d93615f2f54fbd2bb"}, {file = "coverage-7.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:6b9f64526286255735847aed0221b189486e0b9ed943446936e41b7e44b08783"}, {file = "coverage-7.2.6-pp37.pp38.pp39-none-any.whl", hash = "sha256:6babcbf1e66e46052442f10833cfc4a0d3554d8276aa37af8531a83ed3c1a01d"}, {file = "coverage-7.2.6.tar.gz", hash = "sha256:2025f913f2edb0272ef15d00b1f335ff8908c921c8eb2013536fcaf61f5a683d"}, ] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] toml = ["tomli"] [[package]] name = "dbus-python" version = "1.3.2" description = "Python bindings for libdbus" optional = true python-versions = ">=3.7" files = [ {file = "dbus-python-1.3.2.tar.gz", hash = "sha256:ad67819308618b5069537be237f8e68ca1c7fcc95ee4a121fe6845b1418248f8"}, ] [package.extras] doc = ["sphinx", "sphinx_rtd_theme"] test = ["tap.py"] [[package]] name = "docutils" version = "0.18.1" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, ] [[package]] name = "exceptiongroup" version = "1.1.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, ] [package.extras] test = ["pytest (>=6)"] [[package]] name = "feedparser" version = "6.0.10" description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" optional = false python-versions = ">=3.6" files = [ {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, ] [package.dependencies] sgmllib3k = "*" [[package]] name = "flake8" version = "6.0.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" files = [ {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"}, {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.10.0,<2.11.0" pyflakes = ">=3.0.0,<3.1.0" [[package]] name = "flaky" version = "3.7.0" description = "Plugin for nose or pytest that automatically reruns flaky tests." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ {file = "flaky-3.7.0-py2.py3-none-any.whl", hash = "sha256:d6eda73cab5ae7364504b7c44670f70abed9e75f77dd116352f662817592ec9c"}, {file = "flaky-3.7.0.tar.gz", hash = "sha256:3ad100780721a1911f57a165809b7ea265a7863305acb66708220820caf8aa0d"}, ] [[package]] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] [[package]] name = "ifaddr" version = "0.2.0" description = "Cross-platform network interface and IP address enumeration library" optional = true python-versions = "*" files = [ {file = "ifaddr-0.2.0-py3-none-any.whl", hash = "sha256:085e0305cfe6f16ab12d72e2024030f5d52674afad6911bb1eee207177b8a748"}, {file = "ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4"}, ] [[package]] name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] [[package]] name = "importlib-metadata" version = "6.6.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.7" files = [ {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] [[package]] name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] [package.dependencies] MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] [[package]] name = "livereload" version = "2.6.3" description = "Python LiveReload is an awesome tool for web developers" optional = false python-versions = "*" files = [ {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] [package.dependencies] six = "*" tornado = {version = "*", markers = "python_version > \"2.7\""} [[package]] name = "markupsafe" version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, ] [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] [[package]] name = "musicbrainzngs" version = "0.7.1" description = "Python bindings for the MusicBrainz NGS and the Cover Art Archive webservices" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ {file = "musicbrainzngs-0.7.1-py2.py3-none-any.whl", hash = "sha256:e841a8f975104c0a72290b09f59326050194081a5ae62ee512f41915090e1a10"}, {file = "musicbrainzngs-0.7.1.tar.gz", hash = "sha256:ab1c0100fd0b305852e65f2ed4113c6de12e68afd55186987b8ed97e0f98e627"}, ] [[package]] name = "mutagen" version = "1.46.0" description = "read and write audio tags for many formats" optional = false python-versions = ">=3.7" files = [ {file = "mutagen-1.46.0-py3-none-any.whl", hash = "sha256:8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"}, {file = "mutagen-1.46.0.tar.gz", hash = "sha256:6e5f8ba84836b99fe60be5fb27f84be4ad919bbb6b49caa6ae81e70584b55e58"}, ] [[package]] name = "mypy" version = "1.3.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.7" files = [ {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=3.10" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] python2 = ["typed-ast (>=1.4.0,<2)"] reports = ["lxml"] [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "packaging" version = "23.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] [[package]] name = "paho-mqtt" version = "1.6.1" description = "MQTT version 5.0/3.1.1 client class" optional = true python-versions = "*" files = [ {file = "paho-mqtt-1.6.1.tar.gz", hash = "sha256:2a8291c81623aec00372b5a85558a372c747cbca8e9934dfe218638b8eefc26f"}, ] [package.extras] proxy = ["PySocks"] [[package]] name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.6" files = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] [[package]] name = "polib" version = "1.2.0" description = "A library to manipulate gettext files (po and mo files)." optional = false python-versions = "*" files = [ {file = "polib-1.2.0-py2.py3-none-any.whl", hash = "sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d"}, {file = "polib-1.2.0.tar.gz", hash = "sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b"}, ] [[package]] name = "pycairo" version = "1.23.0" description = "Python interface for cairo" optional = false python-versions = ">=3.7" files = [ {file = "pycairo-1.23.0-cp310-cp310-win32.whl", hash = "sha256:564601e5f528531c6caec1c0177c3d0709081e1a2a5cccc13561f715080ae535"}, {file = "pycairo-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:e7cde633986435d87a86b6118b7b6109c384266fd719ef959883e2729f6eafae"}, {file = "pycairo-1.23.0-cp311-cp311-win32.whl", hash = "sha256:3a71f758e461180d241e62ef52e85499c843bd2660fd6d87cec99c9833792bfa"}, {file = "pycairo-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:2dec5378133778961993fb59d66df16070e03f4d491b67eb695ca9ad7a696008"}, {file = "pycairo-1.23.0-cp37-cp37m-win32.whl", hash = "sha256:d6bacff15d688ed135b4567965a4b664d9fb8de7417a7865bb138ad612043c9f"}, {file = "pycairo-1.23.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ec305fc7f2f0299df78aadec0eaf6eb9accb90eda242b5d3492544d3f2b28027"}, {file = "pycairo-1.23.0-cp38-cp38-win32.whl", hash = "sha256:1a6d8e0f353062ad92954784e33dbbaf66c880c9c30e947996c542ed9748aaaf"}, {file = "pycairo-1.23.0-cp38-cp38-win_amd64.whl", hash = "sha256:82e335774a17870bc038e0c2fb106c1e5e7ad0c764662023886dfcfce5bb5a52"}, {file = "pycairo-1.23.0-cp39-cp39-win32.whl", hash = "sha256:a4b1f525bbdf637c40f4d91378de36c01ec2b7f8ecc585b700a079b9ff83298e"}, {file = "pycairo-1.23.0-cp39-cp39-win_amd64.whl", hash = "sha256:87efd62a7b7afad9a0a420f05b6008742a6cfc59077697be65afe8dc73ae15ad"}, {file = "pycairo-1.23.0.tar.gz", hash = "sha256:9b61ac818723adc04367301317eb2e814a83522f07bbd1f409af0dada463c44c"}, ] [[package]] name = "pycodestyle" version = "2.10.0" description = "Python style guide checker" optional = false python-versions = ">=3.6" files = [ {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, ] [[package]] name = "pyflakes" version = "3.0.1" description = "passive checker of Python programs" optional = false python-versions = ">=3.6" files = [ {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"}, {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, ] [[package]] name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, ] [package.extras] plugins = ["importlib-metadata"] [[package]] name = "pygobject" version = "3.44.1" description = "Python bindings for GObject Introspection" optional = false python-versions = ">=3.7, <4" files = [ {file = "PyGObject-3.44.1.tar.gz", hash = "sha256:665fbe980c91e8b31ad78ed3f66879946948200864002d193f67eccc1d7d5d83"}, ] [package.dependencies] pycairo = ">=1.16,<2.0" [[package]] name = "pypresence" version = "4.2.1" description = "Discord RPC client written in Python" optional = true python-versions = ">=3.5" files = [ {file = "pypresence-4.2.1-py2.py3-none-any.whl", hash = "sha256:12197b5f51c21e3e555b17f85d3e55023f4ad83b6fff72cd6387659ffd484a02"}, {file = "pypresence-4.2.1.tar.gz", hash = "sha256:691daf98c8189fd216d988ebfc67779e0f664211512d9843f37ab0d51d4de066"}, ] [[package]] name = "pytest" version = "7.3.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pytz" version = "2023.3" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, ] [[package]] name = "pyvirtualdisplay" version = "3.0" description = "python wrapper for Xvfb, Xephyr and Xvnc" optional = false python-versions = "*" files = [ {file = "PyVirtualDisplay-3.0-py3-none-any.whl", hash = "sha256:40d4b8dfe4b8de8552e28eb367647f311f88a130bf837fe910e7f180d5477f0e"}, {file = "PyVirtualDisplay-3.0.tar.gz", hash = "sha256:09755bc3ceb6eb725fb07eca5425f43f2358d3bf08e00d2a9b792a1aedd16159"}, ] [[package]] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.7" files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "sgmllib3k" version = "1.0.0" description = "Py3k port of sgmllib." optional = false python-versions = "*" files = [ {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, ] [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] [[package]] name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = false python-versions = "*" files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] [[package]] name = "soco" version = "0.27.1" description = "SoCo (Sonos Controller) is a simple library to control Sonos speakers." optional = true python-versions = ">=3.5" files = [ {file = "soco-0.27.1-py2.py3-none-any.whl", hash = "sha256:89b668ab2802ae90be5dee3f19dc068654c3d543c4abc6915caae6657a79aaf7"}, {file = "soco-0.27.1.tar.gz", hash = "sha256:c0e747a107bc3e9a4c6eb24477ebb1dfc67febe75300e227bd98fcc7ff2f5e01"}, ] [package.dependencies] appdirs = "*" ifaddr = "*" requests = "*" xmltodict = "*" [package.extras] events-asyncio = ["aiohttp"] [[package]] name = "sphinx" version = "6.2.1" description = "Python documentation generator" optional = false python-versions = ">=3.8" files = [ {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, ] [package.dependencies] alabaster = ">=0.7,<0.8" babel = ">=2.9" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} docutils = ">=0.18.1,<0.20" imagesize = ">=1.3" importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} Jinja2 = ">=3.0" packaging = ">=21.0" Pygments = ">=2.13" requests = ">=2.25.0" snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] [[package]] name = "sphinx-autobuild" version = "2021.3.14" description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." optional = false python-versions = ">=3.6" files = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, ] [package.dependencies] colorama = "*" livereload = "*" sphinx = "*" [package.extras] test = ["pytest", "pytest-cov"] [[package]] name = "sphinx-rtd-theme" version = "1.2.1" description = "Read the Docs theme for Sphinx" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ {file = "sphinx_rtd_theme-1.2.1-py2.py3-none-any.whl", hash = "sha256:2cc9351176cbf91944ce44cefd4fab6c3b76ac53aa9e15d6db45a3229ad7f866"}, {file = "sphinx_rtd_theme-1.2.1.tar.gz", hash = "sha256:cf9a7dc0352cf179c538891cb28d6fad6391117d4e21c891776ab41dd6c8ff70"}, ] [package.dependencies] docutils = "<0.19" sphinx = ">=1.6,<7" sphinxcontrib-jquery = {version = ">=2.0.0,<3.0.0 || >3.0.0", markers = "python_version > \"3\""} [package.extras] dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] [[package]] name = "sphinxcontrib-applehelp" version = "1.0.4" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.8" files = [ {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." optional = false python-versions = ">=3.5" files = [ {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.8" files = [ {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["html5lib", "pytest"] [[package]] name = "sphinxcontrib-jquery" version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" optional = false python-versions = ">=2.7" files = [ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, ] [package.dependencies] Sphinx = ">=1.8" [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = false python-versions = ">=3.5" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, ] [package.extras] test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." optional = false python-versions = ">=3.5" files = [ {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." optional = false python-versions = ">=3.5" files = [ {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] [[package]] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.7" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] [[package]] name = "tornado" version = "6.3.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">= 3.8" files = [ {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"}, {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"}, {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"}, {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"}, {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"}, {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"}, {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"}, {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"}, {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"}, {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"}, {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"}, ] [[package]] name = "types-certifi" version = "2021.10.8.3" description = "Typing stubs for certifi" optional = false python-versions = "*" files = [ {file = "types-certifi-2021.10.8.3.tar.gz", hash = "sha256:72cf7798d165bc0b76e1c10dd1ea3097c7063c42c21d664523b928e88b554a4f"}, {file = "types_certifi-2021.10.8.3-py3-none-any.whl", hash = "sha256:b2d1e325e69f71f7c78e5943d410e650b4707bb0ef32e4ddf3da37f54176e88a"}, ] [[package]] name = "types-docutils" version = "0.19.1.9" description = "Typing stubs for docutils" optional = false python-versions = "*" files = [ {file = "types-docutils-0.19.1.9.tar.gz", hash = "sha256:1d029567e67c52992fd42aa968778bc10a5e445c8450fc751d672d6f50330a4a"}, {file = "types_docutils-0.19.1.9-py3-none-any.whl", hash = "sha256:556fb7ee19248aa482caa142a830c940b776b0f8c7577a98abe0977574546a1d"}, ] [[package]] name = "types-requests" version = "2.31.0.0" description = "Typing stubs for requests" optional = false python-versions = "*" files = [ {file = "types-requests-2.31.0.0.tar.gz", hash = "sha256:c1c29d20ab8d84dff468d7febfe8e0cb0b4664543221b386605e14672b44ea25"}, {file = "types_requests-2.31.0.0-py3-none-any.whl", hash = "sha256:7c5cea7940f8e92ec560bbc468f65bf684aa3dcf0554a6f8c4710f5f708dc598"}, ] [package.dependencies] types-urllib3 = "*" [[package]] name = "types-urllib3" version = "1.26.25.13" description = "Typing stubs for urllib3" optional = false python-versions = "*" files = [ {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"}, {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, ] [[package]] name = "typing-extensions" version = "4.6.1" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" files = [ {file = "typing_extensions-4.6.1-py3-none-any.whl", hash = "sha256:6bac751f4789b135c43228e72de18637e9a6c29d12777023a703fd1a6858469f"}, {file = "typing_extensions-4.6.1.tar.gz", hash = "sha256:558bc0c4145f01e6405f4a5fdbd82050bd221b119f4bf72a961a1cfd471349d6"}, ] [[package]] name = "urllib3" version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.7" files = [ {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "xmltodict" version = "0.13.0" description = "Makes working with XML feel like you are working with JSON" optional = true python-versions = ">=3.4" files = [ {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, ] [[package]] name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.7" files = [ {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [extras] plugins = ["dbus-python", "musicbrainzngs", "paho-mqtt", "pypresence", "soco"] [metadata] lock-version = "2.0" python-versions = "^3.8.1" content-hash = "0e6263276488d0bcac462c4c7facfe21b335344172aa786c5ff194235475ee39" �������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/pyproject.toml����������������������������������������������������������������������0000644�0001750�0001750�00000003501�14455205526�015126� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[tool.poetry] name = "quodlibet" version = "4.6.0-pre" description = "A music library, tagger, and player" authors = ["Joe Wreschnig", "Michael Urman", "Steven Robertson", "Christoph Reiter", "Nick Boultbee", "(many others)"] maintainers = ["Christoph Reiter"] homepage = "https://quodlibet.readthedocs.io/" documentation = "https://quodlibet.readthedocs.io/" repository = "https://github.com/quodlibet/quodlibet" keywords = ["audio", "music", "player", "tags", "gtk"] license = "GPL-2.0-or-later" packages = [ { include = "quodlibet", from = "." } ] [tool.poetry.scripts] # Convenience: `poetry run quodlibet` just runs the app (with no CLI args) quodlibet = "quodlibet.main:main" [tool.poetry.dependencies] python = "^3.8.1" mutagen = "^1.45" feedparser = "^5.2 || ^6.0" pycairo = "^1.19" pygobject = "^3.34.0" # Optional (mainly plugins) musicbrainzngs = { version = "0.*", optional = true } dbus-python = { version = "*", platform="linux", optional = true } # 0.28 switched to lxml which is proving tricky on Windows soco = { version = ">=0.27, <0.28", optional = true } pypresence = { version = "^4.2.1", optional = true } paho-mqtt = { version = "^1.6.1", optional = true } [tool.poetry.extras] # Use with poetry install -E plugins plugins = ["musicbrainzngs", "dbus-python", "paho-mqtt", "soco", "pypresence"] [tool.poetry.dev-dependencies] pytest = '^7.2.2' polib = '^1.2.0' sphinx = '^6.1.3' sphinx_rtd_theme = '^1.2.0' sphinx-autobuild = "^2021.3.14" flake8 = "^6.0.0" coverage = { extras = ["toml"], version = "^7.2.1" } mypy = "1.3.0" flaky = "^3.7.0" types-docutils = "^0.19.0" types-certifi = "^2021.10.8.3" types-requests = "^2.28.11.15" pyvirtualdisplay = { version = "^3.0", platform = "linux" } [tool.coverage.run] omit = ["quodlibet/packages/*"] include = ["quodlibet/*"] [build-system] requires = ["setuptools", "wheel"] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/��������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014172� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/__init__.py���������������������������������������������������������������0000664�0001750�0001750�00000002554�14035600052�016307� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys import os if sys.platform == "win32": # To prevent us loading DLLs in the system directory which clash # with the ones we ship. # https://github.com/quodlibet/quodlibet/issues/2817 from ctypes import windll windll.kernel32.SetDllDirectoryW(os.path.dirname(sys.executable)) from ._import import install_redirect_import_hook install_redirect_import_hook() from .util.i18n import _, C_, N_, ngettext, npgettext from .util.dprint import print_d, print_e, print_w from ._init import init_cli, init from ._main import get_base_dir, is_release, get_user_dir, app, \ set_application_info, init_plugins, enable_periodic_save, run, \ finish_first_session, get_image_dir, is_first_session, \ get_build_description, get_build_version, get_cache_dir _, C_, N_, ngettext, npgettext, is_release, init, init_cli, print_e, \ get_base_dir, print_w, print_d, get_user_dir, app, set_application_info, \ init_plugins, enable_periodic_save, run, finish_first_session, \ get_image_dir, is_first_session, get_build_description, \ get_build_version, get_cache_dir ����������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/_import.py����������������������������������������������������������������0000664�0001750�0001750�00000003334�14035600052�016216� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys import importlib class RedirectImportHook: """Import hook which loads packages as sub packages. e.g. "import raven" will import "quodlibet.packages.raven" even if raven uses absolute imports internally. """ def __init__(self, name, packages): """ Args: name (str): The package path to load the packages from packages (List[str]): A list of packages provided """ for package in packages: if package in sys.modules: raise Exception("%r already loaded, can't redirect" % package) self._name = name self._packages = packages def find_module(self, fullname, path=None): package = fullname.split(".")[0] if package in self._packages: return self def load_module(self, name): mod = None if name in sys.modules: mod = sys.modules[name] loadname = self._name + "." + name if loadname in sys.modules: mod = sys.modules[loadname] if mod is None: mod = importlib.import_module(loadname) sys.modules[name] = mod sys.modules[loadname] = mod return mod def install_redirect_import_hook(): """Install the import hook, does not import anything""" import_hook = RedirectImportHook( "quodlibet.packages", ["senf", "raven"]) sys.meta_path.insert(0, import_hook) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/_init.py������������������������������������������������������������������0000644�0001750�0001750�00000030713�14455205526�015663� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys import warnings import logging from senf import fsn2text from quodlibet.const import MinVersions from quodlibet import config from quodlibet.util import is_osx, is_windows, i18n from quodlibet.util.dprint import print_e, PrintHandler, print_d from quodlibet.util.urllib import install_urllib2_ca_file from ._main import get_base_dir, is_release, get_image_dir, get_cache_dir _cli_initialized = False _initialized = False def _init_gtk_debug(no_excepthook): from quodlibet.errorreport import enable_errorhook enable_errorhook(not no_excepthook) def is_init(): """Returns if init() was called""" global _initialized return _initialized def init(no_translations=False, no_excepthook=False, config_file=None): """This needs to be called before any API can be used. Might raise in case of an error. Pass no_translations=True to disable translations (used by tests) """ global _initialized if _initialized: return init_cli(no_translations=no_translations, config_file=config_file) _init_gtk() _init_gtk_debug(no_excepthook=no_excepthook) _init_gst() _init_dbus() _initialized = True def _init_gettext(no_translations=False): """Call before using gettext helpers""" if no_translations: language = u"C" else: language = config.gettext("settings", "language") if language: print_d(f"Using language in QL settings: {language!r}") else: language = None i18n.init(language) # Use the locale dir in ../build/share/locale if there is one localedir = os.path.join( os.path.dirname(get_base_dir()), "build", "share", "locale") if os.path.isdir(localedir): print_d(f"Using local locale dir {localedir}") else: localedir = None i18n.register_translation("quodlibet", localedir) debug_text = os.environ.get("QUODLIBET_TEST_TRANS") if debug_text is not None: i18n.set_debug_text(fsn2text(debug_text)) def _init_python(): MinVersions.PYTHON3.check(sys.version_info) if is_osx(): # We build our own openssl on OSX and need to make sure that # our own ca file is used in all cases as the non-system openssl # doesn't use the system certs install_urllib2_ca_file() if is_windows(): # Not really needed on Windows as pygi-aio seems to work fine, but # wine doesn't have certs which we use for testing. install_urllib2_ca_file() if is_windows() and os.sep != "\\": # In the MSYS2 console MSYSTEM is set, which breaks os.sep/os.path.sep # If you hit this, do a "setup.py clean -all" to get rid of the # bytecode cache then start things with "MSYSTEM= ..." raise AssertionError("MSYSTEM is set (%r)" % os.environ.get("MSYSTEM")) logging.getLogger().addHandler(PrintHandler()) def _init_formats(): from quodlibet.formats import init init() def init_cli(no_translations=False, config_file=None): """This needs to be called before any API can be used. Might raise in case of an error. Like init() but for code not using Gtk etc. """ global _cli_initialized if _cli_initialized: return _init_python() config.init_defaults() if config_file is not None: config.init(config_file) _init_gettext(no_translations) _init_formats() _init_g() _cli_initialized = True def _init_dbus(): """Setup dbus mainloop integration. Call before using dbus""" # To make GDBus fail early and we don't have to wait for a timeout if is_osx() or is_windows(): os.environ["DBUS_SYSTEM_BUS_ADDRESS"] = "something-invalid" os.environ["DBUS_SESSION_BUS_ADDRESS"] = "something-invalid" try: from dbus.mainloop.glib import DBusGMainLoop, threads_init except ImportError: try: import dbus.glib dbus.glib except ImportError: return else: threads_init() DBusGMainLoop(set_as_default=True) def _fix_gst_leaks(): """gst_element_add_pad and gst_bin_add are wrongly annotated and lead to PyGObject refing the passed element. Work around by adding a wrapper that unrefs afterwards. Can be called multiple times. https://bugzilla.gnome.org/show_bug.cgi?id=741390 https://bugzilla.gnome.org/show_bug.cgi?id=702960 """ from gi.repository import Gst assert Gst.is_initialized() def do_wrap(func): def wrap(self, obj): result = func(self, obj) obj.unref() return result return wrap parent = Gst.Bin() elm = Gst.Bin() parent.add(elm) if elm.__grefcount__ == 3: elm.unref() Gst.Bin.add = do_wrap(Gst.Bin.add) pad = Gst.Pad.new("foo", Gst.PadDirection.SRC) parent.add_pad(pad) if pad.__grefcount__ == 3: pad.unref() Gst.Element.add_pad = do_wrap(Gst.Element.add_pad) def _init_g(): """Call before using GdkPixbuf/GLib/Gio/GObject""" import gi gi.require_version("GLib", "2.0") gi.require_version("Gio", "2.0") gi.require_version("GObject", "2.0") gi.require_version("GdkPixbuf", "2.0") # Newer glib is noisy regarding deprecated signals/properties # even with stable releases. if is_release(): warnings.filterwarnings( 'ignore', '.* It will be removed in a future version.', Warning) # blacklist some modules, simply loading can cause segfaults sys.modules["glib"] = None sys.modules["gobject"] = None def _init_gtk(): """Call before using Gtk/Gdk""" import gi if config.getboolean("settings", "pangocairo_force_fontconfig") and \ "PANGOCAIRO_BACKEND" not in os.environ: os.environ["PANGOCAIRO_BACKEND"] = "fontconfig" # disable for consistency and trigger events seem a bit flaky here if config.getboolean("settings", "scrollbar_always_visible"): os.environ["GTK_OVERLAY_SCROLLING"] = "0" try: # not sure if this is available under Windows gi.require_version("GdkX11", "3.0") from gi.repository import GdkX11 GdkX11 except (ValueError, ImportError): pass gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") gi.require_version("Pango", "1.0") gi.require_version('Soup', '3.0') gi.require_version('PangoCairo', "1.0") from gi.repository import Gtk from quodlibet.qltk import ThemeOverrider, gtk_version # PyGObject doesn't fail anymore when init fails, so do it ourselves initialized, sys.argv[:] = Gtk.init_check(sys.argv) if not initialized: raise SystemExit("Gtk.init failed") # include our own icon theme directory theme = Gtk.IconTheme.get_default() theme_search_path = get_image_dir() assert os.path.exists(theme_search_path) theme.append_search_path(theme_search_path) # Force menu/button image related settings. We might show too many atm # but this makes sure we don't miss cases where we forgot to force them # per widget. # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # some day... but not now warnings.filterwarnings( 'ignore', '.*Stock items are deprecated.*', Warning) warnings.filterwarnings( 'ignore', '.*:use-stock.*', Warning) warnings.filterwarnings( 'ignore', r'.*The property GtkAlignment:[^\s]+ is deprecated.*', Warning) settings = Gtk.Settings.get_default() with warnings.catch_warnings(): warnings.simplefilter("ignore") settings.set_property("gtk-button-images", True) settings.set_property("gtk-menu-images", True) if hasattr(settings.props, "gtk_primary_button_warps_slider"): # https://bugzilla.gnome.org/show_bug.cgi?id=737843 settings.set_property("gtk-primary-button-warps-slider", True) # Make sure PyGObject includes support for foreign cairo structs try: gi.require_foreign("cairo") except ImportError: print_e("PyGObject is missing cairo support") sys.exit(1) css_override = ThemeOverrider() if sys.platform == "darwin": # fix duplicated shadows for popups with Gtk+3.14 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" GtkWindow { box-shadow: none; } .tooltip { border-radius: 0; padding: 0; } .tooltip.background { background-clip: border-box; } """) css_override.register_provider("", style_provider) if gtk_version[:2] >= (3, 20): # https://bugzilla.gnome.org/show_bug.cgi?id=761435 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" spinbutton, button { min-height: 22px; } .view button { min-height: 24px; } entry { min-height: 28px; } entry.cell { min-height: 0; } """) css_override.register_provider("Adwaita", style_provider) css_override.register_provider("HighContrast", style_provider) # https://github.com/quodlibet/quodlibet/issues/2541 style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" treeview.view.separator { min-height: 2px; color: @borders; } """) css_override.register_provider("Ambiance", style_provider) css_override.register_provider("Radiance", style_provider) # https://github.com/quodlibet/quodlibet/issues/2677 css_override.register_provider("Clearlooks-Phenix", style_provider) # https://github.com/quodlibet/quodlibet/issues/2997 css_override.register_provider("Breeze", style_provider) if gtk_version[:2] >= (3, 18): # Hack to get some grab handle like thing for panes style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" GtkPaned.vertical, paned.vertical >separator { -gtk-icon-source: -gtk-icontheme("view-more-symbolic"); -gtk-icon-transform: rotate(90deg) scaleX(0.1) scaleY(3); } GtkPaned.horizontal, paned.horizontal >separator { -gtk-icon-source: -gtk-icontheme("view-more-symbolic"); -gtk-icon-transform: rotate(0deg) scaleX(0.1) scaleY(3); } """) css_override.register_provider("", style_provider) # https://bugzilla.gnome.org/show_bug.cgi?id=708676 warnings.filterwarnings('ignore', '.*g_value_get_int.*', Warning) # blacklist some modules, simply loading can cause segfaults sys.modules["gtk"] = None sys.modules["gpod"] = None sys.modules["gnome"] = None from quodlibet.qltk import pygobject_version, gtk_version MinVersions.GTK.check(gtk_version) MinVersions.PYGOBJECT.check(pygobject_version) def _init_gst(): """Call once before importing GStreamer""" arch_key = "64" if sys.maxsize > 2**32 else "32" registry_name = "gst-registry-%s-%s.bin" % (sys.platform, arch_key) os.environ["GST_REGISTRY"] = os.path.join(get_cache_dir(), registry_name) assert "gi.repository.Gst" not in sys.modules import gi # We don't want python-gst, it changes API.. assert "gi.overrides.Gst" not in sys.modules sys.modules["gi.overrides.Gst"] = None # blacklist some modules, simply loading can cause segfaults sys.modules["gst"] = None # We don't depend on Gst overrides, so make sure it's initialized. try: gi.require_version("Gst", "1.0") from gi.repository import Gst except (ValueError, ImportError): return if Gst.is_initialized(): return from gi.repository import GLib try: ok, sys.argv[:] = Gst.init_check(sys.argv) except GLib.GError: print_e("Failed to initialize GStreamer") # Uninited Gst segfaults: make sure no one can use it sys.modules["gi.repository.Gst"] = None else: # monkey patching ahead _fix_gst_leaks() �����������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689589142.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/_main.py������������������������������������������������������������������0000644�0001750�0001750�00000027624�14455212626�015652� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys from senf import path2fsn from quodlibet import util from quodlibet import const from quodlibet import build from quodlibet.util import cached_func, windows, set_process_title, is_osx from quodlibet.util.dprint import print_d from quodlibet.util.path import mkdir, xdg_get_config_home, xdg_get_cache_home PLUGIN_DIRS = ["editing", "events", "playorder", "songsmenu", "playlist", "gstreamer", "covers", "query"] class Application: """A main application class for controlling the application as a whole and accessing submodules. window - The main window which is present as long as QL is running library - The main library (see library.SongFileLibrary) librarian - The main (and atm only) librarian (see library.SongLibrarian) player - see player._base quit() - Quit the application """ window = None library = None player = None player_options = None """A PlayerOptions instance or None in case there is no playback support""" cover_manager = None name = None """The application name e.g. 'Quod Libet'""" description = None """A short description of the application""" id = None """The application ID e.g. 'io.github.quodlibet.QuodLibet'""" process_name = None """e.g. quodlibet""" is_quitting = False """True after quit() is called at least once""" is_restarting = False """True if the program should restart after quitting""" @property def icon_name(self): return self.id @property def symbolic_icon_name(self): return "%s-symbolic" % self.icon_name @property def librarian(self): return self.library.librarian @property def browser(self): return self.window.browser def restart(self): self.is_restarting = True self.quit() def quit(self): from gi.repository import GLib self.is_quitting = True def idle_quit(): if self.window: self.window.destroy() # so this can be called from a signal handler and before # the main loop starts GLib.idle_add(idle_quit, priority=GLib.PRIORITY_HIGH) def show(self): from quodlibet.qltk import Window for window in Window.windows: window.show() def present(self): # deiconify is needed if the window is on another workspace from quodlibet.qltk import Window for window in Window.windows: window.deiconify() window.present() def hide(self): from quodlibet.qltk import Window for window in Window.windows: window.hide() app = Application() @cached_func def get_base_dir(): """The path to the quodlibet package""" return util.get_module_dir() @cached_func def get_image_dir(): """The path to the image directory in the quodlibet package""" return os.path.join(get_base_dir(), "images") @cached_func def get_cache_dir(): """The directory to store things into which can be deleted at any time""" if os.name == "nt" and build.BUILD_TYPE == u"windows-portable": # avoid writing things to the host system for the portable build path = os.path.join(get_user_dir(), "cache") else: path = os.path.join(xdg_get_cache_home(), "quodlibet") mkdir(path, 0o700) return path @cached_func def get_user_dir(): """Place where QL saves its state, database, config etc.""" if os.name == "nt": USERDIR = os.path.join(windows.get_appdata_dir(), "Quod Libet") elif is_osx(): USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet") else: USERDIR = os.path.join(xdg_get_config_home(), "quodlibet") if not os.path.exists(USERDIR): tmp = os.path.join(os.path.expanduser("~"), ".quodlibet") if os.path.exists(tmp): USERDIR = tmp if 'QUODLIBET_USERDIR' in os.environ: USERDIR = os.environ['QUODLIBET_USERDIR'] if build.BUILD_TYPE == u"windows-portable": USERDIR = os.path.normpath(os.path.join( os.path.dirname(path2fsn(sys.executable)), "..", "..", "config")) # XXX: users shouldn't assume the dir is there, but we currently do in # some places mkdir(USERDIR, 0o750) return USERDIR def is_release(): """Returns whether the running version is a stable release or under development. """ return const.VERSION_TUPLE[-1] != -1 def get_build_version(): """Returns a build version tuple""" version = list(const.VERSION_TUPLE) if is_release() and build.BUILD_VERSION > 0: version.append(build.BUILD_VERSION) return tuple(version) def get_build_description(): """Returns text describing the version of the build. Includes additional build info like git hash and build version. """ version = list(get_build_version()) notes = [] if not is_release(): version = version[:-1] notes.append(u"development") if build.BUILD_INFO: notes.append(build.BUILD_INFO) version_string = u".".join(map(str, version)) note = u" (%s)" % u", ".join(notes) if notes else u"" return version_string + note def init_plugins(no_plugins=False): print_d("Starting plugin manager") from quodlibet import plugins folders = [os.path.join(get_base_dir(), "ext", kind) for kind in PLUGIN_DIRS] folders.append(os.path.join(get_user_dir(), "plugins")) print_d("Scanning folders: %s" % folders) pm = plugins.init(folders, no_plugins) pm.rescan() from quodlibet.qltk.edittags import EditTags from quodlibet.qltk.renamefiles import RenameFiles from quodlibet.qltk.tagsfrompath import TagsFromPath EditTags.init_plugins() RenameFiles.init_plugins() TagsFromPath.init_plugins() return pm def set_application_info(app): """Call after init() and before creating any windows to apply default values for names and icons. """ from quodlibet._init import is_init assert is_init() from gi.repository import Gtk, GLib assert app.process_name set_process_title(app.process_name) # Issue 736 - set after main loop has started (gtk seems to reset it) GLib.idle_add(set_process_title, app.process_name) assert app.id # https://honk.sigxcpu.org/con/GTK__and_the_application_id.html GLib.set_prgname(app.id) assert app.name GLib.set_application_name(app.name) assert app.icon_name theme = Gtk.IconTheme.get_default() assert theme.has_icon(app.icon_name) Gtk.Window.set_default_icon_name(app.icon_name) def _main_setup_osx(window): from AppKit import NSObject, NSApplication import objc try: import gi gi.require_version('GtkosxApplication', '1.0') from gi.repository import GtkosxApplication except (ValueError, ImportError): print_d("importing GtkosxApplication failed, no native menus") else: osx_app = GtkosxApplication.Application() window.set_as_osx_window(osx_app) osx_app.ready() shared_app = NSApplication.sharedApplication() gtk_delegate = shared_app.delegate() # Instead of quitting when the main window gets closed just hide it. # If the dock icon gets clicked we get # applicationShouldHandleReopen_hasVisibleWindows_ and show everything. class Delegate(NSObject): @objc.signature(b'B@:#B') def applicationShouldHandleReopen_hasVisibleWindows_( self, ns_app, flag): print_d("osx: handle reopen") app.present() return True def applicationShouldTerminate_(self, sender): print_d("osx: block termination") # FIXME: figure out why idle_add is needed here from gi.repository import GLib GLib.idle_add(app.quit) return False def applicationDockMenu_(self, sender): return gtk_delegate.applicationDockMenu_(sender) def application_openFile_(self, sender, filename): return app.window.open_file(filename.encode("utf-8")) delegate = Delegate.alloc().init() delegate.retain() shared_app.setDelegate_(delegate) # QL shouldn't exit on window close, EF should if window.get_is_persistent(): window.connect( "delete-event", lambda window, event: window.hide() or True) def run(window, before_quit=None): print_d("Entering quodlibet.main") from gi.repository import Gtk, Gdk, GLib from quodlibet._init import is_init assert is_init() def quit_gtk(window): if before_quit is not None: before_quit() # disable plugins import quodlibet.plugins quodlibet.plugins.quit() # for debug: this will list active copools from quodlibet.util import copool copool.pause_all() # See which browser windows are open and save their names # so that we can restore them on start from quodlibet.qltk.browser import LibraryBrowser LibraryBrowser.save() # destroy all open windows so they hide immediately on close: # destroying all top level windows doesn't work (weird errors), # so we hide them all and only destroy our tracked instances # (browser windows, tag editors, pref window etc.) from quodlibet.qltk import Window for toplevel in Gtk.Window.list_toplevels(): toplevel.hide() for window in Window.windows: window.destroy() Gtk.main_quit() print_d("Quit GTK: done.") window.connect('destroy', quit_gtk) if sys.platform == "darwin": _main_setup_osx(window) if not window.show_maybe(): # if we don't show a window, startup isn't completed, so call manually Gdk.notify_startup_complete() from quodlibet.errorreport import faulthandling # gtk+ on osx is just too crashy if not is_osx(): try: faulthandling.enable(os.path.join(get_user_dir(), "faultdump")) except IOError: util.print_exc() else: GLib.idle_add(faulthandling.raise_and_clear_error) # set QUODLIBET_START_PERF to measure startup time until the # windows is first shown. if "QUODLIBET_START_PERF" in os.environ: window.connect("draw", Gtk.main_quit) Gtk.main() sys.exit() else: Gtk.main() print_d("Gtk.main() done.") def enable_periodic_save(save_library): import quodlibet.library from quodlibet.util import copool from quodlibet import config timeout = 5 * 60 * 1000 # 5 minutes def periodic_config_save(): while 1: config.save() yield copool.add(periodic_config_save, timeout=timeout) if not save_library: return def periodic_library_save(): while 1: # max every 15 minutes quodlibet.library.save(save_period=15 * 60) yield copool.add(periodic_library_save, timeout=timeout) def is_first_session(app_name): """Returns True if the current session is the first one to e.g. show a wizard/setup dialog etc. Will return True after each upgrade as well. app_name: e.g. 'quodlibet' """ from quodlibet import config from quodlibet import const value = config.get("memory", "%s_last_active_version" % app_name, "") if value != const.VERSION: return True return False def finish_first_session(app_name): """Call on shutdown so that is_first_session() works""" from quodlibet import config from quodlibet import const config.set("memory", "%s_last_active_version" % app_name, const.VERSION) ������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/�����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016040� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/__init__.py������������������������������������������������������0000664�0001750�0001750�00000005360�14231604332�020156� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2016-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import List, Type, Union, cast from quodlibet import util from quodlibet.util.importhelper import load_dir_modules from ._base import Browser browsers: List[Type[Browser]] = [] BrowserName = str BrowserKey = Union[int, BrowserName] """Either the index or the string key of the browser""" default = None def init() -> None: """Import all browsers from this package and from the user directory. After this is called the global `browsers` list will contain all classes sorted by priority. Can be called multiple times. """ global browsers, default # ignore double init (for the test suite) if browsers: return this_dir = util.get_module_dir() modules = load_dir_modules(this_dir, package=__package__) for browser in modules: try: browsers.extend(browser.browsers) except AttributeError: util.print_w("%r doesn't contain any browsers." % browser.__name__) def is_browser(Kind): return isinstance(Kind, type) and issubclass(Kind, Browser) browsers = list(filter(is_browser, browsers)) if not browsers: raise SystemExit("No browsers found!") browsers.sort(key=lambda Kind: Kind.priority) try: default = get("SearchBar") except ValueError: raise SystemExit("Default browser not found!") def name(browser: Browser) -> BrowserName: """Return the name of the browser""" return browser.keys[0] def get(i: BrowserKey) -> Type[Browser]: """Return a constructor for a browser, either given by number, a string of the number, or the name. Raises ValueError if the lookup fails. """ try: return browsers[int(i)] except (IndexError, ValueError, TypeError): try: return get(index(cast(str, i))) except IndexError: # ValueError will fall through raise ValueError("%r not found" % i) def index(name: BrowserName) -> int: """Return the index of a browser given its name. Raises ValueError if the lookup fails. """ name = name.lower() for j, browser in enumerate(browsers): keys = [k.lower() for k in browser.keys] if name in keys: return j all_keys = (k.lower() for b in browsers for k in b.keys) raise ValueError(f"{name!r} browser not found. " f"Try: {' | '.join(all_keys)}") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/_base.py���������������������������������������������������������0000644�0001750�0001750�00000033112�14310167056�017467� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2016-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Optional, Dict, List import random from gi.repository import Gtk, GObject, GLib, Pango from quodlibet import app, qltk from quodlibet import util from quodlibet import _ from quodlibet.pattern import XMLFromMarkupPattern from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.textedit import PatternEditBox from quodlibet.util import connect_obj, print_d from quodlibet.util.i18n import numeric_phrase from quodlibet.util.library import background_filter class Filter: active_filter = None """A callable that returns True if the passed song should be in the song list, False if not and None if no filter is active. Used for adding new songs to the song list or dynamic playlist removal when a song ends. def active_filter(self, song): ... """ def can_filter_tag(self, key): """If key can be passed to filter()""" return False def can_filter_text(self): """If filter_text() and get_filter_text() can be used""" return False def filter_text(self, text): """Set a text query""" raise NotImplementedError def get_filter_text(self): """Get the active text query""" raise NotImplementedError def can_filter_albums(self): """If filter_albums() can be used""" return False def filter_albums(self, values): """Filter based on a list of album keys""" raise NotImplementedError def list_albums(self): """Return a list of unique album keys (song.album_key)""" albums = app.library.albums albums.load() return [a.key for a in albums] def filter(self, key, values): """Actually do the filtering (with a union of values).""" # for backward compatibility if self.can_filter_text(): self.filter_text(util.build_filter_query(key, values)) def list(self, tag): """Return a list of unique values for the given tag. This needs to be here since not all browsers pull from the default library. """ library = app.library bg = background_filter() if bg: songs = filter(bg, library.values()) return list({value for song in songs for value in song.list(tag)}) return list(library.tag_values(tag)) def unfilter(self): """Reset all filters and display the whole library.""" pass def can_filter(self, key): """If key can be passed to filter_on() or filter_random()""" c = self.can_filter_text() c = c or (key == "album" and self.can_filter_albums()) return c or (key is not None and self.can_filter_tag(key)) def filter_on(self, songs, key): """Filter in the best way the browser can handle""" if key == "album" and self.can_filter_albums(): values = {s.album_key for s in songs} self.filter_albums(values) elif self.can_filter_tag(key) or self.can_filter_text(): values = set() if key.startswith("~#"): values.update([song(key, 0) for song in songs]) else: for song in songs: values.update(song.list(key)) if self.can_filter_tag(key): self.filter(key, values) else: query = util.build_filter_query(key, values) self.filter_text(query) def filter_random(self, key): """Select one random value for the given key""" if key == "album" and self.can_filter_albums(): albums = self.list_albums() if albums: self.filter_albums([random.choice(albums)]) elif self.can_filter_tag(key): values = self.list(key) if values: value = random.choice(values) self.filter(key, [value]) elif self.can_filter_text(): values = self.list(key) if values: value = random.choice(values) query = util.build_filter_query(key, [value]) self.filter_text(query) class BrowserError(Exception): pass class Browser(Gtk.Box, Filter): """Browsers are how the audio library is presented to the user; they create the list of songs that MainSongList is filled with, and pass them back via a callback function. """ __gsignals__ = { 'songs-selected': (GObject.SignalFlags.RUN_LAST, None, (object, object)), 'songs-activated': (GObject.SignalFlags.RUN_LAST, None, ()), 'uri-received': (GObject.SignalFlags.RUN_LAST, None, (str,)) } name = _("Library Browser") """The browser's name, without an accelerator.""" accelerated_name = _("Library Browser") """The name, with an accelerator.""" keys = ["Unknown"] """Keys which are used to reference the browser from the command line. The first is the primary one. """ priority = 100 """Priority in the menu list (0 is first, higher numbers come later)""" uses_main_library = True """Whether the browser has the main library as source""" def songs_selected(self, songs, is_sorted=False): """Emits the songs-selected signal. If is_sorted is True the songs will be put as is in the song list. In case it's False the songs will be sorted by the song list depending on its current sort configuration. """ self.emit("songs-selected", songs, is_sorted) def songs_activated(self): """Call after calling songs_selected() to activate the songs (start playing, enqueue etc..) """ self.emit("songs-activated") def pack(self, songpane): """For custom packing, define a function that returns a Widget with the browser and MainSongList both packed into it. """ raise NotImplementedError def unpack(self, container, songpane): """Unpack the browser and songlist when switching browsers in the main window. The container will be automatically destroyed afterwards. """ raise NotImplementedError background = True """If true, the global filter will be applied by MainSongList to the songs returned. """ headers: Optional[List[str]] = None """A list of column headers to display; None means all are okay.""" @classmethod def init(klass, library): """Called after library and MainWindow initialization, before the GTK main loop starts. """ pass def save(self): """Save the selected songlist. Browsers should save whatever they need to recreate the criteria for the current song list (not the list itself). """ raise NotImplementedError def restore(self): """Restore the selected songlist. restore is called at startup if the browser is the first loaded. """ raise NotImplementedError def finalize(self, restored): """Called after restore/activate or after the browser is loaded. restored is True if restore was called.""" pass def scroll(self, song): """Scroll to something related to the given song.""" pass def activate(self): """Do whatever is needed to emit songs-selected again.""" raise NotImplementedError can_reorder = False """If the song list should be reorderable. In case this is True every time the song list gets reordered the whole list of songs is passed to reordered(). """ def reordered(self, songs): """In case can_reorder is True and the song list gets reordered this gets called with the whole list of songs. """ raise NotImplementedError def dropped(self, songs): """Called with a list of songs when songs are dropped but the song list does not support reordering. This function should return True if the drop was successful. """ return False def key_pressed(self, event): """Gets called with a key pressed event from the song list. Should return True if the key was handled. """ return False accelerators = None """An AccelGroup that is added to / removed from the window where the browser is. """ def Menu(self, songs, library, items): """This method returns a Gtk.Menu, probably a SongsMenu. After this menu is returned the SongList may modify it further. """ return SongsMenu(library, songs, delete=True, items=items) def status_text(self, count: int, time: Optional[str] = None) -> str: tmpl = numeric_phrase("%d song", "%d songs", count) return f"{tmpl} ({time})" if time else tmpl replaygain_profiles: Optional[List[str]] = None """Replay Gain profiles for this browser.""" def __str__(self): return f"<{type(self).__name__} @ {hex(id(self))}>" class DisplayPatternMixin: """Allows Browsers customisable item (e.g. album) display patterns""" _DEFAULT_PATTERN_TEXT = "" """The default pattern to display""" _PATTERN_FN = "" """The filename to save the display pattern under""" __pattern = None __pattern_text = None @classmethod def load_pattern(cls): """Load the pattern as defined in `_PATTERN_FN`""" print_d("Loading pattern from %s" % cls._PATTERN_FN) try: with open(cls._PATTERN_FN, "r", encoding="utf-8") as f: pattern_text = f.read().rstrip() except EnvironmentError as e: print_d("Couldn't load pattern for %s (%s), using default." % (cls.__name__, e)) pattern_text = cls._DEFAULT_PATTERN_TEXT cls.__refresh_pattern(pattern_text) def update_pattern(self, pattern_text): """Saves `pattern_text` to disk (and caches)""" if pattern_text == self.__pattern_text: return self.__refresh_pattern(pattern_text) self.refresh_all() print_d(f"Saving pattern for {self} at {self._PATTERN_FN}") with open(self._PATTERN_FN, "w", encoding="utf-8") as f: f.write(pattern_text + "\n") @classmethod def __refresh_pattern(cls, pattern_text): cls.__pattern_text = pattern_text cls.__pattern = XMLFromMarkupPattern(pattern_text) @property def display_pattern(self): """The `Pattern` used for formatting entries in this browser""" return self.__pattern @property def display_pattern_text(self): """The text of the display pattern used for formatting entries in this browser""" return self.__pattern_text or self._DEFAULT_PATTERN_TEXT def refresh_all(self): """Refresh the browser's items""" pass class FakeDisplayItem(dict): """Like an `AudioFile`, but if the values aren't present in the underlying dictionary, it uses the translated tag names as values. See also `util.pattern`""" def get(self, key, default="", connector=" - "): if key[:1] == "~" and '~' in key[1:]: return connector.join(map(self.get, util.tagsplit(key))) elif key[:1] == "~" and key[-4:-3] == ":": func = key[-3:] key = key[:-4] return "%s<%s>" % (util.tag(key), func) elif key in self: return self[key] return util.tag(key) __call__ = get def comma(self, key): value = self.get(key) if isinstance(value, (int, float)): return value return value.replace("\n", ", ") class EditDisplayPatternMixin: """Provides a display Pattern in an editable frame""" _PREVIEW_ITEM: Optional[Dict[str, str]] = None """The `FakeItem` (or similar) to use to interpolate into the pattern""" _DEFAULT_PATTERN: Optional[str] = None """The display pattern to use when none is saved""" def edit_display_pane(self, browser, frame_title=None): """Returns a Pattern edit widget, with preview, optionally wrapped in a named Frame""" vbox = Gtk.VBox(spacing=6) label = Gtk.Label() label.set_alignment(0.0, 0.5) label.set_padding(6, 6) eb = Gtk.EventBox() eb.get_style_context().add_class("entry") eb.add(label) edit = PatternEditBox(self._DEFAULT_PATTERN) edit.text = browser.display_pattern_text edit.apply.connect('clicked', self._set_pattern, edit, browser) connect_obj( edit.buffer, 'changed', self._preview_pattern, edit, label) vbox.pack_start(eb, False, True, 3) vbox.pack_start(edit, True, True, 0) self._preview_pattern(edit, label) return qltk.Frame(frame_title, child=vbox) if frame_title else vbox def _set_pattern(self, button, edit, browser): browser.update_pattern(edit.text) def _preview_pattern(self, edit, label): try: text = XMLFromMarkupPattern(edit.text) % self._PREVIEW_ITEM except: text = _("Invalid pattern") edit.apply.set_sensitive(False) try: Pango.parse_markup(text, -1, u"\u0000") except GLib.GError: text = _("Invalid pattern") edit.apply.set_sensitive(False) else: edit.apply.set_sensitive(True) label.set_markup(text) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/albums/����������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017323� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/albums/__init__.py�����������������������������������������������0000664�0001750�0001750�00000000641�14035600052�021433� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import from .main import AlbumList, AlbumTagCompletion AlbumTagCompletion browsers = [AlbumList] �����������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1672734865.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/albums/main.py���������������������������������������������������0000644�0001750�0001750�00000071310�14354764221�020634� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012-2022 Nick Boultbee # 2009-2014 Christoph Reiter # 2018-2020 Uriel Zajaczkovski # 2019 Ruud van Asseldonk # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import import os from typing import Optional import cairo from gi.repository import Gtk, Pango, Gdk, GLib, Gio import quodlibet from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet import ngettext from quodlibet import qltk from quodlibet import util from quodlibet.browsers import Browser from quodlibet.browsers._base import DisplayPatternMixin from quodlibet.qltk import Icons from quodlibet.qltk.completion import EntryWordCompletion from quodlibet.qltk.cover import get_no_cover_pixbuf from quodlibet.qltk.image import add_border_widget, get_surface_for_pixbuf from quodlibet.qltk.information import Information from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import AllTreeView from quodlibet.qltk.x import MenuItem, ScrolledWindow, RadioMenuItem from quodlibet.qltk.x import SymbolicIconImage from quodlibet.query import Query from quodlibet.util import connect_obj, DeferredSignal from quodlibet.util import copool, connect_destroy, cmp from quodlibet.util.i18n import numeric_phrase from quodlibet.util.library import background_filter from .models import AlbumModel, AlbumFilterModel, AlbumSortModel, AlbumItem from .prefs import Preferences, DEFAULT_PATTERN_TEXT def get_cover_size(): return AlbumItem(None).COVER_SIZE class AlbumTagCompletion(EntryWordCompletion): def __init__(self): super().__init__() try: model = self.__model except AttributeError: model = type(self).__model = Gtk.ListStore(str) self.__refreshmodel() self.set_model(model) self.set_text_column(0) def __refreshmodel(self, *args): for tag in ["title", "album", "date", "people", "artist", "genre"]: self.__model.append(row=[tag]) for tag in ["tracks", "discs", "length", "date"]: self.__model.append(row=["#(" + tag]) for tag in ["rating", "playcount", "skipcount"]: for suffix in ["avg", "max", "min", "sum"]: self.__model.append(row=["#(%s:%s" % (tag, suffix)]) def cmpa(a, b): """Like cmp but treats values that evaluate to false as inf""" if not a and b: return 1 if not b and a: return -1 return cmp(a, b) def compare_title(a1, a2): a1, a2 = a1.album, a2.album # All albums should stay at the top if a1 is None: return -1 if a2 is None: return 1 # Move albums without a title to the bottom if not a1.title: return 1 if not a2.title: return -1 return (cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_people(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (cmpa(a1.peoplesort, a2.peoplesort) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_date(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_date_added(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (-cmp(a1("~#added"), a2("~#added")) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_original_date(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 # Take the original date if it is set, or fall back to the regular date # otherewise. a1_date = a1.get("originaldate", a1.date) a2_date = a2.get("originaldate", a2.date) return (cmpa(a1_date, a2_date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_genre(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (cmpa(a1.genre, a2.genre) or cmpa(a1.peoplesort, a2.peoplesort) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_rating(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (-cmp(a1("~#rating"), a2("~#rating")) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) def compare_avgplaycount(a1, a2): a1, a2 = a1.album, a2.album if a1 is None: return -1 if a2 is None: return 1 if not a1.title: return 1 if not a2.title: return -1 return (-cmp(a1("~#playcount:avg"), a2("~#playcount:avg")) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) class PreferencesButton(Gtk.HBox): def __init__(self, browser, model): super().__init__() sort_orders = [ (_("_Title"), self.__compare_title), (_("_People"), self.__compare_people), (_("_Date"), self.__compare_date), (_("_Date Added"), self.__compare_date_added), (_("_Original Date"), self.__compare_original_date), (_("_Genre"), self.__compare_genre), (_("_Rating"), self.__compare_rating), (_("Play_count"), self.__compare_avgplaycount), ] menu = Gtk.Menu() sort_item = Gtk.MenuItem(label=_(u"Sort _by…"), use_underline=True) sort_menu = Gtk.Menu() active = config.getint('browsers', 'album_sort', 1) item = None for i, (label, func) in enumerate(sort_orders): item = RadioMenuItem(group=item, label=label, use_underline=True) model.set_sort_func(100 + i, func) if i == active: model.set_sort_column_id(100 + i, Gtk.SortType.ASCENDING) item.set_active(True) item.connect("toggled", util.DeferredSignal(self.__sort_toggled_cb), model, i) sort_menu.append(item) sort_item.set_submenu(sort_menu) menu.append(sort_item) pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) menu.append(pref_item) connect_obj(pref_item, "activate", Preferences, browser) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) self.pack_start(button, False, False, 0) def __sort_toggled_cb(self, item, model, num): if item.get_active(): config.set("browsers", "album_sort", str(num)) model.set_sort_column_id(100 + num, Gtk.SortType.ASCENDING) def __compare_title(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_title(a1, a2) def __compare_people(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_people(a1, a2) def __compare_date(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_date(a1, a2) def __compare_date_added(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_date_added(a1, a2) def __compare_original_date(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_original_date(a1, a2) def __compare_genre(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_genre(a1, a2) def __compare_rating(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_rating(a1, a2) def __compare_avgplaycount(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_avgplaycount(a1, a2) class VisibleUpdate: # how many rows should be updated # beyond the visible area in both directions PRELOAD_COUNT = 35 def enable_row_update(self, view, sw, column): connect_obj(view, 'draw', self.__update_visibility, view) connect_destroy( sw.get_vadjustment(), "value-changed", self.__stop_update, view) self.__pending_paths = [] self.__update_deferred = DeferredSignal( self.__update_visible_rows, timeout=50, priority=GLib.PRIORITY_LOW) self.__column = column self.__first_expose = True def disable_row_update(self): if self.__update_deferred: self.__update_deferred.abort self.__update_deferred = None if self.__pending_paths: copool.remove(self.__scan_paths) self.__column = None self.__pending_paths = [] def _row_needs_update(self, model, iter_): """Should return True if the rows should be updated""" raise NotImplementedError def _update_row(self, model, iter_): """Do whatever is needed to update the row.""" raise NotImplementedError def __stop_update(self, adj, view): if self.__pending_paths: copool.remove(self.__scan_paths) self.__pending_paths = [] self.__update_visibility(view) def __update_visibility(self, view, *args): if not self.__column.get_visible(): return # update all visible rows on first expose event if self.__first_expose: self.__first_expose = False self.__update_visible_rows(view, 0) for i in self.__scan_paths(): pass self.__update_deferred(view, self.PRELOAD_COUNT) def __scan_paths(self): while self.__pending_paths: model, path = self.__pending_paths.pop() try: iter_ = model.get_iter(path) except ValueError: continue self._update_row(model, iter_) yield True def __update_visible_rows(self, view, preload): vrange = view.get_visible_range() if vrange is None: return model = view.get_model() # Generate a path list so that cover scanning starts in the middle # of the visible area and alternately moves up and down. start, end = vrange # pygtk2.12 sometimes returns empty tuples if not start or not end: return start = start.get_indices()[0] - preload - 1 end = end.get_indices()[0] + preload vlist = list(range(end, start, -1)) top = vlist[:len(vlist) // 2] bottom = vlist[len(vlist) // 2:] top.reverse() vlist_new = [] for i in vlist: if top: vlist_new.append(top.pop()) if bottom: vlist_new.append(bottom.pop()) vlist_new = filter(lambda s: s >= 0, vlist_new) vlist_new = map(Gtk.TreePath, vlist_new) visible_paths = [] for path in vlist_new: try: iter_ = model.get_iter(path) except ValueError: continue if self._row_needs_update(model, iter_): visible_paths.append((model, path)) if not self.__pending_paths and visible_paths: copool.add(self.__scan_paths) self.__pending_paths = visible_paths class AlbumList(Browser, util.InstanceTracker, VisibleUpdate, DisplayPatternMixin): __model = None __last_render = None __last_render_surface = None _PATTERN_FN = os.path.join(quodlibet.get_user_dir(), "album_pattern") _DEFAULT_PATTERN_TEXT = DEFAULT_PATTERN_TEXT name = _("Album List") accelerated_name = _("_Album List") keys = ["AlbumList"] priority = 4 def pack(self, songpane): container = qltk.ConfigRHPaned("browsers", "albumlist_pos", 0.4) container.pack1(self, True, False) container.pack2(songpane, True, False) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) @classmethod def init(klass, library): super(AlbumList, klass).load_pattern() def finalize(self, restored): if not restored: self.view.set_cursor((0,)) @classmethod def _destroy_model(klass): klass.__model.destroy() klass.__model = None @classmethod def toggle_covers(klass): on = config.getboolean("browsers", "album_covers") for albumlist in klass.instances(): albumlist.__cover_column.set_visible(on) for column in albumlist.view.get_columns(): column.queue_resize() def refresh_all(self): self.__model.refresh_all() @classmethod def _init_model(klass, library): klass.__model = AlbumModel(library) klass.__library = library @util.cached_property def _no_cover(self) -> Optional[cairo.Surface]: """Returns a cairo surface representing a missing cover""" cover_size = get_cover_size() scale_factor = self.get_scale_factor() pb = get_no_cover_pixbuf(cover_size, cover_size, scale_factor) if not pb: raise IOError("Can't find / scale missing art image") return get_surface_for_pixbuf(self, pb) def __init__(self, library): super().__init__(spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) self._register_instance() if self.__model is None: self._init_model(library) self._cover_cancel = Gio.Cancellable() sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.set_headers_visible(False) model_sort = AlbumSortModel(model=self.__model) model_filter = AlbumFilterModel(child_model=model_sort) self.__bg_filter = background_filter() self.__filter = None model_filter.set_visible_func(self.__parse_query) render = Gtk.CellRendererPixbuf() self.__cover_column = column = Gtk.TreeViewColumn("covers", render) column.set_visible(config.getboolean("browsers", "album_covers")) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(get_cover_size() + 12) render.set_property('height', get_cover_size() + 8) render.set_property('width', get_cover_size() + 8) def cell_data_pb(column, cell, model, iter_, no_cover): item = model.get_value(iter_) if item.album is None: surface = None elif item.cover: pixbuf = item.cover pixbuf = add_border_widget(pixbuf, self.view) surface = get_surface_for_pixbuf(self, pixbuf) or no_cover # don't cache, too much state has an effect on the result self.__last_render_surface = None else: surface = no_cover if self.__last_render_surface == surface: return self.__last_render_surface = surface cell.set_property("surface", surface) column.set_cell_data_func(render, cell_data_pb, self._no_cover) view.append_column(column) render = Gtk.CellRendererText() column = Gtk.TreeViewColumn("albums", render) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) if view.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) def cell_data(column, cell, model, iter_, data): album = model.get_album(iter_) if album is None: text = util.bold(_("All Albums")) + "\n" text += numeric_phrase("%d album", "%d albums", len(model) - 1) markup = text else: markup = self.display_pattern % album if self.__last_render == markup: return self.__last_render = markup cell.markup = markup cell.set_property('markup', markup) column.set_cell_data_func(render, cell_data) view.append_column(column) view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) view.set_rules_hint(True) view.set_search_equal_func(self.__search_func, None) view.set_search_column(0) view.set_model(model_filter) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) view.connect('row-activated', self.__play_selection) self.__sig = view.connect('selection-changed', util.DeferredSignal(self.__update_songs, owner=view)) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) view.connect("drag-data-get", self.__drag_data_get) connect_obj(view, 'popup-menu', self.__popup, view, library) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) search.connect('query-changed', self.__update_filter) connect_obj(search, 'focus-out', lambda w: w.grab_focus(), view) self.__search = search prefs = PreferencesButton(self, model_sort) search.pack_start(prefs, False, True, 0) hb = Gtk.Box(spacing=3) hb.pack_start(search, True, True, 6) self.pack_start(hb, False, True, 0) self.pack_start(sw, True, True, 0) self.connect("destroy", self.__destroy) self.enable_row_update(view, sw, self.__cover_column) self.connect('key-press-event', self.__key_pressed, library.librarian) if app.cover_manager: connect_destroy( app.cover_manager, "cover-changed", self._cover_changed) self.show_all() def _cover_changed(self, manager, songs): model = self.__model songs = set(songs) for iter_, item in model.iterrows(): album = item.album if album is not None and songs & album.songs: item.scanned = False model.row_changed(model.get_path(iter_), iter_) def __key_pressed(self, widget, event, librarian): if qltk.is_accel(event, "<Primary>I"): songs = self.__get_selected_songs() if songs: window = Information(librarian, songs, self) window.show() return True elif qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): qltk.enqueue(self.__get_selected_songs(sort=True)) return True elif qltk.is_accel(event, "<alt>Return"): songs = self.__get_selected_songs() if songs: window = SongProperties(librarian, songs, self) window.show() return True return False def _row_needs_update(self, model, iter_): item = model.get_value(iter_) return item.album is not None and not item.scanned def _update_row(self, filter_model, iter_): sort_model = filter_model.get_model() model = sort_model.get_model() iter_ = filter_model.convert_iter_to_child_iter(iter_) iter_ = sort_model.convert_iter_to_child_iter(iter_) tref = Gtk.TreeRowReference.new(model, model.get_path(iter_)) def callback(): path = tref.get_path() if path is not None: model.row_changed(path, model.get_iter(path)) item = model.get_value(iter_) scale_factor = self.get_scale_factor() item.scan_cover(scale_factor=scale_factor, callback=callback, cancel=self._cover_cancel) def __destroy(self, browser): self._cover_cancel.cancel() self.disable_row_update() self.view.set_model(None) klass = type(browser) if not klass.instances(): klass._destroy_model() def __update_filter(self, entry, text, scroll_up=True, restore=False): model = self.view.get_model() self.__filter = None query = self.__search.get_query(star=["~people", "album"]) if not query.matches_all: self.__filter = query.search self.__bg_filter = background_filter() self.__inhibit() # We could be smart and try to scroll to a selected album # but that introduces lots of wild scrolling. Feel free to change it. # Without scrolling the TV tries to stay at the same position # (40% down) which makes no sense, so always go to the top. if scroll_up: self.view.scroll_to_point(0, 0) # Don't filter on restore if there is nothing to filter if not restore or self.__filter or self.__bg_filter: model.refilter() self.__uninhibit() def __parse_query(self, model, iter_, data): f, b = self.__filter, self.__bg_filter if f is None and b is None: return True else: album = model.get_album(iter_) if album is None: return True elif b is None: return f(album) elif f is None: return b(album) else: return b(album) and f(album) def __search_func(self, model, column, key, iter_, data): album = model.get_album(iter_) if album is None: return True key = key.lower() title = album.title.lower() if key in title: return False if config.getboolean("browsers", "album_substrings"): people = (p.lower() for p in album.list("~people")) for person in people: if key in person: return False return True def __popup(self, view, library): albums = self.__get_selected_albums() songs = self.__get_songs_from_albums(albums) items = [] if self.__cover_column.get_visible(): num = len(albums) button = MenuItem( ngettext("Reload album _cover", "Reload album _covers", num), Icons.VIEW_REFRESH) button.connect('activate', self.__refresh_album, view) items.append(button) menu = SongsMenu(library, songs, items=[items]) menu.show_all() return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __refresh_album(self, menuitem, view): items = self.__get_selected_items() for item in items: item.scanned = False model = self.view.get_model() for iter_, item in model.iterrows(): if item in items: model.row_changed(model.get_path(iter_), iter_) def __get_selected_items(self): selection = self.view.get_selection() model, paths = selection.get_selected_rows() return model.get_items(paths) def __get_selected_albums(self): selection = self.view.get_selection() model, paths = selection.get_selected_rows() return model.get_albums(paths) def __get_songs_from_albums(self, albums, sort=True): # Sort first by how the albums appear in the model itself, # then within the album using the default order. songs = [] if sort: for album in albums: songs.extend(sorted(album.songs, key=lambda s: s.sort_key)) else: for album in albums: songs.extend(album.songs) return songs def __get_selected_songs(self, sort=True): albums = self.__get_selected_albums() return self.__get_songs_from_albums(albums, sort) def __drag_data_get(self, view, ctx, sel, tid, etime): songs = self.__get_selected_songs() if tid == 1: qltk.selection_set_songs(sel, songs) else: sel.set_uris([song("~uri") for song in songs]) def __play_selection(self, view, indices, col): self.songs_activated() def active_filter(self, song): for album in self.__get_selected_albums(): if song in album.songs: return True return False def can_filter_text(self): return True def filter_text(self, text): self.__search.set_text(text) if Query(text).is_parsable: self.__update_filter(self.__search, text) self.__inhibit() self.view.set_cursor((0,)) self.__uninhibit() self.activate() def get_filter_text(self): return self.__search.get_text() def can_filter(self, key): # Numerics are different for collections, and although title works, # it's not of much use here. if key is not None and (key.startswith("~#") or key == "title"): return False return super().can_filter(key) def can_filter_albums(self): return True def list_albums(self): model = self.view.get_model() return [row[0].album.key for row in model if row[0].album] def filter_albums(self, values): view = self.view self.__inhibit() changed = view.select_by_func( lambda r: r[0].album and r[0].album.key in values) self.view.grab_focus() self.__uninhibit() if changed: self.activate() def unfilter(self): self.filter_text("") self.view.set_cursor((0,)) def activate(self): self.view.get_selection().emit('changed') def __inhibit(self): self.view.handler_block(self.__sig) def __uninhibit(self): self.view.handler_unblock(self.__sig) def restore(self): text = config.gettext("browsers", "query_text") entry = self.__search entry.set_text(text) # update_filter expects a parsable query if Query(text).is_parsable: self.__update_filter(entry, text, scroll_up=False, restore=True) keys = config.gettext("browsers", "albums").split("\n") # FIXME: If albums is "" then it could be either all albums or # no albums. If it's "" and some other stuff, assume no albums, # otherwise all albums. self.__inhibit() if keys == [""]: self.view.set_cursor((0,)) else: def select_fun(row): album = row[0].album if not album: # all return False return album.str_key in keys self.view.select_by_func(select_fun) self.__uninhibit() def scroll(self, song): album_key = song.album_key select = lambda r: r[0].album and r[0].album.key == album_key self.view.select_by_func(select, one=True) def __get_config_string(self): selection = self.view.get_selection() model, paths = selection.get_selected_rows() # All is selected if model.contains_all(paths): return "" # All selected albums albums = model.get_albums(paths) confval = "\n".join((a.str_key for a in albums)) # ConfigParser strips a trailing \n - so we move it to the front if confval and confval[-1] == "\n": confval = "\n" + confval[:-1] return confval def save(self): conf = self.__get_config_string() config.settext("browsers", "albums", conf) text = self.__search.get_text() config.settext("browsers", "query_text", text) def __update_songs(self, view, selection): songs = self.__get_selected_songs(sort=False) self.songs_selected(songs) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/albums/models.py�������������������������������������������������0000664�0001750�0001750�00000010060�14035600052�021153� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet import config from quodlibet.qltk.models import ObjectStore, ObjectModelFilter from quodlibet.qltk.models import ObjectModelSort class AlbumItem: cover = None scanned = False def __init__(self, album): self.album = album @property def COVER_SIZE(self): size = config.getint("browsers", "cover_size") if size <= 0: size = 48 return size def scan_cover(self, force=False, scale_factor=1, callback=None, cancel=None): if (self.scanned and not force) or not self.album or \ not self.album.songs: return self.scanned = True def set_cover_cb(pixbuf): self.cover = pixbuf callback() s = self.COVER_SIZE * scale_factor app.cover_manager.get_pixbuf_many_async( self.album.songs, s, s, cancel, set_cover_cb) def __repr__(self): return repr(self.album) class AlbumModelMixin: def get_items(self, paths): items = [] for path in paths: item = self.get_value(self.get_iter(path)) if item.album is None: return [i for i in self.itervalues() if i.album is not None] items.append(item) return items def get_albums(self, paths): return [i.album for i in self.get_items(paths)] def get_album(self, iter_): return self.get_value(iter_, 0).album class AlbumModel(ObjectStore, AlbumModelMixin): def __init__(self, library): super().__init__() self.__library = library albums = library.albums self.__sigs = [ albums.connect("added", self._add_albums), albums.connect("removed", self._remove_albums), albums.connect("changed", self._change_albums) ] self.append(row=[AlbumItem(None)]) self.append_many((AlbumItem(a) for a in albums.values())) def refresh_all(self): """Trigger redraws for all rows""" for iter_, value in self.iterrows(): self.row_changed(self.get_path(iter_), iter_) def destroy(self): library = self.__library for sig in self.__sigs: library.albums.disconnect(sig) self.__library = None self.clear() def _update_all(self): if not self.is_empty(): row = self[0] self.row_changed(row.path, row.iter) def _add_albums(self, library, added): self.append_many((AlbumItem(a) for a in added)) self._update_all() def _remove_albums(self, library, removed): removed_albums = removed.copy() iters_remove = [] for iter_, item in self.iterrows(): album = item.album if album is not None and album in removed_albums: removed_albums.remove(album) iters_remove.append(iter_) if not removed_albums: break for iter_ in iters_remove: self.remove(iter_) self._update_all() def _change_albums(self, library, changed): """Trigger a row redraw for each album that changed""" changed_albums = changed.copy() for iter_, item in self.iterrows(): album = item.album if album is not None and album in changed_albums: changed_albums.remove(album) self.row_changed(self.get_path(iter_), iter_) if not changed_albums: break class AlbumFilterModel(ObjectModelFilter, AlbumModelMixin): def contains_all(self, paths): values = (self.get_value(self.get_iter(p), 0).album for p in paths) return None in values class AlbumSortModel(ObjectModelSort, AlbumModelMixin): pass ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1659385493.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/albums/prefs.py��������������������������������������������������0000644�0001750�0001750�00000006605�14272033225�021024� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012,2013,2016 Nick Boultbee # 2009-2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.browsers._base import FakeDisplayItem, EditDisplayPatternMixin from quodlibet.formats import PEOPLE from quodlibet.qltk import Button, Icons from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.util import format_rating from quodlibet.util.i18n import numeric_phrase PEOPLE _SOME_PEOPLE = "\n".join([util.tag("artist"), util.tag("performer"), util.tag("composer"), util.tag("arranger"), ]) _EMPTY = _("Songs not in an album") DEFAULT_PATTERN_TEXT = """[b]<album|<album>|%s>[/b]<date| (<date>)> [small]<~discs|<~discs> - ><~tracks> - <~long-length>[/small] <~people>""" % _EMPTY class Preferences(qltk.UniqueWindow, EditDisplayPatternMixin): _DEFAULT_PATTERN = DEFAULT_PATTERN_TEXT _PREVIEW_ITEM = FakeDisplayItem({ "date": "2010-10-31", "~length": util.format_time_display(6319), "~long-length": util.format_time_long(6319), "~tracks": numeric_phrase("%d track", "%d tracks", 5), "~discs": numeric_phrase("%d disc", "%d discs", 2), "~#rating": 0.75, "album": _("An Example Album"), "~people": _SOME_PEOPLE + "..."}) def __init__(self, browser): if self.is_not_unique(): return super().__init__() self.set_border_width(12) self.set_title(_("Album List Preferences")) self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._PREVIEW_ITEM["~rating"] = format_rating(0.75) box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _covers"), "browsers", "album_covers") cb.set_active(config.getboolean("browsers", "album_covers")) cb.connect('toggled', lambda s: browser.toggle_covers()) vbox.pack_start(cb, False, True, 0) cb = ConfigCheckButton( _("Inline _search includes people"), "browsers", "album_substrings") cb.set_active(config.getboolean("browsers", "album_substrings")) vbox.pack_start(cb, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) display_frame = self.edit_display_pane(browser, _("Album Display")) box.pack_start(display_frame, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all() ���������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/collection/������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020173� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/collection/__init__.py�������������������������������������������0000664�0001750�0001750�00000000555�14035600052�022307� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .main import CollectionBrowser browsers = [CollectionBrowser] ���������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1659427951.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/collection/main.py�����������������������������������������������0000644�0001750�0001750�00000034036�14272156157�021512� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-2014 Christoph Reiter # 2017 Uriel Zajaczkovski # 2017-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib, Pango, Gdk from quodlibet import qltk from quodlibet import util from quodlibet import config from quodlibet import _ from quodlibet.browsers.albums import AlbumTagCompletion from quodlibet.browsers import Browser from quodlibet.query import Query from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import AllTreeView from quodlibet.qltk import Icons from quodlibet.qltk.image import add_border_widget, get_surface_for_pixbuf from quodlibet.qltk.x import ScrolledWindow, Align, SymbolicIconImage from quodlibet.util import connect_obj, cmp from quodlibet.util.library import background_filter from .models import (CollectionTreeStore, CollectionSortModel, CollectionFilterModel, AlbumNode, _ORDERING) from .prefs import get_headers, Preferences class CollectionView(AllTreeView): def __init__(self): super().__init__() self.connect_after("row-expanded", self.__expand_helper) def __expand_helper(self, view, iter, path): model = view.get_model() children = list(model[path].iterchildren()) if len(children) == 1: view.expand_row(children[0].path, False) def select_album(self, album, unselect=True): model = self.get_model() path = model.get_path_for_album(album) if path is not None: self.select_path(path, unselect) def select_path(self, path, unselect=True): path_idx = path if isinstance(path_idx, Gtk.TreePath): path_idx = path_idx.get_indices() for i, x in enumerate(path_idx[:-1]): self.expand_row(Gtk.TreePath(tuple(path_idx[:i + 1])), False) self.scroll_to_cell(path, use_align=True, row_align=0.5) selection = self.get_selection() assert selection if unselect: selection.unselect_all() self.set_cursor(path) else: selection.select_path(path) def get_selected_albums(self): selection = self.get_selection() assert selection model, paths = selection.get_selected_rows() albums = set() for path in paths: albums.update(model.get_albums_for_path(path)) return albums class CollectionBrowser(Browser, util.InstanceTracker): name = _("Album Collection") accelerated_name = _("Album _Collection") keys = ["AlbumCollection", "CollectionBrowser"] priority = 6 __model = None def pack(self, songpane): container = qltk.ConfigRHPaned( "browsers", "collectionbrowser_pos", 0.4) container.pack1(self, True, False) container.pack2(songpane, True, False) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) @classmethod def _init_model(klass, library): klass.__model = model = CollectionTreeStore() klass.__albums = albums = library.albums albums.load() klass.__sigs = [ albums.connect("added", klass._add_albums, model), albums.connect("removed", klass._remove_albums, model), albums.connect("changed", klass._change_albums, model), ] klass.set_hierarchy() @classmethod def _destroy_model(klass): for sig in klass.__sigs: klass.__albums.disconnect(sig) klass.__model = None del klass.__sigs def _refilter(self): if hasattr(self, "view"): self.view.get_model().refilter() @classmethod def set_hierarchy(klass): klass.__model.set_albums(get_headers(), klass.__albums.values()) for inst in klass.instances(): inst._refilter() @classmethod def _add_albums(klass, library, added, model): model.add_albums(added) @classmethod def _remove_albums(klass, library, removed, model): model.remove_albums(removed) @classmethod def _change_albums(klass, library, changed, model): model.change_albums(changed) def __init__(self, library): super().__init__(spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) self._register_instance() if self.__model is None: self._init_model(library) sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) self.view = view = CollectionView() view.set_headers_visible(False) model_sort = CollectionSortModel(model=self.__model) model_filter = CollectionFilterModel(child_model=model_sort) self.__filter = None self.__bg_filter = background_filter() model_filter.set_visible_func(self.__parse_query) view.set_model(model_filter) def cmpa(a, b): """Like cmp but treats values that evaluate to false as inf""" if not a and b: return 1 if not b and a: return -1 return cmp(a, b) def cmp_rows(model, i1, i2, data): t1, t2 = model[i1][0], model[i2][0] pos1 = _ORDERING.get(t1, 0) pos2 = _ORDERING.get(t2, 0) if pos1 or pos2: return cmp(pos1, pos2) if not isinstance(t1, AlbumNode): return cmp(util.human_sort_key(t1), util.human_sort_key(t2)) a1, a2 = t1.album, t2.album return (cmpa(a1.peoplesort, a2.peoplesort) or cmpa(a1.date, a2.date) or cmpa(a1.sort, a2.sort) or cmp(a1.key, a2.key)) model_sort.set_sort_func(0, cmp_rows) model_sort.set_sort_column_id(0, Gtk.SortType.ASCENDING) column = Gtk.TreeViewColumn("albums") def cell_data(column, cell, model, iter_, data): markup = model.get_markup(self.__model.tags, iter_) cell.markup = markup cell.set_property('markup', markup) def get_scaled_cover(item): if item.scanned: return item.cover scale_factor = self.get_scale_factor() item.scan_cover(scale_factor=scale_factor) return item.cover def cell_data_pb(column, cell, model, iter_, data): album = model.get_album(iter_) if album is None: cell.set_property('icon-name', Icons.FOLDER) else: item = model.get_value(iter_) cover = get_scaled_cover(item) if cover: cover = add_border_widget(cover, view) surface = get_surface_for_pixbuf(self, cover) cell.set_property("surface", surface) else: cell.set_property('icon-name', Icons.MEDIA_OPTICAL) imgrender = Gtk.CellRendererPixbuf() render = Gtk.CellRendererText() if view.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(imgrender, False) column.pack_start(render, True) column.set_cell_data_func(render, cell_data) column.set_cell_data_func(imgrender, cell_data_pb) view.append_column(column) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) hbox = Gtk.HBox(spacing=6) prefs = Gtk.Button() prefs.add(SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU)) prefs.connect('clicked', lambda *x: Preferences(self)) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) search.connect('query-changed', self.__update_filter) connect_obj(search, 'focus-out', lambda w: w.grab_focus(), view) self.__search = search hbox.pack_start(search, True, True, 0) hbox.pack_start(prefs, False, True, 0) self.pack_start(Align(hbox, left=6, top=0), False, True, 0) self.pack_start(sw, True, True, 0) view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.__sig = view.get_selection().connect('changed', self.__selection_changed) view.connect('row-activated', self.__play) connect_obj(view, 'popup-menu', self.__popup, view, library) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) view.connect("drag-data-get", self.__drag_data_get) self.connect("destroy", self.__destroy) self.connect('key-press-event', self.__key_pressed, library.librarian) self.show_all() def __inhibit(self): self.view.get_selection().handler_block(self.__sig) def __uninhibit(self): self.view.get_selection().handler_unblock(self.__sig) def __parse_query(self, model, iter_, data): f, b = self.__filter, self.__bg_filter if f is None and b is None: return True def check_album(obj): if b is None: return f(obj) if f is None: return b(obj) return f(obj) and b(obj) obj = model.get_value(iter_) if isinstance(obj, AlbumNode): return check_album(obj.album) else: for album in model.iter_albums(iter_): if check_album(album): return True return False def __update_filter(self, entry, text): self.__filter = None star = self.__model.tags + ["album"] query = self.__search.get_query(star) if not query.matches_all: self.__filter = query.search self.__bg_filter = background_filter() self.view.get_model().refilter() def __destroy(self, browser): klass = type(browser) if not klass.instances(): klass._destroy_model() def __drag_data_get(self, view, ctx, sel, tid, etime): songs = self.__get_selected_songs() if tid == 1: qltk.selection_set_songs(sel, songs) else: sel.set_uris([song("~uri") for song in songs]) def __popup(self, view, library): songs = self.__get_selected_songs(view.get_selection()) menu = SongsMenu(library, songs) menu.show_all() return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __play(self, view, path, col): model = view.get_model() if isinstance(model[path][0], AlbumNode): self.songs_activated() else: if view.row_expanded(path): view.collapse_row(path) else: view.expand_row(path, False) def __get_selected_songs(self, sort=True): albums = self.view.get_selected_albums() songs = [] if sort: for album in albums: songs.extend(sorted(album.songs)) else: for album in albums: songs.extend(album.songs) return songs def __selection_changed(self, selection): songs = self.__get_selected_songs(False) if songs is not None: GLib.idle_add(self.songs_selected, songs) def __key_pressed(self, widget, event, librarian): if qltk.is_accel(event, "<Primary>I"): songs = self.__get_selected_songs() if songs: window = Information(librarian, songs, self) window.show() return True elif qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): qltk.enqueue(self.__get_selected_songs(sort=True)) return True elif qltk.is_accel(event, "<alt>Return"): songs = self.__get_selected_songs() if songs: window = SongProperties(librarian, songs, self) window.show() return True return False def can_filter_albums(self): return True def filter_albums(self, album_keys): albums = [a for a in [self.__albums.get(k) for k in album_keys] if a is not None] if albums: self.view.select_album(albums[0], unselect=True) self.view.grab_focus() for album in albums[1:]: self.view.select_album(album, unselect=False) def can_filter_text(self): return True def filter_text(self, text): self.__search.set_text(text) if Query(text).is_parsable: self.__update_filter(self.__search, text) self.activate() def get_filter_text(self): return self.__search.get_text() def unfilter(self): self.filter_text("") def activate(self): self.view.get_selection().emit('changed') def restore(self): paths = config.get("browsers", "collection", "").split("\t") paths = [tuple(map(int, path.split())) for path in paths] self.__inhibit() if paths: if not paths[0]: self.__uninhibit() return self.view.select_path(paths[0], unselect=True) for path in paths[1:]: self.view.select_path(path, unselect=False) self.__uninhibit() def scroll(self, song): album = self.__albums.get(song.album_key) if album: self.view.select_album(album) def save(self): model, paths = self.view.get_selection().get_selected_rows() paths = "\t".join([" ".join(map(str, path)) for path in paths]) config.set("browsers", "collection", paths) browsers = [CollectionBrowser] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/collection/models.py���������������������������������������������0000644�0001750�0001750�00000020546�14327505043�022043� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-2014 Christoph Reiter # 2020-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import util from quodlibet import config from quodlibet import _ from quodlibet.pattern import XMLFromPattern from quodlibet.qltk.models import ObjectTreeStore, ObjectModelFilter from quodlibet.qltk.models import ObjectModelSort EMPTY = _("Songs not in an album") ALBUM_PATTERN = r""" \<b\><album|<album>|%s>\</b\><date| \<small\>(<date>)\</small\>> \<small\><~discs|<~discs> - ><~tracks> - <~long-length>\</small\>""" % EMPTY ALBUM_PATTERN = ALBUM_PATTERN.lstrip() PAT = XMLFromPattern(ALBUM_PATTERN) UNKNOWN_PATTERN = util.bold_italic(_("Unknown %s")) MULTI_PATTERN = util.bold_italic(_("Multiple %s Values")) COUNT_PATTERN = " <span size='small' color='#777'>(%s)</span>" class AlbumNode: def __init__(self, album): self.album = album self.scanned = False @property def COVER_SIZE(self): size = config.getint("browsers", "cover_size") if size <= 0: size = 48 return size def scan_cover(self, scale_factor=1): if self.scanned or not self.album.songs: return self.scanned = True from quodlibet import app s = self.COVER_SIZE * scale_factor * 0.5 self.cover = app.cover_manager.get_pixbuf_many(self.album.songs, s, s) UnknownNode = object() MultiNode = object() _ORDERING = {t: (x + 1) for x, t in enumerate([MultiNode, UnknownNode, None])} """The ordering score by instance of singleton / "special" values".""" def build_tree(tags, albums, cache=None): if not tags: return list(albums) tag, merge = tags[0] tree = {} cache = cache or {} for album in albums: cache_key = (album, tag) if cache_key not in cache: cache[cache_key] = album.list(tag) values = cache[cache_key] if merge and len(values) > 1: values = [MultiNode] for value in values or [UnknownNode]: tree.setdefault(value, []).append(album) for key, value in tree.items(): tree[key] = build_tree(tags[1:], value, cache) return tree class CollectionModelMixin: def get_path_for_album(self, album): """Returns the path for an album or None""" def func(model, path, iter_, result): item = model.get_value(iter_) if getattr(item, "album", None) is album: # pygobject bug: treepath only valid in callback, # so make a copy result[0] = path.copy() return True return False res = [None] self.foreach(func, res) return res[0] def get_albums_for_path(self, path): return self.get_albums_for_iter(self.get_iter(path)) def get_albums_for_iter(self, iter_): obj = self.get_value(iter_) if isinstance(obj, AlbumNode): return {obj.album} albums = set() for child_iter, value in self.iterrows(iter_): if isinstance(value, AlbumNode): albums.add(value.album) else: albums.update(self.get_albums_for_iter(child_iter)) return albums def iter_albums(self, iter_): """Yields all albums below iter_""" for child_iter, value in self.iterrows(iter_): if isinstance(value, AlbumNode): yield value.album else: for album in self.iter_albums(child_iter): yield album def get_markup(self, tags, iter_): obj = self.get_value(iter_, 0) if isinstance(obj, AlbumNode): return PAT % obj.album if isinstance(obj, str): markup = util.escape(obj) else: tag = util.tag(tags[len(self.get_path(iter_).get_indices()) - 1]) if obj is UnknownNode: markup = UNKNOWN_PATTERN % util.escape(tag) else: markup = MULTI_PATTERN % util.escape(tag) num = len(self.get_albums_for_iter(iter_)) return markup + COUNT_PATTERN % num def get_album(self, iter_): obj = self.get_value(iter_, 0) if isinstance(obj, AlbumNode): return obj.album class CollectionFilterModel(ObjectModelFilter, CollectionModelMixin): pass class CollectionSortModel(ObjectModelSort, CollectionModelMixin): pass class CollectionTreeStore(ObjectTreeStore, CollectionModelMixin): def __init__(self): super().__init__(object) self.__tags = [] def set_albums(self, tags, albums): self.clear() self.__tags = tags self.add_albums(albums) @property def tags(self): return [t[0] for t in self.__tags] def add_albums(self, albums): def _add(tree, iter_=None): # lowest level, add albums if isinstance(tree, list): for album in tree: self.append(parent=iter_, row=[AlbumNode(album)]) return # move into existing nodes and remove them from tree child = self.iter_children(iter_) while child: obj = self[child][0] if obj in tree: _add(tree[obj], child) del tree[obj] child = self.iter_next(child) # add missing ones for key, value in tree.items(): _add(value, self.append(parent=iter_, row=[key])) _add(build_tree(self.__tags, albums)) def remove_albums(self, albums): # We can't get anything from the albums (they have no songs), # so we have to look through everything. def _remove_albums(albums, iter_=None): child = self.iter_children(iter_) while child: _remove_albums(albums, child) obj = self[child][0] if isinstance(obj, AlbumNode): # remove albums if obj.album in albums: if not self.remove(child): child = None continue else: child = self.iter_next(child) else: # clean up empty containers if not self.iter_has_child(child): if not self.remove(child): child = None continue else: child = self.iter_next(child) _remove_albums(set(albums)) def change_albums(self, albums): def _check_albums(tree, iter_=None, not_found=None): if not_found is None: not_found = set() if isinstance(tree, list): # save nodes that are not there anymore child = self.iter_children(iter_) while child: row = self[child] try: tree.remove(row[0].album) except ValueError: pass else: # it's still in the same position, trigger a redraw self.row_changed(row.path, row.iter) child = self.iter_next(child) not_found.update(tree) return not_found child = self.iter_children(iter_) while child: obj = self[child][0] if obj in tree: _check_albums(tree[obj], child, not_found) del tree[obj] child = self.iter_next(child) # everything left over changed def _get_all(sub, found=None): if found is None: found = set() if isinstance(sub, list): found.update(sub) return found for v in sub.values(): _get_all(v, found) return found not_found.update(_get_all(tree)) return not_found not_found = _check_albums(build_tree(self.__tags, albums)) self.remove_albums(not_found) self.add_albums(not_found) ����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/collection/prefs.py����������������������������������������������0000644�0001750�0001750�00000015326�14267565021�021704� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config from quodlibet import util from quodlibet import qltk from quodlibet import _ from quodlibet.qltk.tagscombobox import TagsComboBoxEntry from quodlibet.qltk.views import BaseView from quodlibet.qltk import Button, Icons from quodlibet.util import connect_obj def get_headers(): result = [] headers = config.get("browsers", "collection_headers") for h in headers.splitlines(): values = h.split() if len(values) != 2: continue tag, merge = values try: result.append((tag, bool(int(merge)))) except ValueError: continue return result def save_headers(headers): headers = "\n".join(["%s %d" % (t, m) for (t, m) in headers]) config.set("browsers", "collection_headers", headers) class PatternEditor(Gtk.HBox): PRESETS = [ [("~people", False)], [("~year", False)], [("genre", False)], [("genre", False), ("artist", False)], ] COMPLETION = ["genre", "grouping", "~people", "artist", "album", "~year"] def __init__(self): super().__init__(spacing=12) self.__headers = headers = {} buttons = [] group = None for tags in self.PRESETS: tied = "~" + "~".join([t[0] for t in tags]) group = Gtk.RadioButton(group=group, label="_" + util.tag(tied), use_underline=True) headers[group] = tags buttons.append(group) group = Gtk.RadioButton(group=group, label=_("_Custom"), use_underline=True) self.__custom = group headers[group] = [] buttons.append(group) button_box = Gtk.HBox(spacing=6) self.__model = model = Gtk.ListStore(str, bool) radio_box = Gtk.VBox(spacing=6) for button in buttons: radio_box.pack_start(button, False, True, 0) button.connect('toggled', self.__toggled, button_box, model) self.pack_start(radio_box, False, True, 0) cb = TagsComboBoxEntry(self.COMPLETION) view = BaseView(model=model) view.set_reorderable(True) view.set_headers_visible(True) ctrl_box = Gtk.VBox(spacing=6) add = Button(_("_Add"), Icons.LIST_ADD) ctrl_box.pack_start(add, False, True, 0) add.connect('clicked', self.__add, model, cb) remove = Button(_("_Remove"), Icons.LIST_REMOVE) ctrl_box.pack_start(remove, False, True, 0) remove.connect('clicked', self.__remove, view) selection = view.get_selection() selection.connect('changed', self.__selection_changed, remove) selection.emit('changed') sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) edit_box = Gtk.VBox(spacing=6) edit_box.pack_start(cb, False, True, 0) edit_box.pack_start(sw, True, True, 0) button_box.pack_start(edit_box, True, True, 0) button_box.pack_start(ctrl_box, False, True, 0) self.pack_start(button_box, True, True, 0) render = Gtk.CellRendererText() render.set_property("editable", True) def edited_cb(render, path, text, model): model[path][0] = text render.connect("edited", edited_cb, model) column = Gtk.TreeViewColumn(_("Tag"), render, text=0) column.set_expand(True) view.append_column(column) toggle = Gtk.CellRendererToggle() toggle.connect("toggled", self.__toggeled, model) toggle_column = Gtk.TreeViewColumn(_("Merge"), toggle, active=1) view.append_column(toggle_column) def __toggeled(self, render, path, model): model[path][1] = not model[path][1] @property def headers(self): for button in self.__headers.keys(): if button.get_active(): if button == self.__custom: model_headers = [(row[0], row[1]) for row in self.__model] self.__headers[self.__custom] = model_headers return self.__headers[button] @headers.setter def headers(self, new_headers): for button, headers in self.__headers.items(): if headers == new_headers: button.set_active(True) button.emit("toggled") break else: self.__headers[self.__custom] = new_headers self.__custom.set_active(True) def __selection_changed(self, selection, remove): remove.set_sensitive(bool(selection.get_selected()[1])) def __add(self, button, model, cb): if cb.tag: model.append(row=[cb.tag, False]) def __remove(self, button, view): view.remove_selection() def __toggled(self, button, edit_widget, model): tags = self.__headers[button] if tags: model.clear() for tag, merge in tags: model.append(row=[tag, merge]) edit_widget.set_sensitive( button.get_active() and button is self.__custom) class Preferences(qltk.UniqueWindow): def __init__(self, browser): if self.is_not_unique(): return super().__init__() self._browser = browser self.set_transient_for(qltk.get_top_parent(browser)) self.set_default_size(350, 225) self.set_border_width(12) self.set_title(_("Album Collection Preferences")) vbox = Gtk.VBox(spacing=12) editor = PatternEditor() editor.headers = get_headers() apply = Button(_("_Apply")) connect_obj(apply, "clicked", self.__apply, editor, False) cancel = Button(_("_Cancel")) cancel.connect("clicked", lambda x: self.destroy()) box = Gtk.HButtonBox() box.set_spacing(6) box.set_layout(Gtk.ButtonBoxStyle.END) box.pack_start(apply, True, True, 0) self.use_header_bar() if not self.has_close_button(): box.pack_start(cancel, True, True, 0) vbox.pack_start(editor, True, True, 0) vbox.pack_start(box, False, True, 0) self.add(vbox) apply.grab_focus() self.show_all() def __apply(self, editor, close): if editor.headers != get_headers(): save_headers(editor.headers) self._browser.set_hierarchy() if close: self.destroy() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/�������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020024� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/__init__.py��������������������������������������������0000644�0001750�0001750�00000000562�14324322342�022140� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from .main import CoverGrid browsers = [CoverGrid] ����������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1665307309.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/main.py������������������������������������������������0000644�0001750�0001750�00000044673�14320511255�021337� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012-2022 Nick Boultbee # 2009-2014 Christoph Reiter # 2022 Thomas Leberbauer # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import import os from gi.repository import GLib, Gtk, Gdk, Gio from .prefs import Preferences, DEFAULT_PATTERN_TEXT import quodlibet from quodlibet import app from quodlibet import ngettext from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.browsers import Browser from quodlibet.browsers.albums.main import ( AlbumTagCompletion, PreferencesButton as AlbumPreferencesButton, ) from quodlibet.browsers.covergrid.models import ( AlbumListFilterModel, AlbumListModel, AlbumListSortModel, ) from quodlibet.browsers.covergrid.widgets import AlbumWidget from quodlibet.browsers._base import DisplayPatternMixin from quodlibet.query import Query from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.x import MenuItem, Align, ScrolledWindow, RadioMenuItem from quodlibet.qltk.x import SymbolicIconImage from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk import Icons from quodlibet.util import connect_destroy from quodlibet.util import connect_obj from quodlibet.qltk import popup_menu_at_widget class PreferencesButton(AlbumPreferencesButton): def __init__(self, browser, model): Gtk.HBox.__init__(self) sort_orders = [ (_("_Title"), self.__compare_title), (_("_People"), self.__compare_people), (_("_Date"), self.__compare_date), (_("_Date Added"), self.__compare_date_added), (_("_Original Date"), self.__compare_original_date), (_("_Genre"), self.__compare_genre), (_("_Rating"), self.__compare_rating), (_("Play_count"), self.__compare_avgplaycount), ] menu = Gtk.Menu() sort_item = Gtk.MenuItem( label=_(u"Sort _by…"), use_underline=True) sort_menu = Gtk.Menu() active = config.getint("browsers", "album_sort", 1) item = None for i, (label, func) in enumerate(sort_orders): item = RadioMenuItem(group=item, label=label, use_underline=True) model.set_sort_func(100 + i, func) if i == active: model.set_sort_column_id(100 + i, Gtk.SortType.ASCENDING) item.set_active(True) item.connect("toggled", util.DeferredSignal(self.__sort_toggled_cb), model, i) sort_menu.append(item) sort_item.set_submenu(sort_menu) menu.append(sort_item) pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) menu.append(pref_item) connect_obj(pref_item, "activate", Preferences, browser) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) self.pack_start(button, True, True, 0) class CoverGridContainer(ScrolledWindow): def __init__(self, fb): super().__init__( hscrollbar_policy=Gtk.PolicyType.NEVER, vscrollbar_policy=Gtk.PolicyType.AUTOMATIC, shadow_type=Gtk.ShadowType.IN) self._fb = fb fb.set_hadjustment(self.props.hadjustment) fb.set_vadjustment(self.props.vadjustment) self.add(fb) def scroll_up(self): va = self.props.vadjustment va.props.value = va.props.lower def scroll_to_child(self, child): def scroll(): va = self.props.vadjustment if va is None: return v = va.props.value coords = child.translate_coordinates(self, 0, v) if coords is None: return x, y = coords h = child.get_allocation().height p = va.props.page_size if y < v: va.props.value = y elif y + h > v + p: va.props.value = y - p + h GLib.idle_add(scroll, priority=GLib.PRIORITY_LOW) def do_focus(self, direction): is_tab = (direction == Gtk.DirectionType.TAB_FORWARD or direction == Gtk.DirectionType.TAB_BACKWARD) if not is_tab: self._fb.child_focus(direction) return True if self.get_focus_child(): # [Tab] moves focus beyond this container return False children = self._fb.get_selected_children() if children: children[0].grab_focus() else: self._fb.child_focus(direction) return True def _get_cover_size(): mag = config.getfloat("browsers", "covergrid_magnification", 3.) size = config.getint("browsers", "cover_size") if size <= 0: size = 48 return mag * size class CoverGrid(Browser, util.InstanceTracker, DisplayPatternMixin): __model = None _PATTERN_FN = os.path.join(quodlibet.get_user_dir(), "album_pattern") _DEFAULT_PATTERN_TEXT = DEFAULT_PATTERN_TEXT name = _("Cover Grid") accelerated_name = _("_Cover Grid") keys = ["CoverGrid"] priority = 5 def pack(self, songpane): container = self.songcontainer container.pack1(self, True, False) container.pack2(songpane, True, False) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) @classmethod def init(klass, library): super(CoverGrid, klass).load_pattern() @classmethod def _init_model(klass, library): if klass.__model is None: klass.__model = AlbumListModel(library) klass.__library = library @classmethod def _destroy_model(klass): klass.__model.destroy() klass.__model = None @classmethod def toggle_text(klass): text_visible = config.getboolean("browsers", "album_text", True) for covergrid in klass.instances(): for child in covergrid.view: child.props.text_visible = text_visible @classmethod def toggle_item_all(klass): show = config.getboolean("browsers", "covergrid_all", True) for covergrid in klass.instances(): covergrid.__model_filter.props.include_item_all = show @classmethod def toggle_wide(klass): wide = config.getboolean("browsers", "covergrid_wide", False) for covergrid in klass.instances(): covergrid.songcontainer.set_orientation( Gtk.Orientation.HORIZONTAL if wide else Gtk.Orientation.VERTICAL) @classmethod def update_mag(klass): cover_size = _get_cover_size() for covergrid in klass.instances(): for child in covergrid.view: child.cover_size = cover_size covergrid.view.queue_resize() def __init__(self, library): super().__init__( orientation=Gtk.Orientation.VERTICAL, spacing=6) self.songcontainer = qltk.paned.ConfigRVPaned( "browsers", "covergrid_pos", 0.4) if config.getboolean("browsers", "covergrid_wide", False): self.songcontainer.set_orientation(Gtk.Orientation.HORIZONTAL) self._register_instance() self._init_model(library) self.__cover_cancel = Gio.Cancellable() model_sort = AlbumListSortModel(model=self.__model) self.__model_filter = model_filter = AlbumListFilterModel( include_item_all=config.getboolean("browsers", "covergrid_all", True), child_model=model_sort) def create_album_widget(model): item_padding = config.getint("browsers", "item_padding", 6) text_visible = config.getboolean("browsers", "album_text", True) cover_size = _get_cover_size() widget = AlbumWidget( model, display_pattern=self.display_pattern, cover_size=cover_size, padding=item_padding, text_visible=text_visible, cancelable=self.__cover_cancel) widget.connect("songs-menu", self.__popup) return widget self.view = view = Gtk.FlowBox( valign=Gtk.Align.START, activate_on_single_click=False, selection_mode=Gtk.SelectionMode.MULTIPLE, homogeneous=True, min_children_per_line=1, max_children_per_line=10, row_spacing=config.getint("browsers", "row_spacing", 6), column_spacing=config.getint("browsers", "column_spacing", 6)) self.scrollwin = sw = CoverGridContainer(view) view.connect("selected-children-changed", util.DeferredSignal( lambda _: self.__update_songs(select_default=False), owner=self)) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) view.connect("drag-data-get", self.__drag_data_get) view.connect("child-activated", self.__child_activated) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) search.connect("query-changed", lambda *a: self.__update_filter()) connect_obj(search, "focus-out", lambda w: w.grab_focus(), view) self.__search = search prefs = PreferencesButton(self, model_sort) search.pack_start(prefs, False, True, 0) self.pack_start(Align(search, left=6, top=0), False, True, 0) self.pack_start(sw, True, True, 0) self.__update_filter() model_filter.connect("notify::filter", util.DeferredSignal(lambda *a: self.__update_songs(), owner=self)) self.connect("key-press-event", self.__key_pressed, library.librarian) self.connect("destroy", self.__destroy) if app.cover_manager: connect_destroy( app.cover_manager, "cover-changed", self.__cover_changed) # show all before binding the model, so a label in a flowbox child will # stay hidden if so configured by the "browsers.album_text" property. self.show_all() view.bind_model(model_filter, create_album_widget) def __update_songs(self, select_default=True): songs = self.__get_selected_songs(sort=False) if not select_default or songs: self.songs_selected(songs) else: child = self.view.get_child_at_index(0) if child: self.view.select_child(child) else: self.songs_selected(songs) def __key_pressed(self, widget, event, librarian): if qltk.is_accel(event, "<Primary>I"): songs = self.__get_selected_songs() if songs: window = Information(librarian, songs, self) window.show() return True elif qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): qltk.enqueue(self.__get_selected_songs()) return True elif qltk.is_accel(event, "<alt>Return"): songs = self.__get_selected_songs() if songs: window = SongProperties(librarian, songs, self) window.show() return True return False def __destroy(self, browser): self.__cover_cancel.cancel() self.view.bind_model(None, lambda _: None) self.__model_filter.destroy() self.__model_filter = None if not CoverGrid.instances(): CoverGrid._destroy_model() def __cover_changed(self, manager, songs): songs = set(songs) for child in self.view: if not songs: break album = child.model.album if album is None: continue match = songs & album.songs if match: child.populate() songs -= match def __update_filter(self, scroll_up=True): if scroll_up: self.scrollwin.scroll_up() q = self.__search.get_query(star=["~people", "album"]) self.__model_filter.props.filter = None if q.matches_all else q.search def __popup(self, widget): if not widget.is_selected(): self.view.unselect_all() self.view.select_child(widget) albums = self.__get_selected_albums() songs = self.__get_songs_from_albums(albums) button_label = ngettext( "Reload album _cover", "Reload album _covers", len(albums)) button = MenuItem(button_label, Icons.VIEW_REFRESH) button.connect("activate", self.__refresh_cover, widget) menu = SongsMenu(self.__library, songs, items=[[button]]) menu.show_all() popup_menu_at_widget( menu, widget, Gdk.BUTTON_SECONDARY, Gtk.get_current_event_time()) def __refresh_cover(self, menuitem, view): for child in self.view.get_selected_children(): child.populate() def refresh_all(self): display_pattern = self.display_pattern for child in self.view: child.display_pattern = display_pattern def __get_selected_albums(self): items = [] for child in self.view.get_selected_children(): album = child.model.album if album is None: model = self.__model_filter return [item.album for item in model if item.album is not None] items.append(album) return items def __get_songs_from_albums(self, albums, sort=True): # Sort first by how the albums appear in the model itself, # then within the album using the default order. songs = [] if sort: for album in albums: songs.extend(sorted(album.songs, key=lambda s: s.sort_key)) else: for album in albums: songs.extend(album.songs) return songs def __get_selected_songs(self, sort=True): albums = self.__get_selected_albums() return self.__get_songs_from_albums(albums, sort) def __drag_data_get(self, view, ctx, sel, tid, etime): songs = self.__get_selected_songs() if tid == 1: qltk.selection_set_songs(sel, songs) else: sel.set_uris([song("~uri") for song in songs]) def __child_activated(self, view, child): self.songs_activated() def active_filter(self, song): for album in self.__get_selected_albums(): if song in album.songs: return True return False def can_filter_text(self): return True def filter_text(self, text): self.__search.set_text(text) if Query(text).is_parsable: self.__update_filter() self.__update_songs() def get_filter_text(self): return self.__search.get_text() def can_filter_albums(self): return True def can_filter(self, key): # Numerics are different for collections, and although title works, # it's not of much use here. if key is not None and (key.startswith("~#") or key == "title"): return False return super().can_filter(key) def filter_albums(self, values): changed = self.__select_by_func( lambda album: album is not None and album.key in values) self.view.grab_focus() if changed: self.__update_songs() def list_albums(self): model = self.__model_filter return [item.album.key for item in model if item.album is not None] def unfilter(self): self.filter_text("") def __select_by_func(self, func, scroll=True, one=False): first = True view = self.view for i, item in enumerate(self.__model_filter): if not func(item.album): continue child = view.get_child_at_index(i) if first: view.unselect_all() view.select_child(child) if scroll: self.scrollwin.scroll_to_child(child) first = False if one: break else: view.select_child(child) return not first def save(self): conf = self.__get_config_string() config.settext("browsers", "covergrid", conf) text = self.__search.get_text() config.settext("browsers", "query_text", text) def restore(self): text = config.gettext("browsers", "query_text") entry = self.__search entry.set_text(text) if Query(text).is_parsable: self.__update_filter(scroll_up=False) keys = config.gettext("browsers", "covergrid", "").split("\n") if keys != [""]: self.__select_by_func( lambda album: album is not None and album.str_key in keys) else: self.__select_by_func(lambda album: album is None, one=True) def finalize(self, restored): if not restored: self.__select_by_func(lambda album: album is None, one=True) def scroll(self, song): album_key = song.album_key self.__select_by_func( lambda album: album is not None and album.key == album_key, one=True) def activate(self): self.__update_songs() def __get_config_string(self): albums = [] for child in self.view.get_selected_children(): album = child.model.album if album is None: albums.clear() break albums.append(album) if not albums: return "" confval = "\n".join((a.str_key for a in albums)) # ConfigParser strips a trailing \n so we move it to the front if confval and confval[-1] == "\n": confval = "\n" + confval[:-1] return confval ���������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/models.py����������������������������������������������0000644�0001750�0001750�00000020775�14327505043�021700� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2022 Thomas Leberbauer # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Callable, Optional from gi.repository import GObject, Gio from quodlibet import _, app, util from quodlibet.library.song import SongLibrary from quodlibet.qltk.models import ObjectModelSort, ObjectStore, ObjectModelFilter from quodlibet.util.collection import Album from quodlibet.util.i18n import numeric_phrase from quodlibet.util.library import background_filter class AlbumListItem(GObject.Object): """This model represents an entry for a specific album. It will load the album cover and generate the album label on demand. """ def __init__(self, album: Optional[Album] = None): super().__init__() self._album = album self._cover = None self._label = None self.connect('notify::album', self._album_changed) def load_cover(self, size: int, cancelable: Optional[Gio.Cancellable] = None): def callback(cover): self._cover = cover self.notify('cover') manager = app.cover_manager # Skip this during testing if manager: manager.get_pixbuf_many_async( self._album.songs, size, size, cancelable, callback) def format_label(self, pattern): self._label = pattern % self._album self.notify('label') def _album_changed(self, model, prop): self._label = None @GObject.Property def album(self): return self._album @GObject.Property def cover(self): return self._cover @GObject.Property def label(self): return self._label class AlbumListCountItem(AlbumListItem): """This model represents an entry for a set of albums. It will generate a label containing the number of albums on demand. """ def load_cover(self, *args, **kwargs): self.notify('cover') def format_label(self, pattern=None): n = self.__n_albums title = util.bold(_('All Albums')) number_phrase = numeric_phrase('%d album', '%d albums', n) self._label = f"{title}\n{number_phrase}" self.notify('label') @GObject.Property def n_albums(self): return self.__n_albums @n_albums.setter # type: ignore def n_albums(self, value): self.__n_albums = value self.format_label() class AlbumListModel(ObjectStore): """This model creates entries for albums from a library. The first entry represents the whole set of albums in the library. """ def __init__(self, library: SongLibrary): super().__init__() self.__library = library albums = library.albums self.__sigs = [ albums.connect('added', self._add_albums), albums.connect('removed', self._remove_albums), albums.connect('changed', self._change_albums) ] self.append(row=[AlbumListCountItem()]) self.append_many(AlbumListItem(a) for a in albums.values()) def destroy(self): albums = self.__library.albums for sig in self.__sigs: albums.disconnect(sig) self.__library = None self.clear() def _add_albums(self, library, added): self.append_many(AlbumListItem(a) for a in added) def _remove_albums(self, library, removed): removed_albums = removed.copy() iters_remove = [] for iter_, item in self.iterrows(): album = item.album if album is not None and album in removed_albums: removed_albums.remove(album) iters_remove.append(iter_) if not removed_albums: break for iter_ in iters_remove: self.remove(iter_) def _change_albums(self, library, changed): changed_albums = changed.copy() for iter_, item in self.iterrows(): album = item.album if album is not None and album in changed_albums: changed_albums.remove(album) self.iter_changed(iter_) if not changed_albums: break class AlbumListFilterModel(GObject.Object, Gio.ListModel): """This model filters entries in a child model. The property "include_item_all" toggles visibility of the first entry of the child model. The property "filter" is a function which defines visibility for all remaining entries of the child model. If "filter" is set to None, all entries are visible. """ __item_all: AlbumListItem __include_item_all: bool __filter: Optional[Callable[[AlbumListItem], bool]] = None def __init__(self, child_model=None, include_item_all=True, **kwargs): super().__init__(**kwargs) self.__include_item_all = include_item_all self._model = model = ObjectModelFilter(child_model=child_model) self.__item_all = self._get_item(0) self._update_n_albums() # Tell the tree model that all nodes are visible, otherwise it does not # emit the "row-changed" signal. for row in model: model.ref_node(row.iter) model.set_visible_func(self._apply_filter) self.__sigs = [ model.connect('row-changed', self._row_changed), model.connect('row-inserted', self._row_inserted), model.connect('row-deleted', self._row_deleted), model.connect('rows-reordered', self._rows_reordered) ] def destroy(self): model = self._model for sig in self.__sigs: model.disconnect(sig) self._model = None @GObject.Property def include_item_all(self): return self.__include_item_all @include_item_all.setter # type: ignore def include_item_all(self, value): if self.__include_item_all == value: return self.__include_item_all = value removed, added = (0, 1) if value else (1, 0) self.items_changed(0, removed, added) @GObject.Property def filter(self): return self.__filter @filter.setter # type: ignore def filter(self, value): b = background_filter() if b is None and value is None: f = None elif b is None: f = lambda item: value(item.album) else: f = lambda item: b(item.album) and value(item.album) if f or self.__filter: self.__filter = f self._model.refilter() def do_get_n_items(self): return len(self) def do_get_item(self, index): return self[index] def do_get_item_type(self): return AlbumListItem def __len__(self): n = len(self._model) if self.__include_item_all or n < 1: return n return n - 1 def __getitem__(self, index): if not self.__include_item_all: index += 1 return self._get_item(index) def _get_item(self, index: int) -> Optional[AlbumListItem]: model = self._model iter = model.iter_nth_child(None, index) return model.get_value(iter) if iter else None def _update_n_albums(self): self.__item_all.props.n_albums = len(self._model) - 1 def _apply_filter(self, model, iter, _): filter = self.__filter if filter is None: return True item = model.get_value(iter) if item is self.__item_all: return True return filter(item) def _row_changed(self, model, path, iter): item = model.get_value(iter) item.notify('album') def _row_inserted(self, model, path, iter): # Ensure that the tree model will emit the "row-changed" signal model.ref_node(iter) index = path.get_indices()[0] if not self.__include_item_all: index -= 1 if index >= 0: self.items_changed(index, 0, 1) self._update_n_albums() def _row_deleted(self, model, path): index = path.get_indices()[0] if not self.__include_item_all: index -= 1 if index >= 0: self.items_changed(index, 1, 0) self._update_n_albums() def _rows_reordered(self, model, path, iter, new_order): n = len(self) self.items_changed(0, n, n) class AlbumListSortModel(ObjectModelSort): """This model sorts entries of a child model""" pass ���././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660855332.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/prefs.py�����������������������������������������������0000644�0001750�0001750�00000011470�14277522044�021530� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012,2013,2016 Nick Boultbee # 2009-2013 Christoph Reiter # 2016 Mice Pápai # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.browsers._base import FakeDisplayItem, EditDisplayPatternMixin from quodlibet.formats import PEOPLE from quodlibet.qltk import Button, Icons from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.util import format_rating from quodlibet.util.i18n import numeric_phrase from quodlibet.util.dprint import print_d PEOPLE _SOME_PEOPLE = "\n".join([util.tag("artist"), util.tag("performer"), util.tag("composer"), util.tag("arranger"), ]) _EMPTY = _("Songs not in an album") DEFAULT_PATTERN_TEXT = """[b]<album|<album>|%s>[/b]<date| (<date>)> [small]<~discs|<~discs> - ><~tracks> - <~long-length>[/small] <~people>""" % _EMPTY class Preferences(qltk.UniqueWindow, EditDisplayPatternMixin): _DEFAULT_PATTERN = DEFAULT_PATTERN_TEXT _PREVIEW_ITEM = FakeDisplayItem({ "date": "2010-10-31", "~length": util.format_time_display(6319), "~long-length": util.format_time_long(6319), "~tracks": numeric_phrase("%d track", "%d tracks", 5), "~discs": numeric_phrase("%d disc", "%d discs", 2), "~#rating": 0.75, "album": _("An Example Album"), "~people": _SOME_PEOPLE + "..."}) def __init__(self, browser): if self.is_not_unique(): return super().__init__() self.set_border_width(12) self.set_title(_("Cover Grid Preferences")) self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._PREVIEW_ITEM["~rating"] = format_rating(0.75) self.mag_lock = False box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _text"), "browsers", "album_text") cb.set_active(config.getboolean("browsers", "album_text", True)) cb.connect('toggled', lambda s: browser.toggle_text()) vbox.pack_start(cb, False, True, 0) cb2 = ConfigCheckButton( _("Show \"All Albums\" Item"), "browsers", "covergrid_all") cb2.set_active(config.getboolean("browsers", "covergrid_all", True)) cb2.connect('toggled', lambda s: browser.toggle_item_all()) vbox.pack_start(cb2, False, True, 0) cb3 = ConfigCheckButton(_("Wide Mode"), "browsers", "covergrid_wide") cb3.set_active(config.getboolean("browsers", "covergrid_wide", False)) cb3.connect('toggled', lambda s: browser.toggle_wide()) vbox.pack_start(cb3, False, True, 0) def mag_changed(mag): newmag = mag.get_value() oldmag = config.getfloat("browsers", "covergrid_magnification", 3.) if newmag == oldmag: print_d("Covergrid magnification haven't changed: {0}" .format(newmag)) return print_d('Covergrid magnification update from {0} to {1}' .format(oldmag, newmag)) config.set("browsers", "covergrid_magnification", mag.get_value()) browser.update_mag() mag_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(config.getfloat("browsers", "covergrid_magnification", 3), 1, 10., .5, .5, 0)) mag_scale.set_tooltip_text(_("Cover Magnification")) l = Gtk.Label(label=_("Cover Magnification")) mag_scale.set_value_pos(Gtk.PositionType.RIGHT) mag_scale.connect('value-changed', mag_changed) vbox.pack_start(l, False, True, 0) vbox.pack_start(mag_scale, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) display_frame = self.edit_display_pane(browser, _("Album Display")) box.pack_start(display_frame, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660940819.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/covergrid/widgets.py���������������������������������������������0000644�0001750�0001750�00000012574�14277771023�022070� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2022 Thomas Leberbauer # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import from typing import Optional from gi.repository import GObject, Gio, GdkPixbuf, Gtk, Pango, Gdk from cairo import Surface from .models import AlbumListItem from quodlibet.qltk.cover import get_no_cover_pixbuf from quodlibet.qltk.image import add_border_widget, get_surface_for_pixbuf from quodlibet.util import DeferredSignal def _no_cover(size, widget) -> Optional[Surface]: old_size, surface = getattr(_no_cover, 'cache', (None, None)) if old_size != size or surface is None: surface = get_surface_for_pixbuf( widget, get_no_cover_pixbuf(size, size)) setattr(_no_cover, 'cache', (size, surface)) return surface class AlbumWidget(Gtk.FlowBoxChild): """An AlbumWidget displays an album with a cover and a label. The cover initially holds a placeholder. When the widget is drawn the real cover loads and the label is shown. """ __gsignals__ = { 'songs-menu': (GObject.SignalFlags.RUN_LAST, None, ()) } padding = GObject.Property(type=int, default=0) cover_size = GObject.Property(type=int, default=48) text_visible = GObject.Property(type=bool, default=True) display_pattern = GObject.Property() def __init__(self, model: AlbumListItem, cancelable: Optional[Gio.Cancellable] = None, **kwargs): super().__init__(has_tooltip=True, **kwargs) self.model = model self._cancelable = cancelable self.__draw_handler_id = None self._box = box = Gtk.Box( vexpand=False, orientation=Gtk.Orientation.VERTICAL) image_size = self.__get_image_size() self._image = Gtk.Image( width_request=image_size, height_request=image_size) self._label = label = Gtk.Label( ellipsize=Pango.EllipsizeMode.END, justify=Gtk.Justification.CENTER) box.pack_start(self._image, True, True, 0) box.pack_start(self._label, True, True, 0) eb = Gtk.EventBox() eb.connect('popup-menu', lambda _: self.emit('songs-menu')) eb.connect('button-press-event', self.__rightclick) eb.add(box) self.add(eb) # show all before binding "visible" so the label will stay hidden if so # configured by the "text_visible" property. self.show_all() self.bind_property( 'padding', box, 'margin', GObject.BindingFlags.SYNC_CREATE) self.bind_property( 'padding', box, 'spacing', GObject.BindingFlags.SYNC_CREATE) self.bind_property( 'text-visible', label, 'visible', GObject.BindingFlags.SYNC_CREATE) model.connect('notify::album', lambda *a: self._populate()) model.connect('notify::label', lambda *a: self._set_text(model.label)) model.connect('notify::cover', lambda *a: self._set_cover(model.cover)) self.connect('query-tooltip', self.__tooltip) self.connect('notify::cover-size', self.__cover_size) self.connect('notify::display-pattern', self.__display_pattern) self._set_cover(self.model.cover) self._set_text(self.model.label) self._populate_on_draw() def do_get_preferred_width(self): image_size = self.__get_image_size() width = image_size + 4 * self.props.padding return (width, width) def __get_image_size(self) -> int: return self.props.cover_size + 2 def populate(self): self._populate_on_draw() def _populate_on_draw(self): self.__draw_handler_id = self._image.connect( 'draw', DeferredSignal(self.__draw, timeout=10)) def __draw(self, widget, cr): if self.__draw_handler_id is None: return self._image.disconnect(self.__draw_handler_id) self.__draw_handler_id = None self._populate() def _populate(self): size = self.props.scale_factor * self.props.cover_size self.model.load_cover(size, self._cancelable) self.model.format_label(self.props.display_pattern) def _set_cover(self, cover: Optional[GdkPixbuf.Pixbuf] = None): if cover: pb = add_border_widget(cover, self) surface = get_surface_for_pixbuf(self, pb) else: size = self.props.scale_factor * self.props.cover_size surface = _no_cover(size, self) self._image.props.surface = surface def _set_text(self, label: Optional[str] = None): if label: self._label.set_markup(label) def __cover_size(self, _, prop): size = self.__get_image_size() self._image.props.width_request = size self._image.props.height_request = size self._set_cover() self._populate_on_draw() def __display_pattern(self, _, prop): self.model.format_label(self.props.display_pattern) def __rightclick(self, widget, event): if event.button == Gdk.BUTTON_SECONDARY: self.emit('songs-menu') def __tooltip(self, widget, x, y, keyboard_tip, tooltip): label = self.model.label if label: tooltip.set_markup(label) return True ������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/filesystem.py����������������������������������������������������0000644�0001750�0001750�00000022124�14267565021�020610� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. # Some sort of crazy directory-based browser. QL is full of minor hacks # to support this by automatically adding songs to the library when it # needs them to be there. import os from typing import TypeVar, Iterable, List from gi.repository import Gtk, Gdk from senf import fsn2uri, fsn2bytes, bytes2fsn from quodlibet import config from quodlibet import formats from quodlibet import qltk from quodlibet import _ from quodlibet.browsers import Browser from quodlibet.library import SongFileLibrary from quodlibet.qltk.filesel import MainDirectoryTree from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.x import ScrolledWindow from quodlibet.qltk import Icons from quodlibet.util import copool from quodlibet.util.library import get_scan_dirs from quodlibet.util.dprint import print_d from quodlibet.util.path import normalize_path from quodlibet.util import connect_obj T = TypeVar("T") class FileSystem(Browser, Gtk.HBox): __library = None name = _("File System") accelerated_name = _("_File System") keys = ["FileSystem"] priority = 10 uses_main_library = False TARGET_QL, TARGET_EXT = range(1, 3) def pack(self, songpane): container = qltk.ConfigRHPaned("browsers", "filesystem_pos", 0.4) container.pack1(self, True, False) container.pack2(songpane, True, False) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) @classmethod def __added(klass, library, songs): klass.__library.remove(songs) @classmethod def init(klass, library): if klass.__library is not None: return klass.__glibrary = library klass.__library = SongFileLibrary("filesystem") library.connect('added', klass.__remove_because_added) @classmethod def __remove_because_added(klass, library, songs): songs = klass._only_known(songs) klass.__library.remove(songs) @classmethod def _only_known(cls, songs: Iterable[T]) -> List[T]: return [s for s in songs if cls.__library.__contains__(s)] # type:ignore def __init__(self, library): super().__init__() sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) dt = MainDirectoryTree(folders=get_scan_dirs()) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, self.TARGET_QL), ("text/uri-list", 0, self.TARGET_EXT)] targets = [Gtk.TargetEntry.new(*t) for t in targets] dt.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) dt.connect('drag-data-get', self.__drag_data_get) sel = dt.get_selection() sel.unselect_all() connect_obj(sel, 'changed', copool.add, self.__songs_selected, dt) sel.connect("changed", self._on_selection_changed) dt.connect('row-activated', lambda *a: self.songs_activated()) sw.add(dt) self.pack_start(sw, True, True, 0) self.show_all() def _on_selection_changed(self, tree_selection): model, rows = tree_selection.get_selected_rows() selected_paths = [model[row][0] for row in rows] if selected_paths: data = fsn2bytes("\n".join(selected_paths), "utf-8") else: data = b"" config.setbytes("browsers", "filesystem", data) def get_child(self): return self.get_children()[0].get_child() def __drag_data_get(self, view, ctx, sel, tid, etime): model, rows = view.get_selection().get_selected_rows() dirs = [model[row][0] for row in rows] for songs in self.__find_songs(view.get_selection()): pass if tid == self.TARGET_QL: cant_add = [s for s in songs if not s.can_add] if cant_add: qltk.ErrorMessage( qltk.get_top_parent(self), _("Unable to copy songs"), _("The files selected cannot be copied to other " "song lists or the queue.")).run() ctx.drag_abort(etime) return to_add = self._only_known(songs) self.__add_songs(view, to_add) qltk.selection_set_songs(sel, songs) else: # External target (app) is delivered a list of URIS of songs uris = list({fsn2uri(dir) for dir in dirs}) print_d("Directories to drop: %s" % dirs) sel.set_uris(uris) def can_filter_tag(self, key): return key == "~dirname" def filter(self, key, values): self.get_child().get_selection().unselect_all() for v in values: self.get_child().go_to(v) def scroll(self, song): self.__select_paths([song("~dirname")]) def restore(self): data = config.getbytes("browsers", "filesystem", b"") try: paths = bytes2fsn(data, "utf-8") except ValueError: return if not paths: return self.__select_paths(paths.split("\n")) def __select_paths(self, paths): # AudioFile uses normalized paths, DirectoryTree doesn't paths = list(map(normalize_path, paths)) def select(model, path, iter_, paths_): (paths, first) = paths_ value = model.get_value(iter_) if value is None: return not bool(paths) value = normalize_path(value) if value in paths: self.get_child().get_selection().select_path(path) paths.remove(value) if not first: self.get_child().set_cursor(path) # copy treepath, gets invalid after the callback first.append(path.copy()) else: for fpath in paths: if fpath.startswith(value): self.get_child().expand_row(path, False) return not bool(paths) # XXX: We expect all paths we want in DirectoryTree to be # expanded once before first = [] self.get_child().get_model().foreach(select, (paths, first)) if first: self.get_child().scroll_to_cell(first[0], None, True, 0.5) def activate(self): copool.add(self.__songs_selected, self.get_child()) def Menu(self, songs, library, items): i = qltk.MenuItem(_("_Add to Library"), Icons.LIST_ADD) i.set_sensitive(False) i.connect('activate', self.__add_songs, songs) for song in songs: if song not in self.__glibrary: i.set_sensitive(True) break items.append([i]) menu = SongsMenu(library, songs, remove=self.__remove_songs, delete=True, queue=True, items=items) return menu def __add_songs(self, item, songs): songs = self._only_known(songs) self.__library.librarian.move(songs, self.__library, self.__glibrary) def __remove_songs(self, songs): songs = [s for s in songs if self.__glibrary.__contains__(s)] self.__library.librarian.move(songs, self.__glibrary, self.__library) def __find_songs(self, selection): model, rows = selection.get_selected_rows() dirs = [model[row][0] for row in rows] songs = [] to_add = [] for dir in dirs: try: for file in sorted(os.listdir(dir)): if not formats.filter(file): continue raw_path = os.path.join(dir, file) fn = normalize_path(raw_path, canonicalise=True) if fn in self.__glibrary: songs.append(self.__glibrary[fn]) elif fn not in self.__library: song = formats.MusicFile(fn) if song: to_add.append(song) songs.append(song) yield songs if fn in self.__library: song = self.__library[fn] if not song.valid(): self.__library.reload(song) if song in self.__library: songs.append(song) except OSError: pass self.__library.add(to_add) yield songs def __songs_selected(self, view): if self.get_window(): self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) for songs in self.__find_songs(view.get_selection()): yield True if self.get_window(): self.get_window().set_cursor(None) self.songs_selected(songs) browsers = [FileSystem] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661801479.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/iradio.py��������������������������������������������������������0000644�0001750�0001750�00000077163�14303212007�017670� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011 Joe Wreschnig, Christoph Reiter # 2013-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys import bz2 import itertools from functools import reduce from http.client import HTTPException from os.path import splitext from threading import Thread from typing import Dict, Collection, Callable, Iterable, Optional from urllib.request import urlopen import re from gi.repository import Gtk, GLib, Pango from senf import text2fsn from quodlibet.util.dprint import print_d, print_e import quodlibet from quodlibet import _ from quodlibet import qltk from quodlibet import util from quodlibet import config from quodlibet.browsers import Browser from quodlibet.formats.remote import RemoteFile from quodlibet.formats._audio import TAG_TO_SORT, MIGRATE, AudioFile from quodlibet.library import SongLibrary from quodlibet.query import Query from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.notif import Task from quodlibet.qltk import Icons, ErrorMessage, WarningMessage from quodlibet.util import copool, connect_destroy, sanitize_tags, connect_obj from quodlibet.util.i18n import numeric_phrase from quodlibet.util.path import uri_is_valid from quodlibet.util.string import decode, encode from quodlibet.util import print_w from quodlibet.qltk.views import AllTreeView from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.x import MenuItem, Align, ScrolledWindow, Button STATION_LIST_URL = \ "https://quodlibet.github.io/radio/radiolist.bz2" STATIONS_FAV = os.path.join(quodlibet.get_user_dir(), "stations") STATIONS_ALL = os.path.join(quodlibet.get_user_dir(), "stations_all") # TODO: - Ranking: reduce duplicate stations (max 3 URLs per station) # prefer stations that match a genre? # Migration path for pickle sys.modules["browsers.iradio"] = sys.modules[__name__] class IRadioError(Exception): pass class IRFile(RemoteFile): multisong = True can_add = False format = "Radio Station" __CAN_CHANGE = "title artist grouping".split() def __get(self, base_call, key, *args, **kwargs): if key == "title" and "title" not in self and "organization" in self: return base_call("organization", *args, **kwargs) # split title by " - " if no artist tag is present and # this is not the main song: common format for shoutcast stations if not self.multisong and key in ("title", "artist") and \ "title" in self and "artist" not in self: title = base_call("title").split(" - ", 1) if len(title) > 1: return (key == "title" and title[-1]) or title[0] if key in ("artist", TAG_TO_SORT["artist"]) and \ not base_call(key, *args) and "website" in self: return base_call("website", *args) if key == "~format" and "audio-codec" in self: return "%s (%s)" % (self.format, base_call("audio-codec", *args, **kwargs)) return base_call(key, *args, **kwargs) def __call__(self, key, *args, **kwargs): base_call = super().__call__ return self.__get(base_call, key, *args, **kwargs) def get(self, key, *args, **kwargs): base_call = super().get return self.__get(base_call, key, *args, **kwargs) def write(self): pass def to_dump(self): # dump without title title = None if "title" in self: title = self["title"] del self["title"] dump = super().to_dump() if title is not None: self["title"] = title # add all generated tags lines = dump.splitlines() for tag in ["title", "artist", "~format"]: value = self.get(tag) if value is not None: lines.append(encode(tag) + b"=" + encode(value)) return b"\n".join(lines) @property def lyric_filename(self) -> Optional[str]: return None def can_change(self, k=None): if self.streamsong: if k is None: return [] else: return False else: if k is None: return self.__CAN_CHANGE else: return k in self.__CAN_CHANGE def parse_pls(file) -> Collection[IRFile]: data = {} lines = file.read().decode('utf-8', 'replace').splitlines() if not lines or "[playlist]" not in lines.pop(0): return [] for line in lines: try: head, val = line.strip().split("=", 1) except (TypeError, ValueError): continue else: head = head.lower() if head.startswith("length") and val == "-1": continue else: data[head] = val count = 1 files = [] warnings = [] while True: if "file%d" % count in data: filename = text2fsn(data["file%d" % count]) if filename.lower()[-4:] in [".pls", ".m3u", "m3u8"]: warnings.append(filename) else: irf = IRFile(filename) for key in ["title", "genre", "artist"]: try: irf[key] = data["%s%d" % (key, count)] except KeyError: pass try: irf["~#length"] = int(data["length%d" % count]) except (KeyError, TypeError, ValueError): pass files.append(irf) else: break count += 1 if warnings: raise IRadioError( _("Station lists can only contain locations of stations, " "not other station lists or playlists. The following locations " "cannot be loaded:\n%s") % "\n ".join(map(util.escape, warnings))) return files def parse_m3u(fileobj) -> Collection[IRFile]: files = [] pending_title = None lines = fileobj.read().decode('utf-8', 'replace').splitlines() for line in lines: line = line.strip() if line.startswith("#EXTINF:"): try: pending_title = line.split(",", 1)[1] except IndexError: pending_title = None elif line.startswith("http"): irf = IRFile(text2fsn(line)) if pending_title: irf["title"] = pending_title pending_title = None files.append(irf) return files def _get_stations_from(uri: str, on_done: Callable[[Iterable[IRFile], str], None])\ -> None: """Fetches the URI content and extracts IRFiles Called from thread - so no direct GTK+ interaction :param uri: URI of station :param on_done: a callback taking files when done (or none if errored) """ with Task(_("Internet Radio"), _("Add stations")) as task: irfs: Collection[IRFile] = [] GLib.idle_add(task.pulse) if (uri.lower().endswith(".pls") or uri.lower().endswith(".m3u") or uri.lower().endswith(".m3u8")): if not re.match('^([^/:]+)://', uri): # Assume HTTP if no protocol given. See #2731 uri = 'http://' + uri print_d("Assuming http: %s" % uri) # Error handling outside sock = None GLib.idle_add(task.pulse) _fn, ext = splitext(uri.lower()) try: sock = urlopen(uri, timeout=6) if ext == ".pls": irfs = parse_pls(sock) elif ext in (".m3u", ".m3u8"): irfs = parse_m3u(sock) GLib.idle_add(task.pulse) except IOError as e: print_e(f"Couldn't download from {uri} ({e})") finally: if sock: sock.close() else: try: irfs = [IRFile(uri)] except ValueError as e: print_e("Can't add URI %s" % uri, e) on_done(irfs, uri) def download_taglist(url, callback, cofuncid, step=1024 * 10): """Generator for loading the bz2 compressed tag list. Calls callback with the decompressed data or None in case of an error.""" with Task(_("Internet Radio"), _("Downloading station list")) as task: if cofuncid: task.copool(cofuncid) try: response = urlopen(url) except (EnvironmentError, HTTPException) as e: print_e(f"Failed fetching from {url}", e) GLib.idle_add(callback, None) return try: size = int(response.info().get("content-length", 0)) except ValueError: size = 0 decomp = bz2.BZ2Decompressor() data = b"" temp = b"" read = 0 while temp or not data: read += len(temp) if size: task.update(float(read) / size) else: task.pulse() yield True try: data += decomp.decompress(temp) temp = response.read(step) except (IOError, EOFError): data = None break response.close() yield True stations = None if data: stations = parse_taglist(data) print_d(f"Got {len(stations or [])} station(s)") GLib.idle_add(callback, stations) def parse_taglist(data): """Parses a dump file like list of tags and returns a list of IRFiles uri=http://... tag=value1 tag2=value tag=value2 uri=http://... ... """ stations = [] station = None for l in data.split(b"\n"): if not l: continue key = l.split(b"=")[0] value = l.split(b"=", 1)[1] key = decode(key) value = decode(value) if key == "uri": if station: stations.append(station) station = IRFile(value) continue san = list(sanitize_tags({key: value}, stream=True).items()) if not san: continue key, value = san[0] if key == "~listenerpeak": key = "~#listenerpeak" value = int(value) if not station: continue if isinstance(value, str): if value not in station.list(key): station.add(key, value) else: station[key] = value if station: stations.append(station) return stations class AddNewStation(GetStringDialog): def __init__(self, parent): super().__init__( parent, _("New Station"), _("Enter the location of an Internet radio station:"), button_label=_("_Add"), button_icon=Icons.LIST_ADD) def _verify_clipboard(self, text): # try to extract a URI from the clipboard for line in text.splitlines(): line = line.strip() if uri_is_valid(line): return line class GenreFilter: STAR = ["genre", "organization"] # This probably needs improvements GENRES = { "electronic": ( _("Electronic"), "|(electr,house,techno,trance,/trip.?hop/,&(drum,n,bass),chill," "dnb,minimal,/down(beat|tempo)/,&(dub,step))"), "rap": (_("Hip Hop / Rap"), "|(&(hip,hop),rap)"), "oldies": (_("Oldies"), r"|(/[2-9]0\S?s/,oldies)"), "r&b": (_("R&B"), r"/r(\&|n)b/"), "japanese": (_("Japanese"), "|(anime,jpop,japan,jrock)"), "indian": (_("Indian"), "|(bollywood,hindi,indian,bhangra)"), "religious": ( _("Religious"), "|(religious,christian,bible,gospel,spiritual,islam)"), "charts": (_("Charts"), "|(charts,hits,top)"), "turkish": (_("Turkish"), "|(turkish,turkce)"), "reggae": (_("Reggae / Dancehall"), r"|(/reggae([^\w]|$)/,dancehall)"), "latin": (_("Latin"), "|(latin,salsa)"), "college": (_("College Radio"), "|(college,campus)"), "talk_news": (_("Talk / News"), "|(news,talk)"), "ambient": (_("Ambient"), "|(ambient,easy)"), "jazz": (_("Jazz"), "|(jazz,swing)"), "classical": (_("Classical"), "classic"), "pop": (_("Pop"), None), "alternative": (_("Alternative"), None), "metal": (_("Metal"), None), "country": (_("Country"), None), "news": (_("News"), None), "schlager": (_("Schlager"), None), "funk": (_("Funk"), None), "indie": (_("Indie"), None), "blues": (_("Blues"), None), "soul": (_("Soul"), None), "lounge": (_("Lounge"), None), "punk": (_("Punk"), None), "reggaeton": (_("Reggaeton"), None), "slavic": ( _("Slavic"), "|(narodna,albanian,manele,shqip,kosova)"), "greek": (_("Greek"), None), "gothic": (_("Gothic"), None), "rock": (_("Rock"), None), } # parsing all above takes 350ms on an atom, so only generate when needed __CACHE: Dict[str, Query] = {} def keys(self): return self.GENRES.keys() def query(self, key): if key not in self.__CACHE: text, filter_ = self.GENRES[key] if filter_ is None: filter_ = key self.__CACHE[key] = Query(filter_, star=self.STAR) return self.__CACHE[key] def text(self, key): return self.GENRES[key][0] class CloseButton(Gtk.Button): """Reimplementation of 3.10 close button for InfoBar.""" def __init__(self): image = Gtk.Image(visible=True, can_focus=False, icon_name="window-close-symbolic") super().__init__( visible=False, can_focus=True, image=image, relief=Gtk.ReliefStyle.NONE, valign=Gtk.Align.CENTER) ctx = self.get_style_context() ctx.add_class("raised") ctx.add_class("close") class QuestionBar(Gtk.InfoBar): """A widget which suggest to download the radio list if no radio stations are present. Connect to Gtk.InfoBar::response and check for RESPONSE_LOAD as response id. """ RESPONSE_LOAD = 1 def __init__(self): super().__init__() self.connect("response", self.__response) self.set_message_type(Gtk.MessageType.QUESTION) label = Gtk.Label(label=_( "Would you like to load a list of popular radio stations?")) label.set_line_wrap(True) label.show() content = self.get_content_area() content.add(label) self.add_button(_("_Load Stations"), self.RESPONSE_LOAD) self.set_show_close_button(True) def __response(self, bar, response_id): if response_id == Gtk.ResponseType.CLOSE: bar.hide() class InternetRadio(Browser, util.InstanceTracker): __stations = None __fav_stations = None __librarian = None __filter = None name = _("Internet Radio") accelerated_name = _("_Internet Radio") keys = ["InternetRadio"] priority = 16 uses_main_library = False headers = "title artist ~people grouping genre website ~format " \ "channel-mode".split() TYPE, ICON_NAME, KEY, NAME = range(4) TYPE_FILTER, TYPE_ALL, TYPE_FAV, TYPE_SEP, TYPE_NOCAT = range(5) STAR = ["artist", "title", "website", "genre", "comment"] @classmethod def _init(klass, library): klass.__librarian = library.librarian klass.__stations = SongLibrary("iradio-remote") klass.__stations.load(STATIONS_ALL) klass.__fav_stations = SongLibrary("iradio") klass.__fav_stations.load(STATIONS_FAV) klass.filters = GenreFilter() @classmethod def _destroy(klass): if klass.__stations.dirty: klass.__stations.save() klass.__stations.destroy() klass.__stations = None if klass.__fav_stations.dirty: klass.__fav_stations.save() klass.__fav_stations.destroy() klass.__fav_stations = None klass.__librarian = None klass.filters = None def finalize(self, restored): if not restored: # Select "All Stations" by default def sel_all(row): return row[self.TYPE] == self.TYPE_ALL self.view.select_by_func(sel_all, one=True) def __inhibit(self): self.view.get_selection().handler_block(self.__changed_sig) def __uninhibit(self): self.view.get_selection().handler_unblock(self.__changed_sig) def __destroy(self, *args): if not self.instances(): self._destroy() def __init__(self, library, station_list_url: str = STATION_LIST_URL): super().__init__(spacing=12) self.station_list_url = station_list_url self.set_orientation(Gtk.Orientation.VERTICAL) if not self.instances(): self._init(library) self._register_instance() self.connect('destroy', self.__destroy) completion = LibraryTagCompletion(self.__stations) self.accelerators = Gtk.AccelGroup() self.__searchbar = search = SearchBarBox(completion=completion, accel_group=self.accelerators) search.connect('query-changed', self.__filter_changed) def focus(widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() search.connect('focus-out', focus) # treeview scrolled_window = ScrolledWindow() scrolled_window.show() scrolled_window.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.show() view.set_headers_visible(False) scrolled_window.set_policy( Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(view) model = Gtk.ListStore(int, str, str, str) model.append(row=[self.TYPE_ALL, Icons.FOLDER, "__all", _("All Stations")]) model.append(row=[self.TYPE_SEP, Icons.FOLDER, "", ""]) # Translators: Favorite radio stations model.append(row=[self.TYPE_FAV, Icons.FOLDER, "__fav", _("Favorites")]) model.append(row=[self.TYPE_SEP, Icons.FOLDER, "", ""]) filters = self.filters for text, k in sorted([(filters.text(k), k) for k in filters.keys()]): model.append(row=[self.TYPE_FILTER, Icons.EDIT_FIND, k, text]) model.append(row=[self.TYPE_NOCAT, Icons.FOLDER, "nocat", _("No Category")]) def separator(model, iter, data): return model[iter][self.TYPE] == self.TYPE_SEP view.set_row_separator_func(separator, None) def search_func(model, column, key, iter, data): return key.lower() not in model[iter][column].lower() view.set_search_column(self.NAME) view.set_search_equal_func(search_func, None) column = Gtk.TreeViewColumn("genres") column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) renderpb = Gtk.CellRendererPixbuf() renderpb.props.xpad = 3 column.pack_start(renderpb, False) column.add_attribute(renderpb, "icon-name", self.ICON_NAME) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) view.append_column(column) column.pack_start(render, True) column.add_attribute(render, "text", self.NAME) view.set_model(model) # selection selection = view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self.__changed_sig = connect_destroy(selection, 'changed', util.DeferredSignal(lambda x: self.activate())) box = Gtk.HBox(spacing=6) box.pack_start(search, True, True, 0) self._searchbox = Align(box, left=0, right=6, top=0) self._searchbox.show_all() def qbar_response(infobar, response_id): if response_id == infobar.RESPONSE_LOAD: self.__update() self.qbar = QuestionBar() self.qbar.connect("response", qbar_response) if not self.has_stations: self.qbar.show() pane = qltk.ConfigRHPaned("browsers", "internetradio_pos", 0.4) vb = Gtk.VBox(spacing=0) vb.pack_start(scrolled_window, True, True, 0) fb = Gtk.FlowBox() fb.set_column_spacing(3) fb.set_homogeneous(True) new_station = Button(_(u"_Add Station…"), Icons.LIST_ADD) new_station.connect('clicked', self.__add) self._update_button = Button(_("_Update Stations"), Icons.VIEW_REFRESH) self._update_button.connect('clicked', self.__update) fb.insert(new_station, 1) fb.insert(self._update_button, 2) vb.pack_end(Align(fb, left=3), False, False, 3) pane.pack1(vb, resize=False, shrink=False) pane.show_all() songbox = Gtk.VBox(spacing=6) songbox.pack_start(self._searchbox, False, True, 0) self._songpane_container = Gtk.VBox() songbox.pack_start(self._songpane_container, True, True, 0) songbox.pack_start(self.qbar, False, True, 0) songbox.show_all() pane.pack2(songbox, resize=True, shrink=False) self.pack_start(pane, True, True, 0) self.show() @property def has_stations(self) -> bool: return bool(len(self.__stations or []) + len(self.__fav_stations or [])) def pack(self, songpane): container = Gtk.VBox() container.add(self) self._songpane_container.add(songpane) return container def unpack(self, container, songpane): self._songpane_container.remove(songpane) container.remove(self) def __update(self, *args): self.qbar.hide() copool.add(download_taglist, self.station_list_url, self.__update_done, cofuncid="radio-load", funcid="radio-load") def __update_done(self, stations): if not stations: print_w("Loading remote station list failed.") return # filter stations based on quality, listenercount def filter_stations(station): peak = station.get("~#listenerpeak", 0) if peak < 10: return False aac = "AAC" in station("~format") bitrate = station("~#bitrate", 50) if (aac and bitrate < 40) or (not aac and bitrate < 60): return False return True stations = filter(filter_stations, stations) # group them based on the title groups = {} for s in stations: key = s("~title~artist") groups.setdefault(key, []).append(s) # keep at most 2 URLs for each group stations = [] for key, sub in groups.items(): sub.sort(key=lambda s: s.get("~#listenerpeak", 0), reverse=True) stations.extend(sub[:2]) # only keep the ones in at least one category all_ = [self.filters.query(k) for k in self.filters.keys()] assert all_ anycat_filter = reduce(lambda x, y: x | y, all_) stations = list(filter(anycat_filter.search, stations)) # remove listenerpeak for s in stations: s.pop("~#listenerpeak", None) # update the libraries stations = dict(((s.key, s) for s in stations)) # don't add ones that are in the fav list for fav in self.__fav_stations.keys(): stations.pop(fav, None) # separate o, n = set(self.__stations.keys()), set(stations) to_add, to_change, to_remove = n - o, o & n, o - n del o, n # migrate stats to_change = [stations.pop(k) for k in to_change] for new in to_change: old = self.__stations[new.key] # clear everything except stats AudioFile.reload(old) # add new metadata except stats for k in (x for x in new.keys() if x not in MIGRATE): old[k] = new[k] to_add = [stations.pop(k) for k in to_add] to_remove = [self.__stations[k] for k in to_remove] self.__stations.remove(to_remove) self.__stations.changed(to_change) self.__stations.add(to_add) def __filter_changed(self, bar, text, restore=False): self.__filter = Query(text, self.STAR) if not restore: self.activate() def __get_selected_libraries(self): """Returns the libraries to search in depending on the filter selection""" selection = self.view.get_selection() model, rows = selection.get_selected_rows() types = [model[row][self.TYPE] for row in rows] libs = [self.__fav_stations] if types != [self.TYPE_FAV]: libs.append(self.__stations) return libs def __get_selection_filter(self): """Returns a filter object for the current selection or None if nothing should be filtered""" selection = self.view.get_selection() model, rows = selection.get_selected_rows() filter_ = None for row in rows: type_ = model[row][self.TYPE] if type_ == self.TYPE_FILTER: key = model[row][self.KEY] current_filter = self.filters.query(key) if current_filter: if filter_: filter_ |= current_filter else: filter_ = current_filter elif type_ == self.TYPE_NOCAT: # if notcat is selected, combine all filters, negate and merge all_ = [self.filters.query(k) for k in self.filters.keys()] nocat_filter = all_ and -reduce(lambda x, y: x | y, all_) if nocat_filter: if filter_: filter_ |= nocat_filter else: filter_ = nocat_filter elif type_ == self.TYPE_ALL: filter_ = None break return filter_ def unfilter(self): self.filter_text("") def __add_fav(self, songs): songs = [s for s in songs if s in self.__stations] type(self).__librarian.move( songs, self.__stations, self.__fav_stations) def __remove_fav(self, songs): songs = [s for s in songs if s in self.__fav_stations] type(self).__librarian.move( songs, self.__fav_stations, self.__stations) def __add(self, button): parent = qltk.get_top_parent(self) uri = (AddNewStation(parent).run(clipboard=True) or "").strip() if uri != "": self.__add_stations_from(uri) def __add_stations(self, irfs: Collection[IRFile], uri: str) -> None: print_d(f"Got {len(irfs)} station(s) from {uri}") assert self.__fav_stations is not None if not irfs: msg = ErrorMessage( self, _("No stations found"), _("No Internet radio stations were found at %s.") % util.escape(uri)) msg.run() return fav_uris = {af("~uri") for af in self.__fav_stations} irfs = {af for af in irfs if af("~uri") not in fav_uris} if irfs: print_d(f"Adding {irfs} to favourites") self.__fav_stations.add(irfs) else: message = WarningMessage( self, _("Nothing to add"), _("All stations listed are already in your library.")) message.run() def __add_stations_from(self, uri: str) -> None: def on_done(irfs: Iterable[IRFile], uri: str): GLib.idle_add(self.__add_stations, irfs, uri) print_d("Quitting thread") Thread(target=_get_stations_from, args=(uri, on_done)).start() def Menu(self, songs, library, items): in_fav = False in_all = False for song in songs: if song in self.__fav_stations: in_fav = True elif song in self.__stations: in_all = True if in_fav and in_all: break iradio_items = [] button = MenuItem(_("Add to Favorites"), Icons.LIST_ADD) button.set_sensitive(in_all) connect_obj(button, 'activate', self.__add_fav, songs) iradio_items.append(button) button = MenuItem(_("Remove from Favorites"), Icons.LIST_REMOVE) button.set_sensitive(in_fav) connect_obj(button, 'activate', self.__remove_fav, songs) iradio_items.append(button) items.append(iradio_items) menu = SongsMenu(self.__librarian, songs, playlists=False, remove=True, queue=False, items=items) return menu def restore(self): text = config.gettext("browsers", "query_text") self.__searchbar.set_text(text) if Query(text).is_parsable: self.__filter_changed(self.__searchbar, text, restore=True) keys = config.get("browsers", "radio").splitlines() def select_func(row): return row[self.TYPE] != self.TYPE_SEP and row[self.KEY] in keys self.__inhibit() view = self.view if not view.select_by_func(select_func): for row in view.get_model(): if row[self.TYPE] == self.TYPE_FAV: view.set_cursor(row.path) break self.__uninhibit() def __get_filter(self): filter_ = self.__get_selection_filter() text_filter = self.__filter or Query("") if filter_: filter_ &= text_filter else: filter_ = text_filter return filter_ def can_filter_text(self): return True def filter_text(self, text): self.__searchbar.set_text(text) if Query(text).is_parsable: self.__filter_changed(self.__searchbar, text) self.activate() def get_filter_text(self): return self.__searchbar.get_text() def activate(self): filter_ = self.__get_filter() libs = self.__get_selected_libraries() songs = filter_.filter(itertools.chain(*libs)) self.songs_selected(songs) def active_filter(self, song): for lib in self.__get_selected_libraries(): if song in lib: break else: return False filter_ = self.__get_filter() if filter_: return filter_.search(song) return True def save(self): text = self.__searchbar.get_text() config.settext("browsers", "query_text", text) selection = self.view.get_selection() model, rows = selection.get_selected_rows() names = filter(None, [model[row][self.KEY] for row in rows]) config.set("browsers", "radio", "\n".join(names)) def scroll(self, song): # nothing we care about if song not in self.__stations and song not in self.__fav_stations: return path = None for row in self.view.get_model(): if row[self.TYPE] == self.TYPE_FILTER: if self.filters.query(row[self.KEY]).search(song): path = row.path break else: # in case nothing matches, select all path = (0,) self.view.set_cursor(path) self.view.scroll_to_cell(path, use_align=True, row_align=0.5) def status_text(self, count: int, time: Optional[str] = None) -> str: return numeric_phrase("%(count)d station", "%(count)d stations", count, 'count') from quodlibet import app if not app.player or app.player.can_play_uri("http://"): browsers = [InternetRadio] else: browsers = [] �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/�����������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017127� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/__init__.py������������������������������������������������0000664�0001750�0001750�00000000530�14035600052�021234� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .main import PanedBrowser browsers = [PanedBrowser] ������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295006.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/main.py����������������������������������������������������0000644�0001750�0001750�00000025121�14324322336�020431� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2008 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009,2010 Steven Robertson # 2009-2013 Christoph Reiter # 2011-2022 Nick Boultbee # 2017 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib from quodlibet import app from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.browsers import Browser from quodlibet.formats import PEOPLE from quodlibet.qltk import is_accel from quodlibet.qltk.songlist import SongList from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.x import ScrolledWindow, Align from quodlibet.util.library import background_filter from quodlibet.util import connect_destroy from quodlibet.qltk.paned import ConfigMultiRHPaned from .prefs import PreferencesButton, ColumnMode from .util import get_headers from .pane import Pane class PanedBrowser(Browser, util.InstanceTracker): """A Browser enabling "drilling down" of tracks by successive selections in multiple tag pattern panes (e.g. Genre / People / Album ). It presents available values (and track counts) for each pane's tag """ name = _("Paned Browser") accelerated_name = _("_Paned Browser") keys = ["Paned", "PanedBrowser"] priority = 3 def pack(self, songpane): container = Gtk.HBox() self.show() container.pack_start(self, True, True, 0) self.main_box.pack2(songpane, True, False) return container def unpack(self, container, songpane): self.main_box.remove(songpane) container.remove(self) @classmethod def set_all_column_mode(klass, value): for browser in klass.instances(): browser.set_column_mode(value) @classmethod def set_all_panes(klass): for browser in klass.instances(): browser.refresh_panes() browser.fill_panes() def __init__(self, library): super().__init__() self._register_instance() self._filter = lambda s: False self._library = library self.set_spacing(6) self.set_orientation(Gtk.Orientation.VERTICAL) completion = LibraryTagCompletion(library.librarian) self.accelerators = Gtk.AccelGroup() sbb = SearchBarBox(completion=completion, accel_group=self.accelerators) sbb.connect('query-changed', self.__text_parse) sbb.connect('focus-out', self.__focus) sbb.connect('key-press-event', self.__sb_key_pressed) self._sb_box = sbb align = Align(sbb, left=6, right=6, top=0) self.pack_start(align, False, True, 0) keyval, mod = Gtk.accelerator_parse("<Primary>Home") self.accelerators.connect(keyval, mod, 0, self.__select_all) select = Gtk.Button(label=_("Select _All"), use_underline=True) select.connect('clicked', self.__select_all) sbb.pack_start(select, False, True, 0) prefs = PreferencesButton(self) sbb.pack_start(prefs, False, True, 0) connect_destroy(library, 'changed', self.__changed) connect_destroy(library, 'added', self.__added) connect_destroy(library, 'removed', self.__removed) self.connect('destroy', self.__destroy) # contains the panes and the song list self.main_box = qltk.ConfigRPaned("browsers", "panedbrowser_pos", 0.4) self.pack_start(self.main_box, True, True, 0) self.multi_paned = ConfigMultiRHPaned("browsers", "panedbrowser_pane_widths") self.refresh_panes() for child in self.get_children(): child.show_all() def __destroy(self, *args): del self._sb_box def set_column_mode(self, mode): hor = Gtk.Orientation.HORIZONTAL ver = Gtk.Orientation.VERTICAL if mode == ColumnMode.WIDE: self.main_box.props.orientation = hor self.multi_paned.change_orientation(horizontal=False) elif mode == ColumnMode.COLUMNAR: self.main_box.props.orientation = hor self.multi_paned.change_orientation(horizontal=True) else: # ColumnMode.SMALL self.main_box.props.orientation = ver self.multi_paned.change_orientation(horizontal=True) def _get_text(self): return self._sb_box.get_text() def _set_text(self, text): self._sb_box.set_text(text) def __focus(self, widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() def __text_parse(self, bar, text): self.activate() def __sb_key_pressed(self, entry, event): if (is_accel(event, "<Primary>Return") or is_accel(event, "<Primary>KP_Enter")): songs = app.window.songlist.get_songs() limit = config.getint("browsers", "searchbar_enqueue_limit") app.window.enqueue(songs, limit) return True return False def filter_text(self, text): self._set_text(text) self.activate() def get_filter_text(self): return self._get_text() def __select_all(self, *args): self._panes[-1].inhibit() for pane in self._panes: pane.set_selected(None, True) self._panes[-1].uninhibit() self._panes[-1].get_selection().emit('changed') def __added(self, library, songs): songs = list(filter(self._filter, songs)) for pane in self._panes: pane.add(songs) songs = list(filter(pane.matches, songs)) def __removed(self, library, songs, remove_if_empty=True): songs = list(filter(self._filter, songs)) for pane in self._panes: pane.remove(songs, remove_if_empty) def __changed(self, library, songs): self.__removed(library, songs, False) self.__added(library, songs) self.__removed(library, []) def active_filter(self, song): # check with the search filter if not self._filter(song): return False # check if the selection is right in every pane for pane in self._panes: if not pane.matches(song): return False return True def activate(self): star = dict.fromkeys(SongList.star) star.update(self.__star) query = self._sb_box.get_query(star.keys()) if query.is_parsable: self._filter = query.search songs = list(filter(self._filter, self._library)) bg = background_filter() if bg: songs = list(filter(bg, songs)) self._panes[0].fill(songs) def scroll(self, song): for pane in self._panes: pane.scroll(song) def refresh_panes(self): self.multi_paned.destroy() # Fill in the pane list. The last pane reports back to us. self._panes = [self] for header in reversed(get_headers()): pane = Pane(self._library, header, self._panes[0]) pane.connect('row-activated', lambda *x: self.songs_activated()) self._panes.insert(0, pane) self._panes.pop() # remove self # Put the panes in scrollable windows sws = [] for pane in self._panes: sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(pane) sws.append(sw) self.multi_paned.set_widgets(sws) self.multi_paned.show_all() self.main_box.pack1(self.multi_paned.get_paned(), True, False) self.__star = {} for p in self._panes: tags = [t for t in p.tags if not t.startswith("~#")] self.__star.update(dict.fromkeys(tags)) self.set_column_mode(config.getint("browsers", "pane_mode", ColumnMode.SMALL)) def fill_panes(self): self._panes[-1].inhibit() self.activate() self._panes[-1].uninhibit() def make_pane_widths_equal(self): self.multi_paned.make_pane_widths_equal() def __get_filter_pane(self, key): """Get the best pane for filtering etc.""" candidates = [] for pane in self._panes: if (key in pane.tags or (key in PEOPLE and "~people" in pane.tags)): candidates.append((len(pane.tags), pane)) candidates.sort() return (candidates and candidates[0][1]) or None def can_filter_tag(self, tag): return (self.__get_filter_pane(tag) is not None) def can_filter_text(self): return True def filter(self, tag, values): filter_pane = self.__get_filter_pane(tag) for pane in self._panes: if pane is filter_pane: filter_pane.set_selected_by_tag(tag, values, True) filter_pane.grab_focus() return pane.set_selected([None], True) def unfilter(self): self._panes[-1].inhibit() for pane in self._panes: pane.set_selected(None, True) self._panes[-1].uninhibit() self._set_text("") self.activate() def list(self, key): filter_pane = self.__get_filter_pane(key) if filter_pane is None: return super().list(key) for pane in self._panes: if pane is filter_pane: return list(filter_pane.list(key)) pane.set_selected(None, True) return [] def save(self): config.settext("browsers", "query_text", self._get_text()) selected = [] for pane in self._panes: selected.append(pane.get_restore_string()) to_save = u"\n".join(selected) config.settext("browsers", "pane_selection", to_save) def restore(self): try: text = config.gettext("browsers", "query_text") except config.Error: pass else: self._set_text(text) selected = config.gettext("browsers", "pane_selection") if not selected: return for pane, string in zip(self._panes, selected.split(u"\n")): pane.parse_restore_string(string) def finalize(self, restored): config.settext("browsers", "query_text", u"") def fill(self, songs): GLib.idle_add(self.songs_selected, list(songs)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/models.py��������������������������������������������������0000644�0001750�0001750�00000026151�14327505043�020775� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2020-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import re from typing import Tuple, Text from quodlibet.browsers.paned.util import PaneConfig from quodlibet import _ from quodlibet import util from quodlibet.qltk.models import ObjectStore from quodlibet.util.collection import Collection class BaseEntry(Collection): def __init__(self, key=None, songs=None): super().__init__() self.songs = set(songs or []) self.key = key # not used for sorting! self.sort = tuple() def all_have(self, tag, value): """Check if all songs have tag `tag` set to `value`""" if tag[:2] == "~#" and "~" not in tag[2:]: for song in self.songs: if song(tag) != value: return False else: for song in self.songs: if value not in song.list(tag): return False return True def get_count_text(self, config): raise NotImplementedError def get_text(self, config): """Returns (is_markup, text)""" raise NotImplementedError def contains_text(self, text): """Used for the inline search""" raise NotImplementedError class SongsEntry(BaseEntry): def __init__(self, key, sort, songs=None): super().__init__(key, songs) self.sort = sort # value used for sorting def get_count_text(self, config): return config.format_display(self) def get_text(self, config: PaneConfig) -> Tuple[bool, Text]: if config.has_markup: return True, self.key else: return False, self.key def contains_text(self, text): return text.lower() in self.key.lower() def contains_song(self, song): return song in self.songs def __repr__(self): return "<%s key=%r songs=%d>" % ( type(self).__name__, self.key, len(self.songs)) class UnknownEntry(SongsEntry): def __init__(self, songs=None): super().__init__("", tuple(), songs) def get_text(self, config): return True, util.bold(_("Unknown")) def contains_text(self, text): return False def __repr__(self): return "<%s songs=%d>" % (type(self).__name__, len(self.songs)) class AllEntry(BaseEntry): def __init__(self): super().__init__() def get_count_text(self, config): return u"" def get_text(self, config): return True, util.bold(_("All")) def contains_text(self, text): return False def contains_song(self, song): return False def __repr__(self): return "<%s>" % (type(self).__name__,) class PaneModel(ObjectStore): def __init__(self, pattern_config): super().__init__() self.__sort_cache = {} # text to sort text cache self.__key_cache = {} # song to key cache self.config = pattern_config def get_format_keys(self, song): try: return self.__key_cache[song] except KeyError: # We filter out empty values, so Unknown can be "" self.__key_cache[song] = [v for v in self.config.format(song) if v[0]] return self.__key_cache[song] def __human_sort_key(self, text, reg=re.compile('<.*?>')): try: return self.__sort_cache[text], text except KeyError: # remove the markup so it doesn't affect the sort order if self.config.has_markup: text_stripped = reg.sub("", text) else: text_stripped = text self.__sort_cache[text] = util.human_sort_key(text_stripped) return self.__sort_cache[text], text def get_songs(self, paths): """Get all songs for the given paths (from a selection e.g.)""" s = set() if not paths: return s first_path = paths[0] if isinstance(self[first_path][0], AllEntry): for entry in self.itervalues(): s.update(entry.songs) else: for path in paths: s.update(self[path][0].songs) return s def get_keys(self, paths): return {self[p][0].key for p in paths} def remove_songs(self, songs, remove_if_empty): """Remove all songs from the entries. If remove_if_empty == True, entries with no songs will be removed. """ songs = set(songs) for song in songs: if song in self.__key_cache: del self.__key_cache[song] to_remove = [] for iter_, entry in self.iterrows(): if isinstance(entry, AllEntry): continue entry.songs -= songs entry.finalize() self.row_changed(self.get_path(iter_), iter_) if not entry.songs: to_remove.append(iter_) if not remove_if_empty: return # remove from cache and the model for iter_ in to_remove: try: key = self.get_value(iter_).key del(self.__sort_cache[key]) except KeyError: pass self.remove(iter_) if len(self) == 1 and isinstance(self[0][0], AllEntry): # only All is left.. clear everything self.clear() elif to_remove and len(self) == 2: # Only one entry + All -> remove All self.remove(self.get_iter_first()) def add_songs(self, songs): """Add new songs to the list, creating new rows""" collection = {} unknown = UnknownEntry() human_sort = self.__human_sort_key for song in songs: items = self.get_format_keys(song) if not items: unknown.songs.add(song) for key, sort in items: if key in collection: if sort and not collection[key][2]: # first actual sort key hsort = human_sort(sort) collection[key][0].sort = hsort collection[key] = (collection[key][0], hsort, True) collection[key][0].songs.add(song) else: # first key sets up sorting hsort = human_sort(sort) entry = SongsEntry(key, hsort) collection[key] = (entry, hsort, bool(sort)) entry.songs.add(song) items = sorted(collection.items(), key=lambda s: s[1][1], reverse=True) # fast path if not len(self): if unknown.songs: self.insert(0, [unknown]) entries = [] for key, (val, sort_key, srtp) in items: entries.append(val) self.insert_many(0, reversed(entries)) if len(self) > 1: self.insert(0, [AllEntry()]) return # insert all new songs key = None val = None sort_key = None for iter_, entry in self.iterrows(): if not isinstance(entry, SongsEntry): continue if key is None: if not items: break key, (val, sort_key, srtp) = items.pop(-1) if key == entry.key: # Display strings the same entry.songs |= val.songs entry.finalize() self.row_changed(self.get_path(iter_), iter_) key = None elif sort_key < entry.sort: self.insert_before(iter_, row=[val]) key = None # the last one failed, add it again if key: items.append((key, (val, sort_key, srtp))) # insert the left over songs if items: entries = [] for key, (val, srt, srtp) in items: entries.append(val) if isinstance(self[-1][0], UnknownEntry): self.insert_many(len(self) - 1, entries) else: self.append_many(entries) # check if All needs to be inserted if len(self) > 1 and not isinstance(self[0][0], AllEntry): self.insert(0, [AllEntry()]) # check if Unknown needs to be inserted or updated if unknown.songs: last_row = self[-1] entry = last_row[0] if isinstance(entry, UnknownEntry): entry.songs |= unknown.songs entry.finalize() self.row_changed(last_row.path, last_row.iter) else: self.append(row=[unknown]) def matches(self, paths, song): """If the song is included in the selection defined by the paths. paths has to be sorted. """ if not paths: return False # All included if isinstance(self[paths[0]][0], AllEntry): return True keys = self.get_format_keys(song) # empty key -> unknown if not keys and isinstance(self[paths[-1]][0], UnknownEntry): return True for path in paths: entry = self.get_value(self.get_iter(path)) for key in keys: if entry.key == (key[0] if isinstance(key, tuple) else key): return True return False def list(self, tag): tags = self.config.tags # fast path, use the keys since they are unique and only depend # on the tag in question. if tag in tags and len(tags) == 1: return {r.key for r in self.itervalues() if not isinstance(r, AllEntry)} # For patterns/tied tags we have to make sure that filtering for # that key will return only songs that all have the specified value values = set() for entry in self.itervalues(): if isinstance(entry, AllEntry): continue if not entry.key: # add unknown values.add("") else: for value in entry.list(tag): if value not in values and entry.all_have(tag, value): values.add(value) return values def get_keys_by_tag(self, tag, values): """List of keys for entries where all songs contain a tag with at least one value from values. """ tags = self.config.tags # Like with self.list we can select all matching keys if the tag # is our only tag if len(tags) == 1 and tag in tags: return [e.key for e in self.itervalues() if e.key in values] keys = [] for entry in self.itervalues(): if isinstance(entry, SongsEntry): for value in values: if entry.all_have(tag, value): keys.append(entry.key) break # add unknown if "" in values and isinstance(self[-1][0], UnknownEntry): keys.append("") return keys �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1655124463.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/pane.py����������������������������������������������������0000664�0001750�0001750�00000023605�14251630757�020447� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import operator from gi.repository import Gtk, Pango, Gdk from quodlibet import qltk from quodlibet.qltk.views import AllTreeView, TreeViewColumnButton from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.information import Information from quodlibet.qltk import is_accel from quodlibet.util import connect_obj from .models import PaneModel from .util import PaneConfig class Pane(AllTreeView): """Pane of the paned browser""" TARGET_INFO_QL = 1 TARGET_INFO_URI_LIST = 2 def __init__(self, library, prefs, next_=None): super().__init__() self.set_fixed_height_mode(True) self.config = PaneConfig(prefs) self.__next = next_ self.__restore_values = None self.__no_fill = 0 column = TreeViewColumnButton(title=self.config.title) def on_column_header_clicked(column, event): # In case the column header gets clicked select the "All" entry if event.button != Gdk.BUTTON_PRIMARY or \ event.type != Gdk.EventType.BUTTON_PRESS: return Gdk.EVENT_PROPAGATE self.set_selected([]) return Gdk.EVENT_STOP column.set_clickable(True) column.connect("button-press-event", on_column_header_clicked) column.set_use_markup(True) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(50) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(render, True) def text_cdf(column, cell, model, iter_, data): entry = model.get_value(iter_) is_markup, text = entry.get_text(self.config) if is_markup: cell.markup = text cell.set_property('markup', text) else: cell.markup = None cell.set_property('text', text) column.set_cell_data_func(render, text_cdf) render_count = Gtk.CellRendererText() render_count.set_property('xalign', 1.0) column.pack_start(render_count, False) def count_cdf(column, cell, model, iter_, data): entry = model.get_value(iter_) markup = entry.get_count_text(self.config) cell.markup = markup cell.set_property('markup', markup) column.set_cell_data_func(render_count, count_cdf) self.append_column(column) model = PaneModel(self.config) self.set_model(model) self.set_search_equal_func(self.__search_func, None) self.set_search_column(0) self.set_enable_search(True) selection = self.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self.__sig = self.connect( 'selection-changed', self.__selection_changed) s = self.connect('popup-menu', self.__popup_menu, library) connect_obj(self, 'destroy', self.disconnect, s) targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, self.TARGET_INFO_QL), ("text/uri-list", 0, self.TARGET_INFO_URI_LIST) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) self.connect("drag-data-get", self.__drag_data_get) self.connect("destroy", self.__destroy) librarian = library.librarian or library self.connect("key-press-event", self.__key_pressed, librarian) def __key_pressed(self, view, event, librarian): # if ctrl+a is pressed, intercept and select the All entry instead if is_accel(event, "<Primary>a"): self.set_selected([]) return True elif is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): qltk.enqueue(self.__get_selected_songs(sort=True)) return True elif is_accel(event, "<alt>Return"): songs = self.__get_selected_songs(sort=True) if songs: window = SongProperties(librarian, songs, parent=self) window.show() return True elif is_accel(event, "<Primary>I"): songs = self.__get_selected_songs(sort=True) if songs: window = Information(librarian, songs, self) window.show() return True return False def __repr__(self): return "<%s config=%r>" % (type(self).__name__, self.config) def parse_restore_string(self, config_value): assert isinstance(config_value, str) values = config_value.split("\t")[:-1] try: if int(values[0]): values[0] = None else: del values[0] except (ValueError, IndexError): pass self.__restore_values = values def get_restore_string(self): values = self.get_selected() # The first value tells us if All was selected all_ = None in values if all_: values.remove(None) all_ = str(int(bool(all_))) values = list(values) values.insert(0, all_) # The config lib strips all whitespace, # so add a bogus . at the end values.append(u".") return u"\t".join(values) @property def tags(self): """Tags this pane displays""" return self.config.tags def __destroy(self, *args): # needed for gc self.__next = None def __search_func(self, model, column, key, iter_, data): entry = model.get_value(iter_) return not entry.contains_text(key) def __drag_data_get(self, view, ctx, sel, tid, etime): songs = self.__get_selected_songs(sort=True) if tid == self.TARGET_INFO_QL: qltk.selection_set_songs(sel, songs) else: sel.set_uris([song("~uri") for song in songs]) def __popup_menu(self, view, library): songs = self.__get_selected_songs(sort=True) menu = SongsMenu(library, songs) menu.show_all() return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __selection_changed(self, *args): if self.__next: self.__next.fill(self.__get_selected_songs()) def add(self, songs): self.get_model().add_songs(songs) def remove(self, songs, remove_if_empty=True): self.inhibit() self.get_model().remove_songs(songs, remove_if_empty) self.uninhibit() def matches(self, song): model, paths = self.get_selection().get_selected_rows() # nothing == all if not paths: return True return model.matches(paths, song) def inhibit(self): """Inhibit selection change events and song propagation""" self.__no_fill += 1 self.handler_block(self.__sig) def uninhibit(self): """Uninhibit selection change events and song propagation""" self.handler_unblock(self.__sig) self.__no_fill -= 1 def fill(self, songs): # Restore the selection if self.__restore_values is not None: selected = self.__restore_values self.__restore_values = None else: selected = self.get_selected() model = self.get_model() # If previously all entries were selected or None: select All if not selected or len(model) == len(selected): selected = [None] self.inhibit() with self.without_model(): model.clear() model.add_songs(songs) self.set_selected(selected, jump=True) self.uninhibit() if self.__next and self.__no_fill == 0: self.__next.fill(self.__get_selected_songs()) def scroll(self, song): """Select and scroll to entry which contains song""" def select_func(row): entry = row[0] return entry.contains_song(song) self.select_by_func(select_func, one=True) def list(self, tag): return self.get_model().list(tag) def get_selected(self): """A list of keys for selected entries""" model, paths = self.get_selection().get_selected_rows() return model.get_keys(paths) def set_selected(self, values, jump=False, force_any=True): """Select entries with key in values jump -- scroll the the first selected entry any -- if nothing gets selected, select the first entry """ if self.get_model().is_empty(): return values = values or [] # If the selection is the same, change nothing if values != self.get_selected(): self.inhibit() self.get_selection().unselect_all() def select_func(row): entry = row[0] return entry.key in values self.select_by_func(select_func, scroll=jump) self.uninhibit() self.get_selection().emit('changed') if force_any and self.get_selection().count_selected_rows() == 0: self.set_cursor((0,)) def set_selected_by_tag(self, tag, values, *args, **kwargs): """Select the entries which songs all have one of the values for the given tag. """ pattern_values = self.get_model().get_keys_by_tag(tag, values) self.set_selected(pattern_values, *args, **kwargs) def __get_selected_songs(self, sort=False): model, paths = self.get_selection().get_selected_rows() songs = model.get_songs(paths) if sort: return sorted(songs, key=operator.attrgetter("sort_key")) return songs ���������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/prefs.py���������������������������������������������������0000644�0001750�0001750�00000021665�14327505043�020636� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2015 Nick Boultbee # 2017 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config from quodlibet import util from quodlibet import qltk from quodlibet import _ from quodlibet.qltk.views import BaseView from quodlibet.qltk.tagscombobox import TagsComboBoxEntry from quodlibet.qltk.x import SymbolicIconImage, MenuItem, Button from quodlibet.qltk import Icons from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.util import connect_obj from .util import get_headers, save_headers @util.enum class ColumnMode(int): SMALL = 0 WIDE = 1 COLUMNAR = 2 class ColumnModeSelection(Gtk.VBox): def __init__(self, browser): super().__init__(spacing=6) self.browser = browser self.buttons = [] group = None mode_label = { ColumnMode.SMALL: _("Small"), ColumnMode.WIDE: _("Wide"), ColumnMode.COLUMNAR: _("Columnar"), } for mode in ColumnMode.values: lbl = mode_label[ColumnMode.value_of(mode)] group = Gtk.RadioButton(group=group, label=lbl) if mode == config.getint("browsers", "pane_mode", ColumnMode.SMALL): group.set_active(True) self.pack_start(group, False, True, 0) self.buttons.append(group) # Connect to signal after the correct radio button has been # selected for button in self.buttons: button.connect('toggled', self.toggled) def toggled(self, button): selected_mode = ColumnMode.SMALL if self.buttons[1].get_active(): selected_mode = ColumnMode.WIDE if self.buttons[2].get_active(): selected_mode = ColumnMode.COLUMNAR config.set("browsers", "pane_mode", int(selected_mode)) self.browser.set_all_column_mode(selected_mode) class PatternEditor(Gtk.VBox): PRESETS = [ ["genre", "~people", "album"], ["~people", "album"], ] COMPLETION = ["genre", "grouping", "~people", "artist", "album", "~year", "~rating"] _COMPLEX_PATTERN_EXAMPLE = "<~year|[b]<~year>[/b]|[i]unknown year[/i]>" def __init__(self): super().__init__(spacing=6) self.__headers = headers = {} buttons = [] group = None for tags in self.PRESETS: tied = "~" + "~".join(tags) group = Gtk.RadioButton(group=group, label="_" + util.tag(tied), use_underline=True) headers[group] = tags buttons.append(group) group = Gtk.RadioButton(group=group, label=_("_Custom"), use_underline=True) self.__custom = group headers[group] = [] buttons.append(group) button_box = Gtk.HBox(spacing=6) self.__model = model = Gtk.ListStore(str) radio_box = Gtk.VBox(spacing=6) for button in buttons: radio_box.pack_start(button, False, True, 0) button.connect('toggled', self.__toggled, button_box, model) self.pack_start(radio_box, False, True, 0) tooltip = _("Tag pattern with optional markup e.g. <tt>composer</tt> or\n%s" % util.monospace(self._COMPLEX_PATTERN_EXAMPLE)) cb = TagsComboBoxEntry(self.COMPLETION, tooltip_markup=tooltip) view = BaseView(model=model) view.set_reorderable(True) view.set_headers_visible(False) ctrl_box = Gtk.VBox(spacing=6) add = Button(_("_Add"), Icons.LIST_ADD) ctrl_box.pack_start(add, False, True, 0) add.connect('clicked', self.__add, model, cb) remove = Button(_("_Remove"), Icons.LIST_REMOVE) ctrl_box.pack_start(remove, False, True, 0) remove.connect('clicked', self.__remove, view) selection = view.get_selection() selection.connect('changed', self.__selection_changed, remove) selection.emit('changed') sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) edit_box = Gtk.VBox(spacing=6) edit_box.pack_start(cb, False, True, 0) edit_box.pack_start(sw, True, True, 0) button_box.pack_start(edit_box, True, True, 0) button_box.pack_start(ctrl_box, False, True, 0) self.pack_start(button_box, True, True, 0) render = Gtk.CellRendererText() render.set_property("editable", True) def edited_cb(render, path, text, model): model[path][0] = text render.connect("edited", edited_cb, model) column = Gtk.TreeViewColumn(None, render, text=0) view.append_column(column) @property def headers(self): for button in self.__headers.keys(): if button.get_active(): if button == self.__custom: model_headers = [row[0] for row in self.__model] self.__headers[self.__custom] = model_headers return self.__headers[button] @headers.setter def headers(self, new_headers): for button, headers in self.__headers.items(): if headers == new_headers: button.set_active(True) button.emit("toggled") break else: self.__headers[self.__custom] = new_headers self.__custom.set_active(True) def __selection_changed(self, selection, remove): remove.set_sensitive(bool(selection.get_selected()[1])) def __add(self, button, model, cb): if cb.tag: model.append(row=[cb.tag]) def __remove(self, button, view): view.remove_selection() def __toggled(self, button, edit_widget, model): tags = self.__headers[button] if tags: model.clear() for h in tags: model.append(row=[h]) edit_widget.set_sensitive( button.get_active() and button is self.__custom) class PreferencesButton(Gtk.HBox): def __init__(self, browser): super().__init__() self._menu = menu = Gtk.Menu() pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) def preferences_cb(menu_item): window = Preferences(browser) window.show() pref_item.connect("activate", preferences_cb) menu.append(pref_item) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) button.show() self.pack_start(button, True, True, 0) class Preferences(qltk.UniqueWindow): def __init__(self, browser): if self.is_not_unique(): return super().__init__() self.set_transient_for(qltk.get_top_parent(browser)) self.set_default_size(350, 300) self.set_border_width(12) self.set_title(_("Paned Browser Preferences")) vbox = Gtk.VBox(spacing=12) column_modes = ColumnModeSelection(browser) column_mode_frame = qltk.Frame(_("Column layout"), child=column_modes) editor = PatternEditor() editor.headers = get_headers() editor_frame = qltk.Frame(_("Column content"), child=editor) equal_width = ConfigCheckButton(_("Equal pane width"), "browsers", "equal_pane_width", populate=True) apply_ = Button(_("_Apply")) connect_obj(apply_, "clicked", self.__apply, editor, browser, False, equal_width) cancel = Button(_("_Cancel")) cancel.connect("clicked", lambda x: self.destroy()) box = Gtk.HButtonBox() box.set_spacing(6) box.set_layout(Gtk.ButtonBoxStyle.EDGE) box.pack_start(equal_width, True, True, 0) box.pack_start(apply_, False, False, 0) self.use_header_bar() if not self.has_close_button(): box.pack_start(cancel, True, True, 0) vbox.pack_start(column_mode_frame, False, False, 0) vbox.pack_start(editor_frame, True, True, 0) vbox.pack_start(box, False, True, 0) self.add(vbox) cancel.grab_focus() self.get_child().show_all() def __apply(self, editor, browser, close, equal_width): if editor.headers != get_headers(): save_headers(editor.headers) browser.set_all_panes() if equal_width.get_active(): browser.make_pane_widths_equal() if close: self.destroy() ���������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1677336198.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/paned/util.py����������������������������������������������������0000664�0001750�0001750�00000007152�14376417206�020500� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2020 Nick Boultbee # 2021 Jej@github # # 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 2 of the License, or # (at your option) any later version. import re from typing import Tuple, Text, List from quodlibet.formats import TIME_TAGS from quodlibet import config from quodlibet import util from quodlibet.formats import AudioFile from quodlibet.pattern import XMLFromMarkupPattern as XMLFromPattern from quodlibet.util.string.date import format_date class PaneConfig: """Row pattern format: 'categorize_pattern:display_pattern' * display_pattern is optional (fallback: ~#tracks) * patterns, tied and normal tags. * display patterns can have function prefixes for numerical tags. * ':' has to be escaped ('\\:') TODO: sort pattern, filter query """ def __init__(self, row_pattern): parts = [p.replace(r"\:", ":") for p in (re.split(r"(?<!\\):", row_pattern))] is_numeric = lambda s: s[:2] == "~#" and "~" not in s[2:] is_pattern = lambda s: '<' in s f_round = lambda s: (isinstance(s, float) and "%.2f" % s) or s def is_date(s): return s in TIME_TAGS disp = parts[1] if len( parts) >= 2 else r"[i][span alpha='40%']<~#tracks>[/span][/i]" cat = parts[0] if is_pattern(cat): title = util.pattern(cat, esc=True, markup=True) try: pc = XMLFromPattern(cat) except ValueError: pc = XMLFromPattern("") tags = pc.tags format = pc.format_list has_markup = True else: title = util.tag(cat) tags = util.tagsplit(cat) has_markup = False if is_date(cat): def format(song: AudioFile) -> List[Tuple[Text, Text]]: fmt = config.gettext("settings", "datecolumn_timestamp_format") date_str = format_date(song(cat), fmt) return [(date_str, date_str)] elif is_numeric(cat): def format(song: AudioFile) -> List[Tuple[Text, Text]]: v = str(f_round(song(cat))) return [(v, v)] else: def format(song: AudioFile) -> List[Tuple[Text, Text]]: return song.list_separate(cat) if is_pattern(disp): try: pd = XMLFromPattern(disp) except ValueError: pd = XMLFromPattern("") format_display = pd.format else: if is_numeric(disp): format_display = lambda coll: str(f_round(coll(disp))) else: format_display = lambda coll: util.escape(coll.comma(disp)) self.title = title self.tags = set(tags) self.format = format self.format_display = format_display self.has_markup = has_markup def __repr__(self): return "<%s title=%r tags=%r>" % ( self.__class__.__name__, self.title, self.tags) def get_headers(): # QL <= 2.1 saved the headers tab-separated, but had a space-separated # default value, so check for that. headers = config.get("browsers", "panes") if headers == "~people album": return headers.split() else: return headers.split("\t") def save_headers(headers): headers = "\t".join(headers) config.set("browsers", "panes", headers) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/�������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020064� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/__init__.py��������������������������������������������0000664�0001750�0001750�00000000534�14035600052�022175� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from .main import PlaylistsBrowser browsers = [PlaylistsBrowser] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666907943.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/main.py������������������������������������������������0000644�0001750�0001750�00000066170�14326577447�021420� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2011-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from typing import Optional, Tuple from gi.repository import Gtk, GLib, Pango, Gdk import quodlibet from quodlibet import _ from quodlibet import config from quodlibet import qltk from quodlibet.browsers import Browser from quodlibet.browsers._base import DisplayPatternMixin, BrowserError from quodlibet.browsers.playlists.prefs import Preferences, DEFAULT_PATTERN_TEXT from quodlibet.formats import AudioFile from quodlibet.library import SongFileLibrary from quodlibet.library.playlist import PlaylistLibrary from quodlibet.plugins.playlist import PLAYLIST_HANDLER from quodlibet.qltk import Icons from quodlibet.qltk.chooser import choose_files, create_chooser_filter from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.information import Information from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.models import ObjectStore, ObjectModelSort from quodlibet.qltk.msg import ConfirmationPrompt from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.songlist import SongList from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk.x import ScrolledWindow, Align, MenuItem, SymbolicIconImage from quodlibet.util import connect_obj from quodlibet.util.collection import Playlist from quodlibet.util.dprint import print_d, print_w from quodlibet.util.urllib import urlopen from .util import parse_m3u, parse_pls, _name_for, \ confirm_remove_playlist_dialog_invoke, \ confirm_dnd_playlist_dialog_invoke DND_QL, DND_URI_LIST, DND_MOZ_URL = range(3) class PlaylistsBrowser(Browser, DisplayPatternMixin): name = _("Playlists") accelerated_name = _("_Playlists") keys = ["Playlists", "PlaylistsBrowser"] priority = 2 replaygain_profiles = ["track"] __last_render = None _PATTERN_FN = os.path.join(quodlibet.get_user_dir(), "playlist_pattern") _DEFAULT_PATTERN_TEXT = DEFAULT_PATTERN_TEXT def __init__(self, songs_lib: SongFileLibrary, Confirmer=ConfirmationPrompt): super().__init__(spacing=3) self.songs_lib = songs_lib try: self.pl_lib: PlaylistLibrary = songs_lib.playlists except (AttributeError, TypeError): raise BrowserError(f"No playlist library available in {songs_lib!r}") self._lists = ObjectModelSort(model=ObjectStore()) self._lists.set_default_sort_func(ObjectStore._sort_on_value) model = self._lists.get_model() print_d(f"Reading playlists from library: {self.pl_lib}") for playlist in self.pl_lib: model.append(row=[playlist]) # this is instanced with the necessary gtkdialog-settings, and afterwards # its run-method is called to get a to-be-compared Gtk.ResponseType self.Confirmer = Confirmer self.set_orientation(Gtk.Orientation.VERTICAL) self.__render = self.__create_cell_renderer() self.__view = view = self.__create_playlists_view(self.__render) self.__embed_in_scrolledwin(view) self.__configure_buttons(songs_lib) self.__configure_dnd(view) self.__connect_signals(view) self._sb_box = self.__create_searchbar(songs_lib) self._rh_box = None self._main_box = self.__create_box() self.show_all() for child in self.get_children(): child.show_all() self._ids = [ self.pl_lib.connect('removed', self.__removed), self.pl_lib.connect('added', self.__added), self.pl_lib.connect('changed', self.__changed), ] print_d(f"Connected signals: {self._ids} from {self.pl_lib!r} for {self}") self.connect("destroy", self._destroy) def _destroy(self, _browser): for id_ in self._ids: self.pl_lib.disconnect(id_) del self._ids def pack(self, songpane): self._main_box.pack1(self, True, False) self._rh_box = rhbox = Gtk.VBox(spacing=6) align = Align(self._sb_box, left=0, right=6, top=0) rhbox.pack_start(align, False, True, 0) rhbox.pack_start(songpane, True, True, 0) self._main_box.pack2(rhbox, True, False) rhbox.show() align.show_all() return self._main_box def unpack(self, container, songpane): self._rh_box.remove(songpane) container.remove(self._rh_box) container.remove(self) @classmethod def init(klass, library): klass.load_pattern() def playlists(self): return [row[0] for row in self._lists] def changed(self, playlist, refresh=True): current = self._selected_playlist() for row in self._lists: if row[0] is playlist: if refresh: # Changes affect aggregate caches etc print_d(f"Refreshing view in {self} for {playlist}") self._lists.row_changed(row.path, row.iter) if playlist is current: self.activate() break def __removed(self, lib, playlists): for row in self.model: pl = row[0] if pl in playlists: print_d(f"Removing {pl} from view", str(self)) self.__playlist_deleted(row) self.activate() def __added(self, lib, playlists): for playlist in playlists: print_d(f"Looks like a new playlist: {playlist}") self.model.append(row=[playlist]) def __changed(self, lib, playlists): for playlist in playlists: self.changed(playlist) def cell_data(self, col, cell, model, iter, data): playlist = model[iter][0] cell.markup = markup = self.display_pattern % playlist if self.__last_render == markup: return self.__last_render = markup cell.markup = markup cell.set_property('markup', markup) def Menu(self, songs, library, items): model, iters = self.__get_selected_songs() remove = qltk.MenuItem(_("_Remove from Playlist"), Icons.LIST_REMOVE) qltk.add_fake_accel(remove, "Delete") connect_obj(remove, 'activate', self.__remove_songs, iters, model) playlist_iter = self.__selected_playlists()[1] remove.set_sensitive(bool(playlist_iter)) items.append([remove]) menu = super().Menu(songs, library, items) return menu def __get_selected_songs(self): songlist = qltk.get_top_parent(self).songlist model, rows = songlist.get_selection().get_selected_rows() iters = map(model.get_iter, rows) return model, iters @property def _query(self): return self._sb_box.get_query(SongList.star) def __destroy(self, *args): del self._sb_box def __create_box(self): box = qltk.ConfigRHPaned("browsers", "playlistsbrowser_pos", 0.4) box.show_all() return box def __create_searchbar(self, library): self.accelerators = Gtk.AccelGroup() completion = LibraryTagCompletion(library.librarian) sbb = SearchBarBox(completion=completion, accel_group=self.accelerators) sbb.connect('query-changed', self.__text_parse) sbb.connect('focus-out', self.__focus) return sbb def __embed_in_scrolledwin(self, view): swin = ScrolledWindow() swin.set_shadow_type(Gtk.ShadowType.IN) swin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) swin.add(view) self.pack_start(swin, True, True, 0) def __configure_buttons(self, library): new_pl = qltk.Button(_("_New"), Icons.DOCUMENT_NEW, Gtk.IconSize.MENU) new_pl.connect('clicked', self.__new_playlist, library) import_pl = qltk.Button(_("_Import…"), Icons.DOCUMENT_OPEN, Gtk.IconSize.MENU) import_pl.connect('clicked', self.__import, library) fb = Gtk.FlowBox() fb.set_selection_mode(Gtk.SelectionMode.NONE) fb.set_homogeneous(True) fb.insert(new_pl, 0) fb.insert(import_pl, 1) fb.set_max_children_per_line(2) fb.set_column_spacing(3) # The pref button is in its own flowbox instead of directly under the # HBox to make it the same height as the other buttons pref = PreferencesButton(self) fb2 = Gtk.FlowBox() fb2.insert(pref, 0) hb = Gtk.HBox() hb.pack_start(fb, True, True, 3) hb.pack_end(fb2, False, False, 0) self.pack_start(hb, False, False, 0) def __create_playlists_view(self, render): view = RCMHintedTreeView() view.set_enable_search(True) view.set_search_column(0) view.set_search_equal_func( lambda model, col, key, iter, data: not model[iter][col].name.lower().startswith(key.lower()), None) col = Gtk.TreeViewColumn("Playlists", render) col.set_cell_data_func(render, self.cell_data) view.append_column(col) view.set_model(self._lists) view.set_rules_hint(True) view.set_headers_visible(False) return view def __configure_dnd(self, view): targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST), ("text/x-moz-url", 0, DND_MOZ_URL) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) view.enable_model_drag_source( Gdk.ModifierType.BUTTON1_MASK, targets[:2], Gdk.DragAction.COPY) view.connect('drag-data-received', self.__drag_data_received) view.connect('drag-data-get', self._drag_data_get) view.connect('drag-motion', self.__drag_motion) view.connect('drag-leave', self.__drag_leave) def __connect_signals(self, view): view.connect('row-activated', lambda *x: self.songs_activated()) view.connect('popup-menu', self.__popup_menu, self.songs_lib) view.get_selection().connect('changed', self.activate) self.connect('key-press-event', self.__key_pressed) def __create_cell_renderer(self): render = Gtk.CellRendererText() render.set_padding(3, 3) render.set_property('ellipsize', Pango.EllipsizeMode.END) render.connect('editing-started', self.__start_editing) render.connect('edited', self.__edited) return render def key_pressed(self, event): if qltk.is_accel(event, "Delete"): self.__handle_songlist_delete() return True return False def __handle_songlist_delete(self, *args): model, iters = self.__get_selected_songs() self.__remove_songs(iters, model) def __key_pressed(self, widget, event): if qltk.is_accel(event, "Delete"): model, iter = self.__selected_playlists() if not iter: return False playlist = model[iter][0] if confirm_remove_playlist_dialog_invoke(self, playlist, self.Confirmer): playlist.delete() else: print_d("Playlist removal cancelled through prompt") return True elif qltk.is_accel(event, "F2"): model, iter = self.__selected_playlists() if iter: self._start_rename(model.get_path(iter)) return True elif qltk.is_accel(event, "<Primary>I"): songs = self._get_playlist_songs() if songs: window = Information(self.songs_lib.librarian, songs, self) window.show() return True elif qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): qltk.enqueue(self._get_playlist_songs()) return True elif qltk.is_accel(event, "<alt>Return"): songs = self._get_playlist_songs() if songs: window = SongProperties(self.songs_lib.librarian, songs, self) window.show() return True return False def __playlist_deleted(self, row) -> None: self.model.remove(row.iter) def __drag_motion(self, view, ctx, x, y, time): targets = [t.name() for t in ctx.list_targets()] if "text/x-quodlibet-songs" in targets: view.set_drag_dest(x, y, into_only=True) return True else: # Highlighting the view itself doesn't work. view.get_parent().drag_highlight() return True def __drag_leave(self, view, ctx, time): view.get_parent().drag_unhighlight() def __remove_songs(self, iters, smodel): def song_at(itr): return smodel[smodel.get_path(itr)][0] def remove_from_model(iters, smodel): for it in iters: smodel.remove(it) model, iter = self.__selected_playlists() if iter: playlist = model[iter][0] # Build a {iter: song} dict, exhausting `iters` once. removals = {iter_remove: song_at(iter_remove) for iter_remove in iters} if not removals: print_w("No songs selected to remove") return if self._query is None or not self.get_filter_text(): # Calling playlist.remove_songs(songs) won't remove the # right ones if there are duplicates remove_from_model(removals.keys(), smodel) self.__rebuild_playlist_from_songs_model(playlist, smodel) # Emit manually self.songs_lib.emit('changed', removals.values()) else: playlist.remove_songs(removals.values(), True) remove_from_model(removals.keys(), smodel) print_d("Removed %d song(s) from %s" % (len(removals), playlist)) def __rebuild_playlist_from_songs_model(self, playlist, smodel): self.pl_lib.recreate(playlist, [row[0] for row in smodel]) def _selected_playlist(self) -> Optional[Playlist]: """The currently selected playlist's, or None if none selected""" model, iter = self.__selected_playlists() if not iter: return None path = model.get_path(iter) playlist = model[path][0] return playlist def _add_drag_data_tracks_to_playlist(self, target_playlist, songs): """helper-function to facilitate unit-tests without fiddling with views""" # Accidentally extending through DnD'ing a playlist can be a fairly # large operation, so prompt the user before proceeding. # See issue #2367 playlist_name = target_playlist.name response = confirm_dnd_playlist_dialog_invoke( self, songs, playlist_name, self.Confirmer) if response: target_playlist.extend(songs) self.changed(target_playlist) was_modified = True else: print_d("DnD-extension of playlist cancelled through prompt") was_modified = False return was_modified def __drag_data_received(self, view, ctx, x, y, sel, tid, etime): # TreeModelSort doesn't support GtkTreeDragDestDrop. view.emit_stop_by_name('drag-data-received') model = view.get_model() if tid == DND_QL: filenames = qltk.selection_get_filenames(sel) songs = list(filter(None, [self.songs_lib.get(f) for f in filenames])) # Used in conjunction with the prompt for DnD to decide whether to # perform various updates/refreshes. was_modified = True if not songs: Gtk.drag_finish(ctx, False, False, etime) return try: path, pos = view.get_dest_row_at_pos(x, y) except TypeError: # e.g. the target is the empty area after the list of playlists? # TODO: Maybe prompt for this too? Though getting a new playlist is # less intrusive than modifying an existing playlist. # XXX: There does not seem to be an empty area anymore (changed # by one of these pull-requests: #3751 #3974 or the newish browser # code?). playlist = self.pl_lib.create_from_songs(songs) GLib.idle_add(self._select_playlist, playlist) # self.changed() else: playlist = model[path][0] # Call a helper-function that adds the tracks to the playlist if the # user accepts the prompt. was_modified = self._add_drag_data_tracks_to_playlist( playlist, songs ) # self.changed(playlist) Gtk.drag_finish(ctx, True, False, etime) # Cause a refresh to the dragged-to playlist if it is selected # so that the dragged (duplicate) track(s) appears if playlist is self._selected_playlist() and was_modified: model, plist_iter = self.__selected_playlists() songlist = qltk.get_top_parent(self).songlist self.activate(resort=not songlist.is_sorted()) else: if tid == DND_URI_LIST: uri = sel.get_uris()[0] name = os.path.basename(uri) elif tid == DND_MOZ_URL: data = sel.get_data() uri, name = data.decode('utf16', 'replace').split('\n') else: Gtk.drag_finish(ctx, False, False, etime) return name = _name_for(name or os.path.basename(uri)) try: sock = urlopen(uri) uri = uri.lower() if uri.endswith('.pls'): playlist = parse_pls(sock, name, songs_lib=self.songs_lib, pl_lib=self.pl_lib) elif uri.endswith('.m3u') or uri.endswith('.m3u8'): playlist = parse_m3u(sock, name, songs_lib=self.songs_lib, pl_lib=self.pl_lib) else: raise IOError self.songs_lib.add(playlist.songs) # TODO: change to use playlist library too? # self.changed(playlist) Gtk.drag_finish(ctx, True, False, etime) except IOError: Gtk.drag_finish(ctx, False, False, etime) qltk.ErrorMessage( qltk.get_top_parent(self), _("Unable to import playlist"), _("Quod Libet can only import playlists in the M3U/M3U8 " "and PLS formats.")).run() def _drag_data_get(self, view, ctx, sel, tid, etime): model, iters = self.__view.get_selection().get_selected_rows() songs = [] for itr in iters: if itr: songs += model[itr][0].songs if tid == 0: qltk.selection_set_songs(sel, songs) else: sel.set_uris([song("~uri") for song in songs]) def _select_playlist(self, playlist, scroll=False): view = self.__view model = view.get_model() for row in model: if row[0] is playlist: view.get_selection().select_iter(row.iter) if scroll: view.scroll_to_cell(row.path, use_align=True, row_align=0.5) def __popup_menu(self, view, library): model, itr = view.get_selection().get_selected() if itr is None: return songs = list(model[itr][0]) songs = [s for s in songs if isinstance(s, AudioFile)] menu = SongsMenu(library, songs, playlists=False, remove=False, ratings=False) menu.preseparate() def _remove(model, itr): playlist = model[itr][0] response = confirm_remove_playlist_dialog_invoke( self, playlist, self.Confirmer) if response: playlist.delete() else: print_d("Playlist removal cancelled through prompt") rem = MenuItem(_("_Delete"), Icons.EDIT_DELETE) connect_obj(rem, 'activate', _remove, model, itr) menu.prepend(rem) def _rename(path): self._start_rename(path) ren = qltk.MenuItem(_("_Rename"), Icons.EDIT) qltk.add_fake_accel(ren, "F2") connect_obj(ren, 'activate', _rename, model.get_path(itr)) menu.prepend(ren) playlist = model[itr][0] PLAYLIST_HANDLER.populate_menu(menu, library, self, [playlist]) menu.show_all() return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def _start_rename(self, path): view = self.__view self.__render.set_property('editable', True) view.set_cursor(path, view.get_columns()[0], start_editing=True) def __focus(self, widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() def __text_parse(self, bar, text): self.activate() def _set_text(self, text): self._sb_box.set_text(text) def activate(self, widget=None, resort=True): songs = self._get_playlist_songs() query = self._sb_box.get_query(SongList.star) if query and query.is_parsable: songs = query.filter(songs) GLib.idle_add(self.songs_selected, songs, resort) def refresh_all(self): print_d("Refreshing all items...") model = self._lists.get_model() for iter_, value in model.iterrows(): print_d(f"Refreshing row {iter_}") model.row_changed(model.get_path(iter_), iter_) @property def model(self): return self._lists.get_model() def _get_playlist_songs(self): model, iter = self.__selected_playlists() songs = iter and list(model[iter][0]) or [] return [s for s in songs if isinstance(s, AudioFile)] def can_filter_text(self): return True def filter_text(self, text): self._set_text(text) self.activate() def get_filter_text(self): return self._sb_box.get_text() def can_filter(self, key): # TODO: special-case the ~playlists tag maybe? return super().can_filter(key) def finalize(self, restore): config.set("browsers", "query_text", "") def unfilter(self): self.filter_text("") def active_filter(self, song): return (song in self._get_playlist_songs() and (self._query is None or self._query.search(song))) def save(self): model, iter = self.__selected_playlists() name = iter and model[iter][0].name or "" config.set("browsers", "playlist", name) text = self.get_filter_text() config.set("browsers", "query_text", text) def __new_playlist(self, activator, library): playlist = self.pl_lib.create() self._select_playlist(playlist, scroll=True) model, iter = self.__selected_playlists() path = model.get_path(iter) GLib.idle_add(self._start_rename, path) def __start_editing(self, render, editable, path): editable.set_text(self._lists[path][0].name) def __edited(self, render, path, newname): return self._rename(path, newname) def _rename(self, path: Gtk.TreePath, new_name: str, show_error: bool = True) -> bool: playlist = self._lists[path][0] try: playlist.rename(new_name) except ValueError as e: if show_error: qltk.ErrorMessage(None, _("Unable to rename playlist"), str(e)).run() print_w(f"Unable to rename playlist {playlist} ({e})") return False else: row = self._lists[path] child_model = self.model child_model.remove( self._lists.convert_iter_to_child_iter(row.iter)) child_model.append(row=[playlist]) self._select_playlist(playlist, scroll=True) return True def __import(self, activator, library): formats = ["*.pls", "*.m3u", "*.m3u8"] cf = create_chooser_filter(_("Playlists"), formats) fns = choose_files(self, _("Import Playlist"), _("_Import"), cf) self._import_playlists(fns) def _import_playlists(self, fns) -> Tuple[int, int]: """ Import m3u / pls playlists into QL Returns the (total playlists, total songs) added TODO: move this to Playlists library and watch here for new playlists """ total_pls = 0 total_songs = 0 for filename in fns: name = _name_for(filename) with open(filename, "rb") as f: if filename.endswith(".m3u") or filename.endswith(".m3u8"): playlist = parse_m3u(f, name, songs_lib=self.songs_lib, pl_lib=self.pl_lib) elif filename.endswith(".pls"): playlist = parse_pls(f, name, songs_lib=self.songs_lib, pl_lib=self.pl_lib) else: print_w("Unsupported playlist type for '%s'" % filename) continue # Import all the songs in the playlist to the *songs* library total_songs += len(self.songs_lib.add(playlist)) total_pls += 1 return total_pls, total_songs def restore(self): try: name = config.get("browsers", "playlist") except config.Error as e: print_d("Couldn't get last playlist from config: %s" % e) else: self.__view.select_by_func(lambda r: r[0].name == name, one=True) try: text = config.get("browsers", "query_text") except config.Error as e: print_d("Couldn't get last search string from config: %s" % e) else: self._set_text(text) can_reorder = True def scroll(self, song): self.__view.iter_select_by_func(lambda r: song in r[0]) def reordered(self, songs): model, iter = self.__selected_playlists() playlist = None if iter: playlist = model[iter][0] playlist[:] = songs elif songs: playlist = self.pl_lib.create_from_songs(songs) GLib.idle_add(self._select_playlist, playlist) if playlist: self.changed(playlist, refresh=False) def __selected_playlists(self): """Returns a tuple of (model, iter) for the current playlist(s)""" return self.__view.get_selection().get_selected() class PreferencesButton(Gtk.HBox): def __init__(self, browser): super().__init__() menu = Gtk.Menu() pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) menu.append(pref_item) connect_obj(pref_item, "activate", Preferences, browser) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) self.pack_start(button, True, True, 0) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/menu.py������������������������������������������������0000664�0001750�0001750�00000006617�14231604332�021415� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Optional from gi.repository import Gtk, Pango from quodlibet import ngettext, _ from quodlibet import qltk from quodlibet.browsers.playlists.util import GetPlaylistName from quodlibet.library.playlist import PlaylistLibrary from quodlibet.qltk import SeparatorMenuItem, get_menu_item_top_parent, Icons from quodlibet.util.collection import Playlist class PlaylistMenu(Gtk.Menu): def __init__(self, songs, pl_lib: PlaylistLibrary): super().__init__() self.pl_lib = pl_lib i = Gtk.MenuItem(label=_(u"_New Playlist…"), use_underline=True) i.connect('activate', self._on_new_playlist_activate, songs) self.append(i) self.append(SeparatorMenuItem()) self.set_size_request(int(i.size_request().width * 2), -1) for playlist in sorted(pl_lib): name = playlist.name i = Gtk.CheckMenuItem(label=name) some, all = playlist.has_songs(songs) i.set_active(some) i.set_inconsistent(some and not all) i.get_child().set_ellipsize(Pango.EllipsizeMode.END) i.connect( 'activate', self._on_toggle_playlist_activate, playlist, songs) self.append(i) def _on_new_playlist_activate(self, item, songs) -> Optional[Playlist]: parent = get_menu_item_top_parent(item) title = Playlist.suggested_name_for(songs) title = self._get_new_name(parent, title) if title is None: return None return self.pl_lib.create_from_songs(songs, title=title) def _get_new_name(self, parent, title): """Ask the user for a name for the new playlist""" return GetPlaylistName(qltk.get_top_parent(parent)).run(title) def _on_toggle_playlist_activate(self, item, playlist, songs): parent = get_menu_item_top_parent(item) has_some, has_all = playlist.has_songs(songs) if has_all: playlist.remove_songs(songs) elif has_some: resp = ConfirmMultipleSongsAction(parent, playlist, songs).run() if resp == ConfirmMultipleSongsAction.REMOVE: playlist.remove_songs(songs) elif resp == ConfirmMultipleSongsAction.ADD: playlist.extend(songs) return else: playlist.extend(songs) class ConfirmMultipleSongsAction(qltk.Message): """Dialog to ask the user what to do when selecting a playlist for multiple songs with a mix of inclusion""" ADD, REMOVE = range(2) def __init__(self, parent, playlist, songs): desc = ngettext("What do you want to do with that %d song?", "What do you want to do with those %d songs?", len(songs)) % len(songs) title = _("Confirm action for playlist \"%s\"") % playlist.name super().__init__( Gtk.MessageType.QUESTION, parent, title, desc, Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Add"), Icons.LIST_ADD, self.ADD) self.add_icon_button(_("_Remove"), Icons.LIST_REMOVE, self.REMOVE) �����������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/prefs.py�����������������������������������������������0000664�0001750�0001750�00000004656�14035600052�021566� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.util import format_time_display, format_time_long,\ format_size, tag from quodlibet import _ from quodlibet import qltk from quodlibet.browsers._base import EditDisplayPatternMixin, FakeDisplayItem from quodlibet.qltk import Button, Icons from quodlibet.util.i18n import numeric_phrase _FOOTER = "<~tracks> (<~filesize> / <~length>)" DEFAULT_PATTERN_TEXT = ("[b]<~name>[/b]\n" "[small]<~tracks|%s|[i](%s)[/i]>[/small]" % (_FOOTER, (_("empty")))) class Preferences(qltk.UniqueWindow, EditDisplayPatternMixin): _A_SIZE = 127 * 1024 * 1024 _SOME_PEOPLE = "\n".join( tag(t) for t in ["artist", "performer", "composer", "arranger"]) _DEFAULT_PATTERN = DEFAULT_PATTERN_TEXT _PREVIEW_ITEM = FakeDisplayItem({ "date": "2015-11-31", "~length": format_time_display(6319), "~long-length": format_time_long(6319), "~tracks": numeric_phrase("%d track", "%d tracks", 27), "~#filesize": _A_SIZE, "~filesize": format_size(_A_SIZE), "~#rating": 0.75, "~name": _("Example Playlist"), "~people": _SOME_PEOPLE + "..."}) def __init__(self, browser): if self.is_not_unique(): return super().__init__() self.set_border_width(12) self.set_title(_("Playlist Browser Preferences")) self.set_default_size(420, 240) self.set_transient_for(qltk.get_top_parent(browser)) box = Gtk.VBox(spacing=6) edit_frame = self.edit_display_pane(browser, _("Playlist display")) box.pack_start(edit_frame, False, True, 12) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all() ����������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/playlists/util.py������������������������������������������������0000644�0001750�0001750�00000013430�14324322342�021414� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014-2022 Nick Boultbee # 2022 TheMelmacian # # 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 2 of the License, or # (at your option) any later version. import os from quodlibet import _, print_w, ngettext from quodlibet import formats from quodlibet.qltk import Icons from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.msg import ConfirmationPrompt from quodlibet.qltk.wlw import WaitLoadWindow from quodlibet.util import escape from quodlibet.util.path import uri_is_valid from urllib.response import addinfourl from senf import uri2fsn, fsn2text, path2fsn, bytes2fsn, text2fsn def confirm_remove_playlist_dialog_invoke( parent, playlist, Confirmer=ConfirmationPrompt): """Creates and invokes a confirmation dialog that asks the user whether or not to go forth with the deletion of the selected playlist. Confirmer needs to accept the arguments for constructing a dialog, have a run-method returning a response, and have a RESPONSE_INVOKE attribute. returns the result of comparing the result of run to RESPONSE_INVOKE """ title = (_("Are you sure you want to delete the playlist '%s'?") % escape(playlist.name)) description = (_("All information about the selected playlist " "will be deleted and can not be restored.")) ok_text = _("_Delete") ok_icon = Icons.EDIT_DELETE dialog = Confirmer(parent, title, description, ok_text, ok_icon) prompt = dialog.run() response = (prompt == Confirmer.RESPONSE_INVOKE) return response def confirm_dnd_playlist_dialog_invoke( parent, songs, target_playlist_name, Confirmer=ConfirmationPrompt): """see confirm_remove_playlist_dialog_invoke above, except for the action of attempting to extend a playlist with a second dragged and dropped playlist. """ title = ngettext( "Extend \"{pl_name}\" with {num} additional track?", "Extend \"{pl_name}\" with {num} additional tracks?", len(songs), ).format(pl_name=target_playlist_name, num=len(songs)) description = "" ok_text = _("_Add Tracks") dialog = Confirmer(parent, title, description, ok_text) prompt = dialog.run() response = (prompt == Confirmer.RESPONSE_INVOKE) return response class GetPlaylistName(GetStringDialog): def __init__(self, parent): super().__init__( parent, _("New Playlist"), _("Enter a name for the new playlist:"), button_label=_("_Create"), button_icon=Icons.DOCUMENT_NEW) def parse_m3u(filelike, pl_name, songs_lib=None, pl_lib=None): filenames = [] for line in filelike: line = line.strip() if line.startswith(b"#"): continue __attempt_add(line, filenames) return __create_playlist(pl_name, _dir_for(filelike), filenames, songs_lib, pl_lib) def parse_pls(filelike, pl_name, songs_lib=None, pl_lib=None): filenames = [] for line in filelike: line = line.strip() if not line.lower().startswith(b"file"): continue fn = line[line.index(b"=") + 1:].strip() __attempt_add(fn, filenames) return __create_playlist(pl_name, _dir_for(filelike), filenames, songs_lib, pl_lib) def __attempt_add(filename, filenames): try: filenames.append(bytes2fsn(filename, 'utf-8')) except ValueError: print_w(f"Ignoring invalid filename {filename!r}") def __create_playlist(name, source_dir, files, songs_lib, pl_lib): songs = [] win = WaitLoadWindow( None, len(files), _("Importing playlist.\n\n%(current)d/%(total)d songs added.")) win.show() for i, filename in enumerate(files): song = None if not uri_is_valid(filename): # Plain filename. song = _af_for(filename, songs_lib, source_dir) else: try: filename = uri2fsn(filename) except ValueError: # Who knows! Hand it off to GStreamer. song = formats.remote.RemoteFile(filename) else: # URI-encoded local filename. song = _af_for(filename, songs_lib, source_dir) # Only add existing (not None) files to the playlist. # Otherwise multiple errors are thrown when the files are accessed # to update the displayed track infos. if song is not None: songs.append(song) elif (os.path.exists(filename) or os.path.exists(os.path.join(source_dir, filename))): print_w("Can't add file to playlist:" f" Unsupported file format. '{filename}'") else: print_w(f"Can't add file to playlist: File not found. '{filename}'") if win.step(): break win.destroy() return pl_lib.create_from_songs(songs) def _af_for(filename, library, pl_dir): full_path = os.path.join(pl_dir, filename) filename = os.path.realpath(full_path) af = None if library: af = library.get_filename(filename) if af is None: af = formats.MusicFile(filename) return af def _name_for(filename): if not filename: return _("New Playlist") name = os.path.basename(os.path.splitext(filename)[0]) return fsn2text(path2fsn(name)) def _dir_for(filelike): try: if isinstance(filelike, addinfourl): # if the "filelike" was created via urlopen # it is wrapped in an addinfourl object return os.path.dirname(path2fsn(filelike.fp.name)) else: return os.path.dirname(path2fsn(filelike.name)) except AttributeError: # Probably a URL return text2fsn(u'') ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/podcasts.py������������������������������������������������������0000644�0001750�0001750�00000044377�14327505043�020255� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2017-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys import threading import time from typing import Optional from urllib.request import urlopen, Request from gi.repository import Gtk, GLib, Pango, Gdk import feedparser import quodlibet from quodlibet import _ from quodlibet import config from quodlibet import formats from quodlibet import print_d from quodlibet import qltk from quodlibet import util from quodlibet import app from quodlibet.browsers import Browser from quodlibet.formats import AudioFile from quodlibet.formats.remote import RemoteFile from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.msg import ErrorMessage from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import AllTreeView from quodlibet.qltk import Icons from quodlibet.util import connect_obj, print_w from quodlibet.qltk.x import ScrolledWindow, Align, Button, MenuItem from quodlibet.util.path import uri_is_valid from quodlibet.util.picklehelper import pickle_load, pickle_dump, PickleError FEEDS = os.path.join(quodlibet.get_user_dir(), "feeds") DND_URI_LIST, DND_MOZ_URL = range(2) # Migration path for pickle sys.modules["browsers.audiofeeds"] = sys.modules[__name__] class InvalidFeed(ValueError): pass class Feed(list): def __init__(self, uri): self.name = _("Unknown") self.uri = uri self.changed = False self.website = "" self.__lastgot = 0 def get_age(self): return time.time() - self.__lastgot @staticmethod def __fill_af(feed, af): try: af["title"] = feed.title or _("Unknown") except (TypeError, AttributeError): af["title"] = _("Unknown") try: af["date"] = "%04d-%02d-%02d" % feed.modified_parsed[:3] except (AttributeError, TypeError): pass for songkey, feedkey in [ ("website", "link"), ("description", "tagline"), ("language", "language"), ("copyright", "copyright"), ("organization", "publisher"), ("license", "license")]: try: value = getattr(feed, feedkey) except AttributeError: pass else: if value and value not in af.list(songkey): af.add(songkey, value) try: af.add("artwork_url", feed.image["href"]) except (AttributeError, KeyError): pass try: author = feed.author_detail except AttributeError: try: author = feed.author except AttributeError: pass else: if author and author not in af.list("artist"): af.add('artist', author) else: try: if author.email and author.email not in af.list("contact"): af.add("contact", author.email) except AttributeError: pass try: if author.name and author.name not in af.list("artist"): af.add("artist", author.name) except AttributeError: pass try: values = feed.contributors except AttributeError: pass else: for value in values: try: value = value.name except AttributeError: pass else: if value and value not in af.list("performer"): af.add("performer", value) try: af["~#length"] = util.parse_time(feed.itunes_duration) except (AttributeError, ValueError): pass try: values = dict(feed.categories).values() except AttributeError: pass else: for value in values: if value and value not in af.list("genre"): af.add("genre", value) def parse(self): req = Request(self.uri, method="HEAD") try: with urlopen(req, timeout=5) as head: # Some requests don't support status, e.g. file:// if hasattr(head, "status"): print_d(f"Feed URL {self.uri!r} ({head.url}) " f"returned HTTP {head.status}, " f"with content {head.headers.get('Content-Type')}") if head.status and head.status >= 400: return False if head.headers.get("Content-Type").lower().startswith("audio"): print_w("Looks like an audio stream / radio, not a audio feed.") return False # Don't pass feedparser URLs # see https://github.com/kurtmckee/feedparser/pull/80#issuecomment-449543486 content = urlopen(self.uri, timeout=15).read() except IOError as e: print_w(f"Couldn't fetch content from {self.uri} ({e})") return False try: doc = feedparser.parse(content) except Exception as e: print_w(f"Couldn't parse feed: {self.uri} ({e})") return False try: album = doc.channel.title except AttributeError: print_w("No channel title in %s" % doc) return False if album: self.name = album else: self.name = _("Unknown") defaults = AudioFile({"feed": self.uri}) try: self.__fill_af(doc.channel, defaults) except Exception as e: print_w("Error creating feed data: %s (%s)" % (self.uri, e)) return False entries = [] uris = set() print_d("Found %d entries in channel" % len(doc.entries)) for entry in doc.entries: try: for enclosure in entry.enclosures: try: if ("audio" in enclosure.type or "ogg" in enclosure.type or formats.filter(enclosure.url)): uri = enclosure.url if not isinstance(uri, str): uri = uri.decode('utf-8') try: size = float(enclosure.length) except (AttributeError, ValueError): size = 0 entries.append((uri, entry, size)) uris.add(uri) break except AttributeError: pass except AttributeError: print_d("No enclosures found in %s" % entry) for entry in list(self): if entry["~uri"] not in uris: self.remove(entry) else: uris.remove(entry["~uri"]) print_d("Successfully got %d episodes in channel" % len(entries)) entries.reverse() for uri, entry, size in entries: if uri in uris: song = RemoteFile(uri) song["~#size"] = size song.fill_metadata = False song.update(defaults) song["album"] = self.name try: self.__fill_af(entry, song) except Exception as e: print_d("Couldn't convert %s to AudioFile (%s)" % (uri, e)) else: self.insert(0, song) self.__lastgot = time.time() return bool(uris) class AddFeedDialog(GetStringDialog): def __init__(self, parent): super().__init__( qltk.get_top_parent(parent), _("New Feed"), _("Enter the podcast / audio feed location:"), button_label=_("_Add"), button_icon=Icons.LIST_ADD) def run(self, text='', clipboard=True, test=False): uri = super().run(text=text, clipboard=clipboard, test=test) if uri: if not isinstance(uri, str): uri = uri.decode('utf-8') return Feed(uri) return None def _verify_clipboard(self, text): # try to extract a URI from the clipboard for line in text.splitlines(): line = line.strip() if uri_is_valid(line): return line def hacky_py2_unpickle_recover(fileobj): """Can raise anything""" # We just recover the uri and let it refresh the feed later def lookup_func(func, mod, name): class Feed(list): pass class Bar(dict): pass if name == "Feed": return Feed else: return Bar with open(FEEDS, "rb") as fileobj: feeds = pickle_load(fileobj, lookup_func) uris = [] for item in feeds: d = item.__dict__ if b"uri" in d: v = d[b"uri"] elif "uri" in d: v = d["uri"] else: continue if isinstance(v, bytes): v = v.decode("utf-8") uris.append(v) return [Feed(u) for u in uris] class Podcasts(Browser): """ Allows interacting with remote feeds for playing and exploring podcasts and their episodes (or other forms of audio feeds) Formerly known as the AudioFeeds browser. """ __feeds = Gtk.ListStore(object) # unread headers = ("title artist performer ~people album date website language " "copyright organization license contact").split() name = _("Podcasts") accelerated_name = _("_Podcasts") keys = ["AudioFeeds", "Podcasts"] priority = 20 uses_main_library = False def pack(self, songpane): container = qltk.ConfigRHPaned("browsers", "audiofeeds_pos", 0.4) self.show() container.pack1(self, True, False) container.pack2(songpane, True, False) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) @staticmethod def cell_data(col, render, model, iter, data): if model[iter][0].changed: render.markup = util.bold(model[iter][0].name) else: render.markup = util.escape(model[iter][0].name) render.set_property('markup', render.markup) @classmethod def changed(klass, feeds): for row in klass.__feeds: if row[0] in feeds: row[0].changed = True row[0] = row[0] Podcasts.write() @classmethod def write(klass): feeds = [row[0] for row in klass.__feeds] with open(FEEDS, "wb") as f: pickle_dump(feeds, f, 2) @classmethod def init(klass, library): uris = set() feeds = [] try: with open(FEEDS, "rb") as fileobj: feeds = pickle_load(fileobj) except (PickleError, EnvironmentError): try: with open(FEEDS, "rb") as fileobj: feeds = hacky_py2_unpickle_recover(fileobj) except Exception: pass for feed in feeds: if feed.uri in uris: continue klass.__feeds.append(row=[feed]) uris.add(feed.uri) GLib.idle_add(klass.__do_check) @classmethod def reload(klass, library): klass.__feeds = Gtk.ListStore(object) # unread klass.init(library) @classmethod def __do_check(klass): thread = threading.Thread(target=klass.__check, args=(), daemon=True) thread.start() @classmethod def __check(klass): for row in klass.__feeds: feed = row[0] if feed.get_age() < 2 * 60 * 60: continue elif feed.parse(): feed.changed = True row[0] = feed klass.write() GLib.timeout_add(60 * 60 * 1000, klass.__do_check) def __init__(self, library): super().__init__(spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) self._view = view = AllTreeView() self.__render = render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn("Audio Feeds", render) col.set_cell_data_func(render, Podcasts.cell_data) view.append_column(col) view.set_model(self.__feeds) view.set_rules_hint(True) view.set_headers_visible(False) swin = ScrolledWindow() swin.set_shadow_type(Gtk.ShadowType.IN) swin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) swin.add(view) self.pack_start(swin, True, True, 0) new = Button(_("_Add Feed…"), Icons.LIST_ADD, Gtk.IconSize.MENU) new.connect('clicked', self.__new_feed) view.get_selection().connect('changed', self.__changed) view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) view.connect('popup-menu', self._popup_menu) targets = [ ("text/uri-list", 0, DND_URI_LIST), ("text/x-moz-url", 0, DND_MOZ_URL) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) view.connect('drag-data-received', self.__drag_data_received) view.connect('drag-motion', self.__drag_motion) view.connect('drag-leave', self.__drag_leave) connect_obj(self, 'destroy', self.__save, view) self.pack_start(Align(new, left=3, bottom=3), False, True, 0) for child in self.get_children(): child.show_all() def Menu(self, songs, library, items): return SongsMenu(library, songs, download=True, items=items) def __drag_motion(self, view, ctx, x, y, time): targets = [t.name() for t in ctx.list_targets()] if "text/x-quodlibet-songs" not in targets: view.get_parent().drag_highlight() return True return False def __drag_leave(self, view, ctx, time): view.get_parent().drag_unhighlight() def __drag_data_received(self, view, ctx, x, y, sel, tid, etime): view.emit_stop_by_name('drag-data-received') targets = [ ("text/uri-list", 0, DND_URI_LIST), ("text/x-moz-url", 0, DND_MOZ_URL) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) if tid == DND_URI_LIST: uri = sel.get_uris()[0] elif tid == DND_MOZ_URL: uri = sel.data.decode('utf16', 'replace').split('\n')[0] else: ctx.finish(False, False, etime) return ctx.finish(True, False, etime) feed = Feed(uri.encode("ascii", "replace")) feed.changed = feed.parse() if feed: self.__feeds.append(row=[feed]) Podcasts.write() else: self.feed_error(feed).run() def _popup_menu(self, view: Gtk.Widget) -> Optional[Gtk.Menu]: model, paths = self._view.get_selection().get_selected_rows() menu = Gtk.Menu() refresh = MenuItem(_("_Refresh"), Icons.VIEW_REFRESH, tooltip=_("Search source for new episodes")) rebuild = MenuItem( _("_Rebuild"), Icons.EDIT_FIND_REPLACE, tooltip=_("Remove all existing episodes then reload from source")) delete = MenuItem(_("_Delete"), Icons.EDIT_DELETE, tooltip=_("Remove this podcast and its episodes")) connect_obj(refresh, 'activate', self.__refresh, [model[p][0] for p in paths]) connect_obj(rebuild, 'activate', self.__rebuild, [model[p][0] for p in paths]) connect_obj(delete, 'activate', self.__remove_paths, model, paths) menu.append(refresh) menu.append(rebuild) menu.append(delete) menu.show_all() menu.connect('selection-done', lambda m: m.destroy()) if self._view.popup_menu(menu, 0, Gtk.get_current_event_time()): return menu return None def __save(self, view): Podcasts.write() def __refresh(self, feeds): changed = list(filter(Feed.parse, feeds)) Podcasts.changed(changed) def __rebuild(self, feeds): for feed in feeds: feed.clear() changed = list(filter(Feed.parse, feeds)) Podcasts.changed(changed) def __remove_paths(self, model, paths): for path in paths: model.remove(model.get_iter(path)) def activate(self): self.__changed(self._view.get_selection()) def __changed(self, selection): model, paths = selection.get_selected_rows() if model and paths: songs = [] for path in paths: model[path][0].changed = False songs.extend(model[path][0]) self.songs_selected(songs, True) config.set("browsers", "audiofeeds", "\t".join([model[path][0].name for path in paths])) def __new_feed(self, activator): feed = AddFeedDialog(self).run() if feed is not None: feed.changed = feed.parse() if feed: self.__feeds.append(row=[feed]) Podcasts.write() else: self.feed_error(feed).run() def feed_error(self, feed: Feed) -> ErrorMessage: return ErrorMessage( self, _("Unable to add feed"), _("%s could not be added. The server may be down, " "or the location may not be a podcast / audio feed.") % util.bold(util.escape(feed.uri)), escape_desc=False) def restore(self): try: names = config.get("browsers", "audiofeeds").split("\t") except Exception: pass else: self._view.select_by_func(lambda r: r[0].name in names) browsers = [] if not app.player or app.player.can_play_uri("http://"): browsers = [Podcasts] else: print_w(_("The current audio backend does not support URLs, " "Podcast browser disabled.")) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020217� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/__init__.py�������������������������������������������0000664�0001750�0001750�00000000722�14035600052�022327� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from .main import SoundcloudBrowser browsers = ([SoundcloudBrowser] if not app.player or app.player.can_play_uri("http://") else []) ����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/api.py������������������������������������������������0000644�0001750�0001750�00000030331�14455205526�021353� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-23 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import json from datetime import datetime from typing import Optional, Any from urllib.parse import urlencode from gi.repository import GObject, Gio, Soup, GLib from quodlibet import util, config from quodlibet.formats import AudioFile from quodlibet.util import website from quodlibet.util.dprint import print_w, print_d from quodlibet.util.http import (download_json, download, HTTPRequest, FailureCallback) from .library import SoundcloudFile from .util import json_callback, Wrapper, sanitise_tag, DEFAULT_BITRATE, EPOCH class RestApi(GObject.Object): """Semi-generic REST API client, using libsoup / `http.py`""" def __init__(self, root, on_failure: FailureCallback): super().__init__() self._cancellable = Gio.Cancellable.new() self.root = root self._on_failure = on_failure self.access_token = None def _default_params(self): return {} def _get(self, path, callback, data=None, **kwargs): args = self._default_params() args.update(kwargs) msg = self._add_auth_to(Soup.Message.new('GET', self._url(path, args))) download_json(msg, self._cancellable, callback, data, self._on_failure) def _add_auth_to(self, msg: Soup.Message) -> Soup.Message: if self.access_token: msg.get_request_headers().append( "Authorization", f"OAuth {self.access_token}") return msg def _post(self, path, callback, **kwargs): args = self._default_params() args.update(kwargs) msg = self._add_auth_to(Soup.Message.new('POST', self._url(path))) post_body = urlencode(args) if not isinstance(post_body, bytes): post_body = post_body.encode("ascii") msg.set_request_body_from_bytes( 'application/x-www-form-urlencoded', GLib.Bytes.new(post_body)) download_json(msg, self._cancellable, callback, None, self._on_failure) def _delete(self, path, callback, **kwargs): args = self._default_params() args.update(kwargs) # Turns out the SC API doesn't mind body arguments for DELETEs, # and as it's neater and slightly more secure, let's do that. body = urlencode(args) if not isinstance(body, bytes): body = body.encode("ascii") msg = self._add_auth_to(Soup.Message.new('DELETE', self._url(path))) msg.set_request_body_from_bytes( 'application/x-www-form-urlencoded', GLib.Bytes.new(body)) download(msg, self._cancellable, callback, None, try_decode=True) def _url(self, path, args=None): path = "%s%s" % (self.root, path) return "%s?%s" % (path, urlencode(args)) if args else path class SoundcloudApiClient(RestApi): __CLIENT_SECRET = 'ca2b69301bd1f73985a9b47224a2a239' __CLIENT_ID = '5acc74891941cfc73ec8ee2504be6617' API_ROOT = "https://api.soundcloud.com" REDIRECT_URI = 'https://quodlibet.github.io/callbacks/soundcloud.html' PAGE_SIZE = 100 MIN_DURATION_SECS = 120 COUNT_TAGS = {'%s_count' % t for t in ('playback', 'download', 'likes', 'favoritings', 'download', 'comments')} __gsignals__ = { 'fetch-success': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'fetch-failure': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'songs-received': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'stream-uri-received': (GObject.SignalFlags.RUN_LAST, None, (object, str)), 'comments-received': (GObject.SignalFlags.RUN_LAST, None, (int, object,)), 'authenticated': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self): print_d("Starting Soundcloud API...") super().__init__(self.API_ROOT, self._on_failure) self.access_token = config.get("browsers", "soundcloud_token", None) self.refresh_token = config.get("browsers", "soundcloud_refresh_token", None) self.user_id = config.get("browsers", "soundcloud_user_id", None) if not self.user_id: self._get_me() self.username = None @property def online(self): return bool(self.access_token) def _on_failure(self, req: HTTPRequest, _exc: Exception, data: Any) -> None: """Callback for HTTP failures.""" code = req.message.get_property('status-code') if code in (401,): print_w("User session no longer valid, logging out.") if self.access_token: # Could call log_out to persist, but we're probably about to refresh... self.access_token = None self._refresh_tokens() else: print_w("Refreshing didn't work either, oh dear.") self.log_out() def _default_params(self): return {} def authenticate_user(self): # create client object with app credentials if self.access_token: print_d("Ignoring saved Soundcloud token...") # redirect user to authorize URL website(self._authorize_url) def log_out(self): print_d("Destroying access token...") self.access_token = None self.user_id = None self.save_auth() def get_tokens(self, code): print_d("Getting access token...") options = { 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': self.REDIRECT_URI, 'client_id': self.__CLIENT_ID, 'client_secret': self.__CLIENT_SECRET, } self._post('/oauth2/token', self._receive_tokens, **options) def _refresh_tokens(self): print_d("Refreshing access token...") options = { 'grant_type': 'refresh_token', 'refresh_token': self.refresh_token, 'client_id': self.__CLIENT_ID, 'client_secret': self.__CLIENT_SECRET, } self._post('/oauth2/token', self._receive_tokens, **options) @json_callback def _receive_tokens(self, json, _data): self.access_token = json['access_token'] refresh_token = json.get('refresh_token', None) if refresh_token: # Just in case we don't get it... self.refresh_token = refresh_token print_d("Got refresh token.") print_d(f"Got an access token: ...{self.access_token[-6:]}") self.save_auth() if not self.user_id: self._get_me() def _get_me(self): self._get('/me', self._receive_me) @json_callback def _receive_me(self, json, _data): self.username = json['username'] self.user_id = json['id'] self.emit('authenticated', Wrapper(json)) def get_tracks(self, params): merged = { "q": "", "limit": self.PAGE_SIZE, "duration[from]": self.MIN_DURATION_SECS * 1000, "access": "playable", } for k, v in params.items(): delim = " " if k == 'q' else "," merged[k] = delim.join(list(v)) print_d("Getting tracks: params=%s" % merged) self._get('/tracks', self._on_track_data, **merged) def get_stream_url(self, song): try: self._get(f"/tracks/{song['soundcloud_track_id']}/streams", self._on_track_stream_urls_data, song) except Exception as e: print_w(f"Problem getting stream URL for {song} ({e})") @json_callback def _on_track_stream_urls_data(self, json, song): uri = json['http_mp3_128_url'] self.emit("stream-uri-received", song, uri) @json_callback def _on_track_data(self, json, _data): songs = list(filter(None, [self._audiofile_for(r) for r in json])) self.emit('songs-received', songs) def get_favorites(self): self._get("/me/likes/tracks", self._on_track_data, limit=self.PAGE_SIZE) def get_my_tracks(self): self._get('/me/tracks', self._on_track_data, limit=self.PAGE_SIZE) def get_comments(self, track_id): self._get(f"/tracks/{track_id}/comments", self._receive_comments, limit=500) @json_callback def _receive_comments(self, json, _data): print_d("Got comments: %s..." % str(json)[:255]) if json and len(json): # Should all be the same track... track_id = json[0]["track_id"] self.emit('comments-received', track_id, json) def save_auth(self): config.set("browsers", "soundcloud_token", self.access_token or "") config.set("browsers", "soundcloud_refresh_token", self.refresh_token or "") config.set("browsers", "soundcloud_user_id", self.user_id or "") def save_favorite(self, track_id): print_d("Saving track %s as favorite" % track_id) url = f"/likes/tracks/{track_id}" self._post(url, self._on_favorited) def remove_favorite(self, track_id): print_d("Deleting favorite for %s" % track_id) url = f"/likes/tracks/{track_id}" self._delete(url, self._on_favorited) @json_callback def _on_favorited(self, json, _data): print_d("Successfully updated favorite") def _audiofile_for(self, response) -> Optional[AudioFile]: r = Wrapper(response) d = r.data try: # It's not a _play_ URI, because that needs a separate request, # but it's unique and permanent, so that's good enough here url = r.uri if not url: print_d(f"Unusable response (no URI): {d}") return None song = SoundcloudFile(uri=url, track_id=r.id, client=self, favorite=d.get("user_favorite", False)) except Exception as e: print_w(f"Track {r.id} no good ({e})") return None def get_utc_date(s): parts = s.split() dt = datetime.strptime(" ".join(parts[:-1]), "%Y/%m/%d %H:%M:%S") return int((dt - EPOCH).total_seconds()) def put_time(tag, r, attr): try: song[tag] = get_utc_date(r[attr]) except KeyError: pass def put_date(tag, r, attr): try: parts = r[attr].split() dt = datetime.strptime(" ".join(parts[:-1]), "%Y/%m/%d %H:%M:%S") song[tag] = dt.strftime("%Y-%m-%d") except KeyError: pass def put_counts(tags): for tag in tags: try: song["~#%s" % tag] = int(r[tag]) except (KeyError, TypeError): # Nothing we can do really. pass try: song.update(title=r.title, artist=r.user["username"], soundcloud_user_id=str(r.user.id), website=r.permalink_url, genre="\n".join(r.genre and r.genre.split(",") or [])) song["~#bitrate"] = DEFAULT_BITRATE if r.description: song["comment"] = sanitise_tag(r.description) song["~#length"] = int(r.duration) / 1000 art_url = r.artwork_url if art_url: song["artwork_url"] = ( art_url.replace("-large.", "-t500x500.")) put_time("~#mtime", r, "last_modified") put_date("date", r, "created_at") put_counts(self.COUNT_TAGS) plays = d.get("user_playback_count", 0) if plays: song["~#playcount"] = plays except Exception as e: print_w(f"Couldn't parse song ({e!r}): {json.dumps(r._raw)}") return song @util.cached_property def _authorize_url(self): url = '%s/connect' % (self.API_ROOT,) options = { 'scope': '', 'client_id': self.__CLIENT_ID, 'response_type': 'code', 'redirect_uri': self.REDIRECT_URI } return '%s?%s' % (url, urlencode(options)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667166353.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/library.py��������������������������������������������0000644�0001750�0001750�00000015012�14327570221�022240� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GLib from quodlibet import config, _ from quodlibet.browsers.soundcloud.query import SoundcloudQuery from quodlibet.formats import AudioFile from quodlibet.formats.remote import RemoteFile from quodlibet.library import SongLibrary from quodlibet.library.base import K from quodlibet.qltk.notif import Task from quodlibet.util import cached_property, print_exc, copool from quodlibet.util.dprint import print_d, print_w from senf import fsnative class SoundcloudLibrary(SongLibrary[K, "SoundcloudFile"]): STAR = ["artist", "title", "genre", "tags"] def __init__(self, client, player=None): super().__init__("Soundcloud") self.client = client self._sids = [ self.client.connect('songs-received', self._on_songs_received), self.client.connect('stream-uri-received', self._on_stream_uri_received), self.client.connect('comments-received', self._on_comments_received) ] self._psid = None # Keep track of async-changed songs for bulk signalling self._dirty = set() GLib.timeout_add(2000, self._on_tick) if player: self.player = player self._psid = self.player.connect('song-started', self.__song_started) def destroy(self): super().destroy() for sid in self._sids: self.client.disconnect(sid) if self._psid: self.player.disconnect(self._psid) def query(self, text, sort=None, star=STAR): values = self._contents.values() try: return SoundcloudQuery(text).filter(values) except SoundcloudQuery.Error: return values def query_with_refresh(self, query: SoundcloudQuery): """Queries Soundcloud for some (more) relevant results, then filters""" current = self._contents.values() if not query.is_parsable: return current self.client.get_tracks(query.terms) filtered = query.filter(current) print_d("Filtered %d results to %d" % (len(current), len(filtered))) return filtered def rename(self, song, newname, changed=None): raise TypeError("Can't rename Soundcloud files") def _get_stream_urls(self, songs): # Pre-cache. It's horrible, but at least you can play things immediately with Task(_("Soundcloud"), "Pre-fetching stream URLs") as task: total = len(songs) for i, song in enumerate(songs): # Only update ones without streaming URLs # TODO: But yes these will time out... if "~uri" not in song or "api.soundcloud.com" in song["~uri"]: self.client.get_stream_url(song) task.update(i / total) yield def _on_songs_received(self, client, songs): print_d(f"Got {len(songs)} songs") self.add(songs) # Can't have multiple requests cancel each other's copools funcid = hash("".join(s["~uri"] for s in songs)) # Rate limit a little to avoid 429s copool.add(self._get_stream_urls, songs, timeout=100, funcid=funcid) def _on_stream_uri_received(self, client, song: AudioFile, uri: str): # URI isn't the key in this SoundcloudFile, so this is OK song["~uri"] = uri self._dirty.add(song) def _on_tick(self) -> bool: if self._dirty: self.changed(self._dirty) self._dirty.clear() return True def _on_comments_received(self, client, track_id, comments): def bookmark_for(com): text = "\"%s\" – %s" % (com['body'], com['user']['username']) return max(0, int((com.get('timestamp') or 0) / 1000.0)), text try: song = self.song_by_track_id(track_id) except KeyError: # https://github.com/quodlibet/quodlibet/issues/2410 print_exc() return song.bookmarks = [bookmark_for(c) for c in comments] print_d(f"Updated song bookmarks for {song('title')}") def song_by_track_id(self, track_id): for song in self.values(): if song.track_id == track_id: return song raise KeyError("No track with id %s. Do have %s" % (track_id, [s.track_id for s in self.values()])) def _changed(self, items): super()._changed(items) # We should ask the AudioFile subclass to write what it can ASAP for item in items: item.write() def __song_started(self, player, song): if isinstance(song, SoundcloudFile): print_d("Getting comments for %s (%s)" % (song("title"), song.key)) self.client.get_comments(song.track_id) class SoundcloudFile(RemoteFile): format = "Remote Soundcloud File" def __init__(self, uri: str, track_id: int, client, favorite: bool = False): # Don't call super, it invokes __getitem__ self["~uri"] = uri self.sanitize(fsnative(uri)) self.client = client if not self.client: raise EnvironmentError("Must have a Soundcloud client") self["soundcloud_track_id"] = track_id self.favorite = favorite if self.favorite: self['~#rating'] = 1.0 def set_image(self, image): raise TypeError("Can't change images on Soundcloud") @cached_property def track_id(self): return int(self["soundcloud_track_id"]) @cached_property def key(self): return "track-%s" % (self.track_id,) def can_change(self, k=None): if k is None: return ["~rating", "~#rating"] else: return k.endswith("rating") def write(self): if not self.client or not self.client.online: print_w("Can't save without a logged-in Soundcloud client") return # There's not much that can be written self._write_rating() def _write_rating(self): should_fave = self.has_rating and self("~#rating") >= config.RATINGS.default track_id = self.track_id if not self.favorite and should_fave: self.client.save_favorite(track_id) self.favorite = True elif self.favorite and not should_fave: self.client.remove_favorite(track_id) self.favorite = False ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666467687.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/main.py�����������������������������������������������0000644�0001750�0001750�00000041333�14325043547�021531� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from urllib.parse import parse_qs, urlparse from gi.repository import Gtk, Pango from quodlibet import _ from quodlibet import config, app from quodlibet import qltk from quodlibet import util from quodlibet.browsers import Browser from quodlibet.qltk import Icons, Message from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk.x import Align, ScrolledWindow, WebImage from quodlibet.util import connect_destroy, DeferredSignal, website, enum, \ cached_property from quodlibet.util.dprint import print_w, print_d from .api import SoundcloudApiClient from .library import SoundcloudLibrary from .query import SoundcloudQuery from .util import State, FilterType, PROCESS_QL_URLS, EnterAuthCodeDialog, \ SITE_URL, SOUNDCLOUD_NAME, sc_btn_image class SoundcloudBrowser(Browser, util.InstanceTracker): background = False __librarian = None __filter = None name = _("Soundcloud Browser") accelerated_name = _("Sound_cloud") keys = ["Soundcloud"] priority = 30 uses_main_library = False headers = ("artist ~people title genre ~#length ~mtime ~bitrate date " "website comment ~rating " "~#playback_count ~#favoritings_count ~#likes_count").split() @enum class ModelIndex(int): TYPE, ICON_NAME, NAME, QUERY, ALWAYS_ENABLE = range(5) login_state = State.LOGGED_OUT STAR = [tag for tag in headers if not tag.startswith("~#")] @classmethod def _init(klass, library): klass.__librarian = library.librarian klass.filters = [ (_("Search"), (FilterType.SEARCH, Icons.EDIT_FIND, "", True)), # TODO: support for ~#rating=!None etc (#1940) (_("Favorites"), (FilterType.FAVORITES, Icons.FAVORITE, "#(rating = 1.0)", False)), (_("My tracks"), (FilterType.MINE, Icons.MEDIA_RECORD, "soundcloud_user_id=%s", False)), ] try: if klass.library: return except AttributeError: pass klass.api_client = SoundcloudApiClient() klass.library = SoundcloudLibrary(klass.api_client, app.player) @classmethod def _destroy(klass): klass.__librarian = None klass.filters = {} klass.library.destroy() klass.library = None def __inhibit(self): self.view.get_selection().handler_block(self.__changed_sig) def __uninhibit(self): self.view.get_selection().handler_unblock(self.__changed_sig) def __destroy(self, *args): print_d(f"Destroying Soundcloud Browser {self}") if not self.instances(): self._destroy() def __init__(self, library): print_d(f"Creating Soundcloud Browser {self}") super().__init__(spacing=12) self.set_orientation(Gtk.Orientation.VERTICAL) if not self.instances(): self._init(library) self._register_instance() self.connect('destroy', self.__destroy) self.connect('uri-received', self.__handle_incoming_uri) connect_destroy(self.api_client, 'authenticated', self.__on_authenticated) connect_destroy(self.library, 'changed', self.__changed) self.login_state = (State.LOGGED_IN if self.online else State.LOGGED_OUT) self._create_searchbar(self.library) vbox = Gtk.VBox() vbox.pack_start(self._create_header(), False, False, 0) vbox.pack_start(self._create_category_widget(), True, True, 0) vbox.pack_start(self.create_login_button(), False, False, 0) vbox.show() pane = qltk.ConfigRHPaned("browsers", "soundcloud_pos", 0.4) pane.show() pane.pack1(vbox, resize=False, shrink=False) self._songs_box = songs_box = Gtk.VBox(spacing=6) songs_box.pack_start(self._searchbox, False, True, 0) songs_box.show() pane.pack2(songs_box, resize=True, shrink=False) self.pack_start(pane, True, True, 0) self.show() def Menu(self, songs, library, items): return SongsMenu(library, songs, edit=False, download=True, items=items) @property def online(self): return self.api_client.online def _create_header(self): hbox = Gtk.HBox() button = Gtk.Button(always_show_image=True, relief=Gtk.ReliefStyle.NONE) button.connect('clicked', lambda _: website(SITE_URL)) button.set_tooltip_text(_("Go to %s") % SITE_URL) button.add(self._logo_image) hbox.pack_start(button, True, True, 6) hbox.show_all() return hbox def _create_searchbar(self, library): completion = LibraryTagCompletion(library) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=completion, validator=SoundcloudQuery.validator, accel_group=self.accelerators, timeout=3000) self.__searchbar = search search.connect('query-changed', self.__query_changed) def focus(widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() search.connect('focus-out', focus) self._searchbox = Align(search, left=0, right=6, top=0) self._searchbox.show_all() def update_connect_button(self): but = self.login_button but.set_sensitive(False) tooltip, icon = self._login_state_data[self.login_state] but.set_tooltip_text(tooltip) child = but.get_child() if child: print_d("Removing old image...") but.remove(child) but.add(icon if icon else Gtk.Label(tooltip)) but.get_child().show() but.set_sensitive(True) but.show() def create_login_button(self): def clicked_login(*args): # TODO: use a magic enum next() method, or similar state = self.login_state if state == State.LOGGED_IN: self.api_client.log_out() # Reset the selection, lest it get stuck... sel = self.view.get_selection() sel.unselect_all() first_path = self.view.get_model()[0].path.copy() self.view.set_cursor(first_path) sel.select_path(first_path) self._refresh_online_filters() self.login_state = State.LOGGED_OUT elif state == State.LOGGING_IN: dialog = EnterAuthCodeDialog(app.window) value = dialog.run(clipboard=True) if value: self.login_state = State.LOGGED_IN print_d("Got a user token value of '%s'" % value) self.api_client.get_tokens(value) elif state == State.LOGGED_OUT: self.api_client.authenticate_user() self.login_state = State.LOGGING_IN self.update_connect_button() hbox = Gtk.HBox() self.login_button = login = Gtk.Button(always_show_image=True, relief=Gtk.ReliefStyle.NONE) self.update_connect_button() login.connect('clicked', clicked_login) hbox.pack_start(login, True, False, 0) hbox.show_all() return hbox def _create_category_widget(self): scrolled_window = ScrolledWindow() scrolled_window.show() scrolled_window.set_shadow_type(Gtk.ShadowType.IN) self.view = view = RCMHintedTreeView() view.show() view.set_headers_visible(False) scrolled_window.set_policy( Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(view) model = Gtk.ListStore(int, str, str, str, bool) filters = self.filters for (i, (name, data)) in enumerate(filters): filter_type, icon, query, always = data enabled = always model.append(row=[filter_type, icon, name, query, enabled]) def search_func(model, column, key, iter, data): return key.lower() not in model[iter][column].lower() view.set_search_column(self.ModelIndex.NAME) view.set_search_equal_func(search_func, None) column = Gtk.TreeViewColumn("Songs") column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) renderpb = Gtk.CellRendererPixbuf() renderpb.props.xpad = 6 renderpb.props.ypad = 6 column.pack_start(renderpb, False) column.add_attribute(renderpb, "icon-name", self.ModelIndex.ICON_NAME) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) def cdf(column, cell, model, iter_, user_data): on = (self.login_state == State.LOGGED_IN or model[iter_][self.ModelIndex.ALWAYS_ENABLE]) cell.set_sensitive(on) column.set_cell_data_func(render, cdf) column.set_cell_data_func(renderpb, cdf) view.append_column(column) column.pack_start(render, True) column.add_attribute(render, "text", self.ModelIndex.NAME) view.set_model(model) selection = view.get_selection() def select_func(sel, model, path, value): return (self.login_state == State.LOGGED_IN or model[model.get_iter(path)][self.ModelIndex.ALWAYS_ENABLE]) selection.set_select_function(select_func) selection.select_iter(model.get_iter_first()) self._refresh_online_filters() self.__changed_sig = connect_destroy(selection, 'changed', DeferredSignal(self._on_select)) return scrolled_window def _on_select(self, sel): model, paths = sel.get_selected_rows() if not paths: return row = model[paths[0]] query_text = row[self.ModelIndex.QUERY] filter_type = row[self.ModelIndex.TYPE] if filter_type == FilterType.SEARCH: self.__searchbar.set_enabled() elif filter_type == FilterType.FAVORITES: print_d("Getting favorites...") self.api_client.get_favorites() self.__searchbar.set_enabled(False) elif filter_type == FilterType.MINE: print_d("Getting user tracks...") self.api_client.get_my_tracks() self.__searchbar.set_enabled(False) query_text = query_text % self.api_client.user_id self.__searchbar.set_text(query_text) self.activate() def pack(self, songpane): container = Gtk.VBox() container.add(self) self._songs_box.add(songpane) return container def unpack(self, container, songpane): self._songs_box.remove(songpane) container.remove(self) def __changed(self, library, songs): print_d(f"Updating view for {len(songs)} song(s)") self.activate() def __query_changed(self, bar, text, restore=False): try: self.__filter = SoundcloudQuery(text, self.STAR) self.library.query_with_refresh(self.__filter) except SoundcloudQuery.Error as e: print_d("Couldn't parse query: %s" % e) else: print_d("Got terms from query: %s" % (self.__filter.terms,)) if not restore: self.activate() def __get_selected_libraries(self): """Returns the libraries to search in depending on the filter selection""" return [self.library] def restore(self): filter_type = config.getint("browsers", "soundcloud_selection", FilterType.SEARCH) model = self.view.get_model() it = model.get_iter_first() while it: if model.get_value(it, 0) == filter_type: break it = model.iter_next(it) if filter_type == FilterType.SEARCH: self.__searchbar.set_enabled() self.__inhibit() self.view.get_selection().select_iter(it) self.__uninhibit() text = config.gettext("browsers", "query_text") self.__searchbar.set_text(text) self.__query_changed(None, text, restore=True) def __get_filter(self): return self.__filter or SoundcloudQuery("") def can_filter_text(self): return True def filter_text(self, text): model = self.view.get_model() it = model.get_iter_first() selected = False while it: typ = model.get_value(it, 0) if typ == FilterType.SEARCH: search_it = it elif ((typ == FilterType.FAVORITES and text == "#(rating = 1.0)") or (typ == FilterType.MINE and text == f"soundcloud_user_id={self.api_client.user_id}")): self.view.get_selection().select_iter(it) selected = True break it = model.iter_next(it) if not selected: # We don't want the selection to be cleared, so inhibit # the selection callback method self.__inhibit() self.view.get_selection().select_iter(search_it) self.__uninhibit() self.__searchbar.set_enabled() self.__searchbar.set_text(text) self.__query_changed(None, text) if SoundcloudQuery(text).is_parsable: self.activate() else: print_d("Not parsable: %s" % text) def get_filter_text(self): return self.__searchbar.get_text() def activate(self): print_d("Refreshing browser for query \"%r\"" % self.__filter) songs = self.library.query(self.get_filter_text()) self.songs_selected(songs) def active_filter(self, song): for lib in self.__get_selected_libraries(): if song in lib: filter_ = self.__get_filter() if filter_: return filter_.search(song) return True else: return False def save(self): text = self.__searchbar.get_text() config.settext("browsers", "query_text", text) self.api_client.save_auth() model, paths = self.view.get_selection().get_selected_rows() if paths: row = model[paths[0]] filter_type = row[self.ModelIndex.TYPE] config.set("browsers", "soundcloud_selection", filter_type) def _refresh_online_filters(self): model = self.view.get_model() for row in model: model.row_changed(row.path, model.get_iter(row.path)) def __handle_incoming_uri(self, obj, uri): if not PROCESS_QL_URLS: print_w("Processing of quodlibet:// URLs is disabled. (%s)" % uri) return uri = urlparse(uri) if (uri.scheme == 'quodlibet' and uri.netloc == 'callbacks' and uri.path == '/soundcloud'): try: code = parse_qs(uri.query)["code"][0] except IndexError: print_w("Malformed response in callback URI: %s" % uri) return print_d("Processing Soundcloud callback (%s)" % (uri,)) self.api_client.get_tokens(code) else: print_w("Unknown URL format (%s)" % (uri,)) def __on_authenticated(self, obj, data): name = data.username self.login_state = State.LOGGED_IN self.update_connect_button() self.activate() msg = Message(Gtk.MessageType.INFO, app.window, _("Connected"), _("Quod Libet is now connected, %s!") % name) msg.run() @cached_property def _logo_image(self): return WebImage( "https://developers.soundcloud.com/assets/logo_black.png", 104, 16) @cached_property def _login_state_data(self): """Login-state-based data for configuring actions (e.g. the button)""" return { State.LOGGED_IN: (_("Log out of %s") % SOUNDCLOUD_NAME, sc_btn_image('disconnect-l', 140, 29)), State.LOGGING_IN: (_("Enter code…"), None), State.LOGGED_OUT: (_("Log in to %s") % SOUNDCLOUD_NAME, sc_btn_image('connect-l', 124, 29)), } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/query.py����������������������������������������������0000664�0001750�0001750�00000012240�14231604332�021736� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import time import operator from collections import defaultdict from datetime import datetime from quodlibet import print_d from quodlibet.formats import AudioFile from quodlibet.query import Query, QueryType from quodlibet.query._match import Tag, Inter, Union, Numcmp, NumexprTag, \ Numexpr, True_, False_ INVERSE_OPS = {operator.le: operator.gt, operator.gt: operator.le, operator.lt: operator.ge, operator.ge: operator.lt} _DUMMY_AF = AudioFile() _CLOCK = time.time def convert_time(t): return datetime.strftime(datetime.fromtimestamp(int(t)), '%Y-%m-%d %H:%S') _QL_TO_SC = { 'genre': ('genres', None), 'length': ('duration', lambda x: int((x or 0) * 1000)), 'date': ('created_at', convert_time), 'tags': ('tags', None), 'bpm': ('bpm', None), 'artist': ('q', None), 'title': ('q', None), 'comments': ('q', None), 'soundcloud_user_id': ('user_id', None) } """ Convert QL to Soundcloud tags with optional value mapper""" SUPPORTED = set(_QL_TO_SC.keys()) | {"rating"} class SoundcloudQuery(Query): def __init__(self, string, star=None, clock=time.time): super().__init__(string, star) self._clock = clock try: self.terms = self._extract_terms(self._match) except self.Error as e: print_d("Couldn't use query: %s" % e) self.type = QueryType.INVALID self.terms = {} def _extract_terms(self, node): """ Return a dict of sets keyed on API search term, with values for these that could be used to query the API and might return results useful for populating the songlist. Note this is not a *translation* of the query in any sense, and that (currently) the browser filters ingested API results so that the QL results are still valid based on the query given, even if some more could have been returned. ...so if in doubt, *less* restrictive is better here.""" tuples = self._extract_terms_set(node) terms = defaultdict(set) for (k, v) in tuples: terms[k].add(v) return terms def _extract_terms_set(self, node, tag=None): def to_api(tag, raw_value): try: api_tag, converter = _QL_TO_SC[tag] if tag else ('q', None) except KeyError: if tag not in SUPPORTED: raise self.Error("Unsupported '%s' tag. Try: %s" % (tag, ", ". join(SUPPORTED))) return None, None else: value = str(converter(raw_value) if converter else raw_value) return api_tag, value def terms_from_re(pattern, t): """Best efforts to de-regex""" pat = pattern.lstrip('^').rstrip('$') api_tag, pat = to_api(t, pat) return {(api_tag, p) for p in pat.split('|')} if api_tag else set() if isinstance(node, Tag) and set(node._names) & SUPPORTED: if len(node._names) == 1: return self._extract_terms_set(node.res, tag=node._names[0]) return self._extract_terms_set(node.res) elif isinstance(node, (Inter, Union)): # Treat identically as the text-based query will perform # relevance ranking itself, meaning that any term is still useful terms = set() for n in node.res: terms |= self._extract_terms_set(n) return terms elif isinstance(node, Numcmp): def from_relative(op, l, r): raw_value = r.evaluate(_DUMMY_AF, self._clock(), True) tag, value = to_api(l._tag, raw_value) if not value: return set() if op == operator.eq: return {(tag, value)} elif op in (operator.le, operator.lt): return {(tag + "[to]", value)} elif op in (operator.ge, operator.gt): return {(tag + "[from]", value)} raise self.Error("Unsupported operator: %s" % op) left = node._expr right = node._expr2 if isinstance(left, NumexprTag) and isinstance(right, Numexpr): return from_relative(node._op, left, right) elif isinstance(right, NumexprTag) and isinstance(left, Numexpr): # We can reduce the logic by flipping the expression return from_relative(INVERSE_OPS[node._op], right, left) raise self.Error("Unsupported numeric: %s" % node) elif hasattr(node, 'pattern'): return terms_from_re(node.pattern, tag) elif isinstance(node, True_): return set() elif isinstance(node, False_): raise self.Error("False can never be queried") raise self.Error("Unhandled node: %r" % (node,)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/soundcloud/util.py�����������������������������������������������0000664�0001750�0001750�00000006104�14231604332�021550� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from datetime import datetime from typing import Dict, Any from quodlibet import print_d, _ from quodlibet.qltk import WebImage from quodlibet.qltk.getstring import GetStringDialog from quodlibet.util import enum SOUNDCLOUD_NAME = "Soundcloud" PROCESS_QL_URLS = True DEFAULT_BITRATE = 128 EPOCH = datetime(1970, 1, 1) SITE_URL = "https://soundcloud.com" class Wrapper: """Object-like wrapper for read-only dictionaries""" def __init__(self, data: Dict[str, Any]): self._raw = data assert isinstance(data, dict) self.data: Dict = {} for k, v in data.items(): if isinstance(v, Dict): self.data[k] = Wrapper(v) else: self.data[k] = v def __getattr__(self, name): if name in self.data: return self.data.get(name) raise AttributeError("'%s' not found" % (name,)) def __getitem__(self, item): return self.data[item] def __setitem__(self, key, value): raise NotImplementedError def get(self, name, default=None): return self.data.get(name, default) def __str__(self): return "<Wrapped: %s>" % self.data def json_callback(wrapped): """Decorator for `download_json` callbacks, handling common errors""" def _callback(self, message, json, data): if json is None: print_d(f"[HTTP {message.status_code}] Invalid / empty JSON. " f"Body: {message.response_body.data!r} (request: {data})") return if 'errors' in json: raise ValueError("Got HTTP %d (%s)" % (message.status_code, json['errors'])) if 'error' in json: raise ValueError("Got HTTP %d (%s)" % (message.status_code, json['error'])) return wrapped(self, json, data) return _callback def clamp(val, low, high): intval = int(val or 0) return max(low, min(high, intval)) @enum class State(int): LOGGED_OUT, LOGGING_IN, LOGGED_IN = range(3) @enum class FilterType(int): SEARCH, FAVORITES, MINE = range(3) class EnterAuthCodeDialog(GetStringDialog): def __init__(self, parent): super().__init__( parent, _("Soundcloud authorisation"), _("Enter Soundcloud auth code:"), button_icon=None) def _verify_clipboard(self, text): if len(text) > 10: return text def sanitise_tag(value): """QL doesn't want newlines in tags, but they Soundcloud ones are not always best represented as multi-value tags (comments, etc) """ return (value or '').replace('\n', '\t').replace('\r', '') def sc_btn_image(path, w, h): return WebImage('https://connect.soundcloud.com/2/btn-%s.png' % path, w, h) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689587289.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/browsers/tracks.py��������������������������������������������������������0000644�0001750�0001750�00000012130�14455207131�017701� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2022 Joe Wreschnig, Michael Urman, Iñigo Serna, # Christoph Reiter, Steven Robertson, Nick Boultbee, # 2018-2019 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib from quodlibet import app from quodlibet import config from quodlibet import qltk from quodlibet import _ from quodlibet.browsers import Browser from quodlibet.qltk import is_accel from quodlibet.qltk.ccb import ConfigCheckMenuItem from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.searchbar import MultiSearchBarBox from quodlibet.qltk.songlist import SongList from quodlibet.qltk.x import SymbolicIconImage, Align from quodlibet.qltk import Icons class PreferencesButton(Gtk.HBox): def __init__(self, search_bar_box): super().__init__() menu = Gtk.Menu() limit_item = ConfigCheckMenuItem( _("_Limit Results"), "browsers", "search_limit", True) limit_item.connect("toggled", search_bar_box.toggle_limit_widgets) menu.append(limit_item) multi_item = ConfigCheckMenuItem( _("_Allow multiple queries"), "browsers", "multiple_queries", True) multi_item.connect("toggled", search_bar_box.toggle_multi) menu.append(multi_item) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) self.pack_start(button, True, True, 0) class TrackList(Browser): name = _("Track List") accelerated_name = _("_Track List") keys = ["SearchBar", "TrackList"] priority = 1 def pack(self, songpane): container = Gtk.VBox(spacing=6) container.pack_start(self, False, True, 0) container.pack_start(songpane, True, True, 0) return container def unpack(self, container, songpane): container.remove(songpane) container.remove(self) def __init__(self, library): super().__init__(spacing=6, orientation=Gtk.Orientation.VERTICAL) self._query = None self._library = library completion = LibraryTagCompletion(library.librarian) self.accelerators = Gtk.AccelGroup() show_limit = config.getboolean("browsers", "search_limit") show_multi = config.getboolean("browsers", "multiple_queries") sbb = MultiSearchBarBox(completion=completion, accel_group=self.accelerators, show_limit=show_limit, show_multi=show_multi) sbb.connect('query-changed', self.__text_parse) sbb.connect('focus-out', self.__focus) sbb.connect('key-press-event', self.__sb_key_pressed) self._sb_box = sbb prefs = PreferencesButton(sbb) sbb.pack_start(prefs, False, True, 0) self.pack_start(Align(sbb, left=6, right=6), False, True, 0) self.pack_start(sbb.flow_box, False, True, 0) self.connect('destroy', self.__destroy) self.show_all() def _get_text(self): return self._sb_box.get_text() def _set_text(self, text): self._sb_box.set_text(text) def __destroy(self, *args): self._sb_box = None def __focus(self, widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() def _get_songs(self): self._query = self._sb_box.get_query(SongList.star) return self._query.filter(self._library) if self._query else None def activate(self): songs = self._get_songs() if songs is not None: songs = self._sb_box.limit(songs) GLib.idle_add(self.songs_selected, songs) def __text_parse(self, bar, text): self.activate() def __sb_key_pressed(self, entry, event): if (is_accel(event, "<Primary>Return") or is_accel(event, "<Primary>KP_Enter")): songs = app.window.songlist.get_songs() limit = config.getint("browsers", "searchbar_enqueue_limit") app.window.enqueue(songs, limit) return True return False def save(self): config.settext("browsers", "query_text", self._get_text()) self._sb_box.save() def restore(self): text = config.gettext("browsers", "query_text") self._set_text(text) self._sb_box.load() def finalize(self, restore): config.set("browsers", "query_text", "") def can_filter_text(self): return True def filter_text(self, text): self._set_text(text) self.activate() def get_filter_text(self): return self._get_text() def unfilter(self): self.filter_text("") def active_filter(self, song): if self._query is not None: return self._query.search(song) else: return True browsers = [TrackList] ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/build.py������������������������������������������������������������������0000664�0001750�0001750�00000001143�14035600052�015640� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """This file gets edited at build time to add build specific data""" BUILD_TYPE = u"default" """Either 'windows', 'windows-portable', 'osx-quodlibet', 'osx-exfalso' or 'default'""" BUILD_INFO = u"" """Additional build info like git revision etc""" BUILD_VERSION = 0 """1.2.3 with a BUILD_VERSION of 1 results in 1.2.3.1""" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1674482028.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/cli.py��������������������������������������������������������������������0000644�0001750�0001750�00000024543�14363510554�015332� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014,2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import json import os from senf import fsn2text, uri2fsn from quodlibet import C_, _ from quodlibet.util.dprint import print_, print_e from quodlibet.remote import Remote, RemoteError def exit_(status=None, notify_startup=False): """Call this to abort the startup before any mainloop starts. notify_startup needs to be true if QL could potentially have been called from the desktop file. """ if notify_startup: import gi gi.require_version("Gdk", "3.0") from gi.repository import Gdk Gdk.notify_startup_complete() raise SystemExit(status) def is_running(): """If maybe is another instance running""" return Remote.remote_exists() def control(command, arg=None, ignore_error=False): """Sends command to the existing instance if possible and exits. Will print any response it gets to stdout. Does not return except if ignore_error is True and sending the command failed. """ if not is_running(): if ignore_error: return exit_(_("Quod Libet is not running (add '--run' to start it)"), notify_startup=True) return message = command if arg is not None: message += " " + arg try: response = Remote.send_message(message) except RemoteError as e: if ignore_error: return exit_(str(e), notify_startup=True) else: if response is not None: print_(response, end="", flush=True) exit_(notify_startup=True) def process_arguments(argv): from quodlibet.util.path import uri_is_valid from quodlibet import util from quodlibet import const actions = [] controls = ["next", "previous", "play", "pause", "play-pause", "stop", "hide-window", "show-window", "toggle-window", "focus", "quit", "unfilter", "refresh", "force-previous"] controls_opt = ["seek", "repeat", "query", "volume", "filter", "rating", "set-browser", "open-browser", "shuffle", "queue", "stop-after", "random", "repeat-type", "shuffle-type", "add-location"] options = util.OptionParser( "Quod Libet", const.VERSION, _("a music library and player"), _("[option]")) options.add("print-playing", help=_("Print the playing song and exit")) options.add("start-playing", help=_("Begin playing immediately")) options.add("start-hidden", help=_("Don't show any windows on start")) for opt, help in [ ("next", _("Jump to next song")), ("previous", _("Jump to previous song or restart if near the beginning")), ("force-previous", _("Jump to previous song")), ("play", _("Start playback")), ("pause", _("Pause playback")), ("play-pause", _("Toggle play/pause mode")), ("stop", _("Stop playback")), ("volume-up", _("Turn up volume")), ("volume-down", _("Turn down volume")), ("rating-up", _("Increase rating of playing song by one star")), ("rating-down", _("Decrease rating of playing song by one star")), ("status", _("Print player status")), ("hide-window", _("Hide main window")), ("show-window", _("Show main window")), ("toggle-window", _("Toggle main window visibility")), ("focus", _("Focus the running player")), ("unfilter", _("Remove active browser filters")), ("refresh", _("Refresh and rescan library")), ("list-browsers", _("List available browsers")), ("print-playlist", _("Print the current playlist")), ("print-queue", _("Print the contents of the queue")), ("print-query-text", _("Print the active text query")), ("no-plugins", _("Start without plugins")), ("run", _("Start Quod Libet if it isn't running")), ("quit", _("Exit Quod Libet")), ]: options.add(opt, help=help) for opt, help, arg in [ ("seek", _("Seek within the playing song"), _("[+|-][HH:]MM:SS")), ("shuffle", _("Set or toggle shuffle mode"), "0|1|t"), ("shuffle-type", _("Set shuffle mode type"), "random|weighted|off"), ("repeat", _("Turn repeat off, on, or toggle it"), "0|1|t"), ("repeat-type", _("Set repeat mode type"), "current|all|one|off"), ("volume", _("Set the volume"), "[+|-]0..100"), ("query", _("Search your audio library"), _("query")), ("play-file", _("Play a file"), C_("command", "filename")), ("rating", _("Set rating of playing song"), "[+|-]0.0..1.0"), ("set-browser", _("Set the current browser"), "BrowserName"), ("stop-after", _("Stop after the playing song"), "0|1|t"), ("open-browser", _("Open a new browser"), "BrowserName"), ("queue", _("Show or hide the queue"), "on|off|t"), ("random", _("Filter on a random value"), C_("command", "tag")), ("filter", _("Filter on a tag value"), _("tag=value")), ("enqueue", _("Enqueue a file or query"), "%s|%s" % ( C_("command", "filename"), _("query"))), ("enqueue-files", _("Enqueue comma-separated files"), "%s[,%s..]" % ( _("filename"), _("filename"))), ("print-query", _("Print filenames of results of query to stdout"), _("query")), ("unqueue", _("Unqueue a file or query"), "%s|%s" % ( C_("command", "filename"), _("query"))), ("add-location", _("Add a file or directory to the library"), _("location")), ("with-pattern", _("Set template for --print-* commands"), _("pattern")), ]: options.add(opt, help=help, arg=arg) options.add("sm-config-prefix", arg="dummy") options.add("sm-client-id", arg="prefix") options.add("screen", arg="dummy") def is_vol(str): if len(str) == 1 and str[0] in '+-': return True return is_float(str) def is_rate(str): if len(str) == 1 and str[0] in '+-': return True return is_float(str) def is_time(str): if str[0] not in "+-0123456789": return False elif str[0] in "+-": str = str[1:] parts = str.split(":") if len(parts) > 3: return False else: return not (False in [p.isdigit() for p in parts]) def is_float(str): try: float(str) except ValueError: return False else: return True validators = { "shuffle": ["0", "1", "t", "on", "off", "toggle"].__contains__, "shuffle-type": ["random", "weighted", "off", "0"].__contains__, "repeat": ["0", "1", "t", "on", "off", "toggle"].__contains__, "repeat-type": ["current", "all", "one", "off", "0"].__contains__, "volume": is_vol, "seek": is_time, "rating": is_rate, "stop-after": ["0", "1", "t"].__contains__, } cmds_todo = [] def queue(*args): cmds_todo.append(args) # XXX: to make startup work in case the desktop file isn't passed # a file path/uri if argv[-1] == "--play-file": argv = argv[:-1] opts, args = options.parse(argv[1:]) for command, arg in opts.items(): if command in controls: queue(command) elif command in controls_opt: if command in validators and not validators[command](arg): print_e(_("Invalid argument for '%s'.") % command) print_e(_("Try %s --help.") % fsn2text(argv[0])) exit_(True, notify_startup=True) else: queue(command, arg) elif command == "status": queue("status") elif command == "print-playlist": queue("dump-playlist", opts.get('with-pattern')) elif command == "print-queue": queue("dump-queue", opts.get('with-pattern')) elif command == "list-browsers": queue("dump-browsers") elif command == "volume-up": queue("volume +") elif command == "volume-down": queue("volume -") elif command == "rating-up": queue("rating +") elif command == "rating-down": queue("rating -") elif command == "enqueue" or command == "unqueue": try: filename = uri2fsn(arg) except ValueError: filename = arg queue(command, filename) elif command == "enqueue-files": queue(command, arg) elif command == "play-file": if uri_is_valid(arg) and arg.startswith("quodlibet://"): # TODO: allow handling of URIs without --play-file queue("uri-received", arg) else: try: filename = uri2fsn(arg) except ValueError: filename = arg filename = os.path.abspath(os.path.expanduser(arg)) queue("play-file", filename) elif command == 'add-location': try: path = uri2fsn(arg) except ValueError: path = arg path = os.path.abspath(os.path.expanduser(arg)) queue("add-location", path) elif command == "print-playing": try: queue("print-playing", args[0]) except IndexError: queue("print-playing", opts.get('with-pattern')) elif command == "print-query": pattern = opts.get('with-pattern') queue(command, json.dumps({"query": arg, 'pattern': pattern})) elif command == "print-query-text": queue(command) elif command == "start-playing": actions.append(command) elif command == "start-hidden": actions.append(command) elif command == "no-plugins": actions.append(command) elif command == "run": actions.append(command) if cmds_todo: for cmd in cmds_todo: control(*cmd, **{"ignore_error": "run" in actions}) else: # this will exit if it succeeds control('focus', ignore_error=True) return actions, cmds_todo �������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689589191.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/commands.py���������������������������������������������������������������0000644�0001750�0001750�00000035702�14455212707�016364� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna, # 2011-2020 Nick Boultbee # 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import json import os from senf import uri2fsn, fsnative, fsn2text, text2fsn from quodlibet.util.string import split_escape from quodlibet import browsers from quodlibet import util from quodlibet.util import print_d, print_e, copool from quodlibet.qltk.browser import LibraryBrowser from quodlibet.qltk.properties import SongProperties from quodlibet.util.library import scan_library from quodlibet.order.repeat import RepeatListForever, RepeatSongForever, OneSong from quodlibet.order.reorder import OrderWeighted, OrderShuffle from quodlibet.pattern import Pattern from quodlibet.config import RATINGS class CommandError(Exception): pass class CommandRegistry: """Knows about all commands and handles parsing/executing them""" def __init__(self): self._commands = {} def register(self, name, args=0, optional=0): """Register a new command function The functions gets zero or more arguments as `fsnative` and should return `None` or `fsnative`. In case an error occurred the command should raise `CommandError`. Args: name (str): the command name args (int): amount of required arguments optional (int): amount of additional optional arguments Returns: Callable """ def wrap(func): self._commands[name] = (func, args, optional) return func return wrap def handle_line(self, app, line): """Parses a command line and executes the command. Can not fail. Args: app (Application) line (fsnative) Returns: fsnative or None """ assert isinstance(line, fsnative) # only one arg supported atm parts = line.split(" ", 1) command = parts[0] args = parts[1:] print_d("command: %r(*%r)" % (command, args)) try: return self.run(app, command, *args) except CommandError as e: print_e(e) util.print_exc() except: util.print_exc() def run(self, app, name, *args): """Execute the command `name` passing args May raise CommandError """ if name not in self._commands: raise CommandError("Unknown command %r" % name) cmd, argcount, optcount = self._commands[name] if len(args) < argcount: raise CommandError("Not enough arguments for %r" % name) if len(args) > argcount + optcount: raise CommandError("Too many arguments for %r" % name) print_d("Running %r with params %s " % (cmd.__name__, args)) try: result = cmd(app, *args) except CommandError as e: raise CommandError("%s: %s" % (name, str(e))) else: if result is not None and not isinstance(result, fsnative): raise CommandError( "%s: returned %r which is not fsnative" % (name, result)) return result def arg2text(arg): """Like fsn2text but is strict by default and raises CommandError""" try: return fsn2text(arg, strict=True) except ValueError as e: raise CommandError(e) def make_pattern(fstring, default): if fstring is None: return Pattern(default) return Pattern(arg2text(fstring)) registry = CommandRegistry() @registry.register("previous") def _previous(app): app.player.previous() @registry.register("force-previous") def _force_previous(app): app.player.previous(True) @registry.register("next") def _next(app): app.player.next() @registry.register("pause") def _pause(app): app.player.paused = True @registry.register("play") def _play(app): app.player.play() @registry.register("play-pause") def _play_pause(app): app.player.playpause() @registry.register("stop") def _stop(app): app.player.stop() @registry.register("focus") def _focus(app): app.present() @registry.register("volume", args=1) def _volume(app, value): if not value: raise CommandError("invalid arg") if value[0] in ('+', '-'): if len(value) > 1: try: change = (float(value[1:]) / 100.0) except ValueError: return else: change = 0.05 if value[0] == '-': change = -change volume = app.player.volume + change else: try: volume = (float(value) / 100.0) except ValueError: return app.player.volume = min(1.0, max(0.0, volume)) @registry.register("stop-after", args=1) def _stop_after(app, value): po = app.player_options if value == "0": po.stop_after = False elif value == "1": po.stop_after = True elif value == "t": po.stop_after = not po.stop_after else: raise CommandError("Invalid value %r" % value) @registry.register("shuffle", args=1) def _shuffle(app, value): po = app.player_options if value in ["0", "off"]: po.shuffle = False elif value in ["1", "on"]: po.shuffle = True elif value in ["t", "toggle"]: po.shuffle = not po.shuffle @registry.register("shuffle-type", args=1) def _shuffle_type(app, value): if value in ["random", "weighted"]: app.player_options.shuffle = True if value == "random": app.window.order.shuffler = OrderShuffle elif value == "weighted": app.window.order.shuffler = OrderWeighted elif value in ["off", "0"]: app.player_options.shuffle = False @registry.register("repeat", args=1) def _repeat(app, value): po = app.player_options if value in ["0", "off"]: po.repeat = False elif value in ["1", "on"]: print_d("Enabling repeat") po.repeat = True elif value in ["t", "toggle"]: po.repeat = not po.repeat @registry.register("repeat-type", args=1) def _repeat_type(app, value): if value in ["current", "all", "one"]: app.player_options.repeat = True if value == "current": app.window.order.repeater = RepeatSongForever elif value == "all": app.window.order.repeater = RepeatListForever elif value == "one": app.window.order.repeater = OneSong elif value in ["off", "0"]: app.player_options.repeat = False @registry.register("seek", args=1) def _seek(app, time): player = app.player if not player.song: return seek_to = player.get_position() if time[0] == "+": seek_to += util.parse_time(time[1:]) * 1000 elif time[0] == "-": seek_to -= util.parse_time(time[1:]) * 1000 else: seek_to = util.parse_time(time) * 1000 seek_to = min(player.song.get("~#length", 0) * 1000 - 1, max(0, seek_to)) player.seek(seek_to) @registry.register("play-file", args=1) def _play_file(app, value): app.window.open_file(value) @registry.register("add-location", args=1) def _add_location(app, value): if os.path.isfile(value): ret = app.library.add_filename(value) if not ret: print_e("Couldn't add file to library") elif os.path.isdir(value): copool.add(app.library.scan, [value], cofuncid="library", funcid="library") else: print_e("Invalid location") @registry.register("toggle-window") def _toggle_window(app): if app.window.get_property('visible'): app.hide() else: app.show() @registry.register("hide-window") def _hide_window(app): app.hide() @registry.register("show-window") def _show_window(app): app.show() @registry.register("rating", args=1) def _rating(app, value): song = app.player.song if not song: return if value[0] in ('+', '-'): if len(value) > 1: try: change = float(value[1:]) except ValueError: return else: change = (1 / RATINGS.number) if value[0] == '-': change = -change rating = song("~#rating") + change else: try: rating = float(value) except (ValueError, TypeError): return song["~#rating"] = max(0.0, min(1.0, rating)) app.library.changed([song]) @registry.register("dump-browsers") def _dump_browsers(app): response = u"" for i, b in enumerate(browsers.browsers): response += u"%d. %s\n" % (i, browsers.name(b)) return text2fsn(response) @registry.register("set-browser", args=1) def _set_browser(app, value): if not app.window.select_browser(value, app.library, app.player): raise CommandError("Unknown browser %r" % value) @registry.register("open-browser", args=1) def _open_browser(app, value): value = arg2text(value) try: Kind = browsers.get(value) except ValueError: raise CommandError("Unknown browser %r" % value) LibraryBrowser.open(Kind, app.library, app.player) @registry.register("random", args=1) def _random(app, tag): tag = arg2text(tag) if app.browser.can_filter(tag): app.browser.filter_random(tag) @registry.register("filter", args=1) def _filter(app, value): value = arg2text(value) try: tag, value = value.split('=', 1) except ValueError: raise CommandError("invalid argument") if app.browser.can_filter(tag): app.browser.filter(tag, [value]) @registry.register("query", args=1) def _query(app, value): value = arg2text(value) if app.browser.can_filter_text(): app.browser.filter_text(value) @registry.register("unfilter") def _unfilter(app): app.browser.unfilter() @registry.register("properties", optional=1) def _properties(app, value=None): library = app.library player = app.player window = app.window if value is not None: value = arg2text(value) if value in library: songs = [library[value]] else: songs = library.query(value) else: songs = [player.song] songs = list(filter(None, songs)) if songs: window = SongProperties(library, songs, parent=window) window.show() @registry.register("enqueue", args=1) def _enqueue(app, value): playlist = app.window.playlist library = app.library if value in library: songs = [library[value]] elif os.path.isfile(value): songs = [library.add_filename(os.path.realpath(value))] else: songs = library.query(arg2text(value)) songs.sort() playlist.enqueue(songs) @registry.register("enqueue-files", args=1) def _enqueue_files(app, value): """Enqueues comma-separated filenames or song names. Commas in filenames should be backslash-escaped""" library = app.library window = app.window songs = [] for param in split_escape(value, ","): try: song_path = uri2fsn(param) except ValueError: song_path = param if song_path in library: songs.append(library[song_path]) elif os.path.isfile(song_path): songs.append(library.add_filename(os.path.realpath(value))) if songs: window.playlist.enqueue(songs) @registry.register("unqueue", args=1) def _unqueue(app, value): window = app.window library = app.library playlist = window.playlist if value in library: songs = [library[value]] else: songs = library.query(arg2text(value)) playlist.unqueue(songs) @registry.register("quit") def _quit(app): app.quit() @registry.register("status") def _status(app): player = app.player if player.paused: strings = ["paused"] else: strings = ["playing"] strings.append(type(app.browser).__name__) po = app.player_options strings.append("%0.3f" % player.volume) strings.append("shuffle" if po.shuffle else "inorder") strings.append("on" if po.repeat else "off") progress = 0 if player.info: length = player.info.get("~#length", 0) if length: progress = player.get_position() / (length * 1000.0) strings.append("%0.3f" % progress) status = u" ".join(strings) + u"\n" return text2fsn(status) @registry.register("queue", args=1) def _queue(app, value): window = app.window value = arg2text(value) if value.startswith("t"): value = not window.qexpander.get_property('visible') else: value = value not in ['0', 'off', 'false'] window.qexpander.set_property('visible', value) @registry.register("dump-playlist", optional=1) def _dump_playlist(app, fstring=None): pattern = make_pattern(fstring, '<~uri>') window = app.window items = [] for song in window.playlist.pl.get(): items.append(pattern.format(song)) return text2fsn(u"\n".join(items) + u"\n") @registry.register("dump-queue", optional=1) def _dump_queue(app, fstring=None): pattern = make_pattern(fstring, '<~uri>') window = app.window items = [] for song in window.playlist.q.get(): items.append(pattern.format(song)) return text2fsn(u"\n".join(items) + u"\n") @registry.register("refresh") def _refresh(app): scan_library(app.library, False) @registry.register("print-query", args=1) def _print_query(app, json_encoded_args): """Queries library, dumping filenames of matches to stdout See Issue 716 """ try: args = json.loads(arg2text(json_encoded_args)) query = args['query'] fstring = args['pattern'] except (json.decoder.JSONDecodeError, KeyError, TypeError): # backward compatibility query = arg2text(json_encoded_args) fstring = None if (not isinstance(query, str) or (fstring is not None and not isinstance(fstring, str))): # This should not happen return "\n" pattern = make_pattern(fstring, '<~filename>') songs = app.library.query(query) return "\n".join([text2fsn(pattern.format(song)) for song in songs]) + "\n" @registry.register("print-query-text") def _print_query_text(app): if app.browser.can_filter_text(): return text2fsn(str(app.browser.get_filter_text()) + u"\n") @registry.register("print-playing", optional=1) def _print_playing(app, fstring=None): from quodlibet.formats import AudioFile pattern = make_pattern(fstring, u"<artist~album~tracknumber~title>") song = app.player.info if song is None: song = AudioFile({"~filename": fsnative(u"/")}) song.sanitize() else: song = app.player.with_elapsed_info(song) return text2fsn(pattern.format(song) + u"\n") @registry.register("uri-received", args=1) def _uri_received(app, uri): uri = arg2text(uri) app.browser.emit("uri-received", uri) ��������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681489057.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/config.py�����������������������������������������������������������������0000644�0001750�0001750�00000033677�14416276241�016041� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2008 Joe Wreschnig # 2009-2022 Nick Boultbee # 2011-2014 Christoph Reiter # 2018-2019 Peter Strulo # 2022 Jej@github # # 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 2 of the License, or # (at your option) any later version. from typing import Dict import shutil from quodlibet.util import enum from . import const from quodlibet.util.config import Config, Error from quodlibet.util import print_d, print_w from quodlibet.util import is_osx, is_windows # Some plugins can be enabled on first install AUTO_ENABLED_PLUGINS = ["Shuffle Playlist", "Remove Playlist Duplicates"] # this defines the initial and default values INITIAL: Dict[str, Dict[str, str]] = { # User-defined tag name -> human name mappings "header_maps": { }, "player": { "time_remaining": "false", "replaygain": "on", "fallback_gain": "0.0", "pre_amp_gain": "0.0", "backend": "gstbe", "gst_pipeline": "", # stream buffer duration in seconds "gst_buffer": "3", "gst_device": "", "gst_disable_gapless": "false", # Use Jack sink (via Gstreamer) if available "gst_use_jack": "false", # Usually true is good here, but if you have patchbay configured maybe not... "gst_jack_auto_connect": "true", "is_playing": "false", "restore_playing": "false", # Consider a track as played after listening to # this proportion of its overall length "playcount_minimum_length_proportion": "0.5", }, "library": { "exclude": "", "refresh_on_start": "true", # Watch all library files / directories for changes "watch": "false" }, # State about the player, to restore on startup "memory": { # filename of last song "song": "", # last song position, in milliseconds "seek": "0", # internal volume, [0.0, 1.0] "volume": "1.0", # browser name "browser": "PanedBrowser", "queue": "false", "queue_expanded": "false", "shufflequeue": "false", "queue_stop_at_end": "false", "queue_keep_songs": "false", "queue_disable": "false", # <reversed?>tagname, song list sort "sortby": "0album", # Repeat on or off "repeat": "false", # The Repeat (Order) to use "repeat_mode": "repeat_song", # Shuffle on or off "shuffle": "false", # The Shuffle (Order) to use "shuffle_mode": "random", # selected plugin in manager "plugin_selection": "", # column widths in c1,w1,c2,w2... format "column_widths": "", "column_expands": "", }, "song_list": { # Automatically re-sort song list when tags are modified "auto_sort": "true", # Make all browsers sortable even "always_allow_sorting": "true" }, "browsers": { # search bar text "query_text": "", # number of history entries in the search bar "searchbar_historic_entries": "8", # confirmation limit on enqueuing songs from the search bar "searchbar_enqueue_limit": "50", # panes in paned browser "panes": "~people\t<~year|[b][i]<~year>[/i][/b] - ><album>", # selected pane values "pane_selection": "", # equal pane width in paned browser "equal_pane_width": "true", # "global" filter for SearchBar "background": "", # characters ignored in queries "ignored_characters": "", # album list "albums": "", # album sorting mode, default is title "album_sort": "0", # album cover display, on/off "album_covers": "1", # include substrings in inline search "album_substrings": "1", # Collections browser: tag to collect, merge or not (0 = no) "collection_headers": "~people 0", # radio filter selection "radio": "", # click to rate song, on/off "rating_click": "true", # confirm rating multiple songs "rating_confirm_multiple": "false", # max cover height/width, <= 0 is default "cover_size": "-1", # Show the limit widgets for SearchBar "search_limit": "false", # Allow multiple queries in SearchBar "multiple_queries": "false", # show text in covergrid view "album_text": "1", # Cover magnifcation factor in covergrid view "covergrid_magnification": "3.0", # show "all albums" in covergrid view "covergrid_all": "1", # Template to build the track title when title tag is missing "missing_title_template": "<~basename> [untitled <~format>]", }, # Kind of a dumping ground right now, should probably be # cleaned out later. "settings": { # scan directories, :-separated "scan": "", # scroll song list on current song change "jump": "true", # Unrated songs are given this value "default_rating": "0.5", # Rating scale i.e. maximum number of symbols "ratings": "4", # (0 = disabled i.e. arithmetic mean) "bayesian_rating_factor": "0.0", # rating symbol (black star) "rating_symbol_full": u'\u2605', # rating symbol (hollow star) "rating_symbol_blank": u'\u2606', # Comma-separated columns to display in the song list "columns": ",".join(const.DEFAULT_COLUMNS), # hack to disable hints, see bug #526 "disable_hints": "false", # search as soon as text is typed into search box "eager_search": "true", # tags which get searched in addition to the ones present in the # song list, separate with "," "search_tags": "", # If set to "true" allow directly deleting files, even on systems that # support sending them to the trash. "bypass_trash": "false", # osx implementation might be buggy so let users disable it "disable_mmkeys": "false", # the UI language to use, empty means system default "language": "", # the pattern for the main window title "window_title_pattern": "~title~version~~people", # the format of the timestamps in DateColumn "datecolumn_timestamp_format": "", # scrollbar does not fade out when inactive "scrollbar_always_visible": "true" if (is_osx() or is_windows()) else "false", # Force fontconfig as PangoCairo backend "pangocairo_force_fontconfig": "false", # Whether the plugin window appears on top of others "plugins_window_on_top": "false", # search bar font style (#3647) "monospace_query": "false", # size to apply to query box, in any Pango CSS units (e.g. '100%', '1rem') "query_font_size": "100%", # Amount of colour to apply to validating text entries # (0.0 = no colour, 1.0 = full colour) "validator_colorise": "0.4" }, "autosave": { # Maximum time, in seconds, before saving the play queue to disk. # Zero to disable periodic saving (batched instead) "queue_interval": "60" }, "rename": { "spaces": "false", "windows": "true", "ascii": "false", "move_art": "false", "move_art_overwrite": "false", "remove_empty_dirs": "false", }, "tagsfrompath": { "underscores": "false", "titlecase": "false", "split": "false", "add": "false", }, "plugins": { # newline-separated plugin IDs "active_plugins": "\n".join(AUTO_ENABLED_PLUGINS), # Issue 1231: Maximum number of SongsMenu plugins to run at once "default_max_plugin_invocations": "30", }, "editing": { # characters to split tags on "split_on": "/ & ,", # characters used when extracting subtitles/subtags "sub_split_on": "\u301c\u301c \uff08\uff09 [] () ~~ --", # ID3 encodings to try "id3encoding": "", "human_title_case": "true", "save_to_songs": "true", "save_email": const.EMAIL, # show all tags, or just "human-readable" ones "alltags": "true", # Show multi-line tags "show_multi_line_tags": "true", # Which tags can be multi-line (comma-separated) "multi_line_tags": "lyrics,comment", # Skip dialog to save or revert changes "auto_save_changes": "false", # e.g. "title,artist" "default_tags": "", }, "albumart": { "prefer_embedded": "false", "force_filename": "false", "filename": "folder.jpg", "search_filenames": "cover.jpg,folder.jpg,.folder.jpg", }, "display": { "duration_format": "standard" } } # global instance _config = Config(version=0) options = _config.options get = _config.get gettext = _config.gettext getboolean = _config.getboolean getint = _config.getint getfloat = _config.getfloat getstringlist = _config.getstringlist setstringlist = _config.setstringlist getlist = _config.getlist setlist = _config.setlist set = _config.set settext = _config.settext write = _config.write reset = _config.reset add_section = _config.add_section has_option = _config.has_option remove_option = _config.remove_option register_upgrade_function = _config.register_upgrade_function getbytes = _config.getbytes setbytes = _config.setbytes _filename = None """The filename last used for loading""" def init_defaults(): """Fills in the defaults, so they are guaranteed to be available""" _config.defaults.clear() for section, values in INITIAL.items(): _config.defaults.add_section(section) for key, value in values.items(): _config.defaults.set(section, key, value) def init(filename=None): global _filename if not _config.is_empty(): _config.clear() _filename = filename if filename is not None: try: _config.read(filename) except (Error, EnvironmentError): print_w("Reading config file %r failed." % filename) # move the broken file out of the way try: shutil.copy(filename, filename + ".not-valid") except EnvironmentError: pass def save(filename=None): """Writes the active config to filename, ignoring all possible errors. If not filename is given the one used for loading is used. """ global _filename if filename is None: filename = _filename if filename is None: return print_d("Writing config...") try: _config.write(filename) except EnvironmentError: print_w("Unable to write config.") def quit(): """Clears the active config""" _config.clear() def state(arg): return _config.getboolean("settings", arg) class RatingsPrefs: """ Models Ratings settings as configured by the user, with caching. """ def __init__(self): self.__number = self.__default = None self.__full_symbol = self.__blank_symbol = None @property def precision(self): """Returns the smallest ratings delta currently configured""" return 1.0 / self.number @property def number(self): if self.__number is None: self.__number = getint("settings", "ratings") return self.__number @number.setter def number(self, i): """The (maximum) integer number of ratings icons configured""" self.__number = self.__save("ratings", int(i)) @property def default(self): """The current default floating-point rating""" if self.__default is None: self.__default = getfloat("settings", "default_rating") return self.__default @default.setter def default(self, f): self.__default = self.__save("default_rating", float(f)) @property def full_symbol(self): """The symbol to use for a full (active) rating""" if self.__full_symbol is None: self.__full_symbol = self.__get_symbol("full") return self.__full_symbol @full_symbol.setter def full_symbol(self, s): self.__full_symbol = self.__save("rating_symbol_full", s) @property def blank_symbol(self): """The symbol to use for a blank (inactive) rating, if needed""" if self.__blank_symbol is None: self.__blank_symbol = self.__get_symbol("blank") return self.__blank_symbol @blank_symbol.setter def blank_symbol(self, s): self.__blank_symbol = self.__save("rating_symbol_blank", s) @property def all(self): """Returns all the possible ratings currently available""" return [float(i) / self.number for i in range(0, self.number + 1)] @staticmethod def __save(key, value): set("settings", key, value) return value @staticmethod def __get_symbol(variant="full"): return gettext("settings", "rating_symbol_%s" % variant) class HardCodedRatingsPrefs(RatingsPrefs): number = int(INITIAL["settings"]["ratings"]) default = float(INITIAL["settings"]["default_rating"]) blank_symbol = INITIAL["settings"]["rating_symbol_blank"] full_symbol = INITIAL["settings"]["rating_symbol_full"] # Need an instance just for imports to work RATINGS = RatingsPrefs() @enum class DurationFormat(str): NUMERIC, SECONDS = "numeric", "numeric-seconds" STANDARD, FULL = "standard", "text-full" class DurationFormatPref: @property def format(self): raw = get("display", "duration_format") return DurationFormat.value_of(raw, DurationFormat.STANDARD) @format.setter def format(self, value): set("display", "duration_format", value) DURATION = DurationFormatPref() �����������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692732050.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/const.py������������������������������������������������������������������0000644�0001750�0001750�00000014475�14471205222�015705� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. """Constants used in various parts of QL, mostly strings.""" import sys import os # MSYS2 defines MSYSTEM which changes os.sep/os.path.sep for the mingw # Python build. Unset here and restart.. (does not work for py.test etc.) # XXX: do this here since it gets executed by all scripts if os.name == "nt" and "MSYSTEM" in os.environ: import subprocess del os.environ["MSYSTEM"] argv = [] for arg in [sys.executable] + sys.argv: if os.path.exists(arg): arg = arg.replace("/", "\\") argv.append(arg) sys.exit(subprocess.call(argv)) class Version(tuple): """Represent the version of a dependency as a tuple""" def __new__(cls, name, *args, **kwargs): inst = tuple.__new__(Version, args) inst.name = name inst.message = kwargs.pop("message", "") return inst def __init__(self, *args, **kwargs): pass def human_version(self): return ".".join(map(str, self)) def __str__(self): return self.human_version() def check(self, version_tuple): """Raises ImportError if the version isn't supported""" if self[0] == version_tuple[0] and version_tuple >= self: return message = " " + self.message if self.message else "" version = Version("", *version_tuple) raise ImportError(f"{self.name} {self} required. {version} found.{message}") class MinVersions: """Dependency requirements for Quod Libet / Ex Falso""" PYTHON3 = Version("Python3", 3, 8) MUTAGEN = Version("Mutagen", 1, 37, message="Use the Quod Libet unstable PPAs/repos to get a newer " "mutagen version.") GTK = Version("GTK+", 3, 18) PYGOBJECT = Version("PyGObject", 3, 18) GSTREAMER = Version("GStreamer", 1, 8) VERSION_TUPLE = Version("", 4, 6, 0) VERSION = str(VERSION_TUPLE) QL_NAMESPACE = "https://quodlibet.github.io" """A namespace for registering things against e.g. XMLNS""" # entry point for the user guide / wiki _DOCS_BASE_URL = "https://quodlibet.readthedocs.org/en/latest" ONLINE_HELP = _DOCS_BASE_URL + "/guide/index.html" SEARCH_HELP = _DOCS_BASE_URL + "/guide/searching.html" SHORTCUTS_HELP = _DOCS_BASE_URL + "/guide/shortcuts.html" # Email used as default for reading/saving per-user data in tags, etc. EMAIL = os.environ.get("EMAIL", "quodlibet@lists.sacredchao.net") # Displayed as registered / help email address SUPPORT_EMAIL = "quod-libet-development@googlegroups.com" # about dialog, --version etc. WEBSITE = "https://quodlibet.readthedocs.org/" COPYRIGHT = "Copyright 2004-2023" AUTHORS = sorted("""\ Alexandre Passos Alexey Bobyakov Alex Geoffrey Smith Anders Carlsson Andreas Bombe Andrew Chadwick Anton Shestakov Ari Pollak Arkadiy Illarionov Aymeric Mansoux Bastian Kleineidam Bastien Gorissen Benjamin Boutier Ben Zeigler Bernd Wechner Bruno Bergot Carlo Teubner Christine Spang Christoph Reiter Corentin Néau David Kågedal David Morris David Schneider Decklin Foster Didier Villevalois Eduardo Gonzalez Eoin O'Neill Eric Casteleijn Erich Schubert Eric Le Lay Federico Pelloni Felicián Németh Felix Krull Florian Demmer Fredrik Strupe Guillaume Chazarain Hans Scholze Iñigo Serna Jacob Lee Jakob Gahde Jakub Wilk Jan Arne Petersen Jan Path Javier Kohen Joe Higton Joe Wreschnig Johan Hovold Johannes Marbach Johannes Rohrer Joschka Fischer Josh Lee Joshua Homan Joshua Kwan Lalo Martins Lee Willis Ludovic Druette Lukáš Lalinský Markus Koller Martijn Pieters Martin Bergström Michaël Ball Michael Urman Mickael Royer Nicholas J. Michalek Nick Boultbee Niklas Janlert Nikolai Prokoschenko Olli Helin Peter Simonyi Peter Strulo Philipp Müller Philipp Weis Phoenix Dailey Quincy John Hamilton Remi Vanicat Robert Muth Ruud van Asseldonk Ryan Turner Sebastian Thürrschmidt Simonas Kazlauskas Simon Larsen Steven Robertson Thomas Vogt Till Berger Tobias Wolf Tomasz Miasko Tomasz Torcz Tshepang Lekhonkhobe Türerkan İnce Uriel Zajaczkovski Vasiliy Faronov Victoria Hayes Zack Weinberg Vimalan Reddy Jason Heard David Pérez Carmona IBBoard@github CreamyCookie@github Sauyon Lee Thomas Leberbauer Kristian Laakkonen Emanuele Baldino Peter F. Patel-Schneider Pete Beardmore Muges@github Meriipu@github Jonas Platte Eyenseo@github dpitch40@github sphh@github zsau@github luk1337@github luzpaz@github a-vrma@github Phidica@github """.strip().split("\n")) TRANSLATORS = sorted(""" Åka Sikrom (nb) Alexandre Passos (pt) Andreas Bertheussen (nb) Olivier Humbert (fr) Anton Shestakov (ru) Avi Markovitz (he) Bastian Kleineidam (de) Bastien Gorissen (fr) Byung-Hee HWANG (ko) ChangBom Yoon (ko) Daniel Nyberg (sv) Daniele Primon (it) Dimitris Papageorgiou (el) Djavan Fagundes (pt) Einārs Sprūģis (lv) Eirik Haatveit (nb) Emfox Zhou (zh_CN) Erik Christiansson (sv) Fabien Devaux (fr) Filippo Pappalardo (it) Guillaume Ayoub (fr) Hans van Dok (nl) Honza Hejzl (cs_CZ) Hsin-lin Cheng (zh_TW) Jari Rahkonen (fi) Javier Kohen (es) Joe Wreschnig (en_CA) Johám-Luís Miguéns Vila (es, gl, gl_ES, eu, pt) Jonas Slivka (lt) Joshua Kwan (fr) Luca Baraldi (it) Ludovic Druette (fr) Lukáš Lalinský (sk) Mathieu Morey (fr) Michal Nowikowski (pl) Mugurel Tudor (ro) Mykola Lynnyk (uk) Naglis Jonaitis (lt) Nathan Follens (nl) Nick Boultbee (fr, en_GB) Olivier Gambier (fr) Piarres Beobide (eu) Piotr Drąg (pl) Roee Haimovich (he) Rüdiger Arp (de) SZERVÁC Attila (hu) Tomasz Torcz (pl) Türerkan İnce (tr) Witold Kieraś (pl) Yasushi Iwata (ja) Δημήτρης Παπαγεωργίου (el) Андрей Федосеев (ru) Микола 'Cthulhu' Линник (uk) Николай Прокошенко (ru) Ростислав "zbrox" Райков (bg) Сергей Федосеев (ru) scootergrisen (da) Marek Suchánek (cs) Till Berger (de) Jean-Michel Pouré (fr) Kristian Laakkonen (fi) Kirill Romanov (ru) wvxwxvw@github (ru) """.strip().splitlines()) ARTISTS = sorted("""\ Tobias Jakub Steiner Fabien Devaux """.strip().split("\n")) # Default songlist column headers DEFAULT_COLUMNS = "~#track ~people ~title~version ~album~discsubtitle " \ "~#length".split() DEBUG = ("--debug" in sys.argv or "QUODLIBET_DEBUG" in os.environ) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/��������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016557� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/__init__.py���������������������������������������������������0000664�0001750�0001750�00000000551�14035600052�020667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .main import enable_errorhook, errorhook enable_errorhook, errorhook �������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/faulthandling.py����������������������������������������������0000664�0001750�0001750�00000006665�14035600052�021764� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """ Interface around faulthandler to save and restore segfault info for the next program invocation. """ import os import ctypes import errno import re import atexit import faulthandler from quodlibet.util.dprint import print_exc _fileobj = None class FaultHandlerCrash(Exception): """The exception type used for raising errors with a faulthandler stacktrace. Needed so we can add special handling in the error reporting code paths. """ def get_grouping_key(self): """Given a stacktrace produced by the faulthandler module returns a short string for grouping similar stacktraces together. Args: stacktrace (str) Returns: str """ stacktrace = str(self) if isinstance(stacktrace, bytes): stacktrace = stacktrace.decode("utf-8", "replace") assert isinstance(stacktrace, str) # Extract the basename and the function name for each line and hash # them. Could be smarter, but let's try this for now.. reg = re.compile(r'.*?"([^"]+).*?(\w+$)') values = [] for l in stacktrace.splitlines(): m = reg.match(l) if m is not None: path, func = m.groups() path = os.path.basename(path) values.extend([path, func]) return u"|".join(values) def enable(path): """Enable crash reporting and create empty target file Args: path (pathlike): the location of the crash log target path Raises: IOError: In case the location is not writable """ global _fileobj if _fileobj is not None: raise Exception("already enabled") # we open as reading so raise_and_clear_error() can extract the old error try: _fileobj = open(path, "rb+") except IOError as e: if e.errno == errno.ENOENT: _fileobj = open(path, "wb+") else: raise faulthandler.enable(_fileobj, all_threads=False) def disable(): """Disable crash reporting and removes the target file Does not raise. """ global _fileobj if _fileobj is None: return faulthandler.disable() try: _fileobj.close() os.unlink(_fileobj.name) except (OSError, IOError): pass _fileobj = None @atexit.register def _at_exit(): disable() def raise_and_clear_error(): """Raises an error if there is one. Calling this will clear the error so a second call won't do anything. enable() needs to be called first. Raises: FaultHandlerCrash """ global _fileobj if _fileobj is None: return try: _fileobj.seek(0) text = _fileobj.read().decode("utf-8", "replace").strip() _fileobj.seek(0) _fileobj.truncate() except IOError: print_exc() else: if text: raise FaultHandlerCrash(text) def crash(): """Makes the process segfault. For testing purposes""" if os.name == "nt": i = ctypes.c_char(b'a') j = ctypes.pointer(i) c = 0 while True: j[c] = b'a' c += 1 else: ctypes.string_at(0) ���������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/logdump.py����������������������������������������������������0000664�0001750�0001750�00000004025�14035600052�020577� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys import platform import time import mutagen import quodlibet from quodlibet.util import logging from quodlibet.util.path import mkdir from quodlibet.util.dprint import print_exc, format_exception def format_dump_header(exc_info): """Returns system information and the traceback Args: exc_info (tuple): sys.exc_info() result tuple Returns: str """ lines = [ u"=== SYSTEM INFORMATION:" u"", u"Quod Libet %s" % quodlibet.get_build_description(), u"Mutagen %s" % mutagen.version_string, u"Python %s %s" % (sys.version, sys.platform), u"Platform %s" % platform.platform(), u"=== STACK TRACE", u"", ] lines.extend(format_exception(*exc_info)) lines.append(u"") return os.linesep.join(lines) def format_dump_log(limit=75): """Returns recent log entries. Args: limit (int): number of log entries to return Returns: str """ dump = [u"=== LOG:"] dump.extend(logging.get_content(limit=limit)) return os.linesep.join(dump) def dump_to_disk(dump_dir, exc_info): """Writes a new error log file into 'dump_dir' Args: dump_dir (path-like) exc_info (tuple): sys.exc_info() result tuple """ try: mkdir(dump_dir) except EnvironmentError: print_exc() return time_ = time.localtime() dump_path = os.path.join( dump_dir, time.strftime("Dump_%Y%m%d_%H%M%S.txt", time_)) header = format_dump_header(exc_info).encode("utf-8") log = format_dump_log().encode("utf-8") try: with open(dump_path, "wb") as dump: dump.write(header) dump.write(log) except EnvironmentError: print_exc() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/main.py�������������������������������������������������������0000664�0001750�0001750�00000013300�14035600052�020050� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import threading import sys import platform import os from gi.repository import GLib import mutagen import cairo import quodlibet from quodlibet import app from quodlibet.build import BUILD_TYPE, BUILD_INFO from quodlibet.util import fver, cached_func, is_main_thread from quodlibet.util.dprint import format_exception, print_exc, print_e from quodlibet.qltk import gtk_version, pygobject_version, get_backend_name from .sentrywrapper import Sentry, SentryError from .ui import ErrorDialog, find_active_window, SubmitErrorDialog from .faulthandling import FaultHandlerCrash from .logdump import dump_to_disk @cached_func def get_sentry(): """Returns a cached Sentry instance Returns: Sentry """ # reverse, so it isn't so easy to search for at least SENTRY_DSN = ( "514241/oi.yrtnes@0818e5ab0218038bcbb41f049ec5de21:" "0d15f73b978d143b5e84030a1ddf9a73//:sptth")[::-1] sentry = Sentry(SENTRY_DSN) sentry.add_tag("release", quodlibet.get_build_description()) sentry.add_tag("build_type", BUILD_TYPE) sentry.add_tag("build_info", BUILD_INFO or "NONE") sentry.add_tag("mutagen_version", fver(mutagen.version)) sentry.add_tag("python_version", platform.python_version()) sentry.add_tag("gtk_version", fver(gtk_version)) sentry.add_tag("gtk_backend", get_backend_name()) sentry.add_tag("pygobject_version", fver(pygobject_version)) sentry.add_tag("pycairo_version", fver(cairo.version_info)) sentry.add_tag("platform", platform.platform()) return sentry # We guard against recursive errors _error_lock = threading.Lock() _errorhook_enabled = False def enable_errorhook(value): """Enables/Disables the error hook and the excepthook integration. Args: value (bool) """ global _errorhook_enabled value = bool(value) _errorhook_enabled = value if value: sys.excepthook = excepthook else: sys.excepthook = sys.__excepthook__ def run_error_dialogs(exc_info, sentry_error): assert sentry_error is not None error_text = u"%s: %s" % ( exc_info[0].__name__, (str(exc_info[1]).strip() or u"\n").splitlines()[0]) error_text += u"\n------\n" error_text += u"\n".join(format_exception(*exc_info)) # Don't reshow the error dialog in case the user wanted to quit the app # but due to the error state more errors pile up.. if app.is_quitting: return window = find_active_window() if window is None: return # XXX: This does blocking IO and uses nested event loops... but it's simple dialog = ErrorDialog(window, error_text) while 1: response = dialog.run() if response == ErrorDialog.RESPONSE_RESTART: dialog.destroy() app.restart() elif response == ErrorDialog.RESPONSE_SUBMIT: dialog.hide() submit_dialog = SubmitErrorDialog( window, sentry_error.get_report()) submit_response = submit_dialog.run() if submit_response == SubmitErrorDialog.RESPONSE_SUBMIT: sentry_error.set_comment(submit_dialog.get_comment()) timeout_seconds = 5 try: sentry_error.send(timeout_seconds) except SentryError: print_exc() submit_dialog.destroy() dialog.destroy() else: submit_dialog.destroy() dialog.show() continue else: dialog.destroy() break def errorhook(exc_info=None): """This is the main entry point Call in an exception context. Thread safe. def my_thread(): try: do_work() except Exception: errorhook() """ global _error_lock, _errorhook_enabled if not _errorhook_enabled: return if exc_info is None: exc_info = sys.exc_info() if exc_info[0] is None: # called outside of an exception context, just ignore print_e("no active exception!") return # In case something goes wrong during error handling print it first print_exc(exc_info) if not _error_lock.acquire(False): # Make sure only one of these is active at a time return # write error and logs to disk dump_dir = os.path.join(quodlibet.get_user_dir(), "dumps") dump_to_disk(dump_dir, exc_info) sentry = get_sentry() # For crashes the stack trace is not enough to differentiating different # crash sources. We need to give our own grouping key (fingerprint) based # on the stack trace provided by faulthandler. fingerprint = None if isinstance(exc_info[1], FaultHandlerCrash): fingerprint = ["{{ default }}", exc_info[1].get_grouping_key()] try: sentry_error = sentry.capture(exc_info, fingerprint=fingerprint) except SentryError: print_exc() sentry_error = None def called_in_main_thread(): try: if sentry_error is not None: run_error_dialogs(exc_info, sentry_error) finally: _error_lock.release() if is_main_thread(): called_in_main_thread() else: GLib.idle_add(called_in_main_thread) def excepthook(*exc_info): """Custom exception hook. This is called in case an unhandled exception occurs in the main thread. In other threads errorhook() has to be called explicitly. """ errorhook(exc_info) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/sentrywrapper.py����������������������������������������������0000664�0001750�0001750�00000020575�14035600052�022065� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # 2020 Nick Boultbee # 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 2 of the License, or # (at your option) any later version. """ A wrapper API for sentry-raven to make it work in a GUI environment. We need to split the capturing phase from the submit phase so we can show the report to the user and provide feedback about the report submit process. This hacks it together while trying to not touch too many raven internals. It also only imports raven when needed since it takes quite a lot of time to import. """ import os import pprint from urllib.parse import urlencode from quodlibet.util.urllib import Request, urlopen class SentryError(Exception): """Exception type for all the API below""" pass def send_feedback(dsn, event_id, name, email, comment, timeout): """Send feedback, blocking. Args: dsn (str): The DSN event_id (str): The event ID this feedback should be attached to name (str): The user name email (str): The user email comment (str): The feedback text timeout (float): The timeout for this request Raises: SentryError: In case of timeout or other errors """ name = str(name).encode("utf-8") email = str(email).encode("utf-8") comment = str(comment).encode("utf-8") data = urlencode( [('name', name), ('email', email), ('comments', comment)]) if not isinstance(data, bytes): # py3 data = data.encode("utf-8") headers = {"Referer": "https://quodlibet.github.io"} params = urlencode([("dsn", dsn), ("eventId", event_id)]) try: req = Request( "https://sentry.io/api/embed/error-page/?" + params, data=data, headers=headers) urlopen(req, timeout=timeout).close() except EnvironmentError as e: raise SentryError(e) def urlopen_hack(**kwargs): # There is no way to make raven use the system cert store. This makes # it use the standard urlopen instead. url = kwargs["url"] data = kwargs["data"] timeout = kwargs["timeout"] return urlopen(url, data, timeout) class CapturedException: """Contains the data to be send to sentry.""" def __init__(self, dsn, data): """ Args: dsn (str): the sentry.io DSN data (object): some sentry internals """ self._dsn = dsn self._args, self._kwargs = data self._comment = None def get_report(self): """Gives a textual representation of the collected data. The goal is to give the user a way to see what is being send to the sentry servers. Returns: str """ lines = [] if self._args: lines += pprint.pformat(self._args, width=40).splitlines() if self._kwargs: lines += pprint.pformat(self._kwargs, width=40).splitlines() def compact(l): level = len(l) - len(l.lstrip()) return u" " * (level // 4) + l.lstrip() return u"\n".join(map(compact, lines)) def set_comment(self, comment): """Attach a user provided comment to the error. Something like "I clicked button X and then this happened" Args: comment (str) """ self._comment = comment def send(self, timeout): """Submit the error including the user feedback. Blocking. Args: timeout (float): timeout for each request made Returns: str: The sentry event id Raises: SentryError """ from raven import Client from raven.transport import http from raven.transport.http import HTTPTransport http.urlopen = urlopen_hack try: raise Exception except Exception: client = Client( self._dsn + "?timeout=%d" % timeout, install_sys_hook=False, install_logging_hook=False, capture_locals=False, transport=HTTPTransport) # replace the captured data with the one we already have old_send = client.send def inject_data(*args, **kwargs): kw = dict(self._kwargs) kw["event_id"] = kwargs.get("event_id", "") return old_send(*self._args, **kw) client.send = inject_data event_id = client.captureException() if client.state.did_fail(): raise SentryError("captureException failed") # fix leak client.context.deactivate() if self._comment: send_feedback(self._dsn, event_id, "default", "email@example.com", self._comment, timeout) return event_id class Sentry: """The main object of our sentry API wrapper""" def __init__(self, dsn): """ Args: dsn (str) """ self._dsn = dsn self._tags = {} def add_tag(self, key, value): """Attach tags to the error report. Args: key (str) value (str) The keys are arbitrary, but some have a special meaning: * "release" will show up as a separate page in sentry * "environment" will add a dropdown for grouping """ self._tags[key] = value def capture(self, exc_info=None, fingerprint=None): """Captures the current exception and returns a CapturedException The returned object contains everything needed to submit the error at a later point in time (e.g. after pushing it to the main thread and displaying it in the UI) Args: exc_info (tuple): a sys.exc_info() return value fingerprint (List[str] or None): fingerprint for custom grouping Returns: CapturedException Raises: SentryError: Raised if raven isn't installed or capturing failed for some unknown reason. """ try: from raven import Client from raven.transport import Transport from raven.processors import Processor except ImportError as e: raise SentryError(e) class DummyTransport(Transport): """A sync raven transport which does nothing""" def send(self, *args, **kwargs): pass # Some tags have a special meaning and conflict with info given to the # client, so pass them to the client instead tags = dict(self._tags) kwargs = {} if "release" in tags: kwargs["release"] = tags.pop("release") if "environment" in tags: kwargs["environment"] = tags.pop("environment") if "server_name" in tags: kwargs["name"] = tags.pop("server_name") # It would default to the hostname otherwise kwargs.setdefault("name", "default") # We use a dummy transport and intercept the captured data client = Client( self._dsn, install_sys_hook=False, install_logging_hook=False, capture_locals=True, transport=DummyTransport, tags=tags, **kwargs) data = [None] old_send = client.send def save_state(*args, **kwargs): data[0] = (args, kwargs) return old_send(*args, **kwargs) client.send = save_state client.captureException(exc_info, fingerprint=fingerprint) if data[0] is None: raise SentryError("Failed to capture") class SanitizePaths(Processor): """Makes filename on Windows match the Linux one. Also adjust abs_path, so it still contains filename. """ def filter_stacktrace(self, data, **kwargs): for frame in data.get('frames', []): if frame.get("abs_path"): frame["abs_path"] = \ frame["abs_path"].replace(os.sep, "/") if frame.get("filename"): frame["filename"] = \ frame["filename"].replace(os.sep, "/") SanitizePaths(client).process(data[0][1]) # fix leak client.context.deactivate() return CapturedException(self._dsn, data[0]) �����������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/errorreport/ui.py���������������������������������������������������������0000664�0001750�0001750�00000007634�14035600052�017556� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet.qltk.entry import UndoEntry def find_active_window(): """Try to get the active Window, default to the main one""" for window in Gtk.Window.list_toplevels(): if window.is_active(): return window else: return app.window class TextExpander(Gtk.Expander): def __init__(self, title, text): super().__init__(label=title) self.set_resize_toplevel(True) buf = Gtk.TextBuffer() buf.set_text(text) tv = Gtk.TextView(buffer=buf, editable=False) tv.set_left_margin(6) if hasattr(tv, "set_top_margin"): tv.set_top_margin(6) tv.set_bottom_margin(6) label = self.get_label_widget() label.props.margin = 4 win = Gtk.ScrolledWindow() win.add(tv) win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) win.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) win.set_size_request(-1, 175) self.add(win) win.show_all() class ErrorDialog(Gtk.MessageDialog): RESPONSE_RESTART = 1 RESPONSE_SUBMIT = 2 RESPONSE_BUGREPORT = 3 def __init__(self, parent, error_text): main_text = _("An Error Occurred") secondary_text = _( "You can ignore this error, but the application might be unstable " "until it is restarted. Submitting an error report will only " "take a few seconds and would help us a lot.") super().__init__( text=main_text, secondary_text=secondary_text) self.set_transient_for(parent) self.set_modal(True) self.add_button(_("Submit Error Report"), self.RESPONSE_SUBMIT) self.add_button(_("Restart"), self.RESPONSE_RESTART) self.add_button(_("Ignore Error"), Gtk.ResponseType.CANCEL) self.set_default_response(Gtk.ResponseType.CANCEL) area = self.get_message_area() expand = TextExpander(_("Error details:"), error_text) area.pack_start(expand, False, True, 0) area.show_all() class SubmitErrorDialog(Gtk.MessageDialog): RESPONSE_SUBMIT = 1 def __init__(self, parent, error_text): main_text = _("Submit Error Report") secondary_text = _( "Various details regarding the error and your system will be send " "to a third party online service " "(<a href='https://www.sentry.io'>www.sentry.io</a>). You can " "review the data before sending it below.") secondary_text += u"\n\n" secondary_text += _( "(optional) Please provide a short description of what happened " "when the error occurred:") super().__init__( modal=True, text=main_text, secondary_text=secondary_text, secondary_use_markup=True) self.set_transient_for(parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Send"), self.RESPONSE_SUBMIT) self.set_default_response(Gtk.ResponseType.CANCEL) area = self.get_message_area() self._entry = UndoEntry() self._entry.set_placeholder_text(_("Short description…")) area.pack_start(self._entry, False, True, 0) expand = TextExpander(_("Data to be sent:"), error_text) area.pack_start(expand, False, True, 0) area.show_all() self.get_widget_for_response(Gtk.ResponseType.CANCEL).grab_focus() def get_comment(self): """Returns the user provided error description Returns text_Type """ return self._entry.get_text() ����������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/exfalso.py����������������������������������������������������������������0000644�0001750�0001750�00000004144�14266344767�016234� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Niklas Janlert # 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys from senf import fsnative from quodlibet import _ from quodlibet import app from quodlibet import util from quodlibet import const from quodlibet import config def main(argv=None): if argv is None: argv = sys.argv import quodlibet config_file = os.path.join(quodlibet.get_user_dir(), "config") quodlibet.init(config_file=config_file) from quodlibet.qltk import add_signal_watch add_signal_watch(app.quit) opts = util.OptionParser( "Ex Falso", const.VERSION, _("an audio tag editor"), "[%s]" % _("directory")) argv.append(os.path.abspath(fsnative(u"."))) opts, args = opts.parse(argv[1:]) args[0] = os.path.realpath(args[0]) app.name = "Ex Falso" app.description = _("Audio metadata editor") app.id = "io.github.quodlibet.ExFalso" app.process_name = "exfalso" quodlibet.set_application_info(app) import quodlibet.library import quodlibet.player app.library = quodlibet.library.init() app.player = quodlibet.player.init_player("nullbe", app.librarian) from quodlibet.qltk.songlist import PlaylistModel app.player.setup(PlaylistModel(), None, 0) pm = quodlibet.init_plugins() pm.rescan() from quodlibet.qltk.exfalsowindow import ExFalsoWindow dir_ = args[0] app.window = ExFalsoWindow(app.library, dir_) app.window.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet import session session_client = session.init(app) quodlibet.enable_periodic_save(save_library=False) quodlibet.run(app.window) quodlibet.finish_first_session("exfalso") config.save() session_client.close() util.print_d("Finished shutdown.") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014772� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/__init__.py�����������������������������������������������������������0000664�0001750�0001750�00000000727�14035600052�017107� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. """ Extension points for Quod Libet and Ex Falso This (currently) contains code plugins (formerly kept in /plugins) arranged by plugin type (songsmenu, events, etc). Base classes themselves are in /quodlibet/plugins """ �����������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/��������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016377� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/__init__.py���������������������������������������������������0000664�0001750�0001750�00000000615�14035600052�020510� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. """ Shared plugin code lives here - for example, two plugins of different types may want to share common code. """ �������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/squeezebox/���������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020571� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/squeezebox/__init__.py����������������������������������������0000664�0001750�0001750�00000000431�14035600052�022676� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/squeezebox/base.py��������������������������������������������0000664�0001750�0001750�00000015160�14035600052�022056� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk, GLib from quodlibet import _ from quodlibet import print_d, app, config from quodlibet.plugins import PluginConfigMixin from quodlibet.qltk import Message from quodlibet.qltk.x import Frame from quodlibet.qltk.entry import UndoEntry from quodlibet.util.library import get_scan_dirs from .util import GetPlayerDialog from .server import SqueezeboxServer, SqueezeboxException class SqueezeboxPluginMixin(PluginConfigMixin): """ All the Squeezebox connection / communication code in one delicious class """ # Maintain a singleton; we only support one SB server live in QL server = None # We want all derived classes to share the config section CONFIG_SECTION = "squeezebox" @classmethod def _get_ql_base_dir(cls): dirs = get_scan_dirs() return os.path.realpath(dirs[0]) if dirs else "" @classmethod def get_sb_path(cls, song): """Gets a SB path to `song` by simple substitution""" path = song('~filename') return path.replace( cls._get_ql_base_dir(), cls.server.get_library_dir()) @classmethod def post_reconnect(cls): pass @staticmethod def _show_dialog(dialog_type, msg): dialog = Message(dialog_type, app.window, "Squeezebox", msg) dialog.connect('response', lambda dia, resp: dia.destroy()) dialog.show() @staticmethod def quick_dialog(msg, dialog_type=Gtk.MessageType.INFO): GLib.idle_add(SqueezeboxPluginMixin._show_dialog, dialog_type, msg) @classmethod def set_player(cls, val): cls.server.current_player = val cls.config_set("current_player", val) print_d("Setting player to #%d (%s)" % (val, cls.server.players[val])) @classmethod def check_settings(cls, button): cls.init_server() if cls.server.is_connected: ret = 0 if len(cls.server.players) > 1: dialog = GetPlayerDialog(app.window, cls.server.players, cls.server.current_player) ret = dialog.run() or 0 else: cls.quick_dialog( _("Squeezebox OK. Using the only player (%s).") % cls.server.players[0]) cls.set_player(ret) # TODO: verify sanity of SB library path # Manage the changeover as best we can... cls.post_reconnect() else: cls.quick_dialog(_("Couldn't connect to %s") % (cls.server,), Gtk.MessageType.ERROR) @classmethod def PluginPreferences(cls, parent): def value_changed(entry, key): if entry.get_property('sensitive'): cls.server.config[key] = entry.get_text() config.set("plugins", "squeezebox_" + key, entry.get_text()) vb = Gtk.VBox(spacing=12) if not cls.server: cls.init_server() cfg = cls.server.config # Tabulate all settings for neatness table = Gtk.Table(n_rows=3, n_columns=2) table.set_col_spacings(6) table.set_row_spacings(6) rows = [] ve = UndoEntry() ve.set_text(cfg["hostname"]) ve.connect('changed', value_changed, 'server_hostname') lbl = Gtk.Label(label=_("Hostname:"), use_underline=True) lbl.set_mnemonic_widget(ve) rows.append((lbl, ve)) ve = UndoEntry() ve.set_width_chars(5) ve.set_text(str(cfg["port"])) ve.connect('changed', value_changed, 'server_port') lbl = Gtk.Label(label=_("Port:"), use_underline=True) lbl.set_mnemonic_widget(ve) rows.append((lbl, ve)) ve = UndoEntry() ve.set_text(cfg["user"]) ve.connect('changed', value_changed, 'server_user') lbl = Gtk.Label(label=_("Username:"), use_underline=True) lbl.set_mnemonic_widget(ve) rows.append((lbl, ve)) ve = UndoEntry() ve.set_text(str(cfg["password"])) ve.connect('changed', value_changed, 'server_password') lbl = Gtk.Label(label=_("Password:"), use_underline=True) lbl.set_mnemonic_widget(ve) rows.append((lbl, ve)) ve = UndoEntry() ve.set_text(str(cfg["library_dir"])) ve.set_tooltip_text(_("Library directory the server connects to")) ve.connect('changed', value_changed, 'server_library_dir') lbl = Gtk.Label(label=_("Library path:"), use_underline=True) lbl.set_mnemonic_widget(ve) rows.append((lbl, ve)) for (row, (label, entry)) in enumerate(rows): label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, row, row + 1, xoptions=Gtk.AttachOptions.FILL) table.attach(entry, 1, 2, row, row + 1) # Add verify button button = Gtk.Button(label=_("_Verify settings"), use_underline=True) button.set_sensitive(cls.server is not None) button.connect('clicked', cls.check_settings) table.attach(button, 0, 2, row + 1, row + 2) # Server settings Frame cfg_frame = Frame(_("Squeezebox Server"), table) vb.pack_start(cfg_frame, True, True, 0) debug = cls.ConfigCheckButton(_("Debug"), "debug") vb.pack_start(debug, True, True, 0) return vb @classmethod def init_server(cls): """Initialises a server, and connects to check if it's alive""" try: cur = int(cls.config_get("current_player", 0)) except ValueError: cur = 0 cls.server = SqueezeboxServer( hostname=cls.config_get("server_hostname", "localhost"), port=cls.config_get("server_port", 9090), user=cls.config_get("server_user", ""), password=cls.config_get("server_password", ""), library_dir=cls.config_get( "server_library_dir", cls._get_ql_base_dir()), current_player=cur, debug=cls.config_get_bool("debug", False)) try: ver = cls.server.get_version() if cls.server.is_connected: print_d( "Squeezebox server version: %s. Current player: #%d (%s)." % (ver, cur, cls.server.get_players()[cur]["name"])) except (IndexError, KeyError, SqueezeboxException) as e: print_d("Couldn't get player info (%s)." % e) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/squeezebox/server.py������������������������������������������0000664�0001750�0001750�00000020041�14035600052�022444� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import socket from typing import List from telnetlib import Telnet import time from urllib.parse import quote, unquote from quodlibet import _ from quodlibet import app from quodlibet.util.dprint import print_w, print_d, print_ class SqueezeboxException(Exception): """Errors communicating with the Squeezebox""" class SqueezeboxServerSettings(dict): """Encapsulates Server settings""" def __str__(self): try: return _("Squeezebox server at {hostname}:{port}").format(**self) except KeyError: return _("unidentified Squeezebox server") class SqueezeboxPlayerSettings(dict): """Encapsulates player settings""" def __str__(self): try: return "{name} [{playerid}]".format(**self) except KeyError: return _("unidentified Squeezebox player: %r" % self) class SqueezeboxServer: """Encapsulates access to a Squeezebox player via a squeezecenter server""" _TIMEOUT = 10 _MAX_FAILURES = 3 telnet = None is_connected = False current_player = 0 players: List[SqueezeboxPlayerSettings] = [] config = SqueezeboxServerSettings() _debug = False def __init__(self, hostname="localhost", port=9090, user="", password="", library_dir='', current_player=0, debug=False): self._debug = debug self.failures = 0 self.delta = 600 # Default in ms self.config = SqueezeboxServerSettings(locals()) if hostname: del self.config["self"] del self.config["current_player"] self.current_player = int(current_player) or 0 try: if self._debug: print_d("Trying %s..." % self.config) self.telnet = Telnet(hostname, port, self._TIMEOUT) except socket.error as e: print_d("Couldn't talk to %s (%s)" % (self.config, e)) else: result = self.__request("login %s %s" % (user, password)) if result != (6 * '*'): raise SqueezeboxException( "Couldn't log in to squeezebox: response was '%s'" % result) self.is_connected = True self.failures = 0 print_d("Connected to Squeezebox Server! %s" % self) # Reset players (forces reload) self.players = [] self.get_players() def get_library_dir(self): return self.config['library_dir'] def __request(self, line, raw=False, want_reply=True): """ Send a request to the server, if connected, and return its response """ line = line.strip() if not (self.is_connected or line.split()[0] == 'login'): print_d("Can't do '%s' - not connected" % line.split()[0], self) return None if self._debug: print_(">>>> \"%s\"" % line) try: self.telnet.write((line + "\n").encode('utf-8')) if not want_reply: return None raw_response = self.telnet.read_until(b"\n", 5).decode('utf-8') except socket.error as e: print_w("Couldn't communicate with squeezebox (%s)" % e) self.failures += 1 if self.failures >= self._MAX_FAILURES: print_w("Too many Squeezebox failures. Disconnecting") self.is_connected = False return None response = (raw_response if raw else unquote(raw_response)).strip() if self._debug: print_("<<<< \"%s\"" % (response,)) return (response[len(line) - 1:] if line.endswith("?") else response[len(line) + 1:]) def get_players(self): """ Returns (and caches) a list of the Squeezebox players available""" if self.players: return self.players pairs = self.__request("players 0 99", True).split(" ") def demunge(string): s = unquote(string) cpos = s.index(":") return s[0:cpos], s[cpos + 1:] # Do a meaningful URL-unescaping and tuplification for all values pairs = [demunge(p) for p in pairs] # First element is always count count = int(pairs.pop(0)[1]) self.players = [] for pair in pairs: if pair[0] == "playerindex": playerindex = int(pair[1]) self.players.append(SqueezeboxPlayerSettings()) else: # Don't worry playerindex is always the first entry... self.players[playerindex][pair[0]] = pair[1] if self._debug: print_d("Found %d player(s): %s" % (len(self.players), self.players)) assert (count == len(self.players)) return self.players def player_request(self, line, want_reply=True): if not self.is_connected: return try: return self.__request( "%s %s" % (self.players[self.current_player]["playerid"], line), want_reply=want_reply) except IndexError: return None def get_version(self): if self.is_connected: return self.__request("version ?") else: return "(not connected)" def play(self): """Plays the current song""" self.player_request("play") def is_stopped(self): """Returns whether the player is in any sort of non-playing mode""" response = self.player_request("mode ?") return "play" != response def playlist_play(self, path): """Play song immediately""" self.player_request("playlist play %s" % (quote(path))) def playlist_add(self, path): self.player_request("playlist add %s" % (quote(path)), False) def playlist_save(self, name): self.player_request("playlist save %s" % (quote(name)), False) def playlist_clear(self): self.player_request("playlist clear", False) def playlist_resume(self, name, resume, wipe=False): cmd = ("playlist resume %s noplay:%d wipePlaylist:%d" % (quote(name), int(not resume), int(wipe))) self.player_request(cmd, want_reply=False) def change_song(self, path): """Queue up a song""" self.player_request("playlist clear") self.player_request("playlist insert %s" % (quote(path))) def seek_to(self, ms): """Seeks the current song to `ms` milliseconds from start""" if not self.is_connected: return if self._debug: print_d("Requested %0.2f s, adding drift of %d ms..." % (ms / 1000.0, self.delta)) ms += self.delta start = time.time() self.player_request("time %d" % round(int(ms) / 1000)) end = time.time() took = (end - start) * 1000 reported_time = self.get_milliseconds() ql_pos = app.player.get_position() # Assume 50% of the time taken to complete is response. # TODO: Better predictive modelling new_delta = ql_pos - reported_time self.delta = (self.delta + new_delta) / 2 if self._debug: print_d("Player at %0.0f but QL at %0.2f." "(Took %0.0f ms). Drift was %+0.0f ms" % (reported_time / 1000.0, ql_pos / 1000.0, took, new_delta)) def get_milliseconds(self): secs = self.player_request("time ?") or 0 return float(secs) * 1000.0 def pause(self): self.player_request("pause 1") def unpause(self): if self.is_stopped(): self.play() ms = app.player.get_position() self.seek_to(ms) #self.player_request("pause 0") def stop(self): self.player_request("stop") def __str__(self): return str(self.config) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/_shared/squeezebox/util.py��������������������������������������������0000664�0001750�0001750�00000003237�14035600052�022123� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ class GetPlayerDialog(Gtk.Dialog): def __init__(self, parent, players, current=0): title = _("Choose Squeezebox player") super().__init__(title, parent) self.set_border_width(6) self.set_resizable(False) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_OK"), Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) label = Gtk.Label( label=_("Found Squeezebox server.\nPlease choose the player")) box.set_border_width(6) label.set_line_wrap(True) label.set_justify(Gtk.Justification.CENTER) box.pack_start(label, True, True, 0) player_combo = Gtk.ComboBoxText() for player in players: player_combo.append_text(player["name"]) player_combo.set_active(current) self._val = player_combo box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all() def run(self, text=""): self.show() self._val.grab_focus() resp = super().run() if resp == Gtk.ResponseType.OK: value = self._val.get_active() else: value = None self.destroy() return value �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/���������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016273� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/__init__.py����������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�020402� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1664111117.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/artwork_url.py�������������������������������������������������0000644�0001750�0001750�00000002537�14314051015�021222� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from os import path from gi.repository import Soup from quodlibet import _ from quodlibet.plugins.cover import CoverSourcePlugin, cover_dir from quodlibet.util.cover.http import HTTPDownloadMixin from quodlibet.util.path import escape_filename class ArtworkUrlCover(CoverSourcePlugin, HTTPDownloadMixin): PLUGIN_ID = "artwork-url-cover" PLUGIN_NAME = _("Artwork URL Cover Source") PLUGIN_DESC_MARKUP = _( "Downloads covers linked to by the <tt>artwork_url</tt> tag. " "This works with the Soundcloud and Podcasts browsers.") @classmethod def group_by(cls, song): return song.get('album', None) @staticmethod def priority(): return 0.9 @property def cover_path(self): url = self.url if url: return path.join(cover_dir, escape_filename(url)) @property def url(self): return self.song.get('artwork_url', None) def fetch_cover(self): if not self.url: return self.fail('artwork_url missing') self.download(Soup.Message.new('GET', self.url)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661071866.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/discogs.py�����������������������������������������������������0000644�0001750�0001750�00000010110�14300370772�020275� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Mice Pápai # 2018 Nick Boultbee # # Based on lastfm.py by Simonas Kazlauskas # # 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 2 of the License, or # (at your option) any later version. from os import path import re from gi.repository import Soup from quodlibet import _ from quodlibet.plugins.cover import cover_dir from quodlibet.util.http import download_json from quodlibet.util.cover.http import escape_query_value from quodlibet.util.cover.http import ApiCoverSourcePlugin from quodlibet.util.path import escape_filename from quodlibet.util import print_d class DiscogsCover(ApiCoverSourcePlugin): PLUGIN_ID = "discogs-cover" PLUGIN_NAME = _("Discogs Cover Source") PLUGIN_DESC = _("Downloads covers from Discogs.") credentials = ('key=aWfZGjHQvkMcreUECGAp' + '&secret=VlORkklpdvAwJMwxUjNNSgqicjuizJAl') use_secondary = True @classmethod def group_by(cls, song): return song.album_key @staticmethod def priority(): return 0.6 @property def cover_path(self): mbid = self.song.get('musicbrainz_albumid', None) if mbid: return path.join(cover_dir, escape_filename(mbid)) else: return super().cover_path @property def url(self): _url = ('https://api.discogs.com/database/search?' + self.credentials + '&format=CD&per_page=5' '&type=release' + '&artist={artist}' + '&release_title={album}') # Discogs seems to use 'Various' almost exclusively for compilations artists = self._album_artists_for(self.song) or 'Various' if 'various artists' in artists.lower(): artists = 'Various' artist = escape_query_value(artists) album = escape_query_value(self.song.get('album', '')) if artist and album: return _url.format(artist=artist, album=album) else: return None # Not enough data def _handle_search_response(self, message, json_dict, data=None): if not json_dict: print_d('Server did not return any valid JSON') return self.emit('search-complete', []) try: results = json_dict.get('results', []) covers = filter(None, (self.result_for(r.get('cover_image', None)) for r in results)) if covers: return self.emit('search-complete', list(covers)) res_url = results[0].get('resource_url', '') except IndexError: return self.emit('search-complete', []) else: msg = Soup.Message.new('GET', "%s?%s" % (res_url, self.credentials)) download_json(msg, self.cancellable, self._handle_album_data, None) def _handle_album_data(self, message, json_dict, data=None): images = json_dict.get('images', None) if not images: print_d('Covers are not available') return self.emit('search-complete', []) results = list(self._covers_of_type(images)) if not results and images and self.use_secondary: results.append(next(self._covers_of_type(images, "secondary"))) self.emit('search-complete', results) def _covers_of_type(self, images, image_type='primary'): for image in images: url = image.get('uri') if url and image['type'] == image_type: yield self.result_for(url) def result_for(self, url): if not url: return None dimensions = re.compile(r'/(\d+x\d+)/').search(url) dimensions = dimensions and dimensions.group(1) if dimensions: dims = map(int, dimensions.split('x')) if min(dims) < self.MIN_DIMENSION: print_d("%s is too small to use" % dimensions) return None return {'cover': url, 'dimensions': dimensions} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661071877.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/lastfm.py������������������������������������������������������0000644�0001750�0001750�00000006456�14300371005�020140� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from os import path from quodlibet import _ from quodlibet.plugins.cover import cover_dir from quodlibet.util import print_d from quodlibet.util.cover.http import ApiCoverSourcePlugin, escape_query_value from quodlibet.util.path import escape_filename class LastFMCover(ApiCoverSourcePlugin): PLUGIN_ID = "lastfm-cover" PLUGIN_NAME = _("Last.fm Cover Source") PLUGIN_DESC = _("Downloads covers from Last.fm's cover art archive.") @classmethod def group_by(cls, song): return song.album_key @staticmethod def priority(): return 0.33 # No cover size guarantee, accurate @property def cover_path(self): mbid = self.song.get('musicbrainz_albumid', None) # It is beneficial to use mbid for cover names. if mbid: return path.join(cover_dir, escape_filename(mbid)) else: return super().cover_path @property def url(self): _url = 'https://ws.audioscrobbler.com/2.0?method=album.getinfo&' + \ 'api_key=107db6fd4c1c7f53b1526fafddab2c82&format=json&' + \ 'artist={artist}&album={album}&mbid={mbid}' song = self.song # This can work well for albums in Last.FM artists = self._album_artists_for(song) or 'Various Artists' song = self.song artist = escape_query_value(artists) album = escape_query_value(song.get('album', '')) mbid = escape_query_value(song.get('musicbrainz_albumid', '')) if (artist and album) or mbid: return _url.format(artist=artist, album=album, mbid=mbid) else: return None # Not enough data def _handle_search_response(self, message, json, data=None): if not json: print_d('Server did not return valid JSON') return self.emit('search-complete', []) album = json.get('album', {}) if not album: print_d('Album data is not available') return self.emit('search-complete', []) results = [] for img in album['image']: if img['size'] in ('mega', 'extralarge'): url = img['#text'] if not url: # Yes sometimes it's there but blank continue print_d("Got last.fm image: %s" % img) results.append({'artist': album['artist'], 'album': album['name'], 'cover': url.replace('/300x300', '/500x500'), 'dimensions': '500x500' }) # This one can be massive, and slow results.append({'artist': album['artist'], 'album': album['name'], 'cover': url.replace('/300x300', ''), 'dimensions': '(original)' }) # Prefer the bigger ones break self.emit('search-complete', results) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/covers/musicbrainz.py�������������������������������������������������0000644�0001750�0001750�00000004426�14455205526�021212� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2018-23 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Dict from os import path from gi.repository import Soup from quodlibet import _ from quodlibet.plugins.cover import CoverSourcePlugin, cover_dir from quodlibet.util.cover.http import HTTPDownloadMixin, escape_query_value from quodlibet.util.path import escape_filename class MusicBrainzCover(CoverSourcePlugin, HTTPDownloadMixin): PLUGIN_ID = "musicbrainz-cover" PLUGIN_NAME = _("MusicBrainz Cover Source") PLUGIN_DESC = _("Downloads covers from MusicBrainz's cover art archive.") _SIZES = {"original": "front", "500x500": "front-500", "500x500 (back)": "back-500", "original (back)": "back"} @classmethod def group_by(cls, song): return song.get("musicbrainz_albumid", None) @staticmethod def priority(): # It's a pretty good source, but very slow... return 0.55 @property def cover_path(self): mbid = self.mbid if mbid is None: return super().cover_path return path.join(cover_dir, escape_filename(mbid)) @property def mbid(self): return self.song.get("musicbrainz_albumid", None) def search(self): # This class has hard-coded search results, # and relies on 404s being filtered out later if not self.urls: return self.fail("No Musicbrainz tag found") self.emit("search-complete", [{"cover": url, "dimensions": dims} for dims, url in self.urls.items()]) @property def urls(self) -> Dict[str, str]: if not self.mbid: return {} mbid = escape_query_value(self.mbid) return {dim: f"https://coverartarchive.org/release/{mbid}/{extra}" for dim, extra in self._SIZES.items()} def fetch_cover(self): if not self.mbid: return self.fail("MBID is required to fetch the cover") self.download(Soup.Message.new("GET", self.urls.get("original", None))) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9809356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/��������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016415� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/__init__.py���������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�020524� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/iconv.py������������������������������������������������������0000664�0001750�0001750�00000004514�14231604332�020112� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. # Encoding magic. Show off the submenu stuff. from gi.repository import Gtk from quodlibet import _ from quodlibet.qltk import Icons from quodlibet.plugins.editing import EditTagsPlugin ENCODINGS = """\ big5 cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 euc_jp euc_jis_2004 euc_jisx0213 euc_kr gb2312 gbk gb18030 iso2022_jp iso2022_kr iso8859_2 iso8859_3 iso8859_4 iso8859_5 iso8859_6 iso8859_7 iso8859_8 iso8859_9 iso8859_10 iso8859_13 iso8859_14 iso8859_15 johab koi8_r koi8_u ptcp154 shift_jis utf_16_be utf_16_le""".split() class Iconv(EditTagsPlugin): PLUGIN_ID = "Convert Encodings" PLUGIN_NAME = _("Convert Encodings") PLUGIN_DESC = _("Fixes misinterpreted tag value encodings in the " "tag editor.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE def __init__(self, tag, value): super().__init__( _(u"_Convert Encoding…"), use_underline=True) submenu = Gtk.Menu() items = [] # Ok, which encodings do work on this string? for enc in ENCODINGS: try: new = value.encode('latin1').decode(enc) except (UnicodeEncodeError, UnicodeDecodeError, LookupError): continue else: if new == value: continue if not new in items: items.append(new) if not items: self.set_sensitive(False) for i in items: item = Gtk.MenuItem() item.value = i item_label = Gtk.Label(label=i) item_label.set_alignment(0.0, 0.5) item.add(item_label) item.connect('activate', self.__convert) submenu.append(item) self.set_submenu(submenu) def __convert(self, item): self.__value = item.value self.activate() def activated(self, tag, value): try: return [(tag, self.__value)] except AttributeError: # make it different from [(tag, value)] so the menu entry is enabled return [] ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/kakasi.py�����������������������������������������������������0000664�0001750�0001750�00000004073�14035600052�020234� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import sys import subprocess from quodlibet.qltk import Icons if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import Gtk, GObject from quodlibet import _ from quodlibet.plugins.editing import RenameFilesPlugin from quodlibet.util.path import iscommand from quodlibet.util import connect_obj class Kakasi(RenameFilesPlugin, Gtk.CheckButton): PLUGIN_ID = "Kana/Kanji Simple Inverter" PLUGIN_NAME = _("Kana/Kanji Simple Inverter") PLUGIN_DESC = _("Converts kana/kanji to romaji before renaming.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE __gsignals__ = { "preview": (GObject.SignalFlags.RUN_LAST, None, ()) } def __init__(self): super().__init__( _("Romanize _Japanese text"), use_underline=True) connect_obj(self, 'toggled', self.emit, 'preview') @property def active(self): return self.get_active() # Use filter list rather than filter to avoid starting a new process # for each filename. def filter_list(self, originals, values): value = "\n".join(values) try: data = value.encode('shift-jis', 'replace') except UnicodeEncodeError: return values proc = subprocess.Popen( ["kakasi", "-isjis", "-osjis", "-Ha", "-Ka", "-Ja", "-Ea", "-ka", "-s"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) result = proc.communicate(data)[0] try: return result.decode('shift-jis').strip().split("\n") except: return values if not iscommand("kakasi"): from quodlibet import plugins raise plugins.PluginImportException( _("Couldn't find the 'Kanji Kana Simple Inverter' (kakasi).")) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/resub.py������������������������������������������������������0000644�0001750�0001750�00000003131�14267565021�020116� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import re from gi.repository import Gtk, GObject from quodlibet import _ from quodlibet.plugins.editing import RenameFilesPlugin, TagsFromPathPlugin from quodlibet.util import connect_obj from quodlibet.qltk import Icons class RegExpSub(Gtk.HBox, RenameFilesPlugin, TagsFromPathPlugin): PLUGIN_ID = "Regex Substitution" PLUGIN_NAME = _("Regex Substitution") PLUGIN_DESC_MARKUP = _( "Allows arbitrary regex substitutions (<tt>s/from/to/</tt>) " "when tagging or renaming files.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE __gsignals__ = { "changed": (GObject.SignalFlags.RUN_LAST, None, ()) } active = True def __init__(self): super().__init__() self._from = Gtk.Entry() self._to = Gtk.Entry() self.pack_start(Gtk.Label("s/"), True, True, 0) self.pack_start(self._from, True, True, 0) self.pack_start(Gtk.Label("/"), True, True, 0) self.pack_start(self._to, True, True, 0) self.pack_start(Gtk.Label("/"), True, True, 0) connect_obj(self._from, 'changed', self.emit, 'changed') connect_obj(self._to, 'changed', self.emit, 'changed') def filter(self, orig_or_tag, value): fr = self._from.get_text() to = self._to.get_text() try: return re.sub(fr, to, value) except: return value ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/editing/titlecase.py��������������������������������������������������0000664�0001750�0001750�00000004475�14035600052�020754� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010-14 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import util from quodlibet.qltk import Icons from quodlibet.plugins.editing import EditTagsPlugin from quodlibet.plugins import PluginConfigMixin from quodlibet.util.string.titlecase import _humanise class TitleCase(EditTagsPlugin, PluginConfigMixin): PLUGIN_ID = "Title Case" PLUGIN_NAME = _("Title Case") PLUGIN_DESC = _("Title-cases tag values in the tag editor.") PLUGIN_ICON = Icons.TOOLS_CHECK_SPELLING CONFIG_SECTION = "titlecase" # Issue 753: Allow all caps (as before). # Set to False means you get Run Dmc, Ac/Dc, Cd 1/2 etc allow_all_caps = True def process_tag(self, value): if not self.allow_all_caps: value = value.lower() value = util.title(value) return _humanise(value) if self.human else value def __init__(self, tag, value): self.allow_all_caps = self.config_get_bool('allow_all_caps', True) self.human = self.config_get_bool('human_title_case', True) super().__init__( label=_("Title-_case Value"), use_underline=True) self.set_image( Gtk.Image.new_from_icon_name(Icons.TOOLS_CHECK_SPELLING, Gtk.IconSize.MENU)) self.set_sensitive(self.process_tag(value) != value) @classmethod def PluginPreferences(cls, window): vb = Gtk.VBox() vb.set_spacing(8) config_toggles = [ ('allow_all_caps', _("Allow _ALL-CAPS in tags"), None, True), ('human_title_case', _("_Human title case"), _("Uses common English rules for title casing, as in" " \"Dark Night of the Soul\""), True), ] for key, label, tooltip, default in config_toggles: ccb = cls.ConfigCheckButton(label, key, default) if tooltip: ccb.set_tooltip_text(tooltip) vb.pack_start(ccb, True, True, 0) return vb def activated(self, tag, value): return [(tag, self.process_tag(value))] ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.984269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/���������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016276� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/__init__.py����������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�020405� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684387440.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/advanced_preferences.py����������������������������������������0000644�0001750�0001750�00000025325�14431333160�023004� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # 2016-22 Nick Boultbee # 2019 Peter Strulo # 2022 Jej@github # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import config from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk import Icons from quodlibet.util.string import decode from quodlibet.plugins.events import EventPlugin def _config(section, option, label, tooltip=None, getter=None): def on_changed(entry, *args): config.settext(section, option, entry.get_text()) entry = UndoEntry() if tooltip: entry.set_tooltip_text(tooltip) entry.set_text(config.gettext(section, option)) entry.connect("changed", on_changed) def on_reverted(*args): config.reset(section, option) entry.set_text(config.gettext(section, option)) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) lbl = Gtk.Label(label=label, use_underline=True) lbl.set_mnemonic_widget(entry) return (lbl, entry, revert) def text_config(section, option, label, tooltip=None): def getter(section, option): return decode(config.get(section, option)) return _config(section, option, label, tooltip, getter) def boolean_config(section, option, label, tooltip): def on_reverted(*args): config.reset(section, option) button.set_active(config.getboolean(section, option)) def __toggled(self, section, option): config.set(section, option, str(bool(self.get_active())).lower()) default = config.getboolean(section, option) button = Gtk.CheckButton() button.set_active(config.getboolean(section, option, default)) button.set_tooltip_text(tooltip) button.connect('toggled', __toggled, section, option) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) lbl = Gtk.Label(label=label, use_underline=True) lbl.set_mnemonic_widget(button) return lbl, button, revert def int_config(section, option, label, tooltip): def getter(section, option): return str(config.getint(section, option)) return _config(section, option, label, tooltip, getter) def slider_config(section, option, label, tooltip, lower=0, upper=1, on_change_callback=None, label_value_callback=None): def on_reverted(*args): config.reset(section, option) scale.set_value(config.getfloat(section, option)) def on_change(scale): value = scale.get_value() if on_change_callback: value = on_change_callback(value) scale.set_value(value) config.set(section, option, value) default = config.getfloat(section, option) scale = Gtk.HScale.new(Gtk.Adjustment( value=default, lower=lower, upper=upper)) scale.set_value_pos(Gtk.PositionType.LEFT) scale.set_show_fill_level(True) scale.set_tooltip_text(_(tooltip)) if label_value_callback: scale.connect('format-value', lambda _, value: label_value_callback(value)) scale.connect('value-changed', on_change) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) lbl = Gtk.Label(label=label, use_underline=True) lbl.set_mnemonic_widget(scale) return lbl, scale, revert class AdvancedPreferences(EventPlugin): PLUGIN_ID = "Advanced Preferences" PLUGIN_NAME = _("Advanced Preferences") PLUGIN_DESC = _("Allow editing of advanced config settings.") PLUGIN_CAN_ENABLE = False PLUGIN_ICON = Icons.PREFERENCES_SYSTEM def __init_defaults(self): self.__enabled = False def PluginPreferences(self, *args): def changed(entry, name, section="settings"): config.set(section, name, entry.get_text()) vb = Gtk.VBox(spacing=12) # Tabulate all settings for neatness table = Gtk.Table(n_rows=14, n_columns=4) table.set_col_spacings(12) table.set_row_spacings(6) # We don't use translations as these things are internal # and don't want to burden the translators... # TODO: rethink translation here? (#3494) rows = [ text_config( "editing", "id3encoding", "ID3 encodings:", ("ID3 encodings separated by spaces. " "UTF-8 is always tried first, and Latin-1 is always tried last.")), text_config( "settings", "search_tags", "Extra search tags:", ("Tags that get searched in addition to " "the ones present in the song list. Separate with \",\"")), text_config("editing", "multi_line_tags", "Multi-line tags:", ("Tags to consider as multi-line (delimited by \\n) " "rather than multi-valued (comma-separated)")), text_config("settings", "rating_symbol_full", "Rating symbol (full):"), text_config("settings", "rating_symbol_blank", "Rating symbol (blank):"), text_config( "player", "backend", "Backend:", "Identifier of the playback backend to use"), boolean_config( "settings", "disable_hints", "Disable hints:", "Disable popup windows (treeview hints)"), int_config( "browsers", "cover_size", "Album cover size:", ("Size of the album cover images in the album list browser " "(restart required)")), boolean_config( "settings", "disable_mmkeys", "Disable multimedia keys:", "(restart required)"), text_config( "settings", "window_title_pattern", "Main window title:", ("A (tied) tag for the main window title, e.g. ~title~~people " "(restart required)")), text_config( "settings", "datecolumn_timestamp_format", "Timestamp date format:", "A timestamp format for dates, e.g. %Y%m%d %X (restart required)"), boolean_config( "settings", "scrollbar_always_visible", "Scrollbars always visible:", ("Toggles whether the scrollbars on the bottom and side of " "the window always are visible or get hidden when not in use " "(restart required)")), boolean_config( "settings", "monospace_query", "Use monospace font for search input:", "Helps readability of code-like queries, but looks less consistent " "(restart required)"), text_config( "settings", "query_font_size", "Search input font size:", "Size to apply to the search query entry, " "in any Pango CSS units, e.g. '100%', '1rem'. (restart required)"), boolean_config( "settings", "pangocairo_force_fontconfig", "Force Use Fontconfig Backend:", "It's not the default on win/macOS (restart required)"), text_config( "browsers", "ignored_characters", "Ignored characters:", "Characters to ignore in queries"), boolean_config( "settings", "plugins_window_on_top", "Plugin window on top:", "Toggles whether the plugin window appears on top of others"), int_config( "autosave", "queue_interval", "Queue autosave interval:", ("Longest time between play queue auto-saves, or 0 for disabled. " "(restart required)")), int_config( "browsers", "searchbar_historic_entries", "Number of history entries in the search bar:", "8 by default (restart advised)"), int_config( "browsers", "searchbar_enqueue_limit", "Search bar confirmation limit for enqueue:", ("Maximal size of the song list that can be enqueued from " "the search bar without confirmation.")), slider_config( "player", "playcount_minimum_length_proportion", "Minimum length proportion to consider a track as played:", ("Consider a track played after listening to this proportion of " "its total duration"), label_value_callback=lambda value: f"{int(value * 100)}%"), text_config( "browsers", "missing_title_template", "Missing title template string:", ("Template for building title of tracks when title tag is missing. " "Tags are allowed, like <~basename> <~dirname> <~format> <~length> " "<~#bitrate>, etc. See tags documentation for details.") ) ] for (row, (label, widget, button)) in enumerate(rows): label.set_alignment(1.0, 0.5) table.attach(label, 0, 1, row, row + 1, xoptions=Gtk.AttachOptions.FILL) if isinstance(widget, Gtk.CheckButton): xoptions = Gtk.AttachOptions.FILL widget.set_alignment(0.0, 0.5) table.attach(widget, 1, 2, row, row + 1, xoptions=xoptions) # This stops checkbox from expanding too big, or shrinking text entries blank = Gtk.Label() table.attach(blank, 2, 3, row, row + 1, xoptions=Gtk.AttachOptions.EXPAND) else: xoptions = Gtk.AttachOptions.FILL table.attach(widget, 1, 3, row, row + 1, xoptions=xoptions) table.attach(button, 3, 4, row, row + 1, xoptions=Gtk.AttachOptions.SHRINK) def on_click(button): button.hide() table.set_no_show_all(False) table.show_all() button = Gtk.Button(label=_("I know what I'm doing"), use_underline=True) button.connect("clicked", on_click) vb.pack_start(button, True, True, 0) vb.pack_start(table, True, True, 0) table.set_no_show_all(True) return vb �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.984269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/�������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017730� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/__init__.py��������������������������������������������0000664�0001750�0001750�00000001011�14035600052�022030� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2012-13 Nick Boultbee, Thomas Vogt # Copyright (C) 2008 Andreas Bombe # Copyright (C) 2005 Michael Urman # Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig # (C) 2004 Gustavo J. A. M. Carneiro # # 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 2 of the License, or # (at your option) any later version. from .main import AnimOsd AnimOsd �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/config.py����������������������������������������������0000664�0001750�0001750�00000003433�14035600052�021550� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2012-13 Nick Boultbee, Thomas Vogt # Copyright (C) 2008 Andreas Bombe # Copyright (C) 2005 Michael Urman # Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig # (C) 2004 Gustavo J. A. M. Carneiro # # 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 2 of the License, or # (at your option) any later version. from quodlibet.plugins import (PluginConfig, ConfProp, IntConfProp, FloatConfProp, ColorConfProp) DEFAULT_PATTERN = (r"<album|[b]<album>[/b]<discnumber| - Disc " """<discnumber>><part| - [b]<part>[/b]><tracknumber| - <tracknumber>> >[span weight='bold' size='large']<title>[/span] - <~length><version| [small][i]<version>[/i][/small]><~people| by <~people>>""") def get_config(prefix): class AnimOsdConfig: plugin_conf = PluginConfig(prefix) font = ConfProp(plugin_conf, "font", "Sans 22") string = ConfProp(plugin_conf, "string", DEFAULT_PATTERN) pos_x = FloatConfProp(plugin_conf, "pos_x", 0.5) pos_y = FloatConfProp(plugin_conf, "pos_y", 0.0) corners = IntConfProp(plugin_conf, "corners", 1) delay = IntConfProp(plugin_conf, "delay", 2500) monitor = IntConfProp(plugin_conf, "monitor", 0) align = IntConfProp(plugin_conf, "align", 1) coversize = IntConfProp(plugin_conf, "coversize", 120) text = ColorConfProp(plugin_conf, "text", (0.9, 0.9, 0.9, 0.0)) outline = ColorConfProp(plugin_conf, "outline", (-1.0, 0.0, 0.0, 0.2)) shadow = ColorConfProp(plugin_conf, "shadow", (-1.0, 0.0, 0.0, 0.1)) fill = ColorConfProp(plugin_conf, "fill", (0.25, 0.25, 0.25, 0.5)) return AnimOsdConfig() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/main.py������������������������������������������������0000664�0001750�0001750�00000005760�14035600052�021234� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2012,2013,2016 Nick Boultbee # Copyright (C) 2012-13 Thomas Vogt # Copyright (C) 2008 Andreas Bombe # Copyright (C) 2005 Michael Urman # Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig # (C) 2004 Gustavo J. A. M. Carneiro # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gdk, GLib from quodlibet import _ from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.util import cached_property from .osdwindow import OSDWindow from .config import get_config from .prefs import AnimOsdPrefs class AnimOsd(EventPlugin): PLUGIN_ID = "Animated On-Screen Display" PLUGIN_NAME = _("Animated On-Screen Display") PLUGIN_DESC = _("Displays song information on your screen when it " "changes.") PLUGIN_ICON = Icons.DIALOG_INFORMATION __current_window = None @cached_property def Conf(self): return get_config('animosd') def PluginPreferences(self, parent): return AnimOsdPrefs(self) def plugin_on_song_started(self, song): if self.__current_window is not None: if self.__current_window.is_composited(): self.__current_window.fade_out() else: self.__current_window.hide() self.__current_window.destroy() if song is None: self.__current_window = None return window = OSDWindow(self.Conf, song) window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) window.connect('button-press-event', self.__buttonpress) window.connect('fade-finished', self.__fade_finished) self.__current_window = window window.set_opacity(0.0) window.show() window.fade_in() def plugin_on_error(self, song, error): if self.__current_window is not None: self.__current_window.destroy() self.__current_window = None @staticmethod def start_fade_out(window): window.fade_out() return False def __buttonpress(self, window, event): window.hide() if self.__current_window is window: self.__current_window = None window.destroy() def __fade_finished(self, window, fade_in): if fade_in: GLib.timeout_add(self.Conf.delay, self.start_fade_out, window) else: window.hide() if self.__current_window is window: self.__current_window = None # Delay destroy - apparently the hide does not quite register if # the destroy is done immediately. The compiz animation plugin # then sometimes triggers and causes undesirable effects while the # popup should already be invisible. GLib.timeout_add(1000, window.destroy) ����������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/osdwindow.py�������������������������������������������0000664�0001750�0001750�00000025470�14035600052�022325� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2012-13 Thomas Vogt # Copyright (C) 2012-17 Nick Boultbee # Copyright (C) 2008 Andreas Bombe # Copyright (C) 2005 Michael Urman # Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig # (C) 2004 Gustavo J. A. M. Carneiro # # 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 2 of the License, or # (at your option) any later version. from collections import namedtuple from math import pi import gi gi.require_version("PangoCairo", "1.0") from gi.repository import Gtk, GObject, GLib from gi.repository import Gdk from gi.repository import Pango, PangoCairo import cairo from quodlibet.qltk.image import get_surface_for_pixbuf, get_surface_extents from quodlibet import qltk from quodlibet import app from quodlibet import pattern class OSDWindow(Gtk.Window): __gsignals__ = { 'fade-finished': (GObject.SignalFlags.RUN_LAST, None, (bool,)), } MARGIN = 50 """never any closer to the screen edge than this""" BORDER = 20 """text/cover this far apart, from edge""" FADETIME = 0.3 """take this many seconds to fade in or out""" MS = 40 """wait this many milliseconds between steps""" def __init__(self, conf, song): Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP) self.set_type_hint(Gdk.WindowTypeHint.NOTIFICATION) screen = self.get_screen() rgba = screen.get_rgba_visual() if rgba is not None: self.set_visual(rgba) self.conf = conf self.iteration_source = None self.fading_in = False self.fade_start_time = 0 mgeo = screen.get_monitor_geometry(conf.monitor) textwidth = mgeo.width - 2 * (self.BORDER + self.MARGIN) scale_factor = self.get_scale_factor() cover_pixbuf = app.cover_manager.get_pixbuf( song, conf.coversize * scale_factor, conf.coversize * scale_factor) coverheight = 0 coverwidth = 0 if cover_pixbuf: self.cover_surface = get_surface_for_pixbuf(self, cover_pixbuf) coverwidth = cover_pixbuf.get_width() // scale_factor coverheight = cover_pixbuf.get_height() // scale_factor textwidth -= coverwidth + self.BORDER else: self.cover_surface = None layout = self.create_pango_layout('') layout.set_alignment((Pango.Alignment.LEFT, Pango.Alignment.CENTER, Pango.Alignment.RIGHT)[conf.align]) layout.set_spacing(Pango.SCALE * 7) layout.set_font_description(Pango.FontDescription(conf.font)) try: layout.set_markup(pattern.XMLFromMarkupPattern(conf.string) % song) except pattern.error: layout.set_markup("") layout.set_width(Pango.SCALE * textwidth) layoutsize = layout.get_pixel_size() if layoutsize[0] < textwidth: layout.set_width(Pango.SCALE * layoutsize[0]) layoutsize = layout.get_pixel_size() self.title_layout = layout winw = layoutsize[0] + 2 * self.BORDER if coverwidth: winw += coverwidth + self.BORDER winh = max(coverheight, layoutsize[1]) + 2 * self.BORDER self.set_default_size(winw, winh) rect = namedtuple("Rect", ["x", "y", "width", "height"]) rect.x = self.BORDER rect.y = (winh - coverheight) // 2 rect.width = coverwidth rect.height = coverheight self.cover_rectangle = rect winx = int((mgeo.width - winw) * conf.pos_x) winx = max(self.MARGIN, min(mgeo.width - self.MARGIN - winw, winx)) winy = int((mgeo.height - winh) * conf.pos_y) winy = max(self.MARGIN, min(mgeo.height - self.MARGIN - winh, winy)) self.move(winx + mgeo.x, winy + mgeo.y) def do_draw(self, cr): if self.is_composited(): self.draw_title_info(cr) else: # manual transparency rendering follows walloc = self.get_allocation() wpos = self.get_position() if not getattr(self, "_bg_sf", None): # copy the root surface into a temp image surface root_win = self.get_root_window() bg_sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, walloc.width, walloc.height) pb = Gdk.pixbuf_get_from_window( root_win, wpos[0], wpos[1], walloc.width, walloc.height) bg_cr = cairo.Context(bg_sf) Gdk.cairo_set_source_pixbuf(bg_cr, pb, 0, 0) bg_cr.paint() self._bg_sf = bg_sf if not getattr(self, "_fg_sf", None): # draw the window content in another temp surface fg_sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, walloc.width, walloc.height) fg_cr = cairo.Context(fg_sf) fg_cr.set_source_surface(fg_sf) self.draw_title_info(fg_cr) self._fg_sf = fg_sf # first draw the background so we have 'transparancy' cr.set_operator(cairo.OPERATOR_SOURCE) cr.set_source_surface(self._bg_sf) cr.paint() # then draw the window content with the right opacity cr.set_operator(cairo.OPERATOR_OVER) cr.set_source_surface(self._fg_sf) cr.paint_with_alpha(self.get_opacity()) @staticmethod def rounded_rectangle(cr, x, y, radius, width, height): cr.move_to(x + radius, y) cr.line_to(x + width - radius, y) cr.arc(x + width - radius, y + radius, radius, - 90.0 * pi / 180.0, 0.0 * pi / 180.0) cr.line_to(x + width, y + height - radius) cr.arc(x + width - radius, y + height - radius, radius, 0.0 * pi / 180.0, 90.0 * pi / 180.0) cr.line_to(x + radius, y + height) cr.arc(x + radius, y + height - radius, radius, 90.0 * pi / 180.0, 180.0 * pi / 180.0) cr.line_to(x, y + radius) cr.arc(x + radius, y + radius, radius, 180.0 * pi / 180.0, 270.0 * pi / 180.0) cr.close_path() @property def corners_factor(self): if self.conf.corners != 0: return 0.14 return 0.0 def draw_conf_rect(self, cr, x, y, width, height, radius): if self.conf.corners != 0: self.rounded_rectangle(cr, x, y, radius, width, height) else: cr.rectangle(x, y, width, height) def draw_title_info(self, cr): cr.save() do_shadow = (self.conf.shadow[0] != -1.0) do_outline = (self.conf.outline[0] != -1.0) self.set_name("osd_bubble") qltk.add_css(self, """ #osd_bubble { background-color:rgba(0,0,0,0); } """) cr.set_operator(cairo.OPERATOR_OVER) cr.set_source_rgba(*self.conf.fill) radius = min(25, self.corners_factor * min(*self.get_size())) self.draw_conf_rect(cr, 0, 0, self.get_size()[0], self.get_size()[1], radius) cr.fill() # draw border if do_outline: # Make border darker and more translucent than the fill f = self.conf.fill rgba = (f[0] / 1.25, f[1] / 1.25, f[2] / 1.25, f[3] / 2.0) cr.set_source_rgba(*rgba) self.draw_conf_rect(cr, 1, 1, self.get_size()[0] - 2, self.get_size()[1] - 2, radius) cr.set_line_width(2.0) cr.stroke() textx = self.BORDER if self.cover_surface is not None: rect = self.cover_rectangle textx += rect.width + self.BORDER surface = self.cover_surface transmat = cairo.Matrix() if do_shadow: cr.set_source_rgba(*self.conf.shadow) self.draw_conf_rect(cr, rect.x + 2, rect.y + 2, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.fill() if do_outline: cr.set_source_rgba(*self.conf.outline) self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.stroke() cr.set_source_surface(surface, 0, 0) width, height = get_surface_extents(surface)[2:] transmat.scale(width / float(rect.width), height / float(rect.height)) transmat.translate(-rect.x, -rect.y) cr.get_source().set_matrix(transmat) self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.fill() PangoCairo.update_layout(cr, self.title_layout) height = self.title_layout.get_pixel_size()[1] texty = (self.get_size()[1] - height) // 2 if do_shadow: cr.set_source_rgba(*self.conf.shadow) cr.move_to(textx + 2, texty + 2) PangoCairo.show_layout(cr, self.title_layout) if do_outline: cr.set_source_rgba(*self.conf.outline) cr.move_to(textx, texty) PangoCairo.layout_path(cr, self.title_layout) cr.stroke() cr.set_source_rgb(*self.conf.text[:3]) cr.move_to(textx, texty) PangoCairo.show_layout(cr, self.title_layout) cr.restore() def fade_in(self): self.do_fade_inout(True) def fade_out(self): self.do_fade_inout(False) def do_fade_inout(self, fadein): fadein = bool(fadein) self.fading_in = fadein now = GLib.get_real_time() fraction = self.get_opacity() if not fadein: fraction = 1.0 - fraction self.fade_start_time = now - fraction * self.FADETIME if self.iteration_source is None: self.iteration_source = GLib.timeout_add(self.MS, self.fade_iteration_callback) def fade_iteration_callback(self): delta = GLib.get_real_time() - self.fade_start_time fraction = delta / self.FADETIME if self.fading_in: self.set_opacity(fraction) else: self.set_opacity(1.0 - fraction) if not self.is_composited(): self.queue_draw() if fraction >= 1.0: self.iteration_source = None self.emit('fade-finished', self.fading_in) return False return True ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/animosd/prefs.py�����������������������������������������������0000644�0001750�0001750�00000025626�14267565021�021445� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2012-13 Nick Boultbee, Thomas Vogt # Copyright (C) 2008 Andreas Bombe # Copyright (C) 2005 Michael Urman # Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig # (C) 2004 Gustavo J. A. M. Carneiro # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.util import connect_obj from quodlibet.formats import DUMMY_SONG from quodlibet.qltk.textedit import PatternEdit from quodlibet.qltk import Icons class ConfigLabel(Gtk.Label): """Customised Label for configuration, tied to a widget""" def __init__(self, text, widget): super().__init__(label=text, use_underline=True) self.set_mnemonic_widget(widget) self.set_alignment(0.0, 0.5) class AnimOsdPrefs(Gtk.VBox): def __init__(self, plugin): super().__init__(spacing=6) self.Conf = plugin.Conf self.plugin = plugin def __coltofloat(x): return x / 65535.0 def __floattocol(x): return int(x * 65535) def show_preview(): preview_song = (app.player.song if app.player.song else DUMMY_SONG) self.plugin.plugin_on_song_started(preview_song) def on_button_pressed(x=None, y=None): show_preview() def set_text(button): color = button.get_color() color = map(__coltofloat, (color.red, color.green, color.blue, 0.0)) self.Conf.text = tuple(color) show_preview() def set_fill(button): color = button.get_color() color = map(__coltofloat, (color.red, color.green, color.blue, button.get_alpha())) self.Conf.fill = tuple(color) show_preview() def set_font(button): font = button.get_font_name() self.Conf.font = font show_preview() def change_delay(button): value = int(button.get_value() * 1000) self.Conf.delay = value def change_monitor(button): """Monitor number config change handler""" value = int(button.get_value()) self.Conf.monitor = value show_preview() def change_position(button, x, y): self.Conf.pos_x = x / 2.0 self.Conf.pos_y = y / 2.0 show_preview() def change_align(button): value = button.get_active() self.Conf.align = value show_preview() def change_shadow(button): if button.get_active(): self.Conf.shadow = (0.0, 0.0, 0.0, self.Conf.fill[3]) else: self.Conf.shadow = (-1.0, 0.0, 0.0, 0.0) show_preview() def change_outline(button): if button.get_active(): # Vary with fill alpha to create a smoother outline edge alpha = (min(1.0, self.Conf.fill[3] * 1.25)) self.Conf.outline = (0.1, 0.1, 0.1, alpha) else: self.Conf.outline = (-1.0, 0.0, 0.0) show_preview() def change_rounded(button): if button.get_active(): self.Conf.corners = 1 else: self.Conf.corners = 0 show_preview() def change_coversize(button): value = int(button.get_value()) self.Conf.coversize = value show_preview() def edit_pattern(button): w = PatternEdit(button, self.Conf.string) w.set_default_size(520, 260) w.text = self.Conf.string connect_obj(w.apply, 'clicked', set_string, w) w.show() def set_string(window): value = window.text self.Conf.string = value show_preview() def build_display_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) # Set monitor to display OSD on if there's more than one monitor_cnt = Gdk.Screen.get_default().get_n_monitors() if monitor_cnt > 1: adj = Gtk.Adjustment(value=self.Conf.monitor, lower=0, upper=monitor_cnt - 1, step_increment=1) monitor = Gtk.SpinButton(adjustment=adj) monitor.set_numeric(True) monitor.connect('value-changed', change_monitor) l2 = ConfigLabel("_Monitor:", monitor) hb.pack_start(l2, False, True, 0) hb.pack_start(monitor, False, True, 0) vb2.pack_start(hb, True, True, 0) else: # should be this by default anyway self.Conf.monitor = 0 hb = Gtk.HBox(spacing=6) grid = Gtk.Grid(column_homogeneous=True, row_homogeneous=True, row_spacing=4, column_spacing=4) arrows = [['↖', '↑', '↗'], ['←', '○', '→'], ['↙', '↓', '↘ ']] group = None for x in range(3): for y in range(3): rb = Gtk.RadioButton(group=group, label=arrows[y][x]) if (int(self.Conf.pos_x * 2.0) == x and int(self.Conf.pos_y * 2.0) == y): rb.set_active(True) grid.attach(rb, x, y, 1, 1) group = rb # Connect to signal after the correct radio button has been # selected for x in range(3): for y in range(3): rb = grid.get_child_at(x, y) rb.connect('toggled', change_position, x, y) lbl = ConfigLabel(_("_Position:"), grid) hb.pack_start(lbl, False, True, 0) hb.pack_start(grid, False, True, 0) vb2.pack_start(hb, False, True, 6) hb = Gtk.HBox(spacing=6) coversize = Gtk.SpinButton( adjustment=Gtk.Adjustment.new( self.Conf.coversize, 1, 600, 1, 10, 0), climb_rate=1, digits=0) coversize.set_numeric(True) coversize.connect('value-changed', change_coversize) l1 = ConfigLabel(_("_Cover size:"), coversize) hb.pack_start(l1, False, True, 0) hb.pack_start(coversize, False, True, 0) vb2.pack_start(hb, False, True, 0) return vb2 frame = qltk.Frame(label=_("Display"), child=build_display_widget()) frame.set_border_width(6) self.pack_start(frame, False, True, 0) def build_text_widget(): t = Gtk.Table(n_rows=2, n_columns=2) t.props.expand = False t.set_col_spacings(6) t.set_row_spacings(3) font = Gtk.FontButton(show_style=True) font.set_font_name(self.Conf.font) font.connect('font-set', set_font) lbl = ConfigLabel(_("_Font:"), font) t.attach(lbl, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) t.attach(font, 1, 2, 0, 1) align = Gtk.ComboBoxText() align.append_text(_("Left")) align.append_text(_("Center")) align.append_text(_("Right")) align.set_active(self.Conf.align) align.connect('changed', change_align) lbl = ConfigLabel(_("_Align text:"), align) t.attach(lbl, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) t.attach(align, 1, 2, 1, 2) return t frame = qltk.Frame(label=_("Text"), child=build_text_widget()) frame.set_border_width(6) self.pack_start(frame, False, True, 0) def build_colors_widget(): t = Gtk.Table(n_rows=2, n_columns=2) t.props.expand = False t.set_col_spacings(6) t.set_row_spacings(3) b = Gtk.ColorButton( rgba=Gdk.RGBA(*map(__floattocol, self.Conf.text))) l = ConfigLabel(_("_Text:"), b) t.attach(l, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) t.attach(b, 1, 2, 0, 1) b.connect('color-set', set_text) b = Gtk.ColorButton(color=Gdk.Color(*map(__floattocol, self.Conf.fill[0:3]))) b.set_use_alpha(True) b.set_alpha(__floattocol(self.Conf.fill[3])) b.connect('color-set', set_fill) l = ConfigLabel(_("_Fill:"), b) t.attach(l, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) t.attach(b, 1, 2, 1, 2) return t f = qltk.Frame(label=_("Colors"), child=build_colors_widget()) f.set_border_width(6) self.pack_start(f, False, False, 0) def build_effects_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) toggles = [ (_("_Shadows"), self.Conf.shadow[0], change_shadow), (_("_Outline"), self.Conf.outline[0], change_outline), (_("Rou_nded Corners"), self.Conf.corners - 1, change_rounded)] for (label, current, callback) in toggles: checkb = Gtk.CheckButton(label=label, use_underline=True) checkb.set_active(current != -1) checkb.connect("toggled", callback) hb.pack_start(checkb, True, True, 0) vb2.pack_start(hb, True, True, 0) hb = Gtk.HBox(spacing=6) timeout = Gtk.SpinButton( adjustment=Gtk.Adjustment.new( self.Conf.delay / 1000.0, 0, 60, 0.1, 1.0, 0), climb_rate=0.1, digits=1) timeout.set_numeric(True) timeout.connect('value-changed', change_delay) l1 = ConfigLabel(_("_Delay:"), timeout) hb.pack_start(l1, False, True, 0) hb.pack_start(timeout, False, True, 0) vb2.pack_start(hb, False, True, 0) return vb2 frame = qltk.Frame(label=_("Effects"), child=build_effects_widget()) frame.set_border_width(6) self.pack_start(frame, False, True, 0) def build_buttons_widget(): hb = Gtk.HBox(spacing=6) edit_button = qltk.Button(_(u"Ed_it Display Pattern…"), Icons.EDIT) edit_button.connect('clicked', edit_pattern) hb.pack_start(edit_button, False, True, 0) preview_button = Gtk.Button(label=_("Preview"), use_underline=True) preview_button.connect("button-press-event", on_button_pressed) hb.pack_start(preview_button, False, True, 0) return hb self.pack_start(build_buttons_widget(), False, True, 0) ����������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684265741.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/appinfo.py�����������������������������������������������������0000644�0001750�0001750�00000007666�14430755415�020334� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import platform from gi.repository import Gtk, Pango from senf import fsn2uri, fsn2text import mutagen from quodlibet import _ from quodlibet.qltk import Icons from quodlibet.util.path import unexpand from quodlibet.plugins.events import EventPlugin from quodlibet import formats from quodlibet import app, get_user_dir, get_cache_dir from quodlibet.util import fver, escape from quodlibet.qltk import gtk_version, pygobject_version, get_backend_name, \ get_font_backend_name from quodlibet.qltk import show_uri class AppInformation(EventPlugin): PLUGIN_ID = "AppInformation" PLUGIN_NAME = _("Application Information") PLUGIN_DESC = _("Various information about the application and its " "environment.") PLUGIN_CAN_ENABLE = False PLUGIN_ICON = Icons.PREFERENCES_SYSTEM def PluginPreferences(self, *args): vb = Gtk.VBox() row = 0 grid = Gtk.Grid(column_spacing=12, row_spacing=6) def label_title(text): l = Gtk.Label(label=text, xalign=1, yalign=0, wrap=True, justify=Gtk.Justification.RIGHT, selectable=True) l.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL) return l def label_value(text): return Gtk.Label(label=text, wrap=True, xalign=0, yalign=0, width_chars=25, selectable=True) def label_path(path): l = Gtk.Label(label="<a href='%s'>%s</a>" % ( fsn2uri(path), escape(fsn2text(unexpand(path)))), use_markup=True, ellipsize=Pango.EllipsizeMode.MIDDLE, xalign=0, selectable=True) l.connect("activate-link", show_uri) return l grid.insert_row(row) l = label_title(_("Supported Formats")) format_names = sorted([t.format for t in formats.types]) v = label_value(", ".join(format_names)) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title(_("Configuration Directory")) v = label_path(get_user_dir()) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title(_("Cache Directory")) v = label_path(get_cache_dir()) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title(_("Audio Backend")) v = label_value("%s\n%s" % (app.player.name, app.player.version_info)) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title("Python") v = label_value(platform.python_version()) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title("Mutagen") v = label_value(fver(mutagen.version)) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title("Gtk+") v = label_value("%s (%s, %s)" % ( fver(gtk_version), get_backend_name(), get_font_backend_name())) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 grid.insert_row(row) l = label_title("PyGObject") v = label_value(fver(pygobject_version)) grid.attach(l, 0, row, 1, 1) grid.attach(v, 1, row, 1, 1) row += 1 vb.pack_start(grid, True, True, 0) vb.show_all() return vb ��������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/auto_update_tags_in_files.py�����������������������������������0000644�0001750�0001750�00000021666�14327505043�024067� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019-2020 Joschua Gandert # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from enum import IntEnum from gi.repository import Gtk from quodlibet import _, app, config, qltk, const from quodlibet.qltk import Icons, ErrorMessage, Message from quodlibet.plugins import PluginConfig, BoolConfProp, IntConfProp from quodlibet.plugins.events import EventPlugin from quodlibet.plugins.songshelpers import is_writable from quodlibet.util import print_e from quodlibet.util.songwrapper import SongWrapper class UpdateStrategy(IntEnum): AFTER_PLAY_NOT_SKIP = 0 AFTER_PLAY_OR_SKIP = 1 ONCE_ALBUM_RATED = 2 class StrategyText: def __init__(self, name, description): self.name = name self.description = description STRATEGY_TEXTS = { # UpdateStrategy.AFTER_PLAY_NOT_SKIP: StrategyText( _("After every play (default)"), # _("Whenever a song was played but not skipped, the plugin will " "write the tags to the file. Skip counts aren't stored in " "files at all, so this avoids unnecessary writes.")), # UpdateStrategy.AFTER_PLAY_OR_SKIP: StrategyText( _("After every play or skip"), # _("Whenever a song was played or skipped, the plugin will write " "the tags to the file. Can be useful if you want to make sure " "that ratings of songs you dislike and thus skipped are written " "to the files.")), # UpdateStrategy.ONCE_ALBUM_RATED: StrategyText( _("Once, when album fully rated"), # _("When a song was played or skipped, the album of that song will " "be checked. If every song in the album has been rated and at " "least one has no ratings or play counts stored in its file, " "the plugin will write the tags to the songs' files.\n\nUse " "this to avoid constant file updates, but be aware that once an " "album was updated, you'll have to use the 'Update Tags in " "Files' plugin whenever you want modified ratings and play " "counts to be written to the files."))} PLAY_COUNT_ABOVE_ZERO_TOOLTIP = _( "When the plugin writes the tags of an album, it will " "first set the play count of the songs which are zero to one.\n" "Sometimes you already know that you don't like a song, so " "setting it to one when saving can be useful later on, when " "searching for albums you have fully listened to (%s).") WRITE_ERROR_FMT = _("Couldn't write '%s'") class Config: _config = PluginConfig("autoupdatetagsinfiles") update_strategy = IntConfProp(_config, "update_strategy", UpdateStrategy.AFTER_PLAY_NOT_SKIP.value) ensure_play_counts_above_zero = BoolConfProp( # useful for searching _config, "ensure_play_counts_above_zero", False) CONFIG = Config() class AutoUpdateTagsInFiles(EventPlugin): PLUGIN_ID = "AutoUpdateTagsInFiles" PLUGIN_NAME = _("Auto Update Tags in Files") PLUGIN_DESC = _("When songs were played, update the tags in their files. " "This will ensure play counts and ratings are up to date.") PLUGIN_ICON = Icons.DOCUMENT_SAVE def PluginPreferences(self, _): return AutoUpdateTagsPrefs() def enabled(self): if not config.getboolean("editing", "save_to_songs"): config.set("editing", "save_to_songs", True) warning_text = _("The following setting was enabled as it's " "required for this plugin to work:\n\n%s") setting_name = _("Save ratings and play _counts in tags") Message(Gtk.MessageType.INFO, app.window, _("Settings updated"), warning_text % setting_name.replace("_", "")).run() def plugin_on_song_ended(self, song, skipped): if song is None or not is_writable(song): return strategy = CONFIG.update_strategy if strategy == UpdateStrategy.AFTER_PLAY_NOT_SKIP: if not skipped: self._try_to_update_song(song) return elif strategy == UpdateStrategy.AFTER_PLAY_OR_SKIP: self._try_to_update_song(song) return self._update_album_if_fully_rated(song.album_key) def _try_to_update_song(self, song_wrapper): try: song_wrapper._needs_write = True except Exception as e: print_e(e) self._error_msg(WRITE_ERROR_FMT % song_wrapper._song) def _error_msg(self, message): title = _("Error in %s") % self.PLUGIN_NAME ErrorMessage(app.window, title, message).run() def _update_album_if_fully_rated(self, album_key): album = app.library.albums.get(album_key, None) if album is None: return songs = album.songs # first check for ratings to avoid costly file checks if not songs or not all(song.has_rating for song in songs): return songs = [s for s in songs if s.supports_rating_and_play_count_in_file] if not songs: return email = config.get("editing", "save_email", const.EMAIL).strip() if all(s.has_rating_and_playcount_in_file(email) for s in songs): return # at least one song has no ratings or play counts stored in files try: self._update_album(songs) except Exception as e: print_e(e) self._error_msg(WRITE_ERROR_FMT % album_key) def _update_album(self, songs): song_wrappers = [] req_play_counts_above_zero = CONFIG.ensure_play_counts_above_zero for song in songs: if req_play_counts_above_zero and not song.get("~#playcount", 0): song['~#playcount'] = 1 wrapper = SongWrapper(song) wrapper._needs_write = True song_wrappers.append(wrapper) class AutoUpdateTagsPrefs(Gtk.Box): def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) strategy_boxes = [] for strategy in UpdateStrategy: desc = STRATEGY_TEXTS[strategy].description desc_label = Gtk.Label(label=desc, wrap=True) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) box.pack_start(desc_label, False, False, 0) strategy_boxes.append(box) def ensure_play_count_toggled(button, *args): CONFIG.ensure_play_counts_above_zero = button.get_active() ensure_play_count_checkbutton = Gtk.CheckButton( label=_("Ensure play counts are above zero when saving"), valign=Gtk.Align.START) ensure_play_count_checkbutton.set_tooltip_text( PLAY_COUNT_ABOVE_ZERO_TOOLTIP % "#(playcount:min = 1)") ensure_play_count_checkbutton.set_active( CONFIG.ensure_play_counts_above_zero) ensure_play_count_checkbutton.connect("toggled", ensure_play_count_toggled) album_box = strategy_boxes[UpdateStrategy.ONCE_ALBUM_RATED] album_box.pack_start(ensure_play_count_checkbutton, False, False, 0) def show_only_current_box(): current = CONFIG.update_strategy for n, box in enumerate(strategy_boxes): box.set_visible(n == current) grid = Gtk.Grid(column_spacing=6, row_spacing=6) def grid_add(x, y, child): grid.attach(child, x, y, 1, 1) def change_strategy(button): new_strategy = button.get_active() CONFIG.update_strategy = new_strategy show_only_current_box() update_combobox = Gtk.ComboBoxText() for strategy in UpdateStrategy: update_combobox.append_text(STRATEGY_TEXTS[strategy].name) update_combobox.set_active(CONFIG.update_strategy) update_combobox.connect('changed', change_strategy) update_lbl = ConfigLabel(_("_Update strategy:"), update_combobox) grid_add(0, 0, update_lbl) grid_add(1, 0, update_combobox) for box in strategy_boxes: # show_all will be called on the plugin preference interface, so # without the following that would result in overlapping text box.show_all() box.props.no_show_all = True grid_add(1, 1, box) show_only_current_box() frame = qltk.Frame(label=_("Preferences"), child=grid) self.pack_start(frame, False, False, 0) class ConfigLabel(Gtk.Label): """Customised Label for configuration, tied to a widget""" def __init__(self, text, widget): super().__init__(label=text, use_underline=True) self.set_mnemonic_widget(widget) self.set_alignment(0.0, 0.5) ��������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/automask.py����������������������������������������������������0000664�0001750�0001750�00000003277�14035600052�020503� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2014 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gio from quodlibet import _ from quodlibet.qltk import Icons from quodlibet import app from quodlibet.plugins.events import EventPlugin class AutoMasking(EventPlugin): PLUGIN_ID = "automask" PLUGIN_NAME = _("Automatic Masking") PLUGIN_DESC = _("Automatically masks and unmasks drives when they " "are unmounted or mounted.") PLUGIN_ICON = Icons.DRIVE_REMOVABLE_MEDIA __sigs = None __monitor = None def enabled(self): if self.__monitor is None: self.__monitor = Gio.VolumeMonitor.get() self.__sigs = [ self.__monitor.connect('mount-added', self.__mounted), self.__monitor.connect('mount-removed', self.__unmounted), ] else: for signal_id in self.__sigs: self.__monitor.handler_unblock(signal_id) def disabled(self): for signal_id in self.__sigs: self.__monitor.handler_unblock(signal_id) def __mounted(self, monitor, mount): path = mount.get_default_location().get_path() if path is not None: app.library.unmask(os.path.normpath(path)) def __unmounted(self, monitor, mount): path = mount.get_default_location().get_path() if path is not None: app.library.mask(os.path.normpath(path)) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/autorating.py��������������������������������������������������0000644�0001750�0001750�00000002162�14327505043�021032� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons class AutoRating(EventPlugin): PLUGIN_ID = "Automatic Rating" PLUGIN_NAME = _("Automatic Rating") PLUGIN_DESC = _("Rates songs automatically when they are played or " "skipped. This uses the 'accelerated' algorithm from " "vux (Vacillating Utilitarian eXtemporizer) " "by Brian Nelson.") PLUGIN_ICON = Icons.USER_BOOKMARKS def plugin_on_song_ended(self, song, skipped): if song is not None: rating = song("~#rating") invrating = 1.0 - rating delta = min(rating, invrating) / 2.0 if skipped: rating -= delta else: rating += delta song["~#rating"] = rating ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/bansheeimport.py�����������������������������������������������0000644�0001750�0001750�00000013443�14266344767�021541� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Phidica Veia # # 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 2 of the License, or # (at your option) any later version. import os import sqlite3 from gi.repository import Gtk from senf import uri2fsn, text2fsn from quodlibet import _ from quodlibet import app from quodlibet import ngettext from quodlibet import util from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk import Icons from quodlibet.qltk.msg import Message, WarningMessage, ErrorMessage from quodlibet.util.path import normalize_path from quodlibet.plugins.events import EventPlugin class BansheeDBImporter: def __init__(self, library): self._library = library self._changed_songs = [] def read(self, db): """Iterate through the database and import data for songs found in the library """ # use the Row class for extracting rows db.row_factory = sqlite3.Row # iterate over all songs in the database # throws sqlite3.OperationalError if CoreTracks is not found for row in db.execute("SELECT * FROM CoreTracks"): try: filename = uri2fsn(row["Uri"]) except ValueError: continue song = self._library.get(normalize_path(filename)) if not song: continue has_changed = False # rating is stored as integer from 0 to 5 b_rating = row["Rating"] / 5.0 if b_rating != song("~#rating"): song["~#rating"] = b_rating has_changed = True # play count is stored as integer from 0 if row["PlayCount"] != song("~#playcount"): # summing play counts would break on multiple imports song["~#playcount"] = row["PlayCount"] has_changed = True # skip count is stored as integer from 0 if row["SkipCount"] != song("~#skipcount"): song["~#skipcount"] = row["SkipCount"] has_changed = True # timestamp is stored as integer or None if row["LastPlayedStamp"] is not None: value = row["LastPlayedStamp"] # keep timestamp if it is newer than what we had if value > song("~#lastplayed", 0): song["~#lastplayed"] = value has_changed = True if row["DateAddedStamp"] is not None: value = row["DateAddedStamp"] # keep timestamp if it is older than what we had if value < song("~#added", 0): song["~#added"] = value has_changed = True if has_changed: self._changed_songs.append(song) def finish(self): """Call at the end, also returns number of songs with data imported""" count = len(self._changed_songs) self._library.changed(self._changed_songs) self._changed_songs = [] return count def do_import(parent, library): db_path = os.path.expanduser(BansheeImport.USR_PATH) importer = BansheeDBImporter(library) try: db = sqlite3.connect(db_path) importer.read(db) db.close() except sqlite3.OperationalError: msg = _("Specified Banshee database is malformed or missing") WarningMessage(parent, BansheeImport.PLUGIN_NAME, msg).run() except Exception: util.print_exc() importer.finish() msg = _("Import Failed") # FIXME: don't depend on the plugin class here ErrorMessage(parent, BansheeImport.PLUGIN_NAME, msg).run() else: count = importer.finish() msg = ngettext( "Successfully imported ratings and statistics for %d song", "Successfully imported ratings and statistics for %d songs", count) % count Message(Gtk.MessageType.INFO, parent, BansheeImport.PLUGIN_NAME, msg).run() class BansheeImport(EventPlugin): PLUGIN_ID = "bansheeimport" PLUGIN_NAME = _("Banshee Import") PLUGIN_DESC = _("Imports ratings and song statistics from Banshee.") PLUGIN_ICON = Icons.DOCUMENT_OPEN DEF_PATH = "~/.config/banshee-1/banshee.db" USR_PATH = DEF_PATH def PluginPreferences(self, *args): grid = Gtk.Grid(row_spacing=6, column_spacing=6) label = Gtk.Label(label=_("_Database path:"), use_underline=True) label.set_alignment(0.0, 0.5) grid.attach(label, 0, 0, 1, 1) entry = UndoEntry() entry.set_hexpand(True) entry.set_text(BansheeImport.DEF_PATH) def path_activate(entry, *args): path = text2fsn(entry.get_text()) if BansheeImport.USR_PATH != path: BansheeImport.USR_PATH = path entry.connect_after("activate", path_activate) entry.connect_after("focus-out-event", path_activate) grid.attach_next_to(entry, label, Gtk.PositionType.RIGHT, 1, 1) path_revert = Gtk.Button() path_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) def path_revert_cb(button, entry): entry.set_text(BansheeImport.DEF_PATH) entry.emit("activate") path_revert.connect("clicked", path_revert_cb, entry) grid.attach_next_to(path_revert, entry, Gtk.PositionType.RIGHT, 1, 1) button = Gtk.Button(label=_("Start Import")) def clicked_cb(button): do_import(button, app.library) button.connect("clicked", clicked_cb) box = Gtk.VBox(spacing=12) box.pack_start(grid, True, True, 0) box.pack_start(button, False, False, 0) return box �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/clock.py�������������������������������������������������������0000664�0001750�0001750�00000010056�14035600052�017743� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2016,18 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import time from gi.repository import Gtk, GLib from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet.plugins.events import EventPlugin from quodlibet.qltk.entry import ValidatingEntry from quodlibet.qltk import Icons from quodlibet.util import connect_obj class Alarm(EventPlugin): PLUGIN_ID = "Alarm Clock" PLUGIN_NAME = _("Alarm Clock") PLUGIN_DESC = _("Wakes you up with loud music.") PLUGIN_ICON = Icons.APPOINTMENT_NEW _pref_name = "alarm_times" _times = ["HH:MM"] * 7 _enabled = False def __init__(self): try: self._times = config.get("plugins", self._pref_name).split(' ')[:7] except: pass else: self._times = (self._times + ["HH:MM"] * 7)[:7] GLib.timeout_add(30000, self._check) def enabled(self): self._enabled = True def disabled(self): self._enabled = False @staticmethod def is_valid_time(time): try: hour, minute = map(int, time.split(":")) except: return False else: return (hour < 24 and minute < 60) def plugin_on_song_started(self, song): pass def _entry_changed(self, entries): self._times = [ValidatingEntry.get_text(e) for e in entries] config.set("plugins", self._pref_name, " ".join(self._times)) def _ready(self): tdata = time.localtime() goal = self._times[tdata.tm_wday] try: ghour, gminute = map(int, goal.split(":")) except: return False else: return (tdata.tm_hour, tdata.tm_min) == (ghour, gminute) def _fire(self): if self._enabled: if app.player.paused: if app.player.song is None: app.player.next() else: app.player.paused = False GLib.timeout_add(60000, self._longer_check) def _longer_check(self): if self._ready(): self._fire() else: GLib.timeout_add(30000, self._check) def _check(self): if self._ready(): self._fire() else: return True def PluginPreferences(self, parent): t = Gtk.Table(n_rows=2, n_columns=7) t.set_col_spacings(6) entries = [] for i in range(7): e = ValidatingEntry(Alarm.is_valid_time) e.set_size_request(100, -1) e.set_text(self._times[i]) e.set_max_length(5) e.set_width_chars(6) day = Gtk.Label( label=time.strftime("_%A:", (2000, 1, 1, 0, 0, 0, i, 1, 0))) day.set_mnemonic_widget(e) day.set_use_underline(True) day.set_alignment(0.0, 0.5) t.attach(day, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) t.attach(e, 1, 2, i, i + 1, xoptions=Gtk.AttachOptions.FILL) entries.append(e) for e in entries: connect_obj(e, 'changed', self._entry_changed, entries) return t class Lullaby(Alarm): PLUGIN_ID = "Lullaby" PLUGIN_NAME = _("Lullaby") PLUGIN_DESC = _("Fades out and pauses your music.") PLUGIN_ICON = Icons.MEDIA_PLAYBACK_PAUSE _pref_name = "lullaby_times" def _fire(self): if self._enabled: GLib.timeout_add(500, self._fade_out) self.__was_volume = app.player.volume else: GLib.timeout_add(30000, self._check) def _fade_out(self): app.player.volume -= 0.005 if app.player.volume == 0: app.player.paused = True if app.player.paused: app.player.volume = self.__was_volume GLib.timeout_add(30000, self._check) else: return True ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/discord_status.py����������������������������������������������0000644�0001750�0001750�00000011566�14267565021�021724� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# discord_status: Set Discord status as current song. # # Copyright (c) 2022 Aditi K <105543244+teeleafs@users.noreply.github.com> # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _, app from quodlibet.plugins import PluginConfig, ConfProp from quodlibet.plugins.events import EventPlugin from quodlibet.pattern import Pattern from gi.repository import Gtk try: from pypresence import Presence, InvalidID, DiscordNotFound except ImportError: from quodlibet.plugins import MissingModulePluginException raise MissingModulePluginException("pypresence") # The below resources are from/uploaded-to the Discord Application portal. QL_DISCORD_RP_ID = '974521025356242984' QL_LARGE_IMAGE = "io-github-quodlibet-quodlibet" VERSION = "1.0" # Default Rich Presence status lines. CONFIG_DEFAULT_RP_LINE1 = "<artist> / <title>" CONFIG_DEFAULT_RP_LINE2 = "<album>" class DiscordStatusConfig: _config = PluginConfig(__name__) rp_line1 = ConfProp(_config, "rp_line1", CONFIG_DEFAULT_RP_LINE1) rp_line2 = ConfProp(_config, "rp_line2", CONFIG_DEFAULT_RP_LINE2) discord_status_config = DiscordStatusConfig() class DiscordStatusMessage(EventPlugin): PLUGIN_ID = _("Discord status message") PLUGIN_NAME = _("Discord Status Message") PLUGIN_DESC = _("Change your Discord status message according to what " "you're currently listening to.") VERSION = VERSION def __init__(self): self.song = None self.discordrp = None def update_discordrp(self, details, state=None): if not self.discordrp: try: self.discordrp = Presence(QL_DISCORD_RP_ID, pipe=0) self.discordrp.connect() except (DiscordNotFound, ConnectionRefusedError): self.discordrp = None if self.discordrp: try: self.discordrp.update(details=details, state=state, large_image=QL_LARGE_IMAGE) except InvalidID: # XXX Discord was closed? self.discordrp = None def handle_play(self): if self.song: details = Pattern(discord_status_config.rp_line1) % self.song state = Pattern(discord_status_config.rp_line2) % self.song # The details and state fields must be atleast 2 characters. if len(details) < 2: details = None if len(state) < 2: state = None self.update_discordrp(details, state) def handle_paused(self): self.update_discordrp(details=_("Paused")) def handle_unpaused(self): if not self.song: self.song = app.player.song self.handle_play() def plugin_on_song_started(self, song): self.song = song if not app.player.paused: self.handle_play() def plugin_on_paused(self): self.handle_paused() def plugin_on_unpaused(self): self.handle_unpaused() def enabled(self): if app.player.paused: self.handle_paused() else: self.handle_unpaused() def disabled(self): if self.discordrp: self.discordrp.clear() self.discordrp.close() self.discordrp = None self.song = None def PluginPreferences(self, parent): vb = Gtk.VBox(spacing=6) def rp_line1_changed(entry): discord_status_config.rp_line1 = entry.get_text() if not app.player.paused: self.handle_play() def rp_line2_changed(entry): discord_status_config.rp_line2 = entry.get_text() if not app.player.paused: self.handle_play() status_line1_box = Gtk.HBox(spacing=6) status_line1_box.set_border_width(3) status_line1 = Gtk.Entry() status_line1.set_text(discord_status_config.rp_line1) status_line1.connect('changed', rp_line1_changed) status_line1_box.pack_start(Gtk.Label(label=_("Status Line #1")), False, True, 0) status_line1_box.pack_start(status_line1, True, True, 0) status_line2_box = Gtk.HBox(spacing=3) status_line2_box.set_border_width(3) status_line2 = Gtk.Entry() status_line2.set_text(discord_status_config.rp_line2) status_line2.connect('changed', rp_line2_changed) status_line2_box.pack_start(Gtk.Label(label=_('Status Line #2')), False, True, 0) status_line2_box.pack_start(status_line2, True, True, 0) vb.pack_start(status_line1_box, True, True, 0) vb.pack_start(status_line2_box, True, True, 0) return vb ������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/equalizer.py���������������������������������������������������0000644�0001750�0001750�00000032613�14267565021�020667� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010 Steven Robertson # 2012 Christoph Reiter # 2017 Nick Boultbee # 2018 Olli Helin # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet.qltk import Button, Icons from quodlibet.plugins.events import EventPlugin from quodlibet.util import print_e, print_w import ast # Presets (roughly) taken from Pulseaudio equalizer PRESET_BANDS = [50, 100, 156, 220, 311, 440, 622, 880, 1250, 1750, 2500, 3500, 5000, 10000, 20000] PRESETS = { "flat": (_("Flat"), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), "live": (_("Live"), [-9.0, -5.5, 0.0, 1.5, 2.0, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.0, 1.5, 2.0]), "full_bass_treble": (_("Full Bass & Treble"), [5.0, 5.0, 3.5, 2.5, 0.0, -7.0, -14.0, -10.0, -10.0, -8.0, 1.0, 1.0, 5.0, 7.5, 9.5]), "club": (_("Club"), [0.0, 0.0, 0.0, 0.0, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 2.5, 2.5, 0.0, 0.0]), "large_hall": (_("Large Hall"), [7.0, 7.0, 7.0, 3.5, 3.0, 3.0, 3.0, 1.5, 0.0, -2.0, -3.5, -6.0, -9.0, -1.0, 0.0]), "party": (_("Party"), [5.0, 5.0, 5.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.5, 5.0]), "rock": (_("Rock"), [5.5, 2.5, 2.5, -8.5, -10.5, -11.0, -16.0, -14.5, -6.5, -5.5, -3.0, 3.0, 6.5, 7.0, 7.0]), "soft": (_("Soft"), [3.0, 3.0, 1.0, 1.0, 0.0, -2.5, -5.0, 1.5, 0.0, 1.0, 3.0, 3.0, 6.0, 8.0, 8.0]), "full_bass": (_("Full Bass"), [-16.0, -16.0, 6.5, 6.5, 6.0, 5.5, 4.5, 1.0, 1.0, 1.0, -8.0, -10.0, -16.0, -16.0, -20.5]), "classical": (_("Classical"), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -21.0, -21.0, -27.0]), "reggae": (_("Reggae"), [0.0, 0.0, 0.0, 0.0, 0.0, -4.5, -10.0, -6.0, 0.5, 1.0, 2.0, 4.0, 4.0, 0.0, 0.0]), "headphones": (_("Headphones"), [3.0, 3.0, 7.0, 7.0, 3.0, -1.0, -6.5, -6.0, -4.5, -4.0, 1.0, 1.0, 6.0, 8.0, 9.0]), "soft_rock": (_("Soft Rock"), [3.0, 3.0, 3.0, 1.5, 1.5, 1.5, 0.0, -3.5, -8.0, -7.0, -10, -9.0, -6.5, 1.5, 6.0]), "full_treble": (_("Full Treble"), [5.0, -18.5, -18.5, -18.5, -18.5, -10.0, -8.0, -6.5, 1.5, 1.5, 1.5, 8.5, 10.5, 10.5, 10.5]), "dance": (_("Dance"), [6.0, 4.0, 4.0, 1.5, 1.5, 1.5, 0.0, 0.0, 0.0, 1.0, -10.5, -14.0, -15.0, -7.0, 0.0]), "pop": (_("Pop"), [-3.5, 1.0, 2.0, 3.0, 5.0, 5.5, 6.5, 5.0, 3.0, 1.5, 0.0, -2.5, -5.0, -5.0, -3.0]), "techno": (_("Techno"), [5.0, 4.0, 4.0, 3.0, 0.0, -4.5, -10.0, -9.0, -8.0, -5.5, -1.5, 3.0, 6.0, 6.0, 6.0]), "ska": (_("Ska"), [-4.5, -8.0, -9.0, -8.5, -8.0, -6.0, 0.0, 1.5, 2.5, 2.5, 3.0, 3.0, 6.0, 6.0, 6.0]), "laptop": (_("Laptop"), [-1, -1, -1, -1, -5, -10, -18, -15, -10, -5, -5, -5, -5, 0, 0]), } def interp_bands(src_band, target_band, src_gain): """Linear interp from one band to another. All must be sorted.""" gain = [] for i, b in enumerate(target_band): if b in src_band: gain.append(src_gain[i]) continue idx = sorted(src_band + [b]).index(b) idx = min(max(idx, 1), len(src_band) - 1) x1, x2 = src_band[idx - 1:idx + 1] y1, y2 = src_gain[idx - 1:idx + 1] g = y1 + ((y2 - y1) * (b - x1)) / float(x2 - x1) gain.append(min(12.0, g)) return gain def get_config(): try: config_str = config.get("plugins", "equalizer_levels", "[]") config_dict = ast.literal_eval(config_str) if isinstance(config_dict, list): print_w("Converting old EQ config to new format.") config_dict = {"Current": config_dict} if not isinstance(config_dict, dict): raise ValueError("Saved config is of wrong type.") if not "Current" in config_dict.keys(): raise ValueError("Saved config was malformed.") # Run through the values to check everything is of correct type. for key in config_dict.keys(): [float(s) for s in config_dict[key]] return config_dict except (config.Error, ValueError) as e: print_e(str(e)) return {"Current": []} class Equalizer(EventPlugin): PLUGIN_ID = "Equalizer" PLUGIN_NAME = _("Equalizer") PLUGIN_DESC = _("Controls the tone of your music with an equalizer.\n" "Click or use keys to customise levels " "(right-click resets the band).") PLUGIN_ICON = Icons.AUDIO_CARD @property def player_has_eq(self): return hasattr(app.player, 'eq_bands') and app.player.eq_bands def __init__(self): super().__init__() self._enabled = False self._config = {} def apply(self): if not self.player_has_eq: return levels = self._enabled and get_config()["Current"] or [] lbands = len(app.player.eq_bands) if len(levels) != lbands: print_w("Number of bands didn't match current. Using flat EQ.") levels = [0.] * lbands app.player.eq_values = levels def enabled(self): self._enabled = True self.apply() def disabled(self): self._enabled = False self.apply() def PluginPreferences(self, win): main_vbox = Gtk.VBox(spacing=12) if not self.player_has_eq: l = Gtk.Label() l.set_markup( _('The current backend does not support equalization.')) main_vbox.pack_start(l, False, True, 0) return main_vbox def format_hertz(band): if band >= 1000: return _('%.1f kHz') % (band / 1000.) return _('%d Hz') % band bands = [format_hertz(band) for band in app.player.eq_bands] self._config = get_config() levels = self._config["Current"] # This fixes possible old corrupt config files with extra level values. if len(levels) != len(bands): print_w("Number of bands didn't match current. Using flat EQ.") levels = [0.] * len(bands) table = Gtk.Table(rows=len(bands), columns=3) table.set_col_spacings(6) def set_band(adj, idx): rounded = int(adj.get_value() * 2) / 2.0 adj.set_value(rounded) levels[idx] = rounded self._config["Current"] = levels config.set('plugins', 'equalizer_levels', str(self._config)) self.apply() adjustments = [] for i, band in enumerate(bands): # align numbers and suffixes in separate rows for great justice lbl = Gtk.Label(label=band.split()[0]) lbl.set_alignment(1, 0.5) lbl.set_padding(0, 4) table.attach(lbl, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) lbl = Gtk.Label(label=band.split()[1]) lbl.set_alignment(1, 0.5) table.attach(lbl, 1, 2, i, i + 1, xoptions=Gtk.AttachOptions.FILL) adj = Gtk.Adjustment.new(levels[i], -24., 12., 0.5, 3, 0) adj.connect('value-changed', set_band, i) adjustments.append(adj) hs = Gtk.HScale(adjustment=adj) hs.connect('button-press-event', self.__rightclick) hs.set_draw_value(True) hs.set_value_pos(Gtk.PositionType.RIGHT) hs.connect('format-value', lambda s, v: _('%.1f dB') % v) table.attach(hs, 2, 3, i, i + 1) main_vbox.pack_start(table, True, True, 0) # Reset EQ button def clicked_rb(button): [adj.set_value(0) for adj in adjustments] self._combo_default.set_active(0) self._combo_custom.set_active(0) # Delete custom preset button def clicked_db(button): selected_index = self._combo_custom.get_active() if selected_index < 1: return # Select… selected = self._combo_custom.get_active_text() self._combo_custom.set_active(0) self._combo_custom.remove(selected_index) del self._config[selected] config.set('plugins', 'equalizer_levels', str(self._config)) # Save custom preset button def clicked_sb(button): name = self._preset_name_entry.get_text() is_new = not name in self._config.keys() levels = [adj.get_value() for adj in adjustments] self._config[name] = levels config.set('plugins', 'equalizer_levels', str(self._config)) self._preset_name_entry.set_text("") if is_new: self._combo_custom.append_text(name) def find_iter(list_store, text): i = list_store.get_iter_first() while (i is not None): if list_store.get_value(i, 0) == text: return i i = list_store.iter_next(i) return None itr = find_iter(self._combo_custom.get_model(), name) self._combo_custom.set_active_iter(itr) sorted_presets = sorted(PRESETS.items()) def default_combo_changed(combo): if combo.get_active() < 1: return # Select… self._combo_custom.set_active(0) gain = sorted_presets[combo.get_active() - 1][1][1] gain = interp_bands(PRESET_BANDS, app.player.eq_bands, gain) for (g, a) in zip(gain, adjustments): a.set_value(g) def custom_combo_changed(combo): if combo.get_active() < 1: # Case: Select… self._delete_button.set_sensitive(False) return self._combo_default.set_active(0) self._delete_button.set_sensitive(True) gain = self._config[combo.get_active_text()] for (g, a) in zip(gain, adjustments): a.set_value(g) def save_name_changed(entry): name = entry.get_text() if not name or name == "Current" or name.isspace(): self._save_button.set_sensitive(False) else: self._save_button.set_sensitive(True) frame = Gtk.Frame(label=_("Default presets"), label_xalign=0.5) main_middle_hbox = Gtk.HBox(spacing=6) # Default presets combo = Gtk.ComboBoxText() self._combo_default = combo combo.append_text(_("Select…")) combo.set_active(0) for key, (name, gain) in sorted_presets: combo.append_text(name) combo.connect("changed", default_combo_changed) # This block is just for padding. padboxv = Gtk.VBox() padboxv.pack_start(combo, True, True, 6) padboxh = Gtk.HBox() padboxh.pack_start(padboxv, True, True, 6) frame.add(padboxh) main_middle_hbox.pack_start(frame, True, True, 0) reset = Button(_("_Reset EQ"), Icons.EDIT_UNDO) reset.connect('clicked', clicked_rb) main_middle_hbox.pack_start(reset, False, False, 0) main_vbox.pack_start(main_middle_hbox, False, False, 0) frame = Gtk.Frame(label=_("Custom presets"), label_xalign=0.5) main_bottom_vbox = Gtk.VBox() # Custom presets combo = Gtk.ComboBoxText() self._combo_custom = combo combo.append_text(_("Select…")) combo.set_active(0) custom_presets = self._config.keys() - {"Current"} for key in custom_presets: combo.append_text(key) combo.connect("changed", custom_combo_changed) hb = Gtk.HBox(spacing=6) hb.pack_start(combo, True, True, 0) delete = Button(_("_Delete selected"), Icons.EDIT_DELETE) delete.connect('clicked', clicked_db) delete.set_sensitive(False) self._delete_button = delete hb.pack_start(delete, False, False, 0) main_bottom_vbox.pack_start(hb, True, True, 6) hs = Gtk.HSeparator() main_bottom_vbox.pack_start(hs, True, True, 6) hb = Gtk.HBox() l = Gtk.Label(label=_("Preset name for saving:")) hb.pack_start(l, False, False, 0) main_bottom_vbox.pack_start(hb, False, False, 0) e = Gtk.Entry() e.connect("changed", save_name_changed) self._preset_name_entry = e hb = Gtk.HBox(spacing=6) hb.pack_start(e, True, True, 0) save = Button(_("_Save"), Icons.DOCUMENT_SAVE) save.connect('clicked', clicked_sb) save.set_sensitive(False) self._save_button = save hb.pack_start(save, False, False, 0) main_bottom_vbox.pack_start(hb, True, True, 6) # This block is just for padding. padboxh = Gtk.HBox() padboxh.pack_start(main_bottom_vbox, True, True, 6) frame.add(padboxh) main_vbox.pack_start(frame, True, True, 0) return main_vbox def __rightclick(self, hs, event): if event.button == Gdk.BUTTON_SECONDARY: hs.set_value(0) ���������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/gajim_status.py������������������������������������������������0000644�0001750�0001750�00000015533�14267565021�021362� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2006 Sergey Fedoseev <fedoseev.sergey@gmail.com> # Copyright 2007 Simon Morgan <zen84964@zen.co.uk> # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import GLib from gi.repository import Gio from gi.repository import Gtk from quodlibet import _ from quodlibet.plugins.events import EventPlugin from quodlibet.pattern import Pattern from quodlibet.qltk import Frame, Icons from quodlibet import config # Translators: statuses relating to Instant Messenger apps _STATUSES = {'online': _('online'), 'offline': _('offline'), 'chat': _('chat'), 'away': _('away'), 'xa': _('xa'), 'invisible': _('invisible')} class GajimStatusMessage(EventPlugin): PLUGIN_ID = 'Gajim status message' PLUGIN_NAME = _('Gajim Status Message') PLUGIN_DESC = _("Changes Gajim status message according to what " "you are currently listening to.") PLUGIN_ICON = Icons.FACE_SMILE c_accounts = __name__ + '_accounts' c_paused = __name__ + '_paused' c_statuses = __name__ + '_statuses' c_pattern = __name__ + '_pattern' def __init__(self): try: self.accounts = config.get('plugins', self.c_accounts).split() except: self.accounts = [] config.set('plugins', self.c_accounts, '') try: self.paused = config.getboolean('plugins', self.c_paused) except: self.paused = True config.set('plugins', self.c_paused, 'True') try: self.statuses = config.get('plugins', self.c_statuses).split() except: self.statuses = ['online', 'chat'] config.set('plugins', self.c_statuses, " ".join(self.statuses)) try: self.pattern = config.get('plugins', self.c_pattern) except: self.pattern = '<artist> - <title>' config.set('plugins', self.c_pattern, self.pattern) def enabled(self): self.interface = None self.current = '' def disabled(self): if self.current != '': self.change_status(self.accounts, '') def change_status(self, enabled_accounts, status_message): if not self.interface: try: self.interface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, 'org.gajim.dbus', '/org/gajim/dbus/RemoteObject', 'org.gajim.dbus.RemoteInterface', None) except GLib.Error: self.interface = None if self.interface: try: for account in self.interface.list_accounts(): status = self.interface.get_status('(s)', account) if enabled_accounts != [] and \ account not in enabled_accounts: continue if status in self.statuses: self.interface.change_status('(sss)', status, status_message, account) except GLib.Error: self.interface = None def plugin_on_song_started(self, song): if song: self.current = Pattern(self.pattern) % song else: self.current = '' self.change_status(self.accounts, self.current) def plugin_on_paused(self): if self.paused and self.current != '': self.change_status(self.accounts, "%s [%s]" % (self.current, _("paused"))) def plugin_on_unpaused(self): self.change_status(self.accounts, self.current) def accounts_changed(self, entry): self.accounts = entry.get_text().split() config.set('plugins', self.c_accounts, entry.get_text()) def pattern_changed(self, entry): self.pattern = entry.get_text() config.set('plugins', self.c_pattern, self.pattern) def paused_changed(self, c): config.set('plugins', self.c_paused, str(c.get_active())) def statuses_changed(self, b): if b.get_active() and b.get_name() not in self.statuses: self.statuses.append(b.get_name()) elif b.get_active() is False and b.get_name() in self.statuses: self.statuses.remove(b.get_name()) config.set('plugins', self.c_statuses, " ".join(self.statuses)) def PluginPreferences(self, parent): vb = Gtk.VBox(spacing=6) pattern_box = Gtk.HBox(spacing=6) pattern_box.set_border_width(3) pattern = Gtk.Entry() pattern.set_text(self.pattern) pattern.connect('changed', self.pattern_changed) pattern_box.pack_start(Gtk.Label(label=_("Pattern:")), False, True, 0) pattern_box.pack_start(pattern, True, True, 0) accounts_box = Gtk.HBox(spacing=3) accounts_box.set_border_width(3) accounts = Gtk.Entry() accounts.set_text(" ".join(self.accounts)) accounts.connect('changed', self.accounts_changed) accounts.set_tooltip_text( _("List accounts, separated by spaces, for " "changing status message. If none are specified, " "status message of all accounts will be changed.")) accounts_box.pack_start(Gtk.Label(label=_("Accounts:")), False, True, 0) accounts_box.pack_start(accounts, True, True, 0) c = Gtk.CheckButton(label=_("Add '[paused]'")) c.set_active(self.paused) c.connect('toggled', self.paused_changed) c.set_tooltip_text(_("If checked, '[paused]' will be added to " "status message on pause")) table = Gtk.Table() self.list = [] i = 0 j = 0 for status, translated in _STATUSES.items(): button = Gtk.CheckButton(label=translated) button.set_name(status) if status in self.statuses: button.set_active(True) button.connect('toggled', self.statuses_changed) self.list.append(button) table.attach(button, i, i + 1, j, j + 1) if i == 2: i = 0 j += 1 else: i += 1 vb.pack_start(pattern_box, True, True, 0) vb.pack_start(accounts_box, True, True, 0) vb.pack_start(c, True, True, 0) frame = Frame(label=_("Statuses for which message will be changed"), child=table) vb.pack_start(frame, True, True, 6) return vb ���������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/headphonemon.py������������������������������������������������0000664�0001750�0001750�00000013033�14035600052�021313� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys from quodlibet.qltk import Icons if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError import fcntl import subprocess from gi.repository import GLib, GObject from quodlibet import _ from quodlibet.plugins.events import EventPlugin from quodlibet.util import print_d from quodlibet import app def get_headphone_status(): """Returns if headphones are connected.""" # No idea if this is a good way... but works here :) try: data = subprocess.check_output(["pactl", "list", "sinks"]) except OSError: return False for line in data.splitlines(): if line.strip() == b"Active Port: analog-output-headphones": return True else: return False class HeadphoneAction: DISCONNECTED = 0 CONNECTED = 1 class HeadphoneMonitor(GObject.Object): """Monitors the headphone connection state advertised by pulseaudio. After start() is called will emit a signal in case headphones get connected or disconnected. If pulseaudio isn't active this will work but always return a disconnected status. The changed signal will never be emitted with the same status multiple times. """ __gsignals__ = { 'action': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self): super().__init__() self._subscribe_id = None self._process = None self._status = None def is_connected(self): """Returns whether headphones are currently connected""" if self._status is None: raise Exception("call start() first") return self._status def _emit(self): self.emit("action", HeadphoneAction.CONNECTED if self._status else HeadphoneAction.DISCONNECTED) def _update_status(self): assert self._status is not None new_status = get_headphone_status() if new_status != self._status: self._status = new_status self._emit() return def start(self): """Start the monitoring process. Once this gets called the "changed" signal will be emitted. """ NULL = open(os.devnull, 'wb') try: self._process = subprocess.Popen( ["pactl", "subscribe"], stdout=subprocess.PIPE, stderr=NULL) except OSError: self._status = False return f = self._process.stdout fcntl.fcntl(f, fcntl.F_SETFL, os.O_NONBLOCK) def can_read_cb(fd, flags): if flags & (GLib.IOCondition.HUP | GLib.IOCondition.ERR): f.close() self._subscribe_id = None return False data = f.read() if not data: f.close() self._subscribe_id = None return False # querying the status also results in client events which would # lead us into an endless loop. Instead just something if there # is a sink event if b" on sink " in data: self._update_status() return True self._status = get_headphone_status() self._subscribe_id = GLib.io_add_watch( f, GLib.PRIORITY_HIGH, GLib.IOCondition.IN | GLib.IOCondition.ERR | GLib.IOCondition.HUP, can_read_cb) def stop(self): """Stop the monitoring process. After this returns no signal will be emitted. Can be called multiple times. start() can be called to start monitoring again after this returns. """ if self._subscribe_id is not None: GLib.source_remove(self._subscribe_id) self._subscribe_id = None if self._process is not None: self._process.terminate() self._process.wait() self._process = None self._status = None class HeadphoneMonitorPlugin(EventPlugin): PLUGIN_ID = "HeadphoneMonitor" PLUGIN_NAME = _("Pause on Headphone Unplug") PLUGIN_DESC = _("Pauses in case headphones get unplugged and unpauses in " "case they get plugged in again.") PLUGIN_ICON = Icons.MEDIA_PLAYBACK_PAUSE def enabled(self): self._was_paused = False self._do_act = False self._mon = HeadphoneMonitor() self._mon.connect("action", self._changed) self._mon.start() def _changed(self, mon, action): if action == HeadphoneAction.DISCONNECTED: print_d("Headphones disconnected") if self._do_act: do_act = self._do_act self._was_paused = app.player.paused app.player.paused = True self._do_act = do_act elif action == HeadphoneAction.CONNECTED: print_d("Headphones connected") if self._do_act: do_act = self._do_act app.player.paused = self._was_paused self._do_act = do_act def disabled(self): self._mon.stop() del self._mon def plugin_on_paused(self): self._do_act = False def plugin_on_unpaused(self): self._do_act = self._mon.is_connected() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/inhibit.py�����������������������������������������������������0000644�0001750�0001750�00000010172�14267565021�020310� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011 Christoph Reiter <reiter.christoph@gmail.com> # Copyright 2020 Antigone <mail@antigone.xyz> # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import Gio from gi.repository import GLib from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet.qltk import Icons from quodlibet.plugins.events import EventPlugin def get_toplevel_xid(): if app.window.get_window(): try: return app.window.get_window().get_xid() except AttributeError: # non x11 pass return 0 class InhibitFlags: LOGOUT = 1 USERSWITCH = 1 << 1 SUSPEND = 1 << 2 IDLE = 1 << 3 class InhibitStrings: SUSPEND = "inhibit_suspend" IDLE = "inhibit_idle" class SessionInhibit(EventPlugin): PLUGIN_ID = "screensaver_inhibit" PLUGIN_NAME = _("Inhibit Screensaver/Suspend") PLUGIN_DESC = _("On a GNOME desktop, when a song is playing, prevents" " either the screensaver from activating, or prevents the" " computer from suspending.") PLUGIN_ICON = Icons.PREFERENCES_DESKTOP_SCREENSAVER CONFIG_MODE = PLUGIN_ID + "_mode" DBUS_NAME = "org.gnome.SessionManager" DBUS_INTERFACE = "org.gnome.SessionManager" DBUS_PATH = "/org/gnome/SessionManager" APPLICATION_ID = "quodlibet" INHIBIT_REASON = _("Music is playing") __cookie = None def __get_dbus_proxy(self): bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) return Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH, self.DBUS_INTERFACE, None) def enabled(self): if not app.player.paused: self.plugin_on_unpaused() def disabled(self): if not app.player.paused: self.plugin_on_paused() def plugin_on_unpaused(self): xid = get_toplevel_xid() mode = config.get("plugins", self.CONFIG_MODE, InhibitStrings.IDLE) flags = InhibitFlags.SUSPEND if mode == InhibitStrings.SUSPEND \ else InhibitFlags.IDLE try: dbus_proxy = self.__get_dbus_proxy() self.__cookie = dbus_proxy.Inhibit('(susu)', self.APPLICATION_ID, xid, self.INHIBIT_REASON, flags) except GLib.Error: pass def plugin_on_paused(self): if self.__cookie is None: return try: dbus_proxy = self.__get_dbus_proxy() dbus_proxy.Uninhibit('(u)', self.__cookie) self.__cookie = None except GLib.Error: pass def PluginPreferences(self, parent): def changed(combo): index = combo.get_active() mode = InhibitStrings.SUSPEND if index == 1 \ else InhibitStrings.IDLE config.set("plugins", self.CONFIG_MODE, mode) if not app.player.paused: self.plugin_on_paused() self.plugin_on_unpaused() mode = config.get("plugins", self.CONFIG_MODE, InhibitStrings.IDLE) hb = Gtk.HBox(spacing=6) hb.set_border_width(6) # Translators: Inhibiting Mode hb.pack_start(Gtk.Label(label=_("Mode:")), False, True, 0) combo = Gtk.ComboBoxText() combo.append_text(_("Inhibit Screensaver")) combo.append_text(_("Inhibit Suspend")) combo.set_active(1 if mode == InhibitStrings.SUSPEND else 0) combo.connect('changed', changed) hb.pack_start(combo, True, True, 0) return hb ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/iradiolog.py���������������������������������������������������0000664�0001750�0001750�00000002424�14231604332�020624� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons class IRadioLog(EventPlugin): PLUGIN_ID = "Internet Radio Log" PLUGIN_NAME = _("Internet Radio Log") PLUGIN_DESC = _("Records the last 10 songs played on radio stations, " "and lists them in the seek context menu.") PLUGIN_ICON = Icons.EDIT def plugin_on_song_started(self, song): if song is None: return player = app.player if player.song and player.song.multisong and not song.multisong: time = player.get_position() title = song("title") bookmarks = player.song.bookmarks bookmarks.append([time // 1000, title]) try: bookmarks.pop(-10) except IndexError: pass player.song.bookmarks = bookmarks elif song.multisong: song.bookmarks = [] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1672734865.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/jep118.py������������������������������������������������������0000644�0001750�0001750�00000003233�14354764221�017672� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. import os import io import quodlibet from quodlibet import _ from quodlibet import util from quodlibet.qltk import Icons from quodlibet.plugins.events import EventPlugin outfile = os.path.join(quodlibet.get_user_dir(), "jabber") format = """\ <tune xmlns='http://jabber.org/protocol/tune'> <artist>%s</artist> <title>%s %s %d %d """ class JEP118(EventPlugin): PLUGIN_ID = "JEP-118" PLUGIN_NAME = _("JEP-118") PLUGIN_DESC_MARKUP = ( _("Outputs a Jabber User Tunes file to %(path)s.") % {"path": util.monospace("~/.quodlibet/jabber")} ) PLUGIN_ICON = Icons.DOCUMENT_SAVE def plugin_on_song_started(self, song): if song is None: try: with io.open(outfile, "w", encoding="utf-8") as f: f.write("") except EnvironmentError: pass else: try: with io.open(outfile, "w", encoding="utf-8") as f: f.write(format % ( util.escape(song.comma("artist")), util.escape(song.comma("title")), util.escape(song.comma("album")), song("~#track", 0), song.get("~#length", 0))) except EnvironmentError: pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/ext/events/language.py0000664000175000017500000000512314035600052020432 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango from quodlibet import _ from quodlibet import config from quodlibet.qltk import Icons from quodlibet.util.i18n import get_available_languages from quodlibet.util import iso639, escape from quodlibet.plugins.events import EventPlugin from quodlibet.qltk.models import ObjectStore class LanguagePreference(EventPlugin): PLUGIN_ID = "Change Language" PLUGIN_NAME = _("Change Language") PLUGIN_DESC = _("Change the user interface language.") PLUGIN_CAN_ENABLE = False PLUGIN_ICON = Icons.PREFERENCES_SYSTEM def PluginPreferences(self, *args): current = config.gettext("settings", "language") if not current: current = None combo = Gtk.ComboBox() model = ObjectStore() combo.set_model(model) for lang_id in ([None] + sorted(get_available_languages("quodlibet"))): iter_ = model.append(row=[lang_id]) if lang_id == current: combo.set_active_iter(iter_) def cell_func(combo, render, model, iter_, *args): value = model.get_value(iter_) if value is None: text = escape(_("System Default")) else: if value == u"C": value = u"en" text = "%s (%s)" % ( escape(value), escape(iso639.translate(value.split("_", 1)[0]))) render.set_property("markup", text) render = Gtk.CellRendererText() render.props.ellipsize = Pango.EllipsizeMode.END combo.pack_start(render, True) combo.set_cell_data_func(render, cell_func) def on_combo_changed(combo): new_language = model.get_value(combo.get_active_iter()) if new_language is None: new_language = u"" config.settext("settings", "language", new_language) combo.connect("changed", on_combo_changed) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) box.pack_start(combo, False, False, 0) box.pack_start( Gtk.Label( label=_( "A restart is required for any changes to take effect"), wrap=True, xalign=0), False, False, 0) return box ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.984269 quodlibet-4.6.0/quodlibet/ext/events/listenbrainz/0000755000175000017500000000000014471213412021002 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/ext/events/listenbrainz/__init__.py0000644000175000017500000005121014327505043023116 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2018 Ian Campbell # # 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 2 of the License, or # (at your option) any later version. # # Derived from the QLScrobbler plugin: # # QLScrobbler: an Audioscrobbler client plugin for Quod Libet. # version 0.11 # (C) 2005-2016 by Joshua Kwan , # Joe Wreschnig , # Franz Pletyz , # Nicholas J. Michalek , # Steven Robertson # Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import List, Tuple import os import threading import time from gi.repository import Gtk, GLib import quodlibet from quodlibet import _ from quodlibet import app, qltk from quodlibet.pattern import Pattern from quodlibet.query import Query from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfig from quodlibet.qltk.entry import ValidatingEntry, UndoEntry from quodlibet.qltk.msg import Message from quodlibet.qltk import Icons from quodlibet.util.dprint import print_d from quodlibet.util.picklehelper import pickle_load, pickle_dump, PickleError import csv from io import StringIO from . import listenbrainz DEFAULT_TITLEPAT = '<version| (<version>)>' DEFAULT_ARTISTPAT = '<artist|<artist>|<composer|<composer>|<performer>>>' plugin_config = PluginConfig("listenbrainz") defaults = plugin_config.defaults #defaults.set("endpoint", "https://api.listenbrainz.org") defaults.set("user_token", "") defaults.set("titlepat", "") defaults.set("artistpat", "") defaults.set("exclude", "") defaults.set("offline", False) defaults.set("tags", "") def config_get_title_pattern(): return plugin_config.get('titlepat') or DEFAULT_TITLEPAT def config_get_artist_pattern(): return plugin_config.get('artistpat') or DEFAULT_ARTISTPAT def config_get_tags(): tags = plugin_config.get('tags') or None if tags is None: return [] parser = csv.reader(StringIO(tags), quoting=csv.QUOTE_ALL, skipinitialspace=True) try: return next(parser) except Exception as e: print_d("Failed to parse tags \"%s\": %s" % tags, e) return [] class ListenBrainzSubmitQueue(): """Manages the submit queue for listens. Works independently of the plugin being enabled; other plugins may use submit() to queue songs for submission. """ DUMP = os.path.join(quodlibet.get_user_dir(), "listenbrainz_cache") # These objects are shared across instances, to allow other plugins to # queue listens in future versions of QL. queue: List[Tuple[int, listenbrainz.Track]] = [] condition = threading.Condition() def set_nowplaying(self, song): """Send a Now Playing notification.""" track = self._track(song) if not track or self.nowplaying_track == track: return print_d("Set now playing: %s" % track) self.condition.acquire() self.nowplaying_track = track self.nowplaying_sent = False self.changed() self.condition.release() def submit(self, song, timestamp=0): """Submit a song. If 'timestamp' is 0, the current time will be used.""" track = self._track(song) if track is None: return self.condition.acquire() if timestamp == 0: timestamp = int(time.time()) print_d("Queueing: %s" % track) self.queue.append((timestamp, track)) self.changed() self.condition.release() def _track(self, song): """Returns a listenbrainz.Track.""" artist = self.artpat.format(song) title = self.titlepat.format(song) if artist is None or title is None: return None album = song.comma("album") # https://listenbrainz.readthedocs.io/en/latest/dev/json.html#payload-json-details # # artist_mbids A list of MusicBrainz Artist IDs, one or more Artist # IDs may be included here. If you have a complete # MusicBrainz artist credit that contains multiple # Artist IDs, include them all in this list. # release_group_mbid A MusicBrainz Release Group ID of the release group this # recording was played from. # release_mbid A MusicBrainz Release ID of the release this recording # was played from. # recording_mbid A MusicBrainz Recording ID of the recording that was # played. # track_mbid A MusicBrainz Track ID associated with the recording # that was played. # work_mbids A list of MusicBrainz Work IDs that may be associated # with this recording. # tracknumber The tracknumber of the recording. This first recording # on a release is tracknumber 1. # isrc The ISRC code associated with the recording. # spotify_id The Spotify track URL associated with this recording. # tags A list of user defined tags to be associated with this # recording. These tags are similar to last.fm tags. For # example, you have apply tags such as punk, see-live, # smelly. You may submit up to MAX_TAGS_PER_LISTEN tags # and each tag may be up to MAX_TAG_SIZE characters large. # # https://picard.musicbrainz.org/docs/mappings/ # Above Tag # artists_mbids MUSICBRAINZ_ARTISTID (multiple) # release_group_mbid MUSICBRAINZ_RELEASEGROUPID # release_mbid MUSICBRAINZ_ALBUMID # recording_mbid MUSICBRAINZ_TRACKID # track_mbid MUSICBRAINZ_RELEASETRACKID # work_mbids MUSICBRAINZ_WORKID (multiple) # tracknumber TRACKNUMBER # isrc ISRC # spotify_id N/A # tags N/A additional_info = {} for (k, v) in [ ('artist_mbids', song.list("musicbrainz_artistid")), ('release_group_mbid', song.get("musicbrainz_releasegroupid", None)), ('release_mbid', song.get("musicbrainz_albumid", None)), ('recording_mbid', song.get("musicbrainz_trackid", None)), ('track_mbid', song.get("musicbrainz_releasetrackid", None)), ('work_mbids', song.list("musicbrainz_workid")), ('tracknumber', song.get("tracknumber", None)), ('isrc', song.get("isrc", None)), ('tags', self.tags)]: if v is not None and v != []: additional_info[k] = v print_d("Track(%s,%s,%s,%s)" % (artist, title, album, additional_info)) return listenbrainz.Track(artist, title, album, additional_info) def __init__(self): print("logging") self.nowplaying_track = None self.nowplaying_sent = False self.broken = False self.offline = False self.retries = 0 self.lb = listenbrainz.ListenBrainzClient() # XXX logger=xxx # These need to be set early for _format_song to work self.titlepat = Pattern(config_get_title_pattern()) self.artpat = Pattern(config_get_artist_pattern()) self.tags = config_get_tags() try: with open(self.DUMP, 'rb') as disk_queue_file: disk_queue = pickle_load(disk_queue_file) os.unlink(self.DUMP) self.queue += disk_queue except (EnvironmentError, PickleError): pass @classmethod def dump_queue(klass): if klass.queue: try: with open(klass.DUMP, 'wb') as disk_queue_file: pickle_dump(klass.queue, disk_queue_file) except (EnvironmentError, PickleError): pass # Must be called with self.condition acquired def _check_config(self): #endpoint = plugin_config.get('endpoint') user_token = plugin_config.get('user_token') #if not endpoint or not user_token: if not user_token: if self.queue and not self.broken: self.quick_dialog(_("Please visit the Plugins window to set " "ListenBrainz up. Until then, listens will not be " "submitted."), Gtk.MessageType.INFO) self.broken = True #elif (self.lb.host_name, self.lb.user_token) != (endpoint, user_token): elif self.lb.user_token != user_token: #print_d("Setting %s, %s" % (endpoint, user_token)) #self.lb.host_name, self.lb.user_token = (endpoint, user_token) print_d("Setting user_token %s" % user_token) self.lb.user_token = user_token self.broken = False self.offline = plugin_config.getboolean('offline') self.titlepat = Pattern(config_get_title_pattern()) self.artpat = Pattern(config_get_artist_pattern()) self.tags = config_get_tags() # Must be called with self.condition acquired def changed(self): """Signal that settings or queue contents were changed.""" self._check_config() if not self.broken and not self.offline and (self.queue or (self.nowplaying_track and not self.nowplaying_sent)): self.condition.notify() def run(self): """Submit songs from the queue. Call from a daemon thread.""" print_d("Submission queue thread running") while True: print_d("Top of queue loop") self.condition.acquire() while self.broken or \ self.offline or \ (not self.queue and (not self.nowplaying_track or self.nowplaying_sent)): print_d("Nothing to do, waiting") self.condition.wait() print_d("Awoke") print_d("Running iteration") # Poll inputs under the lock submit = None if self.queue: submit = self.queue[0] nowplaying = None if self.nowplaying_track and not self.nowplaying_sent: nowplaying = self.nowplaying_track self.condition.release() # Call f() and handle errors with backoff and disable def with_backoff(f): try: rsp = f() except Exception as e: rsp = None print_d("Error: %s" % e) if rsp and rsp.status == 200: self.retries = 0 return True elif self.retries >= 6: # Too many retries, put self offline print_d("Too many retries, setting to offline") self.offline = True plugin_config.set("offline", True) self.quick_dialog(_( "Too many consecutive submission failures (%d). " "Setting to offline mode. " "Please visit the Plugins window to reset " "ListenBrainz. Until then, listens will not be " "submitted." % self.retries), Gtk.MessageType.INFO) return False else: delay = 10 print_d("Failure, waiting %ds" % delay) self.retries += 1 time.sleep(delay) print_d("Done sleeping") return False return True if submit: (listened_at, track) = submit print_d("Submitting: %s" % track) if not with_backoff(lambda: self.lb.listen(listened_at, track)): continue print_d("Submission successful") # Remove submitted entry under lock self.condition.acquire() if self.queue[0] == submit: self.queue.pop(0) self.condition.release() if nowplaying: print_d("Now playing: %s" % nowplaying) if not with_backoff(lambda: self.lb.playing_now(nowplaying)): continue print_d("Now playing submission successful") self.condition.acquire() if nowplaying == self.nowplaying_track: # only if it didn't change under our feet self.nowplaying_sent = True self.condition.release() def quick_dialog_helper(self, dialog_type, msg): dialog = Message(dialog_type, app.window, "ListenBrainz", msg) dialog.connect('response', lambda dia, resp: dia.destroy()) dialog.show() def quick_dialog(self, msg, dialog_type): GLib.idle_add(self.quick_dialog_helper, dialog_type, msg) class ListenbrainzSubmission(EventPlugin): PLUGIN_ID = "listenbrainz" PLUGIN_NAME = _("ListenBrainz Submission") PLUGIN_DESC = _("Submit listens to ListenBrainz.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP def __init__(self): self.__enabled = False self.queue = ListenBrainzSubmitQueue() queue_thread = threading.Thread(None, self.queue.run) queue_thread.setDaemon(True) queue_thread.start() self.start_time = 0 self.unpaused_time = 0 self.elapsed = 0 self.nowplaying = None self.exclude = plugin_config.get('exclude') def plugin_on_song_ended(self, song, stopped): if song is None or not self.__enabled: return if self.unpaused_time > 0: self.elapsed += time.time() - self.unpaused_time # https://listenbrainz.readthedocs.io/en/latest/dev/api.html # # Listens should be submitted for tracks when the user has # listened to half the track or 4 minutes of the track, # whichever is lower. If the user hasn’t listened to 4 minutes # or half the track, it doesn’t fully count as a listen and # should not be submitted. # # we check 'elapsed' rather than 'length' to work around wrong ~#length if self.elapsed < (4 * 60) and self.elapsed <= .5 * song.get("~#length", 0): return print_d("Checking against filter %s" % self.exclude) if self.exclude and Query(self.exclude).search(song): print_d("Not submitting: %s" % song("~artist~title")) return self.queue.submit(song, self.start_time) def song_excluded(self, song): if self.exclude and Query(self.exclude).search(song): print_d("%s is excluded by %s" % (song("~artist~title"), self.exclude)) return True return False def send_nowplaying(self, song): if not self.song_excluded(song): self.queue.set_nowplaying(song) def plugin_on_song_started(self, song): if song is None: return self.start_time = int(time.time()) if app.player.paused: self.unpaused_time = 0 else: self.unpaused_time = time.time() self.elapsed = 0 if self.__enabled and not app.player.paused: self.send_nowplaying(song) else: self.nowplaying = song def plugin_on_paused(self): if self.unpaused_time > 0: self.elapsed += time.time() - self.unpaused_time self.unpaused_time = 0 def plugin_on_unpaused(self): self.unpaused_time = time.time() if self.__enabled and self.nowplaying: self.send_nowplaying(self.nowplaying) self.nowplaying = None def enabled(self): self.__enabled = True print_d("Plugin enabled - accepting new songs.") def disabled(self): self.__enabled = False print_d("Plugin disabled - not accepting any new songs.") #ListenBrainzSubmitQueue.dump_queue() def PluginPreferences(self, parent): def changed(entry, key): if entry.get_property('sensitive'): plugin_config.set(key, entry.get_text()) box = Gtk.VBox(spacing=12) # first frame table = Gtk.Table(n_rows=2, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = [] label_names = [_("User _token:")] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # endpoint url / hostname #entry = UndoEntry() #entry.set_text(plugin_config.get('endpoint')) #entry.connect('changed', changed, 'endpoint') #table.attach(entry, 1, 2, row, row + 1) #labels[row].set_mnemonic_widget(entry) #row += 1 # token entry = UndoEntry() entry.set_text(plugin_config.get('user_token')) entry.connect('changed', changed, 'user_token') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # verify data #button = qltk.Button(_("_Verify account data"), # Icons.DIALOG_INFORMATION) #button.connect('clicked', check_login) #table.attach(button, 0, 2, 4, 5) box.pack_start(qltk.Frame(_("Account"), child=table), True, True, 0) # second frame table = Gtk.Table(n_rows=5, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) label_names = [_("_Artist pattern:"), _("_Title pattern:"), _("T_ags:"), _("Exclude _filter:")] labels = [] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # artist pattern entry = UndoEntry() entry.set_text(plugin_config.get('artistpat')) entry.connect('changed', changed, 'artistpat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the artist name for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # title pattern entry = UndoEntry() entry.set_text(plugin_config.get('titlepat')) entry.connect('changed', changed, 'titlepat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the title for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # tags entry = UndoEntry() entry.set_text(plugin_config.get('tags')) entry.connect('changed', changed, 'tags') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("List of tags to include in the submission. " "Comma-separated, use double-quotes if necessary.")) labels[row].set_mnemonic_widget(entry) row += 1 # exclude filter entry = ValidatingEntry(Query.validator) entry.set_text(plugin_config.get('exclude')) entry.set_tooltip_text( _("Songs matching this filter will not be submitted.")) entry.connect('changed', changed, 'exclude') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # offline mode offline = plugin_config.ConfigCheckButton( _("_Offline mode (don't submit anything)"), 'offline', populate=True) table.attach(offline, 0, 2, row, row + 1) box.pack_start(qltk.Frame(_("Submission"), child=table), True, True, 0) return box ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/listenbrainz/listenbrainz.py�����������������������������������0000644�0001750�0001750�00000014453�14327505043�024073� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2018 Philipp Wolfer <ph.wolfer@gmail.com> # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from typing import Optional import json import logging import os import ssl import time from http.client import HTTPConnection, HTTPSConnection HOST_NAME: Optional[str] = "api.listenbrainz.org" PATH_SUBMIT = "/1/submit-listens" SSL_CONTEXT: Optional[ssl.SSLContext] = ssl.create_default_context() # to run against a local dev server if os.getenv("QL_LISTENBRAINZ_DEV_SERVER") is not None: HOST_NAME = os.getenv("QL_LISTENBRAINZ_DEV_SERVER") SSL_CONTEXT = None class Track: """ Represents a single track to submit. See https://listenbrainz.readthedocs.io/en/latest/dev/json.html """ def __init__(self, artist_name, track_name, release_name=None, additional_info={}): """ Create a new Track instance @param artist_name as str @param track_name as str @param release_name as str @param additional_info as dict """ self.artist_name = artist_name self.track_name = track_name self.release_name = release_name self.additional_info = additional_info @staticmethod def from_dict(data): return Track( data["artist_name"], data["track_name"], data.get("release_name", None), data.get("additional_info", {}) ) def to_dict(self): return { "artist_name": self.artist_name, "track_name": self.track_name, "release_name": self.release_name, "additional_info": self.additional_info } def __repr__(self): return "Track(%s, %s)" % (self.artist_name, self.track_name) class ListenBrainzClient: """ Submit listens to ListenBrainz.org. See https://listenbrainz.readthedocs.io/en/latest/dev/api.html """ def __init__(self, logger=logging.getLogger(__name__)): self.__next_request_time = 0 self.user_token = None self.logger = logger def listen(self, listened_at, track): """ Submit a listen for a track @param listened_at as int @param entry as Track """ payload = _get_payload(track, listened_at) return self._submit("single", [payload]) def playing_now(self, track): """ Submit a playing now notification for a track @param track as Track """ payload = _get_payload(track) return self._submit("playing_now", [payload]) def import_tracks(self, tracks): """ Import a list of tracks as (listened_at, Track) pairs @param track as [(int, Track)] """ payload = _get_payload_many(tracks) return self._submit("import", payload) def _submit(self, listen_type, payload, retry=0): self._wait_for_ratelimit() self.logger.debug("ListenBrainz %s: %r", listen_type, payload) data = { "listen_type": listen_type, "payload": payload } headers = { "Authorization": "Token %s" % self.user_token, "Content-Type": "application/json" } body = json.dumps(data) print("submit: %s" % body) if SSL_CONTEXT is not None: conn = HTTPSConnection(HOST_NAME, context=SSL_CONTEXT) else: conn = HTTPConnection(HOST_NAME) # XXX TODO, catch errors? conn.request("POST", PATH_SUBMIT, body, headers) response = conn.getresponse() response_text = response.read() try: response_data = json.loads(response_text) #Python3 #except json.JSONDecodeError: # response_data = response_text #Python2 except ValueError as e: if str(e) != "No JSON object could be decoded": raise e response_data = response_text self._handle_ratelimit(response) log_msg = "Response %s: %r" % (response.status, response_data) if response.status == 429 and retry < 5: # Too Many Requests self.logger.warning(log_msg) return self._submit(listen_type, payload, retry + 1) elif response.status == 200: self.logger.debug(log_msg) else: self.logger.error(log_msg) return response def _wait_for_ratelimit(self): now = time.time() if self.__next_request_time > now: delay = self.__next_request_time - now self.logger.debug("Rate limit applies, delay %d", delay) time.sleep(delay) def _handle_ratelimit(self, response): remaining = int(response.getheader("X-RateLimit-Remaining", 0)) reset_in = int(response.getheader("X-RateLimit-Reset-In", 0)) self.logger.debug("X-RateLimit-Remaining: %i", remaining) self.logger.debug("X-RateLimit-Reset-In: %i", reset_in) if remaining == 0: self.__next_request_time = time.time() + reset_in def _get_payload_many(tracks): payload = [] for (listened_at, track) in tracks: data = _get_payload(track, listened_at) payload.append(data) return payload def _get_payload(track, listened_at=None): data = { "track_metadata": track.to_dict() } if listened_at is not None: data["listened_at"] = listened_at return data ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mediaserver.py�������������������������������������������������0000664�0001750�0001750�00000056450�14035600052�021166� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2013 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import Gtk, GdkPixbuf from senf import fsn2uri import dbus import dbus.service from quodlibet import _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.pattern import Pattern from quodlibet.qltk import Icons from quodlibet.util.dbusutils import DBusIntrospectable, DBusProperty from quodlibet.util.dbusutils import dbus_unicode_validate as unival from quodlibet.util import NamedTemporaryFile BASE_PATH = "/org/gnome/UPnP/MediaServer2" BUS_NAME = "org.gnome.UPnP.MediaServer2.QuodLibet" class MediaServer(EventPlugin): PLUGIN_ID = "mediaserver" PLUGIN_NAME = _("UPnP AV Media Server") PLUGIN_DESC = _("Exposes all albums to the Rygel UPnP Media Server " "through the MediaServer2 D-Bus interface.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP def PluginPreferences(self, parent): vbox = Gtk.VBox(spacing=12) conf_exp = _("Ensure the following is in your rygel config file " "(~/.config/rygel.conf):") conf_cont = ("[External]\n" "enabled=true\n\n" "[org.gnome.UPnP.MediaServer2.QuodLibet]\n" "enabled=true") exp_lbl = Gtk.Label(label=conf_exp) exp_lbl.set_selectable(True) exp_lbl.set_line_wrap(True) exp_lbl.set_alignment(0, 0) conf_lbl = Gtk.Label() conf_lbl.set_selectable(True) conf_lbl.set_alignment(0, 0) conf_lbl.set_markup("<span font='mono'>{}</span>".format(conf_cont)) vbox.pack_start(exp_lbl, True, False, 0) vbox.pack_start(conf_lbl, True, False, 0) return vbox def enabled(self): try: dbus.SessionBus() except dbus.DBusException: self.objects = [] return entry = EntryObject() albums = AlbumsObject(entry, app.library) song = SongObject(app.library, [albums]) icon = Icon(entry) self.objects = [entry, albums, song, icon] def disabled(self): for obj in self.objects: obj.remove_from_connection() for obj in self.objects: obj.destroy() del self.objects import gc gc.collect() class DBusPropertyFilter(DBusProperty): """Adds some methods to support the MediaContainer property filtering.""" def get_properties_for_filter(self, interface, filter_): props = self.get_properties(interface) if "*" not in filter_: props = [p for p in props if p[1] in filter_] return props def get_values(self, properties, path="/"): result = {} for iface, prop in properties: result[prop] = self.get_value(iface, prop, path) return result class MediaContainer: IFACE = "org.gnome.UPnP.MediaContainer2" ISPEC_PROP = """ <property type="u" name="ChildCount" access="read"/> <property type="u" name="ItemCount" access="read"/> <property type="u" name="ContainerCount" access="read"/> <property type="b" name="Searchable" access="read"/> <property type="o" name="Icon" access="read"/> """ ISPEC = """ <method name="ListChildren"> <arg type="u" name="offset" direction="in"/> <arg type="u" name="max" direction="in"/> <arg type="as" name="filter" direction="in"/> <arg type="aa{sv}" name="arg_3" direction="out"/> </method> <method name="ListContainers"> <arg type="u" name="offset" direction="in"/> <arg type="u" name="max" direction="in"/> <arg type="as" name="filter" direction="in"/> <arg type="aa{sv}" name="arg_3" direction="out"/> </method> <method name="ListItems"> <arg type="u" name="offset" direction="in"/> <arg type="u" name="max" direction="in"/> <arg type="as" name="filter" direction="in"/> <arg type="aa{sv}" name="arg_3" direction="out"/> </method> <method name="SearchObjects"> <arg type="s" name="query" direction="in"/> <arg type="u" name="offset" direction="in"/> <arg type="u" name="max" direction="in"/> <arg type="as" name="filter" direction="in"/> <arg type="aa{sv}" name="arg_4" direction="out"/> </method> <signal name="Updated"/> """ def __init__(self, optional=tuple()): self.set_introspection(MediaContainer.IFACE, MediaContainer.ISPEC) props = ["ChildCount", "ItemCount", "ContainerCount", "Searchable"] props += list(optional) self.set_properties(MediaContainer.IFACE, MediaContainer.ISPEC_PROP, wl=props) self.implement_interface(MediaContainer.IFACE, MediaObject.IFACE) def emit_updated(self, path="/"): self.Updated(rel=path) @dbus.service.method(IFACE, in_signature="uuas", out_signature="aa{sv}", rel_path_keyword="path") def ListChildren(self, offset, max_, filter_, path): if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: return self.list_children(offset, max_, filter_, path) return self.list_children(offset, max_, filter_) @dbus.service.method(IFACE, in_signature="uuas", out_signature="aa{sv}", rel_path_keyword="path") def ListContainers(self, offset, max_, filter_, path): if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: return self.list_containers(offset, max_, filter_, path) return self.list_containers(offset, max_, filter_) @dbus.service.method(IFACE, in_signature="uuas", out_signature="aa{sv}", rel_path_keyword="path") def ListItems(self, offset, max_, filter_, path): if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: return self.list_items(offset, max_, filter_, path) return self.list_items(offset, max_, filter_) @dbus.service.method(IFACE, in_signature="suuas", out_signature="aa{sv}", rel_path_keyword="path") def SearchObjects(self, query, offset, max_, filter_, path): return [] @dbus.service.signal(IFACE, rel_path_keyword="rel") def Updated(self, rel=""): pass class MediaObject: IFACE = "org.gnome.UPnP.MediaObject2" ISPEC = """ <property type="o" name="Parent" access="read"/> <property type="s" name="Type" access="read"/> <property type="o" name="Path" access="read"/> <property type="s" name="DisplayName" access="read"/> """ parent = None def __init__(self, parent=None): self.set_properties(MediaObject.IFACE, MediaObject.ISPEC) self.parent = parent or self class MediaItem: IFACE = "org.gnome.UPnP.MediaItem2" ISPEC = """ <property type="as" name="URLs" access="read"/> <property type="s" name="MIMEType" access="read"/> <property type="x" name="Size" access="read"/> <property type="s" name="Artist" access="read"/> <property type="s" name="Album" access="read"/> <property type="s" name="Date" access="read"/> <property type="s" name="Genre" access="read"/> <property type="s" name="DLNAProfile" access="read"/> <property type="i" name="Duration" access="read"/> <property type="i" name="Bitrate" access="read"/> <property type="i" name="SampleRate" access="read"/> <property type="i" name="BitsPerSample" access="read"/> <property type="i" name="Width" access="read"/> <property type="i" name="Height" access="read"/> <property type="i" name="ColorDepth" access="read"/> <property type="i" name="PixelWidth" access="read"/> <property type="i" name="PixelHeight" access="read"/> <property type="o" name="Thumbnail" access="read"/> <property type="o" name="AlbumArt" access="read"/> <property type="i" name="TrackNumber" access="read"/> """ def __init__(self, optional=tuple()): props = ["URLs", "MIMEType"] + list(optional) self.set_properties(MediaItem.IFACE, MediaItem.ISPEC, wl=props) self.implement_interface(MediaItem.IFACE, MediaObject.IFACE) class EntryObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable, dbus.service.Object): PATH = BASE_PATH + "/QuodLibet" DISPLAY_NAME = "@REALNAME@'s Quod Libet on @HOSTNAME@" def __init__(self): self.__sub = [] DBusIntrospectable.__init__(self) DBusPropertyFilter.__init__(self) MediaObject.__init__(self) MediaContainer.__init__(self, optional=["Icon"]) bus = dbus.SessionBus() name = dbus.service.BusName(BUS_NAME, bus) dbus.service.Object.__init__(self, bus, self.PATH, name) def get_property(self, interface, name): if interface == MediaContainer.IFACE: if name == "ChildCount": return len(self.__sub) elif name == "ItemCount": return 0 elif name == "ContainerCount": return len(self.__sub) elif name == "Searchable": return False elif name == "Icon": return Icon.PATH elif interface == MediaObject.IFACE: if name == "Parent": return self.parent.PATH elif name == "Type": return "container" elif name == "Path": return self.PATH elif name == "DisplayName": return self.DISPLAY_NAME def destroy(self): # break cycle del self.__sub del self.parent def register_child(self, child): self.__sub.append(child) self.emit_properties_changed(MediaContainer.IFACE, ["ChildCount", "ContainerCount"]) def list_containers(self, offset, max_, filter_): props = self.get_properties_for_filter(MediaContainer.IFACE, filter_) end = (max_ and offset + max_) or None result = [] for sub in self.__sub[offset:end]: result.append(sub.get_values(props)) return result list_children = list_containers def list_items(self, offset, max_, filter_): return [] SUPPORTED_SONG_PROPERTIES = ("Size", "Artist", "Album", "Date", "Genre", "Duration", "TrackNumber") class DummySongObject(MediaItem, MediaObject, DBusPropertyFilter, DBusIntrospectable): """ A dummy song object that is not exported on the bus, but supports the usual interfaces. You need to assign a real song before using it, and have to pass a path prefix. The path of the song is /org/gnome/UPnP/MediaServer2/Song/<PREFIX>/SongID This lets us reconstruct the original parent path: /org/gnome/UPnP/MediaServer2/<PREFIX> atm. a prefix can look like "Albums/123456" """ SUPPORTS_MULTIPLE_OBJECT_PATHS = False __pattern = Pattern( "<discnumber|<discnumber>.><tracknumber>. <title>") def __init__(self, parent): DBusIntrospectable.__init__(self) DBusPropertyFilter.__init__(self) MediaObject.__init__(self, parent) MediaItem.__init__(self, optional=SUPPORTED_SONG_PROPERTIES) def set_song(self, song, prefix): self.__song = song self.__prefix = prefix def get_property(self, interface, name): if interface == MediaObject.IFACE: if name == "Parent": return BASE_PATH + "/" + self.__prefix elif name == "Type": return "music" elif name == "Path": path = SongObject.PATH path += "/" + self.__prefix + "/" + str(id(self.__song)) return path elif name == "DisplayName": return unival(self.__song.comma("title")) elif interface == MediaItem.IFACE: if name == "URLs": return [self.__song("~uri")] elif name == "MIMEType": mimes = self.__song.mimes return mimes and mimes[0] elif name == "Size": return self.__song("~#filesize") elif name == "Artist": return unival(self.__song.comma("artist")) elif name == "Album": return unival(self.__song.comma("album")) elif name == "Date": return unival(self.__song.comma("date")) elif name == "Genre": return unival(self.__song.comma("genre")) elif name == "Duration": return self.__song("~#length") elif name == "TrackNumber": return self.__song("~#track", 0) class DummyAlbumObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable): SUPPORTS_MULTIPLE_OBJECT_PATHS = False __pattern = Pattern("<albumartist|<~albumartist~album>|<~artist~album>>") def __init__(self, parent): DBusIntrospectable.__init__(self) DBusPropertyFilter.__init__(self) MediaObject.__init__(self, parent) MediaContainer.__init__(self) self.__song = DummySongObject(self) def get_dummy(self, song): self.__song.set_song(song, "Albums/" + str(id(self.__album))) return self.__song def set_album(self, album): self.__album = album self.PATH = self.parent.PATH + "/" + str(id(album)) def get_property(self, interface, name): if interface == MediaContainer.IFACE: if name == "ChildCount" or name == "ItemCount": return len(self.__album.songs) elif name == "ContainerCount": return 0 elif name == "Searchable": return False elif interface == MediaObject.IFACE: if name == "Parent": return self.parent.PATH elif name == "Type": return "container" elif name == "Path": return self.PATH elif name == "DisplayName": return unival(self.__pattern % self.__album) def list_containers(self, offset, max_, filter_): return [] def list_items(self, offset, max_, filter_): songs = sorted(self.__album.songs, key=lambda s: s.sort_key) dummy = self.get_dummy(None) props = dummy.get_properties_for_filter(MediaItem.IFACE, filter_) end = (max_ and offset + max_) or None result = [] for song in songs[offset:end]: result.append(self.get_dummy(song).get_values(props)) return result list_children = list_items class SongObject(MediaItem, MediaObject, DBusProperty, DBusIntrospectable, dbus.service.FallbackObject): PATH = BASE_PATH + "/Song" def __init__(self, library, users): DBusIntrospectable.__init__(self) DBusProperty.__init__(self) MediaObject.__init__(self, None) MediaItem.__init__(self, optional=SUPPORTED_SONG_PROPERTIES) bus = dbus.SessionBus() self.ref = dbus.service.BusName(BUS_NAME, bus) dbus.service.FallbackObject.__init__(self, bus, self.PATH) self.__library = library self.__map = dict((id(v), v) for v in self.__library.values()) self.__reverse = dict((v, k) for k, v in self.__map.items()) self.__song = DummySongObject(self) self.__users = users signals = [ ("changed", self.__songs_changed), ("removed", self.__songs_removed), ("added", self.__songs_added), ] self.__sigs = map( lambda x: self.__library.connect(x[0], x[1]), signals) def __songs_changed(self, lib, songs): # We don't know what changed, so get all properties props = [p[1] for p in self.get_properties(MediaItem.IFACE)] for song in songs: song_id = str(id(song)) # https://github.com/quodlibet/quodlibet/issues/id=1127 # XXX: Something is emitting wrong changed events.. # ignore song_ids we don't know for now if song_id not in self.__map: continue for user in self.__users: # ask the user for the prefix with which the song is used prefix = user.get_prefix(song) path = "/" + prefix + "/" + song_id self.emit_properties_changed(MediaItem.IFACE, props, path) def __songs_added(self, lib, songs): for song in songs: new_id = id(song) self.__map[new_id] = song self.__reverse[song] = new_id def __songs_removed(self, lib, songs): for song in songs: del self.__map[self.__reverse[song]] del self.__reverse[song] def destroy(self): for signal_id in self.__sigs: self.__library.disconnect(signal_id) def get_dummy(self, song, prefix): self.__song.set_song(song, prefix) return self.__song def get_property(self, interface, name, path): # extract the prefix prefix, song_id = path[1:].rsplit("/", 1) song = self.__map[int(song_id)] return self.get_dummy(song, prefix).get_property(interface, name) class AlbumsObject(MediaContainer, MediaObject, DBusPropertyFilter, DBusIntrospectable, dbus.service.FallbackObject): PATH = BASE_PATH + "/Albums" DISPLAY_NAME = "Albums" def __init__(self, parent, library): DBusIntrospectable.__init__(self) DBusPropertyFilter.__init__(self) MediaObject.__init__(self, parent) MediaContainer.__init__(self) bus = dbus.SessionBus() self.ref = dbus.service.BusName(BUS_NAME, bus) dbus.service.FallbackObject.__init__(self, bus, self.PATH) parent.register_child(self) self.__library = library.albums self.__library.load() self.__map = dict((id(v), v) for v in self.__library.values()) self.__reverse = dict((v, k) for k, v in self.__map.items()) signals = [ ("changed", self.__albums_changed), ("removed", self.__albums_removed), ("added", self.__albums_added), ] self.__sigs = map( lambda x: self.__library.connect(x[0], x[1]), signals) self.__dummy = DummyAlbumObject(self) def get_dummy(self, album): self.__dummy.set_album(album) return self.__dummy def get_path_dummy(self, path): return self.get_dummy(self.__map[int(path[1:])]) def __albums_changed(self, lib, albums): for album in albums: rel_path = "/" + str(id(album)) self.emit_updated(rel_path) self.emit_properties_changed( MediaContainer.IFACE, ["ChildCount", "ItemCount", "DisplayName"], rel_path) def __albums_added(self, lib, albums): for album in albums: new_id = id(album) self.__map[new_id] = album self.__reverse[album] = new_id self.emit_updated() self.emit_properties_changed(MediaContainer.IFACE, ["ChildCount", "ContainerCount"]) def __albums_removed(self, lib, albums): for album in albums: del self.__map[self.__reverse[album]] del self.__reverse[album] self.emit_updated() self.emit_properties_changed(MediaContainer.IFACE, ["ChildCount", "ContainerCount"]) def get_prefix(self, song): album = self.__library[song.album_key] return "Albums/" + str(id(album)) def destroy(self): for signal_id in self.__sigs: self.__library.disconnect(signal_id) def __get_albums_property(self, interface, name): if interface == MediaContainer.IFACE: if name == "ChildCount": return len(self.__library) elif name == "ItemCount": return 0 elif name == "ContainerCount": return len(self.__library) elif name == "Searchable": return False elif interface == MediaObject.IFACE: if name == "Parent": return self.parent.PATH elif name == "Type": return "container" elif name == "Path": return self.PATH elif name == "DisplayName": return self.DISPLAY_NAME def get_property(self, interface, name, path): if path == "/": return self.__get_albums_property(interface, name) return self.get_path_dummy(path).get_property(interface, name) def __list_albums(self, offset, max_, filter_): props = self.get_properties_for_filter(MediaContainer.IFACE, filter_) albums = sorted(self.__library, key=lambda a: a.sort) end = (max_ and offset + max_) or None result = [] for album in albums[offset:end]: result.append(self.get_dummy(album).get_values(props)) return result def list_containers(self, offset, max_, filter_, path): if path == "/": return self.__list_albums(offset, max_, filter_) return [] def list_items(self, offset, max_, filter_, path): if path != "/": return self.get_path_dummy(path).list_items(offset, max_, filter_) return [] def list_children(self, offset, max_, filter_, path): if path == "/": return self.__list_albums(offset, max_, filter_) return self.get_path_dummy(path).list_children(offset, max_, filter_) class Icon(MediaItem, MediaObject, DBusProperty, DBusIntrospectable, dbus.service.Object): PATH = BASE_PATH + "/Icon" SIZE = 160 def __init__(self, parent): DBusIntrospectable.__init__(self) DBusProperty.__init__(self) MediaObject.__init__(self, parent=parent) MediaItem.__init__(self, optional=["Height", "Width", "ColorDepth"]) bus = dbus.SessionBus() name = dbus.service.BusName(BUS_NAME, bus) dbus.service.Object.__init__(self, bus, self.PATH, name) # https://bugzilla.gnome.org/show_bug.cgi?id=669677 self.implement_interface("org.gnome.UPnP.MediaItem1", MediaItem.IFACE) # load into a pixbuf theme = Gtk.IconTheme.get_default() pixbuf = theme.load_icon(Icons.QUODLIBET, Icon.SIZE, 0) # make sure the size is right pixbuf = pixbuf.scale_simple(Icon.SIZE, Icon.SIZE, GdkPixbuf.InterpType.BILINEAR) self.__depth = pixbuf.get_bits_per_sample() # save and keep reference self.__f = f = NamedTemporaryFile() pixbuf.savev(f.name, "png", [], []) def get_property(self, interface, name): if interface == MediaObject.IFACE: if name == "Parent": return EntryObject.PATH elif name == "Type": return "image" elif name == "Path": return Icon.PATH elif name == "DisplayName": return r"I'm an icon \o/" elif interface == MediaItem.IFACE: if name == "URLs": return [fsn2uri(self.__f.name)] elif name == "MIMEType": return "image/png" elif name == "Width" or name == "Height": return Icon.SIZE elif name == "ColorDepth": return self.__depth def destroy(self): pass ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.984269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpdserver/�����������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020305� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpdserver/__init__.py������������������������������������������0000664�0001750�0001750�00000014150�14035600052�022415� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import os if os.name == "nt": from quodlibet.plugins import PluginNotSupportedError # we are missing socket.fromfd on Windows raise PluginNotSupportedError import socket from gi.repository import Gtk from quodlibet import _ from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.events import EventPlugin from quodlibet import app from quodlibet import qltk from quodlibet import config from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk import Icons from quodlibet.util import print_w, print_d from quodlibet.util.thread import call_async, Cancellable from .main import MPDServer from .tcpserver import ServerError from .avahi import AvahiService, AvahiError def fetch_local_ip(): """Returns a guess for the local IP""" try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) addr = s.getsockname()[0] s.close() except EnvironmentError: addr = "?.?.?.?" return addr DEFAULT_PORT = 6600 def get_port_num(): return config.getint("plugins", "mpdserver_port", DEFAULT_PORT) def set_port_num(value): return config.set("plugins", "mpdserver_port", str(value)) class MPDServerPlugin(EventPlugin, PluginConfigMixin): PLUGIN_ID = "mpd_server" PLUGIN_NAME = _("MPD Server") PLUGIN_DESC = _("Allows remote control of Quod Libet using an MPD Client. " "Streaming, playlist and library management " "are not supported.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP CONFIG_SECTION = "mpdserver" _server = None def PluginPreferences(self, parent): table = Gtk.Table(n_rows=3, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) label = Gtk.Label(label=_("_Port:"), use_underline=True) label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) entry = UndoEntry() entry.set_text(str(get_port_num())) def validate_port(entry, text, *args): try: int(text) except ValueError: entry.stop_emission("insert-text") entry.connect("insert-text", validate_port) def port_activate(entry, *args): try: port_num = int(entry.get_text()) except ValueError as e: print_w(e) else: if get_port_num() != port_num: set_port_num(port_num) self._refresh() entry.connect_after("activate", port_activate) entry.connect_after("focus-out-event", port_activate) table.attach(entry, 1, 2, 1, 2) port_revert = Gtk.Button() port_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) def port_revert_cb(button, entry): entry.set_text(str(DEFAULT_PORT)) entry.emit("activate") port_revert.connect("clicked", port_revert_cb, entry) table.attach( port_revert, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.SHRINK) label = Gtk.Label(label=_("Local _IP:"), use_underline=True) label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) label = Gtk.Label(label=_("P_assword:"), use_underline=True) label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, 2, 3, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) entry = UndoEntry() entry.set_text(self.config_get("password")) entry.connect('changed', self.config_entry_changed, "password") table.attach(entry, 1, 3, 2, 3) label = Gtk.Label() label.set_padding(6, 6) label.set_alignment(0.0, 0.5) label.set_selectable(True) label.set_label("...") table.attach(label, 1, 3, 0, 1) cancel = Cancellable() label.connect("destroy", lambda *x: cancel.cancel()) call_async(fetch_local_ip, cancel, label.set_label) box = Gtk.VBox(spacing=12) clients = Gtk.Label() clients.set_padding(6, 6) clients.set_markup(u"""\ \u2022 <a href="https://play.google.com/store/apps/details?id=com.\ namelessdev.mpdroid">MPDroid</a> (Android) \u2022 <a href="https://play.google.com/store/apps/details?id=org.\ gateshipone.malp">M.A.L.P.</a> (Android) """) clients.set_alignment(0, 0) box.pack_start( qltk.Frame(_("Connection"), child=table), False, True, 0) box.pack_start( qltk.Frame(_("Tested Clients"), child=clients), True, True, 0) return box def _refresh(self): # only restart if it was running if self._server: self._disable_server() self._enable_server() self._update_avahi() def _enable_server(self): port_num = get_port_num() print_d("Starting MPD server on port %d" % port_num) self._server = MPDServer(app, self, port_num) try: self._server.start() except ServerError as e: print_w(e) def _disable_server(self): print_d("Stopping MPD server") self._server.stop() self._server = None def _update_avahi(self): assert self._avahi port_num = get_port_num() try: self._avahi.register(app.name, port_num, "_mpd._tcp") except AvahiError as e: print_w(e) def enabled(self): self._enable_server() self._avahi = AvahiService() self._update_avahi() def disabled(self): self._avahi.unregister() self._avahi = None self._disable_server() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpdserver/avahi.py���������������������������������������������0000644�0001750�0001750�00000017030�14310167056�021754� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. from contextlib import contextmanager from gi.repository import GLib from gi.repository import Gio from quodlibet.util import print_d def alternative_service_name(name): if "#" in name: name, num = name.rsplit("#", 1) num = int(num) else: num = 1 return "%s#%d" % (name, num + 1) class AvahiPublishFlags: NONE = 0 UNIQUE = 1 << 0 NO_PROBE = 1 << 1 NO_ANNOUNCE = 1 << 2 ALLOW_MULTIPLE = 1 << 3 NO_REVERSE = 1 << 4 NO_COOKIE = 1 << 5 UPDATE = 1 << 6 USE_WIDE_AREA = 1 << 7 USE_MULTICAST = 1 << 8 class AvahiEntryGroupState: UNCOMMITED = 0 REGISTERING = 1 ESTABLISHED = 2 COLLISION = 3 FAILURE = 4 class AvahiServerState: INVALID = 0 REGISTERING = 1 RUNNING = 2 COLLISION = 3 FAILURE = 4 class AvahiProtocol: INET = 0 INET6 = 1 UNSPEC = -1 AVAHI_IF_UNSPEC = -1 class AvahiError(Exception): pass @contextmanager def ignored(*exceptions): try: yield except exceptions: pass class AvahiService: """Register a single network service using zeroconf/avahi service = AvahiService() service.register("foo", 4242, "_mpd._tcp") service.register("foo", 2424, "_mpd._tcp") service.unregister() http://avahi.org/download/doxygen/ """ DBUS_NAME = "org.freedesktop.Avahi" DBUS_PATH_SERVER = "/" DBUS_INTERFACE_ENTRY_GROUP = "org.freedesktop.Avahi.EntryGroup" DBUS_INTERFACE_SERVER = "org.freedesktop.Avahi.Server" def register(self, name, port, stype): """Register the service with avahi. Can be called multiple times and will update the service entry each time. In case Avahi isn't running or ready, the service will be registered when it is ready. Can raise AvahiError """ try: GLib.Variant('q', port) # guint16 except OverflowError as e: raise AvahiError(e) self.name = name self._real_name = name self.port = port self.stype = stype try: bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) if not self._watch: self._watch = Gio.bus_watch_name_on_connection( bus, self.DBUS_NAME, Gio.BusNameWatcherFlags.NONE, self._owner_appeared, self._owner_vanished) else: self._try_update_service() except GLib.Error as e: raise AvahiError(e) def unregister(self): """Unregister the service. Can be called multiple times. In case you want to update, call register() with new data instead. Will not raise. """ if self._watch: with ignored(GLib.Error): Gio.bus_unwatch_name(self._watch) self._watch = None self._remove_server() def __init__(self): self.name = None self.stype = None self.port = None self._group = None self._group_id = None self._server = None self._server_id = None self._watch = None self._real_name = None self._last_server_state = None def _on_group_signal(self, proxy, sender, signal, *args): if signal == 'StateChanged': self._group_state_change(args[0]) def _group_state_change(self, state, *args): if state == AvahiEntryGroupState.COLLISION: self._real_name = alternative_service_name(self._real_name) self._try_update_service() def _group_add_service_and_commit(self, group, flags): print_d("name=%s, flags=%x, stype=%s, port=%d" % ( self._real_name, flags, self.stype, self.port)) group.AddService('(iiussssqaay)', AVAHI_IF_UNSPEC, AvahiProtocol.UNSPEC, flags, self._real_name, self.stype, '', '', self.port, []) group.Commit() def _add_service(self): assert not self._group assert not self._group_id try: bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) server = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH_SERVER, self.DBUS_INTERFACE_SERVER, None) group_path = server.EntryGroupNew() group = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, group_path, self.DBUS_INTERFACE_ENTRY_GROUP, None) self._group_id = group.connect('g-signal', self._on_group_signal) self._group_add_service_and_commit(group, AvahiPublishFlags.NONE) self._group = group except GLib.Error: self._remove_service() def _try_update_service(self): if not self._group: return assert self._group_id try: group = self._group # XXX: http://markmail.org/message/b5d5wa2tdcplxpk2 # It's "documented" that Reset() shouldn't be called in this case, # but it doesn't work otherwise... group.Reset() self._group_add_service_and_commit(group, AvahiPublishFlags.UPDATE) except GLib.Error: self._remove_service() def _remove_service(self): if self._group: if self._group_id: with ignored(GLib.Error): self._group.disconnect(self._group_id) self._group_id = None with ignored(GLib.Error): self._group.Free() self._group = None def _remove_server(self): if self._server: if self._server_id: with ignored(GLib.Error): self._server.disconnect(self._server_id) self._server_id = None self._server = None self._last_server_state = None self._remove_service() def _add_server(self): assert not self._server_id try: server = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SYSTEM, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH_SERVER, self.DBUS_INTERFACE_SERVER, None) self._server_id = server.connect('g-signal', self._on_server_signal) self._server_state_changed(server.GetState()) self._server = server except GLib.Error: self._remove_server() def _on_server_signal(self, proxy, sender, signal, *args): if signal == 'StateChanged': self._server_state_changed(args[0]) def _server_state_changed(self, state, *args): # protect from calling this twice in a row for the same state # because we have to call this manually on start and can't # be sure if the signal fires as well if state == self._last_server_state: return self._last_server_state = state if state == AvahiServerState.RUNNING: self._add_service() elif state in (AvahiServerState.COLLISION, AvahiServerState.REGISTERING): self._remove_service() def _owner_appeared(self, bus, name, owner): self._add_server() def _owner_vanished(self, bus, owner): self._remove_server() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpdserver/main.py����������������������������������������������0000664�0001750�0001750�00000055632�14035600052�021614� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import re import shlex from typing import Dict, Tuple, Callable from senf import bytes2fsn, fsn2bytes from quodlibet import const from quodlibet.util import print_d, print_w from .tcpserver import BaseTCPServer, BaseTCPConnection class AckError: NOT_LIST = 1 ARG = 2 PASSWORD = 3 PERMISSION = 4 UNKNOWN = 5 NO_EXIST = 50 PLAYLIST_MAX = 51 SYSTEM = 52 PLAYLIST_LOAD = 53 UPDATE_ALREADY = 54 PLAYER_SYNC = 55 EXIST = 56 class Permissions: PERMISSION_NONE = 0 PERMISSION_READ = 1 PERMISSION_ADD = 2 PERMISSION_CONTROL = 4 PERMISSION_ADMIN = 8 PERMISSION_ALL = PERMISSION_NONE | \ PERMISSION_READ | \ PERMISSION_ADD | \ PERMISSION_CONTROL | \ PERMISSION_ADMIN TAG_MAPPING = [ (u"Artist", "artist"), (u"ArtistSort", "artistsort"), (u"Album", "album"), (u"AlbumArtist", "albumartist"), (u"AlbumArtistSort", "albumartistsort"), (u"Title", "title"), (u"Track", "tracknumber"), (u"Genre", "genre"), (u"Date", "~year"), (u"Composer", "composer"), (u"Performer", "performer"), (u"Comment", "commend"), (u"Disc", "discnumber"), (u"Name", "~basename"), (u"MUSICBRAINZ_ARTISTID", "musicbrainz_artistid"), (u"MUSICBRAINZ_ALBUMID", "musicbrainz_albumid"), (u"MUSICBRAINZ_ALBUMARTISTID", "musicbrainz_albumartistid"), (u"MUSICBRAINZ_TRACKID", "musicbrainz_trackid"), ] def format_tags(song): """Gives a tag list message for a song""" lines = [] for mpd_key, ql_key in TAG_MAPPING: value = song.comma(ql_key) or None if value is not None: lines.append(u"%s: %s" % (mpd_key, value)) return u"\n".join(lines) class ParseError(Exception): pass def parse_command(line): """Parses a MPD command (without trailing newline) Returns (command, [arguments]) or raises ParseError in case of an error. """ assert isinstance(line, bytes) parts = re.split(b"[ \\t]+", line, maxsplit=1) if not parts: raise ParseError("empty command") command = parts[0] if len(parts) > 1: lex = shlex.shlex(bytes2fsn(parts[1], "utf-8"), posix=True) lex.whitespace_split = True lex.commenters = "" lex.quotes = "\"" lex.whitespace = " \t" args = [fsn2bytes(a, "utf-8") for a in lex] else: args = [] try: command = command.decode("utf-8") except ValueError as e: raise ParseError(e) dec_args = [] for arg in args: try: arg = arg.decode("utf-8") except ValueError as e: raise ParseError(e) dec_args.append(arg) return command, dec_args class MPDService: """This is the actual shared MPD service which the clients talk to""" version = (0, 17, 0) def __init__(self, app, config): self._app = app self._connections = set() self._idle_subscriptions = {} self._idle_queue = {} self._pl_ver = 0 self._config = config self._options = app.player_options if not self._config.config_get("password"): self.default_permission = Permissions.PERMISSION_ALL else: self.default_permission = Permissions.PERMISSION_NONE def options_changed(*args): self.emit_changed("options") self._options.connect("notify::shuffle", options_changed) self._options.connect("notify::repeat", options_changed) self._options.connect("notify::single", options_changed) self._player_sigs = [] def volume_changed(*args): self.emit_changed("mixer") id_ = app.player.connect("notify::volume", volume_changed) self._player_sigs.append(id_) def player_changed(*args): self.emit_changed("player") id_ = app.player.connect("paused", player_changed) self._player_sigs.append(id_) id_ = app.player.connect("unpaused", player_changed) self._player_sigs.append(id_) id_ = app.player.connect("seek", player_changed) self._player_sigs.append(id_) def playlist_changed(*args): self._pl_ver += 1 self.emit_changed("playlist") id_ = app.player.connect("song-started", playlist_changed) self._player_sigs.append(id_) def _get_id(self, info): # XXX: we need a unique 31 bit ID, but don't have one. # Given that the heap is continuous and each object is >16 bytes # this should work return (id(info) & 0xFFFFFFFF) >> 1 def destroy(self): for id_ in self._player_sigs: self._app.player.disconnect(id_) del self._options del self._app def add_connection(self, connection): self._connections.add(connection) self._idle_queue[connection] = set() def remove_connection(self, connection): self._idle_subscriptions.pop(connection, None) self._idle_queue.pop(connection, None) self._connections.remove(connection) def register_idle(self, connection, subsystems): self._idle_subscriptions[connection] = set(subsystems) self.flush_idle() def flush_idle(self): flushed = [] for conn, subs in self._idle_subscriptions.items(): # figure out which subsystems to report for each connection queued = self._idle_queue[conn] if subs: to_send = subs & queued else: to_send = queued queued -= to_send # send out the response and remove the idle status for affected # connections for subsystem in to_send: conn.write_line(u"changed: %s" % subsystem) if to_send: flushed.append(conn) conn.ok() conn.start_write() for conn in flushed: self._idle_subscriptions.pop(conn, None) def unregister_idle(self, connection): self._idle_subscriptions.pop(connection, None) def emit_changed(self, subsystem): for conn, subs in self._idle_queue.items(): subs.add(subsystem) self.flush_idle() def play(self): self._app.player.playpause() def playid(self, songid): self.play() def pause(self, value=None): if value is None: self._app.player.paused = not self._app.player.paused else: self._app.player.paused = value def stop(self): self._app.player.stop() def next(self): self._app.player.next() def previous(self): self._app.player.previous() def seek(self, songpos, time_): """time_ in seconds""" self._app.player.seek(time_ * 1000) def seekid(self, songid, time_): """time_ in seconds""" self._app.player.seek(time_ * 1000) def seekcur(self, value, relative): if relative: pos = self._app.player.get_position() self._app.player.seek(pos + value * 1000) else: self._app.player.seek(value * 1000) def setvol(self, value): """value: 0..100""" self._app.player.volume = value / 100.0 def repeat(self, value): self._options.repeat = value def random(self, value): self._options.shuffle = value def single(self, value): self._options.single = value def stats(self): has_song = int(bool(self._app.player.info)) stats = [ ("artists", has_song), ("albums", has_song), ("songs", has_song), ("uptime", 1), ("playtime", 1), ("db_playtime", 1), ("db_update", 1252868674), ] return stats def status(self): app = self._app info = app.player.info if info: if app.player.paused: state = "pause" else: state = "play" else: state = "stop" status = [ ("volume", int(app.player.volume * 100)), ("repeat", int(self._options.repeat)), ("random", int(self._options.shuffle)), ("single", int(self._options.single)), ("consume", 0), ("playlist", self._pl_ver), ("playlistlength", int(bool(app.player.info))), ("mixrampdb", 0.0), ("state", state), ] if info: status.append(("audio", "%d:%d:%d" % ( info("~#samplerate") or 0, info("~#bitdepth") or 0, info("~#channels") or 0))) total_time = int(info("~#length")) elapsed_time = int(app.player.get_position() / 1000) elapsed_exact = "%1.3f" % (app.player.get_position() / 1000.0) status.extend([ ("song", 0), ("songid", self._get_id(info)), ]) if state != "stop": status.extend([ ("time", "%d:%d" % (elapsed_time, total_time)), ("elapsed", elapsed_exact), ("bitrate", info("~#bitrate")), ]) return status def currentsong(self): info = self._app.player.info if info is None: return None parts = [] parts.append(u"file: %s" % info("~filename")) parts.append(format_tags(info)) parts.append(u"Time: %d" % int(info("~#length"))) parts.append(u"Pos: %d" % 0) parts.append(u"Id: %d" % self._get_id(info)) return u"\n".join(parts) def playlistinfo(self, start=None, end=None): if start is not None and start > 1: return None return self.currentsong() def playlistid(self, songid=None): return self.currentsong() def plchanges(self, version): if version != self._pl_ver: return self.currentsong() def plchangesposid(self, version): info = self._app.player.info if version != self._pl_ver and info: parts = [] parts.append(u"file: %s" % info("~filename")) parts.append(u"Pos: %d" % 0) parts.append(u"Id: %d" % self._get_id(info)) return u"\n".join(parts) class MPDServer(BaseTCPServer): def __init__(self, app, config, port): self._app = app self._config = config super().__init__(port, MPDConnection, const.DEBUG) def handle_init(self): print_d("Creating the MPD service") self.service = MPDService(self._app, self._config) def handle_idle(self): print_d("Destroying the MPD service") self.service.destroy() del self.service def log(self, msg): print_d(msg) class MPDRequestError(Exception): def __init__(self, msg, code=AckError.UNKNOWN, index=None): self.msg = msg self.code = code self.index = index class MPDConnection(BaseTCPConnection): # ------------ connection interface ------------ def handle_init(self, server): service = server.service self.service = service service.add_connection(self) str_version = u".".join(map(str, service.version)) self._buf = bytearray((u"OK MPD %s\n" % str_version).encode("utf-8")) self._read_buf = bytearray() # begin - command processing state self._use_command_list = False # everything below is only valid if _use_command_list is True self._command_list_ok = False self._command_list = [] self._command = None # end - command processing state self.permission = self.service.default_permission self.start_write() self.start_read() def handle_read(self, data): self._feed_data(data) while 1: line = self._get_next_line() if line is None: break self.log(u"-> " + repr(line)) try: cmd, args = parse_command(line) except ParseError: # TODO: not sure what to do here re command lists continue try: self._handle_command(cmd, args) except MPDRequestError as e: self._error(e.msg, e.code, e.index) self._use_command_list = False del self._command_list[:] def handle_write(self): data = self._buf[:] del self._buf[:] return data def can_write(self): return bool(self._buf) def handle_close(self): self.log("connection closed") self.service.remove_connection(self) del self.service # ------------ rest ------------ def authenticate(self, password): if password == self.service._config.config_get("password"): self.permission = Permissions.PERMISSION_ALL else: self.permission = self.service.default_permission raise MPDRequestError("Password incorrect", AckError.PASSWORD) def log(self, msg): if const.DEBUG: print_d("[%s] %s" % (self.name, msg)) def _feed_data(self, new_data): """Feed new data into the read buffer""" self._read_buf.extend(new_data) def _get_next_line(self): """Returns the next line from the read buffer or None""" try: index = self._read_buf.index(b"\n") except ValueError: return None line = bytes(self._read_buf[:index]) del self._read_buf[:index + 1] return line def write_line(self, line): """Writes a line to the client""" assert isinstance(line, str) self.log(u"<- " + repr(line)) self._buf.extend(line.encode("utf-8", errors="replace") + b"\n") def ok(self): self.write_line(u"OK") def _error(self, msg, code, index): error = [] error.append(u"ACK [%d" % code) if index is not None: error.append(u"@%d" % index) assert self._command is not None error.append(u"] {%s}" % self._command) if msg is not None: error.append(u" %s" % msg) self.write_line(u"".join(error)) def _handle_command(self, command, args): self._command = command if command == u"command_list_end": if not self._use_command_list: self._error(u"list_end without begin") return for i, (cmd, args) in enumerate(self._command_list): try: self._exec_command(cmd, args) except MPDRequestError as e: # reraise with index raise MPDRequestError(e.msg, e.code, i) self.ok() self._use_command_list = False del self._command_list[:] return if command in (u"command_list_begin", u"command_list_ok_begin"): if self._use_command_list: raise MPDRequestError(u"begin without end") self._use_command_list = True self._command_list_ok = command == u"command_list_ok_begin" assert not self._command_list return if self._use_command_list: self._command_list.append((command, args)) else: self._exec_command(command, args) def _exec_command(self, command, args, no_ack=False): self._command = command if command not in self._commands: print_w("Unhandled command %r, sending OK." % command) command = "ping" # Unhandled command, default to OK for now.. if not self._use_command_list: self.ok() elif self._command_list_ok: self.write_line(u"list_OK") return cmd, do_ack, permission = self._commands[command] if permission != (self.permission & permission): raise MPDRequestError("Insufficient permission", AckError.PERMISSION) cmd(self, self.service, args) if self._use_command_list: if self._command_list_ok: self.write_line(u"list_OK") elif do_ack: self.ok() _commands: Dict[str, Tuple[Callable, bool, int]] = {} @classmethod def Command(cls, name, ack=True, permission=Permissions.PERMISSION_ADMIN): def wrap(func): assert name not in cls._commands, name cls._commands[name] = (func, ack, permission) return func return wrap @classmethod def list_commands(cls): """A list of supported commands""" return cls._commands.keys() def _verify_length(args, length): if not len(args) >= length: raise MPDRequestError("Wrong arg count") def _parse_int(arg): try: return int(arg) except ValueError: raise MPDRequestError("invalid arg") def _parse_bool(arg): try: value = int(arg) if value not in (0, 1): raise ValueError except ValueError: raise MPDRequestError("invalid arg") else: return bool(value) def _parse_range(arg): try: values = [int(v) for v in arg.split(":")] except ValueError: raise MPDRequestError("arg in range not a number") if len(values) == 1: return (values[0], values[0] + 1) elif len(values) == 2: return values else: raise MPDRequestError("invalid range") @MPDConnection.Command("idle", ack=False) def _cmd_idle(conn, service, args): service.register_idle(conn, args) @MPDConnection.Command("ping", permission=Permissions.PERMISSION_NONE) def _cmd_ping(conn, service, args): return @MPDConnection.Command("password", permission=Permissions.PERMISSION_NONE) def _cmd_password(conn, service, args): _verify_length(args, 1) conn.authenticate(args[0]) @MPDConnection.Command("noidle") def _cmd_noidle(conn, service, args): service.unregister_idle(conn) @MPDConnection.Command("close", ack=False, permission=Permissions.PERMISSION_NONE) def _cmd_close(conn, service, args): conn.close() @MPDConnection.Command("play") def _cmd_play(conn, service, args): service.play() @MPDConnection.Command("listplaylists") def _cmd_listplaylists(conn, service, args): pass @MPDConnection.Command("list") def _cmd_list(conn, service, args): pass @MPDConnection.Command("playid") def _cmd_playid(conn, service, args): _verify_length(args, 1) songid = _parse_int(args[0]) service.playid(songid) @MPDConnection.Command("pause") def _cmd_pause(conn, service, args): value = None if args: _verify_length(args, 1) value = _parse_bool(args[0]) service.pause(value) @MPDConnection.Command("stop") def _cmd_stop(conn, service, args): service.stop() @MPDConnection.Command("next") def _cmd_next(conn, service, args): service.next() @MPDConnection.Command("previous") def _cmd_previous(conn, service, args): service.previous() @MPDConnection.Command("repeat") def _cmd_repeat(conn, service, args): _verify_length(args, 1) value = _parse_bool(args[0]) service.repeat(value) @MPDConnection.Command("random") def _cmd_random(conn, service, args): _verify_length(args, 1) value = _parse_bool(args[0]) service.random(value) @MPDConnection.Command("single") def _cmd_single(conn, service, args): _verify_length(args, 1) value = _parse_bool(args[0]) service.single(value) @MPDConnection.Command("setvol") def _cmd_setvol(conn, service, args): _verify_length(args, 1) value = _parse_int(args[0]) service.setvol(value) @MPDConnection.Command("status") def _cmd_status(conn, service, args): status = service.status() for k, v in status: conn.write_line(u"%s: %s" % (k, v)) @MPDConnection.Command("stats") def _cmd_stats(conn, service, args): status = service.stats() for k, v in status: conn.write_line(u"%s: %s" % (k, v)) @MPDConnection.Command("currentsong") def _cmd_currentsong(conn, service, args): stats = service.currentsong() if stats is not None: conn.write_line(stats) @MPDConnection.Command("count") def _cmd_count(conn, service, args): conn.write_line(u"songs: 0") conn.write_line(u"playtime: 0") @MPDConnection.Command("plchanges") def _cmd_plchanges(conn, service, args): _verify_length(args, 1) version = _parse_int(args[0]) changes = service.plchanges(version) if changes is not None: conn.write_line(changes) @MPDConnection.Command("plchangesposid") def _cmd_plchangesposid(conn, service, args): _verify_length(args, 1) version = _parse_int(args[0]) changes = service.plchangesposid(version) if changes is not None: conn.write_line(changes) @MPDConnection.Command("listallinfo") def _cmd_listallinfo(*args): _cmd_currentsong(*args) @MPDConnection.Command("seek") def _cmd_seek(conn, service, args): _verify_length(args, 2) songpos = _parse_int(args[0]) time_ = _parse_int(args[1]) service.seek(songpos, time_) @MPDConnection.Command("seekid") def _cmd_seekid(conn, service, args): _verify_length(args, 2) songid = _parse_int(args[0]) time_ = _parse_int(args[1]) service.seekid(songid, time_) @MPDConnection.Command("seekcur") def _cmd_seekcur(conn, service, args): _verify_length(args, 1) relative = False time_ = args[0] if time_.startswith(("+", "-")): relative = True try: time_ = int(time_) except ValueError: raise MPDRequestError("arg not a number") service.seekcur(time_, relative) @MPDConnection.Command("outputs") def _cmd_outputs(conn, service, args): conn.write_line(u"outputid: 0") conn.write_line(u"outputname: dummy") conn.write_line(u"outputenabled: 1") @MPDConnection.Command("commands", permission=Permissions.PERMISSION_NONE) def _cmd_commands(conn, service, args): for name in conn.list_commands(): conn.write_line(u"command: " + str(name)) @MPDConnection.Command("tagtypes") def _cmd_tagtypes(conn, service, args): for mpd_key, ql_key in TAG_MAPPING: conn.write_line(mpd_key) @MPDConnection.Command("lsinfo") def _cmd_lsinfo(conn, service, args): _verify_length(args, 1) @MPDConnection.Command("playlistinfo") def _cmd_playlistinfo(conn, service, args): if args: _verify_length(args, 1) start, end = _parse_range(args[0]) result = service.playlistinfo(start, end) else: result = service.playlistinfo() if result is not None: conn.write_line(result) @MPDConnection.Command("playlistid") def _cmd_playlistid(conn, service, args): if args: songid = _parse_int(args[0]) else: songid = None result = service.playlistid(songid) if result is not None: conn.write_line(result) ������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpdserver/tcpserver.py�����������������������������������������0000664�0001750�0001750�00000017116�14035600052�022700� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. """A reactive tcp server""" import socket import errno from gi.repository import Gio, GLib from quodlibet.qltk import io_add_watch class ServerError(Exception): pass class BaseTCPServer: def __init__(self, port, connection_class, debug=False): """port -- IP port connection_class -- BaseTCPConnection subclass """ self._connections = [] self._port = port self._connection_class = connection_class self._sock_service = None self._debug = debug def log(self, msg): """Override for logging""" pass def start(self): """Start accepting connections. May raise ServerError. """ assert not self._sock_service service = Gio.SocketService.new() try: service.add_inet_port(self._port, None) except GLib.GError as e: raise ServerError(e) except OverflowError as e: raise ServerError("port: %s" % e) self._id = service.connect("incoming", self._incoming_connection_cb) service.start() self._sock_service = service def stop(self): """Stop accepting connections and close all existing connections. Can be called multiple times. """ if not self._sock_service: return self._sock_service.disconnect(self._id) if self._sock_service.is_active(): self._sock_service.stop() self._sock_service = None for conn in list(self._connections): conn.close() assert not self._connections, self._connections def handle_init(self): """Gets called if a new connection starts and there was none before""" pass def handle_idle(self): """Gets called once the last connection closes""" pass def _remove_connection(self, conn): """Called by the connection class on close""" self._connections.remove(conn) del conn._gio_connection if not self._connections: self.handle_idle() def _incoming_connection_cb(self, service, connection, *args): try: addr = connection.get_remote_address() except GLib.GError: addr_string = "?.?.?.?" else: addr_string = addr.get_address().to_string() fd = connection.get_socket().get_fd() sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(0) msg = "New connection from %s at socket %d" % ( addr_string, sock.fileno()) if self._debug: self.log(msg) if not self._connections: self.handle_init() tcp_conn = self._connection_class(self, sock) self._connections.append(tcp_conn) # XXX: set unneeded `connection` to keep the reference tcp_conn._gio_connection = connection tcp_conn.handle_init(self) class BaseTCPConnection: """Abstract base class for TCP connections. Subclasses need to implement the handle_*() can_*() methods. """ def __init__(self, server, sock): self._server = server self._sock = sock self._in_id = None self._out_id = None self._closed = False @property def name(self): return str(self._sock.fileno()) def start_read(self): """Start to read and call handle_read() if data is available. Only call once. """ assert self._in_id is None and not self._closed def can_read_cb(sock, flags, *args): if flags & (GLib.IOCondition.HUP | GLib.IOCondition.ERR): self.close() return False if flags & GLib.IOCondition.IN: while True: try: data = sock.recv(4096) except (IOError, OSError) as e: if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN): return True elif e.errno == errno.EINTR: continue else: self.close() return False break if not data: self.close() return False self.handle_read(data) # the implementation could close in handle_read() if not self._closed: self.start_write() return True self._in_id = io_add_watch( self._sock, GLib.PRIORITY_DEFAULT, GLib.IOCondition.IN | GLib.IOCondition.ERR | GLib.IOCondition.HUP, can_read_cb) def start_write(self): """Trigger at least one call to handle_write() if can_write is True. Used to start writing to a client not triggered by a client request. """ assert not self._closed write_buffer = bytearray() def can_write_cb(sock, flags, *args): if flags & (GLib.IOCondition.HUP | GLib.IOCondition.ERR): self.close() return False if flags & GLib.IOCondition.OUT: if self.can_write(): write_buffer.extend(self.handle_write()) if not write_buffer: self._out_id = None return False while True: try: result = sock.send(write_buffer) except (IOError, OSError) as e: if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN): return True elif e.errno == errno.EINTR: continue else: self.close() return False break del write_buffer[:result] return True if self._out_id is None: self._out_id = io_add_watch( self._sock, GLib.PRIORITY_DEFAULT, GLib.IOCondition.OUT | GLib.IOCondition.ERR | GLib.IOCondition.HUP, can_write_cb) def close(self): """Close this connection. Can be called multiple times. handle_close() will be called last. """ if self._closed: return self._closed = True if self._in_id is not None: GLib.source_remove(self._in_id) self._in_id = None if self._out_id is not None: GLib.source_remove(self._out_id) self._out_id = None self.handle_close() self._server._remove_connection(self) self._sock.close() def handle_init(self, server): """Called first, gets passed the BaseServer instance""" raise NotImplementedError def handle_read(self, data): """Called if new data was read""" raise NotImplementedError def handle_write(self): """Called if new data can be written, should return the data""" raise NotImplementedError def can_write(self): """Should return True if handle_write() can return data""" raise NotImplementedError def handle_close(self): """Called last when the connection gets closed""" raise NotImplementedError ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.984269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpris/���������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017430� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpris/__init__.py����������������������������������������������0000644�0001750�0001750�00000006200�14267565021�021550� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010,2012 Christoph Reiter <reiter.christoph@gmail.com> # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import Gtk import dbus try: import indicate except ImportError: indicate = None from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet import qltk from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk import Icons from quodlibet.plugins.events import EventPlugin from .mpris2 import MPRIS2 class MPRIS(EventPlugin): PLUGIN_ID = "mpris" PLUGIN_NAME = _("MPRIS D-Bus Support") PLUGIN_DESC_MARKUP = _( "Allows control of Quod Libet using the " "<a href=\"https://mpris2.readthedocs.io/en/latest/\">MPRIS 2</a> " "D-Bus Interface Specification. " "This allows various Linux desktop integrations (e.g. multimedia keys).") PLUGIN_ICON = Icons.NETWORK_WORKGROUP def PluginPreferences(self, parent): box = Gtk.HBox() ccb = ConfigCheckButton(_("Hide main window on close"), 'plugins', 'mpris_window_hide') ccb.set_active(self.__do_hide()) box.pack_start(qltk.Frame(_("Preferences"), child=ccb), True, True, 0) return box def __do_hide(self): return config.getboolean('plugins', 'mpris_window_hide', False) def __window_delete(self, win, event): if self.__do_hide(): win.hide() return True def enabled(self): self.__sig = app.window.connect('delete-event', self.__window_delete) self.objects = [] for service in [MPRIS2]: try: self.objects.append(service()) except dbus.DBusException: pass # Needed for sound menu support in some older Ubuntu versions if indicate: self.__indicate_server = s = indicate.indicate_server_ref_default() s.set_type("music.quodlibet") s.set_desktop_file( "/usr/share/applications/io.github.quodlibet.QuodLibet.desktop" ) s.show() def disabled(self): if indicate: self.__indicate_server.hide() for obj in self.objects: obj.remove_from_connection() self.objects = [] import gc gc.collect() app.window.disconnect(self.__sig) def plugin_on_paused(self): for obj in self.objects: obj.paused() def plugin_on_unpaused(self): for obj in self.objects: obj.unpaused() def plugin_on_song_started(self, song): for obj in self.objects: obj.song_started(song) def plugin_on_song_ended(self, song, skipped): for obj in self.objects: obj.song_ended(song, skipped) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpris/mpris2.py������������������������������������������������0000664�0001750�0001750�00000033243�14231604332�021224� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010,2012 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import time import tempfile import dbus import dbus.service from senf import fsn2uri from quodlibet import app from quodlibet.order.repeat import RepeatListForever, RepeatSongForever from quodlibet.util.dbusutils import DBusIntrospectable, DBusProperty from quodlibet.util.dbusutils import dbus_unicode_validate as unival from .util import MPRISObject # TODO: OpenUri, CanXYZ # Date parsing (util?) # http://www.mpris.org/2.0/spec/ class MPRIS2(DBusProperty, DBusIntrospectable, MPRISObject): BUS_NAME = "org.mpris.MediaPlayer2.quodlibet" PATH = "/org/mpris/MediaPlayer2" ROOT_IFACE = "org.mpris.MediaPlayer2" ROOT_ISPEC = """ <method name="Raise"/> <method name="Quit"/>""" ROOT_PROPS = """ <property name="CanQuit" type="b" access="read"/> <property name="CanRaise" type="b" access="read"/> <property name="CanSetFullscreen" type="b" access="read"/> <property name="HasTrackList" type="b" access="read"/> <property name="Identity" type="s" access="read"/> <property name="DesktopEntry" type="s" access="read"/> <property name="SupportedUriSchemes" type="as" access="read"/> <property name="SupportedMimeTypes" type="as" access="read"/>""" PLAYER_IFACE = "org.mpris.MediaPlayer2.Player" PLAYER_ISPEC = """ <method name="Next"/> <method name="Previous"/> <method name="Pause"/> <method name="PlayPause"/> <method name="Stop"/> <method name="Play"/> <method name="Seek"> <arg direction="in" name="Offset" type="x"/> </method> <method name="SetPosition"> <arg direction="in" name="TrackId" type="o"/> <arg direction="in" name="Position" type="x"/> </method> <method name="OpenUri"> <arg direction="in" name="Uri" type="s"/> </method> <signal name="Seeked"> <arg name="Position" type="x"/> </signal>""" PLAYER_PROPS = """ <property name="PlaybackStatus" type="s" access="read"/> <property name="LoopStatus" type="s" access="readwrite"/> <property name="Rate" type="d" access="readwrite"/> <property name="Shuffle" type="b" access="readwrite"/> <property name="Metadata" type="a{sv}" access="read"/> <property name="Volume" type="d" access="readwrite"/> <property name="Position" type="x" access="read"> <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" \ value="false"/> </property> <property name="MinimumRate" type="d" access="read"/> <property name="MaximumRate" type="d" access="read"/> <property name="CanGoNext" type="b" access="read"/> <property name="CanGoPrevious" type="b" access="read"/> <property name="CanPlay" type="b" access="read"/> <property name="CanPause" type="b" access="read"/> <property name="CanSeek" type="b" access="read"/> <property name="CanControl" type="b" access="read"> <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" \ value="false"/> </property>""" def __init__(self): DBusIntrospectable.__init__(self) DBusProperty.__init__(self) self.set_introspection(MPRIS2.ROOT_IFACE, MPRIS2.ROOT_ISPEC) self.set_properties(MPRIS2.ROOT_IFACE, MPRIS2.ROOT_PROPS) self.set_introspection(MPRIS2.PLAYER_IFACE, MPRIS2.PLAYER_ISPEC) self.set_properties(MPRIS2.PLAYER_IFACE, MPRIS2.PLAYER_PROPS) bus = dbus.SessionBus() name = dbus.service.BusName(self.BUS_NAME, bus) MPRISObject.__init__(self, bus, self.PATH, name) self.__metadata = None self.__cover = None player_options = app.player_options self.__repeat_id = player_options.connect( "notify::repeat", self.__repeat_changed) self.__random_id = player_options.connect( "notify::shuffle", self.__shuffle_changed) self.__single_id = player_options.connect( "notify::single", self.__single_changed) self.__lsig = app.librarian.connect("changed", self.__library_changed) self.__vsig = app.player.connect("notify::volume", self.__volume_changed) self.__seek_sig = app.player.connect("seek", self.__seeked) def remove_from_connection(self, *arg, **kwargs): super().remove_from_connection(*arg, **kwargs) player_options = app.player_options player_options.disconnect(self.__repeat_id) player_options.disconnect(self.__random_id) player_options.disconnect(self.__single_id) app.librarian.disconnect(self.__lsig) app.player.disconnect(self.__vsig) app.player.disconnect(self.__seek_sig) if self.__cover is not None: self.__cover.close() self.__cover = None self.__invalidate_metadata() def __volume_changed(self, *args): self.emit_properties_changed(self.PLAYER_IFACE, ["Volume"]) def __repeat_changed(self, *args): self.emit_properties_changed(self.PLAYER_IFACE, ["LoopStatus"]) def __shuffle_changed(self, *args): self.emit_properties_changed(self.PLAYER_IFACE, ["Shuffle"]) def __single_changed(self, *args): self.emit_properties_changed(self.PLAYER_IFACE, ["LoopStatus"]) def __seeked(self, player, song, ms): self.Seeked(ms * 1000) def __library_changed(self, library, songs): self.__invalidate_metadata() if not songs or app.player.info not in songs: return self.emit_properties_changed(self.PLAYER_IFACE, ["Metadata"]) @dbus.service.method(ROOT_IFACE) def Raise(self): app.present() @dbus.service.method(ROOT_IFACE) def Quit(self): app.quit() @dbus.service.signal(PLAYER_IFACE, signature="x") def Seeked(self, position): pass @dbus.service.method(PLAYER_IFACE) def Next(self): player = app.player paused = player.paused player.next() player.paused = paused @dbus.service.method(PLAYER_IFACE) def Previous(self): player = app.player paused = player.paused player.previous() player.paused = paused @dbus.service.method(PLAYER_IFACE) def Pause(self): app.player.paused = True @dbus.service.method(PLAYER_IFACE) def Play(self): app.player.play() @dbus.service.method(PLAYER_IFACE) def PlayPause(self): app.player.playpause() @dbus.service.method(PLAYER_IFACE) def Stop(self): app.player.stop() @dbus.service.method(PLAYER_IFACE, in_signature="x") def Seek(self, offset): new_pos = app.player.get_position() + offset / 1000 app.player.seek(new_pos) @dbus.service.method(PLAYER_IFACE, in_signature="ox") def SetPosition(self, track_id, position): if track_id == self.__get_current_track_id(): app.player.seek(position / 1000) def paused(self): self.emit_properties_changed(self.PLAYER_IFACE, ["PlaybackStatus"]) unpaused = paused def song_started(self, song): self.__invalidate_metadata() # so the position in clients gets updated faster self.Seeked(0) self.emit_properties_changed(self.PLAYER_IFACE, ["PlaybackStatus", "Metadata"]) def __get_current_track_id(self): path = "/net/sacredchao/QuodLibet" if not app.player.info: return dbus.ObjectPath(path + "/" + "NoTrack") return dbus.ObjectPath(path + "/" + str(id(app.player.info))) def __invalidate_metadata(self): self.__metadata = None def __get_metadata(self): if self.__metadata is None: self.__metadata = self.__get_metadata_real() assert self.__metadata is not None return self.__metadata def __get_metadata_real(self): """ https://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata/ """ metadata = {} metadata["mpris:trackid"] = self.__get_current_track_id() def ignore_overflow(dbus_type, value): try: return dbus_type(value) except OverflowError: return 0 song = app.player.info if not song: return metadata metadata["mpris:length"] = ignore_overflow( dbus.Int64, song("~#length") * 10 ** 6) if self.__cover is not None: self.__cover.close() self.__cover = None cover = app.cover_manager.get_cover(song) if cover: is_temp = cover.name.startswith(tempfile.gettempdir()) if is_temp: self.__cover = cover metadata["mpris:artUrl"] = fsn2uri(cover.name) # All list values list_val = {"artist": "artist", "albumArtist": "albumartist", "comment": "comment", "composer": "composer", "genre": "genre", "lyricist": "lyricist"} for xesam, tag in list_val.items(): vals = song.list(tag) if vals: metadata["xesam:" + xesam] = list(map(unival, vals)) # All single values sing_val = {"album": "album", "title": "title", "asText": "~lyrics"} for xesam, tag in sing_val.items(): vals = song.comma(tag) if vals: metadata["xesam:" + xesam] = unival(vals) # URI metadata["xesam:url"] = song("~uri") # Integers num_val = {"audioBPM": "bpm", "discNumber": "disc", "trackNumber": "track", "useCount": "playcount"} for xesam, tag in num_val.items(): val = song("~#" + tag, None) if val is not None: metadata["xesam:" + xesam] = ignore_overflow(dbus.Int32, val) # Rating metadata["xesam:userRating"] = ignore_overflow( dbus.Double, song("~#rating")) # Dates ISO_8601_format = "%Y-%m-%dT%H:%M:%S" tuple_time = time.gmtime(song("~#lastplayed")) iso_time = time.strftime(ISO_8601_format, tuple_time) metadata["xesam:lastUsed"] = iso_time year = song("~year") if year: try: tuple_time = time.strptime(year, "%Y") iso_time = time.strftime(ISO_8601_format, tuple_time) except ValueError: pass else: metadata["xesam:contentCreated"] = iso_time return metadata def set_property(self, interface, name, value): player = app.player player_options = app.player_options if interface == self.PLAYER_IFACE: if name == "LoopStatus": if value == "Playlist": player_options.repeat = True app.window.order.repeater = RepeatListForever elif value == "Track": player_options.repeat = True app.window.order.repeater = RepeatSongForever elif value == "None": player_options.repeat = False app.window.order.repeater = RepeatListForever elif name == "Rate": pass elif name == "Shuffle": player_options.shuffle = value elif name == "Volume": player.volume = value def get_property(self, interface, name): player = app.player player_options = app.player_options if interface == self.ROOT_IFACE: if name == "CanQuit": return True elif name == "CanRaise": return True elif name == "CanSetFullscreen": return False elif name == "HasTrackList": return False elif name == "Identity": return app.name elif name == "DesktopEntry": return "io.github.quodlibet.QuodLibet" elif name == "SupportedUriSchemes": # TODO: enable once OpenUri is done can = lambda s: False #can = lambda s: app.player.can_play_uri("%s://fake" % s) schemes = ["http", "https", "ftp", "file", "mms"] return filter(can, schemes) elif name == "SupportedMimeTypes": from quodlibet import formats return formats.mimes elif interface == self.PLAYER_IFACE: if name == "PlaybackStatus": if not player.song: return "Stopped" return ("Playing", "Paused")[int(player.paused)] elif name == "LoopStatus": if not player_options.repeat: return "None" else: if player_options.single: return "Track" return "Playlist" elif name == "Rate": return 1.0 elif name == "Shuffle": return player_options.shuffle elif name == "Metadata": return self.__get_metadata() elif name == "Volume": # https://gitlab.freedesktop.org/mpris/mpris-spec/issues/8 return player.volume elif name == "Position": return player.get_position() * 1000 elif name == "MinimumRate": return 1.0 elif name == "MaximumRate": return 1.0 elif name == "CanGoNext": return True elif name == "CanGoPrevious": return True elif name == "CanPlay": return True elif name == "CanPause": return True elif name == "CanSeek": return True elif name == "CanControl": return True �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mpris/util.py��������������������������������������������������0000664�0001750�0001750�00000001046�14035600052�020756� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010,2012 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import dbus class MPRISObject(dbus.service.Object): def paused(self): pass def unpaused(self): pass def song_started(self, song): pass def song_ended(self, song, skipped): pass ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/mqtt.py��������������������������������������������������������0000644�0001750�0001750�00000021070�14327505043�017641� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 - 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from quodlibet import _ from quodlibet.formats import AudioFile from quodlibet.util import monospace from quodlibet.util.tags import _TAGS _TOTAL_MQTT_ITEMS = 5 try: import paho.mqtt.client as mqtt except ImportError: from quodlibet.plugins import MissingModulePluginException raise MissingModulePluginException('paho-mqtt') from gi.repository import Gtk from quodlibet.pattern import Pattern from quodlibet.qltk.entry import UndoEntry, ValidatingEntry from quodlibet import qltk, app from quodlibet.util import copool from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfigMixin from quodlibet.util.dprint import print_d, print_w from quodlibet.qltk import Icons, ErrorMessage, Message EXPAND = Gtk.AttachOptions.EXPAND FILL = Gtk.AttachOptions.FILL class Config: STATUS_SONGLESS = 'no_song_text', "" PAT_PLAYING = 'playing_pattern', "♫ <~artist~title> ♫" PAT_PAUSED = 'paused_pattern', "<~artist~title> [%s]" % _("paused") HOST = 'host', "localhost" PORT = 'port', 1883 USERNAME = 'username', "" PASSWORD = 'password', "" TOPIC = 'topic', 'quodlibet/now-playing' EMPTY_STATUS = "" _ACCEPTS_PATTERNS = (_("Accepts QL Patterns e.g. %s") % monospace('<~artist~title>')) class MqttPublisherPlugin(EventPlugin, PluginConfigMixin): PLUGIN_ID = "MQTT Status" PLUGIN_NAME = _("MQTT Publisher") PLUGIN_DESC = _("Publishes status messages to an MQTT topic.") PLUGIN_ICON = Icons.FACE_SMILE def __init__(self) -> None: super().__init__() self.song = self.host = self.port = self.topic = None self.username = self.password = None self.status = Config.EMPTY_STATUS def on_connect(self, client, userdata, flags, rc): """Callback for when the client receives a CONNACK response from the server.""" print_d("Connected to %s at %s:%d with result code %s" % (self.topic, self.host, self.port, rc)) def on_message(self, client, userdata, msg): """The callback for messages received from the server.""" print_d("%s: %s" % (msg.topic, msg.payload)) def _set_up_mqtt_client(self): self.client = client = mqtt.Client() client.on_connect = self.on_connect client.on_message = self.on_message if self.username: client.username_pw_set(self.username, None) if self.password: client.username_pw_set(self.username, self.password) client.connect(self.host, self.port, 60) # Uses Threading.Thread internally, so we don't have to... self.client.loop_start() def _set_status(self, text): print_d("Setting status to \"%s\"..." % text) result, mid = self.client.publish(self.topic, text, retain=True) if result != mqtt.MQTT_ERR_SUCCESS: print_w("Couldn't publish to %s at %s:%d (%s)" % (self.topic, self.host, self.port, mqtt.error_string(result))) self.status = text def plugin_on_song_started(self, song): self.song = song pat_str = self.config_get(*Config.PAT_PLAYING) pattern = Pattern(pat_str) status = (pattern.format(song) if song else self.config_get(Config.STATUS_SONGLESS, "")) self._set_status(status) def plugin_on_paused(self): pat_str = self.config_get(*Config.PAT_PAUSED) pattern = Pattern(pat_str) self.status = (pattern.format(self.song) if self.song else Config.EMPTY_STATUS) self._set_status(self.status) def plugin_on_unpaused(self): self.plugin_on_song_started(self.song) def disabled(self): if self.status: self._set_status(self.config_get(Config.STATUS_SONGLESS)) self.client.on_connect = None self.client.on_message = None self.client.disconnect() def enabled(self): self.host = self.config_get(*Config.HOST) or 'localhost' self.port = int(self.config_get(*Config.PORT)) or 1883 self.username = self.config_get(*Config.USERNAME) self.password = self.config_get(*Config.PASSWORD) self.topic = self.config_get(*Config.TOPIC) self._set_up_mqtt_client() _CONFIG = [ (_("Broker hostname / IP"), Config.HOST, _("Defaults to localhost")), (_("Broker port"), Config.PORT, _("Defaults to 1883")), (_("Broker username"), Config.USERNAME, None), (_("Broker password"), Config.PASSWORD, None), (_("Topic"), Config.TOPIC, None), (_("Playing Pattern"), Config.PAT_PLAYING, _("Status text when a song is started.") + ' ' + _ACCEPTS_PATTERNS), (_("Paused Pattern"), Config.PAT_PAUSED, _("Text when a song is paused.") + ' ' + _ACCEPTS_PATTERNS), (_("No-song Text"), Config.STATUS_SONGLESS, _("Plain text for when there is no current song")) ] @staticmethod def _is_pattern(cfg): return cfg[0] in (Config.PAT_PLAYING[0], Config.PAT_PAUSED[0]) def PluginPreferences(self, parent): outer_vb = Gtk.VBox(spacing=12) t = self.config_table_for(self._CONFIG[:_TOTAL_MQTT_ITEMS]) frame = qltk.Frame(_("MQTT Configuration"), child=t) outer_vb.pack_start(frame, False, True, 0) t = self.config_table_for(self._CONFIG[_TOTAL_MQTT_ITEMS:]) frame = qltk.Frame(_("Status Text"), child=t) outer_vb.pack_start(frame, False, True, 0) return outer_vb def config_table_for(self, config_data): t = Gtk.Table(n_rows=2, n_columns=len(config_data)) t.set_col_spacings(6) t.set_row_spacings(6) for i, (label, cfg, tooltip) in enumerate(config_data): entry = (ValidatingEntry(validator=validator) if self._is_pattern(cfg) else UndoEntry()) entry.set_text(str(self.config_get(*cfg))) entry.connect('changed', self._on_changed, cfg) lbl = Gtk.Label(label=label + ":") lbl.set_size_request(140, -1) lbl.set_alignment(xalign=0.0, yalign=0.5) if tooltip is not None: entry.set_tooltip_markup(tooltip) lbl.set_mnemonic_widget(entry) t.attach(lbl, 0, 1, i, i + 1, xoptions=FILL) t.attach(entry, 1, 2, i, i + 1, xoptions=FILL | EXPAND) return t def _on_changed(self, entry, cfg): self.config_entry_changed(entry, cfg[0]) if cfg in [Config.HOST, Config.PORT]: self.disabled() copool.add(self.try_connecting, funcid="connect", timeout=1000) def try_connecting(self): try: self.enabled() msg = (_("Connected to broker at %(host)s:%(port)d") % {'host': self.host, 'port': self.port}) Message(Gtk.MessageType.INFO, app.window, "Success", msg).run() except IOError as e: template = _("Couldn't connect to %(host)s:%(port)d (%(msg)s)") msg = template % {'host': self.host, 'port': self.port, 'msg': e} print_w(msg) ErrorMessage(app.window, _("Connection error"), msg).run() yield def validator(pat): """Validates Patterns a bit. TODO: Extract to somewhere good - see #1983""" try: return bool(Pattern(pat).format(DUMMY_AF)) except Exception as e: print_d("Problem with pattern (%s)" % e) return False class FakeAudioFile(AudioFile): def __call__(self, *args, **kwargs): real = super().__call__(*args, **kwargs) tag = args[0] return real or self.fake_value(tag) def get(self, key, default=None): if key not in self: return default or self.fake_value(key) return super().get(key, default) def fake_value(self, key): if key.replace('~', '').replace('#', '') in _TAGS: if key.startswith('~#'): return 0 elif key.startswith('~'): return "The %s" % key if key.startswith('~'): raise ValueError("Unknown tag %s" % key) return "The %s" % key DUMMY_AF = FakeAudioFile({'~filename': '/dev/null'}) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/musicbrainzsync.py���������������������������������������������0000664�0001750�0001750�00000007172�14231604507�022107� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019 LoveIsGrief # # 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 2 of the License, or # (at your option) any later version. from quodlibet import plugins, qltk from quodlibet.qltk.entry import UndoEntry from quodlibet.util.thread import call_async_background, Cancellable try: import musicbrainzngs except ImportError: raise plugins.MissingModulePluginException("musicbrainzngs") from gi.repository import Gtk from quodlibet import _ from quodlibet.plugins import PluginConfig from quodlibet.plugins.events import EventPlugin ATTR_BRAINZ = 'musicbrainz_trackid' ATTR_RATING = '~#rating' BRAINZ_APP = "quodlibetMusicBrainzSync" VERSION = "0.1" plugin_config = PluginConfig("musicbrainz-sync") defaults = plugin_config.defaults defaults.set("username", "") defaults.set("password", "") class MusicBrainzSyncPlugin(EventPlugin): PLUGIN_ID = "musicbrainzsync" VERSION = VERSION PLUGIN_NAME = _("MusicBrainz Sync") PLUGIN_DESC = _("Syncs the rating of a song with MusicBrainz.") def __init__(self): super().__init__() musicbrainzngs.set_rate_limit() musicbrainzngs.set_useragent( BRAINZ_APP, VERSION, "quodlibet@lists.sacredchao.net" ) musicbrainzngs.auth( plugin_config.get("username"), plugin_config.get("password") ) def plugin_on_changed(self, songs): ratings_dict = { song(ATTR_BRAINZ): int(song(ATTR_RATING) * 100) for song in songs if ATTR_BRAINZ in song and ATTR_RATING in song } if len(ratings_dict): call_async_background( musicbrainzngs.submit_ratings, Cancellable(), callback=lambda *args: (), kwargs=dict( recording_ratings=ratings_dict, ), ) def PluginPreferences(self, parent): def changed(entry, key): if entry.get_property('sensitive'): plugin_config.set(key, entry.get_text()) musicbrainzngs.auth( plugin_config.get("username"), plugin_config.get("password") ) box = Gtk.VBox(spacing=12) # first frame table = Gtk.Table(n_rows=5, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = [] label_names = [_("User_name:"), _("_Password:")] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # username entry = UndoEntry() entry.set_text(plugin_config.get('username')) entry.connect('changed', changed, 'username') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # password entry = UndoEntry() entry.set_text(plugin_config.get('password')) entry.set_visibility(False) entry.connect('changed', changed, 'password') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 box.pack_start(qltk.Frame(_("Account"), child=table), True, True, 0) return box ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/notify.py������������������������������������������������������0000664�0001750�0001750�00000040721�14231604332�020165� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2010 Felix Krull <f_krull@gmx.de> # 2011-2013 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError import re from gi.repository import Gtk, GObject, GLib, Gio from senf import fsn2uri from quodlibet import _ from quodlibet import qltk, app from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfig from quodlibet.pattern import XMLFromPattern from quodlibet.qltk.textedit import TextView, TextBuffer from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.msg import ErrorMessage from quodlibet.qltk import Icons from quodlibet.util import unescape, print_w pconfig = PluginConfig("notify") pconfig.defaults.set("timeout", 4000) pconfig.defaults.set("show_notifications", "all") pconfig.defaults.set("show_only_when_unfocused", True) pconfig.defaults.set("show_next_button", True) pconfig.defaults.set("titlepattern", "<artist|<artist> - ><title>") pconfig.defaults.set("bodypattern", """<~length> <album|<album><discsubtitle| - <discsubtitle>> ><~year|<~year>>""") class PreferencesWidget(Gtk.VBox): def __init__(self, parent, plugin_instance): GObject.GObject.__init__(self, spacing=12) self.plugin_instance = plugin_instance # notification text settings table = Gtk.Table(n_rows=2, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) text_frame = qltk.Frame(_("Notification text"), child=table) title_entry = UndoEntry() title_entry.set_text(pconfig.gettext("titlepattern")) def on_entry_changed(entry, cfgname): pconfig.settext(cfgname, entry.get_text()) title_entry.connect("changed", on_entry_changed, "titlepattern") table.attach(title_entry, 1, 2, 0, 1) title_label = Gtk.Label(label=_("_Title:")) title_label.set_use_underline(True) title_label.set_alignment(0, 0.5) title_label.set_mnemonic_widget(title_entry) table.attach(title_label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) title_revert = Gtk.Button() title_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) title_revert.set_tooltip_text(_("Revert to default pattern")) title_revert.connect( "clicked", lambda *x: title_entry.set_text( pconfig.defaults.gettext("titlepattern"))) table.attach(title_revert, 2, 3, 0, 1, xoptions=Gtk.AttachOptions.SHRINK) body_textbuffer = TextBuffer() body_textview = TextView(buffer=body_textbuffer) body_textview.set_size_request(-1, 85) body_textview.get_buffer().set_text(pconfig.gettext("bodypattern")) def on_textbuffer_changed(text_buffer, cfgname): start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, True) pconfig.settext(cfgname, text) body_textbuffer.connect("changed", on_textbuffer_changed, "bodypattern") body_scrollarea = Gtk.ScrolledWindow() body_scrollarea.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) body_scrollarea.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) body_scrollarea.add(body_textview) table.attach(body_scrollarea, 1, 2, 1, 2) body_label = Gtk.Label(label=_("_Body:")) body_label.set_padding(0, 3) body_label.set_use_underline(True) body_label.set_alignment(0, 0) body_label.set_mnemonic_widget(body_textview) table.attach(body_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.SHRINK) body_revert = Gtk.Button() body_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) body_revert.set_tooltip_text(_("Revert to default pattern")) body_revert.connect("clicked", lambda *x: body_textbuffer.set_text(pconfig.defaults.gettext("bodypattern"))) table.attach( body_revert, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.SHRINK, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) # preview button preview_button = qltk.Button( _("_Show notification"), Icons.SYSTEM_RUN) preview_button.set_sensitive(app.player.info is not None) preview_button.connect("clicked", self.on_preview_button_clicked) self.qlplayer_connected_signals = [ app.player.connect("paused", self.on_player_state_changed, preview_button), app.player.connect("unpaused", self.on_player_state_changed, preview_button), ] table.attach( preview_button, 0, 3, 2, 3, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) self.pack_start(text_frame, True, True, 0) # notification display settings display_box = Gtk.VBox(spacing=12) display_frame = qltk.Frame(_("Show notifications"), child=display_box) radio_box = Gtk.VBox(spacing=6) display_box.pack_start(radio_box, True, True, 0) only_user_radio = Gtk.RadioButton(label=_( "Only on <i>_manual</i> song changes" ), use_underline=True) only_user_radio.get_child().set_use_markup(True) only_user_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "user") radio_box.pack_start(only_user_radio, True, True, 0) only_auto_radio = Gtk.RadioButton(group=only_user_radio, label=_( "Only on <i>_automatic</i> song changes" ), use_underline=True) only_auto_radio.get_child().set_use_markup(True) only_auto_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "auto") radio_box.pack_start(only_auto_radio, True, True, 0) all_radio = Gtk.RadioButton(group=only_user_radio, label=_( "On <i>a_ll</i> song changes" ), use_underline=True) all_radio.get_child().set_use_markup(True) all_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "all") radio_box.pack_start(all_radio, True, True, 0) { "user": only_user_radio, "auto": only_auto_radio, "all": all_radio }.get(pconfig.gettext("show_notifications"), all_radio).set_active(True) focus_check = Gtk.CheckButton( label=_("Only when the main window is not _focused"), use_underline=True) focus_check.set_active(pconfig.getboolean("show_only_when_unfocused")) focus_check.connect("toggled", self.on_checkbutton_toggled, "show_only_when_unfocused") display_box.pack_start(focus_check, True, True, 0) show_next = Gtk.CheckButton( label=_("Show \"_Next\" button"), use_underline=True) show_next.set_active(pconfig.getboolean("show_next_button")) show_next.connect("toggled", self.on_checkbutton_toggled, "show_next_button") display_box.pack_start(show_next, True, True, 0) self.pack_start(display_frame, True, True, 0) self.show_all() self.connect("destroy", self.on_destroyed) def on_radiobutton_toggled(self, radio, cfgname, value): if radio.get_active(): pconfig.set(cfgname, value) def on_checkbutton_toggled(self, button, cfgname): pconfig.set(cfgname, button.get_active()) def on_preview_button_clicked(self, button): if app.player.info is not None: if not self.plugin_instance.show_notification(app.player.info): ErrorMessage(self, _("Connection Error"), _("Couldn't connect to notification daemon.")).run() def on_player_state_changed(self, player, preview_button): preview_button.set_sensitive(player.info is not None) def on_destroyed(self, ev): for sig in self.qlplayer_connected_signals: app.player.disconnect(sig) self.qlplayer_connected_signals = [] self.plugin_instance = None class Notify(EventPlugin): PLUGIN_ID = "Notify" PLUGIN_NAME = _("Song Notifications") PLUGIN_DESC = _("Displays a notification when the song changes.") PLUGIN_ICON = Icons.DIALOG_INFORMATION DBUS_NAME = "org.freedesktop.Notifications" DBUS_IFACE = "org.freedesktop.Notifications" DBUS_PATH = "/org/freedesktop/Notifications" # these can all be used even if it wasn't enabled __enabled = False __last_id = 0 __image_fp = None __interface = None __action_sig = None __watch = None def enabled(self): self.__enabled = True # This works because: # - if paused, any on_song_started event will be generated by user # interaction # - if playing, an on_song_ended event will be generated before any # on_song_started event in any case. self.__was_stopped_by_user = True self.__force_notification = False self.__caps = None self.__spec_version = None self.__enable_watch() def disabled(self): self.__disable_watch() self.__disconnect() self.__enabled = False self._set_image_fileobj(None) def __enable_watch(self): """Enable events for dbus name owner change""" try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) # This also triggers for existing name owners self.__watch = Gio.bus_watch_name_on_connection( bus, self.DBUS_NAME, Gio.BusNameWatcherFlags.NONE, None, self.__owner_vanished) except GLib.Error: pass def __disable_watch(self): """Disable name owner change events""" if self.__watch: Gio.bus_unwatch_name(self.__watch) self.__watch = None def __disconnect(self): if self.__interface is None: return if self.__action_sig: self.__interface.disconnect(self.__action_sig) self.__action_sig = None self.__interface = None def __owner_vanished(self, bus, owner): # In case the owner gets removed, remove all references to it self.__disconnect() def PluginPreferences(self, parent): return PreferencesWidget(parent, self) def __get_interface(self): """Returns a fresh proxy + info about the server""" interface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH, self.DBUS_IFACE, None) name, vendor, version, spec_version = \ list(map(str, interface.GetServerInformation())) spec_version = list(map(int, spec_version.split("."))) caps = list(map(str, interface.GetCapabilities())) return interface, caps, spec_version def close_notification(self): """Closes the last opened notification""" if not self.__last_id: return try: interface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH, self.DBUS_IFACE, None) interface.CloseNotification('(u)', self.__last_id) except GLib.Error: pass else: self.__last_id = 0 def _set_image_fileobj(self, fileobj): if self.__image_fp is not None: self.__image_fp.close() self.__image_fp = None self.__image_fp = fileobj def _get_image_uri(self, song): """A unicode file URI or an empty string""" fileobj = app.cover_manager.get_cover(song) self._set_image_fileobj(fileobj) if fileobj: return fsn2uri(fileobj.name) return u"" def show_notification(self, song): """Returns True if showing the notification was successful""" if not song: return True try: if self.__enabled: # we are enabled try to work with the data we have and # keep it fresh if not self.__interface: iface, caps, spec = self.__get_interface() self.__interface = iface self.__caps = caps self.__spec_version = spec if "actions" in caps: self.__action_sig = iface.connect( 'g-signal', self._on_signal) else: iface = self.__interface caps = self.__caps spec = self.__spec_version else: # not enabled, just get everything temporary, # probably preview iface, caps, spec = self.__get_interface() except GLib.Error: print_w("[notify] %s" % _("Couldn't connect to notification daemon.")) self.__disconnect() return False strip_markup = lambda t: re.subn(r"\</?[iub]\>", "", t)[0] strip_links = lambda t: re.subn(r"\</?a.*?\>", "", t)[0] strip_images = lambda t: re.subn(r"\<img.*?\>", "", t)[0] title = XMLFromPattern(pconfig.gettext("titlepattern")) % song title = unescape(strip_markup(strip_links(strip_images(title)))) body = "" if "body" in caps: body = XMLFromPattern(pconfig.gettext("bodypattern")) % song if "body-markup" not in caps: body = strip_markup(body) if "body-hyperlinks" not in caps: body = strip_links(body) if "body-images" not in caps: body = strip_images(body) actions = [] if pconfig.getboolean("show_next_button") and "actions" in caps: actions = ["next", _("Next")] hints = { "desktop-entry": GLib.Variant( 's', "io.github.quodlibet.QuodLibet"), } image_uri = self._get_image_uri(song) if image_uri: hints["image_path"] = GLib.Variant('s', image_uri) hints["image-path"] = GLib.Variant('s', image_uri) try: self.__last_id = iface.Notify('(susssasa{sv}i)', "Quod Libet", self.__last_id, image_uri, title, body, actions, hints, pconfig.getint("timeout")) except GLib.Error: print_w("[notify] %s" % _("Couldn't connect to notification daemon.")) self.__disconnect() return False # preview done, remove all references again if not self.__enabled: self.__disconnect() return True def _on_signal(self, proxy, sender, signal, args): if signal == 'ActionInvoked': notify_id = args[0] key = args[1] self.on_dbus_action(notify_id, key) def on_dbus_action(self, notify_id, key): if notify_id == self.__last_id and key == "next": # Always show a new notification if the next button got clicked self.__force_notification = True app.player.next() def on_song_change(self, song, typ): if not song: self.close_notification() if pconfig.gettext("show_notifications") in [typ, "all"] \ and not (pconfig.getboolean("show_only_when_unfocused") and app.window.has_toplevel_focus()) \ or self.__force_notification: def idle_show(song): self.show_notification(song) GLib.idle_add(idle_show, song) self.__force_notification = False def plugin_on_song_started(self, song): typ = (self.__was_stopped_by_user and "user") or "auto" self.on_song_change(song, typ) def plugin_on_song_ended(self, song, stopped): # if `stopped` is `True`, this song was ended due to some kind of user # interaction. self.__was_stopped_by_user = stopped �����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667166353.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/notify_bookmarks.py��������������������������������������������0000644�0001750�0001750�00000010506�14327570221�022236� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from collections import deque from typing import Optional import gi from quodlibet.formats import AudioFile from quodlibet.player._base import BasePlayer from quodlibet.qltk import Icons try: gi.require_version('Notify', '0.7') from gi.repository import GLib, Notify except (ValueError, ImportError) as e: from quodlibet import plugins raise plugins.PluginNotSupportedError(f"Can't load GI Notify module ({e!r})") from quodlibet import app, _ from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.events import EventPlugin from quodlibet.util import format_time from quodlibet.util.dprint import print_d class BookmarkNotify(EventPlugin, PluginConfigMixin): PLUGIN_ID = "BookmarkNotify" PLUGIN_NAME = _("Bookmark Notifications") PLUGIN_DESC = _("Uses notifications to display bookmarks / comments in real-time. " "Works well for the Soundcloud browser.") PLUGIN_ICON = Icons.DIALOG_INFORMATION def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._timer = None self.song: Optional[AudioFile] = None self._bookmarks = [] self._loaded = False def enabled(self) -> None: self._timer = GLib.timeout_add(1000, self._sync) if app.player: self._player: BasePlayer = app.player else: raise TypeError(f"App {app} has no player set up") def disabled(self) -> None: GLib.source_remove(self._timer) def _sync(self) -> bool: if not (self._player.paused): shown = 0 while self.bookmarks: t, text = self.bookmarks[0] if t * 1000 < self._player.get_position(): if not shown: # Limit throughput to 1 per tick (second currrently) self._show(t, text) shown += 1 self.bookmarks.popleft() else: return True return True @property def bookmarks(self): if not self._bookmarks and not self._loaded and self.song: self._bookmarks = deque(self.song.bookmarks) if self._bookmarks: print_d(f"Loaded {len(self._bookmarks)} bookmarks") self._loaded = True return self._bookmarks @bookmarks.setter def bookmarks(self, bms): self._bookmarks = deque(bms) def _show(self, ts: int, line: str) -> None: if not self.song: return msg = f"♪ {format_time(ts)}: <b>{line.strip()}</b> ♪" print_d(msg) line = GLib.markup_escape_text(line) notif = Notify.Notification.new(f"Quodlibet – {self.song('title')}", f"<b>{line}</b> @ {format_time(ts)}", "user-idle") # notif.category = "im" notif.show() def plugin_on_song_started(self, song) -> None: self.song = song if self.song: Notify.init(f"Quodlibet - {self.song('title')}") self.bookmarks = [] # Keep a track of whether we _ever_ got them for this song self._loaded = False def plugin_on_seek(self, song: AudioFile, msec: int) -> None: self.song = song self._reset_to(msec) def plugin_on_changed(self, songs): if self.song in songs: print_d("Song has been changed, reloading") self._loaded = False self.bookmarks = [] def _reset_to(self, msec: int) -> None: print_d(f"Resetting to {format_time(msec / 1000)}") self.bookmarks = deque([] if self.song is None else self.song.bookmarks) while self.bookmarks: t, text = self.bookmarks[0] if t * 1000 < msec: self.bookmarks.popleft() else: time_str = format_time(msec / 1000) print_d(f"Next bookmark at {format_time(t)}s " f"(at {time_str}) - {len(self.bookmarks)} left") return print_d("Finished bookmarks") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/qlscrobbler.py�������������������������������������������������0000664�0001750�0001750�00000053636�14231604332�021200� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# QLScrobbler: an Audioscrobbler client plugin for Quod Libet. # version 0.11 # (C) 2005-2016 by Joshua Kwan <joshk@triplehelix.org>, # Joe Wreschnig <piman@sacredchao.net>, # Franz Pletyz <fpletz@franz-pletz.org>, # Nicholas J. Michalek <djphazer@gmail.com>, # Steven Robertson <steven@strobe.cc> # 2012-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import threading import time from typing import Dict, List from hashlib import md5 from urllib.parse import urlencode from gi.repository import Gtk, GLib import quodlibet from quodlibet import _ from quodlibet import const, app, util, qltk from quodlibet.pattern import Pattern from quodlibet.query import Query from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfig from quodlibet.qltk.entry import ValidatingEntry, UndoEntry from quodlibet.qltk.msg import Message from quodlibet.qltk import Icons from quodlibet.util.dprint import print_d, print_w from quodlibet.util.picklehelper import pickle_load, pickle_dump, PickleError from quodlibet.util.urllib import urlopen, UrllibError from quodlibet.errorreport import errorhook SERVICES = { 'Last.fm': 'http://post.audioscrobbler.com/', 'Libre.fm': 'http://turtle.libre.fm/' } DEFAULT_SERVICE = 'Last.fm' DEFAULT_TITLEPAT = '<title><version| (<version>)>' DEFAULT_ARTISTPAT = '<artist|<artist>|<composer|<composer>|<performer>>>' plugin_config = PluginConfig("scrobbler") defaults = plugin_config.defaults defaults.set("service", DEFAULT_SERVICE) defaults.set("titlepat", "") defaults.set("artistpat", "") defaults.set("url", "") defaults.set("username", "") defaults.set("password", "") defaults.set("exclude", "") defaults.set("offline", False) def config_get_url(): """Gets the URL for the currently configured service. This logic was used often enough to be split out from generic config """ # TODO: share this between the classes better service = plugin_config.get('service') if service in SERVICES: return SERVICES[service] else: return plugin_config.get('url') def config_get_title_pattern(): return plugin_config.get('titlepat') or DEFAULT_TITLEPAT def config_get_artist_pattern(): return plugin_config.get('artistpat') or DEFAULT_ARTISTPAT class QLSubmitQueue: """Manages the submit queue for scrobbles. Works independently of the QLScrobbler plugin being enabled; other plugins may use submit() to queue songs for scrobbling. """ CLIENT = "qlb" CLIENT_VERSION = const.VERSION PROTOCOL_VERSION = "1.2" SCROBBLER_CACHE_FILE = os.path.join(quodlibet.get_user_dir(), "scrobbler_cache_v2") # These objects are shared across instances, to allow other plugins to # queue scrobbles in future versions of QL queue: List[Dict[str, str]] = [] changed_event = threading.Event() def set_nowplaying(self, song): """Send a Now Playing notification.""" formatted = self._format_song(song) if not formatted or self.nowplaying_song == formatted: return self.nowplaying_song = formatted self.nowplaying_sent = False self.changed() def submit(self, song, timestamp=0): """Submit a song. If 'timestamp' is 0, the current time will be used.""" formatted = self._format_song(song) if formatted is None: return if timestamp > 0: formatted['i'] = str(timestamp) elif timestamp == 0: formatted['i'] = str(int(time.time())) else: # TODO: Forging timestamps for submission from PMPs return self.queue.append(formatted) self.changed() def _format_song(self, song): """Returns a dict with the keys formatted as required by spec.""" store = { "l": str(song.get("~#length", 0)), "n": str(song("~#track")), "b": song.comma("album"), "m": song("musicbrainz_trackid"), "t": self.titlepat.format(song), "a": self.artpat.format(song), } # Spec requires title and artist at minimum if not (store.get("a") and store.get("t")): return None return store def __init__(self): self.nowplaying_song = None self.nowplaying_sent = False self.sessionid = None self.handshake_event = None self.handshake_delay = 1.0 self.failures = 0 self.handshake_sent = 0 self.session_id, self.nowplaying_url, self.submit_url = None, None, None self.broken = False self.username, self.password, self.base_url = ('', '', '') # These need to be set early for _format_song to work self.titlepat = Pattern(config_get_title_pattern()) self.artpat = Pattern(config_get_artist_pattern()) self._load_queue() def _load_queue(self): try: with open(self.SCROBBLER_CACHE_FILE, 'rb') as disk_queue_file: disk_queue = pickle_load(disk_queue_file) os.unlink(self.SCROBBLER_CACHE_FILE) self.queue += disk_queue except (EnvironmentError, PickleError): pass @classmethod def dump_queue(klass): if klass.queue: print_d(f"Saving scrobble queue to {klass.SCROBBLER_CACHE_FILE}") try: with open(klass.SCROBBLER_CACHE_FILE, 'wb') as disk_queue_file: pickle_dump(klass.queue, disk_queue_file) except (EnvironmentError, PickleError) as e: print_w(f"Couldn't persist scrobble queue ({e})") def _check_config(self): user = plugin_config.get('username') passw = md5(plugin_config.getbytes('password')).hexdigest() url = config_get_url() if not user or not passw or not url: if self.queue and not self.broken: self.quick_dialog(_("Please visit the Plugins window to set " "QLScrobbler up. Until then, songs will not be " "submitted."), Gtk.MessageType.INFO) self.broken = True elif (self.username, self.password, self.base_url) != (user, passw, url): self.username, self.password, self.base_url = (user, passw, url) self.broken = False self.handshake_sent = False self.offline = plugin_config.getboolean('offline') self.titlepat = Pattern(config_get_title_pattern()) self.artpat = Pattern(config_get_artist_pattern()) def changed(self): """Signal that settings or queue contents were changed.""" self._check_config() pending = self.queue or (self.nowplaying_song and not self.nowplaying_sent) if not self.broken and not self.offline and pending: self.changed_event.set() return self.changed_event.clear() def run(self): """Submit songs from the queue. Call from a daemon thread.""" # The spec calls for exponential backoff of failed handshakes, with a # minimum of 1m and maximum of 120m delay between attempts. self.handshake_sent = False self.handshake_event = threading.Event() self.handshake_event.set() self.handshake_delay = 1 self.failures = 0 while True: self.changed_event.wait() if not self.handshake_sent: self.handshake_event.wait() if self.send_handshake(): self.failures = 0 self.handshake_delay = 1 self.handshake_sent = True else: self.handshake_event.clear() self.handshake_delay = min(self.handshake_delay * 2, 120) GLib.timeout_add(self.handshake_delay * 60 * 1000, self.handshake_event.set) continue self.changed_event.wait() if self.queue: if self.send_submission(): self.failures = 0 else: self.failures += 1 if self.failures >= 3: self.handshake_sent = False elif self.nowplaying_song and not self.nowplaying_sent: self.send_nowplaying() self.nowplaying_sent = True else: # Nothing left to do; wait until something changes self.changed_event.clear() def send_handshake(self, show_dialog=False): # construct url stamp = int(time.time()) auth = md5(self.password.encode("utf-8") + str(stamp).encode("utf-8")).hexdigest() qp = dict(hs="true", p=self.PROTOCOL_VERSION, c=self.CLIENT, v=self.CLIENT_VERSION, u=self.username, a=auth, t=int(stamp)) qs = urlencode(qp) url = f"{self.base_url}/?{qs}" print_d(f"Sending handshake to service at {self.base_url}.") try: resp = urlopen(url) except UrllibError: if show_dialog: self.quick_dialog( _("Could not contact service '%s'.") % util.escape(self.base_url), Gtk.MessageType.ERROR) else: print_d("Could not contact service. Queueing submissions.") return False except ValueError: self.quick_dialog(_("Authentication failed: invalid URL."), Gtk.MessageType.ERROR) self.broken = True return False # check response lines = resp.read().decode("utf-8", "ignore").rstrip().split("\n") status = lines.pop(0) if status == "OK": self.session_id, self.nowplaying_url, self.submit_url = lines self.handshake_sent = True print_d("Session ID: %s, NP URL: %s, Submit URL: %s" % ( self.session_id, self.nowplaying_url, self.submit_url)) return True print_w(f"Bad handshake status: {status}") if status == "BADAUTH": self.quick_dialog(_("Authentication failed: Invalid username '%s' " "or bad password.") % util.escape(self.username), Gtk.MessageType.ERROR) self.broken = True elif status == "BANNED": self.quick_dialog(_("Client is banned. Contact the author."), Gtk.MessageType.ERROR) self.broken = True elif status == "BADTIME": self.quick_dialog(_("Wrong system time. Submissions may fail " "until it is corrected."), Gtk.MessageType.ERROR) else: # "FAILED" self.quick_dialog(util.escape(status), Gtk.MessageType.ERROR) self.changed() return False def _check_submit(self, url, data): data_str = urlencode(data).encode("ascii") try: resp = urlopen(url, data_str) except EnvironmentError: print_d("Audioscrobbler server not responding, will try later.") return False resp_save = resp.read().decode("utf-8", "ignore") status = resp_save.rstrip().split("\n")[0] print_d("Submission status: %s" % status) if status == "OK": return True elif status == "BADSESSION": self.handshake_sent = False return False else: return False def send_submission(self): data = {'s': self.session_id} to_submit = self.queue[:min(len(self.queue), 50)] for idx, song in enumerate(to_submit): for key, val in song.items(): data['%s[%d]' % (key, idx)] = val.encode('utf-8') data['o[%d]' % idx] = 'P' data['r[%d]' % idx] = '' song_info = '\n\t'.join(f"{s['a']} - {s['t']}" for s in to_submit) print_d(f"Submitting song(s): {song_info}") if self._check_submit(self.submit_url, data): del self.queue[:len(to_submit)] return True else: return False def send_nowplaying(self): data = {'s': self.session_id} for key, val in self.nowplaying_song.items(): data[key] = val.encode('utf-8') print_d('Now playing song: %s - %s' % (self.nowplaying_song['a'], self.nowplaying_song['t'])) return self._check_submit(self.nowplaying_url, data) def quick_dialog_helper(self, dialog_type, msg): dialog = Message(dialog_type, app.window, "QLScrobbler", msg) dialog.connect('response', lambda dia, resp: dia.destroy()) dialog.show() def quick_dialog(self, msg, dialog_type): GLib.idle_add(self.quick_dialog_helper, dialog_type, msg) class QLScrobbler(EventPlugin): PLUGIN_ID = "QLScrobbler" PLUGIN_NAME = _("AudioScrobbler Submission") PLUGIN_DESC = _("Audioscrobbler client for Last.fm, Libre.fm and other " "Audioscrobbler services.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP AUTOSAVE_INTERVAL = 30 """How often, in seconds, to save the queue (if any) to disk""" def __init__(self): self.__enabled = False self.queue = QLSubmitQueue() self._tid = None def queue_run(): try: self.queue.run() except Exception: errorhook() queue_thread = threading.Thread(None, queue_run) queue_thread.setDaemon(True) queue_thread.start() print_d(f"Started Scrobbler thread {queue_thread}") self.start_time = 0 self.unpaused_time = 0 self.elapsed = 0 self.nowplaying = None self.exclude = plugin_config.get('exclude') def plugin_on_song_ended(self, song, stopped): if song is None or not self.__enabled: return if self.unpaused_time > 0: self.elapsed += time.time() - self.unpaused_time # Spec: * don't submit when song length < 00:30 # * submit at end of playback (not in the middle, as with v1.1) # * submit if played for >= .5*length or >= 240s # we check 'elapsed' rather than 'length' to work around wrong ~#length if self.elapsed < 30: return if self.elapsed < 240 and self.elapsed <= .5 * song.get("~#length", 0): return print_d("Checking against filter %s" % self.exclude) if self.exclude and Query(self.exclude).search(song): print_d("Not submitting: %s" % song("~artist~title")) return self.queue.submit(song, self.start_time) def song_excluded(self, song): if self.exclude and Query(self.exclude).search(song): print_d("%s is excluded by %s" % (song("~artist~title"), self.exclude)) return True return False def send_nowplaying(self, song): if not self.song_excluded(song): self.queue.set_nowplaying(song) def plugin_on_song_started(self, song): if song is None: return self.start_time = int(time.time()) if app.player.paused: self.unpaused_time = 0 else: self.unpaused_time = time.time() self.elapsed = 0 if self.__enabled and not app.player.paused: self.send_nowplaying(song) else: self.nowplaying = song def plugin_on_paused(self): if self.unpaused_time > 0: self.elapsed += time.time() - self.unpaused_time self.unpaused_time = 0 def plugin_on_unpaused(self): self.unpaused_time = time.time() if self.__enabled and self.nowplaying: self.send_nowplaying(self.nowplaying) self.nowplaying = None def enabled(self): self.__enabled = True print_d("Plugin enabled - accepting new songs.") if not self._tid: print_d("Starting scrobble autosaver") self._tid = GLib.timeout_add_seconds( self.AUTOSAVE_INTERVAL, lambda: QLSubmitQueue.dump_queue() or True) def disabled(self): self.__enabled = False print_d("Plugin disabled - not accepting any new songs.") if self._tid: print_d("Stopping scrobble autosaver") GLib.source_remove(self._tid) self._tid = None QLSubmitQueue.dump_queue() def PluginPreferences(self, parent): def changed(entry, key): if entry.get_property('sensitive'): plugin_config.set(key, entry.get_text()) def combo_changed(widget, urlent): service = widget.get_active_text() plugin_config.set("service", service) urlent.set_sensitive((service not in SERVICES)) urlent.set_text(config_get_url()) def check_login(*args): queue = QLSubmitQueue() queue.changed() status = queue.send_handshake(show_dialog=True) if status: queue.quick_dialog(_("Authentication successful."), Gtk.MessageType.INFO) box = Gtk.VBox(spacing=12) # first frame table = Gtk.Table(n_rows=5, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = [] label_names = [_("_Service:"), _("_URL:"), _("User_name:"), _("_Password:")] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 service_combo = Gtk.ComboBoxText() table.attach(service_combo, 1, 2, row, row + 1) cur_service = plugin_config.get('service') # Translators: Other service other_label = _(u"Other…") for idx, serv in enumerate(sorted(SERVICES.keys()) + [other_label]): service_combo.append_text(serv) if cur_service == serv: service_combo.set_active(idx) if service_combo.get_active() == -1: service_combo.set_active(0) labels[row].set_mnemonic_widget(service_combo) row += 1 # url entry = UndoEntry() entry.set_text(plugin_config.get('url')) entry.connect('changed', changed, 'url') service_combo.connect('changed', combo_changed, entry) service_combo.emit('changed') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # username entry = UndoEntry() entry.set_text(plugin_config.get('username')) entry.connect('changed', changed, 'username') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # password entry = UndoEntry() entry.set_text(plugin_config.get('password')) entry.set_visibility(False) entry.connect('changed', changed, 'password') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # verify data button = qltk.Button(_("_Verify account data"), Icons.DIALOG_INFORMATION) button.connect('clicked', check_login) table.attach(button, 0, 2, 4, 5) box.pack_start(qltk.Frame(_("Account"), child=table), True, True, 0) # second frame table = Gtk.Table(n_rows=4, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) label_names = [_("_Artist pattern:"), _("_Title pattern:"), _("Exclude _filter:")] labels = [] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # artist pattern entry = UndoEntry() entry.set_text(plugin_config.get('artistpat')) entry.connect('changed', changed, 'artistpat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the artist name for submission. Leave blank for " "default.")) labels[row].set_mnemonic_widget(entry) row += 1 # title pattern entry = UndoEntry() entry.set_text(plugin_config.get('titlepat')) entry.connect('changed', changed, 'titlepat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the title for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # exclude filter entry = ValidatingEntry(Query.validator) entry.set_text(plugin_config.get('exclude')) entry.set_tooltip_text( _("Songs matching this filter will not be submitted")) entry.connect('changed', changed, 'exclude') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # offline mode offline = plugin_config.ConfigCheckButton( _("_Offline mode (don't submit anything)"), 'offline', populate=True) table.attach(offline, 0, 2, row, row + 1) box.pack_start(qltk.Frame(_("Submission"), child=table), True, True, 0) return box ��������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/radioadmute.py�������������������������������������������������0000664�0001750�0001750�00000004220�14035600052�021142� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011-2013 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import re from quodlibet import _ from quodlibet import app from quodlibet.qltk import Icons from quodlibet.util import re_escape from quodlibet.plugins.events import EventPlugin class RadioAdMute(EventPlugin): PLUGIN_ID = "radio_ad_mute" PLUGIN_NAME = _("Mute Radio Ads") PLUGIN_DESC = _("Mutes output while radio advertisements are playing.\n" "Stations: di.fm.") PLUGIN_ICON = Icons.AUDIO_VOLUME_MUTED TEXT_SPAM = [ "www.webex.co.uk", "di.fm/premium", "There's more to Digitally Imported!", "Digitally Imported AMTAG_60 ADWTAG_30000_START=0", "Digitally Imported TSTAG_60 ADWTAG", "PhotonVPS.com", "Get Digitally Imported Premium", "More of the show after these messages", "Choose premium for the best audio experience", "www.di.fm/jobs", ] RE_SPAM = [ r"Sponsored Message\s+\([0-9]+\)", ] _SPAM = list(map(re_escape, TEXT_SPAM)) + RE_SPAM SPAM = [re.compile(s, re.I) for s in _SPAM] __old_volume = 0 __muted = False def disabled(self): self.plugin_on_song_ended() def plugin_on_song_started(self, song): # only check stream info songs if not song or not song.streamsong: return player = app.player data = song("~title~artist") for spam in self.SPAM: if spam.search(data): self.__old_volume = player.volume self.__muted = True player.volume = 0 break def plugin_on_song_ended(self, *args): if not self.__muted: return self.__muted = False player = app.player if player.volume != 0: # volume changed, do nothing return # restore old volume player.volume = self.__old_volume ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/randomalbum.py�������������������������������������������������0000644�0001750�0001750�00000023537�14327505043�021167� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2009 Joe Wreschnig, Steven Robertson # 2012-2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import random from typing import Dict from gi.repository import Gtk, GLib from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet.plugins.events import EventPlugin from quodlibet import util from quodlibet.util import print_d from quodlibet.browsers.playlists import PlaylistsBrowser from quodlibet.qltk import notif, Icons class RandomAlbum(EventPlugin): PLUGIN_ID = 'Random Album Playback' PLUGIN_NAME = _('Random Album Playback') PLUGIN_DESC = _("Starts a random album when your playlist reaches its " "end. It requires that your active browser supports " "filtering by album.") PLUGIN_ICON = Icons.MEDIA_SKIP_FORWARD weights: Dict[str, float] = {} use_weights = False # Not a dict because we want to impose a particular order # Third item is to specify a non-default aggregation function keys = [ ("rating", _("Rated higher"), None), ("playcount", _("Played more often"), 'avg'), ("skipcount", _("Skipped more often"), 'avg'), ("lastplayed", _("Played more recently"), None), ("laststarted", _("Started more recently"), None), ("added", _("Added more recently"), None), ("length", _("Longer albums"), None), ] def __init__(self): for (key, text, func) in self.keys: val = config.getfloat("plugins", "randomalbum_%s" % key, 0.0) self.weights[key] = val use = config.getint("plugins", "randomalbum_use_weights", 0) self.use_weights = use delay = config.getint("plugins", "randomalbum_delay", 0) self.delay = delay def PluginPreferences(self, song): def changed_cb(hscale, key): val = hscale.get_value() self.weights[key] = val config.set("plugins", "randomalbum_%s" % key, val) def delay_changed_cb(spin): self.delay = int(spin.get_value()) config.set("plugins", "randomalbum_delay", str(self.delay)) def toggled_cb(check, widgets): self.use_weights = check.get_active() for w in widgets: w.set_sensitive(self.use_weights) config.set("plugins", "randomalbum_use_weights", str(int(self.use_weights))) vbox = Gtk.VBox(spacing=12) table = Gtk.Table(n_rows=len(self.keys) + 1, n_columns=3) table.set_border_width(3) hbox = Gtk.HBox(spacing=6) spin = Gtk.SpinButton( adjustment=Gtk.Adjustment.new(self.delay, 0, 3600, 1, 10, 0)) spin.connect("value-changed", delay_changed_cb) hbox.pack_start(spin, False, True, 0) lbl = Gtk.Label(label=_("seconds before starting next album")) hbox.pack_start(lbl, False, True, 0) vbox.pack_start(hbox, True, True, 0) frame = Gtk.Frame(label=_("Weights")) check = Gtk.CheckButton(label=_("Play some albums more than others")) vbox.pack_start(check, False, True, 0) # Toggle both frame and contained table; frame doesn't always work? check.connect("toggled", toggled_cb, [frame, table]) check.set_active(self.use_weights) toggled_cb(check, [frame, table]) frame.add(table) vbox.pack_start(frame, True, True, 0) # Less label less_lbl = Gtk.Label() arr = Gtk.Arrow(arrow_type=Gtk.ArrowType.LEFT, shadow_type=Gtk.ShadowType.OUT) less_lbl.set_markup(util.italic(_("avoid"))) less_lbl.set_alignment(0, 0) hb = Gtk.HBox(spacing=0) hb.pack_start(arr, False, True, 0) hb.pack_start(less_lbl, True, True, 0) table.attach(hb, 1, 2, 0, 1, xpadding=3, xoptions=Gtk.AttachOptions.FILL) # More label more_lbl = Gtk.Label() arr = Gtk.Arrow(arrow_type=Gtk.ArrowType.RIGHT, shadow_type=Gtk.ShadowType.OUT) more_lbl.set_markup(util.italic(_("prefer"))) more_lbl.set_alignment(1, 0) hb = Gtk.HBox(spacing=0) hb.pack_end(arr, False, True, 0) hb.pack_end(more_lbl, True, True, 0) table.attach(hb, 2, 3, 0, 1, xpadding=3, xoptions=Gtk.AttachOptions.FILL) for (idx, (key, text, func)) in enumerate(self.keys): lbl = Gtk.Label(label=text) lbl.set_alignment(0, 0) table.attach(lbl, 0, 1, idx + 1, idx + 2, xoptions=Gtk.AttachOptions.FILL, xpadding=3, ypadding=3) adj = Gtk.Adjustment(lower=-1.0, upper=1.0, step_increment=0.1) hscale = Gtk.HScale(adjustment=adj) hscale.set_value(self.weights[key]) hscale.set_draw_value(False) hscale.set_show_fill_level(False) hscale.connect("value-changed", changed_cb, key) lbl.set_mnemonic_widget(hscale) table.attach(hscale, 1, 3, idx + 1, idx + 2, xpadding=3, ypadding=3) return vbox def _score(self, albums): """Score each album. Returns a list of (score, album) tuples.""" # Score the album based on its weighted rank ordering for each key # Rank ordering is more resistant to clustering than weighting # based on normalized means, and also normalizes the scale of each # weight slider in the prefs pane. ranked = {} for (tag, text, func) in self.keys: tag_key = ("~#%s:%s" % (tag, func) if func else "~#%s" % tag) ranked[tag] = sorted(albums, key=lambda al: al.get(tag_key)) scores = {} for album in albums: scores[album] = 0 for (tag, text, func) in self.keys: rank = ranked[tag].index(album) scores[album] += rank * self.weights[tag] return [(score, album) for album, score in scores.items()] def plugin_on_song_started(self, song): one_song = app.player_options.single if song is None and not one_song and not app.player.paused: browser = app.window.browser if self.disabled_for_browser(browser): print_d("%s doesn't support album filtering" % browser.name) return albumlib = app.library.albums albumlib.load() if browser.can_filter_albums(): keys = browser.list_albums() values = [albumlib[k] for k in keys] else: keys = set(browser.list("album")) values = [a for a in albumlib if a("album") in keys] if not values: print_d("No albums to randomly choose from.") return if self.use_weights: # Select 3% of albums, or at least 3 albums total = len(values) nr_albums = min(total, max(int(0.03 * total), 3)) print_d("Choosing from %d library albums:" % nr_albums) chosen_albums = random.sample(values, nr_albums) album_scores = self._score(chosen_albums) # Find highest score value max_score = max(album_scores, key=lambda t: t[0])[0] print_d("Maximum score found: %0.1f" % max_score) # Filter albums by highest score value albums = [(sc, al) for sc, al in album_scores if sc == max_score] print_d("Albums with maximum score:") for score, album in albums: print_d(" %s" % album("album")) # Pick random album from list of highest scored albums album = random.choice(albums)[1] else: album = random.choice(values) if album is not None: print_d("Chosen album: %s" % album("album")) self.schedule_change(album) def schedule_change(self, album): if self.delay: srcid = GLib.timeout_add(1000 * self.delay, self.change_album, album) task = notif.Task(_("Random Album"), _("Waiting to start %s") % util.bold(album("album")), stop=lambda: GLib.source_remove(srcid)) def countdown(): for i in range(10 * self.delay): task.update(i / (10. * self.delay)) yield True task.finish() yield False GLib.timeout_add(100, next, countdown()) else: self.change_album(album) def change_album(self, album): browser = app.window.browser if self.disabled_for_browser(browser): return if browser.can_filter_albums(): browser.filter_albums([album.key]) else: browser.filter('album', [album("album")]) GLib.idle_add(self.unpause) def unpause(self): # Wait for the next GTK loop to make sure everything's tidied up # after the song ended. Also, if this is program startup and the # previous current song wasn't found, we'll get this condition # as well, so just leave the player paused if that's the case. try: app.player.next() except AttributeError: app.player.paused = True def disabled_for_browser(self, browser): return (not browser.can_filter("album") or isinstance(browser, PlaylistsBrowser)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/rbimport.py����������������������������������������������������0000644�0001750�0001750�00000010300�14266344767�020524� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import xml.sax from xml.sax.handler import ContentHandler from gi.repository import Gtk from senf import uri2fsn from quodlibet import _ from quodlibet import app from quodlibet import util from quodlibet.qltk import Icons from quodlibet.qltk.msg import WarningMessage, ErrorMessage from quodlibet.util.path import normalize_path from quodlibet.plugins.events import EventPlugin class RBDBContentHandler(ContentHandler): def __init__(self, library): ContentHandler.__init__(self) self._library = library self._current = None self._tag = None self._changed_songs = [] def characters(self, content): if self._current is not None and self._tag is not None: self._current[self._tag] = content def startElement(self, name, attrs): self._tag = None if name == "entry" and attrs.get("type") == "song": self._current = {} elif name in ("location", "rating", "play-count", "last-played"): self._tag = name def endElement(self, name): self._tag = None if name == "entry" and self._current is not None: current = self._current self._current = None if len(current) > 1: uri = current.pop("location", "") try: filename = uri2fsn(uri) except ValueError: return self._process_song(normalize_path(filename), current) def _process_song(self, path, stats): song = self._library.get(path, None) if not song: return has_changed = False if "rating" in stats: try: value = int(stats["rating"]) / 5.0 except ValueError: pass else: song["~#rating"] = value has_changed = True if "play-count" in stats: try: value = int(stats["play-count"]) except ValueError: pass else: # we could sum them, but that would break on multiple imports song["~#playcount"] = value has_changed = True if "last-played" in stats: try: value = int(stats["last-played"]) except ValueError: pass else: if value > song("~#lastplayed", 0): song["~#lastplayed"] = value has_changed = True if has_changed: self._changed_songs.append(song) def finish(self): """Call at the end, also returns amount of imported songs""" count = len(self._changed_songs) self._library.changed(self._changed_songs) self._changed_songs = [] return count def do_import(parent, library): db_path = os.path.expanduser("~/.local/share/rhythmbox/rhythmdb.xml") handler = RBDBContentHandler(library) try: xml.sax.parse(db_path, handler) except Exception: util.print_exc() handler.finish() msg = _("Import Failed") # FIXME: don't depend on the plugin class here.. ErrorMessage(parent, RBImport.PLUGIN_NAME, msg).run() else: count = handler.finish() msg = _("Successfully imported ratings and statistics " "for %d songs") % count # FIXME: this is just a warning so it works with older QL WarningMessage(parent, RBImport.PLUGIN_NAME, msg).run() class RBImport(EventPlugin): PLUGIN_ID = "rbimport" PLUGIN_NAME = _("Rhythmbox Import") PLUGIN_DESC = _("Imports ratings and song statistics from Rhythmbox.") PLUGIN_ICON = Icons.DOCUMENT_OPEN def PluginPreferences(self, *args): button = Gtk.Button(label=_("Start Import")) def clicked_cb(button): do_import(button, app.library) button.connect("clicked", clicked_cb) return button ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/screensaver.py�������������������������������������������������0000664�0001750�0001750�00000006135�14035600052�021173� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2014 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import Gio from gi.repository import GLib from quodlibet import _ from quodlibet import app from quodlibet.qltk import Icons from quodlibet.plugins.events import EventPlugin class ScreensaverPause(EventPlugin): PLUGIN_ID = "screensaver_pause" PLUGIN_NAME = _("Screensaver Pause") PLUGIN_DESC = _("Pauses playback while the GNOME screensaver is active.") PLUGIN_ICON = Icons.MEDIA_PLAYBACK_PAUSE DBUS_NAME = "org.gnome.ScreenSaver" DBUS_INTERFACE = "org.gnome.ScreenSaver" DBUS_PATH = "/org/gnome/ScreenSaver" __was_paused = False __ignore_next = False __interface = None __active = False __watch = None def __on_signal(self, proxy, sender, signal, args): if signal == 'ActiveChanged': # Gnome-Shell fires ActiveChanged even if it doesn't change # (aborted transition to lock screen), so handle that active = args[0] if active == self.__active: return self.__active = active if active: self.__was_paused = app.player.paused app.player.paused = True elif not self.__was_paused and not self.__ignore_next: app.player.paused = False self.__ignore_next = False def plugin_on_unpaused(self): # In case pause/unpause happens while the session is inactive # (mpris, remote, etc.) don't unpause when it gets active again self.__ignore_next = True plugin_on_paused = plugin_on_unpaused def __remove_interface(self): if self.__interface: self.__interface.disconnect(self.__sig) self.__interface = None def __owner_appeared(self, bus, name, owner): if not self.__interface: iface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH, self.DBUS_INTERFACE, None) self.__sig = iface.connect('g-signal', self.__on_signal) self.__active = iface.GetActive() self.__interface = iface def __owner_vanished(self, bus, owner): self.__remove_interface() def enabled(self): try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) self.__watch = Gio.bus_watch_name_on_connection( bus, self.DBUS_NAME, Gio.BusNameWatcherFlags.NONE, self.__owner_appeared, self.__owner_vanished) except GLib.Error: pass def disabled(self): if self.__watch: Gio.bus_unwatch_name(self.__watch) self.__remove_interface() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684387440.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/searchprovider.py����������������������������������������������0000644�0001750�0001750�00000020551�14431333160�021672� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter <reiter.christoph@gmail.com> # 2023 Nick Boultbee # 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 2 of the License, or # (at your option) any later version. """ For this plugin to work GNOME Shell needs this file: /usr/share/gnome-shell/search-providers/io.github.quodlibet.QuodLibet-search-provider.ini (or in a similar XDG directory) A copy of this file can be found in ../../../data/ """ import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import GLib from gi.repository import Gio from quodlibet import _ from quodlibet import app from quodlibet.util.dbusutils import dbus_unicode_validate from quodlibet.plugins.events import EventPlugin from quodlibet.query import Query from quodlibet.plugins import PluginImportException from quodlibet.util.path import xdg_get_system_data_dirs from quodlibet.qltk import Icons DEFAULT_SEARCH_PROVIDER_DIR = "/usr/share/gnome-shell/search-providers" def get_gs_provider_files(): """Return all installed search provider files for GNOME Shell""" ini_files = [] for d in xdg_get_system_data_dirs(): path = os.path.join(d, "gnome-shell", "search-providers") try: for entry in os.listdir(path): if entry.endswith(".ini"): ini_files.append(os.path.join(path, entry)) except EnvironmentError: pass return ini_files def check_ini_installed(): """Raise if no GNOME Shell ini file for Quod Libet is found""" provider_installed = False for path in get_gs_provider_files(): try: with open(path, "rb") as handle: data = handle.read().decode("utf-8", "replace") if SearchProvider.BUS_NAME in data: provider_installed = True break except EnvironmentError: pass if not provider_installed: path = DEFAULT_SEARCH_PROVIDER_DIR msg = (_("No GNOME Shell search provider for Quod Libet installed.") + " \n" + _("Have you copied the ini file to %s (or similar)?") % path) raise PluginImportException(msg) class GnomeSearchProvider(EventPlugin): PLUGIN_ID = "searchprovider" PLUGIN_NAME = _("GNOME Search Provider") PLUGIN_DESC = _("Allows GNOME Shell to search the library.") PLUGIN_ICON = Icons.SYSTEM_SEARCH def enabled(self): self.obj = SearchProvider() def disabled(self): self.obj.remove_from_connection() del self.obj import gc gc.collect() ENTRY_ICON = ". GThemedIcon audio-mpeg gnome-mime-audio-mpeg audio-x-generic" def get_song_id(song): return str(id(song)) def get_songs_for_ids(library, ids): songs = [] ids = set(ids) for song in library: song_id = get_song_id(song) if song_id in ids: songs.append(song) ids.discard(song_id) if not ids: break return songs class SearchProvider: """ <!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'> <node name="/io/github/quodlibet/QuodLibet/SearchProvider"> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg direction="out" type="s" /> </method> </interface> <interface name="org.gnome.Shell.SearchProvider2"> <method name="GetInitialResultSet"> <arg direction="in" type="as" name="terms" /> <arg direction="out" type="as" name="results" /> </method> <method name="GetSubsearchResultSet"> <arg direction="in" type="as" name="previous_results" /> <arg direction="in" type="as" name="terms" /> <arg direction="out" type="as" name="results" /> </method> <method name="GetResultMetas"> <arg direction="in" type="as" name="identifiers" /> <arg direction="out" type="aa{sv}" name="metas" /> </method> <method name="ActivateResult"> <arg direction="in" type="s" name="identifier" /> <arg direction="in" type="as" name="terms" /> <arg direction="in" type="u" name="timestamp" /> </method> <method name="LaunchSearch"> <arg direction="in" type="as" name="terms" /> <arg direction="in" type="u" name="timestamp" /> </method> </interface> </node> """ PATH = "/io/github/quodlibet/QuodLibet/SearchProvider" BUS_NAME = "io.github.quodlibet.QuodLibet.SearchProvider" IFACE = "org.gnome.Shell.SearchProvider2" def __init__(self): self._own_id = Gio.bus_own_name(Gio.BusType.SESSION, self.BUS_NAME, Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, None, self.on_name_lost) self._registered_ids = [] self._method_outargs = {} def on_bus_acquired(self, connection, name): info = Gio.DBusNodeInfo.new_for_xml(self.__doc__) for interface in info.interfaces: for method in interface.methods: self._method_outargs[method.name] = '({})'.format( ''.join([arg.signature for arg in method.out_args])) _id = connection.register_object( object_path=self.PATH, interface_info=interface, method_call_closure=self.on_method_call) self._registered_ids.append(_id) def on_name_lost(self, connection, name): for _id in self._registered_ids: connection.unregister_object(_id) def remove_from_connection(self): if self._own_id is not None: Gio.bus_unown_name(self._own_id) self._own_id = None def on_method_call(self, connection, sender, object_path, interface_name, method_name, parameters, invocation): args = list(parameters.unpack()) result = getattr(self, method_name)(*args) if not isinstance(result, tuple): result = (result,) out_args = self._method_outargs[method_name] if out_args != '()': variant = GLib.Variant(out_args, result) invocation.return_value(variant) else: invocation.return_value(None) def Introspect(self): return self.__doc__ def GetInitialResultSet(self, terms): if terms: query = Query("") for term in terms: query &= Query(term) songs = filter(query.search, app.library) else: songs = app.library.values() ids = [get_song_id(s) for s in songs] return ids def GetSubsearchResultSet(self, previous_results, terms): query = Query("") for term in terms: query &= Query(term) songs = get_songs_for_ids(app.library, previous_results) ids = [get_song_id(s) for s in songs if query.search(s)] return ids def GetResultMetas(self, identifiers): metas = [] for song in get_songs_for_ids(app.library, identifiers): name = song("title") description = song("~artist~title") song_id = get_song_id(song) meta = { "name": GLib.Variant('s', dbus_unicode_validate(name)), "id": GLib.Variant('s', song_id), "description": GLib.Variant( 's', dbus_unicode_validate(description)), "gicon": GLib.Variant('s', ENTRY_ICON) } metas.append(meta) return metas def ActivateResult(self, identifier, terms, timestamp): songs = get_songs_for_ids(app.library, [identifier]) if not songs: return if app.player.go_to(songs[0], True): app.player.paused = False def LaunchSearch(self, terms, timestamp): try: app.window.browser.filter_text(" ".join(terms)) except NotImplementedError: pass else: app.present() # the plugin is useless without the ini file... check_ini_installed() �������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/seekbar.py�����������������������������������������������������0000664�0001750�0001750�00000010445�14035600052�020266� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import contextlib from gi.repository import GObject, Gtk from quodlibet import _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.qltk.seekbutton import TimeLabel from quodlibet.qltk.tracker import TimeTracker from quodlibet.qltk import Align from quodlibet.util import connect_destroy class SeekBar(Gtk.Box): def __init__(self, player, library): super().__init__() self._elapsed_label = TimeLabel() self._remaining_label = TimeLabel() scale = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL) scale.set_adjustment(Gtk.Adjustment.new(0, 0, 0, 3, -15, 0)) scale.set_draw_value(False) self._scale = scale self.pack_start(Align(self._elapsed_label, border=6), False, True, 0) self.pack_start(scale, True, True, 0) self.pack_start(Align(self._remaining_label, border=6), False, True, 0) for child in self.get_children(): child.show_all() self._id = self._scale.connect( 'value-changed', self._on_user_changed, player) self._scale.connect( 'value-changed', self._on_scale_value_changed, player) self._tracker = TimeTracker(player) self._tracker.connect('tick', self._on_tick, player) connect_destroy(player, 'seek', self._on_player_seek) connect_destroy(player, 'song-started', self._on_song_started) connect_destroy(player, "notify::seekable", self._on_seekable_changed) connect_destroy( library, "changed", self._on_song_changed, player) self.connect("destroy", self._on_destroy) with self._inhibit(): self._update(player) self._tracker.tick() def _on_destroy(self, *args): self._tracker.destroy() @contextlib.contextmanager def _inhibit(self): with GObject.signal_handler_block(self._scale, self._id): yield def _on_user_changed(self, scale, player): if player.seekable: player.seek(scale.get_value() * 1000) def _on_scale_value_changed(self, scale, player): self._update(player) def _on_tick(self, tracker, player): position = player.get_position() // 1000 with self._inhibit(): self._scale.set_value(position) def _on_seekable_changed(self, player, *args): with self._inhibit(): self._update(player) def _on_song_changed(self, library, songs, player): if player.info in songs: with self._inhibit(): self._update(player) def _on_player_seek(self, player, song, ms): with self._inhibit(): self._scale.set_value(ms // 1000) self._update(player) def _on_song_started(self, player, song): with self._inhibit(): self._scale.set_value(0) self._update(player) def _update(self, player): if player.info: self._scale.set_range(0, player.info("~#length")) else: self._scale.set_range(0, 1) if not player.seekable: self._scale.set_value(0) value = self._scale.get_value() max_ = self._scale.get_adjustment().get_upper() remaining = value - max_ self._elapsed_label.set_time(value) self._remaining_label.set_time(remaining) self._remaining_label.set_disabled(not player.seekable) self._elapsed_label.set_disabled(not player.seekable) self.set_sensitive(player.seekable) class SeekBarPlugin(EventPlugin): PLUGIN_ID = "SeekBar" PLUGIN_NAME = _("Alternative Seek Bar") PLUGIN_DESC = _("Alternative seek bar which is always visible and spans " "the whole window width.") PLUGIN_ICON = Icons.GO_JUMP def enabled(self): self._bar = SeekBar(app.player, app.librarian) self._bar.show() app.window.set_seekbar_widget(self._bar) def disabled(self): app.window.set_seekbar_widget(None) self._bar.destroy() del self._bar ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/seekpoints.py��������������������������������������������������0000644�0001750�0001750�00000012165�14267565021�021052� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _, app from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.songshelpers import has_bookmark from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.tracker import TimeTracker class SeekPointsPlugin(EventPlugin, PluginConfigMixin): """The plugin class.""" PLUGIN_ID = "Seekpoints" PLUGIN_NAME = _("Seekpoint Bookmarks") PLUGIN_ICON = Icons.GO_JUMP PLUGIN_CONFIG_SECTION = __name__ PLUGIN_DESC = _( "Store Seekpoints A and/or B for tracks. " "Skip to time A and stop after time B when track is played.\n\n" "ℹ Note that changing the names of the points below does not " "update the actual bookmark names, it only changes which " "bookmark names the plugin looks for when deciding whether to seek.") CFG_SEEKPOINT_A_TEXT = "A" CFG_SEEKPOINT_B_TEXT = "B" DEFAULT_A_TEXT = "A" DEFAULT_B_TEXT = "B" def enabled(self): self._seekpoint_A, self._seekpoint_B = self._get_seekpoints() self._tracker = TimeTracker(app.player) self._tracker.connect('tick', self._on_tick) def disabled(self): self._tracker.destroy() def plugin_on_song_started(self, song): """Seeks to point A if it exists, and also fetches the bookmarks of the current track that matches the seekpoint names set in config. """ self._seekpoint_A, self._seekpoint_B = self._get_seekpoints() if not self._seekpoint_A: return self._seek(self._seekpoint_A) def _on_tick(self, tracker): """Checks whether the current position is past point B if it exists, and if it is -- seek to the end of the track. """ if not self._seekpoint_B: return time = app.player.get_position() // 1000 if self._seekpoint_B <= time: self._seek(app.player.info("~#length")) def _get_seekpoints(self): """Reads seekpoint-names from config, which are compared to the bookmark-names of the current track to get timestamps (if any). """ if not app.player.song: return None, None marks = [] if has_bookmark(app.player.song): marks = app.player.song.bookmarks seekpoint_A = None seekpoint_B = None seekpoint_A_name = self.config_get(self.CFG_SEEKPOINT_A_TEXT, self.DEFAULT_A_TEXT) seekpoint_B_name = self.config_get(self.CFG_SEEKPOINT_B_TEXT, self.DEFAULT_B_TEXT) for time, mark in marks: if mark == seekpoint_A_name: seekpoint_A = time elif mark == seekpoint_B_name: seekpoint_B = time # if seekpoints are not properly ordered (or identical), the track # will likely endlessly seek when looping tracks, so discard B # (maybe raise an exception for the plugin list?). if (seekpoint_A is not None) and (seekpoint_B is not None): if seekpoint_A >= seekpoint_B: return seekpoint_A, None return seekpoint_A, seekpoint_B def _seek(self, seconds): app.player.seek(seconds * 1000) def PluginPreferences(self, parent): vb = Gtk.VBox(spacing=12) # Bookmark name to use for point A hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_SEEKPOINT_A_TEXT, self.DEFAULT_A_TEXT)) entry.connect('changed', self.config_entry_changed, self.CFG_SEEKPOINT_A_TEXT) lbl = Gtk.Label(label=_("Bookmark name for point A")) entry.set_tooltip_markup(_("Bookmark name to check for when " "a track is started, and if found the player seeks to that " "timestamp")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Bookmark name to use for point B hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_SEEKPOINT_B_TEXT, self.DEFAULT_B_TEXT)) entry.connect('changed', self.config_entry_changed, self.CFG_SEEKPOINT_B_TEXT) lbl = Gtk.Label(label=_("Bookmark name for point B")) entry.set_tooltip_markup(_("Bookmark name to use each tick during " "play of a track if it exist. If the current position exceeds " "the timestamp, seek to the end of the track.")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) return vb �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/squeezebox_sync.py���������������������������������������������0000664�0001750�0001750�00000006372�14231604332�022107� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011-2021 Nick Boultbee # # Inspired in parts by PySqueezeCenter (c) 2010 JingleManSweep # SqueezeCenter and SqueezeBox are copyright Logitech # # 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 2 of the License, or # (at your option) any later version. import os from quodlibet import _ from quodlibet import qltk, app from quodlibet.ext._shared.squeezebox.base import SqueezeboxPluginMixin from quodlibet.util.dprint import print_d from quodlibet.qltk import Icons from quodlibet.plugins.events import EventPlugin if os.name == "nt": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError class SqueezeboxSyncPlugin(EventPlugin, SqueezeboxPluginMixin): PLUGIN_ID = 'Squeezebox Output' PLUGIN_NAME = _('Squeezebox Sync') PLUGIN_DESC_MARKUP = ( _("Makes Logitech Squeezebox mirror Quod Libet output, " "provided both read from an identical library.") + "\n" + _("Shares configuration with <a href=\"%(plugin_link)s\">Export to " "Squeezebox plugin</a>.") % {"plugin_link": "quodlibet:///prefs/plugins/Export to Squeezebox Playlist"} ) PLUGIN_ICON = Icons.MEDIA_PLAYBACK_START server = None active = False _debug = False def __init__(self): super().__init__() @classmethod def post_reconnect(cls): cls.server.stop() SqueezeboxPluginMixin.post_reconnect() player = app.player cls.plugin_on_song_started(player.info) cls.plugin_on_seek(player.info, player.get_position()) def enabled(self): print_d("Debug is set to %s" % self._debug) self.active = True self.init_server() self.server.pause() if not self.server.is_connected: qltk.ErrorMessage( None, _("Error finding Squeezebox server"), _("Error finding %s. Please check settings") % self.server.config ).run() def disabled(self): # Stopping might be annoying in some situations, but seems more correct if self.server: self.server.stop() self.active = False @classmethod def plugin_on_song_started(cls, song): # Yucky hack to allow some form of immediacy on re-configuration cls.server._debug = cls._debug = cls.config_get_bool("debug", False) if cls._debug: print_d("Paused" if app.player.paused else "Not paused") if song and cls.server and cls.server.is_connected: path = cls.get_sb_path(song) print_d("Requesting to play %s..." % path) if app.player.paused: cls.server.change_song(path) else: cls.server.playlist_play(path) @classmethod def plugin_on_paused(cls): if cls.server: cls.server.pause() @classmethod def plugin_on_unpaused(cls): if cls.server: cls.server.unpause() @classmethod def plugin_on_seek(cls, song, msec): if not app.player.paused: if cls.server: cls.server.seek_to(msec) cls.server.play() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/stop_on_pause.py�����������������������������������������������0000664�0001750�0001750�00000006011�14244626671�021543� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2018 David Morris # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfigMixin from quodlibet.qltk import Icons from quodlibet.qltk.ccb import ConfigCheckButton class StopOnPause(EventPlugin, PluginConfigMixin): PLUGIN_ID = "StopOnPause" PLUGIN_NAME = _("Stop on Pause") PLUGIN_ICON = Icons.MEDIA_PLAYBACK_PAUSE PLUGIN_DESC = _("This plugin changes Pause to Stop/Play/Seek." "\n\n" "Useful if Quod Libet can't switch audio devices " "when a new one (Bluetooth speaker, USB DAC, etc.) " "is added to the system." "\n\n" "Ensures position in the current source is maintained " "so long as 'Only Seekable Sources' is off. " "Otherwise, playback is left stopped and must be restarted " "from the beginning.") _CFG_SEEKABLE_ONLY = 'seekable_only' __enabled = False __restarting = False def enabled(self): self.__enabled = True def disabled(self): self.__enabled = False def plugin_on_paused(self): if self.__enabled: if not self.__restarting: onlySeekable = self.config_get_bool(self._CFG_SEEKABLE_ONLY) if (onlySeekable and app.player.seekable): self.__restarting = True position = app.player.get_position() app.player.stop() app.player.seek(position) self.__restarting = False elif not onlySeekable: self.__restarting = True # Check if the stream is seekable before stopping! isSeekable = app.player.seekable position = app.player.get_position() app.player.stop() if isSeekable: app.player.seek(position) self.__restarting = False @classmethod def PluginPreferences(cls, window): # Plugin Options toggles = [ (cls._CFG_SEEKABLE_ONLY, _("Only Seekable Sources")), ] vb = Gtk.VBox(spacing=10) vb.set_border_width(0) vb2 = Gtk.VBox(spacing=6) for key, label in toggles: ccb = ConfigCheckButton(label, 'plugins', cls._config_key(key)) ccb.set_active(cls.config_get_bool(key)) vb2.pack_start(ccb, True, True, 0) frame = qltk.Frame(label=_("Plugin Options"), child=vb2) vb.pack_start(frame, False, True, 0) vb.show_all() return vb �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684387440.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/synchronize_to_device.py���������������������������������������0000755�0001750�0001750�00000134245�14431333160�023257� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Jan Korte # 2020 Daniel Petrescu # # 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 2 of the License, or # (at your option) any later version. import os import shutil import unicodedata from pathlib import Path from gi.repository import Gtk, Pango from senf import fsn2text from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet import get_user_dir from quodlibet import ngettext from quodlibet import qltk from quodlibet import util from quodlibet.pattern import FileFromPattern from quodlibet.plugins import PM from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.qltk.cbes import ComboBoxEntrySave from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk.views import HintedTreeView from quodlibet.query import Query from quodlibet.util import print_d, print_e, print_exc from quodlibet.util.enum import enum from quodlibet.util.path import strip_win32_incompat_from_path PLUGIN_CONFIG_SECTION = 'synchronize_to_device' class Entry: """ An entry in the tree of previewed export paths. """ @enum class Tags(str): """ Various tags that will be used in the output. """ EMPTY = '' PENDING_COPY = _('Pending copy') PENDING_DELETE = _('Pending delete') DELETE = _('delete') SKIP = _('Skip') SKIP_DUPLICATE = _('DUPLICATE') IN_PROGRESS_SYNC = _('Synchronizing') IN_PROGRESS_DELETE = _('Deleting') RESULT_SUCCESS = _('Success') RESULT_FAILURE = _('FAILURE') RESULT_SKIP_EXISTING = _('Skipped existing file') def __init__(self, song, export_path=None): self._song = song self.export_path = export_path or '' self.tag = self.Tags.EMPTY self._filename = None @property def filename(self): if self._song is not None: return fsn2text(self._song('~filename')) else: return self._filename @filename.setter def filename(self, name): if self._song is None: self._filename = name else: raise ValueError(_('Cannot set the filename of a song.')) class SyncToDevice(EventPlugin, PluginConfigMixin): PLUGIN_ICON = Icons.NETWORK_TRANSMIT PLUGIN_ID = PLUGIN_CONFIG_SECTION PLUGIN_NAME = _('Synchronize to Device') PLUGIN_DESC = _('Synchronizes all songs from the selected saved searches ' 'with the specified folder.') CONFIG_SECTION = PLUGIN_CONFIG_SECTION CONFIG_QUERY_PREFIX = 'query_' CONFIG_PATH_KEY = '{}_{}'.format(PLUGIN_CONFIG_SECTION, 'path') CONFIG_PATTERN_KEY = '{}_{}'.format(PLUGIN_CONFIG_SECTION, 'pattern') path_query = os.path.join(get_user_dir(), 'lists', 'queries.saved') path_pattern = os.path.join(get_user_dir(), 'lists', 'renamepatterns') spacing_main = 20 spacing_large = 6 spacing_small = 3 summary_sep = ' ' * 2 summary_sep_list = ',' + summary_sep default_export_pattern = os.path.join('<artist>', '<album>', '<title>') model_cols = {'entry': (0, object), 'tag': (1, str), 'filename': (2, str), 'export': (3, str)} def PluginPreferences(self, parent): # Check if the queries file exists if not os.path.exists(self.path_query): return self._no_queries_frame() # Read saved searches from file self.queries = {} with open(self.path_query, 'r', encoding='utf-8') as query_file: for query_string in query_file: name = next(query_file).strip() self.queries[name] = Query(query_string.strip()) if not self.queries: # query_file is empty return self._no_queries_frame() main_vbox = Gtk.VBox(spacing=self.spacing_main) self.main_vbox = main_vbox # Saved search selection frame saved_search_vbox = Gtk.VBox(spacing=self.spacing_large) self.saved_search_vbox = saved_search_vbox for query_name, query in self.queries.items(): query_config = self.CONFIG_QUERY_PREFIX + query_name check_button = ConfigCheckButton(query_name, PM.CONFIG_SECTION, self._config_key(query_config)) check_button.set_active(self.config_get_bool(query_config)) saved_search_vbox.pack_start(check_button, False, False, 0) saved_search_scroll = self._expandable_scroll(min_h=0, max_h=300) saved_search_scroll.add(saved_search_vbox) frame = qltk.Frame(label=_('Synchronize the following saved searches:'), child=saved_search_scroll) main_vbox.pack_start(frame, False, False, 0) # Destination path entry field destination_entry = Gtk.Entry( placeholder_text=_('The absolute path to your export location'), text=config.get(PM.CONFIG_SECTION, self.CONFIG_PATH_KEY, '') ) destination_entry.connect('changed', self._destination_path_changed) self.destination_entry = destination_entry # Destination path selection button destination_button = qltk.Button(label='', icon_name=Icons.FOLDER_OPEN) destination_button.connect('clicked', self._select_destination_path) # Destination path hbox destination_path_hbox = Gtk.HBox(spacing=self.spacing_small) destination_path_hbox.pack_start(destination_entry, True, True, 0) destination_path_hbox.pack_start(destination_button, False, False, 0) # Destination path information destination_warn_label = self._label_with_icon( _("All pre-existing files in the destination folder that aren't in " "the saved searches will be deleted."), Icons.DIALOG_WARNING) destination_info_label = self._label_with_icon( _('For devices mounted with MTP, export to a local destination ' 'folder, then transfer it to your device with rsync. ' 'Or, when syncing many files to an Android Device, use adb-sync, ' 'which is much faster.'), Icons.DIALOG_INFORMATION) # Destination path frame destination_vbox = Gtk.VBox(spacing=self.spacing_large) destination_vbox.pack_start(destination_path_hbox, False, False, 0) destination_vbox.pack_start(destination_warn_label, False, False, 0) destination_vbox.pack_start(destination_info_label, False, False, 0) frame = qltk.Frame(label=_('Destination path:'), child=destination_vbox) main_vbox.pack_start(frame, False, False, 0) # Export pattern frame export_pattern_combo = ComboBoxEntrySave( self.path_pattern, [self.default_export_pattern], title=_('Path Patterns'), edit_title=_(u'Edit saved patterns…')) export_pattern_combo.enable_clear_button() export_pattern_combo.show_all() export_pattern_entry = export_pattern_combo.get_child() export_pattern_entry.set_placeholder_text( _('The structure of the exported filenames, based on their tags')) export_pattern_entry.set_text(config.get(PM.CONFIG_SECTION, self.CONFIG_PATTERN_KEY, self.default_export_pattern)) export_pattern_entry.connect('changed', self._export_pattern_changed) self.export_pattern_entry = export_pattern_entry frame = qltk.Frame(label=_('Export pattern:'), child=export_pattern_combo) main_vbox.pack_start(frame, False, False, 0) # Start preview button preview_start_button = qltk.Button(label=_('Preview'), icon_name=Icons.VIEW_REFRESH) preview_start_button.set_visible(True) preview_start_button.connect('clicked', self._start_preview) self.preview_start_button = preview_start_button # Stop preview button preview_stop_button = qltk.Button(label=_('Stop preview'), icon_name=Icons.PROCESS_STOP) preview_stop_button.set_visible(False) preview_stop_button.set_no_show_all(True) preview_stop_button.connect('clicked', self._stop_preview) self.preview_stop_button = preview_stop_button # Details view column_types = [column[1] for column in self.model_cols.values()] self.model = Gtk.ListStore(*column_types) self.details_tree = details_tree = HintedTreeView(model=self.model) details_scroll = self._expandable_scroll() details_scroll.set_shadow_type(Gtk.ShadowType.IN) details_scroll.add(details_tree) self.renders = {} # Preview column: status render = Gtk.CellRendererText() column = self._tree_view_column(render, self._cdf_status, title=_('Status'), expand=False, sort=self._model_col_id('tag')) details_tree.append_column(column) # Preview column: file render = Gtk.CellRendererText() column = self._tree_view_column(render, self._cdf_source_path, title=_('Source File'), sort=self._model_col_id('filename')) details_tree.append_column(column) # Preview column: export path render = Gtk.CellRendererText() render.set_property('editable', True) render.connect('edited', self._row_edited) column = self._tree_view_column(render, self._cdf_export_path, title=_('Export Path'), sort=self._model_col_id('export')) details_tree.append_column(column) # Status labels self.status_operation = Gtk.Label(xalign=0.0, yalign=0.5, wrap=True, visible=False, no_show_all=True) self.status_progress = Gtk.Label(xalign=0.0, yalign=0.5, wrap=True, visible=False, no_show_all=True) self.status_duplicates = self._label_with_icon( _('Duplicate export paths detected! The export paths above can be ' 'edited before starting the synchronization.'), Icons.DIALOG_WARNING, visible=False) self.status_deletions = self._label_with_icon( _("Existing files in the destination path will be deleted (except " "files named 'cover.jpg')!"), Icons.DIALOG_WARNING, visible=False) # Section for previewing exported files preview_vbox = Gtk.VBox(spacing=self.spacing_large) preview_vbox.pack_start(preview_start_button, False, False, 0) preview_vbox.pack_start(preview_stop_button, False, False, 0) preview_vbox.pack_start(details_scroll, True, True, 0) preview_vbox.pack_start(self.status_operation, False, False, 0) preview_vbox.pack_start(self.status_progress, False, False, 0) preview_vbox.pack_start(self.status_duplicates, False, False, 0) preview_vbox.pack_start(self.status_deletions, False, False, 0) main_vbox.pack_start(preview_vbox, True, True, 0) # Start sync button sync_start_button = qltk.Button(label=_('Start synchronization'), icon_name=Icons.DOCUMENT_SAVE) sync_start_button.set_sensitive(False) sync_start_button.set_visible(True) sync_start_button.connect('clicked', self._start_sync) self.sync_start_button = sync_start_button # Stop sync button sync_stop_button = qltk.Button(label=_('Stop synchronization'), icon_name=Icons.PROCESS_STOP) sync_stop_button.set_visible(False) sync_stop_button.set_no_show_all(True) sync_stop_button.connect('clicked', self._stop_sync) self.sync_stop_button = sync_stop_button # Section for the sync buttons sync_vbox = Gtk.VBox(spacing=self.spacing_large) sync_vbox.pack_start(sync_start_button, False, False, 0) sync_vbox.pack_start(sync_stop_button, False, False, 0) main_vbox.pack_start(sync_vbox, False, False, 0) return main_vbox @staticmethod def _no_queries_frame(): """ Create a frame to use when there are no saved searches. :return: A new Frame. """ return qltk.Frame( _('No saved searches yet, create some and come back!')) def _expandable_scroll(self, min_h=50, max_h=-1, expand=True): """ Create a ScrolledWindow that expands as content is added. :param min_h: The minimum height of the window, in pixels. :param max_h: The maximum height of the window, in pixels. It will grow up to this height before it starts scrolling the content. :param expand: Whether the window should expand. :return: A new ScrolledWindow. """ return Gtk.ScrolledWindow(min_content_height=min_h, max_content_height=max_h, propagate_natural_height=expand) def _label_with_icon(self, text, icon_name, visible=True): """ Create a new label with an icon to the left of the text. :param text: The new text to set for the label. :param icon_name: An icon name or None. :return: A HBox containing an icon followed by a label. """ image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.BUTTON) label = Gtk.Label(label=text, xalign=0.0, yalign=0.5, wrap=True) hbox = Gtk.HBox(spacing=self.spacing_large) if not visible: hbox.set_visible(False) hbox.set_no_show_all(True) hbox.pack_start(image, False, False, 0) hbox.pack_start(label, True, True, 0) return hbox def _tree_view_column(self, render, cdf, title=None, sort=None, expand=True, resize=True, reorder=True): """ Create a new TreeViewColumn with the given properties. :param render: The A Gtk.CellRenderer of this cell. :param cdf: The Gtk.TreeCellDataFunc to use for updating content. :param title: The column's title. :param sort: The model column to use when sorting this column. :param expand: Whether the column width should automatically expand. :param resize: Whether the column can be resized. :param reorder: Whether the column can be reordered. :return: The new TreeViewColumn. """ tvc = Gtk.TreeViewColumn() tvc.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) tvc.set_expand(expand) tvc.set_resizable(resize) tvc.set_reorderable(reorder) if title: tvc.set_title(title) if resize: render.set_property('ellipsize', Pango.EllipsizeMode.END) if sort: tvc.set_sort_column_id(sort) tvc.set_cell_data_func(render, cdf) tvc.pack_start(render, True) self.renders[tvc] = render return tvc def _destination_path_changed(self, entry): """ Save the destination path to the global config when the path changes. :param entry: The destination path entry field. """ config.set(PM.CONFIG_SECTION, self.CONFIG_PATH_KEY, entry.get_text()) def _select_destination_path(self, button): """ Show a folder selection dialog to select the destination path from the file system. :param button: The destination path selection button. """ dialog = Gtk.FileChooserDialog( title=_('Choose destination path'), action=Gtk.FileChooserAction.SELECT_FOLDER, select_multiple=False, create_folders=True, local_only=False, show_hidden=True) dialog.add_buttons( _('_Cancel'), Gtk.ResponseType.CANCEL, _('_Save'), Gtk.ResponseType.OK ) dialog.set_default_response(Gtk.ResponseType.OK) # If there is an existing path in the entry field, # make that path the default destination_entry_text = self.destination_entry.get_text() if destination_entry_text != '': dialog.set_current_folder(destination_entry_text) # Show the dialog and get the selected path response = dialog.run() response_path = dialog.get_filename() # Close the dialog and save the selected path dialog.destroy() if response == Gtk.ResponseType.OK \ and response_path != destination_entry_text: self.destination_entry.set_text(response_path) def _export_pattern_changed(self, entry): """ Save the export pattern to the global config when the pattern changes. :param entry: The export pattern entry field. """ config.set(PM.CONFIG_SECTION, self.CONFIG_PATTERN_KEY, entry.get_text()) def _cdf_status(self, column, cell, model, iter_, data): """ Handle entering data into the "Status" column of the sync previews. """ cell.set_property('text', model[iter_][self._model_col_id('tag')]) def _cdf_source_path(self, column, cell, model, iter_, data): """ Handle entering data into the "File" column of the sync previews. """ cell.set_property('text', model[iter_][self._model_col_id('filename')]) def _cdf_export_path(self, column, cell, model, iter_, data): """ Handle entering data into the "Export" column of the sync previews. """ cell.set_property('text', model[iter_][self._model_col_id('export')]) def _row_edited(self, renderer, path, entered_path): """ Handle a manual edit of a previewed export path. :param renderer: The object which received the signal. :param path: The path identifying the edited cell. :param entered_path: The new path entered by the user. """ def _update_warnings(): """ Toggle the visibility of the status warning labels based on the song counts. """ if self.c_song_dupes == 0: self.status_duplicates.set_visible(False) else: self.status_duplicates.set_visible(True) if self.c_songs_delete == 0: self.status_deletions.set_visible(False) else: self.status_deletions.set_visible(True) def _make_duplicate(entry, old_unique): """ Mark the given entry as a duplicate. """ print_d(entry.filename) entry.tag = Entry.Tags.SKIP_DUPLICATE self.c_song_dupes += 1 if old_unique: self.c_songs_copy -= 1 _update_warnings() def _make_unique(entry, old_duplicate): """ Mark the given entry as a unique file. """ print_d(entry.filename) entry.tag = Entry.Tags.PENDING_COPY self.c_songs_copy += 1 if old_duplicate: self.c_song_dupes -= 1 _update_warnings() def _make_skip(entry, counter): """ Skip the given entry during synchronization. """ print_d(entry.filename) entry.tag = Entry.Tags.SKIP entry.export_path = '' return counter - 1 def _update_other_song(model, path, iter_, *data): """ Update a previewed path based on the current change. This is a callback function passed to Gtk.TreeModel.foreach() to iterate over the rows in a tree model. :return: True to stop iterating, False to continue. """ model_entry = model[path][self._model_col_id('entry')] if model_entry is entry \ or model_entry.tag == Entry.Tags.DELETE \ or model_entry.export_path == '': pass elif model_entry.export_path == entered_path \ and model_entry.tag == Entry.Tags.PENDING_COPY: _make_duplicate(model_entry, True) self._update_model_value(iter_, 'tag', model_entry.tag) elif model_entry.tag == Entry.Tags.SKIP_DUPLICATE \ and model_entry.export_path != entered_path \ and self._get_paths()[model_entry.export_path] == 1: _make_unique(model_entry, True) self._update_model_value(iter_, 'tag', model_entry.tag) return False path = Gtk.TreePath.new_from_string(path) entry = self.model[path][self._model_col_id('entry')] if entry.export_path != entered_path: old_path, new_path = {}, {} old_path['duplicate'] = entry.tag == Entry.Tags.SKIP_DUPLICATE old_path['delete'] = entry.tag == Entry.Tags.PENDING_DELETE old_path['empty'] = not entry.export_path and not old_path['delete'] old_path['unique'] = not (old_path['duplicate'] or old_path['delete'] or old_path['empty']) old_path_inv = {} for key, value in old_path.items(): old_path_inv.setdefault(value, []).append(key) previewed_paths = self._get_paths().keys() new_path['duplicate'] = entered_path in previewed_paths new_path['delete'] = entered_path.lower() == Entry.Tags.DELETE new_path['empty'] = not entered_path and not new_path['delete'] new_path['unique'] = not (new_path['duplicate'] or new_path['delete'] or new_path['empty']) new_path_inv = {} for key, value in new_path.items(): new_path_inv.setdefault(value, []).append(key) print_d(_('Export path changed from [{old_path}] to [{new_path}] ' 'for file [{filename}]').format( filename=entry.filename, old_path=' '.join(old_path_inv[True]), new_path=' '.join(new_path_inv[True]))) # If the old path was empty... if old_path['empty'] and new_path['empty']: pass elif old_path['empty'] and new_path['delete']: try: Path(entry.filename).relative_to(self.expanded_destination) entry.tag = Entry.Tags.PENDING_DELETE self.c_songs_delete += 1 _update_warnings() except ValueError: pass elif old_path['empty'] and new_path['duplicate']: _make_duplicate(entry, False) entry.export_path = entered_path elif old_path['empty'] and new_path['unique']: _make_unique(entry, False) entry.export_path = entered_path # If the old path was a deletion... elif old_path['delete'] and new_path['empty']: pass elif old_path['delete'] and new_path['delete']: self.c_songs_delete = _make_skip(entry, self.c_songs_delete) _update_warnings() elif old_path['delete'] and new_path['duplicate']: pass elif old_path['delete'] and new_path['unique']: pass # If the old path was a duplicate... elif old_path['duplicate'] and new_path['empty']: self.c_song_dupes = _make_skip(entry, self.c_song_dupes) self.model.foreach(_update_other_song) _update_warnings() elif old_path['duplicate'] and new_path['delete']: self.c_song_dupes = _make_skip(entry, self.c_song_dupes) self.model.foreach(_update_other_song) _update_warnings() elif old_path['duplicate'] and new_path['duplicate']: entry.export_path = entered_path elif old_path['duplicate'] and new_path['unique']: _make_unique(entry, True) entry.export_path = entered_path self.model.foreach(_update_other_song) # If the old path was unique... elif old_path['unique'] and new_path['empty']: self.c_songs_copy = _make_skip(entry, self.c_songs_copy) self.model.foreach(_update_other_song) _update_warnings() elif old_path['unique'] and new_path['delete']: self.c_songs_copy = _make_skip(entry, self.c_songs_copy) self.model.foreach(_update_other_song) _update_warnings() elif old_path['unique'] and new_path['duplicate']: _make_duplicate(entry, True) entry.export_path = entered_path elif old_path['unique'] and new_path['unique']: entry.export_path = entered_path self.model.foreach(_update_other_song) # Update the model and the summary field self.model.set_row(self.model.get_iter(path), self._make_model_row(entry)) self._update_preview_summary() def _update_model_value(self, iter_, column, value): """ Set the data in a since cell of the ListStore model. :param iter_: A Gtk.TreeIter for the row being modified. :param column: The name of the column to modify. :param value: The new value for the cell. """ self.model.set_value(iter_, self._model_col_id(column), value) def _model_col_id(self, name): """ Get the column ID from the given name. :param name: The column name to search for. :raises: KeyError if a column with the given name does not exist. """ return self.model_cols[name][0] @staticmethod def _make_model_row(entry): """ Create a new row to insert into the ListStore model. :param entry: The Entry to insert. """ return [entry, entry.tag, entry.filename, entry.export_path] @staticmethod def _run_pending_events(): """ Prevent the application from becoming unresponsive. """ while Gtk.events_pending(): Gtk.main_iteration() def _start_preview(self, button): """ Start the generation of export paths for all songs. :param button: The start preview button. """ print_d(_('Starting synchronization preview')) self.running = True # Summary labels self.status_operation.set_label( _('Synchronization preview in progress.')) self.status_operation.set_visible(True) self.status_progress.set_visible(False) self.status_duplicates.set_visible(False) self.status_deletions.set_visible(False) # Change button visibility self.preview_start_button.set_visible(False) self.preview_stop_button.set_visible(True) self.c_songs_copy = self.c_song_dupes = self.c_songs_delete = 0 if self._run_preview() is None: return self._stop_preview() self.sync_start_button.set_sensitive(True) print_d(_('Finished synchronization preview')) def _stop_preview(self, button=None): """ Stop the generation of export paths for all songs. :param button: The stop preview button. """ if button: print_d(_('Stopping synchronization preview')) self.status_operation.set_label( _('Synchronization preview was stopped.')) else: self.status_operation.set_label( _('Synchronization preview has finished.')) self.status_operation.set_visible(True) self.running = False # Change button visibility self.preview_start_button.set_visible(True) self.preview_stop_button.set_visible(False) self._update_preview_summary() def _run_preview(self): """ Show the export paths for all songs to be synchronized. :return: Whether the generation of preview paths was successful. """ destination_path, pattern = self._get_valid_inputs() if None in {destination_path, pattern}: return False self.expanded_destination = os.path.expanduser(destination_path) # Get a list containing all songs to export songs = self._get_songs_from_queries() if not songs: return False self.model.clear() export_paths = [] for song in songs: if not self.running: print_d(_('Stopped synchronization preview')) return None self._run_pending_events() if not self.destination_entry.get_text(): print_d(_('A different plugin was selected - stop preview')) return False export_path = self._get_export_path(song, destination_path, pattern) if not export_path: return False entry = Entry(song, export_path) expanded_path = os.path.expanduser(export_path) if expanded_path in export_paths: entry.tag = Entry.Tags.SKIP_DUPLICATE self.c_song_dupes += 1 else: entry.tag = Entry.Tags.PENDING_COPY self.c_songs_copy += 1 export_paths.append(expanded_path) self.model.append(row=self._make_model_row(entry)) # List files to delete for root, __, files in os.walk(self.expanded_destination): for name in files: file_path = os.path.join(root, name) if file_path not in export_paths and \ "cover.jpg" not in file_path: entry = Entry(None) entry.filename = file_path entry.tag = Entry.Tags.PENDING_DELETE self.model.append(row=self._make_model_row(entry)) self.c_songs_delete += 1 return True def _update_preview_summary(self): """ Update the preview summary text field. """ prefix = _('Synchronization will:') + self.summary_sep preview_progress = [] if self.c_songs_copy > 0: counter = self.c_songs_copy preview_progress.append( ngettext('attempt to write {count} file', 'attempt to write {count} files', counter).format(count=counter)) if self.c_song_dupes > 0: counter = self.c_song_dupes preview_progress.append( ngettext('skip {count} duplicate file', 'skip {count} duplicate files', counter).format(count=counter)) for child in self.status_duplicates.get_children(): child.set_visible(True) self.status_duplicates.set_visible(True) if self.c_songs_delete > 0: counter = self.c_songs_delete preview_progress.append( ngettext('delete {count} file', 'delete {count} files', counter).format(count=counter)) for child in self.status_deletions.get_children(): child.set_visible(True) self.status_deletions.set_visible(True) preview_progress_text = self.summary_sep_list.join(preview_progress) if preview_progress_text: preview_progress_text = prefix + preview_progress_text self.status_progress.set_label(preview_progress_text) self.status_progress.set_visible(True) print_d(preview_progress_text) def _get_paths(self): """ Build a list of all current export paths for the songs to be synchronized. """ paths = {} for row in self.model: entry = row[self._model_col_id('entry')] if entry.tag != Entry.Tags.PENDING_DELETE and entry.export_path: if entry.export_path not in paths.keys(): paths[entry.export_path] = 1 else: paths[entry.export_path] += 1 return paths def _show_sync_error(self, title, message): """ Show an error message whenever a synchronization error occurs. :param title: The title of the message popup. :param message: The error message. """ qltk.ErrorMessage(self.main_vbox, title, message).run() print_e(title) def _get_valid_inputs(self): """ Ensure that all user inputs have been given. Shows a popup error message if values are not as expected. :return: The entered destination path and an fsnative pattern, or None if an error occurred. """ # Get text from the destination path entry destination_path = self.destination_entry.get_text() if not destination_path: self._show_sync_error(_('No destination path provided'), _('Please specify the directory where songs ' 'should be exported.')) return None, None # Get text from the export pattern entry export_pattern = self.export_pattern_entry.get_text() if not export_pattern: self._show_sync_error(_('No export pattern provided'), _('Please specify an export pattern for the ' 'names of the exported songs.')) return None, None # Combine destination path and export pattern to form the full pattern full_export_path = os.path.join(destination_path, export_pattern) try: pattern = FileFromPattern(full_export_path) except ValueError: self._show_sync_error( _('Export path is not absolute'), _('The pattern\n\n{}\n\ncontains "/" but does not start ' 'from root. Please provide an absolute destination path by ' 'making sure it starts with / or ~/.') .format(util.bold(full_export_path))) return None, None return destination_path, pattern def _get_songs_from_queries(self): """ Build a list of songs to be synchronized, filtered using the selected saved searches. :return: A list of the selected songs. """ enabled_queries = [] for query_name, query in self.queries.items(): query_config = self.CONFIG_QUERY_PREFIX + query_name if self.config_get_bool(query_config): enabled_queries.append(query) if not enabled_queries: self._show_sync_error(_('No saved searches selected'), _('Please select at least one saved search.')) return [] selected_songs = [] for song in app.library.itervalues(): if any(query.search(song) for query in enabled_queries): selected_songs.append(song) if not selected_songs: self._show_sync_error(_('No songs in the selected saved searches'), _('All selected saved searches are empty.')) return [] print_d(_('Found {} songs to synchronize').format(len(selected_songs))) return selected_songs def _get_export_path(self, song, destination_path, export_pattern): """ Use the given pattern of song tags to build the destination path for a song. :param song: The song for which to build the export path. :param destination_path: The user-entered destination path. :param export_pattern: An fsnative file path pattern. :return: A safe full destination path for the song. """ new_name = Path(export_pattern.format(song)) try: relative_name = new_name.relative_to(self.expanded_destination) except ValueError as ex: self._show_sync_error( _('Mismatch between destination path and export ' 'pattern'), _('The export pattern starts with a path that ' 'differs from the destination path. Please ' 'correct the pattern.\n\nError:\n{}').format(ex)) return None return os.path.join(destination_path, self._make_safe_name(relative_name)) def _make_safe_name(self, input_path): """ Make a file path safe by replacing unsafe characters. :param input_path: A relative Path. :return: The given path, with any unsafe characters replaced. Returned as a string. """ # Remove diacritics (accents) safe_filename = unicodedata.normalize('NFKD', str(input_path)) safe_filename = u''.join( [c for c in safe_filename if not unicodedata.combining(c)]) if os.name != "nt": # Ensure that Win32-incompatible chars are always removed. # On Windows, this is called during `FileFromPattern`. safe_filename = strip_win32_incompat_from_path(safe_filename) return safe_filename def _start_sync(self, button): """ Start the song synchronization. :param button: The start sync button. """ # Check sort column sort_columns = [c.get_title() for c in self.details_tree.get_columns() if c.get_sort_indicator()] if 'Status' in sort_columns: self._show_sync_error(_('Unable to sync'), _('Cannot start synchronization while ' 'sorting by <b>Status</b>.')) return print_d(_('Starting song synchronization')) self.running = True # Summary labels self.status_operation.set_label(_('Synchronization in progress.')) self.status_duplicates.set_visible(False) self.status_deletions.set_visible(False) # Change button visibility self.sync_start_button.set_visible(False) self.sync_stop_button.set_visible(True) if not self._run_sync(): return self._stop_sync() print_d(_('Finished song synchronization')) def _stop_sync(self, button=None): """ Stop the song synchronization. :param button: The stop sync button. """ if button: print_d(_('Stopping song synchronization')) self.status_operation.set_label(_('Synchronization was stopped.')) else: self.status_operation.set_label(_('Synchronization has finished.')) self.running = False # Change button visibility self.sync_start_button.set_visible(True) self.sync_stop_button.set_visible(False) def _run_sync(self): """ Synchronize the songs from the selected saved searches with the specified folder. :return: Whether the synchronization was successful. """ self.c_files_copy = self.c_files_skip = self.c_files_skip_previous \ = self.c_files_dupes = self.c_files_delete = self.c_files_failed = 0 self.model.foreach(self._sync_entry) if not self.running: return False self._remove_empty_dirs() return True def _sync_entry(self, model, path, iter_, *data): """ Synchronize a single song. This is a callback function passed to Gtk.TreeModel.foreach() to iterate over the rows in a tree model. :return: True to stop iterating, False to continue. """ entry = model[path][self._model_col_id('entry')] if not self.running: print_d(_('Stopped song synchronization')) return True self._run_pending_events() if not self.destination_entry.get_text(): print_d(_('A different plugin was selected - stop synchronization')) return True print_d(_('{tag} - "{filename}"').format(tag=entry.tag, filename=entry.filename)) if not entry.export_path and not entry.tag: return False if entry.tag == Entry.Tags.PENDING_COPY: # Export, skipping existing files expanded_path = os.path.expanduser(entry.export_path) if os.path.exists(expanded_path): entry.tag = Entry.Tags.RESULT_SKIP_EXISTING self._update_model_value(iter_, 'tag', entry.tag) self.c_files_skip += 1 else: entry.tag = Entry.Tags.IN_PROGRESS_SYNC self._update_model_value(iter_, 'tag', entry.tag) song_folders = os.path.dirname(expanded_path) os.makedirs(song_folders, exist_ok=True) try: shutil.copyfile(entry.filename, expanded_path) except Exception as ex: entry.tag = Entry.Tags.RESULT_FAILURE + ': ' + str(ex) self._update_model_value(iter_, 'tag', entry.tag) print_exc() self.c_files_failed += 1 else: entry.tag = Entry.Tags.RESULT_SUCCESS self._update_model_value(iter_, 'tag', entry.tag) self.c_files_copy += 1 elif entry.tag == Entry.Tags.SKIP_DUPLICATE: self.c_files_dupes += 1 elif entry.tag == Entry.Tags.PENDING_DELETE: # Delete file try: entry.tag = Entry.Tags.IN_PROGRESS_DELETE self._update_model_value(iter_, 'tag', entry.tag) os.remove(entry.filename) except Exception as ex: entry.tag = Entry.Tags.RESULT_FAILURE + ': ' + str(ex) self._update_model_value(iter_, 'tag', entry.tag) print_exc() self.c_files_failed += 1 else: entry.tag = Entry.Tags.RESULT_SUCCESS self._update_model_value(iter_, 'tag', entry.tag) self.c_files_delete += 1 else: self.c_files_skip_previous += 1 self._update_sync_summary() return False def _remove_empty_dirs(self): """ Delete all empty sub-directories from the given path. """ for root, dirs, files in os.walk(self.expanded_destination, topdown=False): for dirname in dirs: dir_path = os.path.realpath(os.path.join(root, dirname)) last_file_is_cover = files and files[0] == 'cover.jpg' if not files or last_file_is_cover: entry = Entry(None) entry.filename = dir_path entry.tag = Entry.Tags.IN_PROGRESS_DELETE iter_ = self.model.append(row=self._make_model_row(entry)) print_d(_('Removing "{}"').format(entry.filename)) self.c_songs_delete += 1 try: if last_file_is_cover: os.remove(os.path.join(dir_path, files[0])) os.rmdir(dir_path) except Exception as ex: entry.tag = Entry.Tags.RESULT_FAILURE + ': ' + str(ex) self._update_model_value(iter_, 'tag', entry.tag) print_exc() self.c_files_failed += 1 else: entry.tag = Entry.Tags.RESULT_SUCCESS self._update_model_value(iter_, 'tag', entry.tag) self.c_files_delete += 1 self._update_sync_summary() def _update_sync_summary(self): """ Update the synchronization summary text field. """ sync_summary_prefix = _('Synchronization has:') + self.summary_sep sync_summary = [] if self.c_files_copy > 0 or self.c_files_skip > 0: text = [] counter = self.c_files_copy text.append( ngettext('written {count}/{total} file', 'written {count}/{total} files', counter).format(count=counter, total=self.c_songs_copy)) if self.c_files_skip > 0: counter = self.c_files_skip text.append( ngettext('(skipped {count} existing file)', '(skipped {count} existing files)', counter).format(count=counter)) sync_summary.append(self.summary_sep.join(text)) if self.c_files_dupes > 0: counter = self.c_files_dupes sync_summary.append( ngettext('skipped {count}/{total} duplicate file', 'skipped {count}/{total} duplicate files', counter).format(count=counter, total=self.c_song_dupes)) if self.c_files_delete > 0: counter = self.c_files_delete sync_summary.append( ngettext('deleted {count}/{total} file', 'deleted {count}/{total} files', counter).format(count=counter, total=self.c_songs_delete)) if self.c_files_failed > 0: counter = self.c_files_failed sync_summary.append( ngettext('failed to sync {count} file', 'failed to sync {count} files', counter).format(count=counter)) if self.c_files_skip_previous > 0: counter = self.c_files_skip_previous sync_summary.append( ngettext('skipped {count} file synchronized previously', 'skipped {count} files synchronized previously', counter).format(count=counter)) sync_summary_text = self.summary_sep_list.join(sync_summary) sync_summary_text = sync_summary_prefix + sync_summary_text self.status_progress.set_label(sync_summary_text) print_d(sync_summary_text) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/synchronizedlyrics.py������������������������������������������0000644�0001750�0001750�00000025207�14327505043�022627� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Synchronized Lyrics: a Quod Libet plugin for showing synchronized lyrics. # Copyright (C) 2015 elfalem # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import functools import os import re from os.path import splitext from typing import List, Tuple, Optional from gi.repository import Gtk, Gdk, GLib from quodlibet import _, util from quodlibet import app from quodlibet import qltk from quodlibet.formats import AudioFile from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.util.dprint import print_d class SynchronizedLyrics(EventPlugin, PluginConfigMixin): PLUGIN_ID = 'SynchronizedLyrics' PLUGIN_NAME = _('Synchronized Lyrics') PLUGIN_DESC = _('Shows synchronized lyrics from an .lrc file ' 'with same name as the track (or similar).') PLUGIN_ICON = Icons.FORMAT_JUSTIFY_FILL SYNC_PERIOD = 10000 DEFAULT_BGCOLOR = '#343428282C2C' DEFAULT_TXTCOLOR = '#FFFFFFFFFFFF' DEFAULT_FONTSIZE = 25 CFG_BGCOLOR_KEY = "backgroundColor" CFG_TXTCOLOR_KEY = "textColor" CFG_FONTSIZE_KEY = "fontSize" # Note the trimming of whitespace, seems "most correct" behaviour LINE_REGEX = re.compile(r"\s*\[([0-9]+:[0-9.]*)]\s*(.+)\s*") def __init__(self) -> None: super().__init__() self._lines: List[Tuple[int, str]] = [] self._timers: List[Tuple[int, int]] = [] self._start_clearing_from = 0 self.textview = None self.scrolled_window = None @classmethod def PluginPreferences(cls, window): vb = Gtk.VBox(spacing=6) vb.set_border_width(6) t = Gtk.Table(n_rows=5, n_columns=2, homogeneous=True) t.set_col_spacings(6) t.set_row_spacings(3) clr_section = Gtk.Label() clr_section.set_markup(util.bold(_("Colors"))) t.attach(clr_section, 0, 2, 0, 1) l = Gtk.Label(label=_("Text:")) l.set_alignment(xalign=1.0, yalign=0.5) t.attach(l, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) c = Gdk.RGBA() c.parse(cls._get_text_color()) b = Gtk.ColorButton(rgba=c) t.attach(b, 1, 2, 1, 2) b.connect('color-set', cls._set_text_color) l = Gtk.Label(label=_("Background:")) l.set_alignment(xalign=1.0, yalign=0.5) t.attach(l, 0, 1, 2, 3, xoptions=Gtk.AttachOptions.FILL) c = Gdk.RGBA() c.parse(cls._get_background_color()) b = Gtk.ColorButton(rgba=c) t.attach(b, 1, 2, 2, 3) b.connect('color-set', cls._set_background_color) font_section = Gtk.Label() font_section.set_markup(util.bold(_("Font"))) t.attach(font_section, 0, 2, 3, 4) l = Gtk.Label(label=_("Size (px):")) l.set_alignment(xalign=1.0, yalign=0.5) t.attach(l, 0, 1, 4, 5, xoptions=Gtk.AttachOptions.FILL) a = Gtk.Adjustment.new(cls._get_font_size(), 10, 72, 2, 3, 0) s = Gtk.SpinButton(adjustment=a) s.set_numeric(True) s.set_text(str(cls._get_font_size())) t.attach(s, 1, 2, 4, 5) s.connect('value-changed', cls._set_font_size) vb.pack_start(t, False, False, 0) return vb @classmethod def _get_text_color(cls): v = cls.config_get(cls.CFG_TXTCOLOR_KEY, cls.DEFAULT_TXTCOLOR) return v[:3] + v[5:7] + v[9:11] @classmethod def _get_background_color(cls): v = cls.config_get(cls.CFG_BGCOLOR_KEY, cls.DEFAULT_BGCOLOR) return v[:3] + v[5:7] + v[9:11] @classmethod def _get_font_size(cls): return int(cls.config_get(cls.CFG_FONTSIZE_KEY, cls.DEFAULT_FONTSIZE)) def _set_text_color(self, button): self.config_set(self.CFG_TXTCOLOR_KEY, button.get_color().to_string()) self._style_lyrics_window() def _set_background_color(self, button): self.config_set(self.CFG_BGCOLOR_KEY, button.get_color().to_string()) self._style_lyrics_window() def _set_font_size(self, button): self.config_set(self.CFG_FONTSIZE_KEY, button.get_value_as_int()) self._style_lyrics_window() def enabled(self): self.scrolled_window = Gtk.ScrolledWindow() self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolled_window.get_vadjustment().set_value(0) self.textview = Gtk.TextView() self.textview.set_editable(False) self.textview.set_cursor_visible(False) self.textview.set_wrap_mode(Gtk.WrapMode.WORD) self.textview.set_justification(Gtk.Justification.CENTER) self.scrolled_window.add_with_viewport(self.textview) vb = Gtk.HBox() vb.pack_start(self.scrolled_window, True, True, 6) vb.show_all() app.window.get_child().pack_start(vb, False, True, 0) app.window.get_child().reorder_child(vb, 2) self._style_lyrics_window() self.scrolled_window.show() self._sync_timer = GLib.timeout_add(self.SYNC_PERIOD, self._sync) self._build_data(app.player.song) self._timer_control() def disabled(self): self._clear_timers() GLib.source_remove(self._sync_timer) self.textview.destroy() self.textview = None self.scrolled_window.destroy() self.scrolled_window = None def _style_lyrics_window(self): if self.scrolled_window is None: return self.scrolled_window.set_size_request(-1, 1.5 * self._get_font_size()) qltk.add_css(self.textview, f""" * {{ background-color: {self._get_background_color()}; color: {self._get_text_color()}; font-size: {self._get_font_size()}px; padding: 0.25rem; border-radius: 6px; }} """) def _cur_position(self): return app.player.get_position() @functools.lru_cache() def _build_data(self, song: Optional[AudioFile]) -> List[Tuple[int, str]]: if self.textview: self.textview.get_buffer().set_text("") if song: # check in same location as track track_name = splitext(song("~basename") or "")[0] dir_ = song("~dirname") print_d(f"Looking for .lrc files in {dir_}") for filename in [f"{s}.lrc" for s in { track_name, track_name.lower(), track_name.upper(), song("~artist~title"), song("~artist~tracknumber~title"), song("~tracknumber~title") } ]: print_d(f"Looking for {filename!r}") try: with open(os.path.join(dir_, filename), 'r', encoding="utf-8") as f: print_d(f"Found lyrics file: {filename}") contents = f.read() except FileNotFoundError: continue return self._parse_lrc(contents) print_d(f"No lyrics found for {track_name!r}") return [] def _parse_lrc(self, contents: str) -> List[Tuple[int, str]]: data = [] for line in contents.splitlines(): match = self.LINE_REGEX.match(line) if not match: continue timing, text = match.groups() minutes, seconds = (float(p) for p in timing.split(":", 1)) timestamp = int(1000 * (minutes * 60 + seconds)) data.append((timestamp, text)) return sorted(data) def _set_timers(self): if not self._timers: print_d("Setting timers") cur_time = self._cur_position() cur_idx = self._greater(self._lines, cur_time) if cur_idx != -1: while (cur_idx < len(self._lines) and self._lines[cur_idx][0] < cur_time + self.SYNC_PERIOD): timestamp = self._lines[cur_idx][0] line = self._lines[cur_idx][1] tid = GLib.timeout_add(timestamp - cur_time, self._show, line) self._timers.append((timestamp, tid)) cur_idx += 1 def _sync(self): if not app.player.paused: self._clear_timers() self._set_timers() return True def _timer_control(self): if app.player.paused: self._clear_timers() else: self._set_timers() return False def _clear_timers(self): for ts, tid in self._timers[self._start_clearing_from:]: GLib.source_remove(tid) self._timers = [] self._start_clearing_from = 0 def _show(self, line) -> bool: if self.textview: self.textview.get_buffer().set_text(line) self._start_clearing_from += 1 print_d(f"♪ {line.strip()} ♪") return False def plugin_on_song_started(self, song: AudioFile) -> None: if song: print_d(f"Preparing for {song.key}") self._clear_timers() self._lines = self._build_data(song) # delay so that current position is for current track, not previous one GLib.timeout_add(5, self._timer_control) def plugin_on_song_ended(self, song, stopped): self._clear_timers() def plugin_on_paused(self): self._timer_control() def plugin_on_unpaused(self): self._timer_control() def plugin_on_seek(self, song, msec): if not app.player.paused: self._clear_timers() self._set_timers() def _greater(self, array, probe): length = len(array) if length == 0: return -1 elif probe < array[0][0]: return 0 elif probe >= array[length - 1][0]: return length else: return self._search(array, probe, 0, length - 1) def _search(self, array, probe, lower, upper): if lower == upper: if array[lower][0] <= probe: return lower + 1 else: return lower else: middle = int((lower + upper) / 2) if array[middle][0] <= probe: return self._search(array, probe, middle + 1, upper) else: return self._search(array, probe, lower, middle) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/telepathy_status.py��������������������������������������������0000644�0001750�0001750�00000014263�14327505043�022264� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Quod Libet Telepathy Plugin # Copyright 2012 Christoph Reiter # 2012,2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import sys if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError from gi.repository import GLib from gi.repository import Gio from gi.repository import Gtk from quodlibet import _ from quodlibet.pattern import Pattern from quodlibet.qltk.entry import UndoEntry from quodlibet import util from quodlibet import qltk from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import PluginConfigMixin from quodlibet.util.dprint import print_d from quodlibet.qltk import Icons AM_PATH = "/org/freedesktop/Telepathy/AccountManager" AM_NAME = "org.freedesktop.Telepathy.AccountManager" AM_IFACE = "org.freedesktop.Telepathy.AccountManager" AC_IFACE = "org.freedesktop.Telepathy.Account" PROPS_IFACE = "org.freedesktop.DBus.Properties" CONN_PRESENCE_TYPE_AVAILABLE = 2 def is_valid_presence_type(x): return x not in [0, 7, 8] def get_active_account_paths(): bus_iface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, AM_NAME, AM_PATH, PROPS_IFACE, None) return bus_iface.Get('(ss)', AM_IFACE, "ValidAccounts") def set_accounts_requested_presence(paths, message): bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) for path in paths: bus_iface = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, AM_NAME, path, PROPS_IFACE, None) presence_type, status = bus_iface.Get( '(ss)', AC_IFACE, "CurrentPresence")[:2] if not is_valid_presence_type(presence_type): presence_type = CONN_PRESENCE_TYPE_AVAILABLE value = GLib.Variant('(uss)', (presence_type, status, message)) bus_iface.Set('(ssv)', AC_IFACE, "RequestedPresence", value) class TelepathyStatusPlugin(EventPlugin, PluginConfigMixin): PLUGIN_ID = "Telepathy Status" PLUGIN_NAME = _("Telepathy Status Messages") PLUGIN_DESC = _("Updates all Telepathy-based IM accounts (as configured " "in Empathy etc) with a status message based on current " "song.") PLUGIN_ICON = Icons.FACE_SMILE DEFAULT_PAT = "♫ <~artist~title> ♫" DEFAULT_PAT_PAUSED = "<~artist~title> [%s]" % _("paused") CFG_STATUS_SONGLESS = 'no_song_text' CFG_LEAVE_STATUS = "leave_status" CFG_PAT_PLAYING = "playing_pattern" CFG_PAT_PAUSED = "paused_pattern" def _set_status(self, text): print_d("Setting status to \"%s\"..." % text) self.status = text try: accounts = get_active_account_paths() # TODO: account filtering set_accounts_requested_presence(accounts, text) except GLib.Error: print_d("...but setting failed") util.print_exc() def plugin_on_song_started(self, song): self.song = song pat_str = self.config_get(self.CFG_PAT_PLAYING, self.DEFAULT_PAT) pattern = Pattern(pat_str) status = (pattern.format(song) if song else self.config_get(self.CFG_STATUS_SONGLESS, "")) self._set_status(status) def plugin_on_paused(self): pat_str = self.config_get(self.CFG_PAT_PAUSED, self.DEFAULT_PAT_PAUSED) pattern = Pattern(pat_str) self.status = pattern.format(self.song) if self.song else "" self._set_status(self.status) def plugin_on_unpaused(self): self.plugin_on_song_started(self.song) def disabled(self): if self.status: self._set_status(self.config_get(self.CFG_STATUS_SONGLESS)) def enabled(self): self.song = None self.status = "" def PluginPreferences(self, parent): outer_vb = Gtk.VBox(spacing=12) vb = Gtk.VBox(spacing=12) # Playing hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_PAT_PLAYING, self.DEFAULT_PAT)) entry.connect('changed', self.config_entry_changed, self.CFG_PAT_PLAYING) lbl = Gtk.Label(label=_("Playing:")) entry.set_tooltip_markup(_("Status text when a song is started. " "Accepts QL Patterns e.g. %s") % util.monospace("<~artist~title>")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Paused hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_PAT_PAUSED, self.DEFAULT_PAT_PAUSED)) entry.connect('changed', self.config_entry_changed, self.CFG_PAT_PAUSED) lbl = Gtk.Label(label=_("Paused:")) entry.set_tooltip_markup(_("Status text when a song is paused. " "Accepts QL Patterns e.g. %s") % util.monospace("<~artist~title>")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # No Song hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_STATUS_SONGLESS, "")) entry.connect('changed', self.config_entry_changed, self.CFG_STATUS_SONGLESS) entry.set_tooltip_text( _("Plain text for status when there is no current song")) lbl = Gtk.Label(label=_("No song:")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Frame frame = qltk.Frame(_("Status Patterns"), child=vb) outer_vb.pack_start(frame, False, True, 0) return outer_vb ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/themeswitcher.py�����������������������������������������������0000644�0001750�0001750�00000012174�14267565021�021541� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import warnings import os from gi.repository import Gtk, Gio, GLib from quodlibet import _ from quodlibet import qltk from quodlibet import config from quodlibet.qltk import Icons from quodlibet.util.path import get_home_dir, xdg_get_system_data_dirs from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.plugins.events import EventPlugin class ThemeSwitcher(EventPlugin): PLUGIN_ID = "Theme Switcher" PLUGIN_NAME = _("Theme Switcher") PLUGIN_DESC = _("Changes the active GTK+ theme.") PLUGIN_ICON = Icons.PREFERENCES_DESKTOP_THEME __enabled = False __defaults = False CONFIG_THEME = PLUGIN_ID + "_theme" CONFIG_DARK = PLUGIN_ID + "_prefer_dark" def __init_defaults(self): if self.__defaults: return self.__defaults = True settings = Gtk.Settings.get_default() self.__default_theme = settings.get_property('gtk-theme-name') self.__default_dark = settings.get_property( 'gtk-application-prefer-dark-theme') def PluginPreferences(self, *args): self.__init_defaults() hb = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("_Theme:")) combo = Gtk.ComboBoxText() theme = config.get("plugins", self.CONFIG_THEME, None) combo.append_text(_("Default Theme")) themes = self.__get_themes() select = 0 for i, name in enumerate(sorted(themes)): combo.append_text(name) if name == theme: select = i + 1 combo.set_active(select) combo.connect('changed', self.__changed) dark_button = ConfigCheckButton( _("Prefer dark theme version"), "plugins", self.CONFIG_DARK, populate=True, default=self.__get_dark()) def dark_cb(button): self.__set_dark(button.get_active()) dark_button.connect('toggled', dark_cb) label.set_mnemonic_widget(combo) label.set_use_underline(True) hb.pack_start(label, False, True, 0) hb.pack_start(combo, False, True, 0) vbox = Gtk.VBox(spacing=6) vbox.pack_start(hb, False, True, 0) vbox.pack_start(dark_button, False, True, 0) return qltk.Frame(_("Preferences"), child=vbox) def __changed(self, combo): index = combo.get_active() name = (index and combo.get_active_text()) or "" config.set("plugins", self.CONFIG_THEME, name) self.__set_theme(name) def __get_themes(self): # deprecated, but there is no public replacement with warnings.catch_warnings(): warnings.simplefilter("ignore") theme_dir = Gtk.rc_get_theme_dir() theme_dirs = [theme_dir, os.path.join(get_home_dir(), ".themes")] theme_dirs += [ os.path.join(d, "themes") for d in xdg_get_system_data_dirs()] def is_valid_teme_dir(path): """If the path contains a theme for the running gtk version""" major = qltk.gtk_version[0] minor = qltk.gtk_version[1] names = ["gtk-%d.%d" % (major, m) for m in range(minor, -1, -1)] for name in names: if os.path.isdir(os.path.join(path, name)): return True return False themes = set() for theme_dir in set(theme_dirs): try: subdirs = os.listdir(theme_dir) except OSError: continue for dir_ in subdirs: if is_valid_teme_dir(os.path.join(theme_dir, dir_)): themes.add(dir_) try: resource_themes = Gio.resources_enumerate_children( "/org/gtk/libgtk/theme", 0) except GLib.GError: pass else: themes.update([t.rstrip("/") for t in resource_themes]) return themes def __set_theme(self, name): if not self.__enabled: return settings = Gtk.Settings.get_default() themes = self.__get_themes() name = ((name in themes) and name) or self.__default_theme settings.set_property('gtk-theme-name', name) def __set_dark(self, value): if not self.__enabled: return settings = Gtk.Settings.get_default() if value is None: value = self.__default_dark settings.set_property('gtk-application-prefer-dark-theme', value) def __get_dark(self): return config.getboolean( "plugins", self.CONFIG_DARK, self.__default_dark) def enabled(self): self.__enabled = True self.__init_defaults() theme = config.get("plugins", self.CONFIG_THEME, None) self.__set_theme(theme) self.__set_dark(self.__get_dark()) def disabled(self): self.__set_theme(None) self.__set_dark(None) self.__enabled = False ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/thumbrating.py�������������������������������������������������0000644�0001750�0001750�00000013136�14327505043�021204� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2018 Eoin O'Neill (eoinoneill1991@gmail.com) # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _, util from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons, ToggleButton from quodlibet.plugins.gui import UserInterfacePlugin class RatingBox(Gtk.VBox): def __init__(self): super().__init__(self) self.thumb_ups = 1 self.thumb_downs = 1 self.title = Gtk.Label("") self.title.set_line_wrap(True) self.title.set_lines(2) hbox = Gtk.HBox() self.upvote = ToggleButton("👍") self.downvote = ToggleButton("👎") self.upvote.connect("toggled", self.__thumb_toggled) self.downvote.connect("toggled", self.__thumb_toggled) self.score_label = Gtk.Label("----") self.upvote.set_property("height-request", 50) self.downvote.set_property("height-request", 50) hbox.pack_start(self.upvote, True, True, 5) hbox.pack_start(self.downvote, True, True, 5) self.hbox = hbox self.pack_start(self.title, False, False, 10) self.pack_start(self.score_label, True, True, 5) self.pack_start(self.hbox, False, False, 5) def set_current_title(self, title): self.title.set_text(title) def set_current_score(self, cth_up, cth_down): self.thumb_ups = cth_up self.thumb_downs = cth_down self.__set_pending_score_value(self.thumb_ups - self.thumb_downs) def poll_vote(self, reset=True): upward = 1 if self.upvote.get_active() else 0 downward = 1 if self.downvote.get_active() else 0 vote = (upward, downward) if reset: self.downvote.set_active(False) self.upvote.set_active(False) return vote def __set_pending_score_value(self, score): existing_score = self.thumb_ups - self.thumb_downs if score == existing_score: self.score_label.set_markup(util.bold(str(int(score)))) elif score > existing_score: self.score_label.set_markup("<b><span foreground=\"green\">" + str(int(score)) + "</span></b>") else: self.score_label.set_markup("<b><span foreground=\"red\">" + str(int(score)) + "</span></b>") def __thumb_toggled(self, button): if button.get_active(): if button == self.upvote: self.downvote.set_active(False) elif button == self.downvote: self.upvote.set_active(False) vote = self.poll_vote(False) self.__set_pending_score_value( self.thumb_ups + vote[0] - self.thumb_downs - vote[1]) class ThumbRating(EventPlugin, UserInterfacePlugin): """ Plugin for more hands off rating system using a thumb up / thumbdown system. """ PLUGIN_ID = 'Thumb Rating' PLUGIN_NAME = _('Thumb Rating') PLUGIN_DESC_MARKUP = _('Adds a thumb-up / thumb-down scoring system ' 'which is converted to a rating value. Useful ' 'for keeping running vote totals and sorting by ' '<b><tt>~#score</tt></b>.') PLUGIN_ICON = Icons.USER_BOOKMARKS # Threshold value where points should be recalculated score_point_threshold = 0.2 def enabled(self): self.rating_box = RatingBox() def create_sidebar(self): vbox = Gtk.VBox() vbox.pack_start(self.rating_box, False, False, 0) vbox.show_all() return vbox def disabled(self): self.rating_box.destroy() def plugin_on_song_ended(self, song, stopped): if song is not None: poll = self.rating_box.poll_vote() if poll[0] >= 1 or poll[1] >= 1: ups = int(song.get("~#wins") or 0) downs = int(song.get("~#losses") or 0) ups += poll[0] downs += poll[1] song["~#wins"] = ups song["~#losses"] = downs song["~#rating"] = ups / max((ups + downs), 2) # note: ^^^ Look into implementing w/ confidence intervals! song["~#score"] = ups - downs def plugin_on_song_started(self, song): if song is not None: ups = int(song("~#wins") or 0) downs = int(song("~#losses") or 0) # Handle case where there's no score but user has a defined rating. if (ups + downs == 0) and (song.get("~#rating")): percent = song["~#rating"] ups = int(percent * 10) downs = int((1.0 - percent) * 10.0) song["~#wins"] = ups song["~#losses"] = downs elif song.get("~#rating") and \ abs((ups / max((ups + downs), 2)) - song["~#rating"]) > \ self.score_point_threshold: # Cases where rating and points are not in alignment. total = max(ups + downs, 10) percent = song["~#rating"] ups = int(percent * total) downs = int((1.0 - percent) * total) song["~#wins"] = ups song["~#losses"] = downs self.rating_box.set_current_score(ups, downs) self.rating_box.set_current_title(song("~artist~title")) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/toggle_menu.py�������������������������������������������������0000664�0001750�0001750�00000003610�14035600052�021153� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gdk from quodlibet import _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons class ToggleMenuBarPlugin(EventPlugin): PLUGIN_ID = "ToggleMenuBar" PLUGIN_NAME = _("Toggle Menu Bar") PLUGIN_DESC = _("Toggle the menu bar by pressing the Alt key.") PLUGIN_ICON = Icons.EDIT def enabled(self): window = app.window # Maybe this should be made directly accessible self._menubar = window.get_children()[0].get_children()[0] # Initially set hidden self._menubar.set_visible(False) # Menu bar visibility toggle def toggle_menubar(widget, event): if event.keyval in (Gdk.KEY_Alt_L, Gdk.KEY_Alt_R): self._menubar.set_visible(not self._menubar.get_visible()) # Select the menu bar if visible if self._menubar.get_visible(): self._menubar.select_first(False) self._menubar.deselect() self._key_release_handler = \ window.connect('key_release_event', toggle_menubar) # Menu bar hide after deactivation def hide_menubar(widget): self._menubar.set_visible(False) self._deactivate_handler = \ self._menubar.connect('deactivate', hide_menubar) def disabled(self): window = app.window window.disconnect(self._key_release_handler) del self._key_release_handler self._menubar.disconnect(self._deactivate_handler) self._menubar.set_visible(True) del self._deactivate_handler ������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735241.984269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020126� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/__init__.py�������������������������������������������0000664�0001750�0001750�00000004577�14231604332�022255� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013,16,21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.util import (is_linux, is_osx, print_w, print_d) from quodlibet.util.environment import dbus_name_owned from .prefs import Preferences from .systemtray import SystemTray if is_osx(): # Works, but not without problems: # https://github.com/quodlibet/quodlibet/issues/1870 # The dock menu is more useful so disable. from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError def get_indicator_impl(): """Returns a BaseIndicator implementation depending on the environ""" use_app_indicator = ( is_linux() and dbus_name_owned("org.kde.StatusNotifierWatcher")) print_d("use app indicator: %s" % use_app_indicator) if not use_app_indicator: return SystemTray else: try: from .appindicator import AppIndicator except ImportError as e: print_w(f"Loading AppIndicator failed ({e}). Using {SystemTray}") # no indicator, fall back return SystemTray else: return AppIndicator class TrayIconPlugin(EventPlugin): PLUGIN_ID = "Tray Icon" PLUGIN_NAME = _("Tray Icon") PLUGIN_DESC = _("Controls Quod Libet from the system tray.") PLUGIN_ICON = Icons.USER_DESKTOP def enabled(self): impl = get_indicator_impl() self._tray = impl() self._tray.set_song(app.player.song) self._tray.set_info_song(app.player.info) self._tray.set_paused(app.player.paused) def disabled(self): self._tray.remove() del self._tray def PluginPreferences(self, parent): return Preferences() def plugin_on_song_started(self, song): self._tray.set_song(app.player.song) self._tray.set_info_song(app.player.info) def plugin_on_paused(self): self._tray.set_paused(True) def plugin_on_unpaused(self): self._tray.set_paused(False) ���������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/appindicator.py���������������������������������������0000644�0001750�0001750�00000010103�14310167056�023154� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013,21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import gi try: gi.require_version("AppIndicator3", "0.1") except ValueError as e: raise ImportError(f"Can't load ({e}). Perhaps install gir*-appindicator3* package?") from gi.repository import AppIndicator3, Gdk import quodlibet from quodlibet import _ from quodlibet import app from quodlibet.util import is_plasma from quodlibet.pattern import Pattern from .base import BaseIndicator from .util import pconfig from .menu import IndicatorMenu def get_next_app_id(state=[0]): """Returns an ever-increasing app id variant... I can't find a way to remove an indicator, so just hide old ones and add new different ones this way. """ state[0] += 1 return "%s-%d" % (app.id, state[0]) class AppIndicator(BaseIndicator): def __init__(self): # KDE doesn't support symbolic icons afaics icon_name = app.icon_name if is_plasma() else app.symbolic_icon_name self.indicator = AppIndicator3.Indicator.new( get_next_app_id(), icon_name, AppIndicator3.IndicatorCategory.APPLICATION_STATUS) self.indicator.set_icon_theme_path(quodlibet.get_image_dir()) self.indicator.set_title(app.name) self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) self.menu = IndicatorMenu(app, add_show_item=True) def on_action_item_changed(menu, indicator): indicator.set_secondary_activate_target(menu.get_action_item()) self.menu.connect("action-item-changed", on_action_item_changed, self.indicator) action_item = self.menu.get_action_item() self.indicator.set_secondary_activate_target(action_item) self.indicator.set_menu(self.menu) self.__scroll_id = self.indicator.connect( "scroll_event", self.__on_scroll) self.__w_sig_del = app.window.connect('delete-event', self.__window_delete) def set_info_song(self, song): if song: try: pattern = Pattern(pconfig.get("tooltip")) except ValueError: tooltip = u"" else: tooltip = pattern % song else: tooltip = _("Not playing") self.indicator.set_title(tooltip) def set_paused(self, value): self.menu.set_paused(value) def set_song(self, song): self.menu.set_song(song) def remove(self): # No function to remove an Indicator so it can be added back :( # If there is we can get rid of get_next_app_id() app.window.disconnect(self.__w_sig_del) self.indicator.disconnect(self.__scroll_id) self.__scroll_id = None self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE) self.indicator = None self.menu.destroy() self.menu = None def __on_scroll(self, indicator, steps, direction): # If direction here is always UP you're hitting # https://bugs.launchpad.net/indicator-application/+bug/1075152 modifier_swap = pconfig.getboolean("modifier_swap") for step in range(steps): if direction == Gdk.ScrollDirection.UP: if modifier_swap: app.player.previous() else: app.player.volume += 0.05 elif direction == Gdk.ScrollDirection.DOWN: if modifier_swap: app.player.next() else: app.player.volume -= 0.05 def __window_delete(self, win, event): if pconfig.getboolean("window_hide"): self.__hide_window() return True return False def __hide_window(self): app.hide() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/base.py�����������������������������������������������0000664�0001750�0001750�00000002106�14035600052�021407� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. class BaseIndicator: def remove(self): """Remove the indicator""" raise NotImplementedError def set_paused(self, value): """Update the paused state of the indicator""" pass def set_song(self, song): """Update the provided state of the indicator using the passed song or None if no song is active. """ pass def set_info_song(self, song): """Update the provided information of the indicator using the passed song or None if no song is active. """ pass def popup_menu(self): """Show the context menu as if the icon was pressed. Mainly for testing """ pass ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689589142.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/menu.py�����������������������������������������������0000644�0001750�0001750�00000016346�14455212626�021466� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011-2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GObject, Gtk from quodlibet.browsers.playlists.menu import PlaylistMenu from quodlibet import _ from quodlibet import browsers from quodlibet import qltk from quodlibet.qltk.ratingsmenu import RatingsMenuItem from quodlibet.qltk.x import SeparatorMenuItem, MenuItem from quodlibet.util import connect_obj, connect_destroy, is_plasma from quodlibet.qltk import Icons from quodlibet.qltk.browser import LibraryBrowser from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.util import GSignals class IndicatorMenu(Gtk.Menu): __gsignals__: GSignals = { 'action-item-changed': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self, app, add_show_item=False): super().__init__() self._app = app player = app.player show_item_bottom = is_plasma() if add_show_item: show_item = Gtk.CheckMenuItem.new_with_mnemonic( _("_Show %(application-name)s") % { "application-name": app.name}) def on_toggled(menuitem): if menuitem.get_active(): app.present() else: app.hide() self._toggle_id = show_item.connect("toggled", on_toggled) def on_visible_changed(*args): with show_item.handler_block(self._toggle_id): show_item.set_active(app.window.get_visible()) connect_destroy(app.window, "notify::visible", on_visible_changed) else: show_item = None self._play_item = MenuItem(_("_Play"), Icons.MEDIA_PLAYBACK_START) self._play_item.connect("activate", self._on_play_pause, player) self._play_item.set_no_show_all(True) self._pause_item = MenuItem(_("P_ause"), Icons.MEDIA_PLAYBACK_PAUSE) self._pause_item.connect("activate", self._on_play_pause, player) self._pause_item.set_no_show_all(True) self._action_item = None previous = MenuItem(_("Pre_vious"), Icons.MEDIA_SKIP_BACKWARD) previous.connect('activate', lambda *args: player.previous(force=True)) next = MenuItem(_("_Next"), Icons.MEDIA_SKIP_FORWARD) next.connect('activate', lambda *args: player.next()) player_options = app.player_options shuffle = Gtk.CheckMenuItem(label=_("_Shuffle"), use_underline=True) player_options.bind_property("shuffle", shuffle, "active", GObject.BindingFlags.BIDIRECTIONAL) player_options.notify("shuffle") repeat = Gtk.CheckMenuItem(label=_("_Repeat"), use_underline=True) player_options.bind_property("repeat", repeat, "active", GObject.BindingFlags.BIDIRECTIONAL) player_options.notify("repeat") safter = Gtk.CheckMenuItem(label=_("Stop _After This Song"), use_underline=True) player_options.bind_property("stop-after", safter, "active", GObject.BindingFlags.BIDIRECTIONAL) player_options.notify("stop-after") browse = qltk.MenuItem(_("Open _Browser"), Icons.EDIT_FIND) browse_sub = Gtk.Menu() for Kind in browsers.browsers: i = Gtk.MenuItem(label=Kind.accelerated_name, use_underline=True) connect_obj(i, 'activate', LibraryBrowser.open, Kind, app.library, app.player) browse_sub.append(i) browse.set_submenu(browse_sub) self._props = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT) def on_properties(*args): song = player.song window = SongProperties(app.librarian, [song]) window.show() self._props.connect('activate', on_properties) self._info = MenuItem(_("_Information"), Icons.DIALOG_INFORMATION) self._playlists_item = MenuItem(_("Play_lists"), Icons.FOLDER_DRAG_ACCEPT) self._new_playlist_submenu_for(player.song) def on_information(*args): song = player.song window = Information(app.librarian, [song]) window.show() self._info.connect('activate', on_information) def set_rating(value): song = player.song song["~#rating"] = value app.librarian.changed([song]) self._rating_item = rating = RatingsMenuItem([], app.library) quit = MenuItem(_("_Quit"), Icons.APPLICATION_EXIT) quit.connect('activate', lambda *x: app.quit()) if not show_item_bottom and show_item: self.append(show_item) self.append(SeparatorMenuItem()) self.append(self._play_item) self.append(self._pause_item) self.append(previous) self.append(next) self.append(SeparatorMenuItem()) self.append(shuffle) self.append(repeat) self.append(safter) self.append(SeparatorMenuItem()) self.append(rating) self.append(self._playlists_item) self.append(self._props) self.append(self._info) self.append(SeparatorMenuItem()) self.append(browse) self.append(SeparatorMenuItem()) self.append(quit) if show_item_bottom and show_item: self.append(SeparatorMenuItem()) self.append(show_item) self.show_all() self.set_paused(True) self.set_song(None) def get_action_item(self): """Returns the 'Play' or 'Pause' action menu item (used for unity). 'action-item-changed' gets emitted if this changes. """ return self._action_item def set_paused(self, paused): """Update the menu based on the player paused state""" self._play_item.set_visible(paused) self._pause_item.set_visible(not paused) self._action_item = self._play_item if paused else self._pause_item self.emit("action-item-changed") def set_song(self, song): """Update the menu based on the passed song. Can be None. This should be the persistent song and not a stream/info one. """ self._rating_item.set_sensitive(song is not None) self._info.set_sensitive(song is not None) self._props.set_sensitive(song is not None) self._rating_item.set_songs([song]) self._new_playlist_submenu_for(song) def _new_playlist_submenu_for(self, song): submenu = self._playlists_item.get_submenu() pl_lib = self._app.library and self._app.library.playlists if submenu: submenu.destroy() playlist_menu = PlaylistMenu([song], pl_lib) self._playlists_item.set_submenu(playlist_menu) self._playlists_item.set_sensitive(bool(song) and song.can_add) self._playlists_item.show_all() def _on_play_pause(self, menuitem, player): player.playpause() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/prefs.py����������������������������������������������0000644�0001750�0001750�00000007265�14267565021�021642� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013,2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.util import is_windows from quodlibet.qltk import Icons from quodlibet.pattern import Pattern from quodlibet.qltk.entry import UndoEntry from .util import pconfig def supports_scrolling(): """If our tray icon implementation supports scrolling""" return not is_windows() class Preferences(Gtk.VBox): """A small window to configure the tray icon's tooltip.""" def __init__(self): super().__init__(spacing=12) self.set_border_width(6) ccb = pconfig.ConfigCheckButton(_("Hide main window on close"), 'window_hide', populate=True) self.pack_start(qltk.Frame(_("Behavior"), child=ccb), False, True, 0) def on_scroll_changed(button, new_state): if button.get_active(): pconfig.set("modifier_swap", new_state) modifier_swap = pconfig.getboolean("modifier_swap") scrollwheel_box = Gtk.VBox(spacing=0) group = Gtk.RadioButton( group=None, label=_("Scroll wheel adjusts volume"), use_underline=True) group.connect("toggled", on_scroll_changed, False) group.set_active(not modifier_swap) scrollwheel_box.pack_start(group, False, True, 0) group = Gtk.RadioButton( group=group, label=_("Scroll wheel changes song"), use_underline=True) group.connect("toggled", on_scroll_changed, True) group.set_active(modifier_swap) scrollwheel_box.pack_start(group, False, True, 0) if supports_scrolling(): self.pack_start( qltk.Frame(_("Scroll _Wheel"), child=scrollwheel_box), True, True, 0) box = Gtk.VBox(spacing=6) entry_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry_box.pack_start(entry, True, True, 0) def on_reverted(*args): pconfig.reset("tooltip") entry.set_text(pconfig.gettext("tooltip")) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) entry_box.pack_start(revert, False, True, 0) box.pack_start(entry_box, False, True, 0) preview = Gtk.Label() preview.set_line_wrap(True) preview_frame = Gtk.Frame(label=_("Preview")) vbox = Gtk.VBox(margin=18) vbox.pack_start(preview, False, False, 0) preview_frame.add(vbox) box.pack_start(preview_frame, False, True, 0) tt_frame = qltk.Frame(_("Tooltip Display"), child=box) tt_frame.get_label_widget().set_mnemonic_widget(entry) self.pack_start(tt_frame, True, True, 0) entry.connect('changed', self.__changed_entry, preview, preview_frame) entry.set_text(pconfig.gettext("tooltip")) for child in self.get_children(): child.show_all() def __changed_entry(self, entry, label, frame): text = entry.get_text() if app.player.info is None: text = _("Not playing") else: text = Pattern(text) % app.player.info label.set_text(text) frame.set_tooltip_text(text) pconfig.set("tooltip", entry.get_text()) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1655124466.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/systemtray.py�����������������������������������������0000664�0001750�0001750�00000025145�14251630762�022744� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys from gi.repository import Gtk, Gdk, GdkPixbuf, GLib from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet import util from quodlibet.pattern import Pattern from quodlibet.qltk import Icons from quodlibet.util.thumbnails import scale from .base import BaseIndicator from .menu import IndicatorMenu from .util import pconfig def get_paused_pixbuf(boundary, diff): """Returns a pixbuf for a paused icon from the current theme. The returned pixbuf can have a size of size->size+diff size needs to be > 0 """ size = min(boundary) if size <= 0: raise ValueError("size has to be > 0") if diff < 0: raise ValueError("diff has to be >= 0") names = (Icons.MEDIA_PLAYBACK_PAUSE,) theme = Gtk.IconTheme.get_default() # Get the suggested icon info = theme.choose_icon(names, size, Gtk.IconLookupFlags.USE_BUILTIN) if not info: return try: pixbuf = info.load_icon() except GLib.GError: pass else: # In case it is too big, rescale pb_size = min(pixbuf.get_height(), pixbuf.get_width()) if abs(pb_size - size) > diff: return scale(pixbuf, boundary) return pixbuf def new_with_paused_emblem(icon_pixbuf): """Returns a new pixbuf with a pause emblem in the right bottom corner (success, new pixbuf) """ padding = 1.0 / 15.0 size = 5.0 / 8.0 base = icon_pixbuf.copy() w, h = base.get_width(), base.get_height() hpad = int(h * padding) wpad = int(w * padding) # get the sqare area where we can place the icon hn = int((w - wpad) * size) wn = int((h - hpad) * size) if hn <= 0 or wn <= 0: return False, base # get a pixbuf with roughly the size we want overlay = get_paused_pixbuf((hn, wn), min(hn, wn) / 5) if not overlay: return False, base wo, ho = overlay.get_width(), overlay.get_height() # we expect below that the icon fits into the icon including padding wo = min(w - wpad, wo) ho = min(h - hpad, ho) overlay.composite(base, w - wo - wpad, h - ho - hpad, wo, ho, w - wo - wpad, h - ho - hpad, 1.0, 1.0, GdkPixbuf.InterpType.BILINEAR, 255) return True, base class SystemTray(BaseIndicator): """A wrapper for Gtk.StatusIcon with some added features, workarounds for bugs etc.. """ def __init__(self): self.__size = -1 self.__pixbuf = None self.__pixbuf_paused = None self.__menu = None self._icon = Gtk.StatusIcon() self.__icon_theme = Gtk.IconTheme.get_default() self.__theme_sig = self.__icon_theme.connect('changed', self.__theme_changed) self._icon.connect('size-changed', self.__size_changed) self._icon.connect("notify::embedded", self.__embedded_changed) self.__embedded_changed(self._icon) self._icon.connect('popup-menu', self.__popup_menu) self._icon.connect('activate', self.__button_left) self._icon.connect('scroll-event', self.__scroll) self._icon.connect('button-press-event', self.__button_middle) self.__w_sig_del = app.window.connect('delete-event', self.__window_delete) # If after the main loop is idle and 3 seconds have passed # the tray icon isn't embedded, assume it won't be and unhide # all windows, so QL isn't 'lost'.. def add_timeout(): def check_embedded(): is_embedded = self._icon.is_embedded() main_window_shown = app.window.get_visible() if not is_embedded and not main_window_shown: app.present() self.__emb_sig = None return False self.__emb_sig = GLib.timeout_add(3000, check_embedded) return False self.__emb_sig = GLib.idle_add(add_timeout) def remove(self): """Hides the tray icon and frees all resources. Can only be called once. """ if self.__menu: self.__menu.destroy() self.__menu = None if self.__emb_sig: GLib.source_remove(self.__emb_sig) self.__emb_sig = None self.__icon_theme.disconnect(self.__theme_sig) self.__icon_theme = None app.window.disconnect(self.__w_sig_del) self._icon.set_visible(False) self._icon = None self.__show_window() def set_info_song(self, song): """Updates the tooltip based on the passed song""" if not self._icon: return if song: try: pattern = Pattern(pconfig.get("tooltip")) except ValueError: tooltip = u"" else: tooltip = pattern % song else: tooltip = _("Not playing") self._icon.set_tooltip_markup(util.escape(tooltip)) def set_paused(self, paused): """Update the icon base on the paused state""" self.__update_icon() def popup_menu(self): """Show the context menu as if the icon was pressed. Mainly for testing """ if not self._icon: return self.__popup_menu( self._icon, Gdk.BUTTON_SECONDARY, Gtk.get_current_event_time()) def __embedded_changed(self, icon, *args): if icon.get_property("embedded"): size = icon.get_size() self.__size_changed(icon, size) def __user_can_unhide(self): """Return if the user has the possibility to show the Window somehow""" if sys.platform == "darwin": return False # Either if it's embedded, or if we are waiting for the embedded check return bool(self._icon.is_embedded() or self.__emb_sig) def __update_icon(self): if self.__size <= 0: return if not self.__pixbuf: flags = 0 if sys.platform == "win32": flags = Gtk.IconLookupFlags.FORCE_SIZE try: self.__pixbuf = self.__icon_theme.load_icon( Icons.QUODLIBET, self.__size, flags) except GLib.GError: util.print_exc() return # We need to fill the whole height that is given to us, or # the KDE panel will emit size-changed until we reach 0 w, h = self.__pixbuf.get_width(), self.__pixbuf.get_height() if h < self.__size: bg = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, w, self.__size) bg.fill(0) self.__pixbuf.copy_area(0, 0, w, h, bg, 0, (self.__size - h) / 2) self.__pixbuf = bg if app.player.paused and not self.__pixbuf_paused: self.__pixbuf_paused = new_with_paused_emblem(self.__pixbuf)[1] if app.player.paused: new_pixbuf = self.__pixbuf_paused else: new_pixbuf = self.__pixbuf self._icon.set_from_pixbuf(new_pixbuf) def __theme_changed(self, theme, *args): self.__pixbuf = None self.__pixbuf_paused = None self.__update_icon() def __size_changed(self, icon, req_size, *args): # https://bugzilla.gnome.org/show_bug.cgi?id=733647 # Workaround: if size < 16, create a 16px pixbuf anyway and return that # we didn't set the right size size = max(req_size, 16) if size != self.__size: self.__pixbuf = None self.__pixbuf_paused = None self.__size = size self.__update_icon() return size == req_size and self.__pixbuf is not None def __window_delete(self, win, event): if self.__user_can_unhide() and pconfig.getboolean("window_hide"): self.__hide_window() return True return False def __hide_window(self): app.hide() def __show_window(self): app.present() def __button_left(self, icon): if self.__destroy_win32_menu(): return if app.window.get_property('visible'): self.__hide_window() else: self.__show_window() def __button_middle(self, widget, event, _last_timestamp=[0]): if event.type == Gdk.EventType.BUTTON_PRESS and \ event.button == Gdk.BUTTON_MIDDLE: if self.__destroy_win32_menu(): return # work around gnome shell (3.14) bug, it sends middle clicks twice # with the same timestamp, so ignore the second event if event.time == _last_timestamp[0]: return _last_timestamp[0] = event.time self.__play_pause() def __play_pause(self, *args): app.player.playpause() def __scroll(self, widget, event): state = event.get_state() try: state ^= pconfig.getboolean("modifier_swap") except config.Error: pass DIR = Gdk.ScrollDirection if event.direction in [DIR.LEFT, DIR.RIGHT]: state = Gdk.ModifierType.SHIFT_MASK player = app.player if state & Gdk.ModifierType.SHIFT_MASK: if event.direction in [DIR.UP, DIR.LEFT]: player.previous() elif event.direction in [DIR.DOWN, DIR.RIGHT]: player.next() else: if event.direction in [DIR.UP, DIR.LEFT]: player.volume += 0.05 elif event.direction in [DIR.DOWN, DIR.RIGHT]: player.volume -= 0.05 def __destroy_win32_menu(self): """Returns True if current action should only hide the menu""" if sys.platform in ("win32", "darwin") and self.__menu: self.__menu.destroy() self.__menu = None return True def __popup_menu(self, icon, button, time): if self.__destroy_win32_menu(): return self.__menu = menu = IndicatorMenu(app) menu.set_paused(app.player.paused) menu.set_song(app.player.song) menu.show_all() if sys.platform in ("win32", "darwin"): pos_func = pos_arg = None else: pos_func = Gtk.StatusIcon.position_menu pos_arg = self._icon menu.popup(None, None, pos_func, pos_arg, button, time) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/trayicon/util.py�����������������������������������������������0000664�0001750�0001750�00000002135�14035600052�021454� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2013 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import config from quodlibet.plugins import PluginConfig DEFAULT_PATTERN = ("<album|<album~discnumber~part~tracknumber~title~version>|" "<artist~title~version>>") def _get_plugin_config(): # migrate option if config.has_option('plugins', 'trayicon_window_hide'): value = config.getboolean('plugins', 'trayicon_window_hide') config.remove_option('plugins', 'trayicon_window_hide') config.set('plugins', 'icon_window_hide', value) pconfig = PluginConfig("icon") pconfig.defaults.set("window_hide", True) pconfig.defaults.set("tooltip", DEFAULT_PATTERN) pconfig.defaults.set("modifier_swap", False) return pconfig pconfig = _get_plugin_config() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/viewlyrics.py��������������������������������������������������0000644�0001750�0001750�00000012702�14267565021�021063� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # View Lyrics: a Quod Libet plugin for viewing lyrics. # Copyright (C) 2008, 2011, 2012 Vasiliy Faronov <vfaronov@gmail.com> # 2013-17 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk from quodlibet import _, print_d, app from quodlibet.plugins.events import EventPlugin from quodlibet.plugins.gui import UserInterfacePlugin from quodlibet.qltk import Icons, add_css, Button from quodlibet.qltk.information import Information from quodlibet.util.songwrapper import SongWrapper class ViewLyrics(EventPlugin, UserInterfacePlugin): """The plugin for viewing lyrics in the main window.""" PLUGIN_ID = 'View Lyrics' PLUGIN_NAME = _('View Lyrics') PLUGIN_DESC = _('Automatically displays tag or file-based lyrics ' 'in a sidebar.') PLUGIN_ICON = Icons.FORMAT_JUSTIFY_FILL def enabled(self): self.scrolled_window = Gtk.ScrolledWindow() self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.adjustment = self.scrolled_window.get_vadjustment() self.textview = Gtk.TextView() self.textbuffer = self.textview.get_buffer() self._italics = self.textbuffer.create_tag("italic", style="italic", foreground="grey") self.textview.set_editable(False) self.textview.set_cursor_visible(False) self.textview.set_wrap_mode(Gtk.WrapMode.WORD) self.textview.set_justification(Gtk.Justification.CENTER) self.textview.connect('key-press-event', self.key_press_event_cb) add_css(self.textview, "* { padding: 6px; }") vbox = Gtk.VBox() vbox.pack_start(self.textview, True, True, 0) self._edit_button = Button("Edit Lyrics", Icons.EDIT) hbox = Gtk.HBox() hbox.pack_end(self._edit_button, False, False, 3) vbox.pack_start(hbox, False, False, 3) self.scrolled_window.add(vbox) self.textview.show() self.scrolled_window.show() self._sig = None cur = app.player.info if cur is not None: cur = SongWrapper(cur) self.plugin_on_song_started(cur) def create_sidebar(self): vbox = Gtk.VBox(margin=0) vbox.pack_start(self.scrolled_window, True, True, 0) vbox.show_all() return vbox def disabled(self): self.textview.destroy() self.scrolled_window.destroy() def plugin_on_song_started(self, song): """Called when a song is started. Loads the lyrics. If there are lyrics associated with `song`, load them into the lyrics viewer. Otherwise, hides the lyrics viewer. """ lyrics = None if song is not None: print_d("Looking for lyrics for %s" % song("~filename")) lyrics = song("~lyrics") if lyrics: self.textbuffer.set_text(lyrics) self.adjustment.set_value(0) # Scroll to the top. self.textview.show() else: title = _("No lyrics found for\n %s") % song("~basename") self._set_italicised(title) def edit(widget): print_d("Launching lyrics editor for %s" % song("~filename")) assert isinstance(song, SongWrapper) information = Information(app.librarian, [song._song]) information.get_child()._switch_to_lyrics() information.show() if self._sig: self._edit_button.disconnect(self._sig) self._sig = self._edit_button.connect('clicked', edit) def _set_italicised(self, title): self.textbuffer.set_text(title) start = self.textbuffer.get_start_iter() end = self.textbuffer.get_end_iter() self.textbuffer.remove_all_tags(start, end) self.textbuffer.apply_tag(self._italics, start, end) def plugin_on_changed(self, songs): cur = app.player.info if cur: fn = cur("~filename") for s in songs: if s("~filename") == fn: print_d("Active song changed, reloading lyrics") self.plugin_on_song_started(SongWrapper(cur)) else: self._set_italicised(_("No active song")) def key_press_event_cb(self, widget, event): """Handles up/down "key-press-event" in the lyrics view.""" adj = self.scrolled_window.get_vadjustment().props if event.keyval == Gdk.KEY_Up: adj.value = max(adj.value - adj.step_increment, adj.lower) elif event.keyval == Gdk.KEY_Down: adj.value = min(adj.value + adj.step_increment, adj.upper - adj.page_size) elif event.keyval == Gdk.KEY_Page_Up: adj.value = max(adj.value - adj.page_increment, adj.lower) elif event.keyval == Gdk.KEY_Page_Down: adj.value = min(adj.value + adj.page_increment, adj.upper - adj.page_size) elif event.keyval == Gdk.KEY_Home: adj.value = adj.lower elif event.keyval == Gdk.KEY_End: adj.value = adj.upper - adj.page_size else: return False return True ��������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/visualisations.py����������������������������������������������0000644�0001750�0001750�00000006351�14267565021�021743� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import signal from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import print_d from quodlibet import print_w from quodlibet.plugins import PluginConfig from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Button from quodlibet.qltk import ErrorMessage from quodlibet.qltk import Icons from quodlibet.qltk.entry import UndoEntry from quodlibet.util import escape class ProjectM(EventPlugin): """Launch external visualisations, e.g. via projectM Try this first (Ubuntu/Debian): sudo apt-get install projectm-pulseaudio """ _config = PluginConfig(__name__) PLUGIN_ID = "visualisations" PLUGIN_NAME = _("Launch Visualisations") PLUGIN_ICON = Icons.IMAGE_X_GENERIC PLUGIN_DESC = _("Launch external visualisations.") DEFAULT_EXEC = 'projectM-pulseaudio' def __init__(self): self._pid = None def enabled(self): from gi.repository import GLib print_d("Starting %s" % self.PLUGIN_NAME) try: self._pid, fdin, fdout, fderr = GLib.spawn_async( argv=self.executable.split(), flags=GLib.SpawnFlags.SEARCH_PATH, standard_output=True, standard_input=True) except GLib.Error as e: msg = ((_("Couldn't run visualisations using '%s'") + " (%s)") % (escape(self.executable), escape(e.message))) ErrorMessage(title=_("Error"), description=msg, parent=app.window).run() else: # self._stdin = os.fdopen(fdin, mode='w') print_d("Launched with PID: %s" % self._pid) def disabled(self): if not self._pid: return print_d("Shutting down %s" % self.PLUGIN_NAME) try: os.kill(self._pid, signal.SIGTERM) os.kill(self._pid, signal.SIGKILL) except Exception as e: print_w("Couldn't shut down cleanly (%s)" % e) def PluginPreferences(self, *args): vbox = Gtk.VBox(spacing=12) label = Gtk.Label(label=_("Visualiser executable:")) def edited(widget): self.executable = widget.get_text() entry = UndoEntry() entry.connect('changed', edited) entry.set_text(self.executable) hbox = Gtk.HBox(spacing=6) hbox.pack_start(label, False, False, 0) hbox.pack_start(entry, True, True, 0) vbox.pack_start(hbox, True, True, 0) def refresh_clicked(widget): self.disabled() self.enabled() refresh_button = Button(_("Reload"), Icons.VIEW_REFRESH) refresh_button.connect('clicked', refresh_clicked) vbox.pack_start(refresh_button, False, False, 0) return vbox @property def executable(self): return self._config.get('executable', self.DEFAULT_EXEC) @executable.setter def executable(self, value): self._config.set('executable', value) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661798727.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/waveformseekbar.py���������������������������������������������0000644�0001750�0001750�00000064510�14303204507�022040� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 0x1777 # 2016-22 Nick Boultbee # 2017 Didier Villevalois # 2017 Muges # 2017 Eyenseo # 2018 Joschua Gandert # 2018 Blimmo # 2018 Olli Helin # # 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 2 of the License, or # (at your option) any later version. from math import ceil, floor from typing import List from gi.repository import Gtk, Gdk, Gst import cairo from quodlibet import _, app from quodlibet import print_w from quodlibet import util from quodlibet.plugins import PluginConfig, IntConfProp, \ ConfProp, BoolConfProp from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Align from quodlibet.qltk import Icons from quodlibet.qltk.seekbutton import TimeLabel from quodlibet.qltk.tracker import TimeTracker from quodlibet.qltk import get_fg_highlight_color from quodlibet.util import connect_destroy, print_d from quodlibet.util.path import uri2gsturi class WaveformSeekBar(Gtk.Box): """A widget containing labels and the seekbar.""" def __init__(self, player, library): super().__init__() self._player = player self._rms_vals = [] self._hovering = False self._elapsed_label = TimeLabel() self._remaining_label = TimeLabel() self._waveform_scale = WaveformScale(player) self.pack_start(Align(self._elapsed_label, border=6), False, True, 0) self.pack_start(self._waveform_scale, True, True, 0) self.pack_start(Align(self._remaining_label, border=6), False, True, 0) for child in self.get_children(): child.show_all() self.set_time_label_visibility(CONFIG.show_time_labels) self._waveform_scale.connect('size-allocate', self._update_redraw_interval) self._waveform_scale.connect('motion-notify-event', self._on_mouse_hover) self._waveform_scale.connect('leave-notify-event', self._on_mouse_leave) self._label_tracker = TimeTracker(player) self._label_tracker.connect('tick', self._on_tick_label, player) self._redraw_tracker = TimeTracker(player) self._redraw_tracker.connect('tick', self._on_tick_waveform, player) connect_destroy(player, 'seek', self._on_player_seek) connect_destroy(player, 'song-started', self._on_song_started) connect_destroy(player, 'song-ended', self._on_song_ended) connect_destroy(player, 'notify::seekable', self._on_seekable_changed) connect_destroy(library, 'changed', self._on_song_changed, player) self.connect('destroy', self._on_destroy) self._update(player) if player.info: self._create_waveform(player.info, CONFIG.max_data_points) def set_time_label_visibility(self, is_visible): self._time_labels_visible = is_visible if is_visible: self._elapsed_label.show() self._remaining_label.show() else: self._elapsed_label.hide() self._remaining_label.hide() def _create_waveform(self, song, points): # Close any existing pipeline to avoid leaks self._clean_pipeline() if not song.is_file: return command_template = """ uridecodebin name=uridec ! audioconvert ! level name=audiolevel interval={} post-messages=true ! fakesink sync=false""" interval = int(song("~#length") * 1E9 / points) if not interval: return print_d("Computing data for each %.3f seconds" % (interval / 1E9)) command = command_template.format(interval) pipeline = Gst.parse_launch(command) pipeline.get_by_name("uridec").set_property("uri", uri2gsturi(song("~uri"))) bus = pipeline.get_bus() self._bus_id = bus.connect("message", self._on_bus_message, points) bus.add_signal_watch() pipeline.set_state(Gst.State.PLAYING) self._pipeline = pipeline self._new_rms_vals = [] def _on_bus_message(self, bus, message, points): force_stop = False if message.type == Gst.MessageType.ERROR: error, debug = message.parse_error() print_d("Error received from element {name}: {error}".format( name=message.src.get_name(), error=error)) print_d("Debugging information: {}".format(debug)) elif message.type == Gst.MessageType.ELEMENT: structure = message.get_structure() if structure.get_name() == "level": rms_db = structure.get_value("rms") if rms_db: # Calculate average of all channels (usually 2) rms_db_avg = sum(rms_db) / len(rms_db) # Normalize dB value to value between 0 and 1 rms = pow(10, (rms_db_avg / 20)) self._new_rms_vals.append(rms) if len(self._new_rms_vals) >= points: # The audio might be much longer than we anticipated # and we would get way too many events due to the too # short interval set. force_stop = True else: print_w("Got unexpected message of type {}" .format(message.type)) if message.type == Gst.MessageType.EOS or force_stop: self._clean_pipeline() # Update the waveform with the new data self._rms_vals = self._new_rms_vals self._waveform_scale.reset(self._rms_vals) self._update_redraw_interval() # Clear temporary reference to the waveform data del self._new_rms_vals def _clean_pipeline(self): if hasattr(self, "_pipeline") and self._pipeline: self._pipeline.set_state(Gst.State.NULL) if self._bus_id: bus = self._pipeline.get_bus() bus.remove_signal_watch() bus.disconnect(self._bus_id) self._bus_id = None if self._pipeline: self._pipeline = None def _update_redraw_interval(self, *args): if self._player.info and self.is_visible(): # Must be recomputed when size is changed interval = self._waveform_scale.compute_redraw_interval() self._redraw_tracker.set_interval(interval) def _on_destroy(self, *args): self._clean_pipeline() self._label_tracker.destroy() self._redraw_tracker.destroy() def _on_tick_label(self, tracker, player): self._update_label(player) def _on_tick_waveform(self, tracker, player): self._update_waveform(player) def _on_seekable_changed(self, player, *args): self._update_label(player) def _on_player_seek(self, player, song, ms): self._update(player) def _on_song_changed(self, library, songs, player): if not player.info: return # Check that the currently playing song has changed if player.info in songs: # Trigger a re-computation of the waveform self._create_waveform(player.info, CONFIG.max_data_points) self._resize_labels(player.info) # Only update the label if some tag value changed self._update_label(player) def _on_song_started(self, player, song): if player.info: # Trigger a re-computation of the waveform self._create_waveform(player.info, CONFIG.max_data_points) self._resize_labels(player.info) self._rms_vals.clear() self._update(player, True) def _on_song_ended(self, player, song, ended): self._update(player) def _update(self, player, full_redraw=False): self._update_label(player) self._update_waveform(player, full_redraw) def _update_label(self, player): if not self._time_labels_visible: self.set_sensitive(player.info is not None and player.seekable) return if player.info: if self._hovering: # Show the position pointed by the mouse position = self._waveform_scale.get_mouse_position() else: # Show the position of the player (converted in seconds) position = player.get_position() / 1000.0 length = player.info("~#length") remaining = length - position self._elapsed_label.set_time(position) self._remaining_label.set_time(remaining) self._elapsed_label.set_disabled(not player.seekable) self._remaining_label.set_disabled(not player.seekable) self.set_sensitive(player.seekable) else: self._remaining_label.set_disabled(True) self._elapsed_label.set_disabled(True) self.set_sensitive(False) def _update_waveform(self, player, full_redraw=False): if player.info: # Position in ms, length in seconds position = player.get_position() / 1000.0 length = player.info("~#length") if length != 0: self._waveform_scale.set_position(position / length) else: print_d("Length reported as zero for %s" % player.info) self._waveform_scale.set_position(0) if position == 0 or full_redraw: self._waveform_scale.queue_draw() else: (x, y, w, h) = self._waveform_scale.compute_redraw_area() self._waveform_scale.queue_draw_area(x, y, w, h) else: self._rms_vals.clear() self._waveform_scale.queue_draw() def _on_mouse_hover(self, _, event): def clamp(a, x, b): """Return x if a <= x <= b, else the a or b nearest to x.""" return min(max(x, a), b) width = self._waveform_scale.get_allocation().width self._waveform_scale.set_mouse_x_position(clamp(0, event.x, width)) if self._hovering: (x, y, w, h) = self._waveform_scale.compute_hover_redraw_area() self._waveform_scale.queue_draw_area(x, y, w, h) else: self._waveform_scale.queue_draw() self._update_label(self._player) self._hovering = True def _on_mouse_leave(self, _, event): self._waveform_scale.set_mouse_x_position(-1) self._waveform_scale.queue_draw() self._hovering = False self._update_label(self._player) def _resize_labels(self, song): """Resize the labels to make sure there is enough space to display the length of the songs. This prevents the waveform from changing size when the position changes from 9:59 to 10:00 for example.""" length = util.format_time_display(song("~#length")) # Get the width needed to display the length of the song (the text # displayed in the labels will always be shorter than that) layout = self._remaining_label.get_layout() layout.set_text(length, -1) width, height = layout.get_pixel_size() # Set it as the minimum width of the labels to prevent them from # changing width self._remaining_label.set_size_request(width, -1) self._elapsed_label.set_size_request(width, -1) class WaveformScale(Gtk.EventBox): """The waveform widget.""" _rms_vals: List[int] = [] _player = None def __init__(self, player): super().__init__() self._player = player self.set_size_request(40, 40) self.position = 0 self._last_drawn_position = 0 self.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(alpha=0)) self.mouse_position = -1 self._last_mouse_position = -1 self.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.SCROLL_MASK) self._seeking = False @property def width(self): return self.get_allocation().width def reset(self, rms_vals): self._rms_vals = rms_vals self._seeking = False self.queue_draw() def compute_redraw_interval(self): allocation = self.get_allocation() width = allocation.width scale_factor = self.get_scale_factor() pixel_ratio = float(scale_factor) # Compute the coarsest time interval for redraws length = self._player.info("~#length") if length == 0: # The length is 0 for example when playing a stream from # Internet radio. If 0 is passed forward as the update interval, # UI will freeze as it will try to update continuously. # The update interval is usually 1 second so use that instead. print_d(f"Length is zero for {self._player.info}, " "using redraw interval of 1000 ms") return 1000 return length * 1000 / max(width * pixel_ratio, 1) def compute_redraw_area(self): width = self.width last_position_x = self._last_drawn_position * width position_x = self.position * width return self._compute_redraw_area_between(last_position_x, position_x) def compute_hover_redraw_area(self): return self._compute_redraw_area_between(self._last_mouse_position, self.mouse_position) def _compute_redraw_area_between(self, x1, x2): allocation = self.get_allocation() width = allocation.width height = allocation.height scale_factor = self.get_scale_factor() pixel_ratio = float(scale_factor) line_width = 1.0 / pixel_ratio # Compute the thinnest rectangle to redraw x = max(0.0, min(x1, x2) - line_width * 5) w = min(width, abs(x2 - x1) + line_width * 10) return x, 0.0, w, height def draw_waveform(self, cr, width, height, elapsed_color, hover_color, remaining_color, show_current_pos_config): if width == 0 or height == 0: return scale_factor = self.get_scale_factor() pixel_ratio = float(scale_factor) line_width = 1.0 / pixel_ratio half_height = self.compute_half_height(height, pixel_ratio) value_count = len(self._rms_vals) max_value = max(self._rms_vals) ratio_width = value_count / (float(width) * pixel_ratio) ratio_height = max_value / half_height cr.set_line_width(line_width) cr.set_line_cap(cairo.LINE_CAP_ROUND) cr.set_line_join(cairo.LINE_JOIN_ROUND) position_width = self.position * width * pixel_ratio mouse_position = self.mouse_position * scale_factor hw = line_width / 2.0 # Avoiding object lookups is slightly faster data = self._rms_vals # Use the clip rectangles to redraw only what is necessary for (cx, cy, cw, ch) in cr.copy_clip_rectangle_list(): for x in range(int(floor(cx * pixel_ratio)), int(ceil((cx + cw) * pixel_ratio)), 1): if mouse_position >= 0: if self._seeking: # The user is seeking (holding mousebutton down) fg_color = (elapsed_color if x < mouse_position else remaining_color) elif show_current_pos_config: # Use hover color and elapsed color to display the # current playing position while hovering if x < mouse_position: if x < position_width: fg_color = elapsed_color else: fg_color = hover_color elif x < position_width: fg_color = hover_color else: fg_color = remaining_color else: # The mouse is hovering the seekbar fg_color = (hover_color if x < mouse_position else remaining_color) else: fg_color = elapsed_color if x < position_width else remaining_color cr.set_source_rgba(*list(fg_color)) # Basic anti-aliasing / oversampling u1 = max(0, int(floor((x - hw) * ratio_width))) u2 = min(int(ceil((x + hw) * ratio_width)), len(data)) val = (sum(data[u1:u2]) / (ratio_height * (u2 - u1)) if u1 != u2 else 0.0) hx = x / pixel_ratio + hw cr.move_to(hx, half_height - val) cr.line_to(hx, half_height + val) cr.stroke() self._last_drawn_position = self.position self._last_mouse_position = self.mouse_position def draw_placeholder(self, cr, width, height, color): if width == 0 or height == 0: return scale_factor = self.get_scale_factor() pixel_ratio = float(scale_factor) line_width = 1.0 / pixel_ratio position_width = self.position * width * pixel_ratio half_height = self.compute_half_height(height, pixel_ratio) hw = line_width / 2.0 cr.set_line_width(line_width) cr.set_line_cap(cairo.LINE_CAP_ROUND) cr.set_line_join(cairo.LINE_JOIN_ROUND) cr.set_source_rgba(*self.elapsed_color) cr.move_to(hw, half_height) cr.rectangle(hw, half_height - line_width, position_width - hw, line_width * 2) cr.fill() cr.set_source_rgba(*color) cr.move_to(position_width, half_height) cr.line_to(width, half_height) cr.stroke() @staticmethod def compute_half_height(height, pixel_ratio): # Ensure half_height is in the middle of a pixel (c.f. Cairo's FAQ) height_px = int(height * pixel_ratio) half_height = (height_px if height_px % 2 else height_px - 1) / pixel_ratio / 2 return half_height def do_draw(self, cr): context = self.get_style_context() # Get colors context.save() context.set_state(Gtk.StateFlags.NORMAL) bg_color = context.get_background_color(context.get_state()) remaining_color = context.get_color(context.get_state()) remaining_color.alpha = 0.35 context.restore() elapsed_color = self.elapsed_color # Check if the user set a different remaining color in the config remaining_color_config = CONFIG.remaining_color if remaining_color_config and Gdk.RGBA().parse(remaining_color_config): remaining_color = Gdk.RGBA() remaining_color.parse(remaining_color_config) # Check if the user set a hover color in the config hover_color_config = CONFIG.hover_color if hover_color_config and Gdk.RGBA().parse(hover_color_config): hover_color = Gdk.RGBA() hover_color.parse(hover_color_config) else: # Generate default hover_color by blending elapsed_color and # remaining_color opacity = 0.4 r = (opacity * elapsed_color.alpha * elapsed_color.red + (1 - opacity) * remaining_color.alpha * remaining_color.red) g = (opacity * elapsed_color.alpha * elapsed_color.green + (1 - opacity) * remaining_color.alpha * remaining_color.green) b = (opacity * elapsed_color.alpha * elapsed_color.blue + (1 - opacity) * remaining_color.alpha * remaining_color.blue) a = (opacity * elapsed_color.alpha + (1 - opacity) * remaining_color.alpha) hover_color = Gdk.RGBA(r, g, b, a) # Check if the user turned on showing current position show_current_pos_config = CONFIG.show_current_pos # Paint the background cr.set_source_rgba(*list(bg_color)) cr.paint() allocation = self.get_allocation() width = allocation.width height = allocation.height if self._rms_vals: self.draw_waveform(cr, width, height, elapsed_color, hover_color, remaining_color, show_current_pos_config) else: self.draw_placeholder(cr, width, height, remaining_color) @property def elapsed_color(self): # Check if the user set a different elapsed color in the config elapsed_color_config = CONFIG.elapsed_color if elapsed_color_config and Gdk.RGBA().parse(elapsed_color_config): col = Gdk.RGBA() col.parse(elapsed_color_config) return col return get_fg_highlight_color(self) def do_button_press_event(self, event): # Left mouse button if event.button == 1 and self._player: self._seeking = True self.queue_draw() def do_button_release_event(self, event): # Left mouse button if event.button == 1 and self._player: ratio = event.x / self.get_allocation().width length = self._player.info("~#length") self._player.seek(ratio * length * 1000) self._seeking = False self.queue_draw() return True def do_scroll_event(self, event): if event.direction == Gdk.ScrollDirection.UP: self._player.seek(self._player.get_position() + CONFIG.seek_amount) self.queue_draw() elif event.direction == Gdk.ScrollDirection.DOWN: self._player.seek(self._player.get_position() - CONFIG.seek_amount) self.queue_draw() def set_position(self, position): self.position = position def set_mouse_x_position(self, mouse_position): """Set the horizontal position of the mouse in pixel""" self.mouse_position = mouse_position def get_mouse_position(self): """Return the position of the song pointed by the mouse in seconds""" ratio = self.mouse_position / self.get_allocation().width length = self._player.info("~#length") return ratio * length class Config: _config = PluginConfig(__name__) elapsed_color = ConfProp(_config, "elapsed_color", "") hover_color = ConfProp(_config, "hover_color", "") remaining_color = ConfProp(_config, "remaining_color", "") show_current_pos = BoolConfProp(_config, "show_current_pos", False) seek_amount = IntConfProp(_config, "seek_amount", 5000) max_data_points = IntConfProp(_config, "max_data_points", 3000) show_time_labels = BoolConfProp(_config, "show_time_labels", True) CONFIG = Config() class WaveformSeekBarPlugin(EventPlugin): """The plugin class.""" PLUGIN_ID = "WaveformSeekBar" PLUGIN_NAME = _("Waveform Seek Bar") PLUGIN_ICON = Icons.GO_JUMP PLUGIN_CONFIG_SECTION = __name__ PLUGIN_DESC = _("∿ A seekbar in the shape of the waveform of the current song.") def __init__(self): self._bar = None def enabled(self): self._bar = WaveformSeekBar(app.player, app.librarian) self._bar.show() app.window.set_seekbar_widget(self._bar) def disabled(self): app.window.set_seekbar_widget(None) self._bar.destroy() self._bar = None def PluginPreferences(self, parent): red = Gdk.RGBA() red.parse("#ff0000") def validate_color(entry): text = entry.get_text() if not Gdk.RGBA().parse(text): # Invalid color, make text red entry.override_color(Gtk.StateFlags.NORMAL, red) else: # Reset text color entry.override_color(Gtk.StateFlags.NORMAL, None) def elapsed_color_changed(entry): validate_color(entry) CONFIG.elapsed_color = entry.get_text() def hover_color_changed(entry): validate_color(entry) CONFIG.hover_color = entry.get_text() def remaining_color_changed(entry): validate_color(entry) CONFIG.remaining_color = entry.get_text() def on_show_pos_toggled(button, *args): CONFIG.show_current_pos = button.get_active() def seek_amount_changed(spinbox): CONFIG.seek_amount = spinbox.get_value_as_int() vbox = Gtk.VBox(spacing=6) def on_show_time_labels_toggled(button, *args): CONFIG.show_time_labels = button.get_active() if self._bar is not None: self._bar.set_time_label_visibility(CONFIG.show_time_labels) def create_color(label_text, color, callback): hbox = Gtk.HBox(spacing=6) hbox.set_border_width(6) label = Gtk.Label(label=label_text) hbox.pack_start(label, False, True, 0) entry = Gtk.Entry() if color: entry.set_text(color) entry.connect('changed', callback) hbox.pack_start(entry, True, True, 0) return hbox box = create_color(_("Override foreground color:"), CONFIG.elapsed_color, elapsed_color_changed) vbox.pack_start(box, True, True, 0) box = create_color(_("Override hover color:"), CONFIG.hover_color, hover_color_changed) vbox.pack_start(box, True, True, 0) box = create_color(_("Override remaining color:"), CONFIG.remaining_color, remaining_color_changed) vbox.pack_start(box, True, True, 0) show_current_pos = Gtk.CheckButton(label=_("Show current position")) show_current_pos.set_active(CONFIG.show_current_pos) show_current_pos.connect("toggled", on_show_pos_toggled) vbox.pack_start(show_current_pos, True, True, 0) show_time_labels = Gtk.CheckButton(label=_("Show time labels")) show_time_labels.set_active(CONFIG.show_time_labels) show_time_labels.connect("toggled", on_show_time_labels_toggled) vbox.pack_start(show_time_labels, True, True, 0) hbox = Gtk.HBox(spacing=6) hbox.set_border_width(6) label = Gtk.Label(label=_("Seek amount when scrolling (milliseconds):")) hbox.pack_start(label, False, True, 0) seek_amount = Gtk.SpinButton( adjustment=Gtk.Adjustment(CONFIG.seek_amount, 0, 60000, 1000, 1000, 0) ) seek_amount.set_numeric(True) seek_amount.connect("changed", seek_amount_changed) hbox.pack_start(seek_amount, True, True, 0) vbox.pack_start(hbox, True, True, 0) return vbox ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/events/write_cover.py�������������������������������������������������0000644�0001750�0001750�00000004061�14267565021�021212� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import shutil from gi.repository import Gtk import quodlibet from quodlibet import _, print_w from quodlibet import app from quodlibet import config from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons def get_path(): default = os.path.join(quodlibet.get_user_dir(), "current.cover") return config.get("plugins", __name__, default=default) def set_path(value): config.set("plugins", __name__, value) class PictureSaver(EventPlugin): PLUGIN_ID = "Picture Saver" PLUGIN_NAME = _("Picture Saver") PLUGIN_DESC = _("Saves the cover image of the current song to a file.") PLUGIN_ICON = Icons.DOCUMENT_SAVE def plugin_on_song_started(self, song): def delete(outfile): try: os.unlink(outfile) except EnvironmentError as e: print_w("Couldn't delete '%s' (%s)" % (outfile, e)) outfile = get_path() if song is None: delete(outfile) else: cover = app.cover_manager.get_cover(song) if cover is None: delete(outfile) else: with open(outfile, "wb") as f: f.write(cover.read()) def PluginPreferences(self, parent): def changed(entry): fn = entry.get_text() try: shutil.move(get_path(), fn) except EnvironmentError: pass else: set_path(fn) hb = Gtk.HBox(spacing=6) hb.set_border_width(6) hb.pack_start(Gtk.Label(label=_("File:")), False, True, 0) e = Gtk.Entry() e.set_text(get_path()) e.connect('changed', changed) hb.pack_start(e, True, True, 0) return hb �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9876022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016763� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/__init__.py�������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�021072� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/compressor.py�����������������������������������������������0000664�0001750�0001750�00000010472�14035600052�021533� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gst, Gtk, GObject from quodlibet import _ from quodlibet.plugins import PluginImportException from quodlibet.plugins.gstelement import GStreamerPlugin from quodlibet.qltk.util import GSignals from quodlibet import qltk from quodlibet import config _PLUGIN_ID = "compressor" _SETTINGS = { "threshold": [_("_Threshold:"), _("Threshold until the filter is activated"), 1.0], "ratio": [_("R_atio:"), _("Compression ratio"), 1.0], } def get_cfg(option): cfg_option = "%s_%s" % (_PLUGIN_ID, option) default = _SETTINGS[option][2] if option == "threshold": return config.getfloat("plugins", cfg_option, default) elif option == "ratio": return config.getfloat("plugins", cfg_option, default) def set_cfg(option, value): cfg_option = "%s_%s" % (_PLUGIN_ID, option) if get_cfg(option) != value: config.set("plugins", cfg_option, value) class Preferences(Gtk.VBox): __gsignals__: GSignals = { 'changed': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__(spacing=12) table = Gtk.Table(n_rows=2, n_columns=2) table.set_col_spacings(6) table.set_row_spacings(6) labels = {} for idx, key in enumerate(["threshold", "ratio"]): text, tooltip = _SETTINGS[key][:2] label = Gtk.Label(label=text) labels[key] = label label.set_tooltip_text(tooltip) label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) threshold_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(0, 0, 1, 0.01, 0.1, 0)) threshold_scale.set_digits(2) labels["threshold"].set_mnemonic_widget(threshold_scale) threshold_scale.set_value_pos(Gtk.PositionType.RIGHT) def format_perc(scale, value): return _("%d %%") % (value * 100) threshold_scale.connect('format-value', format_perc) table.attach(threshold_scale, 1, 2, 0, 1) def threshold_changed(scale): value = scale.get_value() set_cfg("threshold", value) self.emit("changed") threshold_scale.connect('value-changed', threshold_changed) threshold_scale.set_value(get_cfg("threshold")) ratio_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(0, 0, 1, 0.01, 0.1, 0)) ratio_scale.set_digits(2) labels["ratio"].set_mnemonic_widget(ratio_scale) ratio_scale.set_value_pos(Gtk.PositionType.RIGHT) table.attach(ratio_scale, 1, 2, 1, 2) def ratio_changed(scale): value = scale.get_value() set_cfg("ratio", value) self.emit("changed") ratio_scale.connect('value-changed', ratio_changed) ratio_scale.set_value(get_cfg("ratio")) self.pack_start(qltk.Frame(_("Preferences"), child=table), True, True, 0) class Compressor(GStreamerPlugin): PLUGIN_ID = _PLUGIN_ID PLUGIN_NAME = _("Audio Compressor") PLUGIN_DESC = _("Changes the amplitude of all samples above a specific " "threshold with a specific ratio.") @classmethod def setup_element(cls): return Gst.ElementFactory.make('audiodynamic', cls.PLUGIN_ID) @classmethod def update_element(cls, element): element.set_property("characteristics", "soft-knee") element.set_property("mode", "compressor") element.set_property("ratio", get_cfg("ratio")) element.set_property("threshold", get_cfg("threshold")) @classmethod def PluginPreferences(cls, window): prefs = Preferences() prefs.connect("changed", lambda *x: cls.queue_update()) return prefs if not Compressor.setup_element(): raise PluginImportException( "GStreamer element 'audiodynamic' missing (gst-plugins-good)") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/crossfeed.py������������������������������������������������0000664�0001750�0001750�00000013631�14035600052�021314� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gst, GObject from quodlibet import _ from quodlibet.plugins.gstelement import GStreamerPlugin from quodlibet import qltk, plugins from quodlibet.qltk.util import GSignals from quodlibet import config _PLUGIN_ID = "crossfeed" _SETTINGS = { "preset": [_("_Preset:"), _("Filter preset")], "fcut": [_("_Frequency cut:"), _("Low-pass filter cut frequency")], "feed": [_("Feed _level:"), _("Feed level")], } _PRESETS = [ ["default", _("Default"), _("Closest to virtual speaker placement (30°, 3 meter)"), 700, 45], ["cmoy", _("Chu Moy"), _("Close to Chu Moy's crossfeeder (popular)"), 700, 60], ["jmeier", _("Jan Meier"), _("Close to Jan Meier's CORDA amplifiers (little change)"), 650, 90], ["custom", _("Custom"), _("Custom settings"), -1, -1], ] _CUSTOM_INDEX = 3 def get_cfg(option): cfg_option = "%s_%s" % (_PLUGIN_ID, option) if option == "feed": return config.getint("plugins", cfg_option, _PRESETS[0][4]) elif option == "fcut": return config.getint("plugins", cfg_option, _PRESETS[0][3]) def set_cfg(option, value): cfg_option = "%s_%s" % (_PLUGIN_ID, option) if get_cfg(option) != value: config.set("plugins", cfg_option, value) class Preferences(Gtk.VBox): __gsignals__: GSignals = { 'changed': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__(spacing=12) table = Gtk.Table(n_rows=3, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = {} for idx, key in enumerate(["preset", "fcut", "feed"]): text, tooltip = _SETTINGS[key] label = Gtk.Label(label=text) labels[key] = label label.set_tooltip_text(tooltip) label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) preset_combo = Gtk.ComboBoxText() self.__combo = preset_combo labels["preset"].set_mnemonic_widget(preset_combo) for preset in _PRESETS: preset_combo.append_text(preset[1]) preset_combo.set_active(-1) table.attach(preset_combo, 1, 2, 0, 1) fcut_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(700, 300, 2000, 10, 100, 0)) fcut_scale.set_tooltip_text(_SETTINGS["fcut"][1]) labels["fcut"].set_mnemonic_widget(fcut_scale) fcut_scale.set_value_pos(Gtk.PositionType.RIGHT) def format_hz(scale, value): return _("%d Hz") % value fcut_scale.connect('format-value', format_hz) table.attach(fcut_scale, 1, 2, 1, 2) def fcut_changed(scale): value = int(scale.get_value()) set_cfg("fcut", value) self.__update_combo() self.emit("changed") fcut_scale.connect('value-changed', fcut_changed) fcut_scale.set_value(get_cfg("fcut")) level_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(45, 10, 150, 1, 5, 0)) level_scale.set_tooltip_text(_SETTINGS["feed"][1]) labels["feed"].set_mnemonic_widget(level_scale) level_scale.set_value_pos(Gtk.PositionType.RIGHT) def format_db(scale, value): return _("%.1f dB") % (value / 10.0) level_scale.connect('format-value', format_db) table.attach(level_scale, 1, 2, 2, 3) def level_changed(scale): value = int(scale.get_value()) set_cfg("feed", value) self.__update_combo() self.emit("changed") level_scale.connect('value-changed', level_changed) level_scale.set_value(get_cfg("feed")) def combo_change(combo, level_scale, fcut_scale): index = combo.get_active() if index == _CUSTOM_INDEX: combo.set_tooltip_text("") return tooltip, fcut, feed = _PRESETS[index][-3:] combo.set_tooltip_text(tooltip) level_scale.set_value(feed) fcut_scale.set_value(fcut) preset_combo.connect("changed", combo_change, level_scale, fcut_scale) self.__update_combo() self.pack_start(qltk.Frame(_("Preferences"), child=table), True, True, 0) def __update_combo(self): feed = get_cfg("feed") fcut = get_cfg("fcut") for i, preset in enumerate(_PRESETS): def_fcut, def_feed = preset[-2:] if def_fcut == fcut and def_feed == feed: self.__combo.set_active(i) return self.__combo.set_active(_CUSTOM_INDEX) class Crossfeed(GStreamerPlugin): PLUGIN_ID = _PLUGIN_ID PLUGIN_NAME = _("Crossfeed") PLUGIN_DESC = _("Mixes the left and right channel in a way that simulates" " a speaker setup while using headphones, or to adjust " "for early Stereo recordings.") PLUGIN_ICON = "audio-volume-high" @classmethod def setup_element(cls): return Gst.ElementFactory.make('bs2b', cls.PLUGIN_ID) @classmethod def update_element(cls, element): element.set_property("feed", get_cfg("feed")) element.set_property("fcut", get_cfg("fcut")) @classmethod def PluginPreferences(cls, window): prefs = Preferences() prefs.connect("changed", lambda *x: cls.queue_update()) return prefs if not Crossfeed.setup_element(): raise plugins.MissingGstreamerElementPluginException("bs2b") �������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/karaoke.py��������������������������������������������������0000664�0001750�0001750�00000010342�14035600052�020750� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gst, Gtk, GObject from quodlibet import _ from quodlibet.plugins import PluginImportException from quodlibet.plugins.gstelement import GStreamerPlugin from quodlibet import qltk from quodlibet import config from quodlibet.qltk import Icons from quodlibet.qltk.util import GSignals _PLUGIN_ID = "karaoke" _SETTINGS = { "band": [_("Filter _band:"), _("The Frequency band of the filter"), 220.0], "width": [_("Filter _width:"), _("The Frequency width of the filter"), 100.0], "level": [_("_Level:"), _("Level of the effect"), 1.0], } def get_cfg(option): cfg_option = "%s_%s" % (_PLUGIN_ID, option) default = _SETTINGS[option][2] return config.getfloat("plugins", cfg_option, default) def set_cfg(option, value): cfg_option = "%s_%s" % (_PLUGIN_ID, option) if get_cfg(option) != value: config.set("plugins", cfg_option, value) class Preferences(Gtk.VBox): __gsignals__: GSignals = { 'changed': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__(spacing=12) table = Gtk.Table(n_rows=3, n_columns=2) table.set_col_spacings(6) table.set_row_spacings(6) labels = {} for idx, key in enumerate(["level", "band", "width"]): label = Gtk.Label(label=_SETTINGS[key][0]) labels[key] = label label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_tooltip_text(_SETTINGS[key][1]) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) def scale_changed(scale, option): value = scale.get_value() set_cfg(option, value) self.emit("changed") max_values = [1.0, 441, 100] steps = [0.01, 10, 10] pages = [0.1, 50, 25] scales = {} for idx, key in enumerate(["level", "band", "width"]): max_value = max_values[idx] step = steps[idx] page = pages[idx] scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(0, 0, max_value, step, page, 0)) scales[key] = scale if step < 0.1: scale.set_digits(2) scale.add_mark(_SETTINGS[key][2], Gtk.PositionType.BOTTOM, None) labels[key].set_mnemonic_widget(scale) scale.set_value_pos(Gtk.PositionType.RIGHT) table.attach(scale, 1, 2, idx, idx + 1) scale.connect('value-changed', scale_changed, key) scale.set_value(get_cfg(key)) def format_perc(scale, value): return _("%d %%") % (value * 100) scales["level"].connect('format-value', format_perc) def format_hertz(scale, value): return _("%d Hz") % value scales["band"].connect('format-value', format_hertz) scales["width"].connect('format-value', format_hertz) self.pack_start(qltk.Frame(_("Preferences"), child=table), True, True, 0) class Karaoke(GStreamerPlugin): PLUGIN_ID = _PLUGIN_ID PLUGIN_NAME = _("Karaoke") PLUGIN_DESC = _("Removes main vocals from audio.") PLUGIN_ICON = Icons.AUDIO_INPUT_MICROPHONE @classmethod def setup_element(cls): return Gst.ElementFactory.make('audiokaraoke', cls.PLUGIN_ID) @classmethod def update_element(cls, element): element.set_property("level", get_cfg("level")) element.set_property("filter-band", get_cfg("band")) element.set_property("filter-width", get_cfg("width")) @classmethod def PluginPreferences(cls, window): prefs = Preferences() prefs.connect("changed", lambda *x: cls.queue_update()) return prefs if not Karaoke.setup_element(): raise PluginImportException( "GStreamer element 'audiokaraoke' missing (gst-plugins-good)") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/mono.py�����������������������������������������������������0000664�0001750�0001750�00000001534�14035600052�020306� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gst from quodlibet import _ from quodlibet.plugins.gstelement import GStreamerPlugin class MonoDownmix(GStreamerPlugin): PLUGIN_ID = "mono" PLUGIN_NAME = _("Mono Downmix") PLUGIN_DESC = _("Downmixes audio channels to mono.") priority = -1 @classmethod def setup_element(cls): element = Gst.ElementFactory.make('capsfilter', cls.PLUGIN_ID) if not element: return caps = Gst.Caps.from_string('audio/x-raw,channels=1') element.set_property('caps', caps) return element ��������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/gstreamer/pitch.py����������������������������������������������������0000664�0001750�0001750�00000007322�14035600052�020446� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2018 Ludovic Druette # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GObject, Gst from quodlibet import _ from quodlibet.plugins import PluginImportException from quodlibet.plugins.gstelement import GStreamerPlugin from quodlibet.qltk.util import GSignals from quodlibet import qltk from quodlibet import config _PLUGIN_ID = "pitch" _SETTINGS = { "rate": [_("R_ate:"), 1.0], "tempo": [_("_Tempo:"), 1.0], "pitch": [_("_Pitch:"), 1.0], } def get_cfg(option): cfg_option = "%s_%s" % (_PLUGIN_ID, option) default = _SETTINGS[option][1] if option == "rate": return config.getfloat("plugins", cfg_option, default) elif option == "tempo": return config.getfloat("plugins", cfg_option, default) elif option == "pitch": return config.getfloat("plugins", cfg_option, default) def set_cfg(option, value): cfg_option = "%s_%s" % (_PLUGIN_ID, option) if get_cfg(option) != value: config.set("plugins", cfg_option, value) class Preferences(Gtk.VBox): __gsignals__: GSignals = { 'changed': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__(spacing=12) table = Gtk.Table(n_rows=3, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) labels = {} for idx, key in enumerate(["tempo", "rate", "pitch"]): label = Gtk.Label(label=_SETTINGS[key][0]) labels[key] = label label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) def scale_changed(scale, option): value = scale.get_value() set_cfg(option, value) self.emit("changed") for idx, key in enumerate(["tempo", "rate", "pitch"]): adjustment = Gtk.Adjustment(0, 0.1, 3, 0.1, 1, 0) scale = Gtk.HScale(adjustment=adjustment) scale.set_digits(2) scale.add_mark(1.0, Gtk.PositionType.BOTTOM, None) labels[key].set_mnemonic_widget(scale) scale.set_draw_value(False) table.attach(scale, 1, 2, idx, idx + 1) spin = Gtk.SpinButton(adjustment=adjustment) spin.set_digits(2) table.attach(spin, 2, 3, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) scale.connect('value-changed', scale_changed, key) scale.set_value(get_cfg(key)) self.pack_start(qltk.Frame(_("Preferences"), child=table), True, True, 0) class Pitch(GStreamerPlugin): PLUGIN_ID = _PLUGIN_ID PLUGIN_NAME = _("Audio Pitch / Speed") PLUGIN_DESC = _("Controls the pitch of an audio stream.") @classmethod def setup_element(cls): return Gst.ElementFactory.make('pitch', cls.PLUGIN_ID) @classmethod def update_element(cls, element): for key in ["tempo", "rate", "pitch"]: element.set_property(key, get_cfg(key)) @classmethod def PluginPreferences(cls, window): prefs = Preferences() prefs.connect("changed", lambda *x: cls.queue_update()) return prefs if not Pitch.setup_element(): raise PluginImportException( "GStreamer element 'pitch' missing (gst-plugins-bad)") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9876022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/�������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016633� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/__init__.py��������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�020742� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684387440.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/export_to_folder.py������������������������������������������0000644�0001750�0001750�00000014224�14431333160�022565� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Didier Villevalois # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet.pattern import FileFromPattern from quodlibet.plugins import PluginConfig, ConfProp from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.qltk import Icons from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.notif import Task from quodlibet.qltk.window import Dialog from quodlibet.qltk.msg import ErrorMessage from quodlibet.util import copool from quodlibet.util.dprint import print_d from shutil import copyfile class ExportToFolderDialog(Dialog): """A dialog to collect export settings""" def __init__(self, parent, pattern): super().__init__( title=_("Export Playlist to Folder"), transient_for=parent, use_header_bar=True) self.set_default_size(400, -1) self.set_resizable(True) self.set_border_width(6) self.vbox.set_spacing(6) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Export"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) destination_label = Gtk.Label(_("Destination folder:")) destination_label.set_line_wrap(True) destination_label.set_xalign(0.0) box.pack_start(destination_label, False, False, 0) frame = Gtk.Frame() self.directory_chooser = Gtk.FileChooserWidget( action=Gtk.FileChooserAction.SELECT_FOLDER) self.directory_chooser.set_select_multiple(False) self.directory_chooser.set_border_width(1) frame.add(self.directory_chooser) frame.set_shadow_type(Gtk.ShadowType.IN) frame.set_border_width(0) box.pack_start(frame, True, True, 0) pattern_label = Gtk.Label(_("Filename pattern:")) pattern_label.set_line_wrap(True) pattern_label.set_xalign(0.0) box.pack_start(pattern_label, False, False, 0) self.pattern_entry = UndoEntry() self.pattern_entry.set_text(pattern) box.pack_start(self.pattern_entry, False, False, 0) self.vbox.pack_start(box, True, True, 0) self.set_response_sensitive(Gtk.ResponseType.OK, False) def changed(*args): has_directory = self.directory_chooser.get_filename() is not None self.set_response_sensitive(Gtk.ResponseType.OK, has_directory) pattern_text = self.pattern_entry.get_text() has_pattern = bool(pattern_text) self.set_response_sensitive(Gtk.ResponseType.OK, has_pattern) self.directory_chooser.connect("selection-changed", changed) self.pattern_entry.connect("changed", changed) self.get_child().show_all() class Config: _config = PluginConfig(__name__) DEFAULT_PATTERN = "<artist~title>" default_pattern = ConfProp(_config, "default_pattern", DEFAULT_PATTERN) CONFIG = Config() class ExportToFolder(PlaylistPlugin): PLUGIN_ID = "ExportToFolder" PLUGIN_NAME = _("Export Playlist to Folder") PLUGIN_DESC = _("Exports a playlist by copying files to a folder.") PLUGIN_ICON = Icons.FOLDER REQUIRES_ACTION = True def __copy_songs(self, task, songs, directory, pattern, parent=None): """Generator for copool to copy songs to the folder""" self.__cancel = False total = len(songs) print_d("Copying %d song(s) to directory %s. " "This might take a while..." % (total, directory)) for i, song in enumerate(songs): if self.__cancel: print_d("Cancelled export to directory.") self.__cancel = False break # Actually do the copy try: self._copy_file(song, directory, i + 1, pattern) except OSError as e: print_d("Unable to copy file: {}".format(e)) ErrorMessage(parent, _("Unable to export playlist"), _("Ensure you have write access to the destination.") ).run() break task.update(float(i) / total) yield True print_d("Finished export to directory.") task.finish() def __cancel_copy(self): """Tell the copool to stop copying songs""" self.__cancel = True def _copy_file(self, song, directory, index, pattern): filename = song["~filename"] print_d("Copying %s." % filename) new_name = pattern.format(song) copyfile(filename, "%s/%04d - %s" % (directory, index, new_name)) def plugin_playlist(self, playlist): pattern_text = CONFIG.default_pattern dialog = ExportToFolderDialog(self.plugin_window, pattern_text) if dialog.run() == Gtk.ResponseType.OK: directory = dialog.directory_chooser.get_filename() pattern = FileFromPattern(dialog.pattern_entry.get_text()) task = Task("Export", _("Export Playlist to Folder"), stop=self.__cancel_copy) copool.add(self.__copy_songs, task, playlist.songs, directory, pattern, self.plugin_window, funcid="export-playlist-folder") dialog.destroy() @classmethod def PluginPreferences(cls, parent): def changed(entry): CONFIG.default_pattern = entry.get_text() vbox = Gtk.VBox(spacing=6) def create_pattern(): hbox = Gtk.HBox(spacing=6) hbox.set_border_width(6) label = Gtk.Label(label=_("Default filename pattern:")) hbox.pack_start(label, False, True, 0) entry = UndoEntry() if CONFIG.default_pattern: entry.set_text(CONFIG.default_pattern) entry.connect('changed', changed) hbox.pack_start(entry, True, True, 0) return hbox vbox.pack_start(create_pattern(), True, True, 0) return vbox ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681806286.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/export_to_sonos.py�������������������������������������������0000644�0001750�0001750�00000024547�14417451716�022500� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2020-23 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import time import quodlibet DEVICE_CACHE_SEC = 600 try: from soco import SoCo, SoCoException from soco.data_structures import DidlMusicTrack, DidlPlaylistContainer, DidlItem except ImportError: raise quodlibet.plugins.MissingModulePluginException("soco") from typing import Text, Optional, Dict, Tuple, Collection from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.formats import AudioFile from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.qltk import Icons, Dialog, WarningMessage from quodlibet.qltk.notif import Task from quodlibet.util import copool, escape from quodlibet.util.dprint import print_d, print_w from quodlibet.util.string.filter import remove_punctuation try: import soco except ImportError: raise quodlibet.plugins.MissingModulePluginException("soco") PlaylistID = Text ID = Text Name = Text SonosPlaylistDict = Dict[PlaylistID, Name] class ComboBoxEntry(Gtk.ComboBox): def __init__(self, choices: Dict[Text, Text], tooltip_markup=None): super().__init__( model=Gtk.ListStore(str, str), entry_text_column=1, has_entry=True) self._fill_model(choices) if tooltip_markup: self.get_child().set_tooltip_markup(tooltip_markup) def _fill_model(self, choices: Dict[Text, Text]): self.clear() render = Gtk.CellRendererText() self.pack_start(render, True) self.add_attribute(render, 'text', 1) model = self.get_model() for id_, name in choices.items(): model.append(row=[id_, name]) self.set_model(model) comp = Gtk.EntryCompletion() comp.set_model(self.get_model()) comp.set_text_column(1) self.get_child().set_completion(comp) def get_chosen(self) -> Tuple[Optional[ID], Name]: tree_iter = self.get_active_iter() if tree_iter is not None: model = self.get_model() id_, name = model[tree_iter][:2] return id_, name entry = self.get_child() return None, entry.get_text() def set_text(self, text: Text): model = self.get_model() for i, (id_, value) in enumerate(model): if value == text: self.set_active(i) print_d(f"Text matched existing playlist: {id_} ({value!r})") return return self.get_child().set_text(text) class GetSonosPlaylistDialog(Dialog): def __init__(self, choices: SonosPlaylistDict): super().__init__(title="Which Sonos Playlist?", transient_for=None) self.options = choices self.set_border_width(6) self.set_resizable(True) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_OK"), Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) label = Gtk.Label( label=_("Type a new playlist name,\n" "or choose an existing Sonos playlist to overwrite")) box.set_border_width(6) label.set_line_wrap(True) label.set_justify(Gtk.Justification.CENTER) box.pack_start(label, True, True, 0) self._combo = ComboBoxEntry(choices) box.pack_start(self._combo, False, False, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all() def run(self, text: Optional[Text] = None) -> Optional[Tuple[Optional[Name], Text]]: self.show() if text: self._combo.set_text(text) self._combo.grab_focus() resp = super().run() try: return (self._combo.get_chosen() if resp == Gtk.ResponseType.OK else None) finally: self.destroy() class SonosPlaylistPlugin(PlaylistPlugin): PLUGIN_ID = "Export to Sonos Playlist" PLUGIN_NAME = _("Export to Sonos Playlist") PLUGIN_DESC = _("Exports a playlist to Sonos by matching tracks.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP REQUIRES_ACTION = True DEBUG = False MAX_RESULTS_PER_SEARCH = 10 """Request this many max results, for each search to then filter in code""" def __init__(self, playlists=None, library=None): super().__init__(playlists, library) self.__cancel = False self.devices = [] self._last_discovery = 0 def enabled(self): print_d(f"Using Sonos device: {self.device}") @property def device(self) -> Optional[SoCo]: now = time.time() if not self.devices or now - self._last_discovery > DEVICE_CACHE_SEC: devices = soco.discover() print_d(f"Found {len(devices)} Sonos devices") coords = [d for d in devices if d.is_coordinator] if not coords: raise Exception(f"No Sonos coordinators found in {devices}") print_d(f"Found {len(coords)} Sonos coordinators") self.devices = coords self._last_discovery = now return self.devices[0] def __cancel_add(self): """Tell the copool to stop (adding songs)""" self.__cancel = True @classmethod def _score(cls, t: DidlMusicTrack, song: AudioFile) -> float: d = t.to_dict() try: person = song.list("~people")[0] except IndexError: person = None album = song("album") score = (int(remove_punctuation(t.title).lower() == remove_punctuation(song("title")).lower()) + int(bool(person) and person in d.values()) + int(bool(album) and album in d.get("album", ""))) if cls.DEBUG: print_d("%.1f for %s (%s)" % (score, t.title, d)) return score def __add_songs(self, task: Task, songs: Collection[AudioFile], spl: DidlPlaylistContainer): """Generator for copool to add songs to the temp playlist""" assert self.device task_total = float(len(songs)) print_d("Adding %d song(s) to Sonos playlist. " "This might take a while..." % task_total) failures = [] for i, song in enumerate(songs): if self.__cancel: print_d("Cancelled Sonos export") return lib = self.device.music_library # Exact title gets the best results it seems; some problems with ’ search_term = song("title") assert search_term results = lib.get_tracks(search_term=search_term, max_items=self.MAX_RESULTS_PER_SEARCH) yield total = len(results) if total == 1: track = results[0] elif total > 1: desc = song("~~people~album~title") candidates = [(self._score(t, song), t) for t in results] in_order = sorted(candidates, reverse=True, key=lambda x: x[0]) track = in_order[0][1] print_d(f"From {len(results)} choice(s) for {desc!r}, " f"chose {self.uri_for(track)}") else: print_w("No results for \"%s\"" % search_term) failures.append(search_term) track = None if track: try: self.device.add_item_to_sonos_playlist(track, spl) except SoCoException as e: failures.append(track) print_w(f"Couldn't add {track} ({e}, skipping") task.update(float(i) / task_total) yield task.update((task_total - 2) / task_total) yield task.finish() if failures: print_w(f"Got {len(failures)} failure(s), of {int(task_total)}: {failures}") successes = int(task_total) - len(failures) print_d(f"Finished export to {spl.title!r}, {successes} tracks in total") @staticmethod def uri_for(track: DidlItem) -> Text: """More usable elsewhere (on Linux at least)""" return track.get_uri().replace("x-file-cifs", "smb") def plugin_playlist(self, playlist): print_d(f"Using Sonos device: {self.device!r}") device = self.device if not device: qltk.ErrorMessage( app.window, _("Error finding Sonos device(s)"), _("Error finding Sonos. Please check settings") ).run() else: sonos_pls = device.get_sonos_playlists() pl_id_to_name = {pl.item_id: pl.title for pl in sonos_pls} print_d("Sonos playlists: %s" % pl_id_to_name) ret = GetSonosPlaylistDialog(pl_id_to_name).run(playlist.name) if ret: spl_id, name = ret if spl_id: spl: DidlPlaylistContainer = next(s for s in sonos_pls if s.item_id == spl_id) print_w(f"Replacing existing Sonos playlist {spl_id} ({spl.title})") try: device.remove_sonos_playlist(spl) print_d("Removed existing playlist OK") except SoCoException as e: tmpl = _("Failed to delete existing Sonos playlist %s:") err_str = f" \n<tt>{escape(e)!r}</tt>" dialog = WarningMessage(None, tmpl % escape(spl.title) + err_str, escape_desc=False) dialog.run() return print_d(f"Creating new playlist {name!r}") spl = device.create_sonos_playlist(name) data = {"playlist": name[:30], "total": len(playlist)} task = Task("Sonos", _("Export to playlist %(playlist)r " "(%(total)d tracks)") % data, stop=self.__cancel_add) copool.add(self.__add_songs, task, playlist.songs, spl, funcid="sonos-playlist-save") ���������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/export_to_squeezebox.py��������������������������������������0000664�0001750�0001750�00000010107�14231604332�023502� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.qltk.notif import Task from quodlibet.qltk import Icons from quodlibet.qltk.getstring import GetStringDialog from quodlibet.util import copool from quodlibet.util.dprint import print_d from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.ext._shared.squeezebox.base import SqueezeboxPluginMixin class SqueezeboxPlaylistPlugin(PlaylistPlugin, SqueezeboxPluginMixin): PLUGIN_ID = "Export to Squeezebox Playlist" PLUGIN_NAME = _(u"Export to Squeezebox") PLUGIN_DESC_MARKUP = ( _("Dynamically exports a playlist to Logitech Squeezebox " "playlist, provided both share a directory structure.") + "\n" + _("Shares configuration with <a href=\"%(plugin_link)s\">Squeezebox " "Sync plugin</a>.") % {"plugin_link": "quodlibet:///prefs/plugins/Squeezebox Output"} ) PLUGIN_ICON = Icons.NETWORK_WORKGROUP ELLIPSIZE_NAME = True _PERSIST_FUDGE = 100 TEMP_PLAYLIST = "_quodlibet" def __add_songs(self, task, songs, name): """Generator for copool to add songs to the temp playlist""" print_d("Backing up current Squeezebox playlist." "This can take a while if your current playlist is big...") self.__cancel = False # Arbitrarily assign playlist operations a value of 2 * addition task_total = float(len(songs) + 2 * self._PERSIST_FUDGE + 3 * 2) self.server.playlist_save(self.TEMP_PLAYLIST) task.update(self._PERSIST_FUDGE / task_total) yield True self.server.playlist_clear() task.update((self._PERSIST_FUDGE + 2.0) // task_total) yield True # Check if we're currently playing. stopped = self.server.is_stopped() total = len(songs) print_d("Adding %d song(s) to Squeezebox playlist. " "This might take a while..." % total) for i, song in enumerate(songs): if self.__cancel: print_d("Cancelled squeezebox export") self.__cancel = False break # Actually do the (slow) call self.server.playlist_add(self.get_sb_path(song)) task.update(float(i) / task_total) yield True print_d("Saving Squeezebox playlist \"%s\"" % name) self.server.playlist_save(name) task.update((task_total - 2) / task_total) yield True # Resume if we actually stopped self.server.playlist_resume(self.TEMP_PLAYLIST, not stopped, True) task.finish() def __cancel_add(self): """Tell the copool to stop (adding songs)""" self.__cancel = True @staticmethod def __get_playlist_name(name="Quod Libet playlist"): dialog = GetStringDialog(None, _("Export playlist to Squeezebox"), _("Playlist name (will overwrite existing)"), button_label=_("_Save"), button_icon=Icons.DOCUMENT_SAVE) name = dialog.run(text=name) return name def plugin_playlist(self, playlist): self.init_server() if not self.server.is_connected: qltk.ErrorMessage( app.window, _("Error finding Squeezebox server"), _("Error finding %s. Please check settings") % self.server.config ).run() else: name = self.__get_playlist_name(name=playlist.name) if name: task = Task("Squeezebox", _("Export to Squeezebox playlist"), stop=self.__cancel_add) copool.add(self.__add_songs, task, playlist.songs, name, funcid="squeezebox-playlist-save") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/remove_duplicates.py�����������������������������������������0000664�0001750�0001750�00000004235�14035600052�022721� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.formats import AudioFile from quodlibet import print_d, ngettext, _ from quodlibet import qltk from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.qltk import Icons from gi.repository import Gtk class RemoveDuplicates(PlaylistPlugin): PLUGIN_ID = "Remove Playlist Duplicates" PLUGIN_NAME = _("Remove Playlist Duplicates") PLUGIN_DESC = _("Removes duplicate entries in a playlist.") PLUGIN_ICON = Icons.EDIT_CLEAR def plugin_handles(self, playlists): return len(playlists) == 1 and playlists[0].has_duplicates def plugin_playlist(self, playlist): songs = filter(lambda s: isinstance(s, AudioFile), playlist.songs) unique = set() dupes = list() for s in songs: if s in unique: dupes.append(s) else: unique.add(s) if len(dupes) < 1: print_d("No duplicates in this playlist") return dialog = ConfirmRemoveDuplicatesDialog(self, playlist, len(dupes)) if dialog.run() == Gtk.ResponseType.YES: playlist.remove_songs(dupes, True) return True return False class ConfirmRemoveDuplicatesDialog(qltk.Message): def __init__(self, parent, playlist, count): title = ngettext("Are you sure you want to remove %d duplicate song?", "Are you sure you want to remove %d duplicate songs?", count) % count description = (_("The duplicate songs will be removed " "from the playlist '%s'.") % playlist.name) super().__init__( Gtk.MessageType.WARNING, parent, title, description, Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Remove"), Icons.LIST_REMOVE, Gtk.ResponseType.YES) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playlist/shuffle.py���������������������������������������������������0000664�0001750�0001750�00000001444�14035600052�020642� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014,2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.qltk import Icons class Shuffle(PlaylistPlugin): PLUGIN_ID = "Shuffle Playlist" PLUGIN_NAME = _("Shuffle Playlist") PLUGIN_DESC = _("Randomly shuffles a playlist.") PLUGIN_ICON = Icons.MEDIA_PLAYLIST_SHUFFLE def plugin_playlist(self, playlist): playlist.shuffle() return True def plugin_handles(self, playlists): return len(playlists) == 1 and len(playlists[0].songs) > 1 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9876022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016773� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/__init__.py�������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�021102� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/follow.py���������������������������������������������������0000664�0001750�0001750�00000003521�14231604332�020651� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010 Christoph Reiter # 2016,20 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet.order import OrderInOrder, OrderRemembered from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.qltk import Icons class FollowOrder(ShufflePlugin, OrderInOrder, OrderRemembered): PLUGIN_ID = "follow" PLUGIN_NAME = _("Follow Cursor") PLUGIN_ICON = Icons.GO_JUMP PLUGIN_DESC = _("Adds a play order mode that follows your selection, " "or the next song in the list once exhausted.") display_name = _("Follow cursor") accelerated_name = _("_Follow cursor") __last_path = None def next(self, playlist, iter): next_fallback = OrderInOrder.next(self, playlist, iter) OrderRemembered.next(self, playlist, iter) selected = app.window.songlist.get_selected_songs() if not selected: return next_fallback selected_iter = playlist.find(selected[0]) selected_path = playlist.get_path(selected_iter) current_path = iter and playlist.get_path(iter) if selected_path in (current_path, self.__last_path): return next_fallback self.__last_path = selected_path return selected_iter def previous(self, *args): self.__last_path = None return super().previous(*args) def set(self, playlist, iter): if iter: self.__last_path = playlist.get_path(iter) return super().set(playlist, iter) def reset(self, playlist): super().reset(playlist) self.__last_path = None �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/playcounteq.py����������������������������������������������0000664�0001750�0001750�00000003564�14231604332�021722� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2016 Ryan "ZDBioHazard" Turner <zdbiohazard2@gmail.com> # 2016-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import math import random from quodlibet import _ from quodlibet.order.reorder import Reorder from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.order import OrderRemembered from quodlibet.qltk import Icons class PlaycountEqualizer(ShufflePlugin, OrderRemembered): PLUGIN_ID = "playcounteq" PLUGIN_NAME = _("Playcount Equalizer") PLUGIN_DESC = _("Adds a shuffle mode " "that prefers songs with fewer total plays.") PLUGIN_ICON = Icons.MEDIA_PLAYLIST_SHUFFLE display_name = _("Prefer less played") accelerated_name = _("Prefer _less played") priority = Reorder.priority # Select the next track. def next(self, playlist, current): super().next(playlist, current) remaining = self.remaining(playlist) # Don't try to search through an empty / played playlist. if len(remaining) <= 0: return None # Set-up the search information. max_count = max([song('~#playcount') for song in remaining.values()]) weights = {i: max_count - song('~#playcount') for i, song in remaining.items()} choice = int(max(1, math.ceil(sum(weights) * random.random()))) # Search for a track. for i, weight in weights.items(): choice -= weight if choice <= 0: return playlist.get_iter([i]) else: # This should only happen if all songs have equal play counts. return playlist.get_iter([random.choice(list(remaining.keys()))]) ��������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/queue.py����������������������������������������������������0000644�0001750�0001750�00000004553�14267565021�020511� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2009 Steven Robertson # 2016-20 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet import qltk from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk import Icons from quodlibet.qltk.playorder import OrderInOrder from gi.repository import Gtk class QueueOrder(ShufflePlugin, OrderInOrder): PLUGIN_ID = "queue" PLUGIN_NAME = _("Queue Only") PLUGIN_ICON = Icons.VIEW_LIST PLUGIN_DESC = _("Limits playing of songs to the queue.\n\n" "Select this play order in the main window, " "then double-clicking any song will enqueue it " "instead of playing.") display_name = _("Queue only") accelerated_name = _("_Queue only") def PluginPreferences(self): box = Gtk.HBox() ccb = ConfigCheckButton(_("Automatically start playing " "double-clicked songs"), 'plugins', 'queue_only_autoplay') autoplay = config.getboolean('plugins', 'queue_only_autoplay', False) ccb.set_active(autoplay) box.pack_start(qltk.Frame(_("Preferences"), child=ccb), True, True, 0) return box def next(self, playlist, iter): return None def set_explicit(self, playlist, iter): if iter is None: return song = playlist[iter][0] if song is None: return # store queue size for jumping to newly added items queue = app.window.playlist.q queue_size = len(queue) app.window.playlist.enqueue([playlist[iter][0]]) # if setting enabled, start playing the first added song autoplay = config.getboolean("plugins", "queue_only_autoplay", False) if autoplay and len(queue) > queue_size: # queue_size is 1 greater than previous last index new_song_iter = queue.iter_nth_child(None, queue_size) app.window.playlist._player.go_to(new_song_iter, True, queue) app.window.playlist._player.play() �����������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/reverse.py��������������������������������������������������0000664�0001750�0001750�00000001612�14231604332�021021� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.qltk import Icons from quodlibet.qltk.playorder import OrderInOrder class ReverseOrder(ShufflePlugin, OrderInOrder): PLUGIN_ID = "reverse" PLUGIN_NAME = _("Reverse") PLUGIN_ICON = Icons.MEDIA_SKIP_BACKWARD PLUGIN_DESC = _("Adds a shuffle mode " "that reverses the play order of songs.") display_name = _("Reverse") accelerated_name = _("Re_verse") def previous(self, playlist, iter): return super().next(playlist, iter) def next(self, playlist, iter): return super().previous(playlist, iter) ����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/shufflebygrouping.py����������������������������������������0000664�0001750�0001750�00000016320�14231604332�023112� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Phoenix Dailey # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import random from gi.repository import Gtk, GLib from quodlibet import _ from quodlibet import app from quodlibet.order import OrderInOrder from quodlibet.order import OrderRemembered from quodlibet.order.reorder import Reorder from quodlibet.plugins import PluginConfig from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.qltk import Icons from quodlibet.qltk.notif import Task pconfig = PluginConfig("shufflebygrouping") pconfig.defaults.set("grouping", "~grouping~album~albumartist") pconfig.defaults.set("grouping_filter", "grouping") pconfig.defaults.set("delay", 0) class ShuffleByGrouping(ShufflePlugin, OrderRemembered): PLUGIN_ID = "Shuffle by Grouping" PLUGIN_NAME = _("Shuffle by Grouping") PLUGIN_DESC = _("Adds a shuffle mode that groups songs with a common tag " "– similar to album shuffles.\n\n" "This is useful for shuffling multi-movement classical " "pieces, making sure all movements play in order " "before shuffling to the next piece.") PLUGIN_ICON = Icons.MEDIA_PLAYLIST_SHUFFLE display_name = _("Shuffle by grouping") accelerated_name = _("Shuffle by _grouping") priority = Reorder.priority def next(self, playlist, current_song): return self._next(playlist, current_song) def _next(self, playlist, current_song, delay_on=True): grouping = str(pconfig.gettext("grouping")).strip() grouping_filter = str(pconfig.gettext("grouping_filter")).strip() delay = pconfig.getint("delay") def same_group(song_iter_a, song_iter_b): if song_iter_a is None or song_iter_b is None: return False song_a = playlist.get_value(song_iter_a) song_b = playlist.get_value(song_iter_b) if not self._tag_defined(grouping_filter, song_a): return False if not self._tag_defined(grouping_filter, song_b): return False return song_a(grouping) == song_b(grouping) # Keep track of played songs OrderRemembered.next(self, playlist, current_song) remaining = OrderRemembered.remaining(self, playlist) # Check if playlist is finished or empty if not remaining: OrderRemembered.reset(self, playlist) return None # Play next song in current grouping next_song = OrderInOrder.next(self, playlist, current_song) if same_group(next_song, current_song): return next_song # Pause for a moment before picking new group if delay_on: self._resume_after_delay(delay) # Pick random song at the start of a new group while True: song_location = random.choice(list(remaining.keys())) new_song = playlist.get_iter(song_location) new_song_prev = (playlist.get_iter(song_location - 1) if song_location >= 1 else None) if not same_group(new_song, new_song_prev): return new_song @staticmethod def _resume_after_delay(delay, refresh_rate=20): if delay <= 0: return app.player.paused = True delay_timer = GLib.timeout_add(1000 * delay, app.player.play) task = Task(_("Shuffle by Grouping"), _("Waiting to start new group…"), stop=lambda: GLib.source_remove(delay_timer)) def countdown(): for i in range(int(refresh_rate * delay)): task.update(i / (refresh_rate * delay)) yield True task.finish() yield False GLib.timeout_add(1000 / refresh_rate, next, countdown()) @staticmethod def _tag_defined(tag_name, song): if not tag_name: return True tag_value = song(tag_name) return bool(tag_value.strip()) def next_explicit(self, playlist, current_song): return self._next(playlist, current_song, delay_on=False) def previous(self, playlist, current_song): return OrderRemembered.previous(self, playlist, current_song) @classmethod def PluginPreferences(cls, window): def on_change(widget, config_entry): config_value = widget.get_text() pconfig.set(config_entry, config_value) def on_spin(widget, config_entry): config_value = widget.get_value() pconfig.set(config_entry, config_value) def default_on_click(widget): pconfig.reset("grouping") pconfig.reset("grouping_filter") pconfig.reset("delay") grouping_entry.set_text(pconfig.gettext("grouping")) grouping_filter_entry.set_text(pconfig.gettext("grouping_filter")) delay_spin.set_value(pconfig.getint("delay")) def make_label(label_text): label = Gtk.Label(label_text, selectable=True) label.set_alignment(0.0, 0.5) label.set_margin_end(3) return label vbox = Gtk.VBox(spacing=12) grouping_label = make_label(_("Grouping tag:")) grouping_entry = Gtk.Entry() grouping_entry.connect('changed', on_change, "grouping") grouping_entry.set_text(pconfig.gettext("grouping")) grouping_entry.set_tooltip_text(_("Tag to group songs by")) grouping_filter_label = make_label(_("Filter tag:")) grouping_filter_entry = Gtk.Entry() grouping_filter_entry.connect('changed', on_change, "grouping_filter") grouping_filter_entry.set_text(pconfig.gettext("grouping_filter")) grouping_filter_entry.set_tooltip_text(_( "Grouping is applied only if the filter tag is defined.\n" "A song with an undefined filter tag will be treated as\n" "a group consisting only of itself. Typically the filter\n" "tag should match or partially match the grouping tag.")) delay_label = make_label(_("Delay:")) adj = Gtk.Adjustment.new(pconfig.getint("delay"), 0, 3600, 1, 5, 0) delay_spin = Gtk.SpinButton(adjustment=adj, climb_rate=0.1, digits=0) delay_spin.set_numeric(True) delay_spin.connect('value-changed', on_spin, "delay") delay_spin.set_tooltip_text(_( "Time delay in seconds before starting next group")) table = Gtk.Table(3, 2) table.set_col_spacings(6) table.set_row_spacings(6) table.attach(grouping_label, 0, 1, 0, 1, Gtk.AttachOptions.FILL) table.attach(grouping_filter_label, 0, 1, 1, 2, Gtk.AttachOptions.FILL) table.attach(delay_label, 0, 1, 2, 3, Gtk.AttachOptions.FILL) table.attach(grouping_entry, 1, 2, 0, 1) table.attach(grouping_filter_entry, 1, 2, 1, 2) table.attach(delay_spin, 1, 2, 2, 3) vbox.add(table) defaults = Gtk.Button(_("Reset to defaults")) defaults.connect('clicked', default_on_click) vbox.add(defaults) return vbox ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/skip_disliked.py��������������������������������������������0000644�0001750�0001750�00000005120�14310167056�022165� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-20 Nick Boultbee # 2017 Jason Heard # 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _, print_d from quodlibet.order import OrderInOrder from quodlibet.plugins import PluginConfig from quodlibet.plugins.playorder import ShufflePlugin from quodlibet.qltk import Icons pconfig = PluginConfig("skip_songs") pconfig.defaults.set("threshold", 0.0) class SkipDisliked(ShufflePlugin, OrderInOrder): PLUGIN_ID = "skip_songs" PLUGIN_NAME = _("Skip Disliked Tracks") PLUGIN_ICON = Icons.GO_JUMP PLUGIN_DESC = _("Adds a play order (shuffle) mode that plays in order, " "but skips tracks with a rating " "below (or equal to) a given threshold.") display_name = _("Skip disliked tracks") accelerated_name = _("Skip _disliked tracks") @classmethod def PluginPreferences(cls, window): vb = Gtk.VBox(spacing=10) vb.set_border_width(0) adj = Gtk.Adjustment.new( pconfig.getfloat("threshold"), 0, 1.0, 0.01, 0.01, 0.0) fb_spin = Gtk.SpinButton(adjustment=adj) fb_spin.set_digits(2) def on_changed(button): pconfig.set("threshold", button.get_value()) fb_spin.connect('changed', on_changed) vb.add(fb_spin) vb.show_all() return vb def next(self, playlist, current): next_ = super().next(playlist, current) while next_ is not None and self._should_skip(playlist, next_): next_ = super().next(playlist, next_) return next_ def previous(self, playlist, current): previous = super().previous(playlist, current) is_first = False while not is_first and previous is not None and \ self._should_skip(playlist, previous): previous = super().previous(playlist, previous) is_first = playlist.get_path(previous).get_indices()[0] == 0 return previous def _should_skip(self, playlist, song_iter): song = playlist.get_value(song_iter) if not song.has_rating: return False rating = song("~#rating") threshold = pconfig.getfloat("threshold") if rating <= threshold: print_d("Rating is %f <= %f; skipping..." % (rating, threshold)) return True return False ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/playorder/track_repeat.py���������������������������������������������0000644�0001750�0001750�00000005647�14267565021�022036� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet.order.repeat import Repeat from quodlibet.plugins.playorder import RepeatPlugin from quodlibet.util.dprint import print_d from quodlibet.plugins import PluginConfigMixin from quodlibet.qltk import Icons START_COUNT = 1 class TrackRepeatOrder(RepeatPlugin, PluginConfigMixin): """ Repeats a given track a configurable number of times Useful for musicians practising / working out songs... or maybe you just REALLY like your playlist. """ PLUGIN_ID = "track_repeat" PLUGIN_NAME = _("Repeat Each Track") PLUGIN_ICON = Icons.MEDIA_PLAYLIST_REPEAT PLUGIN_DESC = _("Adds a shuffle mode that plays tracks in order, " "but repeating every track a set number of times.") display_name = _("Repeat each track") accelerated_name = _("Repeat _each track") PLAY_EACH_DEFAULT = 2 START_COUNT = 1 """By the time this plugin is invoked, the song has already been played""" # Plays of the current song play_count = START_COUNT priority = Repeat.priority @classmethod def PluginPreferences(cls, parent): def plays_changed(spin): cls.config_set("play_each", int(spin.get_value())) vb = Gtk.VBox(spacing=10) vb.set_border_width(10) hbox = Gtk.HBox(spacing=6) lbl = Gtk.Label(label=_("Number of times to play each song:")) hbox.pack_start(lbl, False, True, 0) val = cls.config_get("play_each", cls.PLAY_EACH_DEFAULT) spin = Gtk.SpinButton( adjustment=Gtk.Adjustment.new(float(val), 2, 20, 1, 10, 0)) spin.connect("value-changed", plays_changed) hbox.pack_start(spin, False, True, 0) vb.pack_start(hbox, True, True, 0) vb.show_all() return vb def restart_counting(self): self.play_count = START_COUNT print_d("Resetting play count") def next(self, playlist, iter): play_each = int(self.config_get('play_each', self.PLAY_EACH_DEFAULT)) self.play_count += 1 if self.play_count <= play_each and iter is not None: print_d("Play count now at %d/%d" % (self.play_count, play_each)) return iter else: self.restart_counting() return self.wrapped.next(playlist, iter) def next_explicit(self, playlist, iter): self.restart_counting() return self.wrapped.next_explicit(playlist, iter) def set(self, playlist, iter): self.restart_counting() return super().set(playlist, iter) def reset(self, playlist): self.play_count = 0 return super().reset(playlist) �����������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9876022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016137� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/__init__.py�����������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�020246� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/conditional.py��������������������������������������������������0000664�0001750�0001750�00000002307�14231604332�021017� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Ryan Dellenbaugh # 2020 Nick Boultbee # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.query import QueryPlugin, QueryPluginError, markup_for_syntax from quodlibet.query._parser import QueryParser class ConditionalQuery(QueryPlugin): PLUGIN_ID = "conditional_query" PLUGIN_NAME = _("Conditional Query") PLUGIN_DESC = _("Chooses the query to match based on a condition query.") key = 'if' query_syntax = _("@(if: condition-query, then-query, else-query)") usage = markup_for_syntax(query_syntax) def search(self, song, body): if body[0].search(song): return body[1].search(song) else: return body[2].search(song) def parse_body(self, body): if body is None: raise QueryPluginError parser = QueryParser(body) queries = parser.match_list(parser.Query) if len(queries) != 3: raise QueryPluginError return queries �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/missing.py������������������������������������������������������0000664�0001750�0001750�00000002744�14231604332�020172� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet.plugins.query import QueryPlugin, markup_for_syntax from quodlibet.plugins import PluginConfigMixin from quodlibet.qltk import Frame class MissingQuery(QueryPlugin, PluginConfigMixin): PLUGIN_ID = "missing_query" PLUGIN_NAME = _("Missing Query") PLUGIN_DESC = _("Matches songs without the given tag.") key = 'missing' query_syntax = "@(missing: artist)" usage = markup_for_syntax(query_syntax) def search(self, data, body): val = data.get(body.strip() if body else '', None) return (val is None or (self.config_get_bool("include_empty", True) and val == "")) @classmethod def PluginPreferences(cls, window): example = super().PluginPreferences(window) box = Gtk.VBox() box.pack_start(example, True, True, 0) prefs_box = Gtk.VBox() button = cls.ConfigCheckButton(_("Include empty tags"), "include_empty", True) prefs_box.pack_start(button, False, False, 6) frame = Frame(_("Preferences"), child=prefs_box) box.pack_start(frame, True, True, 12) return box ����������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684264158.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/pythonexpression.py���������������������������������������������0000644�0001750�0001750�00000004620�14430752336�022164� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Ryan Dellenbaugh # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import random import time from quodlibet import _, print_d, print_w from quodlibet.plugins.query import QueryPlugin, QueryPluginError, markup_for_syntax class PythonQuery(QueryPlugin): PLUGIN_ID = "python_query" PLUGIN_NAME = _("Python Query") PLUGIN_DESC = _("🐍Use Python expressions in queries.") key = 'python' query_syntax = _("@(python: expression)") query_description = _( "The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being " "matched." "\n\n" "<tt>_ts</tt> is a (real number) timestamp at start of query." "\n\n" "Modules <tt>time</tt> and <tt>random</tt> are also available, and the " "class <tt>Random</tt> (==<tt>random.Random</tt>) too.") usage = markup_for_syntax(query_syntax) + "\n\n" + query_description def __init__(self): print_d("Initialising") self._globals = {'random': random, 'Random': random.Random, 'time': time} self._reported = set() self._raw_body = None def search(self, data, body): try: self._globals['s'] = data # Albums can be queried too... self._globals['a'] = data # eval modifies the globals in place, it seems ret = eval(body, dict(self._globals)) return ret except Exception as e: key = str(e) if key not in self._reported: self._reported.add(key) print_w("%s(%s) in expression '%s'. " "Example failing data: %s" % (type(e).__name__, key, self._raw_body, self._globals)) return False def parse_body(self, body): if body is None: raise QueryPluginError self._raw_body = body.strip() self._reported.clear() try: self._globals.update(_ts=time.time()) return compile(body.strip(), 'query', 'eval') except SyntaxError as e: print_w("Couldn't compile query (%s)" % e) raise QueryPluginError ����������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/savedsearch.py��������������������������������������������������0000664�0001750�0001750�00000004150�14231604332�021002� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Ryan Dellenbaugh # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os.path from quodlibet import _, print_w from quodlibet.plugins.query import QueryPlugin, QueryPluginError, markup_for_syntax from quodlibet.query import Query from quodlibet.query._match import Error as QueryError from quodlibet import get_user_dir class IncludeSavedSearchQuery(QueryPlugin): PLUGIN_ID = "include_saved" PLUGIN_NAME = _("Include Saved Search") PLUGIN_DESC = _("💾 Include the results of a saved search " "as part of another query.") key = "saved" query_syntax = _("@(saved: search-name)") usage = markup_for_syntax(query_syntax) def search(self, data, body): return body.search(data) def parse_body(self, body, query_path_=None): if body is None: raise QueryPluginError body = body.strip().lower() # Use provided query file for testing if query_path_: query_path = query_path_ else: query_path = os.path.join(get_user_dir(), 'lists', 'queries.saved') try: with open(query_path, 'r', encoding="utf-8") as query_file: for query_string in query_file: name = next(query_file).strip().lower() if name == body: try: return Query(query_string.strip()) except QueryError: raise QueryPluginError # We've searched the whole file and haven't found a match print_w(f"None found for {body}") raise QueryPluginError except IOError: raise QueryPluginError except StopIteration: # The file has an odd number of lines. This shouldn't happen unless # it has been externally modified raise QueryPluginError ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1676832588.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/query/unique.py�������������������������������������������������������0000644�0001750�0001750�00000004106�14374467514�020040� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2023 LoveIsGrief # # 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 2 of the License, or # (at your option) any later version. from typing import Any, Optional from quodlibet import _, print_d, print_w from quodlibet.formats import AudioFile from quodlibet.plugins.query import QueryPlugin, QueryPluginError class UniqueQuery(QueryPlugin): PLUGIN_ID = "unique_query" PLUGIN_NAME = _("Unique Query") PLUGIN_DESC = _("Filter search results by unique tags.") key = 'unique' query_syntax = _("@(unique: tag)") query_description = "<tt>tag</tt> can be album, artist, title or any other tag. " \ "Use multiple <tt>@(unique: tag)</tt> to filter by multiple tags." usage = f"{query_syntax}\n\n{query_description}" def __init__(self): self.unique_tag_values = set() """The unique tag values that have been seen in the songs being filtered""" self._reported = set() """Unique errors to counter error log spam""" def search(self, song: AudioFile, body: Optional[Any]) -> bool: return_value = False try: field_value = song[body] return_value = field_value not in self.unique_tag_values self.unique_tag_values.add(field_value) print_d(f"unique filtering value '{field_value}': {return_value}") except KeyError: pass except Exception as e: err_str = str(e) if err_str not in self._reported: self._reported.add(err_str) print_w(f"{type(e).__name__} while filtering unique values for " f"'{body}': {err_str}") return return_value def parse_body(self, body: str) -> str: self.unique_tag_values.clear() if body is None: raise QueryPluginError unique_tag = body.strip() print_d(f"unique filtering tag: {unique_tag}") self._reported.clear() return unique_tag ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9909356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�017010� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/__init__.py�������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�021117� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/albumart.py�������������������������������������������������0000644�0001750�0001750�00000077137�14327505043�021214� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Eduardo Gonzalez <wm.eddie@gmail.com>, Niklas Janlert # 2006 Joe Wreschnig # 2008 Antonio Riva, Eduardo Gonzalez <wm.eddie@gmail.com>, # Anthony Bretaudeau <wxcover@users.sourceforge.net>, # 2010 Aymeric Mansoux <aymeric@goto10.org> # 2008-2013 Christoph Reiter # 2011-2022 Nick Boultbee # 2016 Mice Pápai # # 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 2 of the License, or # (at your option) any later version. import gzip import json import os import re import threading import time from io import BytesIO from typing import List, Dict, Any from urllib.parse import urlencode from gi.repository import Gtk, Pango, GLib, Gdk, GdkPixbuf from quodlibet import _ from quodlibet import util, qltk, app from quodlibet.pattern import ArbitraryExtensionFileFromPattern from quodlibet.pattern import Pattern from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.songshelpers import any_song, is_a_file from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons, ConfigRHPaned from quodlibet.qltk.entry import ValidatingEntry from quodlibet.qltk.image import scale, add_border_widget, get_surface_for_pixbuf from quodlibet.qltk.msg import ConfirmFileReplace from quodlibet.qltk.views import AllTreeView from quodlibet.qltk.window import PersistentWindowMixin from quodlibet.qltk.x import Align, Button from quodlibet.util import format_size, print_exc from quodlibet.util.dprint import print_d, print_w from quodlibet.util.path import iscommand from quodlibet.util.urllib import urlopen, Request USER_AGENT = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) " \ "Gecko/20101210 Iceweasel/3.6.13 (like Firefox/3.6.13)" PLUGIN_CONFIG_SECTION = 'cover' CONFIG_ENG_PREFIX = 'engine_' SEARCH_PATTERN = Pattern( '<albumartist|<albumartist>|<artist>> - <album|<album>|<title>>') REQUEST_LIMIT_MAX = 15 def get_encoding_from_socket(socket): content_type = socket.headers.get("Content-Type", "") p = [s.lower().strip() for s in content_type.split(";")] enc = [t.split("=")[-1].strip() for t in p if t.startswith("charset")] return (enc and enc[0]) or "utf-8" def get_url(url, post=None, get=None): post_params = urlencode(post or {}) get_params = urlencode(get or {}) if get: get_params = '?' + get_params # add post, get data and headers url = '%s%s' % (url, get_params) if post_params: request = Request(url, post_params) else: request = Request(url) # for discogs request.add_header('Accept-Encoding', 'gzip') request.add_header('User-Agent', USER_AGENT) url_sock = urlopen(request) enc = get_encoding_from_socket(url_sock) # unzip the response if needed data = url_sock.read() if url_sock.headers.get("content-encoding", "") == "gzip": data = gzip.GzipFile(fileobj=BytesIO(data)).read() url_sock.close() content_type = url_sock.headers.get('Content-Type', '').split(';', 1)[0] domain = re.compile(r'\w+://([^/]+)/').search(url).groups(0)[0] print_d("Got %s data from %s" % (content_type, domain)) return (data if content_type.startswith('image') else data.decode(enc)) def get_encoding(url): request = Request(url) request.add_header('Accept-Encoding', 'gzip') request.add_header('User-Agent', USER_AGENT) url_sock = urlopen(request) return get_encoding_from_socket(url_sock) class CoverSearcher: def start(self, query, limit=5) -> List[Dict[str, Any]]: """Start the search and return the covers""" raise NotImplementedError() class DiscogsSearcher(CoverSearcher): """A class for searching covers from Amazon""" def __init__(self): self.page_count = 0 self.covers = [] self.limit = 0 self.creds = {'key': 'aWfZGjHQvkMcreUECGAp', 'secret': 'VlORkklpdvAwJMwxUjNNSgqicjuizJAl'} def __parse_page(self, page, query): """Gets all item tags and calls the item parsing function for each""" url = 'https://api.discogs.com/database/search' parameters = { 'type': 'release', 'q': query, 'page': page, # Assume that not all results are useful 'per_page': self.limit * 2, } parameters.update(self.creds) data = get_url(url, get=parameters) json_dict = json.loads(data) # TODO: rate limiting pages = json_dict.get('pagination', {}).get('pages', 0) if not pages: return self.page_count = int(pages) items = json_dict.get('results', {}) print_d("Discogs: got %d search result(s)" % len(items)) for item in items: self.__parse_item(item) if len(self.covers) >= self.limit: break def __parse_item(self, item): """Extract all information and add the covers to the list.""" thumbnail = item.get('thumb', '') if thumbnail is None: print_d("Release doesn't have a cover") return res_url = item.get('resource_url', '') data = get_url(res_url, get=self.creds) json_dict = json.loads(data) images = json_dict.get('images', []) for i, image in enumerate(images): type = image.get('type', '') if type != 'primary': continue uri = image.get('uri', '') cover = {'source': 'https://www.discogs.com', 'name': item.get('title', ''), 'thumbnail': image.get('uri150', thumbnail), 'cover': uri, 'size': get_size_of_url(uri)} width = image.get('width', 0) height = image.get('height', 0) cover['resolution'] = '%s x %s px' % (width, height) self.covers.append(cover) if len(self.covers) >= self.limit: break def start(self, query, limit=3): self.page_count = 0 self.covers = [] self.limit = limit page = 1 while len(self.covers) < limit: self.__parse_page(page, query) if page >= self.page_count: break page += 1 return self.covers class CoverArea(Gtk.VBox, PluginConfigMixin): """The image display and saving part.""" CONFIG_SECTION = PLUGIN_CONFIG_SECTION def __init__(self, parent, song): super().__init__() self.song = song self.dirname = song("~dirname") self.main_win = parent self.data_cache = [] self.current_data = None self.current_pixbuf = None self.image = Gtk.Image() self.button = Button(_("_Save"), Icons.DOCUMENT_SAVE_AS) self.button.set_sensitive(False) self.button.connect('clicked', self.__save) close_button = Button(_("_Close"), Icons.WINDOW_CLOSE) close_button.connect('clicked', lambda x: self.main_win.destroy()) self.window_fit = self.ConfigCheckButton(_('Fit image to _window'), 'fit', True) self.window_fit.connect('toggled', self.__scale_pixbuf) self.name_combo = Gtk.ComboBoxText() self.name_combo.set_tooltip_text( _("See '[plugins] cover_filenames' config entry " + "for image filename strings")) self.cmd = ValidatingEntry(iscommand) # Both labels label_open = Gtk.Label(label=_('_Program:')) label_open.set_use_underline(True) label_open.set_mnemonic_widget(self.cmd) label_open.set_justify(Gtk.Justification.LEFT) self.open_check = self.ConfigCheckButton(_('_Edit image after saving'), 'edit', False) label_name = Gtk.Label(label=_('File_name:'), use_underline=True) label_name.set_use_underline(True) label_name.set_mnemonic_widget(self.name_combo) label_name.set_justify(Gtk.Justification.LEFT) self.cmd.set_text(self.config_get('edit_cmd', 'gimp')) # populate the filename combo box fn_list = self.config_get_stringlist('filenames', ["cover.jpg", "folder.jpg", ".folder.jpg"]) # Issue 374 - add dynamic file names fn_dynlist = [] artist = song("artist") alartist = song("albumartist") album = song("album") labelid = song("labelid") if album: fn_dynlist.append("<album>.jpg") if alartist: fn_dynlist.append("<albumartist> - <album>.jpg") else: fn_dynlist.append("<artist> - <album>.jpg") else: print_w(u"No album for \"%s\". Could be difficult " u"finding art…" % song("~filename")) title = song("title") if title and artist: fn_dynlist.append("<artist> - <title>.jpg") if labelid: fn_dynlist.append("<labelid>.jpg") # merge unique fn_list.extend(s for s in fn_dynlist if s not in fn_list) set_fn = self.config_get('filename', fn_list[0]) for i, fn in enumerate(fn_list): self.name_combo.append_text(fn) if fn == set_fn: self.name_combo.set_active(i) if self.name_combo.get_active() < 0: self.name_combo.set_active(0) self.config_set('filename', self.name_combo.get_active_text()) table = Gtk.Table(n_rows=2, n_columns=2, homogeneous=False) table.props.expand = False table.set_row_spacing(0, 5) table.set_row_spacing(1, 5) table.set_col_spacing(0, 5) table.set_col_spacing(1, 5) table.attach(label_open, 0, 1, 0, 1) table.attach(label_name, 0, 1, 1, 2) table.attach(self.cmd, 1, 2, 0, 1) table.attach(self.name_combo, 1, 2, 1, 2) self.scrolled = Gtk.ScrolledWindow() self.scrolled.add_with_viewport(self.image) self.scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) bbox = Gtk.HButtonBox() bbox.set_spacing(6) bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.pack_start(self.button, True, True, 0) bbox.pack_start(close_button, True, True, 0) bb_align = Align(valign=Gtk.Align.END, right=6) bb_align.add(bbox) main_hbox = Gtk.HBox() main_hbox.pack_start(table, False, True, 6) main_hbox.pack_start(bb_align, True, True, 0) top_hbox = Gtk.HBox() top_hbox.pack_start(self.open_check, True, True, 0) top_hbox.pack_start(self.window_fit, False, True, 0) main_vbox = Gtk.VBox() main_vbox.pack_start(top_hbox, True, True, 2) main_vbox.pack_start(main_hbox, True, True, 0) self.pack_start(self.scrolled, True, True, 0) self.pack_start(main_vbox, False, True, 5) # 5 MB image cache size self.max_cache_size = 1024 * 1024 * 5 # For managing fast selection switches of covers... self.stop_loading = False self.loading = False self.current_job = 0 self.connect('destroy', self.__save_config) def __save(self, *data): """Save the cover and spawn the program to edit it if selected""" save_format = self.name_combo.get_active_text() # Allow use of patterns in creating cover filenames pattern = ArbitraryExtensionFileFromPattern(save_format) filename = pattern.format(self.song) print_d("Using '%s' as filename based on %s" % (filename, save_format)) file_path = os.path.join(self.dirname, filename) if os.path.exists(file_path): resp = ConfirmFileReplace(self, file_path).run() if resp != ConfirmFileReplace.RESPONSE_REPLACE: return try: f = open(file_path, 'wb') f.write(self.current_data) f.close() except IOError: qltk.ErrorMessage(None, _('Saving failed'), _('Unable to save "%s".') % file_path).run() else: if self.open_check.get_active(): try: util.spawn([self.cmd.get_text(), file_path]) except: pass app.cover_manager.cover_changed([self.song._song]) self.main_win.destroy() def __save_config(self, widget): self.config_set('edit_cmd', self.cmd.get_text()) self.config_set('filename', self.name_combo.get_active_text()) def __update(self, loader, *data): """Update the picture while it's loading""" if self.stop_loading: return pixbuf = loader.get_pixbuf() def idle_set(): if pixbuf is not None: surface = get_surface_for_pixbuf(self, pixbuf) self.image.set_from_surface(surface) GLib.idle_add(idle_set) def __scale_pixbuf(self, *data): if not self.current_pixbuf: return pixbuf = self.current_pixbuf if self.window_fit.get_active(): alloc = self.scrolled.get_allocation() width = alloc.width height = alloc.height scale_factor = self.get_scale_factor() boundary = (width * scale_factor, height * scale_factor) pixbuf = scale(pixbuf, boundary, scale_up=False) if not pixbuf: return surface = get_surface_for_pixbuf(self, pixbuf) self.image.set_from_surface(surface) def __close(self, loader, *data): if self.stop_loading: return self.current_pixbuf = loader.get_pixbuf() GLib.idle_add(self.__scale_pixbuf) def set_cover(self, url): thr = threading.Thread(target=self.__set_async, args=(url,)) thr.daemon = True thr.start() def __set_async(self, url): """Manages various things: Fast switching of covers (aborting old HTTP requests), The image cache, etc.""" self.current_job += 1 job = self.current_job self.stop_loading = True while self.loading: time.sleep(0.05) self.stop_loading = False if job != self.current_job: return self.loading = True GLib.idle_add(self.button.set_sensitive, False) self.current_pixbuf = None pbloader = GdkPixbuf.PixbufLoader() pbloader.connect('closed', self.__close) # Look for cached images raw_data = None for entry in self.data_cache: if entry[0] == url: raw_data = entry[1] break if not raw_data: pbloader.connect('area-updated', self.__update) data_store = BytesIO() try: request = Request(url) request.add_header('User-Agent', USER_AGENT) url_sock = urlopen(request) except EnvironmentError: print_w(_("[albumart] HTTP Error: %s") % url) else: while not self.stop_loading: tmp = url_sock.read(1024 * 10) if not tmp: break pbloader.write(tmp) data_store.write(tmp) url_sock.close() if not self.stop_loading: raw_data = data_store.getvalue() self.data_cache.insert(0, (url, raw_data)) while 1: cache_sizes = [len(data[1]) for data in self.data_cache] if sum(cache_sizes) > self.max_cache_size: del self.data_cache[-1] else: break data_store.close() else: # Sleep for fast switching of cached images time.sleep(0.05) if not self.stop_loading: pbloader.write(raw_data) try: pbloader.close() except GLib.GError: pass self.current_data = raw_data if not self.stop_loading: GLib.idle_add(self.button.set_sensitive, True) self.loading = False class AlbumArtWindow(qltk.Window, PersistentWindowMixin, PluginConfigMixin): """The main window including the search list""" CONFIG_SECTION = PLUGIN_CONFIG_SECTION THUMB_SIZE = 128 def __init__(self, songs): super().__init__() self.enable_window_tracking(f"plugin_{PLUGIN_CONFIG_SECTION}") self.image_cache = [] self.image_cache_size = 10 self.search_lock = False self.set_title(_('Album Art Downloader')) self.set_icon_name(Icons.EDIT_FIND) self.set_default_size(800, 550) image = CoverArea(self, songs[0]) self.liststore = Gtk.ListStore(object, object) self.treeview = treeview = AllTreeView(model=self.liststore) self.treeview.set_headers_visible(False) self.treeview.set_rules_hint(True) targets = [("text/uri-list", 0, 0)] targets = [Gtk.TargetEntry.new(*t) for t in targets] treeview.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) treeselection = self.treeview.get_selection() treeselection.set_mode(Gtk.SelectionMode.SINGLE) treeselection.connect('changed', self.__select_callback, image) self.treeview.connect("drag-data-get", self.__drag_data_get, treeselection) rend_pix = Gtk.CellRendererPixbuf() img_col = Gtk.TreeViewColumn('Thumb') img_col.pack_start(rend_pix, False) def cell_data_pb(column, cell, model, iter_, *args): surface = model[iter_][0] cell.set_property("surface", surface) img_col.set_cell_data_func(rend_pix, cell_data_pb, None) treeview.append_column(img_col) rend_pix.set_property('xpad', 2) rend_pix.set_property('ypad', 2) border_width = self.get_scale_factor() * 2 rend_pix.set_property('width', self.THUMB_SIZE + 6 + border_width) rend_pix.set_property('height', self.THUMB_SIZE + 6 + border_width) def escape_data(data): for rep in ('\n', '\t', '\r', '\v'): data = data.replace(rep, ' ') return util.escape(' '.join(data.split())) def cell_data(column, cell, model, iter, data): cover = model[iter][1] esc = escape_data txt = util.bold_italic(cover['name'], escaper=esc) txt += "\n<small>%s</small>" % ( _('from %(source)s') % { "source": util.italic(cover['source'], escaper=esc)}) if 'resolution' in cover: txt += "\n" + _('Resolution: %s') % util.italic( cover['resolution'], escaper=esc) if 'size' in cover: txt += "\n" + _('Size: %s') % util.italic(cover['size'], escaper=esc) cell.markup = txt cell.set_property('markup', cell.markup) rend = Gtk.CellRendererText() rend.set_property('ellipsize', Pango.EllipsizeMode.END) info_col = Gtk.TreeViewColumn('Info', rend) info_col.set_cell_data_func(rend, cell_data) treeview.append_column(info_col) sw_list = Gtk.ScrolledWindow() sw_list.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw_list.set_shadow_type(Gtk.ShadowType.IN) sw_list.add(treeview) search_labelraw = Gtk.Label('raw') search_labelraw.set_alignment(xalign=1.0, yalign=0.5) self.search_fieldraw = Gtk.Entry() self.search_fieldraw.connect('activate', self.start_search) self.search_fieldraw.connect('changed', self.__searchfieldchanged) search_labelclean = Gtk.Label('clean') search_labelclean.set_alignment(xalign=1.0, yalign=0.5) self.search_fieldclean = Gtk.Label() self.search_fieldclean.set_can_focus(False) self.search_fieldclean.set_alignment(xalign=0.0, yalign=0.5) self.search_radioraw = Gtk.RadioButton(group=None, label=None) self.search_radioraw.connect("toggled", self.__searchtypetoggled, "raw") self.search_radioclean = Gtk.RadioButton(group=self.search_radioraw, label=None) self.search_radioclean.connect("toggled", self.__searchtypetoggled, "clean") # note: set_active(False) appears to have no effect # self.search_radioraw.set_active( # self.config_get_bool('searchraw', False)) if self.config_get_bool('searchraw', False): self.search_radioraw.set_active(True) else: self.search_radioclean.set_active(True) search_labelresultsmax = Gtk.Label('limit') search_labelresultsmax.set_alignment(xalign=1.0, yalign=0.5) search_labelresultsmax.set_tooltip_text( _("Per engine 'at best' results limit")) search_adjresultsmax = Gtk.Adjustment( value=int(self.config_get("resultsmax", 3)), lower=1, upper=REQUEST_LIMIT_MAX, step_incr=1, page_incr=0, page_size=0) self.search_spinresultsmax = Gtk.SpinButton( adjustment=search_adjresultsmax, climb_rate=0.2, digits=0) self.search_spinresultsmax.set_alignment(xalign=0.5) self.search_spinresultsmax.set_can_focus(False) self.search_button = Button(_("_Search"), Icons.EDIT_FIND) self.search_button.connect('clicked', self.start_search) search_button_box = Gtk.Alignment() search_button_box.set(1, 0, 0, 0) search_button_box.add(self.search_button) search_table = Gtk.Table(rows=3, columns=4, homogeneous=False) search_table.set_col_spacings(6) search_table.set_row_spacings(6) search_table.attach(search_labelraw, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL, xpadding=6) search_table.attach(self.search_radioraw, 1, 2, 0, 1, xoptions=0, xpadding=0) search_table.attach(self.search_fieldraw, 2, 4, 0, 1) search_table.attach(search_labelclean, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL, xpadding=6) search_table.attach(self.search_radioclean, 1, 2, 1, 2, xoptions=0, xpadding=0) search_table.attach(self.search_fieldclean, 2, 4, 1, 2, xpadding=4) search_table.attach(search_labelresultsmax, 0, 2, 2, 3, xoptions=Gtk.AttachOptions.FILL, xpadding=6) search_table.attach(self.search_spinresultsmax, 2, 3, 2, 3, xoptions=Gtk.AttachOptions.FILL, xpadding=0) search_table.attach(search_button_box, 3, 4, 2, 3) widget_space = 5 self.progress = Gtk.ProgressBar() left_vbox = Gtk.VBox(spacing=widget_space) left_vbox.pack_start(search_table, False, True, 0) left_vbox.pack_start(sw_list, True, True, 0) hpaned = ConfigRHPaned(section="plugins", option=f"{PLUGIN_CONFIG_SECTION}_pos", default=0.3) hpaned.set_border_width(widget_space) hpaned.pack1(left_vbox, shrink=False) hpaned.pack2(image, shrink=False) self.add(hpaned) self.show_all() left_vbox.pack_start(self.progress, False, True, 0) self.connect('destroy', self.__save_config) song = songs[0] text = SEARCH_PATTERN.format(song) self.set_text(text) self.start_search() def __save_config(self, widget): self.config_set('searchraw', self.search_radioraw.get_active()) self.config_set('resultsmax', self.search_spinresultsmax.get_value_as_int()) def __drag_data_get(self, view, ctx, sel, tid, etime, treeselection): model, iter = treeselection.get_selected() if not iter: return cover = model.get_value(iter, 1) sel.set_uris([cover['cover']]) def __searchfieldchanged(self, *data): search = data[0].get_text() clean = cleanup_query(search, ' ') self.search_fieldclean.set_text(util.italic(clean)) self.search_fieldclean.set_use_markup(True) def __searchtypetoggled(self, *data): self.config_set('searchraw', self.search_radioraw.get_active()) def start_search(self, *data): """Start the search using the text from the text entry""" text = self.search_fieldraw.get_text() if not text or self.search_lock: return self.search_lock = True self.search_button.set_sensitive(False) self.progress.set_fraction(0) self.progress.set_text(_(u'Searching…')) self.progress.show() self.liststore.clear() self.search = search = CoverSearch(self.__search_callback) for eng in ENGINES: if self.config_get_bool( CONFIG_ENG_PREFIX + eng['config_id'], True): search.add_engine(eng['class'], eng['replace']) raw = self.search_radioraw.get_active() limit = self.search_spinresultsmax.get_value_as_int() search.start(text, raw, limit) # Focus the list self.treeview.grab_focus() self.connect("destroy", self.__destroy) def __destroy(self, *args): self.search.stop() def set_text(self, text): """set the text and move the cursor to the end""" self.search_fieldraw.set_text(text) self.search_fieldraw.emit('move-cursor', Gtk.MovementStep.BUFFER_ENDS, 0, False) def __select_callback(self, selection, image): model, iter = selection.get_selected() if not iter: return cover = model.get_value(iter, 1) image.set_cover(cover['cover']) def __add_cover_to_list(self, cover): try: pbloader = GdkPixbuf.PixbufLoader() pbloader.write(get_url(cover['thumbnail'])) pbloader.close() scale_factor = self.get_scale_factor() size = self.THUMB_SIZE * scale_factor - scale_factor * 2 pixbuf = pbloader.get_pixbuf().scale_simple(size, size, GdkPixbuf.InterpType.BILINEAR) pixbuf = add_border_widget(pixbuf, self) if not pixbuf: return surface = get_surface_for_pixbuf(self, pixbuf) except (GLib.GError, IOError): pass else: def append(data): self.liststore.append(data) GLib.idle_add(append, [surface, cover]) def __search_callback(self, covers, progress): for cover in covers: self.__add_cover_to_list(cover) if self.progress.get_fraction() < progress: self.progress.set_fraction(progress) if progress >= 1: self.progress.set_text(_('Done')) GLib.timeout_add(700, self.progress.hide) self.search_button.set_sensitive(True) self.search_lock = False class CoverSearch: """Class for glueing the search engines together. No UI stuff.""" def __init__(self, callback): self.engine_list = [] self._stop = False def wrap(*args, **kwargs): if not self._stop: return callback(*args, **kwargs) self.callback = wrap self.finished = 0 def add_engine(self, engine, query_replace): """Adds a new search engine, query_replace is the string with which all special characters get replaced""" self.engine_list.append((engine, query_replace)) def stop(self): """After stop the progress callback will no longer be called""" self._stop = True def start(self, query, raw, limit): """Start search. The callback function will be called after each of the search engines has finished.""" for engine, replace in self.engine_list: thr = threading.Thread(target=self.__search_thread, args=(engine, query, replace, raw, limit)) thr.daemon = True thr.start() # tell the other side that we are finished if there is nothing to do. if not len(self.engine_list): GLib.idle_add(self.callback, [], 1) def __search_thread(self, engine, query, replace, raw, limit): """Creates searching threads which call the callback function after they are finished""" search = query if raw else cleanup_query(query, replace) print_d("[AlbumArt] running search %r on engine %s" % (search, engine.__name__)) result = [] try: result = engine().start(search, limit) except Exception as e: print_w(f"[AlbumArt] {engine.__name__}: {query!r} ({e})") print_exc() self.finished += 1 # progress is between 0..1 progress = float(self.finished) / len(self.engine_list) GLib.idle_add(self.callback, result, progress) def cleanup_query(query, replace): """split up at '-', remove some chars, only keep the longest words... more false positives but much better results""" query = query.lower() if query.startswith("the "): query = query[4:] split = query.split('-') replace_str = ('+', '&', ',', '.', '!', '´', '\'', ':', ' and ', '(', ')') new_query = '' for part in split: for stri in replace_str: part = part.replace(stri, replace) p_split = part.split() p_split.sort(key=len, reverse=True) end = max(int(len(p_split) / 4), max(4 - len(p_split), 2)) p_split = p_split[:end] new_query += ' '.join(p_split) + ' ' return new_query.rstrip() def get_size_of_url(url): request = Request(url) request.add_header('Accept-Encoding', 'gzip') request.add_header('User-Agent', USER_AGENT) url_sock = urlopen(request) size = url_sock.headers.get('content-length') url_sock.close() return format_size(int(size)) if size else '' ENGINES = [ { 'class': DiscogsSearcher, 'url': 'https://www.discogs.com/', 'replace': ' ', 'config_id': 'discogs', }, ] class DownloadAlbumArt(SongsMenuPlugin, PluginConfigMixin): """Download and save album (cover) art from a variety of sources""" PLUGIN_ID = 'Download Album Art' PLUGIN_NAME = _('Download Album Art') PLUGIN_DESC = _('Downloads album covers from various websites.') PLUGIN_ICON = Icons.INSERT_IMAGE CONFIG_SECTION = PLUGIN_CONFIG_SECTION REQUIRES_ACTION = True plugin_handles = any_song(is_a_file) @classmethod def PluginPreferences(cls, window): table = Gtk.Table(n_rows=len(ENGINES), n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) frame = qltk.Frame(_("Sources"), child=table) for i, eng in enumerate(sorted(ENGINES, key=lambda x: x["url"])): check = cls.ConfigCheckButton( eng['config_id'].title(), CONFIG_ENG_PREFIX + eng['config_id'], True) table.attach(check, 0, 1, i, i + 1) button = Gtk.Button(label=eng['url']) button.connect('clicked', lambda s: util.website(s.get_label())) table.attach(button, 1, 2, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) return frame def plugin_album(self, songs): return AlbumArtWindow(songs) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/ape2id3.py��������������������������������������������������0000664�0001750�0001750�00000002606�14035600052�020613� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import mutagen.apev2 from quodlibet import _ from quodlibet.formats import AudioFileError from quodlibet.formats._apev2 import APEv2File from quodlibet.plugins.songshelpers import each_song, is_writable from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons from quodlibet.util import print_exc def is_an_mp3(song): return song.get("~filename", "").lower().endswith(".mp3") class APEv2toID3v2(SongsMenuPlugin): PLUGIN_ID = "APEv2 to ID3v2" PLUGIN_NAME = _("APEv2 to ID3v2") PLUGIN_DESC = _("Converts your APEv2 tags to ID3v2 tags. This will delete " "the APEv2 tags after conversion.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE plugin_handles = each_song(is_an_mp3, is_writable) def plugin_song(self, song): try: apesong = APEv2File(song["~filename"]) except: return # File doesn't have an APEv2 tag song.update(apesong) mutagen.apev2.delete(song["~filename"]) try: song._song.write() except AudioFileError: print_exc() ��������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/bookmarks.py������������������������������������������������0000664�0001750�0001750�00000005373�14035600052�021360� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig, 2010 Christoph Reiter # 2016, 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import app from quodlibet import qltk from quodlibet.plugins.songshelpers import any_song, has_bookmark from quodlibet.qltk.bookmarks import EditBookmarks from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin class Bookmarks(SongsMenuPlugin): PLUGIN_ID = "Go to Bookmark" PLUGIN_NAME = _(u"Go to Bookmark") PLUGIN_DESC = _("Manages bookmarks in the selected files.") PLUGIN_ICON = Icons.GO_JUMP plugin_handles = any_song(has_bookmark) def __init__(self, songs, *args, **kwargs): super().__init__(songs, *args, **kwargs) self.__menu = Gtk.Menu() self.__create_children(self.__menu, songs) self.set_submenu(self.__menu) class FakePlayer: def __init__(self, song): self.song = song def seek(self, time): if app.player.go_to(self.song._song, explicit=True): app.player.seek(time) def get_position(self, *args): return 0 def __create_children(self, menu, songs): self.__remove_children(menu) for song in songs: marks = song.bookmarks if marks: fake_player = self.FakePlayer(song) song_item = Gtk.MenuItem(song.comma("title")) song_menu = Gtk.Menu() song_item.set_submenu(song_menu) menu.append(song_item) items = qltk.bookmarks.MenuItems(marks, fake_player, True) for item in items: song_menu.append(item) song_menu.append(SeparatorMenuItem()) i = qltk.MenuItem(_(u"_Edit Bookmarks…"), Icons.EDIT) def edit_bookmarks_cb(menu_item): window = EditBookmarks(self.plugin_window, app.library, fake_player) window.show() i.connect('activate', edit_bookmarks_cb) song_menu.append(i) if menu.get_active() is None: no_marks = Gtk.MenuItem(_("No Bookmarks")) no_marks.set_sensitive(False) menu.append(no_marks) menu.show_all() def __remove_children(self, menu): for child in menu.get_children(): menu.remove(child) def plugin_songs(self, songs): pass ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9909356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/�����������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�020275� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/__init__.py������������������������������������������0000644�0001750�0001750�00000004102�14310167056�022407� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2010 Joshua Kwan <joshk@triplehelix.org>, # Michael Ball <michael.ball@gmail.com>, # Steven Robertson <steven@strobe.cc> # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import is_writable, each_song, is_finite from .util import pconfig from .widgets import SearchWindow class MyBrainz(SongsMenuPlugin): PLUGIN_ID = "MusicBrainz lookup" PLUGIN_NAME = _("MusicBrainz Lookup") PLUGIN_ICON = Icons.MEDIA_OPTICAL PLUGIN_DESC = _('Re-tags an album based on a MusicBrainz search.') plugin_handles = each_song(is_writable, is_finite) def plugin_albums(self, albums): if not albums: return def win_finished_cb(widget, *args): if albums: start_processing(albums.pop(0)) else: self.plugin_finish() def start_processing(disc): win = SearchWindow(self.plugin_window, disc) win.connect("destroy", win_finished_cb) win.show() start_processing(albums.pop(0)) @classmethod def PluginPreferences(cls, win): items = [ ('year_only', _('Only use year for "date" tag')), ('albumartist', _('Write "_albumartist" when needed')), ('artist_sort', _('Write sort tags for artist names')), ('standard', _('Write _standard MusicBrainz tags')), ('labelid2', _('Write "labelid" tag')), ] vb = Gtk.VBox() vb.set_spacing(8) for key, label in items: ccb = pconfig.ConfigCheckButton(label, key, populate=True) vb.pack_start(ccb, True, True, 0) return vb ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/mb.py������������������������������������������������0000644�0001750�0001750�00000012344�14310167056�021255� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. try: import musicbrainzngs except ImportError: from quodlibet import plugins raise plugins.MissingModulePluginException("musicbrainzngs") from quodlibet import app from quodlibet import const from quodlibet import util VARIOUS_ARTISTS_ARTISTID = '89ad4ac3-39f7-470e-963a-56509c546377' def is_mbid(id_): return len(id_) == 36 def search_releases(query): """Returns a list of ReleaseResult or raises MusicBrainzError""" musicbrainzngs.set_useragent(app.name, const.VERSION) return [Release(r) for r in musicbrainzngs.search_releases(query)["release-list"]] def _get_release(release_id): """Returns a release containing all recordings and artists or raises MusicBrainzError """ assert is_mbid(release_id) return musicbrainzngs.get_release_by_id( release_id, includes=["recordings", "artists", "artist-credits", "labels"] )["release"] class Artist: def __init__(self, name, sort_name, id_): self.name = name self.sort_name = sort_name self.id = id_ # MusicBrainz Artist ID / Album Artist ID @property def is_various(self): return self.id == VARIOUS_ARTISTS_ARTISTID @classmethod def from_credit(cls, mbcredit): artists = [] for credit in mbcredit: try: artist = credit["artist"] except TypeError: # join strings pass else: artists.append( Artist(artist["name"], artist["sort-name"], artist["id"])) return artists class ReleaseTrack: """Part of a Release, combines per track and per medium data""" def __init__(self, mbtrack, discnumber, track_count, disctitle): self._mbtrack = mbtrack self.discnumber = discnumber self.track_count = track_count self.disctitle = disctitle @property def id(self): """MusicBrainz release track ID""" return self._mbtrack["id"] @property def artists(self): return Artist.from_credit(self._mbtrack["artist-credit"]) @property def title(self): return self._mbtrack["recording"]["title"] @property def tracknumber(self): return self._mbtrack["position"] class Release: def __init__(self, mbrelease): self._mbrelease = mbrelease @property def labelid(self): label_list = self._mbrelease.get("label-info-list", []) if not label_list: return u"" return label_list[0].get("catalog-number", u"") @property def id(self): """MusicBrainz release ID""" return self._mbrelease["id"] @property def date(self): return self._mbrelease.get("date", u"") @property def medium_format(self): formats = [] for medium in self._mbrelease["medium-list"]: format_ = medium.get("format", u"") if format_: formats.append(format_) formats = util.list_unique(formats) return u"/".join(formats) @property def country(self): return self._mbrelease.get("country", u"") @property def disc_count(self): return self._mbrelease["medium-count"] @property def track_count(self): """Number of tracks for all included mediums""" track_count = 0 for medium in self._mbrelease["medium-list"]: if "track-count" in medium: track_count += medium["track-count"] if "pregap" in medium: track_count += 1 return track_count @property def tracks(self): tracks = [] for medium in self._mbrelease["medium-list"]: disc = medium["position"] title = medium.get("title", u"") track_count = medium["track-count"] if "pregap" in medium: track_count += 1 tracks.append( ReleaseTrack(medium["pregap"], disc, track_count, title)) for track in medium["track-list"]: tracks.append(ReleaseTrack(track, disc, track_count, title)) return tracks @property def title(self): return self._mbrelease["title"] @property def is_single_artist(self): """If all tracks have the same artists as the release""" ids = [a.id for a in self.artists] for track in self.tracks: track_ids = [a.id for a in track.artists] if ids != track_ids: return False return True @property def is_various_artists(self): artists = self.artists return len(artists) == 1 and artists[0].is_various @property def artists(self): return Artist.from_credit(self._mbrelease["artist-credit"]) def fetch_full(self): """Returns a new Release instance containing more info or raises MusicBrainzError This method is blocking... """ return Release(_get_release(self.id)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/query.py���������������������������������������������0000664�0001750�0001750�00000003402�14035600052�022011� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2010 Joshua Kwan <joshk@triplehelix.org>, # Michael Ball <michael.ball@gmail.com>, # Steven Robertson <steven@strobe.cc> # # 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 2 of the License, or # (at your option) any later version. import threading import time from gi.repository import GLib from quodlibet.util import print_exc class QueryThread: """Daemon thread which does HTTP retries and avoids flooding.""" def __init__(self): self.running = True self.queue = [] thread = threading.Thread(target=self.__run) thread.daemon = True thread.start() def add(self, callback, func, *args, **kwargs): """Add a func to be evaluated in a background thread. Callback will be called with the result from the main thread. """ self.queue.append((callback, func, args, kwargs)) def stop(self): """Stop the background thread.""" self.running = False def __run(self): while self.running: if self.queue: callback, func, args, kwargs = self.queue.pop(0) try: res = func(*args, **kwargs) except: time.sleep(2) try: res = func(*args, **kwargs) except: print_exc() res = None def idle_check(cb, res): if self.running: cb(res) GLib.idle_add(idle_check, callback, res) time.sleep(1) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/util.py����������������������������������������������0000664�0001750�0001750�00000001417�14035600052�021625� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2010 Joshua Kwan <joshk@triplehelix.org>, # Michael Ball <michael.ball@gmail.com>, # Steven Robertson <steven@strobe.cc> # # 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 2 of the License, or # (at your option) any later version. from quodlibet.plugins import PluginConfig def get_config(): pc = PluginConfig("brainz") defaults = pc.defaults defaults.set("year_only", False) defaults.set("albumartist", True) defaults.set("artist_sort", False) defaults.set("standard", True) defaults.set("labelid2", False) return pc pconfig = get_config() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/brainz/widgets.py�������������������������������������������0000644�0001750�0001750�00000040375�14327505043�022332� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005-2010 Joshua Kwan <joshk@triplehelix.org>, # Michael Ball <michael.ball@gmail.com>, # Steven Robertson <steven@strobe.cc> # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango from senf import fsn2text from quodlibet import _ from quodlibet import util from quodlibet.qltk import Dialog, Icons from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.views import HintedTreeView, MultiDragTreeView from quodlibet.util.i18n import numeric_phrase from .query import QueryThread from .util import pconfig from .mb import search_releases def get_artist(album): """Returns a single artist likely to be the MB AlbumArtist, or None.""" for tag in ["albumartist", "artist", "performer"]: names = set() for song in album: for single in filter(None, song.get(tag, "").split("\n")): names.add(single) if len(names) == 1: return names.pop() elif len(names) > 1: return None return None def get_trackcount(album): """Returns the track count, hammered into submission.""" parts = [] for song in album: parts.extend(song.get("tracknumber", "0").split("/")) max_count = len(album) for part in parts: try: tracks = int(part) except ValueError: continue max_count = max(max_count, tracks) return max_count def build_query(album): """Builds an initial mb release search query. See: https://musicbrainz.org/doc/Development/XML%20Web%20Service/ Version%202/Search#Release """ if not album: return u"" alb = '"%s"' % album[0].comma("album").replace('"', '') art = get_artist(album) if art: alb = '%s AND artist:"%s"' % (alb, art.replace('"', '')) return u'%s AND tracks:%d' % (alb, get_trackcount(album)) class ResultComboBox(Gtk.ComboBox): """Formatted picker for different Result entries.""" def __init__(self, model): super().__init__(model=model) render = Gtk.CellRendererText() render.set_fixed_height_from_font(2) def celldata(layout, cell, model, iter_, data): release = model.get_value(iter_) extra_info = ", ".join( filter(None, [util.escape(release.date), util.escape(release.country), util.escape(release.medium_format), util.escape(release.labelid)])) artist_names = [a.name for a in release.artists] disc_count = release.disc_count track_count = release.track_count discs_text = numeric_phrase("%d disc", "%d discs", disc_count) tracks_text = numeric_phrase("%d track", "%d tracks", track_count) markup = "%s\n%s - %s, %s (%s)" % ( util.bold(release.title), util.escape(", ".join(artist_names)), util.escape(discs_text), util.escape(tracks_text), extra_info) cell.set_property('markup', markup) self.pack_start(render, True) self.set_cell_data_func(render, celldata, None) class ResultTreeView(HintedTreeView, MultiDragTreeView): """The result treeview""" def __init__(self, album): self.album = album self._release = None self.model = ObjectStore() self.model.append_many(album) super().__init__(self.model) self.set_headers_clickable(True) self.set_rules_hint(True) self.set_reorderable(True) self.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) mode = Pango.EllipsizeMode cols = [ (_('Filename'), self.__name_datafunc, True, mode.MIDDLE), (_('Disc'), self.__disc_datafunc, False, mode.END), (_('Track'), self.__track_datafunc, False, mode.END), (_('Title'), self.__title_datafunc, True, mode.END), (_('Artist'), self.__artist_datafunc, True, mode.END), ] for title, func, resize, mode in cols: render = Gtk.CellRendererText() render.set_property('ellipsize', mode) col = Gtk.TreeViewColumn(title, render) col.set_cell_data_func(render, func) col.set_resizable(resize) col.set_expand(resize) self.append_column(col) def iter_tracks(self): """Yields tuples of (release, track, song) combinations as they are shown in the list. """ tracks = self._tracks for idx, (song, ) in enumerate(self.model): if song is None: continue if idx >= len(tracks): continue track = tracks[idx] yield (self._release, track, song) def update_release(self, full_release): """Updates the TreeView, handling results with a different number of tracks than the album being tagged. Passing in None will reset the list. """ if full_release is not None: tracks = full_release.tracks else: tracks = [] for i in range(len(self.model), len(tracks)): self.model.append((None, )) for i in range(len(self.model), len(tracks), -1): if self.model[-1][0] is not None: break itr = self.model.get_iter_from_string(str(len(self.model) - 1)) self.model.remove(itr) self._release = full_release for row in self.model: self.model.row_changed(row.path, row.iter) # Only show artists if we have any has_artists = bool(filter(lambda t: t.artists, tracks)) col = self.get_column(4) col.set_visible(has_artists) # Only show discs column if we have more than one disc col = self.get_column(1) col.set_visible( bool(full_release) and bool(full_release.disc_count > 1)) self.columns_autosize() @property def _tracks(self): if self._release is None: return [] return self._release.tracks def __name_datafunc(self, col, cell, model, itr, data): song = model[itr][0] if song: cell.set_property('text', fsn2text(song("~basename"))) else: cell.set_property('text', '') def __track_datafunc(self, col, cell, model, itr, data): idx = model.get_path(itr)[0] if idx >= len(self._tracks): cell.set_property('text', '') else: cell.set_property('text', self._tracks[idx].tracknumber) def __disc_datafunc(self, col, cell, model, itr, data): idx = model.get_path(itr)[0] if idx >= len(self._tracks): cell.set_property('text', '') else: cell.set_property('text', self._tracks[idx].discnumber) def __title_datafunc(self, col, cell, model, itr, data): idx = model.get_path(itr)[0] if idx >= len(self._tracks): cell.set_property('text', '') else: cell.set_property('text', self._tracks[idx].title) def __artist_datafunc(self, col, cell, model, itr, data): idx = model.get_path(itr)[0] if idx >= len(self._tracks): cell.set_property('text', '') else: names = [a.name for a in self._tracks[idx].artists] cell.set_property('text', ", ".join(names)) def build_song_data(release, track): """Returns a dict of tags to apply to a song. All the values are unicode. If the value is empty it means the tag should be deleted. """ meta = {} join = lambda l: "\n".join(l) # track/disc data meta["tracknumber"] = "%s/%d" % (track.tracknumber, track.track_count) if release.disc_count > 1: meta["discnumber"] = "%s/%d" % (track.discnumber, release.disc_count) else: meta["discnumber"] = "" meta["title"] = track.title meta["musicbrainz_releasetrackid"] = track.id meta["musicbrainz_trackid"] = u"" # we used to write those, so delete # disc data meta["discsubtitle"] = track.disctitle # release data meta["album"] = release.title meta["date"] = release.date meta["musicbrainz_albumid"] = release.id meta["labelid"] = release.labelid if not release.is_single_artist and not release.is_various_artists: artists = release.artists meta["albumartist"] = join([a.name for a in artists]) meta["albumartistsort"] = join([a.sort_name for a in artists]) meta["musicbrainz_albumartistid"] = join([a.id for a in artists]) else: meta["albumartist"] = "" meta["albumartistsort"] = "" meta["musicbrainz_albumartistid"] = "" meta["artist"] = join([a.name for a in track.artists]) meta["artistsort"] = join([a.sort_name for a in track.artists]) meta["musicbrainz_artistid"] = join([a.id for a in track.artists]) meta["musicbrainz_releasetrackid"] = track.id # clean up "redundant" data if meta["albumartist"] == meta["albumartistsort"]: meta["albumartistsort"] = "" if meta["artist"] == meta["artistsort"]: meta["artistsort"] = "" # finally, as musicbrainzngs returns str values if it's ascii, we force # everything to unicode now for key, value in meta.items(): meta[key] = str(value) return meta def apply_options(meta, year_only, albumartist, artistsort, musicbrainz, labelid): """Takes the tags extracted from musicbrainz and adjusts them according to the user preferences. """ if year_only: meta["date"] = meta["date"].split('-', 1)[0] if not albumartist: meta["albumartist"] = u"" if not artistsort: meta["albumartistsort"] = u"" meta["artistsort"] = u"" if not musicbrainz: for key in meta: if key.startswith("musicbrainz_"): meta[key] = u"" if not labelid: meta["labelid"] = "" def apply_to_song(meta, song): """Applies the tags to a AudioFile instance""" for key, value in meta.items(): if not value: song.remove(key) else: assert isinstance(value, str) song[key] = value def sort_key(song): """Sort by path so untagged albums have a good start order. Also take into account the directory in case it's split in different folders by medium. """ return util.human_sort_key(fsn2text(song("~filename"))) class SearchWindow(Dialog): def __init__(self, parent, album): self.album = album self.album.sort(key=sort_key) self._resultlist = ObjectStore() self._releasecache = {} self._qthread = QueryThread() self.current_release = None super().__init__(_("MusicBrainz lookup")) self.add_button(_("_Cancel"), Gtk.ResponseType.REJECT) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.ACCEPT) self.set_default_size(650, 500) self.set_border_width(5) self.set_transient_for(parent) save_button = self.get_widget_for_response(Gtk.ResponseType.ACCEPT) save_button.set_sensitive(False) vb = Gtk.VBox() vb.set_spacing(8) hb = Gtk.HBox() hb.set_spacing(8) sq = self.search_query = Gtk.Entry() sq.connect('activate', self._do_query) sq.set_text(build_query(album)) lbl = Gtk.Label(label=_("_Query:")) lbl.set_use_underline(True) lbl.set_mnemonic_widget(sq) stb = self.search_button = Gtk.Button(_('S_earch'), use_underline=True) stb.connect('clicked', self._do_query) hb.pack_start(lbl, False, True, 0) hb.pack_start(sq, True, True, 0) hb.pack_start(stb, False, True, 0) vb.pack_start(hb, False, True, 0) self.result_combo = ResultComboBox(self._resultlist) self.result_combo.connect('changed', self._result_changed) vb.pack_start(self.result_combo, False, True, 0) rhb = Gtk.HBox() rl = Gtk.Label() rl.set_markup(_("Results <i>(drag to reorder)</i>")) rl.set_alignment(0, 0.5) rhb.pack_start(rl, False, True, 0) rl = self.result_label = Gtk.Label(label="") rhb.pack_end(rl, False, True, 0) vb.pack_start(rhb, False, True, 0) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS) rtv = self.result_treeview = ResultTreeView(self.album) rtv.set_border_width(8) sw.add(rtv) vb.pack_start(sw, True, True, 0) # TODO: remove deprecated get_action_area # https://developer.gnome.org/gtk3/stable/GtkDialog.html#gtk-dialog-get-action-area self.get_action_area().set_border_width(4) self.get_content_area().pack_start(vb, True, True, 0) self.connect('response', self._on_response) self.connect("destroy", self._on_destroy) stb.emit('clicked') self.get_child().show_all() def _on_destroy(self, *args): self._qthread.stop() def _on_response(self, widget, response): if response != Gtk.ResponseType.ACCEPT: self.destroy() return self._save() def _save(self): """Writes values to Song objects.""" year_only = pconfig.getboolean("year_only") albumartist = pconfig.getboolean("albumartist") artistsort = pconfig.getboolean("artist_sort") musicbrainz = pconfig.getboolean("standard") labelid = pconfig.getboolean("labelid2") for release, track, song in self.result_treeview.iter_tracks(): meta = build_song_data(release, track) apply_options( meta, year_only, albumartist, artistsort, musicbrainz, labelid) apply_to_song(meta, song) self.destroy() def _do_query(self, *args): """Search for album using the query text.""" query = self.search_query.get_text() if not query: self.result_label.set_markup(util.bold(_("Please enter a query."))) self.search_button.set_sensitive(True) return self.result_label.set_markup(util.italic(_("Searching…"))) self._qthread.add(self._process_results, search_releases, query) def _process_results(self, results): """Called when a query result is returned. `results` is None if an error occurred. """ self._resultlist.clear() self.search_button.set_sensitive(True) if results is None: self.result_label.set_text(_("Error encountered. Please retry.")) self.search_button.set_sensitive(True) return self._resultlist.append_many(results) if len(results) > 0: self.result_label.set_markup(util.italic(_("Loading result…"))) self.result_combo.set_active(0) else: self.result_label.set_markup(_("No results found.")) def _result_changed(self, combo): """Called when a release is chosen from the result combo.""" idx = combo.get_active() if idx == -1: return release = self._resultlist[idx][0] if release.id in self._releasecache: self._update_result(self._releasecache[release.id]) else: self.result_label.set_markup(util.italic(_("Loading result…"))) self.result_treeview.update_release(None) self._qthread.add(self._update_result, release.fetch_full) def _update_result(self, full_release): """Callback for release detail download from result combo.""" if full_release is None: self.result_label.set_text(_("Error encountered. Please retry.")) return self.result_label.set_text(u"") self._releasecache.setdefault(full_release.id, full_release) self.result_treeview.update_release(full_release) self.current_release = full_release save_button = self.get_widget_for_response(Gtk.ResponseType.ACCEPT) save_button.set_sensitive(True) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295006.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/console.py��������������������������������������������������0000644�0001750�0001750�00000055520�14324322336�021036� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2006 - Steve Frécinaux # 2016-17 - Nick Boultbee # 2021 - halfbrained@github # # 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 2 of the License, or # (at your option) any later version. # Parts from "Interactive Python-GTK Console" # (stolen from epiphany's console.py) # Copyright (C), 1998 James Henstridge <james@daa.com.au> # Copyright (C), 2005 Adam Hooper <adamh@densi.com> # Bits from gedit Python Console Plugin # Copyright (C), 2005 Raphaël Slinckx # PythonConsole taken from totem # Plugin parts: # Copyright 2009,2010,2013 Christoph Reiter # 2016 Nick Boultbee import sys import re import traceback from itertools import takewhile from gi.repository import Gtk, Pango, Gdk, GLib from quodlibet import _, app, ngettext from quodlibet import const from quodlibet.plugins.events import EventPlugin from quodlibet.plugins.gui import UserInterfacePlugin from quodlibet.qltk import Icons, add_css, Align from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.collection import Collection from quodlibet.util import print_ class PyConsole(SongsMenuPlugin): PLUGIN_ID = 'Python Console' PLUGIN_NAME = _('Python Console') PLUGIN_DESC = _('Interactive Python console. Opens a new window.') PLUGIN_ICON = Icons.UTILITIES_TERMINAL def plugin_songs(self, songs): desc = ngettext("%d song", "%d songs", len(songs)) % len(songs) win = ConsoleWindow(create_console(songs), title=desc) win.set_icon_name(self.PLUGIN_ICON) win.set_title( _("{plugin_name} for {songs} ({app})").format( plugin_name=self.PLUGIN_NAME, songs=desc, app=app.name)) win.show_all() class PyConsoleSidebar(EventPlugin, UserInterfacePlugin): PLUGIN_ID = 'Python Console Sidebar' PLUGIN_NAME = _('Python Console Sidebar') PLUGIN_DESC = _('Interactive Python console sidebar, ' 'that follows the selected songs in the main window.') PLUGIN_ICON = Icons.UTILITIES_TERMINAL def enabled(self): self.console = create_console() def plugin_on_songs_selected(self, songs): self.console.namespace = namespace_for(songs) def create_sidebar(self): align = Align(self.console) self.sidebar = align self.sidebar.show_all() return align def create_console(songs=None): console = PythonConsole(namespace_for(songs)) if songs else PythonConsole() access_string = _("You can access the following objects by default:") access_string += "\\n".join([ "", " %5s: SongWrapper objects", " %5s: Song dictionaries", " %5s: Filename list", " %5s: Songs Collection", " %5s: Application instance"]) % ( "songs", "sdict", "files", "col", "app") dir_string = _("Your current working directory is:") console.eval("import mutagen", False) console.eval("import os", False) console.eval( "print(\"Python: %s / Quod Libet: %s\")" % (sys.version.split()[0], const.VERSION), False) console.eval("print(\"%s\")" % access_string, False) console.eval("print(\"%s \"+ os.getcwd())" % dir_string, False) return console def namespace_for(song_wrappers): files = [song('~filename') for song in song_wrappers] song_dicts = [song._song for song in song_wrappers] collection = Collection() collection.songs = song_dicts return { 'songs': song_wrappers, 'files': files, 'sdict': song_dicts, 'col': collection, 'app': app } class ConsoleWindow(Gtk.Window): def __init__(self, console, title=None): Gtk.Window.__init__(self) if title: self.set_title(title) self.add(console) self.set_size_request(700, 500) console.connect("destroy", lambda *x: self.destroy()) class PythonConsole(Gtk.ScrolledWindow): def __init__(self, namespace=None, destroy_cb=None): Gtk.ScrolledWindow.__init__(self) self.destroy_cb = destroy_cb self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.set_shadow_type(Gtk.ShadowType.NONE) self.view = Gtk.TextView() add_css(self, "scrolledwindow { padding: 6px; " "background-color: white; background-color: @content_view_bg;}") self.view.modify_font(Pango.font_description_from_string('Monospace')) self.view.set_editable(True) self.view.set_wrap_mode(Gtk.WrapMode.CHAR) self.add(self.view) self.view.show() buffer = self.view.get_buffer() self.normal = buffer.create_tag("normal") self.error = buffer.create_tag("error") self.error.set_property("foreground", "red") self.command = buffer.create_tag("command") self.command.set_property("foreground", "blue") self.__spaces_pattern = re.compile(r'^\s+') self.namespace = namespace or {} self.block_command = False # Init first line buffer.create_mark("input-line", buffer.get_end_iter(), True) buffer.insert(buffer.get_end_iter(), ">>> ") buffer.create_mark("input", buffer.get_end_iter(), True) # Init history self.history = [''] self.history_pos = 0 self.current_command = '' self.namespace['__history__'] = self.history # Set up hooks for standard output. self.stdout = OutFile(self, self.normal) self.stderr = OutFile(self, self.error) # Signals self.view.connect("key-press-event", self.__key_press_event_cb) buffer.connect("mark-set", self.__mark_set_cb) def __key_press_event_cb(self, view, event): modifier_mask = Gtk.accelerator_get_default_mod_mask() event_state = event.state & modifier_mask if event.keyval == Gdk.KEY_d and \ event_state == Gdk.ModifierType.CONTROL_MASK: self.destroy() elif event.keyval == Gdk.KEY_Return and ( event_state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK)): # Get the command buffer = view.get_buffer() inp_mark = buffer.get_mark("input") inp = buffer.get_iter_at_mark(inp_mark) cur = buffer.get_end_iter() line = buffer.get_text(inp, cur, True) self.current_command = self.current_command + line + "\n" self.history_add(line) # Prepare the new line cur = buffer.get_end_iter() buffer.insert(cur, "\n... ") cur = buffer.get_end_iter() buffer.move_mark(inp_mark, cur) # Keep indentation of preceding line spaces = re.match(self.__spaces_pattern, line) if spaces is not None: buffer.insert(cur, line[spaces.start():spaces.end()]) else: buffer.insert(cur, " ") cur = buffer.get_end_iter() buffer.place_cursor(cur) GLib.idle_add(self.scroll_to_end) return True elif event.keyval == Gdk.KEY_Return: # Get the marks buffer = view.get_buffer() lin_mark = buffer.get_mark("input-line") inp_mark = buffer.get_mark("input") # Get the command line inp = buffer.get_iter_at_mark(inp_mark) cur = buffer.get_end_iter() line = buffer.get_text(inp, cur, True) self.current_command = self.current_command + line + "\n" # Make the line blue lin = buffer.get_iter_at_mark(lin_mark) buffer.apply_tag(self.command, lin, cur) buffer.insert(cur, "\n") cur_strip = self.current_command.rstrip() if (cur_strip.endswith(":") or (self.current_command[-2:].strip() != "" and self.block_command)): # Unfinished block command self.block_command = True com_mark = "... " elif cur_strip.endswith("\\"): com_mark = "... " else: # Eval the command self.history_add(cur_strip) self.__run(self.current_command) self.current_command = '' self.block_command = False com_mark = ">>> " # Prepare the new line cur = buffer.get_end_iter() buffer.move_mark(lin_mark, cur) buffer.insert(cur, com_mark) cur = buffer.get_end_iter() buffer.move_mark(inp_mark, cur) # Keep indentation of preceding line if com_mark == "... ": spaces = re.match(self.__spaces_pattern, line) if spaces is not None: #cur = buffer.get_end_iter() buffer.insert(cur, line[spaces.start():spaces.end()]) if cur_strip.endswith(":"): #cur = buffer.get_end_iter() buffer.insert(cur, " ") buffer.place_cursor(cur) GLib.idle_add(self.scroll_to_end) return True elif (event.keyval == Gdk.KEY_c and event_state == Gdk.ModifierType.CONTROL_MASK): # Get the marks buffer = view.get_buffer() lin_mark = buffer.get_mark("input-line") inp_mark = buffer.get_mark("input") cur = buffer.get_end_iter() # New line buffer.insert(cur, "\n") com_mark = ">>> " cur = buffer.get_end_iter() buffer.move_mark(lin_mark, cur) buffer.insert(cur, com_mark) # Move marks cur = buffer.get_end_iter() buffer.move_mark(inp_mark, cur) buffer.place_cursor(cur) GLib.idle_add(self.scroll_to_end) return True elif event.keyval == Gdk.KEY_KP_Down or event.keyval == Gdk.KEY_Down: # Next entry from history view.emit_stop_by_name("key_press_event") self.history_down() GLib.idle_add(self.scroll_to_end) return True elif event.keyval == Gdk.KEY_KP_Up or event.keyval == Gdk.KEY_Up: # Previous entry from history view.emit_stop_by_name("key_press_event") self.history_up() GLib.idle_add(self.scroll_to_end) return True elif event.keyval == Gdk.KEY_KP_Left or \ event.keyval == Gdk.KEY_Left or \ event.keyval == Gdk.KEY_BackSpace: buffer = view.get_buffer() inp = buffer.get_iter_at_mark(buffer.get_mark("input")) cur = buffer.get_iter_at_mark(buffer.get_insert()) return inp.compare(cur) == 0 elif event.keyval == Gdk.KEY_Home: # Go to the begin of the command instead of the begin of the line buffer = view.get_buffer() inp = buffer.get_iter_at_mark(buffer.get_mark("input")) if event_state == Gdk.ModifierType.SHIFT_MASK: buffer.move_mark_by_name("insert", inp) else: buffer.place_cursor(inp) return True # completion - Tab, Shift+Tab, Ctrl+Space , Ctrl+Shift+Space elif (event.keyval == Gdk.KEY_Tab or event.keyval == Gdk.KEY_ISO_Left_Tab) or ( event.keyval == Gdk.KEY_space and ( event_state == (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) or event_state == (Gdk.ModifierType.CONTROL_MASK) ) ): buffer = view.get_buffer() # get string to left of caret inside command text-line _inp_mark = buffer.get_mark("input") _ins_mark = buffer.get_mark("insert") _inp = buffer.get_iter_at_mark(_inp_mark) ins = buffer.get_iter_at_mark(_ins_mark) cmd_start = buffer.get_text(_inp, ins, True) # get identifiers chain string, e.g. `a.b.c`, or a single identifier _identifiers_chars = takewhile( lambda x: x.isalnum() or x in {'_', '.'}, reversed(cmd_start)) _idcs_len = len( list(_identifiers_chars)) # lengt of identifiers chain string ids_str = cmd_start[-_idcs_len:] # Ctrl+Shift+Space: has Shift: include identifiers starting with '__' is_shift = bool(event_state & Gdk.ModifierType.SHIFT_MASK) comp_items = self.get_completion_items(ids_str, include_private=is_shift) choice = None if len(comp_items) > 1: # sort completions: case-insensitive, # items starting with '_' - at the end comp_items.sort( key=lambda x: (x[0].startswith('_'), x[0].lower())) dialog = ListChoiceDialog(self.get_parent(), comp_items) choice = dialog.run() dialog.destroy() elif len(comp_items) == 1: # if current text is only suggestion, add a '.' if object # has properties visible to autosuggestion last = ids_str.split('.')[-1] if last == comp_items[0][0]: next_comp_items = self.get_completion_items( ids_str + '.', include_private=is_shift ) if next_comp_items: buffer.insert(ins, '.') else: choice = 0 elif '\n' in self.current_command: # if we're doing multi-line editing, tab should add 4 spaces buffer.insert(ins, " ") if isinstance(choice, int) and choice >= 0: last = ids_str.split('.')[-1] insert_text = comp_items[choice][0] if last: # cut off prefix, already present insert_text = insert_text[len(last):] buffer.insert(ins, insert_text) return True def __mark_set_cb(self, buffer, iter, name): input = buffer.get_iter_at_mark(buffer.get_mark("input")) pos = buffer.get_iter_at_mark(buffer.get_insert()) self.view.set_editable(pos.compare(input) != -1) def get_command_line(self): buffer = self.view.get_buffer() inp = buffer.get_iter_at_mark(buffer.get_mark("input")) cur = buffer.get_end_iter() return buffer.get_text(inp, cur, True) def set_command_line(self, command): buffer = self.view.get_buffer() mark = buffer.get_mark("input") inp = buffer.get_iter_at_mark(mark) cur = buffer.get_end_iter() buffer.delete(inp, cur) buffer.insert(inp, command) buffer.select_range(buffer.get_iter_at_mark(mark), buffer.get_end_iter()) self.view.grab_focus() def history_add(self, line): if line.strip() != '': self.history_pos = len(self.history) self.history[self.history_pos - 1] = line self.history.append('') def history_up(self): if self.history_pos > 0: self.history[self.history_pos] = self.get_command_line() self.history_pos -= 1 self.set_command_line(self.history[self.history_pos]) def history_down(self): if self.history_pos < len(self.history) - 1: self.history[self.history_pos] = self.get_command_line() self.history_pos += 1 self.set_command_line(self.history[self.history_pos]) def scroll_to_end(self): iter = self.view.get_buffer().get_end_iter() self.view.scroll_to_iter(iter, 0.0, False, 0.5, 0.5) return False def write(self, text, tag=None): buf = self.view.get_buffer() if tag is None: buf.insert(buf.get_end_iter(), text) else: buf.insert_with_tags(buf.get_end_iter(), text, tag) GLib.idle_add(self.scroll_to_end) def eval(self, command, display_command=False): buffer = self.view.get_buffer() lin = buffer.get_mark("input-line") buffer.delete(buffer.get_iter_at_mark(lin), buffer.get_end_iter()) if isinstance(command, (list, tuple)): for c in command: if display_command: self.write(">>> " + c + "\n", self.command) self.__run(c) else: if display_command: self.write(">>> " + c + "\n", self.command) self.__run(command) cur = buffer.get_end_iter() buffer.move_mark_by_name("input-line", cur) buffer.insert(cur, ">>> ") cur = buffer.get_end_iter() buffer.move_mark_by_name("input", cur) self.view.scroll_to_iter(buffer.get_end_iter(), 0.0, False, 0.5, 0.5) def __run(self, command): sys.stdout, self.stdout = self.stdout, sys.stdout sys.stderr, self.stderr = self.stderr, sys.stderr try: try: r = eval(command, self.namespace, self.namespace) if r is not None: print_(repr(r)) except SyntaxError: exec(command, self.namespace) except: if hasattr(sys, 'last_type') and sys.last_type == SystemExit: self.destroy() else: traceback.print_exc() sys.stdout, self.stdout = self.stdout, sys.stdout sys.stderr, self.stderr = self.stderr, sys.stderr def get_completion_items(self, ids_str, include_private=False): """ get completion suggestions ids_str - identifiers chain string, e.g. `a.b.c`, or a single identifier """ import inspect def get_comp(obj, pre): """ get completion item names from `obj`-object or `self.namespace` with prefix `pre` """ dir_result = dir(obj) if obj is not None else self.namespace comp = [] # result: (completion-name, details) for name in dir_result: if (pre and not name.startswith(pre)) \ or (not include_private and name.startswith('__')): continue if obj is not None: try: f = getattr(obj, name) except: continue else: f = self.namespace.get(name) if not callable(f): comp.append((name, '')) else: try: spec = inspect.getfullargspec(f) except TypeError: spec = None if spec: sargs = [] arglen = len(spec.args) if spec.args else 0 deflen = len(spec.defaults) if spec.defaults else 0 noargs = arglen - deflen for i in range(arglen): if i == 0 and spec.args[i] == 'self': continue if i < noargs: sargs.append(spec.args[i]) else: default_arg = repr(spec.defaults[i - noargs]) sargs.append(spec.args[i] + '=' + default_arg) details = " ({})".format(", ".join(sargs)) comp.append((name, details)) else: comp.append((name, " ()")) #end for return comp #end get_comp() comp = None # method, field if '.' in ids_str: spl = ids_str.split('.') # search for target object var = None for fname in spl[:-1]: if var is None: var = self.namespace.get(fname) else: try: var = getattr(var, fname, None) except: pass if var is None: break if var is not None: comp = get_comp(obj=var, pre=spl[-1]) # single var or empty else: comp = get_comp(obj=None, pre=ids_str) return comp or [] class OutFile: """A fake output file object. It sends output to a TK test widget, and if asked for a file number, returns one set on instance creation""" def __init__(self, console, tag): self.console = console self.tag = tag def close(self): pass def flush(self): pass def fileno(self): raise IOError def isatty(self): return 0 def read(self, a): return '' def readline(self): return '' def readlines(self): return [] def write(self, s): self.console.write(s, self.tag) def writelines(self, l): self.console.write(l, self.tag) def seek(self, a): raise IOError(29, 'Illegal seek') def tell(self): raise IOError(29, 'Illegal seek') truncate = tell class ListChoiceDialog(Gtk.Dialog): """ display listbox to choose an item from `rows` list, returns index if the chosen item, if positive """ def __init__(self, parent, rows): Gtk.Dialog.__init__(self, title=_("Completion"), transient_for=parent, flags=0) self.set_default_size(400, 250) listbox = Gtk.ListBox() listbox.set_selection_mode(Gtk.SelectionMode.SINGLE) for i, (name, details) in enumerate(rows): row = Gtk.ListBoxRow() hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) row.add(hbox) lbl = Gtk.Label(label=name, xalign=0) lbl2 = Gtk.Label(label=details, xalign=0) hbox.pack_start(lbl, expand=False, fill=False, padding=0) hbox.pack_start(lbl2, expand=True, fill=True, padding=0) # dim the details-label style = lbl2.get_style_context() style.add_class('dim-label') add_css(lbl2, ".dim-label { opacity: 0.5; } ") listbox.add(row) if i == 0: listbox.set_focus_child(row) listbox.connect('row-activated', self.on_row_click) scroll = Gtk.ScrolledWindow() scroll.add(listbox) content = self.get_content_area() content.pack_start(scroll, True, True, 0) content.show_all() self.get_action_area().hide() def on_row_click(self, listbox, row): self.response(row.get_index()) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/cover_download.py�������������������������������������������0000644�0001750�0001750�00000037040�14455205526�022404� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018-2023 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import operator import os import shutil from functools import reduce from typing import Iterable, List from gi.repository import GObject, Gtk, Gdk, Gio, GLib, Soup, GdkPixbuf from quodlibet import _, app, print_d, print_w, util from quodlibet import qltk from quodlibet.formats import AudioFile from senf import path2fsn from quodlibet.pattern import ArbitraryExtensionFileFromPattern, Pattern from quodlibet.plugins import (PluginConfig, ConfProp, IntConfProp, BoolConfProp) from quodlibet.plugins.songshelpers import any_song, is_a_file from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons from quodlibet.qltk.paned import Paned from quodlibet.qltk.window import PersistentWindowMixin from quodlibet.util import connect_destroy, format_size, escape from quodlibet.util.cover import CoverManager from quodlibet.util.cover.manager import CoverData from quodlibet.util.http import download _FULL_PAT = "<albumartist|<albumartist>|<artist>><album| - <album>| - <title>>" SAVE_PATTERNS = [ "folder", "cover", _FULL_PAT, f"{_FULL_PAT} - front", f"{_FULL_PAT} - back" ] IMAGE_EXTENSIONS = { 'image/jpeg': 'jpg', 'image/png': 'png', 'image/gif': 'gif', } class DownloadCoverArt(SongsMenuPlugin): """Download and save album (cover) art from a variety of sources""" PLUGIN_ID = 'Download Cover Art' PLUGIN_NAME = _('Download Cover Art') PLUGIN_DESC = _('Downloads high-quality album covers ' 'using Quod Libet cover plugins.') PLUGIN_ICON = Icons.INSERT_IMAGE REQUIRES_ACTION = True plugin_handles = any_song(lambda song: song("album") and is_a_file(song)) def plugin_album(self, songs): manager = app.cover_manager if not (songs and songs[0]("album")): return dialog = CoverArtWindow(songs, manager, Config()) ret = dialog.run() if ret == Gtk.ResponseType.APPLY: manager.cover_changed(songs) dialog.destroy() class Config: plugin_config = PluginConfig(DownloadCoverArt.PLUGIN_ID.replace(" ", "_")) preview_size = IntConfProp(plugin_config, "preview_size", 500) save_pattern = ConfProp(plugin_config, "save_pattern", "folder.%(ext)") over_scale = BoolConfProp(plugin_config, "preview_over_scale", True) re_encode = BoolConfProp(plugin_config, "re_encode", False) jpg_quality = IntConfProp(plugin_config, "jpeg_quality", 95) class ResizeWebImage(Gtk.Image): """A resizeable widget that can receive loaded images, and save them""" __gsignals__ = { # The content-type, size (in bytes) and properties of a cover # once discovered 'info-known': (GObject.SignalFlags.RUN_LAST, None, (str, int, object)), 'failed': (GObject.SignalFlags.RUN_LAST, None, (str,)) } def __init__(self, url, config: Config, cancellable=None): super().__init__() self.config = config self.url = url self.cancellable = cancellable self.message = msg = Soup.Message.new('GET', self.url) self._content_type = None self._original = None download(msg, cancellable, self._sent, None, failure_callback=lambda *args: self.emit("failed", self.url)) self.set_size_request(config.preview_size, config.preview_size) self._pixbuf = None @property def extension(self): return ("jpg" if self.config.re_encode else IMAGE_EXTENSIONS.get(self._content_type, "jpg")) def _sent(self, msg, result, data): headers = self.message.get_response_headers() self.size = int(headers.get_content_length()) self._content_type = headers.get_content_type()[0] self._original = result try: loader = GdkPixbuf.PixbufLoader() except GLib.GError as e: print_w("Couldn't create GdkPixbuf (%s)" % e) else: loader.write(result) loader.close() self._pixbuf = loader.get_pixbuf() self.emit("info-known", self._content_type, self.size, self._pixbuf.props) self.resize() self.queue_draw() def resize(self, new_size=None): if not self._pixbuf: return if new_size: self.config.preview_size = new_size else: new_size = self.config.preview_size props = self._pixbuf.props if not self.config.over_scale: new_size = min(props.width, props.height, new_size) resized = self._pixbuf.scale_simple(new_size, new_size, GdkPixbuf.InterpType.BILINEAR) self.set_from_pixbuf(resized) self.set_size_request(new_size, new_size) def save_image(self, fsn): fsn = path2fsn(fsn) if self.config.re_encode: quality = str(self.config.jpg_quality) print_d(f"Converting image to JPEG @ {quality}%") ret = self._pixbuf.savev(fsn, "jpeg", ["quality"], [quality]) if not ret: raise IOError("Couldn't save to %s" % fsn) else: print_d("Saving original image to %s" % fsn) with open(fsn, "wb") as f: f.write(self._original) class CoverArtWindow(qltk.Dialog, PersistentWindowMixin): SIZES = { 300: _("Small"), 500: _("Classic"), 600: _("Large"), 720: _("HD"), 1080: _("Full HD"), 1600: _("WQXGA"), 2160: _("4K UHD") } DEFAULT_SIZE = list(SIZES.keys())[0] def __init__(self, songs: Iterable[AudioFile], manager: CoverManager, config: Config, headless: bool = False, **kwargs): super().__init__(title=_("Cover Art Download"), use_header_bar=True, **kwargs) self.set_default_size(1400, 720) id_ = DownloadCoverArt.PLUGIN_ID.lower().replace(" ", "_") self.enable_window_tracking(id_) self.config = config self.headless = headless self.flow_box = box = Gtk.FlowBox() self.model = Gio.ListStore() self.songs = songs self._groups = {} self.button = None def selected(fb): children = fb.get_selected_children() if children: cover = self.model.get_item(children[0].get_index()) if cover: self.button.set_sensitive(True) box.set_valign(Gtk.Align.START) box.set_max_children_per_line(4) box.connect("selected-children-changed", selected) paned = Paned(orientation=Gtk.Orientation.VERTICAL) paned.ensure_wide_handle() sw = Gtk.ScrolledWindow() sw.add(self.flow_box) paned.pack1(sw, True, True) paned.pack2(self.create_options(), False, False) self.vbox.pack_start(paned, True, True, 0) connect_destroy(manager, "covers-found", self._covers_found) connect_destroy(manager, "searches-complete", self._finished) cancellable = self.__cancellable = Gio.Cancellable() self.show_all() # Do the search self._groups = manager.search_cover(cancellable, songs) def destroy(self): if self.__cancellable: print_d("Cancelling remaining requests...") self.__cancellable.cancel() super().destroy() def _image_failed(self, _view, message: str, widget: Gtk.Widget): print_d(f"Failed downloading image ({message}), removing result.") # FlowBox creates a hidden child on addition self.flow_box.remove(widget.get_parent()) def _create_item_widget(self, item): def update(img, content_type, size, props, item, frame): format = IMAGE_EXTENSIONS.get(content_type, content_type).upper() source = escape(item.source) text = (f"{source} - {format}, " f"{props.width} x {props.height}, " f"{util.bold(format_size(size))}") frame.get_label_widget().set_markup(text) frame.get_child().set_reveal_child(True) img = ResizeWebImage(item.url, config=self.config) text = (_("Loading %(source)s - %(dimensions)s…") % {'source': item.source, 'dimensions': item.dimensions}) frame = Gtk.Frame.new(text) img.set_padding(12, 12) frame.set_shadow_type(Gtk.ShadowType.NONE) frame.set_border_width(12) img.connect("info-known", update, item, frame) img.connect("failed", self._image_failed, frame) reveal = Gtk.Revealer() reveal.set_reveal_child(False) reveal.props.transition_duration = 800 reveal.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE eb = Gtk.EventBox() eb.add(img) reveal.add(eb) frame.add(reveal) frame.set_label_align(0.5, 1.0) reveal.connect("button-press-event", self._on_click) return frame def _on_click(self, view, event): # TODO: less hacky way to detect double-click if (event.button == Gdk.BUTTON_PRIMARY and event.type != Gdk.EventType.BUTTON_PRESS): self.__save(None) self.destroy() def _filenames(self, pat_text, ext, full_path=False) -> List[str]: def fn_for(song): pat = ArbitraryExtensionFileFromPattern(f"{pat_text}.{ext}") fn = pat.format(song) return os.path.join(song('~dirname'), fn) if full_path else fn return sorted({fn_for(song) for song in self.songs}) def _covers_found(self, manager, provider, results): if not results: print_d(f"No results from {provider}") return for result in results: self.model.append(result) self.flow_box.insert(self._create_item_widget(result), 0) self.show_all() def _finished(self, manager, results): if not any(results.values()): print_w(f"Nothing found from {len(self._groups)} provider(s)") self.button.set_sensitive(False) if not self.headless: self._quit(results) def _quit(self, results): pat = Pattern("<albumartist|<albumartist>|<artist>> - <album>") group_songs = [songs for group in self._groups.values() for songs in group.values()] texts = {pat.format(s) for s in reduce(operator.concat, group_songs, [])} albums = "\n".join(texts) providers = ", ".join({manager.name for manager in results.keys()}) data = {'albums': util.italic(albums), 'providers': util.monospace(providers)} markup = _("Nothing found for albums:\n%(albums)s.\n\n" "Providers used:\n%(providers)s") % data dialog = qltk.Message(Gtk.MessageType.INFO, parent=self, title=_("No covers found"), description=markup, escape_desc=False) dialog.run() self.destroy() @staticmethod def __image_from_child(child): # Ugh, horrible return child.get_child().get_child().get_child().get_child() def create_options(self): frame = Gtk.Frame(label=_("Options")) hbox = Gtk.HBox() sizes = self.SIZES.keys() slider = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, min(sizes), max(sizes), 100) for size, name in self.SIZES.items(): slider.add_mark(size, Gtk.PositionType.BOTTOM, name) slider.set_show_fill_level(False) slider.set_value(self.config.preview_size) def format_dims(_slider, value): size = int(value) return _(f"{size} ✕ {size} px") def slider_changed(_slider): new_size = slider.get_value() try: for child in self.flow_box.get_children(): img = self.__image_from_child(child) img.resize(new_size) except AttributeError as e: print_w(f"Couldn't set picture size(s) ({e})") slider.connect("format-value", format_dims) slider.connect("value-changed", slider_changed) label = Gtk.Label(_("Preview size")) label.set_mnemonic_widget(slider) hbox.pack_start(label, False, False, 6) hbox.pack_start(slider, True, True, 6) vbox = Gtk.VBox() vbox.pack_start(hbox, False, False, 6) def create_save_box(): hbox = Gtk.HBox() label = Gtk.Label(_("Save destination")) hbox.pack_start(label, False, False, 6) model = Gtk.ListStore(str) for val in SAVE_PATTERNS: model.append(row=[val]) save_filename = Gtk.ComboBox(model=model) label.set_mnemonic_widget(save_filename) cell = Gtk.CellRendererText() save_filename.pack_start(cell, True) def draw_save_type(column, cell, model, it, data): pat_text = model[it][0] ext = "jpg" if self.config.re_encode else "*" text = list(self._filenames(pat_text, ext))[0] cell.set_property("markup", util.monospace(text)) save_filename.set_cell_data_func(cell, draw_save_type, None) def changed(combo): value = model.get_value(combo.get_active_iter(), 0) self.config.save_pattern = value def select_value(combo, value): for i, item in enumerate(model): if value == item[0]: combo.set_active(i) save_filename.connect("changed", changed) select_value(save_filename, self.config.save_pattern) hbox.pack_start(save_filename, False, False, 6) create_ccb = self.config.plugin_config.ConfigCheckButton tooltip = _("If not already a JPEG, convert the image to " "a high-quality JPEG of the same size") re_encode = create_ccb(_("Save as JPEG"), "re_encode", tooltip=tooltip, populate=True) re_encode.connect("toggled", lambda _: hbox.queue_draw()) hbox.pack_start(re_encode, False, False, 6) return hbox vbox.pack_start(create_save_box(), False, False, 6) frame.add(vbox) self.button = self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.APPLY) self.button.set_sensitive(False) self.button.connect("clicked", self.__save) return frame def __save(self, button): child = self.flow_box.get_selected_children()[0] data = self.model.get_item(child.get_index()) img = self.__image_from_child(child) self._save_images(data, img) def _save_images(self, data: CoverData, img: Gtk.Image): paths = self._filenames(self.config.save_pattern, img.extension, full_path=True) try: first_path = paths.pop() except IndexError: print_w("No paths to save somewhow", self) print_d(f"Saving {data} to {first_path}") img.save_image(first_path) # Copying faster than potentially resizing if paths: for path in paths: shutil.copy(first_path, path) print_d(f"Finished copying to {paths}") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/custom_commands.py������������������������������������������0000644�0001750�0001750�00000026117�14267565021�022575� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk import os from quodlibet.util.songwrapper import SongWrapper from quodlibet.qltk.songsmenu import confirm_multi_song_invoke import quodlibet from quodlibet import _ from quodlibet import qltk from quodlibet import util from quodlibet.pattern import Pattern from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk.data_editors import JSONBasedEditor from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.qltk import ErrorMessage, Icons from quodlibet.qltk.getstring import GetStringDialog from quodlibet.util.dprint import print_w, print_d, print_e from quodlibet.util.json_data import JSONObject, JSONObjectDict from quodlibet.util import connect_obj, print_exc Field = JSONObject.Field class Command(JSONObject): """ Wraps an arbitrary shell command and its argument pattern. Serialises as JSON for some editability """ NAME = _("Command") FIELDS = { "name": Field(_("name"), _("The name of this command")), "command": Field(_("command"), _("The shell command syntax to run")), "parameter": Field(_("parameter"), _("If specified, a parameter whose occurrences in " "the command will be substituted with a " "user-supplied value, e.g. by using 'PARAM' " "all instances of '{PARAM}' in your command will " "have the value prompted for when run")), "pattern": Field(_("pattern"), _("The QL pattern, e.g. <~filename>, to use to " "compute a value for the command. For playlists, " "this also supports virtual tags <~playlistname> " "and <~#playlistindex>.")), "unique": Field(_("unique"), _("If set, this will remove duplicate computed values " "of the pattern")), "max_args": Field(_("max args"), _("The maximum number of argument to pass to the " "command at one time (like xargs)")), "reverse": Field(_("reverse"), _("If set, the argument list will be reversed")), } def __init__(self, name=None, command=None, pattern="<~filename>", unique=False, parameter=None, max_args=10000, reverse=False, warn_threshold=50): JSONObject.__init__(self, name) self.command = str(command or "") self.pattern = str(pattern) self.unique = bool(unique) self.max_args = max_args self.reverse = bool(reverse) self.parameter = str(parameter or "") self.__pat = Pattern(self.pattern) self.warn_threshold = warn_threshold def run(self, songs, playlist_name=None): """ Runs this command on `songs`, splitting into multiple calls if necessary. `playlist_name` if populated contains the Playlist's name. """ args = [] template_vars = {} if self.parameter: value = GetStringDialog(None, _("Input value"), _("Value for %s?") % self.parameter).run() template_vars[self.parameter] = value if playlist_name: print_d("Playlist command for %s" % playlist_name) template_vars["PLAYLIST"] = playlist_name actual_command = self.command.format(**template_vars) print_d("Actual command=%s" % actual_command) for i, song in enumerate(songs): wrapped = SongWrapper(song) if playlist_name: wrapped["~playlistname"] = playlist_name wrapped["~playlistindex"] = str(i + 1) wrapped["~#playlistindex"] = i + 1 arg = str(self.__pat.format(wrapped)) if not arg: print_w("Couldn't build shell command using \"%s\"." "Check your pattern?" % self.pattern) break if not self.unique: args.append(arg) elif arg not in args: args.append(arg) max = int((self.max_args or 10000)) com_words = actual_command.split(" ") if self.reverse: args.reverse() while args: print_d("Running %s with %d substituted arg(s) (of %d%s total)..." % (actual_command, min(max, len(args)), len(args), " unique" if self.unique else "")) util.spawn(com_words + args[:max]) args = args[max:] @property def playlists_only(self): return ("~playlistname" in self.pattern or "playlistindex" in self.pattern) def __str__(self): return "{command} {pattern}".format(**dict(self.data)) class CustomCommands(PlaylistPlugin, SongsMenuPlugin, PluginConfigMixin): PLUGIN_ICON = Icons.APPLICATION_UTILITIES PLUGIN_ID = "CustomCommands" PLUGIN_NAME = _("Custom Commands") PLUGIN_DESC = _("Runs custom commands (in batches if required) on songs " "using any of their tags.") # Here are some starters... DEFAULT_COMS = [ Command("Compress files", "file-roller -d"), Command("Browse folders (Thunar)", "thunar", "<~dirname>", unique=True, max_args=50, warn_threshold=20), Command("Burn using K3b", "k3b --audiocd"), Command("Burn using Brasero", "brasero --audio"), Command("Burn using Xfburn", "xfburn --audio-composition", reverse=True), Command("Flash notification", command="notify-send" " -t 2000" " -i " "/usr/share/icons/hicolor/scalable/apps/" "io.github.quodlibet.QuodLibet.svg", pattern="<~rating> \"<title><version| (<version>)>\"" "<~people| by <~people>>" "<album|, from <album><discnumber| : disk <discnumber>>" "<~length| (<~length>)>", max_args=1, warn_threshold=10), Command("Output playlist to stdout", command="echo -e", pattern="<~playlistname>: <~playlistindex>. " " <~artist~title>\\\\n", warn_threshold=20), Command("Fix MP3 VBR with mp3val", "mp3val -f", unique=True, max_args=1), Command("Record Stream", command="x-terminal-emulator -e wget -P $HOME", pattern="<~filename>", max_args=1) ] COMS_FILE = os.path.join( quodlibet.get_user_dir(), 'lists', 'customcommands.json') _commands = None """Commands known to the class""" def __set_pat(self, name): self.com_index = name def get_data(self, key): """Gets the pattern for a given key""" try: return self.all_commands()[key] except (KeyError, TypeError): print_d("Invalid key %s" % key) return None @classmethod def edit_patterns(cls, button): win = JSONBasedEditor(Command, cls.all_commands(), filename=cls.COMS_FILE, title=_("Edit Custom Commands")) # Cache busting cls._commands = None win.show() @classmethod def PluginPreferences(cls, parent): hb = Gtk.HBox(spacing=3) hb.set_border_width(0) button = qltk.Button(_("Edit Custom Commands") + "…", Icons.EDIT) button.connect("clicked", cls.edit_patterns) hb.pack_start(button, True, True, 0) hb.show_all() return hb @classmethod def all_commands(cls): if cls._commands is None: cls._commands = cls._get_saved_commands() return cls._commands @classmethod def _get_saved_commands(cls): filename = cls.COMS_FILE print_d("Loading saved commands from '%s'..." % filename) coms = None try: with open(filename, "r", encoding="utf-8") as f: coms = JSONObjectDict.from_json(Command, f.read()) except (IOError, ValueError) as e: print_w("Couldn't parse saved commands (%s)" % e) # Failing all else... if not coms: print_d("No commands found in %s. Using defaults." % filename) coms = {c.name: c for c in cls.DEFAULT_COMS} print_d("Loaded commands: %s" % coms.keys()) return coms def __init__(self, *args, **kwargs): super().__init__(**kwargs) pl_mode = hasattr(self, '_playlists') and bool(len(self._playlists)) self.com_index = None self.unique_only = False submenu = Gtk.Menu() for name, c in self.all_commands().items(): item = Gtk.MenuItem(label=name) connect_obj(item, 'activate', self.__set_pat, name) if pl_mode and not c.playlists_only: continue item.set_sensitive(c.playlists_only == pl_mode) submenu.append(item) self.add_edit_item(submenu) if submenu.get_children(): self.set_submenu(submenu) else: self.set_sensitive(False) @classmethod def add_edit_item(cls, submenu): config = Gtk.MenuItem(label=_("Edit Custom Commands") + "…") connect_obj(config, 'activate', cls.edit_patterns, config) config.set_sensitive(not JSONBasedEditor.is_not_unique()) submenu.append(SeparatorMenuItem()) submenu.append(config) def plugin_songs(self, songs): self._handle_songs(songs) def plugin_playlist(self, playlist): print_d("Running playlist plugin for %s" % playlist) return self._handle_songs(playlist.songs, playlist) def _handle_songs(self, songs, playlist=None): # Check this is a launch, not a configure if self.com_index: com = self.get_data(self.com_index) if len(songs) > com.warn_threshold: if not confirm_multi_song_invoke( self, com.name, len(songs)): print_d("User decided not to run on %d songs" % len(songs)) return print_d("Running %s on %d song(s)" % (com, len(songs))) try: com.run(songs, playlist and playlist.name) except Exception as err: print_e("Couldn't run command %s: %s %s at:" % (com.name, type(err), err, )) print_exc() ErrorMessage( self.plugin_window, _("Unable to run custom command %s") % util.escape(self.com_index), util.escape(str(err))).run() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/duplicates.py�����������������������������������������������0000644�0001750�0001750�00000040252�14267565021�021533� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Duplicates songs plugin. # # Copyright (C) 2011-2019 Nick Boultbee # # Finds "duplicates" of songs selected by searching the library for # others with the same user-configurable "key", presenting a browser-like # dialog for further interaction with these. # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango from quodlibet import app from quodlibet import print_d, util, qltk, _ from quodlibet.plugins import PluginConfigMixin from quodlibet.plugins.songshelpers import any_song, is_finite from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk.edittags import AudioFileGroup from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk import Icons, Button from quodlibet.util import connect_obj, connect_destroy from quodlibet.util.i18n import numeric_phrase from quodlibet.util.string.filter import remove_diacritics, remove_punctuation class DuplicateSongsView(RCMHintedTreeView): """Allows full tree-like functionality on top of underlying features""" def get_selected_songs(self): selection = self.get_selection() if selection is None: return [] model, rows = selection.get_selected_rows() if not rows: return [] selected = [] for row in rows: row = model[row] if row.parent is None: for child in row.iterchildren(): selected.append(child[0]) else: selected.append(row[0]) return selected def Menu(self, library): songs = self.get_selected_songs() if not songs: return menu = SongsMenu( library, songs, delete=True, plugins=False, playlists=False) menu.show_all() return menu def __select_song(self, player, path, col): if len(path) == 1: if self.row_expanded(path): self.collapse_row(path) else: self.expand_row(path, False) else: songs = self.get_selected_songs() if songs and player.go_to(songs[0], True): player.paused = False def _removed(self, library, songs): model = self.get_model() if not model: return for song in songs: row = model.find_row(song) if row: group_row = model.iter_parent(row.iter) print_d("Found parent group = %s" % group_row) model.remove(row.iter) num_kids = model.iter_n_children(group_row) if num_kids < Duplicates.MIN_GROUP_SIZE: print_d("Removing group %s" % group_row) model.remove(group_row) else: pass def _added(self, library, songs): model = self.get_model() if not model: return for song in songs: key = Duplicates.get_key(song) model.add_to_existing_group(key, song) # TODO: handle creation of new groups based on songs that were # in original list but not as a duplicate def _changed(self, library, songs): model = self.get_model() if not model: # Keeps happening on next song - bug / race condition? return for song in songs: key = Duplicates.get_key(song) row = model.find_row(song) if row: print_d("Changed duplicated file \"%s\" (Row=%s)" % (song("~artist~title"), row)) parent = model.iter_parent(row.iter) old_key = model[parent][0] if old_key != key: print_d("Key changed from \"%s\" -> \"%s\"" % (old_key, key)) self._removed(library, [song]) self._added(library, [song]) else: # Still might be a displayable change print_d("Calling model.row_changed(%s, %s)..." % (row.path, row.iter)) model.row_changed(row.path, row.iter) else: model.add_to_existing_group(key, song) def __init__(self, model): super().__init__(model) connect_obj(self, 'row-activated', self.__select_song, app.player) # Selecting multiple is a nice feature it turns out. self.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) # Handle signals propagated from the underlying library self.connected_library_sigs = [] SIGNAL_MAP = { 'removed': self._removed, 'added': self._added, 'changed': self._changed } for (sig, callback) in SIGNAL_MAP.items(): print_d("Listening to library.%s signals" % sig) connect_destroy(app.library, sig, callback) class DuplicatesTreeModel(Gtk.TreeStore): """A tree store to model duplicated song information""" # Define columns to display (and how, in lieu of using qltk.browsers) def i(x): return x TAG_MAP = [ ("artist", i), ("title", i), ("album", i), ("~#length", lambda s: util.format_time_display(int(s))), ("~#filesize", lambda s: util.format_size(int(s))), ("~#bitrate", i), ("~filename", i)] # Now make a dict. This seems clunky. tag_functions = {} for t, f in TAG_MAP: tag_functions[t] = f @classmethod def group_value(cls, group, tag): """Gets a formatted aggregated value/dummy for a set of tag values""" try: vals = [] for comment in group[tag]: vals.append(comment.get_markup()) group_val = "\n".join(vals) except KeyError: return "" else: try: group_val = cls.tag_functions[tag](group_val) except (ValueError, TypeError): pass return group_val.replace("\n", ", ") def find_row(self, song): """Returns the row in the model from song, or None""" for parent in self: for row in parent.iterchildren(): if row[0] == song: self.__iter = row.iter self.sourced = True return row return None def add_to_existing_group(self, key, song): """Tries to add a song to an existing group. Returns None if not able """ for parent in self: if key == parent[0]: print_d("Found group", self) return self.append(parent.iter, self.__make_row(song)) # TODO: update group return None @classmethod def __make_row(cls, song): """Construct GTK row for a song, with all columns""" return [song] + [util.escape(str(f(song.comma(tag)))) for (tag, f) in cls.TAG_MAP] def add_group(self, key, songs): """Adds a new group, returning the row created""" group = AudioFileGroup(songs, real_keys_only=False) # Add the group first. parent = self.append(None, [key] + [self.group_value(group, tag) for tag, f in self.TAG_MAP]) for s in songs: self.append(parent, self.__make_row(s)) def go_to(self, song, explicit=False): self.__iter = None if isinstance(song, Gtk.TreeIter): self.__iter = song self.sourced = True elif not self.find_row(song): print_d("Failed to find song") return self.__iter def remove(self, itr): if self.__iter and self[itr].path == self[self.__iter].path: self.__iter = None super().remove(itr) def get(self): return [row[0] for row in self] @property def get_current(self): if self.__iter is None: return None elif self.is_empty(): return None else: return self[self.__iter][0] @property def get_current_path(self): if self.__iter is None: return None elif self.is_empty(): return None else: return self[self.__iter].path @property def get_current_iter(self): if self.__iter is None: return None elif self.is_empty(): return None else: return self.__iter def is_empty(self): return not len(self) def __init__(self): super().__init__( object, str, str, str, str, str, str, str) class DuplicateDialog(Gtk.Window): """Main dialog for browsing duplicate results""" def __quit(self, widget=None, response=None): if response == Gtk.ResponseType.OK or \ response == Gtk.ResponseType.CLOSE: print_d("Exiting plugin on user request...") self.finished = True self.destroy() return def __songs_popup_menu(self, songlist): path, col = songlist.get_cursor() menu = songlist.Menu(app.library) if menu is not None: return songlist.popup_menu(menu, 0, Gtk.get_current_event_time()) def __init__(self, model): songs_text = numeric_phrase("%d duplicate group", "%d duplicate groups", len(model)) super().__init__() self.set_destroy_with_parent(True) self.set_title("Quod Libet - %s (%s)" % (Duplicates.PLUGIN_NAME, songs_text)) self.finished = False self.set_default_size(960, 480) self.set_border_width(6) swin = Gtk.ScrolledWindow() swin.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) swin.set_shadow_type(Gtk.ShadowType.IN) # Set up the browser view view = DuplicateSongsView(model) def cell_text(column, cell, model, iter_, index): text = model[iter_][index] cell.markup = text cell.set_property("markup", text) # Set up the columns for i, (tag, f) in enumerate(DuplicatesTreeModel.TAG_MAP): e = (Pango.EllipsizeMode.START if tag == '~filename' else Pango.EllipsizeMode.END) render = Gtk.CellRendererText() render.set_property("ellipsize", e) col = Gtk.TreeViewColumn(util.tag(tag), render) # Numeric columns are better smaller here. if tag.startswith("~#"): col.set_fixed_width(80) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) else: col.set_expand(True) col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) col.set_resizable(True) col.set_cell_data_func(render, cell_text, i + 1) view.append_column(col) view.connect('popup-menu', self.__songs_popup_menu) swin.add(view) # A basic information area hbox = Gtk.HBox(spacing=6) def expand_all(*args): model = view.get_model() for row in model: if view.row_expanded(row.path): view.collapse_row(row.path) else: for row in model: view.expand_row(row.path, False) expand = Gtk.Button(_("Collapse / Expand all")) connect_obj(expand, "clicked", expand_all, view) hbox.pack_start(expand, False, True, 0) label = Gtk.Label(label=_("Duplicate key expression is '%s'") % Duplicates.get_key_expression()) hbox.pack_start(label, True, True, 0) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', self.__quit) hbox.pack_start(close, False, True, 0) vbox = Gtk.VBox(spacing=6) vbox.pack_start(swin, True, True, 0) vbox.pack_start(hbox, False, True, 0) self.add(vbox) self.show_all() class Duplicates(SongsMenuPlugin, PluginConfigMixin): PLUGIN_ID = 'Duplicates' PLUGIN_NAME = _('Duplicates Browser') PLUGIN_DESC = _('Finds and displays similarly tagged versions of songs.') PLUGIN_ICON = Icons.EDIT_SELECT_ALL MIN_GROUP_SIZE = 2 _CFG_KEY_KEY = "key_expression" __DEFAULT_KEY_VALUE = "~artist~title~version" _CFG_REMOVE_WHITESPACE = 'remove_whitespace' _CFG_REMOVE_DIACRITICS = 'remove_diacritics' _CFG_REMOVE_PUNCTUATION = 'remove_punctuation' _CFG_CASE_INSENSITIVE = 'case_insensitive' plugin_handles = any_song(is_finite) # Cached values key_expression = None @classmethod def get_key_expression(cls): if not cls.key_expression: cls.key_expression = ( cls.config_get(cls._CFG_KEY_KEY, cls.__DEFAULT_KEY_VALUE)) return cls.key_expression @classmethod def PluginPreferences(cls, window): def key_changed(entry): cls.key_expression = None cls.config_set(cls._CFG_KEY_KEY, entry.get_text().strip()) vb = Gtk.VBox(spacing=10) vb.set_border_width(0) hbox = Gtk.HBox(spacing=6) # TODO: construct a decent validator and use ValidatingEntry e = UndoEntry() e.set_text(cls.get_key_expression()) e.connect("changed", key_changed) e.set_tooltip_markup(_("Accepts QL tag expressions like " "<tt>~artist~title</tt> or <tt>musicbrainz_track_id</tt>")) lbl = Gtk.Label(label=_("_Group duplicates by:")) lbl.set_mnemonic_widget(e) lbl.set_use_underline(True) hbox.pack_start(lbl, False, True, 0) hbox.pack_start(e, True, True, 0) frame = qltk.Frame(label=_("Duplicate Key"), child=hbox) vb.pack_start(frame, True, True, 0) # Matching Option toggles = [ (cls._CFG_REMOVE_WHITESPACE, _("Remove _Whitespace")), (cls._CFG_REMOVE_DIACRITICS, _("Remove _Diacritics")), (cls._CFG_REMOVE_PUNCTUATION, _("Remove _Punctuation")), (cls._CFG_CASE_INSENSITIVE, _("Case _Insensitive")), ] vb2 = Gtk.VBox(spacing=6) for key, label in toggles: ccb = ConfigCheckButton(label, 'plugins', cls._config_key(key)) ccb.set_active(cls.config_get_bool(key)) vb2.pack_start(ccb, True, True, 0) frame = qltk.Frame(label=_("Matching options"), child=vb2) vb.pack_start(frame, False, True, 0) vb.show_all() return vb @classmethod def get_key(cls, song): key = song(cls.get_key_expression()) if cls.config_get_bool(cls._CFG_REMOVE_DIACRITICS): key = remove_diacritics(key) if cls.config_get_bool(cls._CFG_CASE_INSENSITIVE): key = key.lower() if cls.config_get_bool(cls._CFG_REMOVE_PUNCTUATION): key = remove_punctuation(key) if cls.config_get_bool(cls._CFG_REMOVE_WHITESPACE): key = "_".join(key.split()) return key def plugin_songs(self, songs): model = DuplicatesTreeModel() # Index all songs by our custom key # TODO: make this cache-friendly print_d("Calculating duplicates for %d song(s)..." % len(songs)) groups = {} for song in songs: key = self.get_key(song) if key and key in groups: print_d("Found duplicate based on '%s'" % key) groups[key].add(song._song) elif key: groups[key] = {song._song} for song in app.library: key = self.get_key(song) if key in groups: groups[key].add(song) # Now display the grouped duplicates for (key, children) in groups.items(): if len(children) < self.MIN_GROUP_SIZE: continue # The parent (group) label model.add_group(key, children) dialog = DuplicateDialog(model) dialog.show() # Mainly for testing... return dialog ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/editplaycount.py��������������������������������������������0000644�0001750�0001750�00000011241�14327505043�022251� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2015 Ryan "ZDBioHazard" Turner <zdbiohazard2@gmail.com> # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _, util from quodlibet.plugins.songshelpers import each_song, is_writable from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons class EditPlaycount(SongsMenuPlugin): PLUGIN_ID = "editplaycount" PLUGIN_NAME = _("Edit Playcount") PLUGIN_DESC_MARKUP = _( "Edit a song's <tt>~#playcount</tt> and <tt>~#skipcount.</tt>" "\n\n" "When multiple songs are selected, counts will be " "incremented, rather than set." "\n\n" "When setting a song's <tt>~#playcount</tt> to 0, " "the <tt>~#lastplayed</tt> and <tt>~#laststarted</tt> " "entries will be cleared. " "However, when setting a 0-play song to a positive play " "count, no play times will be created.") PLUGIN_ICON = Icons.EDIT REQUIRES_ACTION = True plugin_handles = each_song(is_writable) def plugin_songs(self, songs): # This is just here so the spinner has something to call. >.> def response(win, response_id): dlg.response(response_id) return # Create a dialog. dlg = Gtk.Dialog(title=_("Edit Playcount"), flags=(Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)) dlg.add_button(_("_Cancel"), Gtk.ResponseType.REJECT) dlg.add_button(_("_Apply"), Gtk.ResponseType.APPLY) dlg.set_default_response(Gtk.ResponseType.APPLY) dlg.set_border_width(4) dlg.vbox.set_spacing(4) # Create some spinners. play = Gtk.SpinButton() play.set_adjustment(Gtk.Adjustment(0, -1000, 1000, 1, 1)) skip = Gtk.SpinButton() skip.set_adjustment(Gtk.Adjustment(0, -1000, 1000, 1, 1)) # Connect the signals. play.connect("activate", response, Gtk.ResponseType.APPLY) skip.connect("activate", response, Gtk.ResponseType.APPLY) # Set some defaults. play.set_numeric(True) skip.set_numeric(True) # Put all this stuff in a pretty table. table = Gtk.Table(rows=2, columns=2) table.set_row_spacings(4) table.set_col_spacings(4) table.attach(Gtk.Label(_("Play Count")), 0, 1, 0, 1) table.attach(Gtk.Label(_("Skip Count")), 0, 1, 1, 2) table.attach(play, 1, 2, 0, 1) table.attach(skip, 1, 2, 1, 2) dlg.vbox.add(table) # Make a couple tweaks based on the current mode. if len(songs) == 1: play.set_adjustment(Gtk.Adjustment(0, 0, 9999, 1, 1)) skip.set_adjustment(Gtk.Adjustment(0, 0, 9999, 1, 1)) play.set_value(songs[0].get('~#playcount', 0)) skip.set_value(songs[0].get('~#skipcount', 0)) else: note = Gtk.Label() note.set_justify(Gtk.Justification.CENTER) note.set_markup(util.bold(_("Multiple files selected.")) + "\n" + _("Counts will be incremented.")) dlg.vbox.add(note) dlg.show_all() # Only operate if apply is pressed. if dlg.run() == Gtk.ResponseType.APPLY: for song in songs: # Increment when not in single mode. if len(songs) == 1: song['~#playcount'] = play.get_value_as_int() song['~#skipcount'] = skip.get_value_as_int() else: # Can't use += here because these tags might not exist. song['~#playcount'] = max(0, (song.get('~#playcount', 0) + play.get_value_as_int())) song['~#skipcount'] = max(0, (song.get('~#skipcount', 0) + skip.get_value_as_int())) # When the playcount is set to 0, delete the playcount # itself and the last played/started time. We don't # want unused or impossible data floating around. if song.get('~#playcount', 0) == 0: for tag in ['~#playcount', '~#lastplayed', '~#laststarted']: song.pop(tag, None) # Also delete the skip count if it's zero. if song.get('~#skipcount', 0) == 0: song.pop('~#skipcount', None) dlg.destroy() return ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1659470130.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/embedded.py�������������������������������������������������0000644�0001750�0001750�00000010377�14272300462�021124� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2013-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _, print_d, ngettext from quodlibet import app from quodlibet import util from quodlibet.plugins.songshelpers import any_song, has_writable_image from quodlibet.qltk.chooser import _get_chooser from quodlibet.qltk.x import MenuItem from quodlibet.qltk import Icons from quodlibet.qltk.wlw import WritingWindow from quodlibet.qltk._editutils import WriteFailedError from quodlibet.formats import EmbeddedImage, AudioFileError, AudioFile from quodlibet.plugins.songsmenu import SongsMenuPlugin class EditEmbedded(SongsMenuPlugin): PLUGIN_ID = "embedded_edit" PLUGIN_NAME = _("Edit Embedded Images") PLUGIN_DESC = _("Adds, removes or replaces embedded images.") PLUGIN_ICON = Icons.INSERT_IMAGE plugin_handles = any_song(has_writable_image) """if any song supports editing, we are active""" def __init__(self, songs, *args, **kwargs): super().__init__(songs, *args, **kwargs) self.__menu = Gtk.Menu() self._init_submenu_items(self.__menu, songs) self.set_submenu(self.__menu) def __remove_images(self, menu_item, songs): win = WritingWindow(self.plugin_window, len(songs)) win.show() for song in songs: if song.has_images and song.can_change_images: try: song.clear_images() except AudioFileError: util.print_exc() WriteFailedError(win, song).run() if win.step(): break win.destroy() self.plugin_finish() def __set_image(self, menu_item, songs): win = WritingWindow(self.plugin_window, len(songs)) win.show() for song in songs: if song.can_change_images: fileobj = app.cover_manager.get_cover(song) if fileobj: path = fileobj.name image = EmbeddedImage.from_path(path) if image: _set_image_or_throw(image, song, win) if win.step(): break win.destroy() self.plugin_finish() def __choose_image(self, menu_item, songs): dialog = _get_chooser(_('_Embed'), _('_Cancel')) total = len(songs) msg = ngettext("Choose image to embed in the %d track", "Choose image to embed in %d tracks", total) % total dialog.set_title(msg) response = dialog.run() path = dialog.get_filename() dialog.destroy() if response != Gtk.ResponseType.ACCEPT: print_d("User cancelled image embedding") return win = WritingWindow(self.plugin_window, len(songs)) win.show() for song in songs: if song.can_change_images: image = EmbeddedImage.from_path(path) if image: _set_image_or_throw(image, song, win) if win.step(): break win.destroy() self.plugin_finish() def _init_submenu_items(self, menu, songs): remove_item = MenuItem(_("_Remove all Images"), Icons.EDIT_DELETE) remove_item.connect('activate', self.__remove_images, songs) remove_item.set_sensitive(any(song.has_images for song in songs)) menu.append(remove_item) set_item = MenuItem(_("_Embed Current Image"), Icons.EDIT_PASTE) set_item.connect('activate', self.__set_image, songs) menu.append(set_item) set_item = MenuItem(_("_Choose Image…"), Icons.DOCUMENT_OPEN) set_item.connect('activate', self.__choose_image, songs) menu.append(set_item) menu.show_all() return menu def plugin_songs(self, songs): return True def _set_image_or_throw(image: EmbeddedImage, song: AudioFile, win: Gtk.Window) -> None: try: song.set_image(image) except AudioFileError: util.print_exc() WriteFailedError(win, song).run() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/exact_rating.py���������������������������������������������0000664�0001750�0001750�00000003721�14037102221�022030� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Jan Path # 2014 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet import config from quodlibet.plugins.songshelpers import any_song from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk import Icons from quodlibet.qltk.ratingsmenu import ConfirmRateMultipleDialog from quodlibet.plugins.songsmenu import SongsMenuPlugin class ExactRating(SongsMenuPlugin): PLUGIN_ID = "exact-rating" PLUGIN_NAME = _("Set Exact Rating") PLUGIN_DESC = _("Allows setting the rating of songs with a number.") REQUIRES_ACTION = True PLUGIN_ICON = Icons.USER_BOOKMARKS plugin_handles = any_song(lambda s: s.can_change()) def plugin_songs(self, songs): value = -1 while not 0 <= value <= 1: input_string = GetStringDialog( self.plugin_window, self.PLUGIN_NAME, _("Please give your desired rating on a scale " "from 0.0 to 1.0"), _("_Apply"), Icons.NONE ).run() if input_string is None: return try: value = float(input_string) except ValueError: continue count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): confirm_dialog = ConfirmRateMultipleDialog(self.plugin_window, count, value) if confirm_dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value �����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/filterall.py������������������������������������������������0000664�0001750�0001750�00000006321�14035600052�021340� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import _ from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.tags import MACHINE_TAGS from quodlibet.util import build_filter_query from quodlibet.qltk import Window, Icons, Button class SelectionWindow(Window): def __init__(self, filters, browser, parent=None): super().__init__() self.set_border_width(10) self.set_title(FilterAll.PLUGIN_NAME) self.set_default_size(200, 250) self.set_transient_for(parent) model = Gtk.ListStore(bool, str, str) for key, value in sorted(filters.items()): model.append(row=[False, key, value]) toggle = Gtk.CellRendererToggle() toggle.connect("toggled", self.__toggeled, model, browser) text = Gtk.CellRendererText() toggle_column = Gtk.TreeViewColumn("", toggle, active=0) column = Gtk.TreeViewColumn(_("Tag"), text, text=1) view = Gtk.TreeView(model) view.append_column(toggle_column) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) buttons = Gtk.HButtonBox() buttons.set_spacing(6) buttons.set_layout(Gtk.ButtonBoxStyle.END) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) buttons.pack_start(close, True, True, 0) box = Gtk.VBox(spacing=12) box.pack_start(sw, True, True, 0) box.pack_start(buttons, False, True, 0) self.add(box) self.show_all() def __filter(self, model, browser): selected = {} for row in model: sel, key, value = row if sel: selected[key] = value joined = ", ".join(sorted(selected.values())) if len(selected) >= 2: joined = "&(%s)" % joined browser.filter_text(joined) def __toggeled(self, render, path, model, browser): model[path][0] = not model[path][0] self.__filter(model, browser) class FilterAll(SongsMenuPlugin): PLUGIN_ID = "FilterAll" PLUGIN_NAME = _("Filter on Any Tag") PLUGIN_DESC = _("Creates a search query based on " "tags of the selected songs.") PLUGIN_ICON = Icons.EDIT_FIND REQUIRES_ACTION = True def plugin_songs(self, songs): browser = self.plugin_window.browser if not browser.can_filter_text(): return keys = {key for song in songs for key in song.realkeys()} keys.difference_update(MACHINE_TAGS) filters = {} for key in keys: values = set() for song in songs: values.update(song.list(key)) filters[key] = build_filter_query(key, values) SelectionWindow(filters, browser, parent=self.plugin_window) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689589142.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/filterbrowser.py��������������������������������������������0000644�0001750�0001750�00000002162�14455212626�022264� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import app from quodlibet import browsers from quodlibet.plugins.songshelpers import any_song, is_a_file from quodlibet.qltk.browser import LibraryBrowser from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin class FilterBrowser(SongsMenuPlugin): PLUGIN_ID = 'filterbrowser' PLUGIN_NAME = _('Filter on Directory') PLUGIN_DESC = _("Filters on directory in a new browser window.") PLUGIN_ICON = Icons.EDIT_SELECT_ALL plugin_handles = any_song(is_a_file) def plugin_songs(self, songs): tag = "~dirname" values = [] for song in songs: values.extend(song.list(tag)) browser = LibraryBrowser.open( browsers.get("SearchBar"), app.library, app.player) browser.browser.filter(tag, set(values)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9909356 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�021337� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/__init__.py�������������������������������������0000644�0001750�0001750�00000006274�14267565021�023472� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gst if not Gst.ElementFactory.find("chromaprint"): from quodlibet import plugins raise plugins.MissingGstreamerElementPluginException("chromaprint") from .submit import FingerprintDialog from .util import get_api_key from quodlibet import _ from quodlibet import config from quodlibet import util from quodlibet.qltk import Button, Frame, Icons from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.msg import ErrorMessage from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import is_writable, is_finite, each_song class AcoustidSearch(SongsMenuPlugin): PLUGIN_ID = "AcoustidSearch" PLUGIN_NAME = _("Acoustic Fingerprint Lookup") PLUGIN_DESC = _("Looks up song metadata through acoustic fingerprinting.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP plugin_handles = each_song(is_finite, is_writable) def plugin_songs(self, songs): from .search import SearchWindow window = SearchWindow(songs, title=self.PLUGIN_NAME) window.show() # plugin_done checks for metadata changes and opens the write dialog window.connect("destroy", self.__plugin_done) def __plugin_done(self, *args): self.plugin_finish() class AcoustidSubmit(SongsMenuPlugin): PLUGIN_ID = "AcoustidSubmit" PLUGIN_NAME = _("Submit Acoustic Fingerprints") PLUGIN_DESC = _("Generates acoustic fingerprints using chromaprint " "and submits them to acoustid.org.") PLUGIN_ICON = Icons.NETWORK_WORKGROUP plugin_handles = each_song(is_finite, is_writable) def plugin_songs(self, songs): if not get_api_key(): ErrorMessage(self, _("API Key Missing"), _("You have to specify an acoustid.org API key in the plugin " "preferences before you can submit fingerprints.")).run() else: FingerprintDialog(songs) @classmethod def PluginPreferences(self, win): box = Gtk.VBox(spacing=12) # api key section def key_changed(entry, *args): config.set("plugins", "fingerprint_acoustid_api_key", entry.get_text()) button = Button(_("Request API key"), Icons.NETWORK_WORKGROUP) button.connect("clicked", lambda s: util.website("https://acoustid.org/api-key")) key_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(get_api_key()) entry.connect("changed", key_changed) label = Gtk.Label(label=_("API _key:")) label.set_use_underline(True) label.set_mnemonic_widget(entry) key_box.pack_start(label, False, True, 0) key_box.pack_start(entry, True, True, 0) key_box.pack_start(button, False, True, 0) box.pack_start(Frame(_("AcoustID Web Service"), child=key_box), True, True, 0) return box ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/acoustid.py�������������������������������������0000644�0001750�0001750�00000026014�14310167056�023533� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import json import collections import threading import gzip from xml.dom.minidom import parseString from io import BytesIO from urllib.parse import urlencode import queue from gi.repository import GLib from quodlibet.util import print_w from quodlibet.util.urllib import urlopen, Request from .util import get_api_key, GateKeeper APP_KEY = "C6IduH7D" gatekeeper = GateKeeper(requests_per_sec=3) class AcoustidSubmissionThread(threading.Thread): URL = "https://api.acoustid.org/v2/submit" SONGS_PER_SUBMISSION = 50 TIMEOUT = 10.0 def __init__(self, results, progress_cb, done_cb): super().__init__() self.__callback = done_cb self.__results = results self.__stopped = False self.__progress_cb = progress_cb self.__done = 0 self.start() def __idle(self, func, *args, **kwargs): def delayed(): if self.__stopped: return func(*args, **kwargs) GLib.idle_add(delayed) def __send(self, urldata): if self.__stopped: return gatekeeper.wait() self.__done += len(urldata) basedata = urlencode({ "format": "xml", "client": APP_KEY, "user": get_api_key(), }) urldata = "&".join([basedata] + list(map(urlencode, urldata))) obj = BytesIO() gzip.GzipFile(fileobj=obj, mode="wb").write(urldata.encode()) urldata = obj.getvalue() headers = { "Content-Encoding": "gzip", "Content-type": "application/x-www-form-urlencoded" } req = Request(self.URL, urldata, headers) error = None try: response = urlopen(req, timeout=self.TIMEOUT) except EnvironmentError as e: error = "urllib error: " + str(e) else: xml = response.read() try: dom = parseString(xml) except: error = "xml error" else: status = dom.getElementsByTagName("status") if not status or not status[0].childNodes or not \ status[0].childNodes[0].nodeValue == "ok": error = "response status error" if error: print_w("[fingerprint] Submission failed: " + error) # emit progress self.__idle(self.__progress_cb, float(self.__done) / len(self.__results)) def run(self): urldata = [] for i, result in enumerate(self.__results): song = result.song track = { "duration": int(round(result.length)), "fingerprint": result.chromaprint, "bitrate": song("~#bitrate"), "fileformat": song("~format"), "mbid": song("musicbrainz_trackid"), "track": song("title"), "artist": song.list("artist"), "album": song("album"), "albumartist": song("albumartist"), "year": song("~year"), "trackno": song("~#track"), "discno": song("~#disc"), } tuples = [] for key, value in track.items(): # this also dismisses 0... which should be ok here. if not value: continue # the postfixes don't have to start at a specific point, # they just need to be different and numbers key += ".%d" % i if isinstance(value, list): for val in value: tuples.append((key, val)) else: tuples.append((key, value)) urldata.append(tuples) if len(urldata) >= self.SONGS_PER_SUBMISSION: self.__send(urldata) urldata = [] if self.__stopped: return if urldata: self.__send(urldata) self.__idle(self.__callback) def stop(self): self.__stopped = True class LookupResult: def __init__(self, fresult, releases, error): self.fresult = fresult self.releases = releases self.error = error @property def song(self): return self.fresult.song Release = collections.namedtuple( "Release", ["id", "score", "sources", "all_sources", "medium_count", "tags"]) def parse_acoustid_response(json_data): """Get all possible tag combinations including the release ID and score. The idea is that for multiple songs the variant for each wins where the release ID is present for more songs and if equal (one song for example) the score wins. Needs meta=releases+recordings+tracks responses. """ VARIOUS_ARTISTS_ARTISTID = "89ad4ac3-39f7-470e-963a-56509c546377" releases = [] for res in json_data.get("results", []): score = res["score"] all_sources = 0 recordings = [] for rec in res.get("recordings", []): sources = rec["sources"] all_sources += sources rec_id = rec["id"] artists = [a["name"] for a in rec.get("artists", [])] artist_ids = [a["id"] for a in rec.get("artists", [])] for release in rec.get("releases", []): # release id_ = release["id"] date = release.get("date", {}) album = release.get("title", "") album_id = release["id"] parts = [date.get(k) for k in ["year", "month", "day"]] date = "-".join([u"%02d" % p for p in parts if p is not None]) albumartists = [] albumartist_ids = [] for artist in release.get("artists", []): if artist["id"] != VARIOUS_ARTISTS_ARTISTID: albumartists.append(artist["name"]) albumartist_ids.append(artist["id"]) discs = release.get("medium_count", 1) # meadium medium = release["mediums"][0] disc = medium.get("position", 0) tracks = medium.get("track_count", 1) # track track_info = medium["tracks"][0] track_id = track_info["id"] track = track_info.get("position", 0) title = track_info.get("title", "") if disc and discs > 1: discnumber = u"%d/%d" % (disc, discs) else: discnumber = u"" if track and tracks > 1: tracknumber = u"%d/%d" % (track, tracks) else: tracknumber = u"" tags = { "title": title, "artist": "\n".join(artists), "albumartist": "\n".join(albumartists), "date": date, "discnumber": discnumber, "tracknumber": tracknumber, "album": album, } mb = { "musicbrainz_releasetrackid": track_id, "musicbrainz_trackid": rec_id, "musicbrainz_albumid": album_id, "musicbrainz_albumartistid": "\n".join(albumartist_ids), "musicbrainz_artistid": "\n".join(artist_ids), } # not that useful, ignore for now del mb["musicbrainz_releasetrackid"] tags.update(mb) recordings.append([id_, score, sources, 0, discs, tags]) for rec in recordings: rec[3] = all_sources releases.append(Release(*rec)) return releases class AcoustidLookupThread(threading.Thread): URL = "https://api.acoustid.org/v2/lookup" MAX_SONGS_PER_SUBMISSION = 5 TIMEOUT = 10.0 def __init__(self, progress_cb): super().__init__() self.__progress_cb = progress_cb self.__queue = queue.Queue() self.__stopped = False self.start() def put(self, result): """Queue a FingerPrintResult""" self.__queue.put(result) def __idle(self, func, *args, **kwargs): def delayed(): if self.__stopped: return func(*args, **kwargs) GLib.idle_add(delayed) def __process(self, results): req_data = [] req_data.append(urlencode({ "format": "json", "client": APP_KEY, "batch": "1", })) for i, result in enumerate(results): postfix = ".%d" % i req_data.append(urlencode({ "duration" + postfix: str(int(round(result.length))), "fingerprint" + postfix: result.chromaprint, })) req_data.append("meta=releases+recordings+tracks+sources") urldata = "&".join(req_data) obj = BytesIO() gzip.GzipFile(fileobj=obj, mode="wb").write(urldata.encode()) urldata = obj.getvalue() headers = { "Content-Encoding": "gzip", "Content-type": "application/x-www-form-urlencoded" } req = Request(self.URL, urldata, headers) releases = {} error = "" try: response = urlopen(req, timeout=self.TIMEOUT) except EnvironmentError as e: error = "urllib error: " + str(e) else: try: data = response.read() data = json.loads(data.decode()) except ValueError as e: error = str(e) else: if data["status"] == "ok": for result_data in data.get("fingerprints", []): if "index" not in result_data: continue index = result_data["index"] releases[index] = parse_acoustid_response(result_data) for i, result in enumerate(results): yield LookupResult(result, releases.get(i, []), error) def run(self): while 1: gatekeeper.wait() results = [] results.append(self.__queue.get()) while len(results) < self.MAX_SONGS_PER_SUBMISSION: # wait a bit to reduce overall request count. timeout = 0.5 / len(results) try: results.append(self.__queue.get(timeout=timeout)) except queue.Empty: break if self.__stopped: return for lookup_result in self.__process(results): self.__idle(self.__progress_cb, lookup_result) self.__queue.task_done() def stop(self): self.__stopped = True self.__queue.put(None) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/analyze.py��������������������������������������0000644�0001750�0001750�00000014662�14310167056�023371� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013,2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import multiprocessing from gi.repository import Gst, GObject from quodlibet.util import connect_obj class FingerPrintResult: def __init__(self, song, chromaprint, length): self.song = song self.chromaprint = chromaprint # in seconds self.length = length class FingerPrintPipeline: def __init__(self): super().__init__() self._song = None self._setup_pipe() def _finish(self, result, error): song = self._song callback = self._callback self._reset() callback(self, song, result, error) def _setup_pipe(self): # pipeline self._pipe = pipe = Gst.Pipeline() # decode part self._filesrc = filesrc = Gst.ElementFactory.make("filesrc", None) pipe.add(filesrc) decode = Gst.ElementFactory.make("decodebin", None) pipe.add(decode) Gst.Element.link(filesrc, decode) # convert to right format convert = Gst.ElementFactory.make("audioconvert", None) resample = Gst.ElementFactory.make("audioresample", None) pipe.add(convert) pipe.add(resample) Gst.Element.link(convert, resample) def new_decoded_pad(convert, pad, *args): pad.link(convert.get_static_pad("sink")) # decodebin creates pad, we link it self._dec = decode self._dec_id = connect_obj(decode, "pad-added", new_decoded_pad, convert) chroma = Gst.ElementFactory.make("chromaprint", None) fake = Gst.ElementFactory.make("fakesink", None) pipe.add(chroma) pipe.add(fake) Gst.Element.link(resample, chroma) Gst.Element.link(chroma, fake) # bus self._bus = bus = pipe.get_bus() self._bus_id = bus.connect("message", self._bus_message) bus.add_signal_watch() def start(self, song, callback): """Start processing a new song""" assert self.is_idle() self._song = song self._callback = callback # use mutagen one, but replace if gstreamer gives us a duration self._length = song("~#length") self._filesrc.set_property("location", song["~filename"]) self._pipe.set_state(Gst.State.PLAYING) def _reset(self): """Reset, so start() can be called again""" if self.is_idle(): return self._pipe.set_state(Gst.State.NULL) self._song = None self._callback = None def stop(self): """Abort processing. Can be called multiple times. After this returns the pipeline isn't usable anymore. """ self._reset() if not self._pipe: return self._bus.remove_signal_watch() self._bus.disconnect(self._bus_id) self._dec.disconnect(self._dec_id) self._dec = None self._filesrc = None self._bus = None self._pipe = None def is_idle(self): """If start() can be called""" return not self._song def _bus_message(self, bus, message): error = None if message.type == Gst.MessageType.TAG: tags = message.parse_tag() ok, value = tags.get_string("chromaprint-fingerprint") if ok: res = FingerPrintResult(self._song, value, self._length) self._finish(res, None) elif message.type == Gst.MessageType.ASYNC_DONE: # GStreamer probably knows song durations better than we do. ok, d = self._pipe.query_duration(Gst.Format.TIME) if ok: self._length = float(d) / Gst.SECOND elif message.type == Gst.MessageType.EOS: error = "EOS but no fingerprint" elif message.type == Gst.MessageType.ERROR: error = str(message.parse_error()[0]) if error: self._finish(None, error) class FingerPrintPool(GObject.GObject): __gsignals__ = { # FingerPrintResult "fingerprint-done": ( GObject.SignalFlags.RUN_LAST, None, (object,)), # AudioFile "fingerprint-started": ( GObject.SignalFlags.RUN_LAST, None, (object,)), # AudioFile, str "fingerprint-error": ( GObject.SignalFlags.RUN_LAST, None, (object, object)), } def __init__(self, max_workers=None): super().__init__() if max_workers is None: max_workers = int(multiprocessing.cpu_count() * 1.5) self._max_workers = max_workers self._idle = set() self._workers = set() self._queue = [] def _get_worker(self): """An idle FingerPrintPipeline or None""" for worker in self._workers: if worker in self._idle: self._idle.discard(worker) break else: worker = None if len(self._workers) < self._max_workers: worker = FingerPrintPipeline() self._workers.add(worker) if worker: assert worker.is_idle() return worker def _start_song(self, worker, song): assert worker.is_idle() worker.start(song, self._callback) self.emit("fingerprint-started", song) def push(self, song): """Add a new song to the queue""" worker = self._get_worker() if worker: self._start_song(worker, song) else: self._queue.append(song) def stop(self): """Stop everything. callback will not be called after this. Can be called multiple times. """ for worker in self._workers: worker.stop() self._workers.clear() self._idle.clear() def _callback(self, worker, song, result, error): self._idle.add(worker) if result: self.emit("fingerprint-done", result) else: self.emit("fingerprint-error", song, error) if self._queue: song = self._queue.pop(0) worker = self._get_worker() assert worker self._start_song(worker, song) elif len(self._idle) == len(self._workers): # all done, all idle, kill em self.stop() ������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/search.py���������������������������������������0000644�0001750�0001750�00000034732�14267565021�023200� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from contextlib import contextmanager from gi.repository import Gtk, Pango, Gdk from .analyze import FingerPrintPool from .acoustid import AcoustidLookupThread from .util import get_write_mb_tags, get_group_by_dir from quodlibet import _ from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.views import AllTreeView from quodlibet.qltk.window import Window from quodlibet.qltk import Button, Icons from quodlibet import util from quodlibet.util import print_w from quodlibet.qltk.ccb import ConfigCheckButton class Status: QUEUED = 0 ANALYZING = 1 LOOKUP = 2 DONE = 3 ERROR = 4 UNKNOWN = 5 @classmethod def to_string(cls, value): if value == cls.QUEUED: return _("Queued") elif value == cls.ANALYZING: return _("Analyzing") elif value == cls.LOOKUP: return _("Lookup") elif value == cls.DONE: return _("Done") elif value == cls.ERROR: return _("Error") elif value == cls.UNKNOWN: return _("Unknown") class SearchEntry: def __init__(self, song): self.song = song self.status = Status.QUEUED self.result = None self.active_release = 0 self._write = True def toggle_write(self): if self.status == Status.DONE and self.release: self._write ^= True @property def can_write(self): return self.status == Status.DONE and self.release and self._write def apply_tags(self, write_musicbrainz=True, write_album=True): """Add the tags of the active release to the song""" non_album_tags = [ "artist", "title", "musicbrainz_trackid", "musicbrainz_artistid" ] if not self.can_write: return # To reduce chaotic results with half tagged albums, delete # all tags for which we could have written values, but don't # or the value would be empty for key, value in self.release.tags.items(): if not write_musicbrainz and key.startswith("musicbrainz_"): value = u"" if not write_album and key not in non_album_tags: value = u"" if not value: self.song.pop(key, None) else: self.song[key] = value @property def releases(self): if self.result: return self.result.releases return [] @property def release(self): result = self.result if not result: return if result.releases: return result.releases[self.active_release] class ResultView(AllTreeView): def __init__(self): super().__init__() self._release_ids = {} render = Gtk.CellRendererPixbuf() column = Gtk.TreeViewColumn(_("Write"), render) def cell_data(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property('icon-name', Icons.EDIT) cell.set_sensitive(entry.can_write) column.set_cell_data_func(render, cell_data) column.set_expand(False) column.set_min_width(60) self.append_column(column) self.connect('button-press-event', self.__button_press, column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn(util.tag("~basename"), render) def cell_data(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property('text', entry.song("~basename")) column.set_cell_data_func(render, cell_data) column.set_expand(True) self.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn(_("Status"), render) def cell_data(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property('text', Status.to_string(entry.status)) column.set_cell_data_func(render, cell_data) column.set_expand(False) column.set_fixed_width(100) self.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) # Translators: album release ID column = Gtk.TreeViewColumn(_("Release"), render) self._release_column = column def cell_data(column, cell, model, iter_, data): entry = model.get_value(iter_) release = entry.release if not release: cell.set_property("text", "-") else: id_ = self.get_release_id(release) cell.set_property("text", str(id_)) column.set_cell_data_func(render, cell_data) column.set_expand(False) self.append_column(column) for tag in ["tracknumber", "artist", "title", "album"]: render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn(util.tag(tag), render) def cell_data2(column, cell, model, iter_, data, tag=tag): entry = model.get_value(iter_) release = entry.release if not release: cell.set_property("text", "-") else: value = release.tags.get(tag, "-") value = ", ".join(value.split("\n")) cell.set_property("text", value) column.set_cell_data_func(render, cell_data2) self.append_column(column) if tag == "tracknumber": self._track_column = column column.set_expand(False) column.set_fixed_width(80) else: column.set_expand(True) for column in self.get_columns(): column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_resizable(True) if column.get_min_width() < 50: column.set_min_width(50) self.set_fixed_height_mode(True) def __button_press(self, view, event, edit_column): x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: return False # header clicks go to the first cell otherwise if event.window is not view.get_bin_window(): return False if event.button == Gdk.BUTTON_PRIMARY and \ event.type == Gdk.EventType.BUTTON_PRESS and \ col == edit_column: model = view.get_model() row = model[path] entry = row[0] entry.toggle_write() model.row_changed(row.path, row.iter) return True return False def set_album_visible(self, value): self._release_column.set_visible(value) self._track_column.set_visible(value) def get_release_id(self, release): return self._release_ids.setdefault( release.id, len(self._release_ids) + 1) def score_release(release): return (float(release.sources) / release.all_sources) * release.score class SearchWindow(Window): def __init__(self, songs, title=None): super().__init__( default_width=800, default_height=400, border_width=12, title=title) self._thread = AcoustidLookupThread(self.__lookup_cb) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) model = ObjectStore() self.view = view = ResultView() view.set_model(model) self.model = model self._iter_map = {} for song in songs: iter_ = self.model.append([SearchEntry(song)]) self._iter_map[song] = iter_ sw.add(view) self.pool = pool = FingerPrintPool() pool.connect('fingerprint-done', self.__fp_done_cb) pool.connect('fingerprint-error', self.__fp_error_cb) pool.connect('fingerprint-started', self.__fp_started_cb) for song in songs: pool.push(song) outer_box = Gtk.VBox(spacing=12) bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.set_spacing(6) self.__save = save = Button(_("_Save"), Icons.DOCUMENT_SAVE) save.connect("clicked", self.__on_save) save.set_sensitive(False) cancel = Button(_("_Cancel")) cancel.connect("clicked", lambda *x: self.destroy()) bbox.pack_start(save, True, True, 0) bbox.pack_start(cancel, True, True, 0) inner_box = Gtk.VBox(spacing=6) inner_box.pack_start(sw, True, True, 0) ccb = ConfigCheckButton( _("Write MusicBrainz tags"), "plugins", "fingerprint_write_mb_tags") ccb.set_active(get_write_mb_tags()) inner_box.pack_start(ccb, False, True, 0) ccb = ConfigCheckButton( _("Group by directory"), "plugins", "fingerprint_group_by_dir") ccb.set_active(get_group_by_dir()) ccb.connect("toggled", self.__group_toggled) self._group_ccb = ccb outer_box.pack_start(inner_box, True, True, 0) bottom_box = Gtk.HBox(spacing=12) mode_button = Gtk.ToggleButton(label=_("Album Mode")) mode_button.set_tooltip_text( _("Write album related tags and try to " "reduce the number of different album releases")) mode_button.set_active(True) mode_button.connect("toggled", self.__mode_toggle) bottom_box.pack_start(mode_button, False, True, 0) bottom_box.pack_start(self._group_ccb, False, True, 0) bottom_box.pack_start(bbox, True, True, 0) outer_box.pack_start(bottom_box, False, True, 0) outer_box.show_all() self.add(outer_box) self.__album_mode = True self.__group_by_dir = True self._release_scores = {} self._directory_scores = {} self.__done = 0 self.connect("destroy", self.__destroy) def __group_toggled(self, button): self.__group_by_dir = button.get_active() self.__update_active_releases() def __mode_toggle(self, button): self.__album_mode = button.get_active() self._group_ccb.set_sensitive(self.__album_mode) self.view.set_album_visible(self.__album_mode) self.__update_active_releases() def __destroy(self, *args): self.pool.stop() self.pool = None self._thread.stop() self._thread = None def __on_save(self, *args): write_mb = get_write_mb_tags() write_album = self.__album_mode for row in self.model: row[0].apply_tags(write_mb, write_album) # the plugin wrapper will handle the rest self.destroy() @contextmanager def __update_row(self, song): iter_ = self._iter_map[song] row = self.model[iter_] yield row[0] self.model.row_changed(row.path, row.iter) def __inc_done(self): self.__done += 1 if self.__done == len(self._iter_map): self.__save.set_sensitive(True) def __update_active_releases(self): """Go through all songs and recalculate the best release""" def sort_key(entry, r): # good if there are many other songs that could be in the # same release and this release is likely as well. # Also sort by id to have a winner in case of a tie. score = score_release(r) if self.__album_mode: if self.__group_by_dir: song = entry.song scores = self._directory_scores[song("~dirname")] else: scores = self._release_scores score = (scores[r.id], score) return (score, r.id) for row in self.model: entry = row[0] if not entry.releases: continue active_release = entry.active_release best_release = sorted( entry.releases, key=lambda r: sort_key(entry, r))[-1] entry.active_release = entry.releases.index(best_release) if entry.active_release != active_release: self.model.row_changed(row.path, row.iter) def __lookup_cb(self, lresult): with self.__update_row(lresult.song) as entry: entry.status = Status.DONE entry.result = lresult # count how many times each release ID is present and weight by the # score for release in lresult.releases: id_ = release.id # to prevent favoring releases which are a superset of # the release we actually want (say 8 CD box containing # every song of an artist), try to reduce the medium count. score = score_release(release) / release.medium_count self._release_scores.setdefault(id_, 0) self._release_scores[id_] += score # do the same again but group by directory dir_ = lresult.song("~dirname") release_scores = self._directory_scores.setdefault(dir_, {}) release_scores.setdefault(id_, 0) release_scores[id_] += score # update display if lresult.releases: self.__update_active_releases() elif lresult.error: entry.status = Status.ERROR # we don't expose in the UI, so at least print it print_w(lresult.error) else: entry.status = Status.UNKNOWN self.__inc_done() def __fp_done_cb(self, pool, result): self._thread.put(result) with self.__update_row(result.song) as entry: entry.status = Status.LOOKUP def __fp_error_cb(self, pool, song, error_msg): print_w(error_msg) with self.__update_row(song) as entry: entry.status = Status.ERROR self.__inc_done() def __fp_started_cb(self, pool, song): with self.__update_row(song) as entry: entry.status = Status.ANALYZING ��������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/submit.py���������������������������������������0000644�0001750�0001750�00000015060�14327505043�023222� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013 Christoph Reiter # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango, GLib from quodlibet import _, util from quodlibet.qltk import Button, Window from quodlibet.util import connect_obj, print_w from .acoustid import AcoustidSubmissionThread from .analyze import FingerPrintPool def get_stats(results): got_mbid = got_meta = 0 for result in results: song = result.song got_mbid += bool(song("musicbrainz_trackid")) got_meta += bool( song("artist") and song.get("title") and song("album")) return got_mbid, got_meta def can_submit(result): got_mbid, got_meta = get_stats([result]) return bool(got_mbid or got_meta) class FingerprintDialog(Window): def __init__(self, songs): super().__init__() self.set_border_width(12) self.set_title(_("Submit Acoustic Fingerprints")) self.set_default_size(450, 0) outer_box = Gtk.VBox(spacing=12) box = Gtk.VBox(spacing=6) self.__label = label = Gtk.Label() label.set_markup(util.bold(_("Generating fingerprints:"))) label.set_alignment(0, 0.5) box.pack_start(label, False, True, 0) self.__bar = bar = Gtk.ProgressBar() self.__set_fraction(0) box.pack_start(bar, False, True, 0) self.__label_song = label_song = Gtk.Label() label_song.set_alignment(0, 0.5) label_song.set_ellipsize(Pango.EllipsizeMode.MIDDLE) box.pack_start(label_song, False, True, 0) self.__stats = stats = Gtk.Label() stats.set_alignment(0, 0.5) stats.set_line_wrap(True) stats.set_size_request(426, -1) expand = Gtk.Expander.new_with_mnemonic(_("_Details")) expand.set_resize_toplevel(True) expand.add(stats) def expand_cb(expand, *args): self.resize(self.get_size()[0], 1) stats.connect("unmap", expand_cb) box.pack_start(expand, False, False, 0) self.__fp_results = {} self.__fp_done = 0 self.__songs = songs self.__musicdns_thread = None self.__acoustid_thread = None self.__update_stats() pool = FingerPrintPool() bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.set_spacing(6) self.__submit = submit = Button(_("_Submit")) submit.set_sensitive(False) submit.connect('clicked', self.__submit_cb) cancel = Button(_("_Cancel")) connect_obj(cancel, 'clicked', self.__cancel_cb, pool) bbox.pack_start(cancel, True, True, 0) bbox.pack_start(submit, True, True, 0) outer_box.pack_start(box, True, True, 0) outer_box.pack_start(bbox, False, True, 0) pool.connect('fingerprint-done', self.__fp_done_cb) pool.connect('fingerprint-error', self.__fp_error_cb) pool.connect('fingerprint-started', self.__fp_started_cb) for song in songs: pool.push(song) connect_obj(self, 'delete-event', self.__cancel_cb, pool) self.add(outer_box) self.show_all() def __update_stats(self): all_ = len(self.__songs) results = self.__fp_results.values() to_send = len(list(filter(can_submit, results))) valid_fp = len(results) got_mbid, got_meta = get_stats(results) text = _("Songs either need a <i><b>musicbrainz_trackid</b></i>, " "or <i><b>artist</b></i> / " "<i><b>title</b></i> / <i><b>album</b></i> tags to get submitted.") text += "\n\n" + util.italic(_("Fingerprints:")) text += " %d/%d" % (valid_fp, all_) text += "\n" + util.italic(_("Songs with MBIDs:")) text += " %d/%d" % (got_mbid, all_) text += "\n" + util.italic(_("Songs with sufficient tags:")) text += " %d/%d" % (got_meta, all_) text += "\n" + util.italic(_("Songs to submit:")) text += " %d/%d" % (to_send, all_) self.__stats.set_markup(text) def __set_fraction(self, progress): self.__bar.set_fraction(progress) self.__bar.set_text("%d%%" % round(progress * 100)) def __inc_fp_fraction(self): self.__fp_done += 1 frac = self.__fp_done / float(len(self.__songs)) self.__set_fraction(frac) if self.__fp_done == len(self.__songs): self.__submit.set_sensitive(True) self.__show_final_stats() def __fp_started_cb(self, pool, song): # increase by an amount smaller than one song, so that the user can # see some progress from the beginning. self.__set_fraction(0.5 / len(self.__songs) + self.__bar.get_fraction()) self.__label_song.set_text(song("~filename")) def __fp_done_cb(self, pool, result): self.__fp_results[result.song] = result self.__inc_fp_fraction() self.__update_stats() def __fp_error_cb(self, pool, song, error): print_w("[fingerprint] " + error) self.__inc_fp_fraction() self.__update_stats() def __show_final_stats(self): all_ = len(self.__songs) results = self.__fp_results.values() to_send = len(list(filter(can_submit, results))) self.__label_song.set_text( _("Done. %(to-send)d/%(all)d songs to submit.") % { "to-send": to_send, "all": all_}) def __cancel_cb(self, pool, *args): self.destroy() def idle_cancel(): pool.stop() if self.__acoustid_thread: self.__acoustid_thread.stop() # pool.stop can block a short time because the CV might be locked # during starting the pipeline -> idle_add -> no GUI blocking GLib.idle_add(idle_cancel) def __submit_cb(self, *args): self.__submit.set_sensitive(False) self.__label.set_markup(util.bold(_("Submitting fingerprints:"))) self.__set_fraction(0) self.__acoustid_thread = AcoustidSubmissionThread( list(filter(can_submit, self.__fp_results.values())), self.__acoustid_update, self.__acoustid_done) def __acoustid_update(self, progress): self.__set_fraction(progress) self.__label_song.set_text(_("Submitting…")) def __acoustid_done(self): self.__acoustid_thread.join() self.__set_fraction(1.0) GLib.timeout_add(500, self.destroy) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/fingerprint/util.py�����������������������������������������0000664�0001750�0001750�00000002260�14035600052�022664� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013,2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import time import threading from quodlibet import config def get_api_key(): """The user API key for submissions""" return config.get("plugins", "fingerprint_acoustid_api_key", "") def get_write_mb_tags(): return config.getboolean("plugins", "fingerprint_write_mb_tags", False) def get_group_by_dir(): return config.getboolean("plugins", "fingerprint_group_by_dir", True) class GateKeeper: def __init__(self, requests_per_sec): self._period = 1 / float(requests_per_sec) self._last = 0 self._lock = threading.Lock() def wait(self): """Block until a new request can be made.""" while 1: with self._lock: current = time.time() if abs(current - self._last) >= self._period: self._last = current break time.sleep(self._period / 10) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/forcewrite.py�����������������������������������������������0000664�0001750�0001750�00000001565�14035600052�021540� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import any_song, is_writable class ForceWrite(SongsMenuPlugin): PLUGIN_ID = "Force Write" PLUGIN_NAME = _("Update Tags in Files") PLUGIN_DESC = _("Update modified tags in files. " "This will ensure play counts and ratings are up to date.") PLUGIN_ICON = Icons.DOCUMENT_SAVE plugin_handles = any_song(is_writable) def plugin_song(self, song): song._needs_write = True �������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/ext/songsmenu/html.py�����������������������������������������������������0000664�0001750�0001750�00000004233�14037102221�020323� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Eduardo Gonzalez # 2020 Roneel Valambhia # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.qltk import Icons from quodlibet.util import tag, escape from quodlibet.qltk.songlist import get_columns from quodlibet.qltk.chooser import choose_target_file from quodlibet.plugins.songsmenu import SongsMenuPlugin HTML = '''<html> <head><title>Quod Libet Playlist

My Quod Libet Playlist


%(headers)s %(songs)s
''' def to_html(songs): cols = get_columns() cols_s = "" for col in cols: cols_s += '%s' % tag(col) songs_s = "" for song in songs: s = '' for col in cols: col = {"~#rating": "~rating", "~#length": "~length"}.get( col, col) s += '\n%s' % ( escape(str(song.comma(col))) or ' ') s += '' songs_s += s return HTML % {'headers': cols_s, 'songs': songs_s} class ExportToHTML(SongsMenuPlugin): PLUGIN_ID = "Export to HTML" PLUGIN_NAME = _("Export to HTML") PLUGIN_DESC = _("Exports the selected song list to HTML.") REQUIRES_ACTION = True PLUGIN_ICON = Icons.TEXT_HTML def plugin_songs(self, songs): if not songs: return target = choose_target_file( self.plugin_window, _("Export to HTML"), _("_Save")) if target is not None: with open(target, "wb") as f: f.write(to_html(songs).encode("utf-8")) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/ifp.py0000644000175000017500000000456014327505043020151 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from quodlibet import _ from quodlibet import util, qltk from quodlibet.plugins.songshelpers import each_song, is_a_file from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons from quodlibet.qltk.wlw import WaitLoadWindow class IFPUpload(SongsMenuPlugin): PLUGIN_ID = "Send to iFP" PLUGIN_NAME = _("Send to iFP") PLUGIN_DESC = _("Uploads songs to an iRiver iFP device.") PLUGIN_ICON = Icons.MULTIMEDIA_PLAYER plugin_handles = each_song(is_a_file) def plugin_songs(self, songs): if os.system("ifp typestring"): qltk.ErrorMessage( None, _("No iFP device found"), _("Unable to contact your iFP device. Check " "that the device is powered on and plugged " "in, and that you have ifp-line " "(http://ifp-driver.sf.net) installed.")).run() return True self.__madedir = [] w = WaitLoadWindow( None, len(songs), _("Uploading %(current)d/%(total)d")) w.show() for i, song in enumerate(songs): if self.__upload(song) or w.step(): w.destroy() return True else: w.destroy() def __upload(self, song): filename = song["~filename"] basename = song("~basename") dirname = os.path.basename(os.path.dirname(filename)) target = os.path.join(dirname, basename) # Avoid spurious calls to ifp mkdir; this can take a long time # on a noisy USB line. if dirname not in self.__madedir: os.system("ifp mkdir %r> /dev/null 2>/dev/null" % dirname) self.__madedir.append(dirname) if os.system("ifp upload %r %r > /dev/null" % (filename, target)): tmpl = _("Unable to upload %s." "The device may be out of space, or turned off.") qltk.ErrorMessage(None, _("Error uploading"), tmpl % util.bold(filename), escape_desc=False).run() return True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1677326785.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py0000644000175000017500000006540714376374701027401 0ustar00nicknick# Copyright 2021 Joschua Gandert # 2023 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import datetime import os.path import json import uuid from pathlib import Path from gi.repository import Gtk from senf import path2fsn from typing import NamedTuple, List, Callable, Any, MutableMapping, Set, Union from quodlibet.plugins import PluginConfig, BoolConfProp, FloatConfProp from quodlibet.qltk.matchdialog import ColumnSpec, MatchListsDialog from quodlibet.qltk.showfiles import show_files from quodlibet.util.matcher import ObjectListMatcher from quodlibet.formats._audio import MIGRATE, AudioFile from quodlibet.util import connect_obj, print_exc import quodlibet from quodlibet.util.path import (join_path_with_escaped_name_of_legal_length, stem_of_file_name, extension_of_file_name) from quodlibet.util.songwrapper import SongWrapper, check_wrapper_changed from quodlibet import _, app, print_e, qltk, util, print_d from quodlibet.plugins.songshelpers import each_song, is_writable, is_finite from quodlibet.qltk.msg import ErrorMessage, WarningMessage from quodlibet.qltk import Icons, SeparatorMenuItem from quodlibet.plugins.songsmenu import SongsMenuPlugin __all__ = ['ImportExportTagsAndTrackUserDataPlugin'] _PLUGIN_ID = "ImportExportTagsAndTrackUserData" # We use this instead of ~playlists, since we want to store playlists in a list PLAYLISTS_KEY = '//playlists' IDENTIFIER_KEY = '//identifier' FILE_STEM_KEY = '//file_stem' USER_DATA_KEYS = " ".join(MIGRATE | {PLAYLISTS_KEY}) # Could be made configurable in the future, but these likely suffice # "tag1 tag2" will result in only tag1 and tag2 being exported # * means all tags (so tags like 'title' and internal (user data) "tags" like ~#added) # * tag1 tag2 means all except tag1 and tag2 EXPORT_OPTIONS = [(_("Export User Data"), USER_DATA_KEYS), (_("Export Tags"), f"* {USER_DATA_KEYS} {FILE_STEM_KEY}"), (_("Export Tags and User Data"), f"* {FILE_STEM_KEY}"), (_("Export File Stems and User Data"), f"{USER_DATA_KEYS} " f"{FILE_STEM_KEY}"), (_("Export File Stems and Tags"), f"* {USER_DATA_KEYS}"), (_("Export File Stems, Tags and User Data"), "*")] EXPORT_DIR_PATH = Path(quodlibet.get_cache_dir(), 'tags_and_track_user_data') os.makedirs(EXPORT_DIR_PATH, exist_ok=True) EXPORT_EXTENSION = 'json' TAGS_AND_USERDATA_INDEX_FILE_PATH = EXPORT_DIR_PATH / f'index.{EXPORT_EXTENSION}' def move_export_to_used(export_path: Path): used_path = EXPORT_DIR_PATH / 'used' used_path.mkdir(exist_ok=True) export_path.rename(used_path / export_path.name) class AlbumId(NamedTuple): id_value: str title: str artist: str discs: int tracks: int last_directory_parts: str @classmethod def of_song(cls, s: SongWrapper): # We're using the last two parts, since sometimes albums have disc folders # below the folder that's named after the album parts = s('~dirname').rsplit(os.path.sep, maxsplit=2)[-2:] return AlbumId(s.album_key[0], s('albumsort', '') or s('album'), s('albumartistsort', '') or s('albumartist') or s('artist'), s('~#discs', 1), s('~#tracks', 1), os.path.join(*parts)) class TrackId(NamedTuple): """ A TrackId is class that's used to identify and match tracks. In theory, almost all metadata could be useful for that, but some things are far more relevant than others (title vs bpm), and for performance reasons we have to limit it anyway. """ artist: str title: str disc: int discs: int track: int tracks: int file_name: str @classmethod def of_song(cls, s: Union[SongWrapper, AudioFile]): return TrackId(s('artist'), s('title'), s('~#disc', 1), s('~#discs', 1), s('~#track', 1), s('~#tracks', 1), s('~basename')) @property def file_stem(self): return os.path.splitext(self.file_name)[0] @property def track_text(self): if self.tracks <= 1: return str(self.track) return f'{self.track}/{self.tracks}' @property def disc_text(self): if self.discs <= 1: return str(self.disc) return f'{self.disc}/{self.discs}' class Config: _config = PluginConfig(_PLUGIN_ID) need_user_check_if_number_of_albums_differs = BoolConfProp( _config, "need_user_check_if_number_of_albums_differs", True) need_user_check_if_number_of_tracks_differs = BoolConfProp( _config, "need_user_check_if_number_of_tracks_differs", True) max_track_similarity_to_need_user_check = FloatConfProp( _config, "max_track_similarity_to_need_user_check", 0.76) max_album_similarity_to_need_user_check = FloatConfProp( _config, "max_album_similarity_to_need_user_check", 0.80) delete_exports_after_importing = BoolConfProp( _config, "delete_exports_after_importing", True) pretty_print_json = BoolConfProp(_config, "pretty_print_json", False) CONFIG = Config() class ImportExportTagsAndTrackUserDataPlugin(SongsMenuPlugin): PLUGIN_ID = _PLUGIN_ID PLUGIN_NAME = _("Import / Export") PLUGIN_DESC = _("Imports and exports tags and track user data.") PLUGIN_ICON = Icons.EDIT_COPY plugin_handles = each_song(is_finite) _album_id_to_export_path: MutableMapping[AlbumId, Path] def PluginPreferences(self, *args): vbox = Gtk.VBox(spacing=6) def asd_toggled(button, *args): CONFIG.need_user_check_if_number_of_albums_differs = button.get_active() def tsd_toggled(button, *args): CONFIG.need_user_check_if_number_of_tracks_differs = button.get_active() def de_toggled(button, *args): CONFIG.delete_exports_after_importing = button.get_active() def pp_toggled(button, *args): CONFIG.pretty_print_json = button.get_active() def mt_scale_changed(scale): CONFIG.max_track_similarity_to_need_user_check = scale.get_value() def ma_scale_changed(scale): CONFIG.max_album_similarity_to_need_user_check = scale.get_value() info_box = Gtk.VBox(spacing=6) info_frame = qltk.Frame(_("Further information"), child=info_box) vbox.pack_start(info_frame, False, True, 0) meta_markup = util.monospace(", ".join(MIGRATE)) info_text = _("The term 'track user data' includes the playlists in which the " "selected tracks are and the following metadata:\n\n%s\n" "\nBe aware that whatever you chose to export will be imported. " "If you exported the file stems (file names without extension), " "then, on import, the selected files will be renamed.\n\nAfter " "exporting an album you can import the data into another version " "of the album. Order and number of tracks can be different. " "The plugin matches the exported data to the new tracks, even if " "the names of the tracks are slightly different. The automatic " "matching is not always correct, so it is better to not reduce " "the following similarity values too much.") % meta_markup info_lbl = Gtk.Label(label=info_text, use_markup=True, wrap=True) info_box.pack_start(info_lbl, True, True, 0) manual_box = Gtk.VBox(spacing=6) manual_frame = qltk.Frame(_("User interaction on import"), child=manual_box) vbox.pack_start(manual_frame, False, True, 0) tsd = Gtk.CheckButton( label=_("Require confirmation if number of tracks differs")) tsd.set_active(CONFIG.need_user_check_if_number_of_tracks_differs) tsd.connect("toggled", tsd_toggled) manual_box.pack_start(tsd, True, True, 0) asd = Gtk.CheckButton( label=_("Require confirmation if number of albums differs")) asd.set_active(CONFIG.need_user_check_if_number_of_albums_differs) asd.connect("toggled", asd_toggled) manual_box.pack_start(asd, True, True, 0) desc = _("Percentage below which the user will have to manually check and " "optionally change which track is matched with which.") perc_table = Gtk.Table(n_rows=2, n_columns=2) perc_table.set_col_spacings(6) perc_table.set_row_spacings(6) manual_box.pack_start(perc_table, True, True, 0) def format_perc(scale, value): return _("%d %%") % (value * 100) def add_perc_scale_with_label(ratio, col, lbl_text, tooltip_text, on_change): scale = Gtk.HScale(adjustment=Gtk.Adjustment.new(0, 0, 1, 0.01, 0.01, 0)) scale.set_digits(2) scale.set_tooltip_text(tooltip_text) scale.set_value_pos(Gtk.PositionType.RIGHT) scale.set_value(ratio) scale.connect('format-value', format_perc) scale.connect('value-changed', on_change) label = Gtk.Label(label=lbl_text) label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_mnemonic_widget(scale) xoptions = Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK perc_table.attach(label, 0, 1, col, col + 1, xoptions=xoptions) perc_table.attach(scale, 1, 2, col, col + 1) add_perc_scale_with_label(CONFIG.max_track_similarity_to_need_user_check, 0, _("Track similarity:"), desc, mt_scale_changed) add_perc_scale_with_label(CONFIG.max_album_similarity_to_need_user_check, 1, _("Album similarity:"), desc, ma_scale_changed) export_box = Gtk.VBox(spacing=6) export_frame = qltk.Frame(_("Export files"), child=export_box) vbox.pack_start(export_frame, False, True, 0) pp = Gtk.CheckButton(label=_("Write pretty and clear JSON (slower)")) pp.set_active(CONFIG.pretty_print_json) pp.connect("toggled", pp_toggled) export_box.pack_start(pp, True, True, 0) de = Gtk.CheckButton(label=_("Delete export files after they've been imported")) de.set_active(CONFIG.delete_exports_after_importing) de.connect("toggled", de_toggled) export_box.pack_start(de, True, True, 0) return vbox def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._export_collectors = [] self._import_or_export_option_index = None self._album_id_matcher: ObjectListMatcher[AlbumId] = ObjectListMatcher({ # lambda a: a.title: 9, # title is the most reliable lambda a: a.artist: 4.5, # lambda a: a.tracks: 1.2, # lambda a: a.last_directory_parts: 1, # needed in case the album has no tags lambda a: a.discs: 0.8, # multi disc albums sometimes become single disc lambda a: a.id_value: 0.5, # is likely to change unless exact same album }) # We want check similarity afterwards, so it needs be as accurate as possible self._album_id_matcher.should_store_similarity_matrix = True self._album_id_matcher.should_go_through_every_attribute = True self._track_id_matcher: ObjectListMatcher[TrackId] = ObjectListMatcher({ # lambda t: t.title: 8, # lambda t: t.artist: 3.5, # lambda t: t.track: 1.2, # lambda t: t.file_stem: 1, # needed in case the track has no tags lambda t: t.disc: 0.8, # }) self._track_id_matcher.should_store_similarity_matrix = True self._album_id_matcher.should_go_through_every_attribute = True self._album_id_to_export_path = {} submenu = Gtk.Menu() self._init_collectors_and_menu(submenu) if submenu.get_children(): self.set_submenu(submenu) else: self.set_sensitive(False) def _init_collectors_and_menu(self, submenu): import_item = Gtk.MenuItem(label=_("Import")) connect_obj(import_item, 'activate', self.__set_import_export_option_index, -1) submenu.append(import_item) submenu.append(SeparatorMenuItem()) for idx, (name, query) in enumerate(EXPORT_OPTIONS): collector = track_data_collector_for(query) self._export_collectors.append(collector) item = Gtk.MenuItem(label=name) connect_obj(item, 'activate', self.__set_import_export_option_index, idx) submenu.append(item) submenu.append(SeparatorMenuItem()) open_dir_item = Gtk.MenuItem(label=_("Open Export Directory")) def open_export_dir(_): show_files(path2fsn(EXPORT_DIR_PATH), [path2fsn(TAGS_AND_USERDATA_INDEX_FILE_PATH.name)]) connect_obj(open_dir_item, 'activate', open_export_dir, None) submenu.append(open_dir_item) def __set_import_export_option_index(self, index): self._import_or_export_option_index = index def _error_msg(self, message): title = _("Error in %s") % self.PLUGIN_NAME ErrorMessage(app.window, title, message).run() def plugin_albums(self, albums): index = self._import_or_export_option_index if index is None or index >= len(self._export_collectors): return if index < 0: self.import_data_to_albums(albums) else: collect_data = self._export_collectors[index] self.export_albums(albums, collect_data) self._rewrite_index() self._import_or_export_option_index = None def import_data_to_albums(self, albums): if not self._try_load_exports(): return for exp_album_id, songs in self._iter_export_album_id_matched_to_songs(albums): if exp_album_id is not None: self.import_data(exp_album_id, songs) def _iter_export_album_id_matched_to_songs(self, albums): album_ids = [AlbumId.of_song(songs[0]) for songs in albums] exp_album_ids = list(self._album_id_to_export_path.keys()) exp_indices = self._album_id_matcher.get_indices(album_ids, exp_album_ids) size_differs = len(exp_album_ids) != len(exp_album_ids) need_check = CONFIG.need_user_check_if_number_of_albums_differs and size_differs need_check = need_check or self._does_match_need_manual_check( self._album_id_matcher, exp_indices, CONFIG.max_album_similarity_to_need_user_check) if need_check: columns = [ # ColumnSpec(_('Discs'), lambda a: str(a.discs), False), ColumnSpec(_('Tracks'), lambda a: str(a.tracks), False), ColumnSpec(_('Title'), lambda a: a.title, True), ColumnSpec(_('Artist(s)'), lambda a: a.artist, True), ColumnSpec(_('End of path'), lambda a: a.last_directory_parts, True), # ] prompt = MatchListsDialog(album_ids, exp_album_ids, exp_indices, columns, _("Match Albums"), _("Continue"), id_for_window_tracking=self.PLUGIN_ID) exp_indices = prompt.run() for exp_idx, songs in zip(exp_indices, albums): if exp_idx is not None: yield exp_album_ids[exp_idx], songs def _try_load_exports(self) -> bool: """:return: Whether we could load the exports""" index_path = TAGS_AND_USERDATA_INDEX_FILE_PATH if not index_path.exists(): self._warning_nothing_to_import() return False try: with index_path.open(encoding='utf-8') as f: album_json_key_to_export_file_name = json.load(f) except ValueError: self._handle_broken_index() return False if not album_json_key_to_export_file_name: self._warning_nothing_to_import() return False self._load_exports_in_index(album_json_key_to_export_file_name) return True def _warning_nothing_to_import(self): WarningMessage(app.window, _("Nothing to import"), _("You have to export something before you can import.")) def _load_exports_in_index(self, album_json_key_to_export_file_name): for key, file_name in album_json_key_to_export_file_name.items(): path = EXPORT_DIR_PATH / file_name if not path.exists(): continue try: # album_id needed to be stored as a json string, since it's a tuple album_id = AlbumId(*json.loads(key)) except ValueError: continue self._album_id_to_export_path[album_id] = path def _handle_broken_index(self): index_path = TAGS_AND_USERDATA_INDEX_FILE_PATH now = cur_datetime_as_str() new_path = index_path.with_name(f'index-broken-{now}.{EXPORT_EXTENSION}') index_path.rename(new_path) self._error_msg(_("The index was corrupt.")) def import_data(self, export_album_id: AlbumId, songs: List[SongWrapper]): songs = [s for s in songs if is_writable(s)] if not songs: return songs.sort(key=sort_key_for_song) export_path = self._album_id_to_export_path[export_album_id] changed_songs = self.import_data_and_get_changed(songs, export_path) if changed_songs: check_wrapper_changed(app.library, changed_songs) # Remove used up export del self._album_id_to_export_path[export_album_id] if CONFIG.delete_exports_after_importing: try: export_path.unlink() except FileNotFoundError: pass else: move_export_to_used(export_path) def import_data_and_get_changed(self, songs: List[SongWrapper], source_path: Path) -> List[SongWrapper]: """:return: List of changed songs""" exported = self._try_read_source_json(source_path) if exported is None: return [] # removes TrackId from exported exported_indices = self._get_exported_indices_matched_to_songs(exported, songs) if not exported_indices: return [] changed_songs = [] for song, exp_idx in zip(songs, exported_indices): if exp_idx is None: continue self._update_song(exported[exp_idx], song) if song._needs_write: changed_songs.append(song) return changed_songs def _try_read_source_json(self, path: Path): try: print_d(f"Loading from {str(path)!r}") with path.open(encoding="utf-8") as f: return json.load(f) except ValueError: print_e(f"Couldn't parse JSON in {path}.") self._error_msg(_("Couldn't parse JSON in %s") % path) return None except OSError: print_e(f"Couldn't read {path}") self._error_msg(_("Couldn't read %s") % path) return None def _update_song(self, exported_data, song): file_stem = exported_data.pop(FILE_STEM_KEY, None) if file_stem is not None: file_ext = extension_of_file_name(song('~basename')) new_name = f'{file_stem}{file_ext}' new_song_path = os.path.join(song('~dirname'), new_name) try: app.library.rename(song._song, new_song_path) except ValueError: print_e(f'Could not rename {song._song} to {new_song_path}.') for pl_name in exported_data.pop(PLAYLISTS_KEY, []): add_song_to_playlist(pl_name, song) for tag_key, tag_value in exported_data.items(): if tag_key in song and song[tag_key] == tag_value: continue song[tag_key] = tag_value song._needs_write = True def _rewrite_index(self): # AlbumId's are tuples, so we need to serialize them to a string for json obj = {json.dumps(k): p.name for k, p in self._album_id_to_export_path.items()} self._rewrite_json(obj, TAGS_AND_USERDATA_INDEX_FILE_PATH) def _rewrite_json(self, obj, path): try: print_d(f"Writing to {str(path)!r}") with path.open('w+', encoding='utf-8') as f: json.dump(obj, f, indent=self._get_json_indent()) except (ValueError, OSError): self._error_msg(_("Couldn't write '%s'") % path) print_e(f"Couldn't write {path} due to:") print_exc() def _get_exported_indices_matched_to_songs(self, exported, songs): songs_ids = [TrackId.of_song(s) for s in songs] export_ids = [TrackId(*md.pop(IDENTIFIER_KEY)) for md in exported] export_ids_indices = self._track_id_matcher.get_indices(songs_ids, export_ids) size_differs = len(exported) != len(songs) need_check = CONFIG.need_user_check_if_number_of_tracks_differs and size_differs need_check = need_check or self._does_match_need_manual_check( self._track_id_matcher, export_ids_indices, CONFIG.max_track_similarity_to_need_user_check) if need_check: columns = [ # ColumnSpec(_('Disc'), lambda t: t.disc_text, False), ColumnSpec(_('Track'), lambda t: t.track_text, False), ColumnSpec(_('Title'), lambda t: t.title, True), ColumnSpec(_('Artist(s)'), lambda t: t.artist, True), ColumnSpec(_('File name'), lambda t: t.file_name, True), # ] prompt = MatchListsDialog(songs_ids, export_ids, export_ids_indices, columns, _("Match Tracks"), _("Import"), id_for_window_tracking=self.PLUGIN_ID) return prompt.run() return export_ids_indices def _does_match_need_manual_check(self, matcher, b_indices, max_similarity_to_need_manual_check): if max_similarity_to_need_manual_check <= 0.0: return False if max_similarity_to_need_manual_check >= 1.0: return True sim_matrix = matcher.similarity_matrix for a_idx, b_idx in enumerate(b_indices): if b_idx is None: continue sim = sim_matrix[a_idx][b_idx] if sim <= max_similarity_to_need_manual_check: return True return False def _get_json_indent(self): return 4 if CONFIG.pretty_print_json else None def export_albums(self, albums, collect_data): self._try_load_exports() for songs in albums: self.extract_data_and_export(songs, collect_data) def extract_data_and_export(self, songs, collect_data): songs.sort(key=sort_key_for_song) songs_data = [collect_data(s._song) for s in songs] album_id = AlbumId.of_song(songs[0]) prev_path = self._album_id_to_export_path.get(album_id) # this overrides export data with the same album key by design, so a user # can simply rerun the export on an album they've modified path = new_export_path_for_album(album_id) if prev_path is None else prev_path self._album_id_to_export_path[album_id] = path self._rewrite_json(songs_data, path) def cur_datetime_as_str(): return f'{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' def sort_key_for_song(s: SongWrapper): return s('~#disc', 0), s('~#track', 0), s('~basename'), s def add_song_to_playlist(pl_name, song): pl_lib = app.library.playlists try: pl_lib[pl_name].append(song) except KeyError: try: pl = pl_lib.create(pl_name) pl.append(song) except ValueError: print_e(f'tried to add {song} to playlist {pl_name} but could not due to:') print_exc() TrackData = MutableMapping[str, Any] """The term data here includes tags and track user data.""" TrackDataCollector = Callable[[AudioFile], TrackData] def track_data_collector_for(query: str) -> TrackDataCollector: """Creates a callable that returns the track data selected by the query.""" keys = query.strip().split() if keys[0] == '*': func = excluding_track_data_collector(set(keys[1:])) else: func = including_track_data_collector(keys) return func def excluding_track_data_collector(excluded_keys: Set[str]) -> TrackDataCollector: include_playlist = PLAYLISTS_KEY not in excluded_keys include_file_stem = FILE_STEM_KEY not in excluded_keys def func(track: AudioFile) -> TrackData: md = basic_track_data(track, include_playlist, include_file_stem) for key in track: if key not in excluded_keys and (key[:1] != "~" or key in MIGRATE): md[key] = track[key] return md return func def including_track_data_collector(keys: List[str]) -> TrackDataCollector: include_playlist = was_removed(keys, PLAYLISTS_KEY) include_file_stem = was_removed(keys, FILE_STEM_KEY) def func(track: AudioFile) -> TrackData: md = basic_track_data(track, include_playlist, include_file_stem) for key in keys: if key in track: md[key] = track[key] return md return func def was_removed(elements: list, o: Any) -> bool: """:return: whether o was in elements and thus removed from elements""" for idx, e in enumerate(elements): if e == o: del elements[idx] return True return False def basic_track_data(track: AudioFile, include_playlist: bool, include_file_stem: bool) -> TrackData: md = {IDENTIFIER_KEY: TrackId.of_song(track)} if include_playlist: if app.library is None: raise ValueError("app.library was None - plugin needs it") pl_lib = app.library.playlists playlist_names = [pl.name for pl in pl_lib.playlists_featuring(track)] if playlist_names: md[PLAYLISTS_KEY] = playlist_names if include_file_stem: md[FILE_STEM_KEY] = stem_of_file_name(track('~basename')) return md def new_export_path_for_album(album_id: AlbumId) -> Path: stem = f'{album_id.title} - {album_id.artist}' path = Path(join_path_with_escaped_name_of_legal_length(str(EXPORT_DIR_PATH), stem, EXPORT_EXTENSION)) trim_count = 1 while path.exists(): new_stem = path.stem[:-trim_count] + uuid.uuid4().hex[:trim_count] trim_count += 1 path = path.with_name(f'{new_stem}.{EXPORT_EXTENSION}') return path ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658776081.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/lastfmsync.py0000644000175000017500000002610514267565021021562 0ustar00nicknick# Copyright 2010 Steven Robertson # 2016 Mice Pápai # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import shelve import time from datetime import date from threading import Thread from urllib.parse import urlencode import json from gi.repository import Gtk, GLib import quodlibet from quodlibet import _, print_w, print_e from quodlibet import config, util, qltk from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.urllib import urlopen max_wait = 15 API_KEY = "f536cdadb4c2aec75ae15e2b719cb3a1" def apicall(method, **kwargs): """Performs Last.fm API call.""" real_args = {'api_key': API_KEY, 'format': 'json', 'method': method} real_args.update(kwargs) url = ''.join(["https://ws.audioscrobbler.com/2.0/?", urlencode(real_args)]) uobj = urlopen(url) json_text = uobj.read().decode("utf-8") resp = json.loads(json_text) if 'error' in resp: errmsg = f"Last.fm API error: {resp.get('message', '')}" print_e(errmsg) raise EnvironmentError(resp['error'], errmsg) return resp def config_get(key, default=None): return config.get('plugins', f"lastfmsync_{key}", default) class LastFMSyncCache: """Stores the Last.fm charts for a particular user.""" registered = 0 lastupdated = None def __init__(self, username): self.username = username self.charts = {} self.songs = {} def update_charts(self, progress=None): """Updates Last.fm charts for the given user. Returns True if an update was attempted, False otherwise. progress is a callback func (msg, frac) that will be called to update a UI. 'frac' may be None to indicate no change should be made. If the function returns False, this thread will stop early.""" def prog(msg, frac): if progress: if not progress(msg, frac): # this gets caught later raise ValueError() try: # Last.fm updates their charts weekly; we only poll for new # charts if it's been more than a day since the last poll if not self.registered: resp = apicall('user.getinfo', user=self.username) self.registered = int(resp['user']['registered']['unixtime']) now = time.time() if not self.lastupdated or self.lastupdated + (24 * 60 * 60) < now: prog(_("Updating chart list."), 0) resp = apicall('user.getweeklychartlist', user=self.username) charts = resp['weeklychartlist']['chart'] for chart in charts: # Charts keys are 2-tuple (from_timestamp, to_timestamp); # values are whether we still need to fetch the chart fro, to = [int(chart[s]) for s in ('from', 'to')] # If the chart is older than the register date of the # user, don't download it. (So the download doesn't start # with ~2005 every time.) if to < self.registered: continue self.charts.setdefault((fro, to), True) self.lastupdated = now elif not [v for v in self.charts.values() if v]: # No charts to fetch, no update scheduled. prog(_("Already up-to-date."), 1.) return False new_charts = [k for k, v in self.charts.items() if v] for idx, (fro, to) in enumerate(sorted(new_charts)): chart_week = date.fromtimestamp(fro).isoformat() prog(_("Fetching chart for week of %s.") % chart_week, (idx + 1.) / (len(new_charts) + 2.)) args = {'user': self.username, 'from': fro, 'to': to} try: resp = apicall('user.getweeklytrackchart', **args) except EnvironmentError as err: msg = "HTTP error %d, retrying in %d seconds." print_w(msg % (err.code, max_wait)) for i in range(max_wait, 0, -1): time.sleep(1) prog(msg % (err.code, i), None) resp = apicall('user.getweeklytrackchart', **args) try: tracks = resp['weeklytrackchart']['track'] except KeyError: tracks = [] # Delightfully, the API JSON frontend unboxes 1-element lists. if isinstance(tracks, dict): tracks = [tracks] for track in tracks: self._update_stats(track, fro, to) self.charts[(fro, to)] = False prog(_("Sync complete."), 1.) except ValueError: # this is probably from prog() pass except Exception as e: util.print_exc() prog(_("Error during sync (%s)") % e, None) return False return True def _update_stats(self, track, chart_fro, chart_to): """Updates a single track's stats. 'track' is as returned by API; 'chart_fro' and 'chart_to' are the chart's timestamp range.""" # we try track mbid, (artist mbid, name), (artist name, name) as keys keys = [] if track['mbid']: keys.append(track['mbid']) for artist in (track['artist']['mbid'], track['artist']['#text']): if artist: keys.append((artist.lower(), track['name'].lower())) stats = list(filter(None, map(self.songs.get, keys))) if stats: # Not sure if last.fm ever changes their tag values, but this # should map all changed values to the same object correctly plays = max(map(lambda d: d.get('playcount', 0), stats)) last = max(map(lambda d: d.get('lastplayed', 0), stats)) added = max(map(lambda d: d.get('added', chart_to), stats)) stats = stats[0] stats.update({'playcount': plays, 'lastplayed': last, 'added': added}) else: stats = {'playcount': 0, 'lastplayed': 0, 'added': chart_to} stats['playcount'] = stats['playcount'] + int(track['playcount']) stats['lastplayed'] = max(stats['lastplayed'], chart_fro) stats['added'] = min(stats['added'], chart_to) for key in keys: self.songs[key] = stats def update_songs(self, songs): """Updates each SongFile in songs from the cache.""" for song in songs: keys = [] if 'musicbrainz_trackid' in song: keys.append(song['musicbrainz_trackid'].lower()) if 'musiscbrainz_artistid' in song: keys.append((song['musicbrainz_artistid'].lower(), song.get('title', '').lower())) keys.append((song.get('artist', '').lower(), song.get('title', '').lower())) stats = list(filter(None, map(self.songs.get, keys))) if not stats: continue stats = stats[0] playcount = max(song.get('~#playcount', 0), stats['playcount']) if playcount != 0: song['~#playcount'] = playcount lastplayed = max(song.get('~#lastplayed', 0), stats['lastplayed']) if lastplayed != 0: song['~#lastplayed'] = lastplayed song['~#added'] = min(song['~#added'], stats['added']) class LastFMSyncWindow(qltk.Dialog): def __init__(self, parent): super().__init__(_("Last.fm Sync"), parent) self.add_button(_("_Cancel"), Gtk.ResponseType.REJECT) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.ACCEPT) self.set_border_width(5) self.set_default_size(300, 100) vbox = Gtk.VBox() vbox.set_spacing(12) self.progbar = Gtk.ProgressBar() vbox.pack_start(self.progbar, False, True, 0) self.status = Gtk.Label(label="") vbox.pack_start(self.status, True, True, 0) self.get_content_area().pack_start(vbox, True, True, 0) self.set_response_sensitive(Gtk.ResponseType.ACCEPT, False) self.show_all() def progress(self, message, fraction): self.status.set_text(message) if fraction is not None: self.progbar.set_fraction(fraction) self.progbar.set_text("%2.1f%%" % (fraction * 100)) if fraction == 1: self.set_response_sensitive(Gtk.ResponseType.ACCEPT, True) class LastFMSync(SongsMenuPlugin): PLUGIN_ID = "Last.fm Sync" PLUGIN_NAME = _("Last.fm Sync") PLUGIN_DESC = _("Updates your library's statistics from your " "Last.fm profile.") PLUGIN_ICON = Icons.EMBLEM_SHARED CACHE_PATH = os.path.join(quodlibet.get_user_dir(), "lastfmsync.db") def runner(self, cache): changed = True try: changed = cache.update_charts(self.progress) except Exception as e: print_w(f"Couldn't update cache ({e})") if changed: self.cache_shelf[cache.username] = cache self.cache_shelf.close() def progress(self, msg, frac): if self.running: GLib.idle_add(self.dialog.progress, msg, frac) return True else: return False def plugin_songs(self, songs): try: self.cache_shelf = shelve.open(self.CACHE_PATH) except: # some Python 2 DB types can't be opened in Python 3 self.cache_shelf = shelve.open(self.CACHE_PATH, "n") user = config_get('username', '') try: cache = self.cache_shelf.setdefault(user, LastFMSyncCache(user)) except Exception: # unpickle can fail in many ways. this is just cache, so ignore cache = self.cache_shelf[user] = LastFMSyncCache(user) self.dialog = LastFMSyncWindow(self.plugin_window) self.running = True thread = Thread(target=self.runner, args=(cache,)) thread.daemon = True thread.start() resp = self.dialog.run() if resp == Gtk.ResponseType.ACCEPT: cache.update_songs(songs) self.running = False self.dialog.destroy() @classmethod def PluginPreferences(klass, win): def entry_changed(entry): config.set('plugins', 'lastfmsync_username', entry.get_text()) label = Gtk.Label(label=_("_Username:"), use_underline=True) entry = UndoEntry() entry.set_text(config_get('username', '')) entry.connect('changed', entry_changed) label.set_mnemonic_widget(entry) hbox = Gtk.HBox() hbox.set_spacing(6) hbox.pack_start(label, False, True, 0) hbox.pack_start(entry, True, True, 0) return qltk.Frame(_("Account"), child=hbox) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/makesorttags.py0000664000175000017500000000315514035600052022070 0ustar00nicknick# Copyright 2008 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.songshelpers import any_song, is_finite, is_writable from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons def artist_to_sort(artist): try: rest, last = artist.rsplit(" ", 1) except ValueError: return None else: return ", ".join([last, rest]) def album_to_sort(album): try: first, rest = album.split(" ", 1) except ValueError: return None else: if first.lower() in ["a", "the"]: return ", ".join([rest, first]) class MakeSortTags(SongsMenuPlugin): PLUGIN_ID = "SortTags" PLUGIN_NAME = _("Create Sort Tags") PLUGIN_DESC = _("Converts album and artist names to sort names, poorly.") PLUGIN_ICON = Icons.EDIT plugin_handles = any_song(is_writable, is_finite) def plugin_song(self, song): for tag in ["album"]: values = filter(None, map(album_to_sort, song.list(tag))) if values and (tag + "sort") not in song: song[tag + "sort"] = "\n".join(values) for tag in ["artist", "albumartist", "performer"]: values = filter(None, map(artist_to_sort, song.list(tag))) if values and (tag + "sort") not in song: song[tag + "sort"] = "\n".join(values) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1672734865.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/playlist.py0000644000175000017500000001361514354764221021242 0ustar00nicknick# Copyright 2009 Christoph Reiter # 2014-2020 Nick Boultbee # 2022 Felix Krull # # 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 2 of the License, or # (at your option) any later version. # The Unofficial M3U and PLS Specification (Winamp): # http://forums.winamp.com/showthread.php?threadid=65772 import os from gi.repository import Gtk from os.path import relpath from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet import _ from quodlibet import util, qltk from quodlibet.util.path import get_home_dir from quodlibet.qltk.msg import ConfirmFileReplace from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin FORMAT_M3U = "m3u" FORMAT_PLS = "pls" lastfolder = get_home_dir() class PlaylistExport(PlaylistPlugin, SongsMenuPlugin): PLUGIN_ID = "Playlist Export" PLUGIN_NAME = _("Export as M3U / PLS Playlist File") PLUGIN_DESC = _("Exports songs to an M3U or PLS playlist.") PLUGIN_ICON = Icons.DOCUMENT_SAVE_AS REQUIRES_ACTION = True lastfolder = None def plugin_single_playlist(self, playlist): return self.__save_playlist_ui(playlist.songs, playlist.name) def plugin_songs(self, songs): self.__save_playlist_ui(songs) def __save_playlist_ui(self, songs, name=None): dialog = Gtk.FileChooserDialog( self.PLUGIN_NAME, None, Gtk.FileChooserAction.SAVE ) dialog.set_show_hidden(False) dialog.set_create_folders(True) dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) dialog.add_button(_("_Save"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) if name: dialog.set_current_name(name) ffilter = Gtk.FileFilter() ffilter.set_name(FORMAT_M3U) ffilter.add_mime_type("audio/x-mpegurl") ffilter.add_pattern("*.m3u") dialog.add_filter(ffilter) ffilter = Gtk.FileFilter() ffilter.set_name(FORMAT_PLS) ffilter.add_mime_type("audio/x-scpls") ffilter.add_pattern("*.pls") dialog.add_filter(ffilter) dialog.set_current_folder(lastfolder) diag_cont = dialog.get_child() hbox_path = Gtk.HBox() combo_path = Gtk.ComboBoxText() hbox_path.pack_end(combo_path, False, False, 6) diag_cont.pack_start(hbox_path, False, False, 0) diag_cont.show_all() for option_text in [_("Use relative paths"), _("Use absolute paths")]: combo_path.append_text(option_text) combo_path.set_active(0) response = dialog.run() if response == Gtk.ResponseType.OK: file_path = dialog.get_filename() file_format = dialog.get_filter().get_name() extension = "." + file_format if not file_path.endswith(extension): file_path += extension if os.path.exists(file_path): resp = ConfirmFileReplace(self.plugin_window, file_path).run() if resp != ConfirmFileReplace.RESPONSE_REPLACE: return relative = combo_path.get_active() == 0 self.save_playlist(songs, file_path, file_format, relative) self.lastfolder = os.path.dirname(file_path) dialog.destroy() def save_playlist(self, songs, file_path, file_format, relative): dir_path = os.path.dirname(file_path) files = self.__get_files(songs, dir_path, relative) if file_format == FORMAT_M3U: self.__m3u_export(file_path, files) elif file_format == FORMAT_PLS: self.__pls_export(file_path, files) def __get_files(self, songs, dir_path, relative=False): files = [] for song in songs: f = {} if "~uri" in song: f["path"] = song("~filename") f["title"] = song("title") f["length"] = -1 else: path = song("~filename") if relative: path = relpath(path, dir_path) if path.startswith("#"): # avoid lines starting with '#' which don't work with M3U path = os.path.join(os.curdir, path) f["path"] = path f["title"] = "%s - %s" % ( song("~people").replace("\n", ", "), song("~title~version"), ) f["length"] = song("~#length") files.append(f) return files def __file_error(self, file_path): dialog = qltk.ErrorMessage( None, _("Unable to export playlist"), _("Writing to %s failed.") % util.bold(file_path), escape_desc=False, ) dialog.run() def __m3u_export(self, file_path, files): try: fhandler = open(file_path, "wb") except IOError: self.__file_error(file_path) else: text = "#EXTM3U\n" for f in files: text += "#EXTINF:%d,%s\n" % (f["length"], f["title"]) text += f["path"] + "\n" fhandler.write(text.encode("utf-8")) fhandler.close() def __pls_export(self, file_path, files): try: fhandler = open(file_path, "wb") except IOError: self.__file_error(file_path) else: text = "[playlist]\n" for num, f in enumerate(files): num += 1 text += "File%d=%s\n" % (num, f["path"]) text += "Title%d=%s\n" % (num, f["title"]) text += "Length%d=%s\n" % (num, f["length"]) text += "NumberOfEntries=%d\n" % len(files) text += "Version=2\n" fhandler.write(text.encode("utf-8")) fhandler.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/refresh.py0000664000175000017500000000256114035600052021022 0ustar00nicknick# Copyright 2013 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet import _ from quodlibet.qltk.notif import Task from quodlibet.qltk import Icons from quodlibet.util import copool from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.i18n import numeric_phrase class RefreshSongs(SongsMenuPlugin): PLUGIN_ID = "refresh-songs" # Translators: Plugin name PLUGIN_NAME = _("Rescan Songs") PLUGIN_DESC = _("Checks for file changes and reloads / removes " "the songs if needed.") PLUGIN_ICON = Icons.VIEW_REFRESH def plugin_songs(self, songs): def check_songs(): desc = numeric_phrase("%d song", "%d songs", len(songs)) with Task(_("Rescan songs"), desc) as task: task.copool(check_songs) for i, song in enumerate(songs): song = song._song if song in app.library: app.library.reload(song) task.update((float(i) + 1) / len(songs)) yield copool.add(check_songs) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/replaygain.py0000644000175000017500000005336114327505043021531 0ustar00nicknick# ReplayGain Album Analysis using gstreamer rganalysis element # Copyright (C) 2005,2007,2009 Michael Urman # 2012-2021 Nick Boultbee # 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from gi.repository import GObject from gi.repository import Pango from gi.repository import Gst from gi.repository import GLib from quodlibet import print_d, ngettext, C_, _, util from quodlibet.plugins import PluginConfigMixin from quodlibet.browsers.collection.models import EMPTY from quodlibet.qltk.views import HintedTreeView from quodlibet.qltk.x import Frame from quodlibet.qltk import Icons, Dialog from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import is_writable, is_finite, each_song from quodlibet.util import cached_property, print_w, print_e, format_int_locale from quodlibet.util.path import uri2gsturi __all__ = ['ReplayGain'] def get_num_threads(): # multiprocessing is >= 2.6. # Default to 2 threads if cpu_count isn't implemented for the current arch # or multiprocessing isn't available try: import multiprocessing threads = multiprocessing.cpu_count() except (ImportError, NotImplementedError): threads = 2 return threads class UpdateMode: """Enum-like class for update strategies""" ALWAYS = "always" ALBUM_MISSING = "album_tags_missing" ANY_MISSING = "any_tags_missing" class RGAlbum: def __init__(self, rg_songs, process_mode): self.songs = rg_songs self.gain = None self.peak = None self.__should_process = None self.__process_mode = process_mode @property def progress(self): all_ = 0.0 done = 0.0 for song in self.songs: all_ += song.length done += song.length * song.progress try: return max(min(done / all_, 1.0), 0.0) except ZeroDivisionError: return 0.0 @property def done(self): for song in self.songs: if not song.done: return False return True @property def title(self): if not self.songs: return "" # It's ok - any() + generator is short-cut-logic-friendly if not any(rgs.song("album") for rgs in self.songs): return "(%s)" % EMPTY return self.songs[0].song.comma('~artist~album') @property def error(self): for song in self.songs: if song.error: return True return False def write(self): # Don't write incomplete data if not self.done: return for song in self.songs: song._write(self.gain, self.peak) @classmethod def from_songs(cls, songs, process_mode=UpdateMode.ALWAYS): return RGAlbum([RGSong(s) for s in songs], process_mode) @cached_property def should_process(self): """Returns true if the album needs analysis, according to prefs""" mode = self.__process_mode if mode == UpdateMode.ALWAYS: return True elif mode == UpdateMode.ANY_MISSING: return not all([s.has_all_rg_tags for s in self.songs]) elif mode == UpdateMode.ALBUM_MISSING: return not all([s.album_gain for s in self.songs]) else: print_w("Invalid setting for update mode: " + mode) # Safest to re-process probably. return True class RGSong: def __init__(self, song): self.song = song self.error = False self.gain = None self.peak = None self.progress = 0.0 self.done = False # TODO: support prefs for not overwriting individual existing tags # e.g. to re-run over entire library but keeping files untouched self.overwrite_existing = True def _write(self, album_gain, album_peak): if self.error or not self.done: return song = self.song def write_to_song(tag, pattern, value): if value is None or value == "": return existing = song(tag, None) if existing and not self.overwrite_existing: print_d("Not overwriting existing tag %s (=%s) for %s" % (tag, existing, self.song("~filename"))) return song[tag] = pattern % value write_to_song('replaygain_track_gain', '%.2f dB', self.gain) write_to_song('replaygain_track_peak', '%.4f', self.peak) write_to_song('replaygain_album_gain', '%.2f dB', album_gain) write_to_song('replaygain_album_peak', '%.4f', album_peak) # bs1770gain writes those and since we still do old replaygain # just delete them so players use the defaults. song.pop("replaygain_reference_loudness", None) song.pop("replaygain_algorithm", None) song.pop("replaygain_album_range", None) song.pop("replaygain_track_range", None) @property def title(self): return self.song('~tracknumber~title~version') @property def filename(self): return self.song("~filename") @property def uri(self): return self.song("~uri") @property def length(self): return self.song("~#length") def _get_rg_tag(self, suffix): ret = self.song("~#replaygain_%s" % suffix) return None if ret == "" else ret @property def track_gain(self): return self._get_rg_tag("track_gain") @property def album_gain(self): return self._get_rg_tag("album_gain") @property def track_peak(self): return self._get_rg_tag('track_peak') @property def album_peak(self): return self._get_rg_tag('album_peak') @property def has_track_tags(self): return not (self.track_gain is None or self.track_peak is None) @property def has_album_tags(self): return not (self.album_gain is None or self.album_peak is None) @property def has_all_rg_tags(self): return self.has_track_tags and self.has_album_tags def __str__(self): vals = {k: self._get_rg_tag(k) for k in 'track_gain album_gain album_peak track_peak'.split()} return "" % (self.song, vals) class ReplayGainPipeline(GObject.Object): __gsignals__ = { # done(self, album) 'done': (GObject.SignalFlags.RUN_LAST, None, (object,)), # update(self, album, song) 'update': (GObject.SignalFlags.RUN_LAST, None, (object, object,)), } def __init__(self): super().__init__() self._current = None self._setup_pipe() def _setup_pipe(self): # gst pipeline for replay gain analysis: # uridecodebin!audioconvert!audioresample!rganalysis!fakesink self.pipe = Gst.Pipeline() self.decode = Gst.ElementFactory.make("uridecodebin", "decode") def new_decoded_pad(dbin, pad): pad.link(self.convert.get_static_pad("sink")) self.decode.connect("pad-added", new_decoded_pad) self.pipe.add(self.decode) self.convert = Gst.ElementFactory.make("audioconvert", "convert") self.pipe.add(self.convert) self.resample = Gst.ElementFactory.make("audioresample", "resample") self.pipe.add(self.resample) self.convert.link(self.resample) self.analysis = Gst.ElementFactory.make("rganalysis", "analysis") self.pipe.add(self.analysis) self.resample.link(self.analysis) self.sink = Gst.ElementFactory.make("fakesink", "sink") self.pipe.add(self.sink) self.analysis.link(self.sink) self.bus = bus = self.pipe.get_bus() bus.add_signal_watch() bus.connect("message", self._bus_message) def request_update(self): if not self._current: return ok, p = self.pipe.query_position(Gst.Format.TIME) if ok: length = self._current.length try: progress = float(p / Gst.SECOND) / length except ZeroDivisionError: progress = 0.0 progress = max(min(progress, 1.0), 0.0) self._current.progress = progress self._emit_update() def _emit_update(self): self.emit("update", self._album, self._current) def start(self, album): self._album = album self._songs = list(album.songs) self._done = [] self._next_song(first=True) def quit(self): self.bus.remove_signal_watch() self.pipe.set_state(Gst.State.NULL) def _next_song(self, first=False): if self._current: self._current.progress = 1.0 self._current.done = True self._emit_update() self._done.append(self._current) self._current = None if not self._songs: self.pipe.set_state(Gst.State.NULL) self.emit("done", self._album) return if first: self.analysis.set_property("num-tracks", len(self._songs)) else: self.analysis.set_locked_state(True) self.pipe.set_state(Gst.State.NULL) self._current = self._songs.pop(0) self.decode.set_property("uri", uri2gsturi(self._current.uri)) if not first: # flush, so the element takes new data after EOS pad = self.analysis.get_static_pad("src") pad.send_event(Gst.Event.new_flush_start()) pad.send_event(Gst.Event.new_flush_stop(True)) self.analysis.set_locked_state(False) self.pipe.set_state(Gst.State.PLAYING) def _bus_message(self, bus, message): if message.type == Gst.MessageType.TAG: tags = message.parse_tag() ok, value = tags.get_double(Gst.TAG_TRACK_GAIN) if ok: self._current.gain = value ok, value = tags.get_double(Gst.TAG_TRACK_PEAK) if ok: self._current.peak = value ok, value = tags.get_double(Gst.TAG_ALBUM_GAIN) if ok: self._album.gain = value ok, value = tags.get_double(Gst.TAG_ALBUM_PEAK) if ok: self._album.peak = value self._emit_update() elif message.type == Gst.MessageType.EOS: self._next_song() elif message.type == Gst.MessageType.ERROR: gerror, debug = message.parse_error() if gerror: print_e(gerror.message) print_e(debug) self._current.error = True self._next_song() class RGDialog(Dialog): def __init__(self, albums, parent, process_mode): super().__init__( title=_('ReplayGain Analyzer'), parent=parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.OK) self.process_mode = process_mode self.set_default_size(600, 400) self.set_border_width(6) hbox = Gtk.HBox(spacing=6) info = Gtk.Label() hbox.pack_start(info, True, True, 0) self.vbox.pack_start(hbox, False, False, 6) swin = Gtk.ScrolledWindow() swin.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) swin.set_shadow_type(Gtk.ShadowType.IN) self.vbox.pack_start(swin, True, True, 0) view = HintedTreeView() swin.add(view) def icon_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.error: cell.set_property('icon-name', Icons.DIALOG_ERROR) else: cell.set_property('icon-name', Icons.NONE) column = Gtk.TreeViewColumn() column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) icon_render = Gtk.CellRendererPixbuf() column.pack_start(icon_render, True) column.set_cell_data_func(icon_render, icon_cdf) view.append_column(column) def track_cdf(column, cell, model, iter_, *args): item = model[iter_][0] cell.set_property('text', item.title) cell.set_sensitive(model[iter_][1]) # Translators: Combined track number/title column heading column = Gtk.TreeViewColumn(C_("track/title", "Track")) column.set_expand(True) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) track_render = Gtk.CellRendererText() track_render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(track_render, True) column.set_cell_data_func(track_render, track_cdf) view.append_column(column) def progress_cdf(column, cell, model, iter_, *args): item = model[iter_][0] cell.set_property('value', int(item.progress * 100)) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Progress")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) progress_render = Gtk.CellRendererProgress() column.pack_start(progress_render, True) column.set_cell_data_func(progress_render, progress_cdf) view.append_column(column) def gain_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.gain is None or not item.done: cell.set_property('text', "-") else: cell.set_property('text', "%.2f db" % item.gain) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Gain")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) gain_renderer = Gtk.CellRendererText() column.pack_start(gain_renderer, True) column.set_cell_data_func(gain_renderer, gain_cdf) view.append_column(column) def peak_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.gain is None or not item.done: cell.set_property('text', "-") else: cell.set_property('text', "%.2f" % item.peak) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Peak")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) peak_renderer = Gtk.CellRendererText() column.pack_start(peak_renderer, True) column.set_cell_data_func(peak_renderer, peak_cdf) view.append_column(column) self.create_pipelines() self._timeout = None self._sigs = {} self._done = [] self.__fill_view(view, albums) num_to_process = sum(int(rga.should_process) for rga in self._todo) template = ngettext( "There is %(to-process)s album to update (of %(all)s)", "There are %(to-process)s albums to update (of %(all)s)", num_to_process) info.set_markup(template % { "to-process": util.bold(format_int_locale(num_to_process)), "all": util.bold(format_int_locale(len(self._todo))), }) self.connect("destroy", self.__destroy) self.connect('response', self.__response) def create_pipelines(self): # create as many pipelines as threads self.pipes = [ReplayGainPipeline() for _ in range(get_num_threads())] def __fill_view(self, view, albums): self._todo = [RGAlbum.from_songs(a, self.process_mode) for a in albums] self._count = len(self._todo) self.model = model = Gtk.TreeStore(object, bool) insert = model.insert for album in reversed(self._todo): enabled = album.should_process base = insert(None, 0, row=[album, enabled]) for song in reversed(album.songs): insert(base, 0, row=[song, enabled]) view.set_model(model) if len(self._todo) == 1: view.expand_all() def start_analysis(self): self._timeout = GLib.idle_add(self.__request_update) # fill the pipelines for p in self.pipes: if not self._todo: break self._sigs[p] = [ p.connect("done", self.__done), p.connect("update", self.__update), ] album = self.get_next_album() if not album: return p.start(album) def get_next_album(self): next_album = None while not next_album: if not self._todo: print_d("No more albums to process") return None next_album = self._todo.pop(0) if not next_album.should_process: print_d("%s needs no processing" % next_album.title) self._done.append(next_album) self.__update_view_for(next_album) next_album = None return next_album def __response(self, win, response): if response == Gtk.ResponseType.CANCEL: self.destroy() elif response == Gtk.ResponseType.OK: for album in self._done: album.write() self.destroy() def __destroy(self, *args): # shut down any active processing and clean up resources, timeouts if self._timeout: GLib.source_remove(self._timeout) for p in self.pipes: if p in self._sigs: for s in self._sigs.get(p, []): p.disconnect(s) p.quit() def __update(self, pipeline, album, song): for row in self.model: row_album = row[0] if row_album is album: self.model.row_changed(row.path, row.iter) for child in row.iterchildren(): row_song = child[0] if row_song is song: self.model.row_changed(child.path, child.iter) break break def __done(self, pipeline, album): self._done.append(album) next_album = self.get_next_album() if next_album: pipeline.start(next_album) self.__update_view_for(album) def __update_view_for(self, album): for row in self.model: row_album = row[0] if row_album is album: self.model.row_changed(row.path, row.iter) break def __request_update(self): GLib.source_remove(self._timeout) self._timeout = None # all done, stop if len(self._done) < self._count: for p in self.pipes: p.request_update() self._timeout = GLib.timeout_add(400, self.__request_update) return False class ReplayGain(SongsMenuPlugin, PluginConfigMixin): PLUGIN_ID = 'ReplayGain' PLUGIN_NAME = _('Replay Gain') PLUGIN_DESC_MARKUP = ( _('Analyzes and updates ReplayGain information, ' 'using GStreamer. Results are grouped by album.') % {"rg_link": _("https://en.wikipedia.org/wiki/ReplayGain")}) PLUGIN_ICON = Icons.MULTIMEDIA_VOLUME_CONTROL CONFIG_SECTION = 'replaygain' plugin_handles = each_song(is_finite, is_writable) def plugin_albums(self, albums): mode = self.config_get("process_if", UpdateMode.ALWAYS) win = RGDialog(albums, parent=self.plugin_window, process_mode=mode) win.show_all() win.start_analysis() # plugin_done checks for metadata changes and opens the write dialog win.connect("destroy", self.__plugin_done) def __plugin_done(self, win): self.plugin_finish() @classmethod def PluginPreferences(cls, parent): vb = Gtk.VBox(spacing=12) # Tabulate all settings for neatness table = Gtk.Table(n_rows=1, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) rows = [] def process_option_changed(combo): # xcode = combo.get_child().get_text() model = combo.get_model() lbl, value = model[combo.get_active()] cls.config_set("process_if", value) def create_model(): model = Gtk.ListStore(str, str) model.append([util.bold(_("always")), UpdateMode.ALWAYS]) model.append([_("if any RG tags are missing"), UpdateMode.ANY_MISSING]) model.append([_("if album RG tags are missing"), UpdateMode.ALBUM_MISSING]) return model def set_active(value): for i, item in enumerate(model): if value == item[1]: combo.set_active(i) model = create_model() combo = Gtk.ComboBox(model=model) set_active(cls.config_get("process_if", UpdateMode.ALWAYS)) renderer = Gtk.CellRendererText() combo.connect('changed', process_option_changed) combo.pack_start(renderer, True) combo.add_attribute(renderer, "markup", 0) rows.append((_("_Process albums:"), combo)) for (row, (label_text, entry)) in enumerate(rows): label = Gtk.Label(label=label_text) label.set_alignment(0.0, 0.5) label.set_use_underline(True) label.set_mnemonic_widget(entry) table.attach(label, 0, 1, row, row + 1, xoptions=Gtk.AttachOptions.FILL) table.attach(entry, 1, 2, row, row + 1) # Server settings Frame frame = Frame(_("Existing Tags"), table) vb.pack_start(frame, True, True, 0) return vb if not Gst.Registry.get().find_plugin("replaygain"): __all__ = [] del ReplayGain raise ImportError("GStreamer replaygain plugin not found") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411642.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/splitting.py0000664000175000017500000000421514035600172021402 0ustar00nicknick# Copyright 2005 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet.plugins.songshelpers import any_song from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.string.splitters import split_title, split_album from quodlibet.qltk import Icons def has_album_splittable(song): return ("album" in song and "discnumber" not in song and song.can_change("album") and song.can_change("discnumber")) def has_title_splittable(song): return ("title" in song and song.can_change("title") and song.can_change("version")) class SplitTags(SongsMenuPlugin): PLUGIN_ID = "Split Tags" PLUGIN_NAME = _("Split Tags") PLUGIN_DESC = _("Splits the disc number from the album and the version " "from the title at the same time.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE plugin_handles = any_song(has_title_splittable) def plugin_song(self, song): if has_title_splittable(song): title, versions = split_title(song["title"]) if title: song["title"] = title if versions: song["version"] = "\n".join(versions) if has_album_splittable(song): album, disc = split_album(song["album"]) if album: song["album"] = album if disc: song["discnumber"] = disc class SplitAlbum(SongsMenuPlugin): PLUGIN_ID = "Split Album" PLUGIN_NAME = _("Split Album") PLUGIN_DESC = _("Split out disc number.") PLUGIN_ICON = Icons.EDIT_FIND_REPLACE plugin_handles = any_song(has_album_splittable) def plugin_song(self, song): if has_album_splittable(song): album, disc = split_album(song["album"]) if album: song["album"] = album if disc: song["discnumber"] = disc ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658776081.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/tapbpm.py0000644000175000017500000001467114267565021020667 0ustar00nicknick# Copyright 2017 Didier Villevalois, # 2010 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gdk, Gtk from quodlibet import _ from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons from quodlibet.qltk.window import Dialog class TapBpmPanel(Gtk.VBox): def __init__(self, parent, song): super().__init__() self.dialog = parent self.song = song self.original_bpm = song["bpm"] if "bpm" in song else _("n/a") self.set_margin_bottom(6) self.set_spacing(6) box = Gtk.HBox() box.set_spacing(6) # TRANSLATORS: BPM mean "beats per minute" box.pack_start(Gtk.Label(_("BPM:")), False, True, 0) self.bpm_label = Gtk.Label(_("n/a")) self.bpm_label.set_xalign(0.5) box.pack_start(self.bpm_label, True, True, 0) self.reset_btn = Gtk.Button(label=_("Reset")) self.reset_btn.connect('clicked', lambda *x: self.reset()) box.pack_end(self.reset_btn, False, True, 0) self.pack_start(box, False, True, 0) self.tap_btn = Gtk.Button(label=_("Tap")) self.tap_btn.connect('button-press-event', self.tap) self.tap_btn.connect('key-press-event', self.key_tap) self.pack_start(self.tap_btn, True, True, 0) self.init_tap() self.update() self.show_all() def update(self): has_new_bpm = self.clicks > 1 self.dialog.set_response_sensitive(Gtk.ResponseType.OK, has_new_bpm) self.reset_btn.set_sensitive(has_new_bpm) if self.clicks > 1: self.bpm_label.set_text("%.1f" % self.floating_bpm) elif self.clicks == 1: self.bpm_label.set_text(_("n/a")) else: self.bpm_label.set_text(str(self.original_bpm)) # Give focus back to the tap button even if reset was pressed self.tap_btn.grab_focus() def tap(self, widget, event): self.count_tap(event.time) self.update() def key_tap(self, widget, event): if event.keyval != Gdk.KEY_space \ and event.keyval != Gdk.KEY_Return: return False self.count_tap(event.time) self.update() return True def reset(self): self.init_tap() self.update() def save(self): self.song["bpm"] = "%.0f" % self.floating_bpm self.song.write() def init_tap(self): self.bpm = 0.0 self.clicks = 0 self.last = 0 self.last_times = [] self.last_bpms = [] self.last_floating_bpms = [] self.last_floating_squares = [] self.bpms_sum = 0.0 self.squares_sum = 0.0 self.average_count = 0 self.min = 0 self.max = 0 try: self.floating_bpm = float(self.original_bpm) except ValueError: self.floating_bpm = 0.0 self.floating_square = 0.0 self.keep = 100 self.pause = 3 self.min_weight = 0.01 def count_tap(self, now): now = now / 1000. # reset? if now - self.last > self.pause: self.clicks = 0 self.bpm = 0.0 self.last_times = [] self.last_bpms = [] self.last_floating_bpms = [] self.last_floating_squares = [] self.bpms_sum = 0.0 self.squares_sum = 0.0 self.average_count = 0 self.min = 0 self.max = 0 self.floating_bpm = 0.0 self.floating_square = 0.0 elif now > self.last: # Use previous 5 values to average BPM bpms = [] bpms.append(60.0 / (now - self.last)) # and four out of the list for i in iter(range(1, 5)): if len(self.last_times) <= i: break bpms.append((i + 1) * 60.0 / (now - self.last_times[-i])) self.bpm = sum(bpms) / len(bpms) # Exponentially weighted floating average weight = (1.0 / self.clicks) ** .5 if weight < self.min_weight: weight = self.min_weight self.floating_bpm = \ self.floating_bpm * (1.0 - weight) \ + self.bpm * weight self.floating_square = \ self.floating_square * (1.0 - weight) \ + self.bpm * self.bpm * weight if self.bpm < self.min or self.average_count == 0: self.min = self.bpm if self.bpm > self.max or self.average_count == 0: self.max = self.bpm self.bpms_sum += self.bpm self.squares_sum += self.bpm * self.bpm self.average_count += 1 # Update history self.last_times = self.last_times[-(self.keep - 1):] + [self.last] self.last_bpms = self.last_bpms[-(self.keep - 1):] + [self.bpm] self.last_floating_bpms = \ self.last_floating_bpms[-(self.keep - 1):] \ + [self.floating_bpm] self.last_floating_squares = \ self.last_floating_squares[-(self.keep - 1):] \ + [self.floating_square] self.last = now self.clicks += 1 class TapBpm(SongsMenuPlugin): PLUGIN_ID = "Tap BPM" PLUGIN_NAME = _("Tap BPM") PLUGIN_DESC = _("🥁 Tap BPM for the selected song.") PLUGIN_ICON = Icons.EDIT PLUGIN_VERSION = "0.1" def plugin_song(self, song): self._window = window = \ Dialog(title=_("Tap BPM"), parent=self.plugin_window) window.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) window.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.OK) window.set_default_size(300, 100) window.set_border_width(6) self.__resp_sig = window.connect('response', self.response) self._panel = TapBpmPanel(window, song) window.vbox.pack_start(self._panel, False, True, 0) window.vbox.show_all() window.present() def response(self, win, response): if response == Gtk.ResponseType.OK: # Save metadata self._panel.save() win.hide() win.disconnect(self.__resp_sig) win.destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/website_search.py0000644000175000017500000001400714327505043022357 0ustar00nicknick# Copyright 2011-2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from urllib.parse import quote_plus from gi.repository import Gtk import quodlibet from quodlibet import _, util from quodlibet import qltk from quodlibet.formats import AudioFile from quodlibet.pattern import Pattern from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons from quodlibet.qltk.cbes import StandaloneEditor from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.util import connect_obj, print_w, print_d from quodlibet.util import website from quodlibet.util.path import uri_is_valid from quodlibet.util.tags import USER_TAGS, MACHINE_TAGS class WebsiteSearch(SongsMenuPlugin): """Loads a browser with a URL designed to search on tags of the song. This may include a standard web search engine, eg Google, or a more specific site look-up. The URLs are customisable using tag patterns. """ PLUGIN_ICON = Icons.APPLICATION_INTERNET PLUGIN_ID = "Website Search" PLUGIN_NAME = _("Website Search") PLUGIN_DESC_MARKUP = (_( "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern)s.") % {"pattern": util.monospace("https://duckduckgo.com?q=<~artist~title>")} ) # Here are some starters... DEFAULT_URL_PATS = [ ("Google song search", "https://google.com/search?q="), ("Wikipedia (en) artist entry", "https://wikipedia.org/wiki/|>"), ("Musicbrainz album listing", "https://musicbrainz.org/|search?query=&type=release>"), ("Discogs album search", "https://www.discogs.com/search?type=release&artist=" "|>&title="), ("Youtube video search", "https://www.youtube.com/results?search_query="), ("Go to ~website", ""), ] PATTERNS_FILE = os.path.join( quodlibet.get_user_dir(), 'lists', 'searchsites') _no_launch = False def __set_site(self, name): self.chosen_site = name def get_url_pattern(self, key): """Gets the pattern for a given key""" return dict(self._url_pats).get(key, self.DEFAULT_URL_PATS[0][1]) @classmethod def edit_patterns(cls, button): def valid_uri(s): # TODO: some pattern validation too (that isn't slow) try: p = Pattern(s) return (p and uri_is_valid(s)) except ValueError: return False win = StandaloneEditor(filename=cls.PATTERNS_FILE, title=_("Search URL patterns"), initial=cls.DEFAULT_URL_PATS, validator=valid_uri) win.show() @classmethod def PluginPreferences(cls, parent): hb = Gtk.HBox(spacing=3) hb.set_border_width(0) button = qltk.Button(_("Edit search URLs"), Icons.EDIT) button.connect("clicked", cls.edit_patterns) hb.pack_start(button, True, True, 0) hb.show_all() return hb def _get_saved_searches(self): filename = self.PATTERNS_FILE + ".saved" self._url_pats = StandaloneEditor.load_values(filename) # Failing all else... if not len(self._url_pats): print_d("No saved searches found in %s. Using defaults." % filename) self._url_pats = self.DEFAULT_URL_PATS def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.chosen_site = None self._url_pats = [] submenu = Gtk.Menu() self._get_saved_searches() for name, url_pat in self._url_pats: item = Gtk.MenuItem(label=name) connect_obj(item, 'activate', self.__set_site, name) submenu.append(item) # Add link to editor configure = Gtk.MenuItem(label=_(u"Configure Searches…")) connect_obj(configure, 'activate', self.edit_patterns, configure) submenu.append(SeparatorMenuItem()) submenu.append(configure) if submenu.get_children(): self.set_submenu(submenu) else: self.set_sensitive(False) def plugin_songs(self, songs): # Check this is a launch, not a configure if self.chosen_site: url_pat = self.get_url_pattern(self.chosen_site) pat = Pattern(url_pat) # Remove Nones, and de-duplicate collection urls = set(filter(None, (website_for(pat, s) for s in songs))) if not urls: print_w("Couldn't build URLs using \"%s\"." "Check your pattern?" % url_pat) return False print_d("Got %d websites from %d songs" % (len(urls), len(songs))) if not self._no_launch: for url in urls: website(url) return True def website_for(pat, song): """Gets a utf-8 encoded string for a website from the given pattern""" # Generate a sanitised AudioFile; allow through most tags subs = AudioFile() # See issue 2762 for k in (USER_TAGS + MACHINE_TAGS + ['~filename']): vals = song.comma(k) if vals: try: # Escaping ~filename stops ~dirname ~basename etc working # But not escaping means ? % & will cause problems. # Who knows what user wants to do with /, seems better raw. subs[k] = (vals if k in ['website', '~filename'] else quote_plus(vals)) except KeyError: print_d("Problem with %s tag values: %r" % (k, vals)) return pat.format(subs) or None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658776081.0 quodlibet-4.6.0/quodlibet/ext/songsmenu/wikipedia.py0000644000175000017500000000754014267565021021347 0ustar00nicknick# Copyright 2005 Inigo Serna # 2018 Phoenix Dailey, Fredrik Strupe # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from urllib.parse import quote from gi.repository import Gtk from quodlibet import _ from quodlibet import config from quodlibet import app from quodlibet import util from quodlibet.qltk.entry import Entry from quodlibet.qltk.data_editors import TagListEditor from quodlibet.qltk import Icons, get_top_parent, ErrorMessage from quodlibet.plugins.songsmenu import SongsMenuPlugin WIKI_URL = "https://%s.wikipedia.org/wiki/Special:Search/" def get_lang(): return config.get("plugins", "wiki_lang", "en") def set_lang(value): config.set("plugins", "wiki_lang", value) class WikiSearch(SongsMenuPlugin): PLUGIN_ID = 'Search Tag in Wikipedia' PLUGIN_NAME = _('Search Tag in Wikipedia') PLUGIN_DESC = _("Opens a browser window with the Wikipedia article " "on the selected song's corresponding tag.") PLUGIN_ICON = Icons.APPLICATION_INTERNET DEFAULT_TAGS = ['album', 'artist', 'composer'] @classmethod def changed(self, e): set_lang(e.get_text()) @classmethod def PluginPreferences(self, parent): hb = Gtk.HBox(spacing=3) hb.set_border_width(6) e = Entry(max_length=2) e.set_width_chars(3) e.set_max_width_chars(3) e.set_text(get_lang()) e.connect('changed', self.changed) hb.pack_start( Gtk.Label(label=_("Search at %(website)s") % { "website": "https://"}), False, True, 0) hb.pack_start(e, False, True, 0) hb.pack_start(Gtk.Label(label=".wikipedia.org"), False, True, 0) vb = Gtk.VBox(spacing=6) vb.pack_start(hb, False, False, 0) def _open_editor(widget): def _editor_closed(widget): config.setlist("plugins", "wiki_tags", widget.tags) tags = config.getlist("plugins", "wiki_tags", self.DEFAULT_TAGS) editor = TagListEditor(_("Edit Tags"), [] if tags == [''] else tags) editor.set_transient_for(get_top_parent(parent)) editor.connect('destroy', _editor_closed) editor.show() button = Gtk.Button(_("Edit Tags")) button.connect('clicked', _open_editor) vb.pack_start(button, False, True, 0) vb.show_all() return vb def __init__(self, *args, **kwargs): super().__init__(**kwargs) self.selected_tag = None self.update_submenu() def update_submenu(self): submenu = Gtk.Menu() tags = config.getlist("plugins", "wiki_tags", self.DEFAULT_TAGS) for tag in tags: if tag: item = Gtk.MenuItem(label=util.tag(tag)) item.connect('activate', self._set_selected_tag, tag) submenu.append(item) if submenu.get_children(): self.set_submenu(submenu) else: self.set_sensitive(False) def _set_selected_tag(self, widget, tag): self.selected_tag = tag def plugin_songs(self, songs): if not self.selected_tag: return l = dict.fromkeys([song(self.selected_tag) for song in songs]).keys() # If no tags values were found, show an error dialog if list(l) == ['']: ErrorMessage(app.window, _('Search failed'), _('Tag "%s" not found.') % self.selected_tag).run() return for a in l: # Only search for non-empty tags if a: a = quote(str(a).title().replace(' ', '_')) util.website(WIKI_URL % get_lang() + a) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9909356 quodlibet-4.6.0/quodlibet/formats/0000755000175000017500000000000014471213412015645 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1677336198.0 quodlibet-4.6.0/quodlibet/formats/__init__.py0000664000175000017500000000153714376417206020001 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from ._audio import PEOPLE, AudioFile, DUMMY_SONG, decode_value, \ FILESYSTEM_TAGS, TIME_TAGS from ._image import EmbeddedImage, APICType from ._misc import AudioFileError, init, MusicFile, types, loaders, filter, \ mimes from ._serialize import load_audio_files, dump_audio_files, SerializationError AudioFile, AudioFileError, EmbeddedImage, DUMMY_SONG, PEOPLE, decode_value, APICType, FILESYSTEM_TAGS, TIME_TAGS, init, MusicFile, types, loaders, filter, mimes, load_audio_files, dump_audio_files, SerializationError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618773137.0 quodlibet-4.6.0/quodlibet/formats/_apev2.py0000664000175000017500000001447614037102221017402 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # # 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 2 of the License, or # (at your option) any later version. import mutagen.apev2 from quodlibet.util.path import get_temp_cover_file from ._audio import AudioFile from ._image import APICType, EmbeddedImage from ._misc import AudioFileError, translate_errors def get_cover_type(key, value): """Returns an APICType or None if the tag isn't an image""" if value.kind != mutagen.apev2.BINARY: return type_map = { "cover art (front)": APICType.COVER_FRONT, "cover art (back)": APICType.COVER_BACK, } return type_map.get(key.lower()) def parse_cover(key, value): """Returns a EmbeddedImage or None""" # http://www.hydrogenaud.io/forums/index.php?showtopic=40603 cover_type = get_cover_type(key, value) if cover_type is None: return parts = value.value.split(b"\x00", 1) if len(parts) != 2: return f = get_temp_cover_file(parts[-1]) if not f: return return EmbeddedImage(f, "image/", type_=cover_type) def write_cover(image): """Takes EmbeddedImage and returns a (key, value) tuple Raises: AudioFileError """ if image.type == APICType.COVER_FRONT: key = "Cover Art (Front)" else: key = "Cover Art (Back)" try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) ext = (image.extensions and image.extensions[0]) or "jpg" data = ("hello.%s\x00" % (ext)).encode("ascii") + data value = mutagen.apev2.APEValue(data, mutagen.apev2.BINARY) return (key, value) class APEv2File(AudioFile): # Map APE names to QL names. APE tags are also usually capitalized. # Also blacklist a number of tags. IGNORE = ["file", "index", "introplay", "dummy"] TRANS = {"subtitle": "version", "track": "tracknumber", "disc": "discnumber", "catalog": "labelid", "year": "date", "record location": "location", "album artist": "albumartist", "debut album": "originalalbum", "record date": "recordingdate", "original artist": "originalartist", "mixartist": "remixer", } SNART = dict((v, k) for k, v in TRANS.items()) can_change_images = True def __init__(self, filename, audio=None): if audio: tag = audio.tags or {} else: with translate_errors(): try: tag = mutagen.apev2.APEv2(filename) except mutagen.apev2.APENoHeaderError: tag = {} for key, value in tag.items(): if get_cover_type(key, value) is not None: self.has_images = True key = self.TRANS.get(key.lower(), key.lower()) if (value.kind == mutagen.apev2.TEXT and key not in self.IGNORE): self[key] = "\n".join(list(value)) self.sanitize(filename) @staticmethod def __titlecase(key): if key.lower() in ["isrc", "isbn", "ean/upc"]: return key.upper() else: return key.title() def can_change(self, key=None): if key is None: return True else: return (super().can_change(key) and key.lower() not in self.IGNORE and key.lower() not in self.TRANS and mutagen.apev2.is_valid_apev2_key(self.__titlecase(key))) def write(self): with translate_errors(): try: tag = mutagen.apev2.APEv2(self['~filename']) except mutagen.apev2.APENoHeaderError: tag = mutagen.apev2.APEv2() # Remove any text keys we read in for key in list(tag.keys()): value = tag[key] if (value.kind == mutagen.apev2.TEXT and key.lower() not in self.IGNORE): del(tag[key]) # Write all tags we have lower = self.as_lowercased() for key in lower.realkeys(): new_key = self.SNART.get(key, key) if new_key in self.IGNORE: continue new_key = self.__titlecase(new_key) tag[new_key] = lower.list(key) with translate_errors(): tag.save(self["~filename"]) self.sanitize() def get_primary_image(self): try: tag = mutagen.apev2.APEv2(self['~filename']) except Exception: return primary = None for key, value in tag.items(): primary = (key, value) cover_type = get_cover_type(key, value) if cover_type == APICType.COVER_FRONT: break if primary is not None: return parse_cover(*primary) def get_images(self): try: tag = mutagen.apev2.APEv2(self['~filename']) except Exception: return [] images = [] for key, value in tag.items(): image = parse_cover(key, value) if image is not None: images.append(image) images.sort(key=lambda c: c.sort_key) return images def clear_images(self): with translate_errors(): try: tag = mutagen.apev2.APEv2(self['~filename']) except mutagen.apev2.APENoHeaderError: return for key, value in tag.items(): cover_type = get_cover_type(key, value) if cover_type is not None: del tag[key] tag.save() self.has_images = False def set_image(self, image): with translate_errors(): try: tag = mutagen.apev2.APEv2(self['~filename']) except mutagen.apev2.APENoHeaderError: tag = mutagen.apev2.APEv2() for key, value in tag.items(): cover_type = get_cover_type(key, value) if cover_type is not None: del tag[key] key, value = write_cover(image) tag[key] = value with translate_errors(): tag.save(self['~filename']) self.has_images = True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1677753347.0 quodlibet-4.6.0/quodlibet/formats/_audio.py0000644000175000017500000012361214400076003017457 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2012-2022 Nick Boultbee # 2022 Jej@github # # 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 2 of the License, or # (at your option) any later version. # Much of this code is highly optimized, because many of the functions # are called in tight loops. Don't change things just to make them # more readable, unless they're also faster. import json import os import re import shutil import time from typing import Any, List, Tuple, Generic, TypeVar, Optional from collections import OrderedDict from itertools import zip_longest from senf import fsn2uri, fsnative, fsn2text, bytes2fsn, path2fsn from quodlibet import _, print_d from quodlibet import util from quodlibet import config from quodlibet.util.path import mkdir, mtime, normalize_path, \ ismount, get_home_dir, RootPathFile from quodlibet.util.string import encode, decode, isascii from quodlibet.util.environment import is_windows from quodlibet.util import iso639, cached_property from quodlibet.util import human_sort_key as human, capitalize from quodlibet.util.string.date import format_date from quodlibet.util.tags import TAG_ROLES, TAG_TO_SORT from ._image import ImageContainer from ._misc import AudioFileError, translate_errors translate_errors AlbumKey = Tuple[str, str, str] """An album key is (currently) a tuple""" MIGRATE = {"~#playcount", "~#laststarted", "~#lastplayed", "~#added", "~#skipcount", "~#rating", "~bookmark"} """These get migrated if a song gets reloaded""" PEOPLE = ["artist", "albumartist", "author", "composer", "~performers", "originalartist", "lyricist", "arranger", "conductor"] """Sources of the ~people tag, most important first""" TIME_TAGS = {"~#lastplayed", "~#laststarted", "~#added", "~#mtime"} """Time in seconds since epoch, defaults to 0""" HUMAN_TO_NUMERIC_TIME_TAGS = {t.replace("~#", "~"): t for t in TIME_TAGS} DURATION_TAGS = {"~#length"} """Duration in seconds""" SIZE_TAGS = {"~#filesize"} """Size in bytes, defaults to 0""" NUMERIC_ZERO_DEFAULT = {"~#skipcount", "~#playcount", "~#length", "~#bitrate"} """Defaults to 0""" NUMERIC_ZERO_DEFAULT.update(TIME_TAGS) NUMERIC_ZERO_DEFAULT.update(SIZE_TAGS) FILESYSTEM_TAGS = {"~filename", "~basename", "~dirname", "~mountpoint"} """Values are bytes in Linux instead of unicode""" SORT_TO_TAG = dict((v, k) for (k, v) in TAG_TO_SORT.items()) """Reverse map, so sort tags can fall back to the normal ones""" PEOPLE_SORT = [TAG_TO_SORT.get(k, k) for k in PEOPLE] """Sources for ~peoplesort, most important first""" VARIOUS_ARTISTS_VALUES = 'V.A.', 'various artists', 'Various Artists' """Values for ~people representing lots of people, most important last""" def decode_value(tag, value): """Returns a unicode representation of the passed value, based on the type and the tag it originated from. Not reversible. """ if tag in FILESYSTEM_TAGS: return fsn2text(value) elif tag[:2] == "~#": if isinstance(value, float): return u"%.2f" % value else: return str(value) return str(value) K = TypeVar("K") class HasKey(Generic[K]): """Many things can be keyed""" key: K class AudioFile(dict, ImageContainer, HasKey): """An audio file. It looks like a dict, but implements synthetic and tied tags via __call__ rather than __getitem__. This means __getitem__, get, and so on can be used for efficiency. If you need to sort many AudioFiles, you can use their sort_key attribute as a decoration. Keys are either ASCII str or unicode. Values are always unicode except if the tag is part of FILESYSTEM_TAGS, then the value is of the path type (str on UNIX, unicode on Windows) Some methods will make sure the returned values are always unicode, see their description. """ fill_metadata = False """New tags received from the backend will update the song""" fill_length = False """New song duration from the backend will update the song""" multisong = False """Is a container for multiple songs i.e. while played new songs can start / end""" streamsong = False """Is part of a multisong""" can_add = True """Can be added to the queue, playlists""" is_file = True """Is a real (local) file""" format = "Unknown Audio File" """The underlying file format""" supports_rating_and_play_count_in_file = False """Does this format support storing ratings and play counts in the file""" mimes: List[str] = [] """MIME types this class can represent""" @cached_property def _date_format(self) -> str: return config.gettext("settings", "datecolumn_timestamp_format") def __init__(self, default=tuple(), **kwargs): for key, value in dict(default).items(): self[key] = value for key, value in kwargs.items(): self[key] = value def __song_key(self): return (self("~#disc", 0), self("~#track", 0), human(self("artistsort")), self.get("musicbrainz_artistid", ""), human(self.get("title", "")), self.get("~filename")) @util.cached_property def album_key(self) -> AlbumKey: id_val: str = (self.get("album_grouping_key") or self.get("labelid") or self.get("musicbrainz_albumid", "")) # type: ignore return id_val, human(self("albumsort", "")), human(self("albumartistsort", "")) @util.cached_property def sort_key(self): return [self.album_key, self.__song_key()] @staticmethod def sort_by_func(tag): """Returns a fast sort function for a specific tag (or pattern). Some keys are already in the sort cache, so we can use them.""" def artist_sort(song): return song.sort_key[1][2] if callable(tag): return lambda song: human(tag(song)) elif tag == "artistsort": return artist_sort elif tag in FILESYSTEM_TAGS: return lambda song: fsn2text(song(tag)) elif tag.startswith("~#") and "~" not in tag[2:]: return lambda song: song(tag, 0) return lambda song: human(song(tag)) def __getstate__(self): """Don't pickle anything from __dict__""" pass def __setstate__(self, state): """Needed because we have defined getstate""" pass def __setitem__(self, key, value): # validate key if not isinstance(key, str): raise TypeError("key has to be str") # validate value if key.startswith("~#"): if not isinstance(value, (int, float)): raise TypeError elif key in FILESYSTEM_TAGS: if not isinstance(value, fsnative): value = path2fsn(value) else: value = str(value) dict.__setitem__(self, key, value) pop = self.__dict__.pop pop("album_key", None) pop("sort_key", None) def __delitem__(self, key): dict.__delitem__(self, key) pop = self.__dict__.pop pop("album_key", None) pop("sort_key", None) @property def key(self) -> K: # type: ignore return self["~filename"] @property def mountpoint(self): return self["~mountpoint"] def __hash__(self): # Dicts aren't hashable by default, so we need a hash # function. Previously this used ~filename. That created a # situation when an object could end up in two buckets by # renaming files. So now it uses identity. return hash(id(self)) def __eq__(self, other): # And to preserve Python hash rules, we need a strict __eq__. return self is other def __lt__(self, other): return self.sort_key < other.sort_key def __ne__(self, other): return self is not other def has_rating_and_playcount_in_file(self, email): """Returns True if the audio file has rating and play counts for the provided email. Returns False otherwise, or if storing ratings and play counts in the file is not supported for this audio format. """ return False def reload(self): """Reload an audio file from disk. If reloading fails nothing will change. Raises: AudioFileError: if the file fails to load """ backup = dict(self) fn = self["~filename"] saved = {} persisted = config.getboolean("editing", "save_to_songs") persisted_keys = ({"~#rating", "~#playcount"} if self.supports_rating_and_play_count_in_file and persisted else set()) for key in self: # Only migrate keys that aren't (probably) persisted to file (#3569) if key in MIGRATE - persisted_keys: saved[key] = self[key] self.clear() self["~filename"] = fn try: self.__init__(fn) except AudioFileError: self.update(backup) raise else: self.update(saved) def realkeys(self): """Returns a list of keys that are not internal, i.e. they don't have '~' in them.""" return [s for s in self.keys() if s[:1] != "~"] def prefixkeys(self, prefix): """Returns a list of dict keys that either match prefix or start with prefix + ':'. """ l = [] for k in self: if k.startswith(prefix): if k == prefix or k.startswith(prefix + ":"): l.append(k) return l def _prefixvalue(self, tag): return "\n".join(self.list_unique(sorted(self.prefixkeys(tag)))) def iterrealitems(self): return ((k, v) for (k, v) in self.items() if k[:1] != "~") def __call__(self, key, default: Any = u"", connector=" - ", joiner=', '): """Return the value(s) for a key, synthesizing if necessary. Multiple values for a key are delimited by newlines. A default value may be given (like `dict.get`); the default default is an empty unicode string (even if the tag is numeric). If a tied tag ('a~b') is requested, the `connector` keyword argument may be used to specify what it is tied with. In case the tied tag contains numeric and file path tags, the result will still be a unicode string. The `joiner` keyword specifies how multiple *values* will be joined within that tied tag output, e.g. ~people~title = "Kanye West, Jay Z - New Day" For details on tied tags, see the documentation for `util.tagsplit`. """ real_key = key if key[:1] == "~": key = key[1:] if "~" in key: values = [] sub_tags = util.tagsplit(real_key) # If it's genuinely a tied tag (not ~~people etc.), we want # to delimit the multi-values separately from the tying j = joiner if len(sub_tags) > 1 else "\n" for t in sub_tags: vs = [decode_value(real_key, v) for v in (self.list(t))] v = j.join(vs) if v: values.append(v) return connector.join(values) or default elif key == "#track": try: return int(self["tracknumber"].split("/")[0]) except (ValueError, TypeError, KeyError): return default elif key == "#disc": try: return int(self["discnumber"].split("/")[0]) except (ValueError, TypeError, KeyError): return default elif key == "length": length = self.get("~#length") if length is None: return default else: return util.format_time_display(length) elif key == "#rating": return dict.get(self, real_key, config.RATINGS.default) elif key == "rating": return util.format_rating(self("~#rating")) elif key == "people": return "\n".join(self.list_unique(PEOPLE)) or default elif key == "people:real": # Issue 1034: Allow removal of V.A. if others exist. unique = self.list_unique(PEOPLE) # Order is important, for (unlikely case): multiple removals for val in VARIOUS_ARTISTS_VALUES: if len(unique) > 1 and val in unique: unique.remove(val) return "\n".join(unique) or default elif key == "people:roles": return (self._role_call("performer", PEOPLE) or default) elif key == "peoplesort": return ("\n".join(self.list_unique(PEOPLE_SORT)) or self("~people", default, connector)) elif key == "peoplesort:roles": # Ignores non-sort tags if there are any sort tags (e.g. just # returns "B" for {artist=A, performersort=B}). # TODO: figure out the "correct" behavior for mixed sort tags return (self._role_call("performersort", PEOPLE_SORT) or self("~peoplesort", default, connector)) elif key in ("performers", "performer"): return self._prefixvalue("performer") or default elif key in ("performerssort", "performersort"): return (self._prefixvalue("performersort") or self(real_key[-4:], default, connector)) elif key in ("performers:roles", "performer:roles"): return (self._role_call("performer") or default) elif key in ("performerssort:roles", "performersort:roles"): return (self._role_call("performersort") or self(real_key.replace("sort", ""), default, connector)) elif key == "basename": return os.path.basename(self["~filename"]) or self["~filename"] elif key == "dirname": return os.path.dirname(self["~filename"]) or self["~filename"] elif key == "uri": try: return self["~uri"] except KeyError: return fsn2uri(self["~filename"]) elif key == "format": return self.get("~format", str(self.format)) elif key == "codec": codec = self.get("~codec") if codec is None: return self("~format") return codec elif key == "encoding": encoding = "\n".join( part for part in [self.get("~encoding"), self.get("encodedby")] if part ) return encoding or default elif key == "language": codes = self.list("language") if not codes: return default return u"\n".join(iso639.translate(c) or c for c in codes) elif key == "bitrate": return util.format_bitrate(self("~#bitrate")) elif key == "#date": date = self.get("date") if date is None: return default return util.date_key(date) elif key == "year": return self.get("date", default)[:4] elif key == "#year": try: return int(self.get("date", default)[:4]) except (ValueError, TypeError, KeyError): return default elif key == "originalyear": return self.get("originaldate", default)[:4] elif key == "#originalyear": try: return int(self.get("originaldate", default)[:4]) except (ValueError, TypeError, KeyError): return default elif key == "#tracks": try: return int(self["tracknumber"].split("/")[1]) except (ValueError, IndexError, TypeError, KeyError): return default elif key == "#discs": try: return int(self["discnumber"].split("/")[1]) except (ValueError, IndexError, TypeError, KeyError): return default elif key == "lyrics": # First, try the embedded lyrics. try: return self["lyrics"] except KeyError: pass try: return self["unsyncedlyrics"] except KeyError: pass # If there are no embedded lyrics, try to read them from # the external file. lyric_filename = self.lyric_filename if not lyric_filename: return default try: with open(lyric_filename, "rb") as fileobj: print_d(f"Reading lyrics from {lyric_filename!r}") text = fileobj.read().decode("utf-8", "replace") # try to skip binary files if "\0" in text: return default return text except (EnvironmentError, UnicodeDecodeError): return default elif key == "filesize": return util.format_size(self("~#filesize", 0)) elif key == "playlists": # TODO: avoid static dependency here... somehow from quodlibet import app lib = app.library if not lib: return "" playlists = lib.playlists.playlists_featuring(self) return "\n".join(s.name for s in playlists) or default elif key.startswith("#replaygain_"): try: val = self.get(key[1:], default) return round(float(val.split(" ")[0]), 2) except (ValueError, TypeError, AttributeError): return default elif real_key in HUMAN_TO_NUMERIC_TIME_TAGS: time_value = float(self.get(HUMAN_TO_NUMERIC_TIME_TAGS[real_key], 0)) return format_date(time_value, self._date_format) elif key[:1] == "#": if real_key in self: return self[real_key] elif real_key in NUMERIC_ZERO_DEFAULT: return 0 else: try: val = self[real_key[2:]] except KeyError: return default try: return int(val) except ValueError: try: return float(val) except ValueError: return default elif key == "json": # Help the testing by being deterministic with sort_keys. return json.dumps(self, sort_keys=True) else: return dict.get(self, real_key, default) elif key == "title": title = dict.get(self, "title") if title is None: # build a title with missing_title_template option unknown_track_template = _(config.gettext( "browsers", "missing_title_template")) from quodlibet.pattern import Pattern try: pattern = Pattern(unknown_track_template) except ValueError: title = decode_value("~basename", self("~basename")) else: title = pattern % self return title elif key in SORT_TO_TAG: try: return self[key] except KeyError: key = SORT_TO_TAG[key] return dict.get(self, key, default) def _role_call(self, role_tag, sub_keys=None): role_tag_keys = self.prefixkeys(role_tag) role_map = {} for key in role_tag_keys: if key == role_tag: # #2986: don't add a role description for the bare tag, unless # this is a composite tag (e.g. only show "(Performance)" for # ~people:roles and not ~performer:roles). if sub_keys is None: continue else: role = TAG_ROLES.get(role_tag, role_tag) else: role = key.split(":", 1)[-1] for name in self.list(key): role_map.setdefault(name, []).append(role) if sub_keys is None: names = self.list_unique(role_tag_keys) else: names = self.list_unique(sub_keys) for tag in sub_keys: if tag in TAG_ROLES: for name in self.list(tag): role_map.setdefault(name, []).append(TAG_ROLES[tag]) descs = [] for name in names: roles = role_map.get(name, []) if not roles: descs.append(name) else: roles = sorted(map(capitalize, roles)) descs.append("%s (%s)" % (name, ", ".join(roles))) return "\n".join(descs) @property def lyric_filename(self) -> Optional[str]: """Returns the validated, or default, lyrics filename for this file. User defined '[memory] lyric_rootpaths' and '[memory] lyric_filenames' matches take precedence""" from quodlibet.pattern \ import ArbitraryExtensionFileFromPattern as expand_patterns rx_params = re.compile(r'[^\\]<[^' + re.escape(os.sep) + r']*[^\\]>') def expand_pathfile(rpf): """Return the expanded RootPathFile""" expanded = [] root = os.path.expanduser(rpf.root) pathfile = os.path.expanduser(rpf.pathfile) if rx_params.search(pathfile): root = expand_patterns(root).format(self) pathfile = expand_patterns(pathfile).format(self) rpf = RootPathFile(root, pathfile) expanded.append(rpf) if not os.path.exists(pathfile) and is_windows(): # prioritise a special character encoded version # # most 'alien' chars are supported for 'nix fs paths, and we # only pass the proposed path through 'escape_filename' (which # apparently doesn't respect case) if we don't care about case! # # FIX: assumes 'nix build used on a case-sensitive fs, nt case # insensitive. clearly this is not biting anyone though (yet!) pathfile = os.path.sep.join([rpf.root, rpf.end_escaped]) rpf = RootPathFile(rpf.root, pathfile) expanded.insert(len(expanded) - 1, rpf) return expanded def sanitise(sep, parts): """Return a sanitised version of a path's parts""" return sep.join(part.replace(os.path.sep, u'')[:128] for part in parts) # setup defaults (user-defined take precedence) # root search paths lyric_paths = config.getstringlist("memory", "lyric_rootpaths", []) # ensure default paths lyric_paths.append(os.path.join(get_home_dir(), ".lyrics")) lyric_paths.append(os.path.join(os.path.dirname(self.comma('~filename')))) # search pathfile names lyric_filenames = config.getstringlist("memory", "lyric_filenames", []) # ensure some default pathfile names lyric_filenames.append( sanitise(os.sep, [(self.comma("lyricist") or self.comma("artist")), self.comma("title")]) + u'.lyric') lyric_filenames.append( sanitise(' - ', [(self.comma("lyricist") or self.comma("artist")), self.comma("title")]) + u'.lyric') # generate all potential paths (unresolved/unexpanded) pathfiles = OrderedDict() for r in lyric_paths: for f in lyric_filenames: pathfile = os.path.join(r, os.path.dirname(f), fsnative(os.path.basename(f))) rpf = RootPathFile(r, pathfile) if not pathfile in pathfiles: pathfiles[pathfile] = rpf #print_d("searching for lyrics in:\n%s" % '\n'.join(pathfiles.keys())) # expand each raw pathfile in turn and test for existence match_ = None pathfiles_expanded = OrderedDict() for pf, rpf in pathfiles.items(): for rpf in expand_pathfile(rpf): # resolved as late as possible pathfile = rpf.pathfile pathfiles_expanded[pathfile] = rpf if os.path.exists(pathfile): match_ = pathfile break if match_: break if not match_: # search even harder! lyric_extensions = ['lyric', 'lyrics', '', 'txt'] #print_d("extending search to extensions: %s" % lyric_extensions) def generate_mod_ext_paths(pathfile): # separate pathfile's extension (if any) ext = os.path.splitext(pathfile)[1][1:] path = pathfile[:-1 * len(ext)].strip('.') if ext else pathfile # skip the proposed lyric extension if it is the same as # the original for a given search pathfile stub - it has # already been tested without success! extra_extensions = [x for x in lyric_extensions if x != ext] # join valid new extensions to pathfile stub and return return ['.'.join([path, ext]) if ext else path for ext in extra_extensions] # look for a match by modifying the extension for each of the # (now fully resolved) 'pathfiles_expanded' search items for pathfile in pathfiles_expanded.keys(): # get alternatives for existence testing paths_mod_ext = generate_mod_ext_paths(pathfile) for path_ext in paths_mod_ext: if os.path.exists(path_ext): # persistence has paid off! #print_d("extended search match!") match_ = path_ext break if match_: break if not match_: # default match_ = list(pathfiles_expanded.keys())[0] return match_ @property def has_rating(self): """True if the song has a rating set. In case this is False song('~#rating') would return the default value """ return self.get("~#rating") is not None def remove_rating(self): """Removes the set rating so the default will be returned""" self.pop("~#rating", None) def comma(self, key): """Get all values of a tag, separated by commas. Synthetic tags are supported, but will be slower. All list items will be unicode. If the value is numeric, that is returned rather than a list. Because this function is used to format values for display, blank tags are removed from the results. """ if "~" in key or key == "title": if key in FILESYSTEM_TAGS: v = fsn2text(self(key, fsnative())) else: v = self(key, u"") else: v = self.get(key, u"") if isinstance(v, (int, float)): return v else: return re.sub("\n+", ", ", v.strip()) def list(self, key): """Get all values of a tag, as a list. Synthetic tags are supported, but will be slower. Numeric tags will give their one value. For file path keys the returned list might contain path items (non-unicode). An empty tag cannot be distinguished from a non-existent tag; both result in []. If a file contains multiple values of a tag, empty instances of the tag will not be included in the list. """ if "~" in key or key == "title": v = self(key) if v == "": return [] else: v = v.split("\n") if isinstance(v, str) else [v] return [x for x in v if x] else: v = self.get(key, "") return [x for x in v.split("\n") if x] def list_sort(self, key): """Like list but return display,sort pairs when appropriate and work on all tags. In case no sort value exists the display one is returned. If a display tag is empty, the tag is removed from the returned list and the corresponding tag in the sort tag list is ignored as well. The assumption being made here is that if the ordering between display and sort tags doesn't match exactly, that's a problem with the user's file. """ display = decode_value(key, self(key)) display = display.split("\n") if display else [] sort = [] if key in TAG_TO_SORT: sort = decode_value(TAG_TO_SORT[key], self(TAG_TO_SORT[key])) # it would be better to use something that doesn't fall back # to the key itself, but what? sort = sort.split("\n") if sort else [] result = [] for d, s in zip_longest(display, sort): if d: result.append((d, (s if s is not None and s != "" else d))) return result def list_separate(self, key): """For tied tags return the list union of the display,sort values otherwise just do list_sort """ if key[:1] == "~" and "~" in key[1:]: # tied tag vals = [self.list_sort(tag) for tag in util.tagsplit(key)] r = [j for i in vals for j in i] return r else: return self.list_sort(key) def list_unique(self, keys): """Returns a combined value of all values in keys; duplicate values will be ignored. Returns the same as list(). """ l = [] seen = set() for k in keys: for v in self.list(k): if v not in seen: l.append(v) seen.add(v) return l def as_lowercased(self): """Returns a new AudioFile with all keys lowercased / values merged. Useful for tag writing for case insensitive tagging formats like APEv2 or VorbisComment. """ merged = AudioFile() text = {} for key, value in self.items(): lower = key.lower() if key.startswith("~#"): merged[lower] = value else: text.setdefault(lower, []).extend(value.split("\n")) for key, values in text.items(): merged[key] = "\n".join(values) return merged def exists(self): """Return true if the file still exists (or we can't tell).""" return os.path.exists(self["~filename"]) def valid(self): """Return true if the file cache is up-to-date (checked via mtime), or we can't tell.""" return (bool(self.get("~#mtime", 0)) and self["~#mtime"] == mtime(self["~filename"])) def mounted(self): """Return true if the disk the file is on is mounted, or the file is not on a disk.""" return ismount(self.get("~mountpoint", "/")) def can_multiple_values(self, key=None): """If no arguments are given, return a list of tags that can have multiple values, or True if 'any' tags can. """ return True def can_change(self, k=None): """See if this file supports changing the given tag. This may be a limitation of the file type or QL's design. The writing code should handle all kinds of keys, so this is just a suggestion. If no arguments are given, return a list of tags that can be changed, or True if 'any' tags can be changed (specific tags should be checked before adding).""" if k is None: return True if not isascii(k): return False if not k or "=" in k or "~" in k: return False return True def is_writable(self): return os.access(self["~filename"], os.W_OK) def rename(self, newname): """Rename a file. Errors are not handled. This shouldn't be used directly; use library.rename instead.""" if os.path.isabs(newname): mkdir(os.path.dirname(newname)) else: newname = os.path.join(self('~dirname'), newname) if not os.path.exists(newname): shutil.move(self['~filename'], newname) elif normalize_path(newname, canonicalise=True) != self['~filename']: raise ValueError self.sanitize(newname) def sanitize(self, filename=None): """Fill in metadata defaults. Find ~mountpoint, ~#mtime, ~#filesize and ~#added. Check for null bytes in tags. Does not raise. """ # Replace nulls with newlines, trimming zero-length segments for key, val in list(self.items()): self[key] = val if isinstance(val, str) and '\0' in val: self[key] = '\n'.join(filter(lambda s: s, val.split('\0'))) # Remove unnecessary defaults if key in NUMERIC_ZERO_DEFAULT and val == 0: del self[key] if filename: self["~filename"] = filename elif "~filename" not in self: raise ValueError("Unknown filename!") assert isinstance(self["~filename"], fsnative) if self.is_file: self["~filename"] = normalize_path( self["~filename"], canonicalise=True) # Find mount point (terminating at "/" if necessary) head = self["~filename"] while "~mountpoint" not in self: head, tail = os.path.split(head) # Prevent infinite loop without a fully-qualified filename # (the unit tests use these). head = head or fsnative(u"/") if ismount(head): self["~mountpoint"] = head else: self["~mountpoint"] = fsnative(u"/") # Fill in necessary values. self.setdefault("~#added", int(time.time())) # For efficiency, do a single stat here. See Issue 504 try: stat = os.stat(self['~filename']) self["~#mtime"] = stat.st_mtime self["~#filesize"] = stat.st_size # Issue 342. This is a horrible approximation (due to headers) but # on FLACs, the most common case, this should be close enough if "~#bitrate" not in self: try: # kbps = bytes * 8 / seconds / 1000 self["~#bitrate"] = int(stat.st_size / (self["~#length"] * (1000 / 8))) except (KeyError, ZeroDivisionError): pass except OSError: self["~#mtime"] = 0 def to_dump(self): """A string of 'key=value' lines, similar to vorbiscomment output. Returns: bytes """ def encode_key(k): return encode(k) if isinstance(k, str) else k s = [] for k in self.keys(): enc_key = encode_key(k) assert isinstance(enc_key, bytes) if isinstance(self[k], int): l = enc_key + encode("=%d" % self[k]) s.append(l) elif isinstance(self[k], float): l = enc_key + encode("=%f" % self[k]) s.append(l) else: for v2 in self.list(k): if not isinstance(v2, bytes): v2 = encode(v2) s.append(enc_key + b"=" + v2) for k in (NUMERIC_ZERO_DEFAULT - set(self.keys())): enc_key = encode_key(k) l = enc_key + encode("=%d" % self.get(k, 0)) s.append(l) if "~#rating" not in self: s.append(encode("~#rating=%f" % self("~#rating"))) s.append(encode("~format=%s" % self.format)) s.append(b"") return b"\n".join(s) def from_dump(self, text): """Parses the text created with to_dump and adds the found tags. Args: text (bytes) """ for line in text.split(b"\n"): if not line: continue parts = line.split(b"=") key = decode(parts[0]) val = b"=".join(parts[1:]) if key == "~format": pass elif key in FILESYSTEM_TAGS: self.add(key, bytes2fsn(val, "utf-8")) elif key.startswith("~#"): try: self.add(key, int(val)) except ValueError: try: self.add(key, float(val)) except ValueError: pass else: self.add(key, decode(val)) def change(self, key, old_value, new_value): """Change 'old_value' to 'new_value' for the given metadata key. If the old value is not found, set the key to the new value.""" try: parts = self.list(key) try: parts[parts.index(old_value)] = new_value except ValueError: self[key] = new_value else: self[key] = "\n".join(parts) except KeyError: self[key] = new_value def add(self, key, value): """Add a value for the given metadata key.""" if key not in self: self[key] = value else: self[key] += "\n" + value def remove(self, key, value=None): """Remove a value from the given key. If value is None remove all values for that key, if it exists. If the key or value is not found, do nothing. """ if key not in self: return elif value is None or self[key] == value: del self[key] else: try: parts = self.list(key) parts.remove(value) self[key] = u"\n".join(parts) except ValueError: pass def replay_gain(self, profiles, pre_amp_gain=0, fallback_gain=0): """Return the computed Replay Gain scale factor. profiles is a list of Replay Gain profile names ('album', 'track') to try before giving up. The special profile name 'none' will cause no scaling to occur. pre_amp_gain will be applied before checking for clipping. fallback_gain will be used when the song does not have replaygain information. """ for profile in profiles: if profile == "none": return 1.0 try: db = float(self["replaygain_%s_gain" % profile].split()[0]) peak = float(self.get("replaygain_%s_peak" % profile, 1)) except (KeyError, ValueError, IndexError): continue else: db += pre_amp_gain try: scale = 10. ** (db / 20) except OverflowError: scale = 1.0 / peak else: if scale * peak > 1: scale = 1.0 / peak # don't clip return min(15, scale) else: try: scale = 10. ** ((fallback_gain + pre_amp_gain) / 20) except OverflowError: scale = 1.0 else: scale = min(scale, 1.0) return min(15, scale) def write(self): """Write metadata back to the file. Raises: AudioFileError: in case writing fails """ raise NotImplementedError @property def bookmarks(self): """Parse and return song position bookmarks, or set them. Accessing this returns a copy, so song.bookmarks.append(...) will not work; you need to do marks = song.bookmarks marks.append(...) song.bookmarks = marks """ marks = [] invalid = [] for line in self.list("~bookmark"): try: time, mark = line.split(" ", 1) except: invalid.append((-1, line)) else: try: time = util.parse_time(time, None) except: invalid.append((-1, line)) else: if time >= 0: marks.append((time, mark)) else: invalid.append((-1, line)) marks.sort() marks.extend(invalid) return marks @bookmarks.setter def bookmarks(self, marks): result = [] for time_, mark in marks: if time_ < 0: raise ValueError("mark times must be positive") result.append(u"%s %s" % (util.format_time(time_), mark)) result = u"\n".join(result) if result: self["~bookmark"] = result elif "~bookmark" in self: del(self["~bookmark"]) # Looks like the real thing. DUMMY_SONG = AudioFile({ '~#length': 234, '~filename': os.devnull, 'artist': 'The Artist', 'album': 'An Example Album', 'title': 'First Track', 'tracknumber': 1, 'date': '2010-12-31', }) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1684322551.0 quodlibet-4.6.0/quodlibet/formats/_id3.py0000644000175000017500000004455614431134367017062 0ustar00nicknick# Copyright 2004-2020 Joe Wreschnig, Michael Urman, Niklas Janlert, # Steven Robertson, Nick Boultbee, h88e22dgpeps56sg # # 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 2 of the License, or # (at your option) any later version. from typing import Optional, Type import mutagen.id3 from quodlibet import config, const, print_w from quodlibet import util from quodlibet.util.iso639 import ISO_639_2 from quodlibet.util.path import get_temp_cover_file from quodlibet.util.string import isascii from ._audio import AudioFile, translate_errors, AudioFileError from ._image import EmbeddedImage, APICType def encoding_for(s): """Returns ID3 encoding ID best for string `s`""" return 3 if isascii(s) else 1 RG_KEYS = { "replaygain_track_peak", "replaygain_track_gain", "replaygain_album_peak", "replaygain_album_gain", } # ID3 is absolutely the worst thing ever. class ID3File(AudioFile): supports_rating_and_play_count_in_file = True # http://www.unixgods.org/~tilo/ID3/docs/ID3_comparison.html # http://www.id3.org/id3v2.4.0-frames.txt IDS = {"TIT1": "grouping", "TIT2": "title", "TIT3": "version", "TPE1": "artist", "TPE2": "performer", "TPE3": "conductor", "TPE4": "arranger", "TEXT": "lyricist", "TCOM": "composer", "TENC": "encodedby", "TALB": "album", "TRCK": "tracknumber", "TPOS": "discnumber", "TSRC": "isrc", "TCOP": "copyright", "TPUB": "organization", "TSST": "discsubtitle", "TOLY": "author", "TMOO": "mood", "TBPM": "bpm", "TDRC": "date", "TDOR": "originaldate", "TOAL": "originalalbum", "TOPE": "originalartist", "WOAR": "website", "TSOP": "artistsort", "TSOA": "albumsort", "TSOT": "titlesort", "TSO2": "albumartistsort", "TSOC": "composersort", "TMED": "media", "TCMP": "compilation", "TKEY": "initialkey", # TLAN requires an ISO 639-2 language code, check manually #"TLAN": "language" } SDI = dict((v, k) for k, v in IDS.items()) # At various times, information for this came from # http://musicbrainz.org/docs/specs/metadata_tags.html # http://bugs.musicbrainz.org/ticket/1383 # http://musicbrainz.org/doc/MusicBrainzTag TXXX_MAP = { u"MusicBrainz Release Group Id": "musicbrainz_releasegroupid", u"MusicBrainz Release Track Id": "musicbrainz_releasetrackid", u"MusicBrainz Artist Id": "musicbrainz_artistid", u"MusicBrainz Album Id": "musicbrainz_albumid", u"MusicBrainz Album Artist Id": "musicbrainz_albumartistid", u"MusicBrainz TRM Id": "musicbrainz_trmid", u"MusicIP PUID": "musicip_puid", u"MusicMagic Fingerprint": "musicip_fingerprint", u"MusicBrainz Album Status": "musicbrainz_albumstatus", u"MusicBrainz Album Type": "musicbrainz_albumtype", u"MusicBrainz Album Release Country": "releasecountry", u"MusicBrainz Disc Id": "musicbrainz_discid", u"ASIN": "asin", u"ALBUMARTISTSORT": "albumartistsort", u"BARCODE": "barcode", } PAM_XXXT = dict((v, k) for k, v in TXXX_MAP.items()) Kind: Optional[Type[mutagen.FileType]] = None def __init__(self, filename): with translate_errors(): audio = self.Kind(filename) if audio.tags is None: audio.add_tags() tag = audio.tags self._parse_info(audio.info) for frame in tag.values(): if frame.FrameID == "APIC" and len(frame.data): self.has_images = True continue elif frame.FrameID == "TCON": self["genre"] = "\n".join(frame.genres) continue elif (frame.FrameID == "UFID" and frame.owner == "http://musicbrainz.org"): self["musicbrainz_trackid"] = frame.data.decode("utf-8", "replace") continue elif frame.FrameID == "POPM": rating = frame.rating / 255.0 if frame.email == const.EMAIL: try: self.setdefault("~#playcount", frame.count) except AttributeError: pass self.setdefault("~#rating", rating) elif frame.email == config.get("editing", "save_email"): try: self["~#playcount"] = frame.count except AttributeError: pass self["~#rating"] = rating continue elif frame.FrameID == "COMM" and frame.desc == "": name = "comment" elif frame.FrameID in ["COMM", "TXXX"]: if frame.desc.startswith("QuodLibet::"): name = frame.desc[11:] elif frame.desc in self.TXXX_MAP: name = self.TXXX_MAP[frame.desc] else: continue elif frame.FrameID == "RVA2": self.__process_rg(frame) continue elif frame.FrameID == "TMCL": for role, name in frame.people: key = self.__validate_name("performer:" + role) if key: self.add(key, name) continue elif frame.FrameID == "TLAN": self["language"] = "\n".join(frame.text) continue elif frame.FrameID == "USLT": name = "lyrics" else: name = self.IDS.get(frame.FrameID, "").lower() name = self.__validate_name(name) if not name: continue name = name.lower() id3id = frame.FrameID if id3id.startswith("T"): text = "\n".join(map(str, frame.text)) elif id3id == "COMM": text = "\n".join(frame.text) elif id3id == "USLT": # lyrics are single string, not list text = frame.text self["~lyricsdescription"] = frame.desc self["~lyricslanguage"] = frame.lang elif id3id.startswith("W"): text = frame.url frame.encoding = 0 else: continue if not text: continue text = self.__distrust_latin1(text, frame.encoding) if text is None: continue if name in self: self[name] += "\n" + text else: self[name] = text self[name] = self[name].strip() # to catch a missing continue above del name # foobar2000 writes long dates in a TXXX DATE tag, leaving the TDRC # tag out. Read the TXXX DATE, but only if the TDRC tag doesn't exist # to avoid reverting or duplicating tags in existing libraries. if audio.tags and "date" not in self: for frame in tag.getall('TXXX:DATE'): self["date"] = "\n".join(map(str, frame.text)) # Read TXXX replaygain and replace previously read values from RVA2 for frame in tag.getall("TXXX"): k = frame.desc.lower() if k in RG_KEYS: self[str(k)] = u"\n".join(map(str, frame.text)) self.sanitize(filename) def _parse_info(self, info): """Optionally implement in subclasses""" pass def __validate_name(self, k): """Returns an ascii string or None if the key isn't supported""" if not k or "=" in k or "~" in k: return if not (k and "=" not in k and "~" not in k and k.encode("ascii", "replace").decode("ascii") == k): return return k def __process_rg(self, frame): if frame.channel == 1: if frame.desc == "album": k = "album" elif frame.desc == "track": k = "track" elif "replaygain_track_gain" not in self: k = "track" # fallback else: return self["replaygain_%s_gain" % k] = "%+f dB" % frame.gain self["replaygain_%s_peak" % k] = str(frame.peak) @util.cached_property def CODECS(self): codecs = ["utf-8"] codecs_conf = config.get("editing", "id3encoding") codecs.extend(codecs_conf.strip().split()) codecs.append("iso-8859-1") return codecs def __distrust_latin1(self, text, encoding): assert isinstance(text, str) if encoding == 0: try: text = text.encode('iso-8859-1') except UnicodeEncodeError: # mutagen might give us text not matching the encoding # https://github.com/quodlibet/mutagen/issues/307 return text for codec in self.CODECS: try: text = text.decode(codec) except (UnicodeError, LookupError): pass else: break else: return None return text def has_rating_and_playcount_in_file(self, email): with translate_errors(): audio = self.Kind(self['~filename']) if audio.tags is None: return False return ("POPM:" + email) in audio.tags def write(self): with translate_errors(): audio = self.Kind(self['~filename']) if audio.tags is None: audio.add_tags() tag = audio.tags # prefill TMCL with the ones we can't read mcl = tag.get("TMCL", mutagen.id3.TMCL(encoding=3, people=[])) mcl.people = [(r, n) for (r, n) in mcl.people if not self.__validate_name(r)] # delete all TXXX/COMM we can read except empty COMM for frame in ["COMM:", "TXXX:"]: for t in tag.getall(frame + "QuodLibet:"): if t.desc and self.__validate_name(t.desc): del tag[t.HashKey] for key in ["UFID:http://musicbrainz.org", "TMCL", "POPM:%s" % const.EMAIL, "POPM:%s" % config.get("editing", "save_email")]: if key in tag: del(tag[key]) for key, id3name in self.SDI.items(): tag.delall(id3name) if key not in self: continue enc = encoding_for(self[key]) Kind = mutagen.id3.Frames[id3name] text = self[key].split("\n") if id3name == "WOAR": for t in text: tag.add(Kind(url=t)) else: tag.add(Kind(encoding=enc, text=text)) dont_write = (RG_KEYS | set(self.TXXX_MAP.values()) | {"genre", "comment", "musicbrainz_trackid", "lyrics"}) if "musicbrainz_trackid" in self.realkeys(): f = mutagen.id3.UFID( owner="http://musicbrainz.org", data=self["musicbrainz_trackid"].encode("utf-8")) tag.add(f) # Issue 439 - Only write valid ISO 639-2 codes to TLAN (else TXXX) tag.delall("TLAN") if "language" in self: langs = self["language"].split("\n") if all([lang in ISO_639_2 for lang in langs]): # Save value(s) to TLAN tag. Guaranteed to be ASCII here tag.add(mutagen.id3.TLAN(encoding=3, text=langs)) dont_write.add("language") else: print_w( f"Not using invalid language {self['language']!r} in TLAN") # Filter out known keys, and ones set not to write [generically]. dont_write |= self.SDI.keys() keys_to_write = (k for k in self.realkeys() if k not in dont_write) for key in keys_to_write: enc = encoding_for(self[key]) if key.startswith("performer:"): mcl.people.append((key.split(":", 1)[1], self[key])) continue f = mutagen.id3.TXXX( encoding=enc, text=self[key].split("\n"), desc=u"QuodLibet::%s" % key) tag.add(f) if mcl.people: tag.add(mcl) if "genre" in self: enc = encoding_for(self["genre"]) t = self["genre"].split("\n") tag.add(mutagen.id3.TCON(encoding=enc, text=t)) else: try: del(tag["TCON"]) except KeyError: pass tag.delall("COMM:") if "comment" in self: enc = encoding_for(self["comment"]) t = self["comment"].split("\n") tag.add(mutagen.id3.COMM(encoding=enc, text=t, desc=u"", lang="\x00\x00\x00")) tag.delall("USLT") if "lyrics" in self: enc = encoding_for(self["lyrics"]) if not ("~lyricslanguage" in self and # language has to be a 3 byte ISO 639-2 code self["~lyricslanguage"] in ISO_639_2): self["~lyricslanguage"] = "und" # undefined # lyrics are single string, not array tag.add(mutagen.id3.USLT(encoding=enc, text=self["lyrics"], desc=self.get("~lyricsdescription", ""), lang=self["~lyricslanguage"])) # Delete old foobar replaygain .. for frame in tag.getall("TXXX"): if frame.desc.lower() in RG_KEYS: del tag[frame.HashKey] # .. write new one for k in RG_KEYS: # Add new ones if k in self: value = self[k] tag.add(mutagen.id3.TXXX(encoding=encoding_for(value), text=value.split("\n"), desc=k.upper())) # we shouldn't delete all, but we use unknown ones as fallback, so make # sure they don't come back after reloading for t in tag.getall("RVA2"): if t.channel == 1: del tag[t.HashKey] for k in ["track", "album"]: if ('replaygain_%s_gain' % k) in self: try: gain = float(self["replaygain_%s_gain" % k].split()[0]) except (ValueError, IndexError): gain = 0 try: peak = float(self["replaygain_%s_peak" % k]) except (ValueError, KeyError): peak = 0 # https://github.com/quodlibet/quodlibet/issues/1027 peak = max(min(1.9, peak), 0) gain = max(min(63.9, gain), -64) f = mutagen.id3.RVA2(desc=k, channel=1, gain=gain, peak=peak) tag.add(f) for key in self.TXXX_MAP: try: del(tag["TXXX:" + key]) except KeyError: pass for key in self.PAM_XXXT: if key in self.SDI: # we already write it back using non-TXXX frames continue if key in self: value = self[key] f = mutagen.id3.TXXX(encoding=encoding_for(value), text=value.split("\n"), desc=self.PAM_XXXT[key]) tag.add(f) if (config.getboolean("editing", "save_to_songs") and (self.has_rating or self.get("~#playcount", 0) != 0)): email = config.get("editing", "save_email").strip() email = email or const.EMAIL t = mutagen.id3.POPM(email=email, rating=int(255 * self("~#rating")), count=self.get("~#playcount", 0)) tag.add(t) with translate_errors(): audio.save() self.sanitize() can_change_images = True def clear_images(self): """Delete all embedded images""" with translate_errors(): audio = self.Kind(self["~filename"]) if audio.tags is not None: audio.tags.delall("APIC") audio.save() self.has_images = False def get_images(self): """Returns a list of embedded images""" images = [] try: with translate_errors(): audio = self.Kind(self["~filename"]) except AudioFileError: return images tag = audio.tags if tag is None: return images for frame in tag.getall("APIC"): f = get_temp_cover_file(frame.data) images.append(EmbeddedImage(f, frame.mime, type_=frame.type)) images.sort(key=lambda c: c.sort_key) return images def get_primary_image(self): """Returns the primary embedded image""" try: with translate_errors(): audio = self.Kind(self["~filename"]) except AudioFileError: return tag = audio.tags if tag is None: return # get the APIC frame with type == 3 (cover) or the first one cover = None for frame in tag.getall("APIC"): cover = cover or frame if frame.type == APICType.COVER_FRONT: cover = frame break if cover: f = get_temp_cover_file(cover.data) return EmbeddedImage(f, cover.mime, type_=cover.type) def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): audio = self.Kind(self["~filename"]) if audio.tags is None: audio.add_tags() tag = audio.tags try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) tag.delall("APIC") frame = mutagen.id3.APIC( encoding=3, mime=image.mime_type, type=APICType.COVER_FRONT, desc=u"", data=data) tag.add(frame) with translate_errors(): audio.save() self.has_images = True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/_image.py0000664000175000017500000001474214035600052017446 0ustar00nicknick# Copyright 2013 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from ._misc import AudioFileError class ImageContainer: """Mixin/Interface for AudioFile to support basic embedded image editing""" def get_primary_image(self): """Returns the primary embedded image or None. In case of an error returns None. """ return def get_images(self): """Returns a list of embedded images, primary first. In case of an error returns an empty list. """ # fall back to the single implementation image = self.get_primary_image() if image: return [image] return [] @property def has_images(self): """Fast way to check for images, might be False if the file was modified externally. """ return "~picture" in self @has_images.setter def has_images(self, value): if value: self["~picture"] = "y" else: self.pop("~picture", None) @property def can_change_images(self): """Return True IFF `clear_images()` and `set_images()` are implemented""" return False def clear_images(self): """Delete all embedded images. Raises: AudioFileError """ raise AudioFileError("Not supported for this format") def set_image(self, image): """Replaces all embedded images by the passed image. The image type recorded in the file will be APICType.COVER_FRONT, disregarding image.type. Raises: AudioFileError """ raise AudioFileError("Not supported for this format") class APICType: """Enumeration of image types defined by the ID3 standard but also reused in WMA/FLAC/VorbisComment """ # Other OTHER = 0 # 32x32 pixels 'file icon' (PNG only) FILE_ICON = 1 # Other file icon OTHER_FILE_ICON = 2 # Cover (front) COVER_FRONT = 3 # Cover (back) COVER_BACK = 4 # Leaflet page LEAFLET_PAGE = 5 # Media (e.g. label side of CD) MEDIA = 6 # Lead artist/lead performer/soloist LEAD_ARTIST = 7 # Artist/performer ARTIST = 8 # Conductor CONDUCTOR = 9 # Band/Orchestra BAND = 10 # Composer COMPOSER = 11 # Lyricist/text writer LYRISCIST = 12 # Recording Location RECORDING_LOCATION = 13 # During recording DURING_RECORDING = 14 # During performance DURING_PERFORMANCE = 15 # Movie/video screen capture SCREEN_CAPTURE = 16 # A bright coloured fish FISH = 17 # Illustration ILLUSTRATION = 18 # Band/artist logotype BAND_LOGOTYPE = 19 # Publisher/Studio logotype PUBLISHER_LOGOTYPE = 20 @classmethod def to_string(cls, value): for k, v in cls.__dict__.items(): if v == value: return k return "" @classmethod def is_valid(cls, value): return cls.OTHER <= value <= cls.PUBLISHER_LOGOTYPE @classmethod def sort_key(cls, value): """Sorts picture types, most important picture is the lowest. Important is defined as most representative of an album release, ymmv. """ # index value -> important important = [ cls.LEAFLET_PAGE, cls.MEDIA, cls.COVER_BACK, cls.COVER_FRONT ] try: return -important.index(value) except ValueError: if value < cls.COVER_FRONT: return 100 - value else: return value class EmbeddedImage: """Embedded image, contains most of the properties needed for FLAC and ID3 images. """ def __init__(self, fileobj, mime_type, width=-1, height=-1, color_depth=-1, type_=APICType.OTHER): self.mime_type = mime_type self.width = width self.height = height self.color_depth = color_depth self.file = fileobj self.type = type_ def __repr__(self): return "<%s mime_type=%r width=%d height=%d type=%s file=%r>" % ( type(self).__name__, self.mime_type, self.width, self.height, APICType.to_string(self.type), self.file) def read(self): """Read the raw image data Returns: bytes Raises: IOError """ self.file.seek(0) data = self.file.read() self.file.seek(0) return data @property def sort_key(self): return APICType.sort_key(self.type) @property def extensions(self): """A possibly empty list of extensions e.g. ["jpeg", jpg"]""" from gi.repository import GdkPixbuf for format_ in GdkPixbuf.Pixbuf.get_formats(): if self.mime_type in format_.get_mime_types(): return format_.get_extensions() return [] @classmethod def from_path(cls, path): """Reads the header of `path` and creates a new image instance or None. """ from gi.repository import GdkPixbuf, GLib pb = [] # Feed data to PixbufLoader until it emits area-prepared, # get the partially filled pixbuf and extract the needed # information. def area_prepared(loader): pb.append(loader.get_pixbuf()) loader = GdkPixbuf.PixbufLoader() loader.connect("area-prepared", area_prepared) try: with open(path, "rb") as h: while not pb: data = h.read(1024) if data: loader.write(data) else: break except (EnvironmentError, GLib.GError): return finally: try: loader.close() except GLib.GError: pass if not pb: return pb = pb[0] width = pb.get_width() height = pb.get_height() color_depth = pb.get_bits_per_sample() format_ = loader.get_format() mime_types = format_.get_mime_types() mime_type = mime_types and mime_types[0] or "" try: return cls(open(path, "rb"), mime_type, width, height, color_depth) except EnvironmentError: return ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1619423935.0 quodlibet-4.6.0/quodlibet/formats/_misc.py0000664000175000017500000000634514041471277017333 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys import contextlib import mutagen from quodlibet import util from quodlibet.util import print_w, print_d, reraise from quodlibet.util.importhelper import load_dir_modules from quodlibet.const import MinVersions mimes = set() """A set of supported mime types""" loaders = {} """A dict mapping file extensions to loaders (func returning an AudioFile)""" types = set() """A set of AudioFile subclasses/implementations""" class AudioFileError(Exception): """Base error for AudioFile, mostly IO/parsing related operations""" class MutagenBug(AudioFileError): """Raised in is caused by a mutagen bug, so we can highlight it""" @contextlib.contextmanager def translate_errors(): """Context manager for mutagen calls to load/save. Translates exceptions to local ones. """ try: yield except AudioFileError: raise except mutagen.MutagenError as e: reraise(AudioFileError, e) except Exception as e: reraise(MutagenBug, e) def init(): """Load/Import all formats. Before this is called loading a file and unpickling will not work. """ global mimes, loaders, types MinVersions.MUTAGEN.check(mutagen.version) base = util.get_module_dir() formats = load_dir_modules(base, package=__package__) module_names = [] for format in formats: name = format.__name__ for ext in format.extensions: loaders[ext] = format.loader types.update(format.types) if format.extensions: for type_ in format.types: mimes.update(type_.mimes) module_names.append(name.split(".")[-1]) # Migrate pre-0.16 library, which was using an undocumented "feature". sys.modules[name.replace(".", "/")] = format # Migrate old layout if name.startswith("quodlibet."): sys.modules[name.split(".", 1)[1]] = format # This can be used for the quodlibet.desktop file desktop_mime_types = "MimeType=" + \ ";".join(sorted({m.split(";")[0] for m in mimes})) + ";" print_d(desktop_mime_types) s = ", ".join(sorted(module_names)) print_d("Supported formats: %s" % s) if not loaders: raise SystemExit("No formats found!") def get_loader(filename): """Returns a callable which takes a filename and returns AudioFile or raises AudioFileError, or returns None. """ ext = os.path.splitext(filename)[-1] return loaders.get(ext.lower()) def MusicFile(filename): """Returns a AudioFile instance or None""" loader = get_loader(filename) if loader is not None: try: return loader(filename) except AudioFileError: print_w("Error loading %r" % filename) util.print_exc() except: print_w("Error loading %r" % filename) raise def filter(filename): """Returns True if the file extension is supported""" return get_loader(filename) is not None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/_serialize.py0000664000175000017500000001103314035600052020341 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Code for serializing AudioFile instances""" import pickle from senf import bytes2fsn, fsn2bytes from quodlibet.util.picklehelper import pickle_loads, pickle_dumps from quodlibet.util import is_windows from ._audio import AudioFile class SerializationError(Exception): pass def _py2_to_py3(items): for i in items: try: l = list(i.items()) except AttributeError: raise SerializationError i.clear() for k, v in l: if isinstance(k, bytes): k = k.decode("utf-8", "replace") else: # strip surrogates try: k.encode("utf-8") except UnicodeEncodeError: k = k.encode("utf-8", "replace").decode("utf-8") if k == "~filename" or k == "~mountpoint": if isinstance(v, bytes): try: v = bytes2fsn(v, "utf-8") except ValueError: # just in case, only on Windows assert is_windows() v = v.decode("utf-8", "replace") elif isinstance(v, bytes): v = v.decode("utf-8", "replace") elif isinstance(v, str): # strip surrogates try: v.encode("utf-8") except UnicodeEncodeError: v = v.encode("utf-8", "replace").decode("utf-8") i[k] = v return items def _py3_to_py2(items): is_win = is_windows() new_list = [] for i in items: inst = dict.__new__(i.__class__) for key, value in i.items(): if key in ("~filename", "~mountpoint") and not is_win: value = fsn2bytes(value, None) try: key = key.encode("ascii") except UnicodeEncodeError: pass dict.__setitem__(inst, key, value) new_list.append(inst) return new_list def load_audio_files(data, process=True): """unpickles the item list and if some class isn't found unpickle as a dict and filter them out afterwards. In case everything gets filtered out will raise SerializationError (because then likely something larger went wrong) Args: data (bytes) process (bool): if the dict key/value types should be converted, either to be usable from py3 or to convert to newer types Returns: List[AudioFile] Raises: SerializationError """ dummy = type("dummy", (dict,), {}) error_occured = [] temp_type_cache = {} def lookup_func(base, module, name): try: real_type = base(module, name) except (ImportError, AttributeError): error_occured.append(True) return dummy if module.split(".")[0] not in ("quodlibet", "tests"): return real_type # return a straight dict subclass so that unpickle doesn't call # our __setitem__. Further down we simply change the __class__ # to our real type. if not real_type in temp_type_cache: new_type = type(name, (dict,), {"real_type": real_type}) temp_type_cache[real_type] = new_type return temp_type_cache[real_type] try: items = pickle_loads(data, lookup_func) except pickle.UnpicklingError as e: raise SerializationError(e) if error_occured: items = [i for i in items if not isinstance(i, dummy)] if not items: raise SerializationError( "all class lookups failed. something is wrong") if process: items = _py2_to_py3(items) try: for i in items: i.__class__ = i.real_type except AttributeError as e: raise SerializationError(e) return items def dump_audio_files(item_list, process=True): """Pickles a list of AudioFiles Returns: bytes Raises: SerializationError """ assert isinstance(item_list, list) assert not item_list or isinstance(item_list[0], AudioFile) if process: item_list = _py3_to_py2(item_list) try: return pickle_dumps(item_list, 2) except pickle.PicklingError as e: raise SerializationError(e) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/aac.py0000664000175000017500000000237514035600052016750 0ustar00nicknick# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from mutagen.aac import AAC from ._audio import AudioFile, translate_errors extensions = [".aac", ".adif", ".adts"] class AACFile(AudioFile): """ADTS/ADIF files""" format = "AAC" mimes = ["audio/x-aac"] fill_length = True def __init__(self, filename): with translate_errors(): audio = AAC(filename) self["~#length"] = audio.info.length self["~#bitrate"] = int(audio.info.bitrate / 1000) if audio.info.channels: self["~#channels"] = audio.info.channels self["~#samplerate"] = audio.info.sample_rate self.sanitize(filename) def write(self): pass def reload(self, *args): title = self.get("title") super().reload(*args) if title is not None: self.setdefault("title", title) def can_change(self, k=None): if k is None: return ["title"] else: return k == "title" loader = AACFile types = [AACFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/aiff.py0000664000175000017500000000135214035600052017123 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from mutagen.aiff import AIFF from ._id3 import ID3File extensions = [".aif", ".aiff", ".aifc"] class AIFFFile(ID3File): format = "AIFF" mimes = ["audio/x-aiff", "audio/aiff"] Kind = AIFF def _parse_info(self, info): self["~#length"] = info.length self["~#bitrate"] = int(info.bitrate / 1000) self["~#channels"] = info.channels self["~#samplerate"] = info.sample_rate loader = AIFFFile types = [AIFFFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1681489057.0 quodlibet-4.6.0/quodlibet/formats/dsf.py0000644000175000017500000000136014416276241017003 0ustar00nicknick# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from mutagen.dsf import DSF from ._id3 import ID3File class DSFFile(ID3File): format = "DSF" mimes = ["audio/dsf"] Kind = DSF def _parse_info(self, info): self["~#length"] = info.length self["~#bitrate"] = int(info.bitrate / 1000) self["~#channels"] = info.channels self["~#samplerate"] = info.sample_rate self["~#bitdepth"] = info.bits_per_sample loader = DSFFile types = [DSFFile] extensions = [".dsf"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/midi.py0000664000175000017500000000205314035600052017137 0ustar00nicknick# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from mutagen.smf import SMF from ._audio import AudioFile, translate_errors class MidiError(Exception): pass class MidiFile(AudioFile): format = "MIDI" mimes = ["audio/midi", "audio/x-midi"] def __init__(self, filename): with translate_errors(): audio = SMF(filename) self["~#length"] = audio.info.length self.sanitize(filename) def write(self): pass def reload(self, *args): title = self.get("title") super().reload(*args) if title is not None: self.setdefault("title", title) def can_change(self, k=None): if k is None: return ["title"] else: return k == "title" loader = MidiFile types = [MidiFile] extensions = [".mid"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/mod.py0000664000175000017500000000430014035600052016771 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # # 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 2 of the License, or # (at your option) any later version. import os import ctypes from quodlibet.util import load_library from ._audio import AudioFile, translate_errors extensions = [ '.669', '.amf', '.ams', '.dsm', '.far', '.it', '.med', '.mod', '.mt2', '.mtm', '.okt', '.s3m', '.stm', '.ult', '.gdm', '.xm'] try: _modplug = load_library( ["libmodplug.so.1", "libmodplug.so.0", "libmodplug-1.dll"])[0] except OSError: extensions = [] else: _modplug.ModPlug_GetName.argtypes = [ctypes.c_void_p] _modplug.ModPlug_GetName.restype = ctypes.c_char_p _modplug.ModPlug_Load.argtypes = [ctypes.c_void_p, ctypes.c_int] _modplug.ModPlug_Load.restype = ctypes.c_void_p _modplug.ModPlug_GetLength.argtypes = [ctypes.c_void_p] _modplug.ModPlug_GetLength.restype = ctypes.c_int _modplug.ModPlug_Unload.argtypes = [ctypes.c_void_p] _modplug.ModPlug_Unload.restype = None class ModFile(AudioFile): format = "MOD/XM/IT" def __init__(self, filename): with translate_errors(): data = open(filename, "rb").read() f = _modplug.ModPlug_Load(data, len(data)) if not f: raise IOError("%r not a valid MOD file" % filename) self["~#length"] = _modplug.ModPlug_GetLength(f) // 1000 title = _modplug.ModPlug_GetName(f) or os.path.basename(filename) try: self["title"] = title.decode('utf-8') except UnicodeError: self["title"] = title.decode("iso-8859-1") _modplug.ModPlug_Unload(f) self.sanitize(filename) def write(self): pass def reload(self, *args): artist = self.get("artist") super().reload(*args) if artist is not None: self.setdefault("artist", artist) def can_change(self, k=None): if k is None: return ["artist"] else: return k == "artist" loader = ModFile types = [ModFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/monkeysaudio.py0000664000175000017500000000173714035600052020734 0ustar00nicknick# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from mutagen.monkeysaudio import MonkeysAudio from ._audio import translate_errors from ._apev2 import APEv2File class MonkeysAudioFile(APEv2File): format = "Monkey's Audio" def __init__(self, filename): with translate_errors(): audio = MonkeysAudio(filename) super().__init__(filename, audio) self["~#length"] = int(audio.info.length) self["~#channels"] = audio.info.channels self["~#samplerate"] = audio.info.sample_rate if hasattr(audio.info, "bits_per_sample"): self["~#bitdepth"] = audio.info.bits_per_sample self.sanitize(filename) loader = MonkeysAudioFile types = [MonkeysAudioFile] extensions = [".ape"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/mp3.py0000664000175000017500000000233114035600052016713 0ustar00nicknick# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Niklas Janlert # # 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 2 of the License, or # (at your option) any later version. from mutagen.mp3 import MP3 from ._id3 import ID3File extensions = [".mp3", ".mp2", ".mp1", ".mpg", ".mpeg"] class MP3File(ID3File): format = "MPEG-1/2" mimes = ["audio/mp3", "audio/x-mp3", "audio/mpeg", "audio/mpg", "audio/x-mpeg"] Kind = MP3 def _parse_info(self, info): self["~#length"] = info.length self["~#bitrate"] = int(info.bitrate / 1000) self["~format"] = u"MP%d" % info.layer self["~#channels"] = info.channels self["~#samplerate"] = info.sample_rate encoder, brm = info.encoder_info, info.bitrate_mode brm = {1: u"CBR", 2: u"VBR", 3: u"ABR"}.get(brm, u"") # encoder_settings is 1.37+ settings = getattr(info, "encoder_settings", u"") encoding = u"\n".join(filter(None, [encoder, brm, settings])) if encoding: self["~encoding"] = encoding loader = MP3File types = [MP3File] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1684322551.0 quodlibet-4.6.0/quodlibet/formats/mp4.py0000644000175000017500000001766714431134367016747 0ustar00nicknick# Copyright 2005 Alexey Bobyakov , Joe Wreschnig # Copyright 2006 Lukas Lalinsky # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from mutagen.mp4 import MP4, MP4Cover from quodlibet.util.path import get_temp_cover_file from quodlibet.util.string import decode from ._audio import AudioFile from ._misc import AudioFileError, translate_errors from ._image import EmbeddedImage class MP4File(AudioFile): format = "MPEG-4" mimes = ["audio/mp4", "audio/x-m4a", "audio/mpeg4", "audio/aac"] __translate = { "\xa9nam": "title", "\xa9alb": "album", "\xa9ART": "artist", "aART": "albumartist", "\xa9wrt": "composer", "\xa9day": "date", "\xa9cmt": "comment", "\xa9grp": "grouping", "\xa9gen": "genre", "tmpo": "bpm", "\xa9too": "encodedby", # FIXME: \xa9enc should be encodedby "desc": "description", # (usually used in podcasts) "cprt": "copyright", "soal": "albumsort", "soaa": "albumartistsort", "soar": "artistsort", "sonm": "titlesort", "soco": "composersort", "----:com.apple.iTunes:CONDUCTOR": "conductor", "----:com.apple.iTunes:DISCSUBTITLE": "discsubtitle", "----:com.apple.iTunes:LANGUAGE": "language", "----:com.apple.iTunes:MOOD": "mood", "----:com.apple.iTunes:MusicBrainz Artist Id": "musicbrainz_artistid", "----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_trackid", "----:com.apple.iTunes:MusicBrainz Release Track Id": "musicbrainz_releasetrackid", "----:com.apple.iTunes:MusicBrainz Album Id": "musicbrainz_albumid", "----:com.apple.iTunes:MusicBrainz Album Artist Id": "musicbrainz_albumartistid", "----:com.apple.iTunes:MusicIP PUID": "musicip_puid", "----:com.apple.iTunes:MusicBrainz Album Status": "musicbrainz_albumstatus", "----:com.apple.iTunes:MusicBrainz Album Type": "musicbrainz_albumtype", "----:com.apple.iTunes:MusicBrainz Album Release Country": "releasecountry", '----:com.apple.iTunes:MusicBrainz Release Group Id': 'musicbrainz_releasegroupid', '----:com.apple.iTunes:replaygain_album_gain': 'replaygain_album_gain', '----:com.apple.iTunes:replaygain_album_peak': 'replaygain_album_peak', '----:com.apple.iTunes:replaygain_track_gain': 'replaygain_track_gain', '----:com.apple.iTunes:replaygain_track_peak': 'replaygain_track_peak', '----:com.apple.iTunes:replaygain_reference_loudness': 'replaygain_reference_loudness', } __rtranslate = dict((v, k) for k, v in __translate.items()) __tupletranslate = { "disk": "discnumber", "trkn": "tracknumber", } __rtupletranslate = dict((v, k) for k, v in __tupletranslate.items()) def __init__(self, filename): with translate_errors(): audio = MP4(filename) self["~codec"] = audio.info.codec_description self["~#length"] = audio.info.length self["~#bitrate"] = int(audio.info.bitrate / 1000) if audio.info.channels: self["~#channels"] = audio.info.channels self["~#samplerate"] = audio.info.sample_rate self["~#bitdepth"] = audio.info.bits_per_sample for key, values in audio.items(): if key in self.__tupletranslate: if values: name = self.__tupletranslate[key] cur, total = values[0] if total: self[name] = u"%d/%d" % (cur, total) else: self[name] = str(cur) elif key in self.__translate: name = self.__translate[key] if key == "tmpo": self[name] = u"\n".join(map(str, values)) elif key.startswith("----"): self[name] = "\n".join( map(lambda v: decode(v).strip("\x00"), values)) else: self[name] = "\n".join(values) elif key == "covr": self.has_images = True self.sanitize(filename) def write(self): with translate_errors(): audio = MP4(self["~filename"]) for key in (list(self.__translate.keys()) + list(self.__tupletranslate.keys())): try: del(audio[key]) except KeyError: pass for key in self.realkeys(): try: name = self.__rtranslate[key] except KeyError: continue values = self.list(key) if name == "tmpo": values = list(map(lambda v: int(round(float(v))), values)) elif name.startswith("----"): values = list(map(lambda v: v.encode("utf-8"), values)) audio[name] = values track, tracks = self("~#track"), self("~#tracks", 0) if track: audio["trkn"] = [(track, tracks)] disc, discs = self("~#disc"), self("~#discs", 0) if disc: audio["disk"] = [(disc, discs)] with translate_errors(): audio.save() self.sanitize() def can_multiple_values(self, key=None): if key is None: return [] return False def can_change(self, key=None): OK = list(self.__rtranslate.keys()) + \ list(self.__rtupletranslate.keys()) if key is None: return OK else: return super().can_change(key) and (key in OK) def get_images(self): images = [] try: tag = MP4(self["~filename"]) except Exception: return [] for cover in tag.get("covr", []): if cover.imageformat == MP4Cover.FORMAT_JPEG: mime = "image/jpeg" elif cover.imageformat == MP4Cover.FORMAT_PNG: mime = "image/png" else: mime = "image/" f = get_temp_cover_file(cover) images.append(EmbeddedImage(f, mime)) return images def get_primary_image(self): try: tag = MP4(self["~filename"]) except Exception: return for cover in tag.get("covr", []): if cover.imageformat == MP4Cover.FORMAT_JPEG: mime = "image/jpeg" elif cover.imageformat == MP4Cover.FORMAT_PNG: mime = "image/png" else: mime = "image/" f = get_temp_cover_file(cover) return EmbeddedImage(f, mime) can_change_images = True def clear_images(self): """Delete all embedded images""" with translate_errors(): tag = MP4(self["~filename"]) tag.pop("covr", None) tag.save() self.has_images = False def set_image(self, image): """Replaces all embedded images by the passed image""" if image.mime_type == "image/jpeg": image_format = MP4Cover.FORMAT_JPEG elif image.mime_type == "image/png": image_format = MP4Cover.FORMAT_PNG else: raise AudioFileError( "mp4: Unsupported image format %r" % image.mime_type) with translate_errors(): tag = MP4(self["~filename"]) try: data = image.read() except EnvironmentError: return cover = MP4Cover(data, image_format) tag["covr"] = [cover] with translate_errors(): tag.save() self.has_images = True loader = MP4File types = [MP4File] extensions = ['.mp4', '.m4a', '.m4b', '.m4v', '.3gp', '.3g2', '.3gp2'] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/mpc.py0000664000175000017500000000336514035600052017003 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # # 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 2 of the License, or # (at your option) any later version. from mutagen.musepack import Musepack from ._audio import translate_errors from ._apev2 import APEv2File class MPCFile(APEv2File): format = "Musepack" mimes = ["audio/x-musepack", "audio/x-mpc"] def __init__(self, filename): with translate_errors(): audio = Musepack(filename) super().__init__(filename, audio) self["~#length"] = audio.info.length self["~#bitrate"] = int(audio.info.bitrate / 1000) self["~#channels"] = audio.info.channels self["~#samplerate"] = audio.info.sample_rate version = audio.info.version self["~codec"] = u"%s SV%d" % (self.format, version) try: if audio.info.title_gain: track_g = u"%+0.2f dB" % audio.info.title_gain self.setdefault("replaygain_track_gain", track_g) if audio.info.album_gain: album_g = u"%+0.2f dB" % audio.info.album_gain self.setdefault("replaygain_album_gain", album_g) if audio.info.title_peak: track_p = str(audio.info.title_peak * 2) self.setdefault("replaygain_track_peak", track_p) if audio.info.album_peak: album_p = str(audio.info.album_peak * 2) self.setdefault("replaygain_album_peak", album_p) except AttributeError: pass self.sanitize(filename) loader = MPCFile types = [MPCFile] extensions = [".mpc", ".mp+"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/remote.py0000664000175000017500000000262514035600052017515 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # # 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 2 of the License, or # (at your option) any later version. from typing import List from senf import fsnative, path2fsn from ._audio import AudioFile extensions: List[str] = [] class RemoteFile(AudioFile): is_file = False fill_metadata = True format = "Remote File" def __init__(self, uri): assert not isinstance(uri, bytes) self["~uri"] = str(uri) self.sanitize(fsnative(self["~uri"])) def __getitem__(self, key): # we used to save them with the wrong type value = super().__getitem__(key) if key in ("~filename", "~mountpoint") and \ not isinstance(value, fsnative): value = path2fsn(value) return value def rename(self, newname): pass def reload(self): pass def exists(self): return True def valid(self): return True def mounted(self): return True def write(self): pass def can_change(self, k=None): if k is None: return [] else: return False @property def key(self): return self["~uri"] loader = RemoteFile types = [RemoteFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/spc.py0000664000175000017500000000435514035600052017011 0ustar00nicknick# Copyright 2007 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. import os from senf import path2fsn, fsn2text from ._audio import AudioFile, translate_errors extensions = [".spc"] class SPCFile(AudioFile): format = "SPC700" def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: head = h.read(46) if len(head) != 46 or \ head[:27] != b'SNES-SPC700 Sound File Data': raise IOError("Not a valid SNES-SPC700 file") if head[35:35 + 1] == b'\x1a': data = h.read(210) if len(data) == 210: self.update(parse_id666(data)) self.setdefault( "title", fsn2text(path2fsn(os.path.basename(filename)[:-4]))) self.sanitize(filename) def write(self): pass def can_change(self, k=None): TAGS = ["artist", "album", "title", "comments"] if k is None: return TAGS else: return k in TAGS def parse_id666(data): #http://snesmusic.org/files/spc_file_format.txt tags = {} tags["title"] = data[:32] tags["album"] = data[32:64] tags["dumper"] = data[64:80] tags["comments"] = data[80:112] # Artist differs based on binary or text mode, which is implicit. # Instead of detecting "perfectly", we'll just detect enough for # the "artist" field. This fails for artist names that begin with # numbers or symbols less than ascii value A. if data[130:130 + 1] < b'A': try: tags["~#length"] = int(data[123:126].strip(b"\x00")) except ValueError: pass tags["artist"] = data[131:163] else: tags["artist"] = data[130:162] for k in list(tags.keys()): if k[:2] == "~#": continue tags[k] = tags[k].replace(b"\x00", b"").decode("ascii", "ignore") if not tags[k]: del tags[k] return tags loader = SPCFile types = [SPCFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/trueaudio.py0000664000175000017500000000125314035600052020217 0ustar00nicknick# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Niklas Janlert # # 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 2 of the License, or # (at your option) any later version. from mutagen.trueaudio import TrueAudio from ._id3 import ID3File class TrueAudioFile(ID3File): format = "True Audio" mimes = ["audio/x-tta"] Kind = TrueAudio def _parse_info(self, info): self["~#length"] = info.length self["~#samplerate"] = info.sample_rate loader = TrueAudioFile types = [TrueAudioFile] extensions = [".tta"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/vgm.py0000664000175000017500000001130014035600052017001 0ustar00nicknick# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import struct import os from typing import List from senf import path2fsn, fsn2text from ._audio import AudioFile, translate_errors from quodlibet.util.dprint import print_d from quodlibet.util import list_unique # VGM and GD3 SPECs: # http://www.smspower.org/uploads/Music/vgmspec170.txt # http://www.smspower.org/uploads/Music/gd3spec100.txt GD3_TAG_PTR_POS = 0x14 GD3_TAG_PTR_SIZE = 4 GD3_ENGLISH_TITLE = 0 GD3_JAPANESE_TITLE = 1 GD3_ENGLISH_GAME = 2 GD3_JAPANESE_GAME = 3 GD3_ENGLISH_SYSTEM = 4 GD3_JAPANESE_SYSTEM = 5 GD3_ENGLISH_ARTIST = 6 GD3_JAPANESE_ARTIST = 7 GD3_DATE = 8 GD3_DUMPER = 9 GD3_COMMENT = 10 class VgmFile(AudioFile): format = "VGM" mimes: List[str] = [] def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: header = h.read(64) if len(header) != 64 or header[:4] != b"Vgm ": # filename useful to show (helps w/ faulty VGM files.) raise Exception(filename + " not a VGM file") samples_to_sec = lambda s: s / 44100. samples = struct.unpack(' GD3_JAPANESE_TITLE: titles = gd3_filter_entries([entries[GD3_ENGLISH_TITLE], entries[GD3_JAPANESE_TITLE]]) if len(titles) > 0: tags["title"] = '\n'.join(titles) if len(entries) > GD3_JAPANESE_ARTIST: artists = gd3_filter_entries([entries[GD3_ENGLISH_ARTIST], entries[GD3_JAPANESE_ARTIST]]) if len(artists) > 0: tags["artist"] = '\n'.join(artists) if len(entries) > GD3_JAPANESE_SYSTEM: consoles = gd3_filter_entries([entries[GD3_ENGLISH_SYSTEM], entries[GD3_JAPANESE_SYSTEM]]) if len(consoles) > 0: tags["console"] = '\n'.join(consoles) if len(entries) > GD3_JAPANESE_GAME: games = gd3_filter_entries([entries[GD3_ENGLISH_GAME], entries[GD3_JAPANESE_GAME]]) if len(games) > 0: tags["album"] = '\n'.join(games) if len(entries) > GD3_DATE and entries[GD3_DATE] != "": tags["date"] = entries[GD3_DATE] if len(entries) > GD3_DUMPER and entries[GD3_DUMPER] != "": tags["dumper"] = entries[GD3_DUMPER] if len(entries) > GD3_COMMENT: tags["comment"] = entries[GD3_COMMENT] return tags def gd3_filter_entries(entries): # First, filter out empty strings... filtered = list(filter(None, entries)) if len(filtered) == 0: return filtered # Then, filter out any duplicate strings... filtered = list_unique(filtered) return sorted(filtered) loader = VgmFile types = [VgmFile] extensions = [".vgm"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/formats/wav.py0000664000175000017500000000250214231604332017014 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import wave from senf import fsn2text from ._audio import AudioFile, translate_errors extensions = [".wav"] class WAVEFile(AudioFile): format = "WAVE" mimes = ["audio/wav", "audio/x-wav", "audio/wave"] def __init__(self, filename): with translate_errors(): with open(filename, "rb") as h: f = wave.open(h) self["~#length"] = float(f.getnframes()) / f.getframerate() self["~#channels"] = f.getnchannels() self["~#samplerate"] = f.getframerate() self["~#bitdepth"] = f.getsampwidth() * 8 self.sanitize(filename) def sanitize(self, filename=None): super().sanitize(filename) self["title"] = fsn2text(os.path.splitext( os.path.basename(self["~filename"]))[0]) def write(self): pass def can_change(self, k=None): if k is None: return ["artist"] else: return k == "artist" loader = WAVEFile types = [WAVEFile] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/formats/wavpack.py0000664000175000017500000000156614035600052017661 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman # # 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 2 of the License, or # (at your option) any later version. from mutagen.wavpack import WavPack from ._audio import translate_errors from ._apev2 import APEv2File class WavpackFile(APEv2File): format = "WavPack" mimes = ["audio/x-wavpack"] def __init__(self, filename): with translate_errors(): audio = WavPack(filename) super().__init__(filename, audio) self["~#length"] = audio.info.length self["~#channels"] = audio.info.channels self["~#samplerate"] = audio.info.sample_rate self.sanitize(filename) loader = WavpackFile types = [WavpackFile] extensions = [".wv"] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1684322551.0 quodlibet-4.6.0/quodlibet/formats/wma.py0000644000175000017500000002072214431134367017015 0ustar00nicknick# Copyright 2006 Lukas Lalinsky # # 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 2 of the License, or # (at your option) any later version. import struct import mutagen.asf from quodlibet.util.path import get_temp_cover_file from ._audio import AudioFile from ._image import EmbeddedImage, APICType from ._misc import AudioFileError, translate_errors class WMAFile(AudioFile): mimes = ["audio/x-ms-wma", "audio/x-ms-wmv", "video/x-ms-asf", "audio/x-wma", "video/x-wmv"] format = "ASF" #http://msdn.microsoft.com/en-us/library/dd743066%28VS.85%29.aspx #http://msdn.microsoft.com/en-us/library/dd743063%28VS.85%29.aspx #http://msdn.microsoft.com/en-us/library/dd743220%28VS.85%29.aspx __translate = { "WM/AlbumTitle": "album", "Title": "title", "Author": "artist", "WM/AlbumArtist": "albumartist", "WM/Composer": "composer", "WM/Writer": "lyricist", "WM/Conductor": "conductor", "WM/ModifiedBy": "remixer", "WM/Producer": "producer", "WM/ContentGroupDescription": "grouping", "WM/SubTitle": "discsubtitle", "WM/TrackNumber": "tracknumber", "WM/PartOfSet": "discnumber", "WM/BeatsPerMinute": "bpm", "Copyright": "copyright", "WM/ISRC": "isrc", "WM/Mood": "mood", "WM/EncodedBy": "encodedby", "MusicBrainz/Track Id": "musicbrainz_trackid", "MusicBrainz/Release Track Id": "musicbrainz_releasetrackid", "MusicBrainz/Album Id": "musicbrainz_albumid", "MusicBrainz/Artist Id": "musicbrainz_artistid", "MusicBrainz/Album Artist Id": "musicbrainz_albumartistid", "MusicBrainz/TRM Id": "musicbrainz_trmid", "MusicIP/PUID": "musicip_puid", "MusicBrainz/Release Group Id": "musicbrainz_releasegroupid", "WM/Year": "date", "WM/OriginalArtist": "originalartist", "WM/OriginalAlbumTitle": "originalalbum", "WM/AlbumSortOrder": "albumsort", "WM/ArtistSortOrder": "artistsort", "WM/AlbumArtistSortOrder": "albumartistsort", "WM/Genre": "genre", "WM/Publisher": "publisher", "WM/AuthorURL": "website", "Description": "comment" } __rtranslate = dict((v, k) for k, v in __translate.items()) # http://msdn.microsoft.com/en-us/library/dd743065.aspx # note: not all names here are used by QL __multi_value_attr = { "Author", "WM/AlbumArtist", "WM/AlbumCoverURL", "WM/Category", "WM/Composer", "WM/Conductor", "WM/Director", "WM/Genre", "WM/GenreID", "WM/Language", "WM/Lyrics_Synchronised", "WM/Mood", "WM/Picture", "WM/Producer", "WM/PromotionURL", "WM/UserWebURL", "WM/Writer", } __multi_value_keys = set() for k, v in __translate.items(): if k in __multi_value_attr: __multi_value_keys.add(v) def __init__(self, filename, audio=None): if audio is None: with translate_errors(): audio = mutagen.asf.ASF(filename) info = audio.info self["~#length"] = info.length self["~#bitrate"] = int(info.bitrate / 1000) if info.channels: self["~#channels"] = info.channels self["~#samplerate"] = info.sample_rate type_, name, desc = info.codec_type, info.codec_name, \ info.codec_description if type_: self["~codec"] = type_ encoding = u"\n".join(filter(None, [name, desc])) if encoding: self["~encoding"] = encoding for name, values in audio.tags.items(): if name == "WM/Picture": self.has_images = True try: name = self.__translate[name] except KeyError: continue self[name] = u"\n".join(map(str, values)) self.sanitize(filename) def write(self): with translate_errors(): audio = mutagen.asf.ASF(self["~filename"]) for key in self.__translate.keys(): try: del(audio[key]) except KeyError: pass for key in self.realkeys(): try: name = self.__rtranslate[key] except KeyError: continue audio.tags[name] = self.list(key) with translate_errors(): audio.save() self.sanitize() def can_multiple_values(self, key=None): if key is None: return self.__multi_value_keys return key in self.__multi_value_keys def can_change(self, key=None): OK = self.__rtranslate.keys() if key is None: return OK else: return super().can_change(key) and (key in OK) def get_images(self): images = [] try: tag = mutagen.asf.ASF(self["~filename"]) except Exception: return images for image in tag.get("WM/Picture", []): try: (mime, desc, data, type_) = unpack_image(image.value) except ValueError: continue f = get_temp_cover_file(data) images.append(EmbeddedImage(f, mime, type_=type_)) images.sort(key=lambda c: c.sort_key) return images def get_primary_image(self): """Returns the primary embedded image or None""" try: tag = mutagen.asf.ASF(self["~filename"]) except Exception: return for image in tag.get("WM/Picture", []): try: (mime, desc, data, type_) = unpack_image(image.value) except ValueError: continue if type_ == APICType.COVER_FRONT: # Only cover images f = get_temp_cover_file(data) return EmbeddedImage(f, mime, type_=type_) can_change_images = True def clear_images(self): """Delete all embedded images""" with translate_errors(): tag = mutagen.asf.ASF(self["~filename"]) tag.pop("WM/Picture", None) tag.save() self.has_images = False def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): tag = mutagen.asf.ASF(self["~filename"]) try: imagedata = image.read() except EnvironmentError as e: raise AudioFileError(e) # thumbnail gets used in WMP.. data = pack_image(image.mime_type, u"thumbnail", imagedata, APICType.COVER_FRONT) value = mutagen.asf.ASFValue(data, mutagen.asf.BYTEARRAY) tag["WM/Picture"] = [value] with translate_errors(): tag.save() self.has_images = True def unpack_image(data): """ Helper function to unpack image data from a WM/Picture tag. The data has the following format: 1 byte: Picture type (0-20), see ID3 APIC frame specification at http://www.id3.org/id3v2.4.0-frames 4 bytes: Picture data length in LE format MIME type, null terminated UTF-16-LE string Description, null terminated UTF-16-LE string The image data in the given length """ try: (type_, size) = struct.unpack_from(" 1: total = parts[1] del self[single] if main in self: total = self[main] del self[main] else: if fallback in self: total = self[fallback] del self[fallback] final = None if one is not None: final = one if total is not None: final = f"{final or ''}/{total}" if final is not None: self[single] = final def __post_read(self): email = config.get("editing", "save_email").strip() maps = {"rating": float, "playcount": int} for keyed_key, func in maps.items(): emails = [s.lower() for s in ["", f":{const.EMAIL}", f":{email}"]] for subkey in emails: key = keyed_key + subkey if key in self: try: self[f"~#{keyed_key}"] = func(self[key]) except ValueError: pass del(self[key]) if "metadata_block_picture" in self: self.has_images = True del(self["metadata_block_picture"]) if "coverart" in self: self.has_images = True del(self["coverart"]) if "coverartmime" in self: del(self["coverartmime"]) self.__post_read_total("tracktotal", "totaltracks", "tracknumber") self.__post_read_total("disctotal", "totaldiscs", "discnumber") def get_images(self): try: audio = self.MutagenType(self["~filename"]) except Exception: return [] # metadata_block_picture images = [] for data in audio.get("metadata_block_picture", []): try: cover = Picture(base64.b64decode(data)) except (TypeError, FLACError): continue f = get_temp_cover_file(cover.data) images.append(EmbeddedImage( f, cover.mime, cover.width, cover.height, cover.depth, cover.type)) # coverart + coverartmime cover = audio.get("coverart") try: cover = cover and base64.b64decode(cover[0]) except TypeError: cover = None if cover: mime = audio.get("coverartmime") mime = (mime and mime[0]) or "image/" f = get_temp_cover_file(cover) images.append(EmbeddedImage(f, mime)) images.sort(key=lambda c: c.sort_key) return images def get_primary_image(self): """Returns the primary embedded image""" try: audio = self.MutagenType(self["~filename"]) except Exception: return None pictures = [] for data in audio.get("metadata_block_picture", []): try: pictures.append(Picture(base64.b64decode(data))) except (TypeError, FLACError, ValueError): pass cover = None for pic in pictures: if pic.type == APICType.COVER_FRONT: cover = pic break cover = cover or pic if cover: f = get_temp_cover_file(cover.data) return EmbeddedImage( f, cover.mime, cover.width, cover.height, cover.depth, cover.type) cover = audio.get("coverart") try: cover = cover and base64.b64decode(cover[0]) except (TypeError, ValueError): cover = None if not cover: self.has_images = False return mime = audio.get("coverartmime") mime = (mime and mime[0]) or "image/" f = get_temp_cover_file(cover) return EmbeddedImage(f, mime) def clear_images(self): """Delete all embedded images""" with translate_errors(): audio = self.MutagenType(self["~filename"]) audio.pop("metadata_block_picture", None) audio.pop("coverart", None) audio.pop("coverartmime", None) audio.save() self.has_images = False def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): audio = self.MutagenType(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth audio.pop("coverart", None) audio.pop("coverartmime", None) audio["metadata_block_picture"] = base64.b64encode( pic.write()).decode("ascii") with translate_errors(): audio.save() self.has_images = True def can_change(self, k=None): if k is None: return super().can_change(None) else: l = k.lower() return (super().can_change(k) and l not in ["rating", "playcount", "metadata_block_picture", "coverart", "coverartmime"] and not l.startswith("rating:") and not l.startswith("playcount:")) def __prep_write(self, comments): email = config.get("editing", "save_email").strip() for key in comments.keys(): if key.startswith("rating:") or key.startswith("playcount:"): if key.split(":", 1)[1] in [const.EMAIL, email]: del(comments[key]) elif key not in ["metadata_block_picture", "coverart", "coverartmime"]: del(comments[key]) if config.getboolean("editing", "save_to_songs"): email = email or const.EMAIL if self.has_rating: comments[f"rating:{email}"] = str(self("~#rating")) playcount = self.get("~#playcount", 0) if playcount != 0: comments[f"playcount:{email}"] = str(playcount) def __prep_write_total(self, comments, main, fallback, single): lower = self.as_lowercased() for k in [main, fallback, single]: if k in comments: del comments[k] if single in lower: parts = lower[single].split("/", 1) if parts[0]: comments[single] = [parts[0]] if len(parts) > 1: comments[main] = [parts[1]] if main in lower: comments[main] = lower.list(main) if fallback in lower: if main in comments: comments[fallback] = lower.list(fallback) else: comments[main] = lower.list(fallback) def has_rating_and_playcount_in_file(self, email): with translate_errors(): audio = self.MutagenType(self['~filename']) tags = audio.tags if tags is None: return False return f"rating:{email}" in tags and f"playcount:{email}" in tags def write(self): with translate_errors(): audio = self.MutagenType(self["~filename"]) if audio.tags is None: audio.add_tags() self.__prep_write(audio.tags) lower = self.as_lowercased() for key in lower.realkeys(): audio.tags[key] = lower.list(key) self.__prep_write_total(audio.tags, "tracktotal", "totaltracks", "tracknumber") self.__prep_write_total(audio.tags, "disctotal", "totaldiscs", "discnumber") with translate_errors(): audio.save() self.sanitize() extensions = [] ogg_formats: List[Type[mutagen.FileType]] = [] from mutagen.oggvorbis import OggVorbis extensions.append(".ogg") extensions.append(".oga") ogg_formats.append(OggVorbis) from mutagen.flac import FLAC, FLACNoHeaderError extensions.append(".flac") ogg_formats.append(FLAC) from mutagen.oggflac import OggFLAC extensions.append(".oggflac") ogg_formats.append(OggFLAC) from mutagen.oggspeex import OggSpeex extensions.append(".spx") ogg_formats.append(OggSpeex) from mutagen.oggtheora import OggTheora extensions.append(".ogv") ogg_formats.append(OggTheora) from mutagen.oggopus import OggOpus extensions.append(".opus") ogg_formats.append(OggOpus) class OggFile(MutagenVCFile): format = "Ogg Vorbis" mimes = ["audio/vorbis", "audio/ogg; codecs=vorbis"] MutagenType = OggVorbis class OggFLACFile(MutagenVCFile): format = "Ogg FLAC" mimes = ["audio/x-oggflac", "audio/ogg; codecs=flac"] MutagenType = OggFLAC class OggSpeexFile(MutagenVCFile): format = "Ogg Speex" mimes = ["audio/x-speex", "audio/ogg; codecs=speex"] MutagenType = OggSpeex class OggTheoraFile(MutagenVCFile): format = "Ogg Theora" mimes = ["video/x-theora", "video/ogg; codecs=theora"] MutagenType = OggTheora class OggOpusFile(MutagenVCFile): format = "Ogg Opus" mimes = ["audio/ogg; codecs=opus"] MutagenType = OggOpus def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self["~#samplerate"] = 48000 class FLACFile(MutagenVCFile): format = "FLAC" mimes = ["audio/x-flac", "application/x-flac"] MutagenType = FLAC def __init__(self, filename, audio=None): if audio is None: with translate_errors(): audio = FLAC(filename) super().__init__(filename, audio) if audio.pictures: self.has_images = True self["~#bitdepth"] = audio.info.bits_per_sample def get_images(self): images = super().get_images() try: tag = FLAC(self["~filename"]) except Exception: return images for cover in tag.pictures: fileobj = get_temp_cover_file(cover.data) images.append(EmbeddedImage( fileobj, cover.mime, cover.width, cover.height, cover.depth, cover.type)) images.sort(key=lambda c: c.sort_key) return images def get_primary_image(self): """Returns the primary embedded image""" try: tag = FLAC(self["~filename"]) except Exception: return None covers = tag.pictures if not covers: return super().get_primary_image() covers.sort(key=lambda c: APICType.sort_key(c.type)) cover = covers[0] fileobj = get_temp_cover_file(cover.data) return EmbeddedImage( fileobj, cover.mime, cover.width, cover.height, cover.depth, cover.type) def clear_images(self): """Delete all embedded images""" with translate_errors(): tag = FLAC(self["~filename"]) tag.clear_pictures() tag.save() # clear vcomment tags super().clear_images() self.has_images = False def set_image(self, image): """Replaces all embedded images by the passed image""" with translate_errors(): tag = FLAC(self["~filename"]) try: data = image.read() except EnvironmentError as e: raise AudioFileError(e) pic = Picture() pic.data = data pic.type = APICType.COVER_FRONT pic.mime = image.mime_type pic.width = image.width pic.height = image.height pic.depth = image.color_depth tag.add_picture(pic) with translate_errors(): tag.save() # clear vcomment tags super().clear_images() self.has_images = True def write(self): if ID3 is not None: with translate_errors(): ID3().delete(filename=self["~filename"]) super().write() types = [] for var in list(globals().values()): if getattr(var, 'MutagenType', None): types.append(var) def loader(filename): """ Returns: AudioFile Raises: AudioFileError """ with translate_errors(): audio = mutagen.File(filename, options=ogg_formats) if audio is None and FLAC is not None: # FLAC with ID3 try: audio = FLAC(filename) except FLACNoHeaderError: pass if audio is None: raise AudioFileError("file type could not be determined") Kind = type(audio) for klass in globals().values(): if Kind is getattr(klass, 'MutagenType', None): return klass(filename, audio) raise AudioFileError("file type could not be determined") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/0000755000175000017500000000000014471213412015437 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/Makefile0000664000175000017500000000332114244626671017115 0ustar00nicknickTHEME=hicolor QL_SOURCE=$(THEME)/scalable/apps/io.github.quodlibet.QuodLibet.svg QL_DEST=io.github.quodlibet.QuodLibet.png EF_SOURCE=$(THEME)/scalable/apps/io.github.quodlibet.ExFalso.svg EF_DEST=io.github.quodlibet.ExFalso.png QL_MC_SOURCE=$(THEME)/scalable/status/quodlibet-missing-cover.svg QL_MC_DEST=quodlibet-missing-cover.png SYMBOLIC_SRC=$(wildcard $(THEME)/scalable/apps/*.svg.in) SYMBOLIC_TARGET=$(SYMBOLIC_SRC:.svg.in=.svg) all: \ png-16x16 \ png-24x24 \ png-32x32 \ png-48x48 \ png-64x64 \ png-128x128 \ png-256x256 \ $(SYMBOLIC_TARGET) clean: rm -f -R \ $(THEME)/16x16 \ $(THEME)/24x24 \ $(THEME)/32x32 \ $(THEME)/48x48 \ $(THEME)/64x64 \ $(THEME)/128x128 \ $(THEME)/256x256 \ $(SYMBOLIC_TARGET) png-%: $(THEME)/%/apps/$(QL_DEST) $(THEME)/%/apps/$(EF_DEST) $(THEME)/%/status/$(QL_MC_DEST) @true $(THEME)/%/apps/$(QL_DEST): $(QL_SOURCE) mkdir -p $(dir $@) inkscape $< --export-filename $@ -w $(shell echo $* | cut -dx -f1) -h $(shell echo $* | cut -dx -f2) ; $(THEME)/%/apps/$(EF_DEST): $(EF_SOURCE) mkdir -p $(dir $@) inkscape $< --export-filename $@ -w $(shell echo $* | cut -dx -f1) -h $(shell echo $* | cut -dx -f2) ; $(THEME)/%/status/$(QL_MC_DEST): $(QL_MC_SOURCE) mkdir -p $(dir $@) inkscape $< --export-filename $@ -w $(shell echo $* | cut -dx -f1) -h $(shell echo $* | cut -dx -f2) ; $(SYMBOLIC_TARGET): $(SYMBOLIC_SRC) cp $(@:.svg=.svg.in) "_temp.svg" inkscape "_temp.svg" --verb=EditSelectAll \ --verb=SelectionUnGroup --verb=StrokeToPath --verb=SelectionUnion \ --verb=FileVacuum \ --verb=FileSave --verb=FileClose --verb=FileQuit mv "_temp.svg" "$@" .PRECIOUS: $(THEME)/%/apps/$(QL_DEST) $(THEME)/%/apps/$(EF_DEST) $(THEME)/%/status/$(QL_MC_DEST) .PHONY: clean png-% ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/0000755000175000017500000000000014471213412017076 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/0000755000175000017500000000000014471213412020033 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/apps/0000755000175000017500000000000014471213412020776 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.ExFalso.png0000664000175000017500000002174714244626671026755 0ustar00nicknickPNG  IHDR>a pHYs\rtEXtSoftwarewww.inkscape.org< IDATx]y`TչsNB–@XdܷVA>[jV}Z>RZ.nEA@ ldLfl]gIf7 _{$̽||(((?d`2Hl;p$@,U^Wv[LfF(G_"%d"L5hmGBD"9k N[my޾F9 r'&vB|/bu0۾_4@"aMÍй)9YPv6ؖPz2\p ]/D#Efd8\@ '_w…-Jۖn&Cbэb,6> M;jvP`ek_,A cab8E\hu7,sGz@@GCvzt p Q<6Pg}WX?!22%DFF- ,.}Rk^/ Ǐ̀(vE?moCZF\4:gK+Fx<i/^U#m`$ @Kg.v=-vp0 _ni#D"7}; 'HY糅}⪺Wɏ0nٗ=]AbN0 v?n^a t«JSNy:}x$ƍkoZôS.p/ SU =K0!5иcu0`8\̥~Y<_rpQyyG(7sqcܳ= Y _ ;lT10d?@΢U_YNL$^wc"Qƞ*u0)_HNݳzamG[u0i90Y=}1&cgk0&PI0F/*r⮎]vM`c߿( X¬gD们7u } \ ox[W0ȋf,%O_Vz"(1L kt@V0S/0XfF^'8 ǽa(|YL[.;NaD<|&Lyۦ@u!R} ւRAŐwb\(pY3qyރ(`LDQkrJik]R |8Fᩘ7JN/zL E!/k^t/(?GP:||1C~;,E\kBk3^2c`BpiǺMee19Y+/9r%7s/圞r~3uT&xQϞ\^3ċo}*mAC.漟l 2' +D@M =xΘLL*W,ܚ zH4/r<@$puđWVL'5o^ݍ,ꪜ!$k"gϟH 1y{Em6*CwQ{-[лgU;ӎ_2,?mVӦi4ҟFw_[>Ln ,y>Ι_%MQtQqޥ|HzCТn:䔍=& >Ol&f5&!ۥ#[PL=㿐A?7I'~sb$vH3 ?$,[2 y+̅Ї>V^yyQ}(;R)K{K 4C :3d)ӥ:艹w!#bKP~ثhl\y8 "8:tBcEX-V8Vح<\+lqAD\ Q[ߎ o` ߛP0*;^Cr0ʒ,Fi+폖.\C5RKE˿sǐƎ 9G!^ &y=6J \8(h|_VX||5‘8B(₈6~MhW#Jƥh" @ t(pSܺ#~`H@:6=攛ΡQWus*PEQ>B"6EN)3*ʟ@._4w"_!i8ms}l!tyWf6y}#Duhk nzp5|.&5w 5eysbYH #W\4l>9)y^<+A(ZP ByN:(G"\z{`lOܾ[=m!J4/{-a`uo>)xk%@m EZv4M1W Y۟-ăgI; e,gk N_ȑJH@ /Aem3G n7.A5 h }, "jC]GG2 aNB6 ɶ<ڴN'>e14_Eq[-eg/BSPΝP4w(D`lG\07BہgΑImƴAٰoC8v.Cw;045e ⦇s 0keէդa*pn֐M "_ ƴQq֯/% Q{_ں+=(tI VWtuPbט7$sHp "}3DbhB9S+*RDpR|јΞ^K|qC4Z=:?IfHE}4~/VfQ|}.=s*J)2.t;<= m XE?LXS"0,6l& jC$=| p[R“w]''ͭJp$_۰5%-:mÁpz: jB24@Fl݂SUjQRW,Fs`_=AqGxmnD ,eo2$q+3_u  @&ϔ(>&ڽSGvF|'D"Z IigI07@ +@&"SG %FMע֡( G?Ad_@aZlrJX2,;R #/t_E7`6za^y 4}4'5 { l:,CZXQX-%CIA[/cK=(s@/ p Pp=0}! !/z"1/4DL,BKDz/eKҢn<.;<.; e': OܱuN aٽg@m0!lRHJ$jxq*}JUڎY-~q276+ٓo~EA&ƀ1߯<6G]yxDB#I:l\rƱxgU GE㳂Ա-8g4̚ ( Iĺ8jgp҅jU4<mǹ kp(wiiZ |0~[ز8cTӊ:ˊpsQZHai&: p#gI$Bq(=oՕE(sd] GyG(Gb} SEV 6O)}QL0`4- DXoM}# 超zۊ3f⩻a()pTWwSOD~"& \s=Hh/RD!3tC ӏczBՋ; @9sNGݚ(|h[0݃ 5 6vlPD)Ok.x9r}BƱy2]"j AЫʛ.;ɰP_}mP-S,?}NBӉ~D ڵb55Zc0]W'DS+ ϫǀl쀱7JiÜrhȓ"yh`8ROrAN-ݠ]zhz-@ʇ5Pw.rN&AZ n #|G] EP8MkJ۵1En5`Ӳ̜\GZw5 n?bepїxRq\qxcnw^q[abyV?{pr`2Ƣ;\! ^MdکuejŰLi %WZ򔡾ǭ `zLXYQ3NXx"cOAERH4`8 (VV (p;PZ'v9S[={} BލMH:tW̸;6/ tXJ`n6QH԰ߎ5LP+$/+Wi(߉5_ݹ>0JF՜5ad[w@Ji(xMZj~_;g7{q!.2Amך<۽(\R]MA~-2olݏg^ތ>äbph𡮩K΀N~NJ.Dx鮻L#]z4z?z9~R^c(BVeE%' ~ Ŀ: (wj0͠+|p|νo9i)4 5ˢfxnv`fF|0jȳuHYVLi[3A_,og%K@H;IX)|Z LxOeBżY] 3PB?,E:ZeZw>kd?$o6NN=x{Vu-O;a cNh`NTNY'#DսHsߟ\壑ގC>yf&{s}2(4SI=+}AOo۟¡^-W,qeo졓 2>x@2xXt2r!j]iOwex9`U]<;:\}d&toM*'O)Sh箷kQ ¦s&Bƺ 7\ZHg@_RݱOsK2'竰[!D:(T>[G o{/oA"֝Jykibj}מg_ 6I;" xKyŸS: ׳i˿kAV2"c!_ ?LYf?xx浭G9/jY6bV|?9= mHH0pOO}ꮜq|F꾗1L=ZJ͢(ۭcG@lxo[w|igXH2 (oݓW:LB4= 4aG(ؠyT千 6oz}lGF_2& ߲EE,&'ׯڰ2<[]u? ! 4wntW\D9KI Sƒ"Lþw|v@)fImy`sشTH p﫿&U^ߴI@^@g*gMyC`hIDAT+?ȄD#0Pw3;_m`Or $]oY4);:D'Iq`b׽; -z 2 7(:Vsj3½~5[WЁ`@7|V޸c,6,i0 uno tDO@6c@oǮuP^8n%#0C,~hK7xh L6Ra`܀l_ᩘuڅ|x@]O}g {?y1T/0㎿bNKcB(ո~_k )tCo08xNUOsᕎ f1!RY=nH~mÉB@Ay5-hEF;?g > ($P𔕕t|yVWBhGBޭ4n|XRFҌQu?F+(Dp/tBu̳(6gsUc?WC[׾8v.i??*T}*v( ЖOSO=^P9̟&c>? u7n}[ f ].#8\sP4,9ygYU=:S2g1QP  @g}>mR3 I>k4p$f ɀɇfa y+ͭ$0  2!Xmmmp#!'a1Sp'@2B(~Ew=D fPΒ^8 ?>']QQQQqZèIENDB`././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.QuodLibet.png0000664000175000017500000001577114244626671027304 0ustar00nicknickPNG  IHDR>a pHYs\rtEXtSoftwarewww.inkscape.org<IDATx]yxյ;vg5 {XIBh) B|@ }ePA$PK@Ix_ݖeYh?fHlO4s=sqc8H ژX"*X>/w :PRB| χ s1&٘$0&0&4HnwRհnx !)T&^t?1[y٠l $'&wbR$zj(TK{`\ ! jPΕ/IQe)͋ &'!Lԋsx';H12 (:mUY9%g][2e)0(wHz>y0:(PnƋ9k8;IKvFcbv+8_>m<00JKŢ/3L$A@{ݎ';@FſYmJϻP< $Q8,챗삁4Q@N?0g?D(?5 $Q8wКn<4$]$Z'eInO"<ۮ;lx idRL KҧW{nLG>y}CH EnΊMX#;\Sc D0ͿkoL0i=sk뷽$=k ʿgN[ 5bӎwoYoGf "7NM˟R4ALI0ѽtpձO#$H+X G(W4妘'+poV=]kԵ1\=|T[ Bh6*]U7#$'LW?3kĿ==XyO<'5t5{u~yUUU#NA`:ʧnd/@/z3&ɇ$yz.S{=D [./?pGMV=ښ5ku^*S͘(?J"I``_;Ћ;%@嗝zĘ&7wB̑_zU=$ +|Js֬fWl>ybHX~c:O(JiŠ%Sg`ִBd< :18$Uu;6A%PR"sN~N@N$noZZcG# Vߖ]xkyӷMRJzI0 ,_V4i@&Ŗ5nG59T04 &[=ƙu:"e$"3dYrD<:C^vE~8mV0'uLPbʘp@%OGB~+",[֫!)HL:723ep&u-"%-Y|zέ(Ե$68sn Θ[u>QijX0r3&ߕX.t'V:9S䳚 0l38K&tp^\'n hRWbi Fdl u7kTbϡ(J^iTA)_8d9#jY7Q1U;<;0] ?|O2n.97!jP gkBhzM :¡͏ ;T~ԑu@Pj4uѪklC9Y]F t.XuT^=ڋy}CmTrR@N()GT cDYQ"uTSN9(;p=#2P6u{| X Fh *.3ҿfm(i0Wb/㓽!I^jY#7|`(h ʖ\S>-5m4em@=w۫O6B~NrӼ.>_!y>m[vݰ:_BiV]G`Vh*| 0BA(%{[;[;nS0 YEG Z;QUӍoZI;+lt42,* Y "td20ɻ$=I]'`F0F, ]LWjp%0 @rrY9sjXd* A顲%7(_y}CcZX%LL=e0$iB+lRxe e:Fuk^T~k3S:JC0"&'Ɔ?_%9<.HL($'-@%9 LK2y9*CHᄶ,̠%fnAń{oH($`$N*[6a9kV,AOu@T_ 2Q].d>ϕ?/4*NUݐD$вdQ0Ad3פx ګ{B>Wzo^e(ȶ@c`3['[_Lj #@nխt+=JL~`)[t iLl@4E(Comνt3:$Ih$›g !qkQ o4ֽޫqM߅`JZ7(I&ry$,Uc# Qʁޟ6%ׯLpڎ!L mGפ"l0V!. [YV$ j9pW5)IK?R/WhQ-UPˆ= \UmH-_$5-I 9}:uߵD)'r<ܰW{ ÈzaLw9Wy$)zpշ?C.+t-*Yg $G.H~ KFEqi@9iT2cMe$ѧk7>FtiQ.[ǧ #Y%ͱoqU==ǯQC.]ѻXf#i)S1w0Fb략&U\Fy˔7hP?$\(g-DԑE` Mn& Q,℩h/FVf$H\Gsżufiss6gyi r-Ee4;!j#ػ1T\y(-*HWꇊLR{r4 A*Zz#`*aBoDwgeL̚>e _~ha(|xC-T"JHmb״ Χ-_eSӕM)o]Q֞G#o|=V K>HK}N7q-'~u:swF* ͻWtšpaõɉD\ IwGoݮ& :_eAd8؅k}] %{+%0v%AݿzJw^<Q-e?mSKhNķSt 6NN=.GW?"oqn^Ϫp#opʅT'ZØ DzY6p`wX@x*_7#éx5 _t9jjrEX{jiw[ Ds Ly]s1_D_>|8`w-PYse$^Mnd{\j>ۛSZU5(ϥzlCOAPԾO׍rϧI>zkv "OQ3o{h6&*ĺx׶q+"Dw݇u_ Zry &|IyQȖX r#|l(1^}?ŽCO7E~DH-}a88Ѐ#[lb][?2A8G4Q nĉ}oD-$4۪*PW lOq6~?!he_{^5YY='~]dswrGj h$?9u~~P]qihޑ0VT׶#Bկ"j=O}UUsG.TLCdh__ r tl|ze7~JY_'Χ2HvU:ĤWBUaogs0}. 8Gk6fD X*Ku+[wsItT^V?Ӈ!$ 56~]55!/:X]0qd 0Qc@^{Z9Y $8ZvyCoCxd+l{nnٽIpa׶'i=_sxHDn]qdng}ookDx3* N_is{6|qX~xgɴ8|D靺/^zvx^>$Րar;x rJ(/ZpiVa:[?Ӳm|]t["aLrs6+~b/P>$O`g횶2Y !>FFH=iҤW,͚<sFyJ1Apw|дGW 'TuF% frgU6ۗOd!߁Is`w~h+|>N @vS f}kni9KIHw<`ϗ]G>rB 38RzP3U3A6 g.=y5k:oNJMńыDv.Ghpۻk5} 90cPytCzT$f ـ(9oyEE%+frd!DQt 2܃}Vlkp]GՐ#%zz0:B=C/QCܛC}=kwÿ=?1qc8F"IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/status/0000755000175000017500000000000014471213412021356 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/128x128/status/quodlibet-missing-cover.png0000664000175000017500000003740414035600052026645 0ustar00nicknickPNG  IHDR>asBIT|d pHYs'_'_jtEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{ IDATxy%y͊@,|( H&Ak9)Ph%6H>sH'Jf-IF hJL&!-NXg0{U只[}o0CJ|WVU-Eݢ[tnw|3;][tc-ϛ[8NwΟz\y3+T(<@w&n"J|Ͼ _sGY}k1 #0Ɗrqpp%!׾/js+Ke8j5,-/n@Re8w"N??/4M~[t4Sˏ=BϛwR@=SNj4i#B(/}/yxKnH)}.]ŋpe$q2D@ "0@]@^"ݤK;PJPUP|9tib)2(@eK(nUvӵ ~y3L5Ỿ';NV1lRAք4spn,t#0bzC#b 0tӧqkX]n-%z6d$նpql{a) cs #Pw]N^@d|^ߔ|K_a!%W+ [[[8~Zk|Gل=H D`\3 WlKؾN3@0Aј|ێmFPTQV?9cŇRJAHHi"Rq8Bo0ȱ:2"4u.5Q> vp_ׯu͢3/n?y8nAc J s zy+⥋C ˌU+XYnը::jT]%p wRJ!e;I)Eh`{Dz6|hgmzZ\_h *Xj,F%Rj03tF|mR?!IFkDx<<_JrjFK%ZmxVhhZjhZhZT*a sRR[z~14 loⶓwvpUtH3ݝa0A^jʂ;VxEʽEY(! Rb4{ @%"8,A&qBHy~qШ7^1)%(T}ם;=r!p sa}}hۨjjP*=6L~N/_:V*VWqI˸a@8^EU2< _^rWB*|4/%cθQ\APTl(i( &)$0:At;}97<  BzMlmm*()jVWQ5׶v:O!r?;Xef,B` #R&D] @|"A((!)%Ea0=J {MDQ )%ڭ6/p8@DH0+- QG{a8v߿RCBB9; f`-{>g}Ke{Q8{2(_6Q t$3ReRiJ.@ H(I$ ֍@5<1B@ZZ3YDM0n/B$(D%PNghbccqDqiB;ۅh^R{ _5X璕ozӛ}k 3p2a\HQ s%f `ֱ}CY/1p}7Zg&R6( ( )zh b<+5%O< ,nA$ TaV^2gQ$ uZJ{\׭!%Ic\9#ƔRBJ"BspC)D ohVaeu7qjǵkx84$Fݻ ڭ%,--Z<8?noJ)pA \ێoz6IWA4"u(UAaӌi4)Ԓ31_ i"Bg%Nc?c7yXY^ʲI)tE\@@RAƉc!|$iWJ~I{;5~v;$ /A+I.ݘ˟ܩ+f&YN'Iz@!'hSO)09r!3#Z09<~\Zt| @xVWZ~AQ8,r v 9jPE%cF޾Vcx+=0+Ȳ0~?ufxZy^6%Hr(@1C(TB6 ,`$y̟qV8Օ58cg0$I$IX #WkH3-!cA.)%#G7q&^ go>μ.L0 %9EL8a la}})yp0'c 'Nʼnd;;f p('8 0|V:@6ZJ?#v]y: d繘RO5 pu(!!rtv1 !HfҲ.VqۉSB?b8w 9pJ]eBS03p6J J8*Y-\hw_KΙލ^-A@#'KĪzhp8DjY-\5= \R8vn| I`e{>p#"88A, !ӎF:o\tem\QoMS]f28:qlzwRHQk4>wZC^@e,8Al$RI~zil`eIؐ~M$ѮUpW:ƟdK.Q)3XRW1FH O;2y( p8vHͺer8ɐg眡Zs㟥b6,R c@Е̗Rիp泚&;%2A n$IƒRF HpZIbUWR O\ 2Rd\BhVb0L2-:$v&=yɐD y#N"/Nfb7߻71kn FzHb9JB^oVe IZnip$1Y8\{̼Bf:{MҬ sVʐq9c ߟsWs!Qp3gΘn^!Zѯv=,5Ȣo|;j5\R =q}XdƏUJFrR*H6Vj4Ԙ1@Ic%@nnT$H̺yʠUF HtEQT0?ȅ( "u^7ҕm\rRJ9sn:adzT0BYOЉ:Aݔtܽy.P;π>r*~=z  D>hp6r#@XѧxM^g+3_i .\(;:b^ &DB"7 paooOfF3)t UDGa;|Jͥ,kJbe%Jw7ȳ/Έ\3 dc6- D0 pPG*)*9j jIڛj1Ct]dY}]-x iL䢌oM@Hp)GO"]IU~?@{TN `97((d.sQ6L.ݖ_;=kAaZ ly\Zf>8Z H=zࠐp邀1}4Jo4*leiMg^9PJtɱ1 h6Oyܖ9 02y:1<*U(Ph_ ӹ F(.ȅNjcH)于.#?v)u>e )`kR_BdNa,1o|@pHx ͋2Π̋)^ȕK2{mY&>"lSlZ y) *L9*MK֏yyƣ麷 lRJ0ERObW?!+eM]pm `Y_U}ͮ*q/ptӨ|Z 弨V+lM2cr))lidh6pA@d?d?HzŜ`Z+g "YHA))RObHC7b`RpA*WQ E4|K2G#FT*z^<#a(J RIaFVfz nF5>N!stňH#*B*`+H,ho0 ĤpB!SŴ,E]|l V7 "b0`0ADU|0vC1fcftpVH Uu?o4& `DH+@@ԘlQl'ʖ&MntCD@YG&RJja F`My)⛛XYYACG5-h6X^^ҒτO8@3A] Ԍw^\@M4~ib.h@t0js %)㒤H$_La8.9R79f%")>u!Fes~Ac}} &dI-><ljSO`ct_LqQۨ`$F^z28.&|xV2'Cť8M@\ Vy}A-0/40kIi "jȤlmc`iSj51wiӼ}LIDAT3iVH'wW֑|kה7ǒs3DVj^2ld̈N"uM$IVUj&w#;he<0 Ru9Y<}VLknT_(aXw+XT B9@o0Q+8+ Wj( 絓>NS 4<\D *;,okQTA#gOO݁a21KU g Zm,`6gcTNCfftMy ̴@\kv򣨴}LQ$ (ج KE 3$Yl()hcoO$pGrhX9tfV&"-ȓ"?av6_'MLeĨ<1Dz=k i/*)v6#rz"nh n`<Dܐ0QoVՙ!r$i;%iNfIxAYZx q0 ( Qe$"t]( NIV*<`K;QG2Yn&_hA 35*o-Q8ƥKf?mg1}敟vc" ?s_^P b ;ܨH͘.2Nxgdx!7=cww Jr+0qi] TӞoڷw]mA1?P03t]7ro{Wk` I#B:wQg\qy. k=uܺ0AaY["nPg\/ #C]Dq(4 gΜ{~Ea˵,[Ϩ~uq6c: _B-@Fr*1GP!ڿt ZRH !(8}4J.}'E64IZl>Kyau={&[u5cg匣Q z&n.Ξ=^O/u-Ǧ?1]~͜2?(.()J0q?տ_#hODg cfqkUgH ^1lٳg5eh?t1ta^q"c=YfisOnk??~v*zðp0u:qy *-Dw[be)~1!0ؾ@طfà <ZńA$t}y=uW^3<홞_u?X^En~&^.IJi 7Ғ!^̢YA.tzX|0lԊR?fF~4Mv]|i],{~Vk4u?+IK[9Bte98JmԪ RitwBjNܘ1v>JWzh5X[[E;;;X^^Fi)97P)Uu8^J]!Ij˨:ș&40^x-R#LYHQp[Fdh5kPJ S@i:8*&(B$t:X^^Zb6E=?<0zp/`nqs] $I2;Rz;mnY]4Ji\án.Kwaͻ$Ad%vUtvS+5=a|fr4PqAd*\7cv0lRyOTs,Q1]Otz^,RYcii ]yn5s=;_81$)p$? b`f^Ul{Na `@l1v̗UhW~ 43U|4Uil4zP|aaQ+zv%*s=k-zZJEQ`5iJ, fYJL6$ݡsV Jt~!Q8qr%@O4QB`VP1[@U}w?i]7 !deYm,;YIPdH\ 3lJsqZR*t=tҋ:jբUFQTCb~l+ Fs HҴuHSک`s`UDh>bg{ :'$sh+h>F{s@$qBvL\ Yb )jI"IRqȈT1n .:`PPUM a!"Dq<ȳqRo- fw3.ϫVE} 9&:UFVo{…BB*hWl~#HJfISJh0$~U*3DqbȬ]ȕRJeY&$I ) "IDJbDZ.$8EY.F񜒀T @/Zc(32ŎOAFuk588K1ADѤyBUYL),{J)RRJ+RD㥔 RJ$8=sVP#+Jf1RuP R(bpbJT*(()x@XPu"jA. v y]l@zί/Kw޻V *=9uJx|'Ƙ_V4͢8A383=N9#I)f")ľe{ibe2 $S 2 *2H I1)qH23Ǝ3T% N駟C)v}S~My?WL9k &O={O=TVo}Ŭ!ZV1!|s.`RJch+L[p`8RP  ʠI1,yƘ >t >Oc&6 @Mo򥥥~=}~jv39N;c`d ~Α NcܧcLV%-LAa˕>Q 1$!C3=q?_׿0q\802 0ejޟ{kokiƚm8rb7Qͧ`ڱw84-íS1JA~G=ַomQԅ[9F8t.SJ:ݳ2V \#"}h_.K_\f22B}'?z"|\L A3H8z~Ͽ瑓ǏywN8$q0 KLҠ?x.}`^Ƙ6N`L\泂1HeW]HY/8s|lߚ֜*@j;OLZi7gu((a+ Gw.kz>.&`."8s~ܙ~{jiyQ"Uvf#T*ailPJy.K)!D8Z=6jLY{ǜsiXSs%" 1Lc1+zon⍯{? 7n;e2M;e~ѭˏο$?zHh6"JQȌٻ4MV]]qzyޖ*l0rY3_RRܴ7qDe"RI)C>g<s3_¥+_) <~φk%ַ'~ _W~ԩSKSJ8pFՕ5=ܙԁ1 J%@YOJ%uLe > !Ps i$:қK~:裿sx1n6,YsZ 0^M??xc;rkk˕j$+Rt Ui}{G*="B&e`9V0M8MB_@DCI='|.% tY,͂ߧ+/|gLj]F8gR}~w>$֦j6~;koAyJTH))(JtDȤDJ%GgImg裟Iq?OO~gN'zKK0RI \FgX^Z.VE{}Tw=si1k LdI%R!%1ȕ" w3PĔvi:8}G?{3%דuPxb?8yq݇DQ z+@?=/e/ !Rp2v(<˙bPDJOFJSTD\L)`;ЦR?LN, , (Ϟz+՛|< \ Ź~kW>/cG{j9:킈V9r! cT< aׄ=)eZ[HD )$ ymXBABi*Ǹ[a]>y3?rX(Ns$-`뮻~K_zOWcX_] ~4MS]2\fLrcI;f SJ2"NJ)s_ 891ŘVv\|ޕ7SoxÛF}i"F_|W]"*mEV׉)aMq9\O\> ^E0' Jz_`+L)ESSቴ z0C?ȗn7-ͼ $b c?wA~}l>ڇwv#/", 8 Cokkk/_+_ZqaccG6W1.}N˧_%?)@qNgߚf1(\~ NjLZeyT :uK}ם[PVQC( "ϤB~9I3 *%ҩa's?,DzMox K" 5j%x}[X_S*`%A1T2W?+z3<9?!hJ! zS>w ] v ٟ}폼_l[o715:=Hf9(DhS l#Ra=@gyoO+<7QLϼ]w,Z=N- ~=X{'1V V%=r A' (F .!D @e͏ #|7%j`>UU/?mN]OڛkRi`}ZQ$F!83 ]dY#o~'1b0|yTc@@Oe/**FL_&V׊ai#IBY wBsϟo xуB[E/ {G^ 0|! Z:6OP zL"?Co{%[6-b^~w3DT AV_*~I<ϔ?{?0jӀpt i\`#7k}sgۃRVh7VOJ]7|dž(`~S篂Z*pgd;-nBS#y^L_\Co}#ȍ-?/J$B u wv- }_ɕwrJݢ,䋚n-E軞IYs'oIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/16x16/0000755000175000017500000000000014471213412017663 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/16x16/apps/0000755000175000017500000000000014471213412020626 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/16x16/apps/io.github.quodlibet.ExFalso.png0000664000175000017500000000146214244626671026575 0ustar00nicknickPNG  IHDRa pHYs;;jtEXtSoftwarewww.inkscape.org<IDAT8}[HTQ3JދTJ,JBeOݛ!.O0 & (襗.TA/eA$E8ٜ{j۬k%&*@Z;@cӵ`Dd)OkYffl̵VɌϑ=L Qy?-JyKVIJ*:s`7(-  ٕ#kA;Qr^ #=:%Еnfpm h \lt>tGh _6V]C gkejvMNfB 8!'.+ӗ+U[چ6>&d3 B*W8mBT|B<]XRgj=ϥ =NcƧBR]ۄeYgbB.(+1( w= [VNgφLM{h R 6./3q"MuUEm_vKnV2~=\˝ͼiª<3 74<B@kܮ˹wp0@"=-c(VMXaJ exA18 v\yzeU? '7I 3#?ֺ 1nޤ̝)ր=Tkxy `1@*ggdXaKz2@9Y=`]˛]eZ>n6;tR"6m UW\0ɴܷFSwƹ< *X*y]ͅJ@Sւ) 4b5S2P!QV2b4%YSR"pas$"`Vruҥ! o+H ضLā ҼsXs ʂvj@2U tdFy1'reu~IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/16x16/status/0000755000175000017500000000000014471213412021206 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/16x16/status/quodlibet-missing-cover.png0000664000175000017500000000163614035600052026473 0ustar00nicknickPNG  IHDRasBIT|d pHYsnrtEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{IDAT8}k\u?;;d&1IMIhҖ-.wYvQQ`V*(hE7XtZ)HLk3&Ltfܙ;?6C@gu|r1ƇW>f=w/w*JiqIm[14oܹy󚽲b7^}ⅸEP.WV;1K,DX__֯prpZ[[~gs'fgL&ގFkiAݦӉPJb`7_s߽Wz0Ȇl{6 S[)ۣR߮^}yyYC|+Ro\mwv:?}D$/yaA_}gHZ$3f?}Ad-XS,IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/0000755000175000017500000000000014471213412017661 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/apps/0000755000175000017500000000000014471213412020624 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/apps/io.github.quodlibet.ExFalso.png0000664000175000017500000000234314244626671026572 0ustar00nicknickPNG  IHDRw= pHYsXXxKbtEXtSoftwarewww.inkscape.org<pIDATHmhU?{b4暮-*_$DnWE %HDB!C "&S]ڜ{p>N/vCzyw~w>DMJe6• +Ю=9'1ڑp"Gm>k3T* B{n45+|tpօk: 3 x :MqSU:v"_s 5ctU!cL*<]6lN(fN .Оk'$uОCh*Iʮ̪ה_ ;}G>NWE2c+@|'i˪VAT48#}O[wLttˬ])T>c#;;z= & Kf[5fza*@{vkǻýn؛7bg<|_$TSQIENDB`././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/apps/io.github.quodlibet.QuodLibet.png0000664000175000017500000000201114244626671027111 0ustar00nicknickPNG  IHDRw= pHYsXXxKbtEXtSoftwarewww.inkscape.org<IDATH[hU眹l7ݴ)ԥAдxAO4RVRzb!&RLB߬(b\M\Ifgvn53k3s7̜g#&3jIʻb5*i8p^s1׆MNXLwo'Œ J —vf{=o-O]^_e]˘,-ƇOdo&SS&%׵9Z rX)z <ʯjs;|$V"'Eo(%l_]9PA _yovH'LuY=|:v?1Qo Vl:7Z&x 3= "qVqz@6;dVo& ݴq 4G ci,0V0~UV Ws1r3%` ;1F ݹP1Ryk6V=nyէ6UŁh-#[kg 59" nj#;>iw,cU cjcz驑?jtSRgַAlp.5 1_8hWQ#mٟ㷡BT IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/status/0000755000175000017500000000000014471213412021204 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/24x24/status/quodlibet-missing-cover.png0000664000175000017500000000274714035600052026475 0ustar00nicknickPNG  IHDRw=sBIT|d pHYsbb8ztEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{;IDATHKlW1oIZ5-qIJExТF]`5!JA X 6A2 . F "UQQVlBh3DZg{xBj*s={\ӹs$ffg39yK*PU66=@Vt0Q(\eyJZ)hYvK>ÿ{r&s&X6JR{1e~_mˀ2x?\chLY{'&)KMnpEx*QFc8y$o ~+FXkmZ@DF4i^Og|`1"VE2lD#$hvFRXg|sp:a166FQ!!IR'PJ!ds{u4gl/5,,Oav( VVW: 81ARDAsde%XOTY][^rkc a $"(V;~?()Ks㉣Cpν=@CDŽa=R 6H)XZ^&i4x)C5a9 B MHYH!hZ8JKJI ;lkwN}3%{DvM%DF=hp7Sh{WW[ 2! H 4l9grg+Is "姮qc5L lԿ>h_{w64Z 38"8[0d{]T7A(=n}`犟??" a7}wfDabS;j!n_9ܡ%<'Սr?`{]/}5;p*_agVrs_&R]6-: pϸ7z!EnăQeoWˉo|? Zk`0^xwyȩK.T7AAi_M{W{g0HF֟Ǿ̉rPzVݻ@,`\F9H0ë6A@iv$.~$pԋHAH$ D*][6~yu ) ؍4~{eF !nDYެߓcCy쒫2M^x:ؐD~{L5ѓ3?2" ? _vU9eW6#.Ӯ}2_ްgC# δ |$4!W䔎}b;.SŢq ,Ljr%$GP)2t[ 7&$ }[|E#3.&7(3 0FFJqx7b|{nϏ񭙃)ag6v\|{%W|1/giOV1 Fd/_ׅm[N1uB@$ylބy/u} T ;ә ]:9gAk&(V$__,/}cw-&jY ɮi%g,}>g\@ڒ@ <1gH<4 r(Q;ɯi}*spġ8t/ܩ `$ɀ${ "-t$@/*yœ잚9H }&h|E0%KN<ՠAŴ.L|kOμi֭>TYK;H7>+-Iu~ߪ;ssBcuX$ڑSs\͸B%JU~3odoR |uHj֫J1w+ IՎC-Ѵ51 ެFλm,(.@F,̢O5BHkj5׉)̱x쾫%H! +A *FO?6sť7fI^4aH`:eDAbE3[Sv?W $?c n! H(YGnEgO i,#ا $NHc$U%_?(AW-Fyǂ4}6蟉!!Rq(TY|^OIv8 D3?vQzMٯmH+[ߎΟf2mѪzaO7z &_ n™7Hq< U: &3NQ ,d1!7UbƐs + ?'EPM"TnXp/WWX"#g?#?45J&n{'-!RAO#j4Hjw\`l43cC{|{@de"{Nq񏾲ٻ:㐒S=pɸ.von½F'M&.4ٛ6W˦VH"y7>]'-O,3]vN8 1HEJŊnL@F,to^ϊ'VݾuHRV 7o_8D0Yc`Y?֏,.YU ⿮eyR}8tt,%y97~nڟBuL]k$/E#l pd>;&ן!E9ڽoWtm˿|OY=H+h 척9?#,;@$:BH$Զ$R͸O=\qyެm 1zH.V]b6{9ѭ博CoDI T-p/W%)SwbFrK|`-]+@^Wy_OOxgL<|e}WcDi >S{V0E˓l¥;I1H /,dC2a)*4>Yz0 B- r"Ga4?Ȓs,v9Fє*l0{YMq"¼Qq#^^}7nklVl>g"+߼W.&]ԾY׫:CV@ut!/VwLQ7st +A2}͊&qִ;Kϙ& (N@~pzHo:&Bd`zYx"{5k}a.ŹFsM# Wl5"lk*` pe-vH9q>~X0A6?ԱY \pxti()B}Sj ztg+ b0̾6Ha,*_Ήqk@wo[KMJk[ԊH 4Ikٛ[W+  LXz߭|t^y: 0cPpit /c [5@賮p@(?',&'u W.&ƾM|$)oWgH π]=!#g+G7"V@<8Ez>%Hӿ.ɺfy|mG=Lv\( šP5T֡5 k?D_lKF׍L/2.<.dyqyz\edFZC[G7Z;hmF[G7[P]߆n)j0Fe!ՠ~S,o?cY>< OǗ0C9!"hLj$ Ri_-VZě\BB^Ե,n[~ ],0dY0aT Ǝ({ {oqttp {zC5hĠ!D\B@A॰qwU-KW o:N+97M5@ 詿1{8UUz7n)XGgܘ8G$D)Î'zaz*k42 LP3P%)D.n+T ]AA*䆚}C{ +@K,_>wqMD[޸(J 1m7- 0BPZg Kfbkl&=c^|@6R~}%?W7%o>TV7Y 5 wYdgm=8/'pZz+!R=CAGx$!dwy1ZC$&ß OfaIgG-Q`4[㞈pɃk."{O9caP<wF-q8^g7H!+0ܡQe7SK¯?k/n}"&{-MiǞX(I;3mY2sP{ e2xk%+ q8^/5w $ $ ]nn߱_Mؙ>(BA[%k|ٗ}u3'뽿уYnC{xuD3"kG[m3WCK{Ś ܂œ̤ F ){Ȭe"Nn@<~y >ٛuqww$ ĸG^v"ᛷ.YF'K_\-zGuS݄Ux54`<,ąw-"\cEyZwHD H2!h >MK$0-EJ3`B`1ttmCV< &-(@x!MB,, X2 H" Hxmn=Rc8$egiMM裂pbFk ,AB|#_tJ2ܞyAc$1\ٵ 3Pa?a+u 3 "> v/pg_ 5 $_ 5bC0G?[[@UbSK Zp%M.[Z@!pbCAd,(;;TU? ?` TW@lHobԮq`/ D)C}S{[=N6Ǿ DqBx\ެE8FsPP'[x?rvPRf6u1*E7\|Tsخ RTնkͬF ϢX3!< .+z w] DBywk;+(ed$M޹+@a@n ;S% M0,17|Cg\xPv> I指$xB^YhbGkPp>0!ѣϿ}?WFXNX$  ڦz$bठnM)ikp`({>eSXi_=sb? +a%]xqN;mW0LqlLQkcC{'BM} h&p{΁J1bFͿ}"!Rq 'aatX%ێVP0wL$0FۄʰnoB:HG VKƟ '+(TVLUB)Ea^&X(@9\QMBl9,i'VY.qg IwgRb0/~ vOB0ofo|.>;N5&Xn"{D׎gg`Cΐg#@`,ެZvQ[)f{c@1T׷5+ac8f~ҭ?̼0̝ #bH%cʗ\1nr 0:(I g3%!e@<6vt ,叅V5ٓqbbϛ)P?8b.p!6ٺ20+Ãsf6 `֞ {ºGa")Ƀ${g! @ў(u !f9(s+vlJ.=~ [@c/x}b3 kI O#@`4@eٝe1!%r$L:P(0dgxxزAf.ܑ& d E IDATX.ɝ19R\CJTc;XC\PIvcBTH˸n<ؾ%ᷓL[u.o 2]3>R0 i76ٺc _yrT ,a%yiy7W߼B5[87o DȞP *6k$iD T@To+>= dgyūρ7>F-H]C-TGZ;A|98T_'N M ݭV'޷h~/o" ޤ_S@$0 #@QQ, aJ _:nm$ jdx0iAX0{|JSޞjhO]`ٚ$eV?p!g\<QfJJ'`P2$衅ŝC\,anp)Vn }uwtᛟY҄D)SG'b bhal"H& 'ҠRs1ګ@+3% ZAɕx[Wq‚_Q>(fR|l:떰Jh__XL.A-eϩd iFX\8w|ZDcD 2qt/(cAMC|^z'Z:+!1Bz|s`֔= }hAQV !R^ mK3Q{ETs@n֮7Edmx5Z$(B5D`o"^ e>#nYZ1P B[;񓿾gk(eg;>Jz;yD8D " %FEYC&aLGhuhA| 0JxAASk Lz_=[yeAͩ3 b TqP>@_@ YvybiVz p:.?>`۾T5>ė<ڌa4t7VׄB$%\ 0ڟQ~nY $A +*F])0 h n[jnqxcͧ`>A" i2 Ї?mV6p!Y5/TMϬ" /*T)CF^;nE{&~\̝λD0#AX'.effg1/UeL>zB/?* B I]A`.6F$ ^$ B%0BbCl;IJE30a:qjMB)$P竬nT׵ (69>d`܈b1y8ʊ!U ďo–=ŠxwtZj` ZM nYˆ<(ǰ\ /ۇL.m~ lāz|z:ZV\ݘZyL%o1"ΐ2₢)!j AJ h( 0 ~|k fYGa¨bY /2[ލN5Uu-nD&T׷#iZ.+UOugaxi^o1O4gL}i);O`ϡj5 𺑗gaԐZ1ÊPZ I +U3Ff: ŚƚXBD{>*5@"lHE+t{Vcm= yLHZ|Wrm# x|B Nwn_ŹIy{po2a1KlF# YM=Z}(~tANz0bm}`dLA6@c֘0 %1J)V|;IHR߄6vA!/~1<.I PXӅ EO ;z,UnkXSaHI'll3M ^[ IH7tw .;o uZ9p}0JwGTJOsz#5071E2 J&EgLa&M_|n>ke;>~gX\2+ S݈j }&B$@(-_ f\siW/T%!ZG^l xLGhK}km;GE$eM] B$ Ip5_n=ԿI": "!hk4X=*4 ]ѷ@HH$]aea{d#f}D/Q_u%{ Λ]  `aFzh@?FV 2Ǿ-uia  &95 A{/0E[4/7 ஛G[Dv#Nbm}&DDe580C=g0Yk 7- )>k: -> 7-=q}^U@,=p祸OCQSӭ&LiBV=4#Ughn 0I΍@" Q9cͼ֬3Y>,3= >D"x\P[F^Tg7H1e9+kK̰5VLf@;0U1h 05 w߃aF`T^sgci8}pȒdq|6eg{;/~ fxW7EUmk alP@ L&<#m܀HÂ` jerV fcc1(`6a+ᓝGc]+ϟs%.Y}[zM]i뮀\5,f 0AL rψɜUܲUοgyd,>s<.?o N ,ew(A<+lLDp 7s48 >F TK2Pۃ $ ` cjDYH@| 2_ƵLGםp-@csl`*u/´ClϜ=Z LA-jۛPDW (X 0 #g}z.}vܺ4m FY8z-A➇^B?`q%`,9k"tiAW}\A|v+nD1 t<چ LK߉g+  \RZTIU3p >YJi>$^w!Xe!ƴB O:5^Q%o:q4 0X =,Q'~t-䥝E}?43^xo+U7vCI"(ZV+@rӈ6lh9ԊYQhMŚJ0À.zݹygC߼DΗfDm7G0 (eUsm 0i} A?]T 8@8 B1 pWMT,_M=23xg3 vV: )0 yTo`!7k7w.,-m]8goMD<(ee0j0D͘exXt6G վ? DDKNǸm: ci+IxeVﲳC9Yf n@wsADY(]{o Vh.>.;>0%kKAG;p mJP; ]hz`Kj7XC{` mRPѣưlTe݈ %p]7-c}c 7,]_[3ih0%P|lk.R Rd0k @w`zk-Z >v(UM 6|93G+tq$; YW;>0@qA&ƍ,J{WU\ ޕ[c=O#͌+(en,#];K T y0Ѽ*DUF@ Ѵ5}mg>A"w?seK%P_֜0rȶEA 3EyښД ';;mB @ }(`gcXqQPl$ ԧҝ@Gwf% W?-lJ``Y[܎$@ĶWA0SP0ӛf``a /|;:s^{LS` wI+@onJQ\ oi :FMaBşl0$'m t%0H ;W IႁAsm1f0d`G'1? 4&?Y";P G_),`Mw(en`GmGH[a#RԺ14?LN?`l$KΝ C3hD`9- `7@% @zóUZb<}a (M8QeE*km_x`h@WFcM+bL[@ov5oooeE9,`l1$>_b@҉v `ᖥgP!Vᕟrj-?b4YA]M5kb#tؐb ,rZ,yu@×9.OB f:]T)'wvkhw "9VA 2}߈2ns&[$BPV.>ݔ3:s̖arr`ɻ:xEuk2" Rz#TIV&Z A|ﱷm=Pq|fX~zqZrP fӁݵ 5&0`I.d:@:{01UJv$ܺ:~ +Ão޲@~U$` N`զcFV xxCUuK?eDzm*ilU $˟76'!\8 1$`vDHE-5D?t~k@.pX@V FJ1c %1_|2Pf uqnb㑏߄j_7?c bShjD]S{7gǞ]/y44R!YIB%AXk@;H(vo~UQV~g[0j=JVm /IJ~ ʻ<ڨvBp֌r|B SP0AEB_F{ߤWpCڕU2vY6|c w\=7ōgN9SF`L./EQ~VHz{EITm&q Rs0ݭӶe @  ' J';uC#^@6ثe'ǵ(ca$@n Q  `3@=(#Ix?5[ac`Ѽlʇbhq.ʊ189";Ӄ,ZXSm~t;ۯ.wӏ :c^ ۅ¼LdcHQ6Ə*|]4i5|)(_#f" Ds#Ԇ@Kt@5A9@ ϼ8~);NǶ J8U+LrM5ȿB}10 ;4AdŸWe m]ؾJ4~`O̰Vٛ3yz+P#"^O*4={+#wF~cڃE`g/9>wJPԆ?:ϵP|D5@*7LxQ "r#z!(Ըf"z|D'||o}V`:θ٬2_w㒙}=Rn9!Dž >Iua Ɍ(ƈp, 2п0mR[N(s/ oEa\^KƤ25}8΀v\<`%cT,}l?9 q qěx)'s\z kMN/PyV+ͮ ߗx_Zcx7M'D,D<_]<'mHg1Bډ?nAWwP>Mcu"4R[TuDp5 @m~k;q磪0g:OBMDl?Cf\2`~B"`:Zd8L)CROHϊx`;N|Ƣqgsg$& +(zBO{|_ >Ub |Ӵa2-]𔙺*h[GPid&X&!A "@ ! vܦk)~w D VwգCO_6/vRBAV\3KA%c ]<?-Ƿ!Q׀k ؇+D\a梶dqݱBƚ=x#mS}Wk_oj#|\yu ؞^!%"*B g@V@ukŊG߂@$;={ؔo'l dQ轁wJms+RGܱZ"hoqmA)Ħ̎qc^bjAӞڽjµ?C=ɝ1JP++ʉtY2 ۱bsTH'&ol=#B8BHa'#$VU@ws+U^܊$q+3ho/K.{d >z.㐢~^/څ^D o}]ñc!c`Dq( 6]GahWCW[y#N{ś7Cgc𺐛}O@A?ޏ߉M{c7($T LjUk%}^a}US2CDTnP\ N-GWw/|I$8 $GG%2\۟kڂWWFK{W1Bg5aZ_X>ŸLBo #v:>XWj^( ko=t_?$?FX&ϸzn81nlV +ۚL~A㾑qr?_҂",Z;C&_. m*@k@bS n=RGY5[YoC 3nx(*G{BbM[?_}j_$2OO h9/?]vkM511n?ۛ@!m/f~$7i#Fy7'TIM${.hk{n2UG`F tTU;7>0mFć쐄{ⲵϚ{iAh4AUondQxq8I0Ȃo& =L};~Z@w< #矢R` T|gG ?G ofB3ʼnQexm~ cI$Y!_V:[jNA5_#?PLۤ# jt]fP5/+ ?!ӄ] 7FE'p?驽+vC58B>}' v6oLmZ^r:n5ïA0 /o_v-¯j|ann_~ G wx@5y?n D PǿGˀGV,=p k pj\lC^.b1-Bo|wFt4~_ @̓{iK=zhpgЩ"yR0Z1/^=fɺ|AK{rg![}S0R` c=Gžw3Z_ U'ֿ7*+R@'3pf%L".b-CYa6~sR0=c5<{@` ~ qim8`@O~ ŸA>A:\G>AsF7φ-7Oƾ: BŞ5Gd~ ַ8f(uOt"R* {SkBdf`xc]CKfa7rXlC 3ߎ[_Oy?"P˔}M(y]rNό*@>43FJ18-hiT34vhW] y]*7_Pt.=;k˗=!- #-klںoE檝x4B3Pk7;g˛YB%29{]~b.|h~ַ5c?yfOka5; >\?vh7;s V]&"eK;oc֓{@=̹JE0H@4HO`}9n_䄜M3:?I;?phk厇@~~hR釛 .reNM"B2u(H|,td9f';PZM9æY%g*=m_yU>GV?&B~~~=U!qZgh|= /49񹻪j_ N{`r4xT3K']aa~a%'Cb8˝!ݰA'؝aZVl${乒Ώߩ,Bme%խ/i9pjm?؟Sj tinxyF|LZ$?bw4@5ӗ~`WK z"p@0tڬҹFM<N;B?`K~PZW_ڌ $AhDpp~ٛ7xلHm; ݶGOyr>? x!r|GUǩrN>xս{'.KT]**oAR]WV`W-}0 ԉ,CPKϔdwaJ[ -h_{xcw}~`_$ :a(@+;dRVɘ`4|t+BU~``[V.AuVme%c&I.Oq խ9ToW(?Ö}b0X"5` 7>Dr24?U_w=Ʒj #Y  ?|wzrJ7RGz ~^?h9@4">9S/o7;1 8H* 6k R/b0`X2Tk9p/kYK tGEՏ[0 n p"ˆd{ GJH$9;t4?Z#`W/izs?AAN搉CFu˭E +'tA th#k-Ƌxx* p 2lhdve>KrM_(m[t􃿼 vtUz?'8;[ f 2A&\ݱ${ݾ))lcJw{jӋ[`}V"BndL[2x‚K3 F\LdWn:@5|G <u@tK9k Za|fIΐ|XVr?1@n('$"11n_y&;don8WF(7DrJSb-00h&o;h:TUR@^!{fOH d`%JpGx/[0";ᾼaC=Yy%;+Wr{˛+ɞ\IvD ILB1JBAƔnX0+ v7)oo8XY|x`W3Ͻ@wѤ&w}@z !n}B0/%^Bq"B vw|!UHERh=pDK\EJ4CA8mponVLG.;HS8`*Ƚ}v`#80x  MnЂ*]&wIENDB`././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/256x256/apps/io.github.quodlibet.QuodLibet.png0000664000175000017500000004011214244626671027273 0ustar00nicknickPNG  IHDR\rf pHYs'tEXtSoftwarewww.inkscape.org< IDATxw\Ui7lM車%D EAE+*b) EDD_P:'D!F $nnrm޹;N9|&=3k?p pTNYV2+Wt_̜dt0q<$n@zi~W[.Wn'o|=7|gy|ɋ?S3/>):ݗ N^!Nϊii~{^.YO9;ӫf.{Yp8OQDk/[!@rY ~zyQjw"M .CJk,/.]}}p A f. O dD፞P\&Vt@qj§<z9<:kew(!K椖7w2oʐ!\ !hOekgY 9*&0撢BnT4÷6zu`< fN"T8Kk>]<~κ;"K/ڇAaH㧠Q( /]L3&Pŀ Az!D(tYuۑc"+"OAHlIMWFpHowUL\2!B Ұ0~חoKGEPI}?Sej%G]+ pH9Dd@HV2x%5'^ : ߏnLO .ѥX~4̛V9k0%'DQ0ߏ>/{p:P;v7! \kFM Q@N!Bd#7Ol`w/*&)S>}Sӳ0nMFOA!bi3 aqx<>!|T߂m4dͰ-nAQ4ݽpa}j/Ϣ+v7(&u+gcD/ :{c<Љ`)cm "] N@۵;"Ulf*W;ΒѿA2"?R\uI KXi/V`4hVV@=:gɦJnAA[?7A_z<+Ȧ$9ӷ㩘7lhenC{je'qY1~ٓkpŊE={@7[!Ci>RpH pW(xppN8k+' 1ܦ ?P^o kKS Ս+5# PŠA%" ߣ/h; jүnɗD<$c[m>p ¢YlhA X0c,.9g.z *B(5Q`7<' QT>dwo"K@ݳ?{/Ewmn_u%R\tZjII ,Kea$7od'd-@FM>uGv 5?)wr? ٸbl℩)3y! !{ٳ"`Y07!E%5+ra[=; p_|QSHRe6/'HTɘԪ2ڡi0r|Uȿ{~B8nW|LfJ>sg / Xڛ{3܎r39@< H-NOuS]3-XZUYwkϕq݄2:3Q@gIB<NJ[)ZAƭc;x #d|vD\ *l'o:HSjƲ*Wquiv1-| =܎<ގVJ_7젨zҵHӈ@:1k.'c|m/L@G|/Og^ް>r.DwElaѐT Ο:3*L'`³釀hJH8f]eý0ǵ6 %< EñN[6"Vd ϫFLhCŕcF^,7?q38eG9y!zъ#3S5'\Eپ  +h :[65>1xK'S%g HN1mf8/Z/A߀iڟK@BDp2R8$ Жr*.,BdfGۂA| pCʁD=. Bqʹ@T cƅ7!Ι)8^=t2k (૷=ԛ pFDOUO@d%J&eξi h?1<}3>Gʷ eiՠygc]I( H(-Sp,X @ L8 0A }On'we$#wi ~LQAd0p;no[ԖF}^G>@Bg.B €d7JJj#Aeݍ??D.dyQ銭 q?D=/sjҐtzQWT}"ߗyK ýd'dQP2Pw+ϊb%'@$@=xD6\J){n}=0׼&9^ ^cp.9$4@8*'|7P Å݆%5lաyDԣ/f:=՟P<a1{G :'O>HbD<mQ4jY"'/xiQ9A"rR BeπR*꾄|HcCi cx;6#EFfoOZWQ}рI8EW ?`<VƢ!gdoV=Ak DzB;x kƯUsE_hEMA +4%; {μz!BuSn*/ +9x冯ت2@u!J=ce w8kn/e30p5W7>? YD[4x+.X m.@y JH(x @$Ddw:V.Y/e qY32ϕ8IDAT'-@JhrN-D$MmI g8 j+#uUUbJ5R + ,AHEюyޒ9Հ9;p€!_O\ۄǵc'9Z1x6 V-&jApldXh|C1~Wiϱ0€7N:V\%il;((g5aFW`XsQ.!3r{Ҡ치Rd9qv 4k Mp80w8 c VWܢSB K#L'񷉓  y؏!m c a'26>b`|XE4vNaBdP( Bl!"Db| A0px[7\ NvI c5+-fRHQJ^O@ R)l'/T:Y @h86ʁ%*52Y Ķ(D隣$ۓKHrWA@\uhX> 'ȸa[`cpuNjxi1=Ufh8w D~bR}^;ݴ@Eb:l 8\{ao0 BH)ކq2IOy/}:Ԍmչa;acH!xƱXIi">SOCAq3c>Mkgs/Jmgd#HSAϱxRdG1? NkoiE@?5w fy}~q`bGG*4v5i<4ж @lakώ1=e~VƯl}љs_{b6`t it `km]Hs@ ­^;LԚbz}j.cEmxz&;VW5^Ad7\3ۯfM=>tl'P?p1\N1vmր}ڔ{D_L"`Jkn,q  l}gwJoޕ׼E7 RXs!I/~r)<~*XԍFҰaG"= :v6nE @H䛐|GUMJlF%'z/CƜ$/?91/efؾ_fZ\@\VmG ۪!|Y'߯uVE99@^Kh"@(@"K[=SƛK`sh7`bޟuJU}[  ސ=gq'8'S)U~pT3_+?rD$7(ۊ[QK}m$ {Z7p~_DIjY{ zC(n5lk|B+5"τ-yIoF\W:~έD癓S,q)88mx✽+Dq[L3h/Cw"o2 ؽSӾMt-NXtbȅϭ8 'Vc1;mK=ik$QWR7dͮ?Gd5mB?@ͯ FW߾(m1"Q[Xd|dBL=GYvÁC^}rNd뮸P?*4,-0dU_"꛷>z0@wC<'%d[qݯM%ݗs°/T`5>${iM=mO`㇍! +A^C 'L{)I&icmO`V1g1&?H]eg`rg"̎Gqx7FF2~cO.1΃!E?@ t1[SBjvc0~H{J= )pxj?wA߁bW{^o(hzF6ޘߐW^q?`mH7RWIHu}! Dq?!,kufڛ|l[ ^ÊTJ]w_I4rr?  VzZm̶ |kA|g10臶2B 挿1`||Gꐠ z7,a۾f|/ [)E{zvI/c?`}mHCO%M0бw}Y;Ƿ~ޡ(ݽ7$̳cyovDz =ӄjhw=㇡'Zu_Ĭ>m0G,z;v"?>І v^{ _a?Zu?d"ǐHz.`?6dAEt`UY.Q}Ƕ!B{ `OBi<gRWH2* ޷r?4@z`x[_ljJ;;]#G,ILPP}Џ @f@o|G!X`s7~zլulb+!J`V {;y-(:BuReO%xu_T$)}xAS^gE@8-C}-g༜[ήI?'z~Ĺlwd}t rb! AG 3tn~?`WKv-}KxE+)l통xrgKΤ 79fFj ׷{ r^!& S.񧡭a@'X2%8kd7CzW{6ggܱp@U`i?wp_B #k9hڽǐ7Uq ݺWM!j(00вX~N`ʉD~UϽ3̿6e1<B6?| !iL zu)QPĻ/@kg?@%˽ Sw-~¼[:^_Ff ֯>±`C$#~? q+]l{@ z:Z?|J|s,흇"Ӈq|6'֮'7_>o[a]FZvs;K ,u4oЬJwW*H|@o?:m*xZ:- GTYסݍ[~޶w.Ȯ6Ll@@n'}f6E)z~b[ڛ8Ά\Ȯ۵[ӌAx&)h]K[WZa4cؾYn,Ao{Vg= ~22/A=my?Ro2"♀٧o$ 67"go8E`O:)(5o(I8~nC"OLni4<Yc@ *zoz#~,&"D8T|_~^z&L_JoǡGmVH7ԧ7@sƟl{=q6IA{u{U8+}ĪD={@72W"dt~-۬!mL4!:7+^z`omcMO;fZ?Xʯe+Y}s`۱~zv5kWx;Ѕ,lg@O׶_hsl|U3hqbEL#`G{^O0V* F jO~8aEs{oq"~ hmަe!ILӁa ^"D#T 0 zǁW(r V=֎CѓqV687Zv_یR_ԙ~+P)<оkݏq%r@I )0p {<=B6>Խ4-T6RX’#2 6Oo6-@m٠C Z{{<P9rRP"eF՝|1 ο[.#PdC@*IRqڼ ؜:ԍ@O:f,-ODp0;y+G|PWٗC}ÑߔYPDfyu]kUfP)"!PIaPIBTǟŷ m_f<_30б WpyW+&8)noҌN@AteP^@A|-41za/ * go;kqA|UBB7ضM%cf zƜD,UyT# bD]KE/G~4)@>/k'$B> @to/KWO>ٰvK~}^JBқX~{t?;w!W3ya@ +c;m o;MtMml&cT;f5~&aW?u7_4~Ls+olhS<'# #O[ײW,>@^Rx}[^_Rcɾhj A@13 S[@YD?kƯ<?8й?]߾~^$ZC53>oLuo>G!BPI҈Im1p!2oLwAPoox!}dg̰!AP okjۗtE"=x c@h>z])ǜ/?0бq7lIS"9Y/% 8xp8*g|-&ry 'ro*?TX:ngs9 97- }DԸ>ǍJRyC @ B \S(BP~w;" ߴZ" /@~X$w~:w7n^hϒ;bzP7ep8*f,ee_-Qv621 @O"GZoCΣ!CvqYrL?H Reg|s{3 wc"' wFg Ur 7.TIS%53 Xjc; bkrg"m-{;_ BAq~V7Yذ Y ʊ;鴫XѼuЍ nq vB& Ufފ93dѨ Qn_S)4kh3]oln  >ԿyJFW_ecg];'@#_>屷}0M CTM=}-/xS>o>,T K7jlE=KcLvP ԹzSG>ܢ gΒJ…R)zyNj뽭nޞ~`0WzS=뜓*9Mp8s0qPK`CoǡWovl誱p' |n) @z | hK痍U6f|K"Jgw壮[ܷt#g>cO{4 Z[`fފ,pWszʧ ≄@x{0mu7jزȶnF`ވdV ؜7P/U1ssfk;*'93oJ@j == };|+Ѝ>hhd7 b`KpFV/{Ԅʉ <ǹJ*jDgItW\]('@!R)Dix I^I i(GÁ~)4O`mHs;{ Ff]zm @vMذ>B!.Ņ=6{NnFb60{wg\5~5Q0=VWTgcfѰ2tnYp͆Vuӭ=ۜ, @cG/fC>'PD 8p8p8p8p89ytΈTIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/256x256/status/0000755000175000017500000000000014471213412021362 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/256x256/status/quodlibet-missing-cover.png0000664000175000017500000011717414035600052026654 0ustar00nicknickPNG  IHDR\rfsBIT|d pHYsNNsjhtEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{ IDATxIdYv%vYYUJfIDYlR ^4JZ B ZpJ %bj.HMHfU*j1xnn=̳2",ùtOtOtOtOtOtOtOtOtOtOtOtOtOtOtOtOtOo2?~{OtO|M0_?`8$ ?'Q__<V.~~]]kJxqիcgx3O&! ?sώ@@DÓɳ_?#&I/^gsf࿽BC">g0bple'gxs<} &}O?߼?i89>9FFFAAպq/3|>9.n} tOw"?Wd߷}q7Ɯatu "BGGٟDZm4]_2>NO Xɾ~D ]_NV[ W!"BLS+</_"E9GfV(IS\\^Odrj 61n{~ĩ.My biw0aY AbM=iz+Q8== NOp~~4H|MK]15jk09^#,A`o>.yo!bscqAMᙔT+VƗ#4'J4,'yg"*N?yVWWxe]o}[a to_ `j,a`y$j"!s\F.&Rg/Ș2Q V ) /g T2!v5_C,63LagkHV/ ӗ{S_B24=Fm9)V cP`tuzsAQUx5>G{#>෌+oA+y~7?zp//]t;U`8\Cm!#x Bƣk\]0##%S[6S OS$\Ϭ#'ǧG˫ܱ oKc0u,* .8_ `6`YB蓧?~Ugeog~88xvTB& ?]1`<'8zydtl9ۛk7>q\\8 ۶`[6`YҌ)8H)Hq#Iq0BKɍmcmAy&!Q}?8+Klc}ݭup0CzJkێ4z}t:]MW}?!Vb ZΜ!"{Z_۶NNVu[ @a`68*x>N/GHiDAkCD>W-я>[:ތ7~l8q_A_iBۃě&+ ΂Nq'''8==+l0܌6} ]X &EBCGӅ|iOB #x ᒂQS0%WJ}vT_A8+D8G!Ɠ ?WWJi]E $1F]jc`  L<ih:?~ǏFNq||4M .1ml M&˲ `[{|mu] ۶aYG3m-ԄHId82dY!!)S!IbDQc<"Nkt;-loId€Ug")3bӅk!MJٍB$]0xnv,L)kLGÇCqNO>O5460m0.۶^nWnW!1[%X~Pܿ:k"9P>l}|ߟ+,ʮ f356sg!nags87 +'4\D(-\4DL:.u8BҶ)jͤa2?[6p8p8W* bFc'9΁-lnnu]ZVI/Uwu*-#H,BEv/1L25Fja}mkG3\^ͩB'>~!ֆs65gXӔöodP9h:Tp0bط Jb YY8,97Np|D n.ڝ.t7t:`k{[ۛ8N!Y*ͤ2~G/)3`YRBA'}{olW،?)l4#%s$.+tuB0i@8aAC@aŢ@`0>|Az*05q,cR vldyL,{mk/MeAS7i!5Ǐc6D$8??l.6qqyAt ~3:4"<up` 6E2άsZr̓Q`D2c"ٴ_@eR fPCA@0r0v;贻XHP 7"kew0 3#Inz1v#g.l)9001woۘ ic Xo}w]t]\_gMѤf:UgWB iНtB~k5pm(sh,;ehs1Hji:36R'(;KOSʰ$!n'$?@8;h<pbz>\]@S I YbW}onc[[;@ZIhZ~&Bl:Z GBH4Oܘ:^B?]qVIA8e`Q©68~gKD!(y]0:J_, %Y9P>F``h)WBIE! "i y 4ݶ$fA0Cpvq@b!D+ד7Nr`0mBӋF'?1aQ$"u2LQE.D 6Zr{E1*%1K9\Va`J#q 2J-@4 (3CV֌1Bb-埠 cϹALR6>EqR;q<0#eCDDijέ.QChb6q&<hBU#z׿ ?FUIYǥ{r)^D˵3mDAxVS&d kcTE58Yl1hKƮx~RhAuoYҹ(# Ș R7+[R˹@'j̒?׽rq, ض3 &ڡBHhE"xX_0Htnunw\/6y>|&<&`kk 73sLyq8??ǫWJmz u$q,UeU$\Do @Uͫ ) OS QuzE;7QFR,F)K#8,y YiGK dHr}}va *YB "a(gVGp)?"0*ERwq&$I^O( q4qtjի5&@Ru; 7 Iz]7 x?ٳx/gxOsMki*.Ϸ .DŽ/R`R:jJ8P-fjmBk6d~ȩ 8 rlYѡ"㨬TlrB0pa)WcyG I!Z xVm96tɎ͓NGXʯ Y/͎KVOa%TB(w\.&{loC!j=oZN-I\GiU7@GW70}n Cʯ > X뒠x O^-쎎ϐ$u&3Ν Z+OV,8s2`T`^& @rA2[r[E #<.l'Frjar]D/s0u]0fuH_ώŹ)d" YB_)T.afaNդa{.NoVN-I'OdYp]`&1,"| :tX41//bkk ?яtٳjOV:=;>qt|BRvf4T؜_",%q.$piprpDƠ eqp"9 .H`$[E\G6,.OzmGSY{Y!c,ۛ "1bJe! gKUcjyU>vw@DYM˩k0QVa0`8XFX?~~>n/ ۶ 4C:3s 5[|K_Ϥ˾@f's.R:KWs [!TB1@#C)_-3K؏L"8m R@dq,XH7 U cV7MH)P%$Dv o! f*q;~^դAo'_c0 $'ϛܺZ IӓamU@nE@kk?L b8zvptrfƒ[]<2NnJs/R<t{6s\ϖ {}h']Ͱп u$Z俑%p.02H8-Xm;_`cV鸘(8f[̘zYfy㖱]Š766iK?EMpqyc\1vwݕ%9qo_4M`[6njEGvVn+d~0Dl]F%3Tp~L؄~wVz  HR)!) CSh0HT%l&鐛T48W?^FtcGiU?2g`1)?w(2Fn䂆A@7#?I\kn/sS߇7|$q7 1$I o:]I90 prvc븲ֆv9r]Dϟ?msG8g8]&mk+7ftÀ;tRE+M$M`*̂R~eHORd3eʯP!Re`D%_ ͘d(CHQP]0Gn#9בTl>&cLqg7%!U `trjQ *q\ C kX_@ۯ!m7MBŋ%!4Mpzvmx}fL->=B˵F0x E ` ]j 8I( T<& RR^‹3S8=# pࢦܲCP橠s0K3ƹ 1mY ~')29"gErd~:@iA=l9W]ߴ|Y7mXM#zvx  Wח1 Jt#Hpulc&SA\x1g۵0p1ƘLV {;x}ZG)()#Yy"p'@T@@pe +nb`BWU!ʙ__ȿ4ڌ<,md$1Ծr g+C~{{ѸytvC0-*.T$EWMڔu$p{HCFރ]@{_ǟ|akm-j 6i>@ @ W`yuMh@/@TP @)@ $8jJ/zm˒"Xp.e$jҶOg_G<-Œo+ϣUlHGV{}96 \\]`}?O=ё,B)^_ph("'|;L䂗fh\j2=XNAjB*9x5sg gʤJX *IW*,arb_V3*ż4V!A0[tm*ҼI{1Ժ.~{7Gxs<9Y0 ~x; VIȔ((OѾۗ6iʳa$AJzqB}ۖ-^Yڋ`u1$1~SM&N7 v_.o;8}R=c\.1]`ϙ(  5jRs ʩ=~FC ''89e5L;Q;cELi qCg< *%ڵ.e%@ / v "cr ڟ3,DW̿aӲ!$tywwE:%f3hT_)ET-⺮!З){*A[[ÇqP 4MKٟ3`1(>~)*y"& "$UC .+}GV(2OmkXVE6}MrU3gXF.`yB6J6&\Ń ~W})%B"E H pP1( @!HDFa+ m aycz]}E˲{[F4QX}W`Mw !Uҩ&cqAUn0`"#HRo;,K圫Qb^m )$ Lzr1`9Terf\@uܢe] q-&2 vs!00}pR@niw8%.ed;;VGqy< mmo`ǚL3q-4݅@( &@O`q UO LT5_j va6 v? '̹k& eoNhilŚo39n$\fBbw{;2L./.0_aFH%DNi@Q267cYդ7,5 uɌYhvi"燩7 H 0V:>&\BTVY`vf</G{n#e馶YCRX 0.n[ L7VU/OG >z 8R1}'ƒ  "D)q$<q@(s,^5^/J!"@%6X+RST7I鞀$QOD@Bu~B,T$ae:^t9%IͿ7.)6gy,-Ua.D$gs%QQy˲T>d/GxDM Ypm`*}[ ov%i%KY&ŏ~Qz-r W5T, X2i'Yψ'yY<qCjOu[%pT "ۄ/=o7_^sh^V2 f)4N/˿vVA*t+ ȀYդI0 } yY!ya"Ni$5v:ڸQ~חszLDAȢ0`c^pCVYeI(hfQΓVK6´mKirZ4~W9L?wuyueIs&MmT,3 W^hI+'!wq'"*bz-0DlN18  4FĈKa1y' 1ӝ pE>!d/v=P;4WiDbep]' 6/붕 iEVW2 0?&MU*L#e+é.U3b0Qж-Đ!}Rc"nuBD(B$pl@)GcDIxxZV.M`w6hvsK&K &dn(.-?*Vj32,ڙ` ?;; B[h/nޔ8vVt-jb!Q!#PSK?MyVAbzrKP my|S~c biNB$y _ٜw#:rQ~(hL (HH`ZQl[J WOvc[lz2Iw %v 4 B!x9Hb`#+@v8jПDCjY4MA>H*oھw.^}4_YsHq*Ӑ *<G\AAYJ>HeըV HRK} +X/>x4^dX)xʑB9/с)~B˗ǶU_/Gmά_]V\&@vg3O,[;t>@>+/b2mrkYff8E!p&hT] R:2@yeے }>{nPݤZ@/'3R@d L>BBDI"?B@v*M9ٙ])W/oIr&!0YW>ӸդWgj|͘H r PIVjbxN-Y\(MUC1V=*$h-sJ,ZuW)P;we&4ࢢ ڳ}eD4}fC cY^v㸙vdQ/]A&@Ee[H&d ʏ[RK-4VBi@gLnڱZf8N)kdUK3&5kGhXȪ0?憾N5mz`΂T,׈xK}{YZQsa40MSnBH^%1 ,7`M}eU L>M2QU9)2cq|MU1 ?l6Cǥy>2vvjkEY㰌A(2jEF%8Nbل.\ 1+0$}BP3C][ZBԔl)Nqq5\@FYPb j.TǩtʨSNe@$76mKğt4~k[]^yA塽M6bFQx+fW>qt677n@)6[IS VSQX>_uy"W: ^r%8Z TxYf*H Vw"1(rd}x *zvj08E ya$MdjnXCd'f1/@w f@>zkZ ۴<lZ{8&aoT!ۗ/_[[[888Ps8(*ziH9ڶ-ooܑ d= 5Hefm+$aLuD"r1Dd1A#L{P059R˪<\@YNJ0|̶Ȯ _f93YP%IK,m&9...pxx=evVjrٲB@?$V}A(2[\|Ο"Ar2@&腮%[Zh:4UN#!\{Akm;Y8r >&H+ܡ`y4c-"zbVB#N٣m-TOK-2,;˓/ `feUj,#<:̧$Fe[Gșz:6O&j{6w1*͚1q.g(/puu/J2IIbl˔׫eYH)/̎&耿( %$r-JFɠ"gK EgLyAI_3t:]x TPq Mx.+w(ds]%);OaM0+܊Xv Ro?c iBFՂD.?96ثpk"|Վ9tٳgW+)(_Ryyʳ) #x}z>Zny>#|_cTJ868AaQ b>1 s }@rA]]8Aj̒eĄ`soH 83[m) @$NRAeSSMeePL.5)rK'( o^iټ7噿?UA3~jd~o:9(B˛z3Su9>}Y1/c*њ#-CBB3:/ClQ~ŚiE3+W,刺|ޘ,_43.X:·d]ڦaʳs>9,dif ~v]),89;+ 9^zϛY{ =ҁQ$SO*9REP˙]ÁDR^hhDxQddGU[Н %j(lp5QյXy徭Z̺_V44yB4-$IptjG^a2"">w;-Qd<B\_ի*9 (UPŐxD[!Ag&M]v< 9. -ksܺ'9+N n7$UJp9NWgE怉i1UGoCCn,Zjv[33^ò-8lF#LysO}2,[˜H y Z䳺Vy6sJ7bWm:HmGNБ"FxusmIgj;AXTPhTg?on]\i|!QT7Xi9FQ]JI:`"YJ-\XdZc'u,L).GeyI-rgi!S7&활ʼn*~1j@_ 2rIrk<^ #b̂I~ic0b<+r7B 8IJZ-U#bA90pK eATC+O!}B I%@ !dp5=/Lc E@DhԎC T޽:%1jrNo `JdX4:mr*V}_yZN Ge 2&5]c-~S{9PjeV(]U*6`mCBE=,eyc\4ۖ2WPQξly0 sOiv nr..c_$Z8!#ܽ p|ɢ` `tI;nz!xօ~7h&5`#}S9I3 ,$ܞ>aGio"V, kt;n9%þ`Yj6S*=2.?TuwU4gꎿM\9G'E`G.h8LJdf)Q,L>Jbd3&(@=Ȥh3!=?㼄&)W{EMm`&'g}{3>?|Zys*#9[-7f76>lihz  gV$Uo-d~%mt菠]b lt-XhHK42u˿V@!8 4 &*l)1^oIi;f0qJ~!iPF^^bXJ0gAD2n謵j8I jɖIT}?@{mLWVT]s}SU裘LS `XM cǶnvZXnכ Le7 95B&ʼW *ÆBDàQE3}yAI`@3^@ dB@% HHG,* E=˘qDe_VHv3̂p]cïL%9n^IY K3p8`Я .|! D!NݬC;i穼 r\^EBYWK\#RH: XKԑJLӅ, ʂѵkWdE23!J˖1Ef]#ETv1gNݭ-Xzݶje(R=9!T=@ .m J[ÇmS)XBBc*<U"#E*OQEAԸ r!jvRV5يmL@3Mx=NZCPq*dDqX&&7>cZ]-m_jz}S'f! Iou۰l v nZvTɲBB ŵ2 GďdDy GP@!{ y"}?L(,,q&PT(0JԓbY-5pH@qm> +nTQ@kQN'X-'EBe"0laG0 jl66^||({L2gڣ*S.D^Tφr*WN Ha( ,= ath惁LUbK48LcM~yل[(u>|X> oD 0loWV?~McAV(kjc(gن5J.w<#P<,@)k:5; lL;ٌԞ4M|xSip@LT(Ox@^&"j |0 ۂGl_>|22u1 #6V VKNpL}Q# ȸGf*tǠ_7 @`Umy=U'6O%6A(wR1?eK>H>ɋi2a Ys"Jz@ik"~:}nurc'EQK }VJDtuMcoC&ATa\ql\]p~~^sNYuJ $xH"gmll@A~ceE «3sɛB.2 !GgrNF,B:\(>e(aTE Jȸ[@3y%?AsŶ=48Z8J ST(0S35yK}"d>?=22 濡T"ԳkLo nH/} ̴ YB'(s @D u *sʹqI k(άgΞXQ"sO眤z?w,Oכ%ƲucQ.Na(בc ӵhlـF̶&fٰye#-@z@Ee2 `VCM̖LldTOAJ)  sGIeBD2ӮjHK0aiFlb{Hl@ 0"'%1 u%ҙ щ۳FjuXAZ,)#ilYr\~΀"@Fyf+1F~ bۈȿ 835^REA;kѡ4.f-Ųj `f ao <fhP#>+S}xPW*Y"0 Aow~ײR#^mٺ*, fh$Zʳ¤Y{b,!## "Z[YY)DMHS g|&fѽe"+iG~+8㲫bU@~k 2. [$Z1_z8;gl%A;b-d2MkHp+0jRO[V&5mYQWUot]vF3`&,ti}G (لf"˳h3Bt{)Y?q.Nb}GPkSlKOBgʵF 0繮XWVV wls0%#;A@)~_:L㌂0jD7uZ I=ҋ»2' =pN0Jrv_{ռR;P Cc1g@*::N'p`0@۵L9 czܖ&3ݕ?05) A3S}6ȟ?6APOLg~f ʪ2S+[(hfvN\XzѠ B,qٖ̚]p8x 9r6mey"KteI)^7FJȿX@@gÓ8 HMEJ\ke?؁5 KiU h~ؚ`$< UNc:?we 6:zlʀa8 i 2B&<̺qP$XȾ( :ŌNf#YpL@r%Fz=c0ZHTA5̌gV~dW5P7Ƥ^lZ2z࣍F¼$Lƺ}2xchzʂXՅpvϚj(E|;ߩ8`PkMS`; ^5;8zIƖ*iZn/+Kg 3ĕ+g/c6Dg_FׯzD!mH@f") ˔.uD2@@q*T~6\< Ah U-(s0dUéS۟;ng~#eȂO 6QQ}56 ak% 8iʰ*Z.f٪v Q(feUMߨZ=7R0AZS"[\2+PElH0Bu<@ }_{`0ECc%N&-F zB |+B lD91umS(EohF6&@D@+qzp̙nLC }˷ vQ 0KGIIqQjtPO0 #IϠ 0M:[[[KRA!9g 2䗲;TF 4OBeGCk5hpfQ$:R88y$.?,iư}Ief?V/3Lo܀F*U9}mQq&I0_ `OD80_(K; YAGTL{ڊ+H*0uB`09C?u &cmmmϚ4nfOvHUןtqSV@dL2*hueݚ~nW:?2md&rzYڲk %(`8̜cO`#fN2V]kae!O(Rbmm-Q3}XZ.DC?([ vTh3QYD얩 3h~@vZ0驑 gU8qԳ2vޛV)oA[cst}s5} I;-j 6P. kpZ-#P#0 A?%Л8uTg3:v0vӪA5Q|mm-ΤTZo^ue?##@8[*ܚ1̬%0_8a#`'R|'P ;"b.oA#QZ46< reK<)[.@x\wK"avhHV$ͦV Pt0p]';}4XE~C[=nohiMyXYY8o AhV sq#SW:)pX@I@v5)?`^rU0Yz<@#F]csU-,TGQe-%Rtڰa2 >#",:PlO=R ˬ#7Ӏ@^᜹!N@ ~ɺ/#!}ݗIUeڌsIH٤z~C+m^RMPmh?|`oG|<77y)hm()%kdFP$oX'3k mDQ￿`8A`75",ی~n?6Z:od[;u(e*6j6 B($!FaP)AB}y(Y{v1f˶[n14Y(]r\uufh8#}SkG`K,bWȌ昤6u800$w~hǏƴW[$&u+AjF?MUA0zg֙LPX>z^ؿI6y5es\D ɓpN;v3kD˃G" c8Am$pu &y7[y21hy^JRtGA0d2"Vcld] ,pqEj HSdH_snz>|_'- D"*bol|8Y8MRʱ#0bm}- =fijDdH%[z[Oflӂŭ٬fGp IDATD N4R)XuHEX__GE8~xse"F@\.ldUc .]AF緍:#t&AI@`@IA&IH? ?/AըŠG0DEt;ԗRn# C8qƀTqp;El[Ie gIO,d/o X][ CYoKx:9e@`]n @\HtL,8hUqz&(e%N^  C>}=E=h##zYv[7Z60anv 5+>"u VC+㧏d 8``cE{LZ F#n" S$8`s BAMvFƕmtD?W@` 3y v3{sXr-e;"+s."bl]D)_2\!j6("  OGUhYa6z޴ e[?[_ 4Åa$#i Ca,a {-,U (-t20zhdbu J}R1}Ǚ3 4'p +`'E썀n.Q1L>ɨʹz=?b0 ~ fpDt}w1P0O`ļ0NhE߀hB`H &bΞ=SXaXJN`v{:Kou RA@2q(JFϏaI*ofF?Ȥ1~V#2ds[/Hڽ}; - h: @$y!ԙM$"$P\?30 " KKgn NpǏĉV4E쭼4e+3#~̕ɘQ&@ߋ8ER lu2+STl4w\ر iwG(GB|$ L~JaՄbS<7,j# ]fbF"9r&X%=U,]>y RپV=? μeaXR kM"AAI `,pF%䷿Ս-N z8`9SqlHp"5)0Hi0N $)@i(t{2hDJ) )!avf @ɓ'E#``N`T)"NwسC,CƣbIe %Q_bkfFV+0Zth8K"iRNxO9 )iƣ45mJZPJA`8`pHR<(pqȑ#h6GF<#o6S,ڤ7[{#a lj3c}} n7 aal+s\P\̷rR)¥J$Ywo*+1x9_58.'@zeJe ,遌\ζ^\ɐ*^9p} 03] |Z J)t8l= "}?dUDRUM0UW:tbj:o4-[l?n/ǣ2敼8=."LDtOO "wF >i4\FǾ}3cfN t:2s2=n I9mAfRJP/ cg~Ld3V p_iI q1\uVVYȭhO9aYvs SAlH3]!} Cb~a>؀^XXXȌ668Pӊ[Ug}n71>3n^B hBut2ǶYU3PeBJ^I]6Ͱara `<'].釡Z̓- (HFa~nsn8b8$HԩSXXX 85!}.rM43}0 J4.剙n'(0!c~P|뚢T `6UY,B7"L_'DAs- TS Z\e3ǣ,F>f1Bg[ =K aHJ*: @hYViQvuannC,eyp a8}QR'fJoHg@(%R)7?fVH AXPI۶4`h"2ߘi.)vy@"΃FKD)1ߜ#i@z 5E" K2Pbnn3k 1 w^cE}$t ˔UFt(LFz7S6T:Έ_%#~dK!jsjeVԏK0!+G6 Yf'^o> =%H`e)BqO"p&q | {9U,/Vaa~ssj/-xy2OR }%>N>NwpWdkyQ>`ʌS@w~gNbLBe3@p~-'N.͟xd,`sz(V  fPA2tʐFfN2eQ2lzY`GG2K+8anv3h5c23 Sy~?MK nCKBsm٤b p4 (`%P20g$.wt߫@Q^Thcڙz @6B#_{5Ͻ_7Rxe!# 2s V*V 1>eD4SQtd8+XY]FVV Fc, J;M̌p~Go),V1kKE\%dӸ gȸKe#;i3Y8G?҅ͷs33Ŭ*BCkңQvCT4$֓bF}`y^Ѩk`]!&0p8`0?Q0=H8vƉHV寓.πf& %Vi0j J*PXŕRz4& H ǩ5' 'd 6bVD%Uf8UF)sK^K<Sٲ9K+|f1PiYyN9&b@)XSZ b0eff @A@s.~Y8(Xio>Й_3y̢Dxf XH&cm甕Vso"jgf-0e/F?|AQ@3U1ć RLb@GAp R?Fc"uEoyTqŬQV@Z]NTLm8y7^tѱGy33-zJ76N`vV K q#f@Cn+|!RJ%`& !R:!O*ȋ2[ħƌ;2p$w6͘E123+!mm-Lat䇵ʈ0y@1rAn`2䙟*e!Ea~=f>{SR;+^mf6e4~ZO";\}?{u㮺{Ͼ^u}+ g~VuKF0 zyԼp})s 3쬭ʵmНaRT0}l5LWO{3_6e?""Z(%eff(V`x_H~?;)CZ=@EQA( Re3̓cD k?r@Io 4ϏeBÏaz`s38{,g.}~)@` *.ݐ10 _◼_|Ddl@s Xߧ!N)3=s/y Nt[2Zd p0*+2\(ek߇'ctn`3 DU2ުNGmSnc|{|}Y{㊣g9olRn6$R@ ӛ|LiKH?IO:Koxث^^6l6qKp:J=#PJcppvO C2elʙ޾-1M ^ ?A!?J۔3vnH_fO As}jL? l'x~ll̟> .ho|̴2"4y5\tEX>]vkgLY *AT˫#F/ϱ1yz?}=!S$3w7'1F$_0ٷ-( .Ϳg>_vmD h"%џc`fV RIg;C٘fȷt\ưe;hu'Өvi - ,m%n/#6̞71þ;wFd.|o4(aUTQ86,-7 e_җe_p/- a~D2p8@ɔ4W EQ=~\(uuq:>4q*8 F"g5%OynElLZ JU@c"m[y 0 nOJO~q|K~sōvh/CCJh;? 63RrI0f-wT2 T >ov_0_IM\w~s(ݯr<m\&ڧsӆe>C?sUWRxF;.#GC0t^D*H%ŰQ+nN;͏aP$S3Pu2u_UmGdžʀc2ӗ3 83;o|o/w? i+e𼨟7}ɇErsw{ӟ6HDؿ wss]aɈ3$+[_+eWzT'^|;UoWh6 vbr@ L7ڝW|W~1@ahE<0[b4UҀ9NW_񲗾o$ofggq"8(0$`>v~ 5`">]? 3ko?j̸kWc&mP}^_Cp~e}U>~2n4 a2l)i;Cl M%H]uUwm/ y^&xcyu9rʦEr Jd ?+z4[ͫ-תBX\| (06ҏ/f8*Pv4)>>k<-)U`9Y0XY[S/K[o PF i0M y/۷?O~\x8sF;>ӚË8 G](OJ0 Q,GiEbqaRdlm˟ Uf"r3u$`8qϞzaknnȓ2T@PםʫVp^ǑC8|qT9 wM8벶|}\3=?27-Mz; [JqQbau"~wޟ\Z^znk‰'bml=L<ݿ?iO{uFt]y"5 0 !`@>620)o%HqqP1+eL0sZ]]yF;^s73m8vKӔW 6ʭ^tl0Ӛ\N`řR*J7Sݤbʰc&#+dr1Y^:{0TFnyڍ@J.o}]]vRo|qnnþ}2ҽ~Ͼi 1SUIDATs}apgI@V/+F*g'l4`#+EF]a8aKZ%Kw;?5]G[%4U?r|3zrh !VVW򙝙CB BM\ D8sV]z"RFT:XBjRA3祀h,q)b83]g?q95F8}(̭k߼o۲{\>R9IQ*|ЭE-Rku9y 0 P0;3F IʞG!ĬKE2g(eӪF7iua@`t~s.ң!++x$Zq8 D @Ie3gzrɅtnܦas ͳ6M,o~K.ug) :Ξ=( ciVkZ]huFv Jr0@k j'R¦@)H@)IAIII@$#ì<VL2(e aΜz2n\C;~"8sL'߾>veݹ@Vj*pf4|G^GD$A*+ p^]yQ0:h9FooNw/`( HUiߝ?u`vn2!TY02V֖̘ijhfP7zUR/ޏ%(DfΟϠ"+d<5GRbb:ؔJf>V q@ h %WWW\m?>KNzJin5`*i.}[%]vkZ-LUJG"mk`D)jOe07+G|Snz!b=)/QDz P QX&%.91p+(U@9I@w@^x5/~ޅe2kz}擞_,]򑈆6XQ;wJ[ Ӻ"\fJ*fX.RD`mH/0+bO&5Dr v>^Y=s_W_͗Kv駒 ~>减yCHDCR|F$F<= L Fk$ `2_2* p@+@i._D}a\G `mDbSԶ?÷?uz?̅ߞ_x㈙Dl4\B8SO Bjޣ%B\S3tZ/xs~E"+&VXQ_FJ$ZG $+3 |2N@~m'0"m" hvg~_zK_F~%P 1*_k~/qӇU$[@;" P 8X 4tH0꒩s\J`=; r9r\ew 6oR ~7I?ϙZ1Rg9*RABQ$φaxg0 g0ey (38qY{9Y@B@D`A, Z)WȦ)0  M@)'J_k/nҏ PFr~Q#ue7{[?յ/w`nv!De;A>lAՃZ3pv9v/ռKR2'3RCS 5*E{VRZA1 ҳ0+!HU Ef@]gTi%qbw 7}[i[ SO׿ǎ;aY~ "-8=HDbq^{JqY `ďQ`,0d"Y@2v+%cWd0D &D+0CO@ TD3 p7tK[ii+`3`-_]^ {~O>t[o4PQE"ּq8"q&NX29H8b]y1JJy|tuQiX Z*8 bb@11 @WR*-(2I,NxEi `VzQVox͟w3d. }[?q!WKhHFC{j:ZYx\DD-u/ռ+M:3=n]h "HX' 0@4IL$a~1L "(y‰gH`yge/T}׻:17)鿺~c/_,4b!ՊɭqNy#jc' RvL?^MP` `@LRac fE%@0ac COQJO_ 7QV*l0V:8q?}s_رcۿZvEQvggcaJA }7Q=)e1*aE=ہ YsbR J)"G@I%  o !bF @ V (KK'̵ܓ}Un=8`;`#`0 {o׎YlZKF#ᙥ!fՃNXՠ{@D-qspDm qJ@'5 ? R$ DJx7Q&XIf3 f{$I$ - ٳ4r"xX}fV0FNdzX[i fFE"jStBEu80TO?uc_%:tn@άb6@bDz@b e1:2b-9' HpGn{ʹTg'.֛k/GQ?jڇE"2*IԺ|]*2+%:?R19B{ 2<2ifW~B:ʬ(ˎC Qv=}KDϻ/<{UL {oS'~aaa[(D4EPX=Q$Z9k_ Wq81 j %Qa<)D$v\WiY `;$XE{ }%?E7+ەOUFËp230@qMA"R]AH%> aB6 i:W N^{uLv+*R@u /l=o+gZiN]v(jM{ (8u?_,9230-K䐓.ICCu)m3ݵOtV3y5=Ys`44  0"[O{O5(|[}w~/QsW Q-iG"..$q$E9zf $/ fx@Xr-(0V Gd~ ?ǣ@pvGJu <33zfc<8rx5/>Rʨ,D)rhWߗ{p#:8A`AO(>t(?oUn= ܥǶQU`+a/ٗo8rdh.&O#&˖Nc8hHLziu# @&}L _VMV #(0 G:X#q>N*f(c7eA=8*Cj }̭|k+^xѱc>~(f>uQQ#H h&6PJ$kI s!|G($RGv*qf1PaF)Q%:S ǎK/us/0^}|}pW2fD+3j3n&.Ab8B̜v> `+۵'!14^g`0n @`Sl )d{0]i!g?;Lw-ڎюQ8IiԾo/z4"!R@đCӑHD}#?Ca0 ^=UgW1JQ1bB|}œGQ&$5eh&@^ǑCGoA ^`EaaV2,U뽢(z˯g֌gRU5 {d*#Ff 0au{K_~[_C(W̩HX<!X"WOK  8"c襤G/>CQ͙dGyihm%l'~w=[]!'u>bT,9W!D7F!~nzK_Gظ]a=أih+ [ݸ@fYQﯹ'}ɒB(mᣘiblQ%>u|K ~u/{3 *ȓk&*1|[~Nj^ş3J :pNߍ}׵~+;Ri0tttv5m=$^vݾ׾977"ańP"p]ÑCqs-<>W~կӟF =:u/Gߪ @033#;|q.Q@B`aa/s=,} 3܅ 6a=أi$LطS.40~ =k0?7  wQdI{ 0,9~yyދT\$ER LH"'S?H>{G?T8ٿko}ǛjDDSe7NٳKy_me=أB6m{et4?/dvHvhP)Fe/*L7zk>]仏l%7P ,vړ\I*oY=j m׽𥿊"OI ;F{G*m0)+?@潅 ܹO_; @a (=Rh@ SzAğ}+}k_EHO{H4(@`3yAlG!"9͂۞l|Y  e9~__x !aqR<SGM&^GShނ5'!Rgj-*l}c`7 $MrufL||@S 4YiAH4ko` y knp|v#YAUQSv)뗯ٺBj9_A*8g_@Tv Feixxٔ-“_fnyqyXC'Bt a+ :fSBU) <^XIvGb- PGg]:/x(#Da"!KbF;?x./E)hZXm3\WRq~ZR7S1$PV$gJJѴgi\ʊxq%dH)xlMO^b_!dv=80P3R)ﯦ 8#=y'kO:J9L뎝8!t(Z3\U|Ys+9tʾ7nOYD9T|׉/;e؎;>(EqA'/\ &nHdlhc0iZҜ(( =._ y 9 'mtMRY{~Hk|dD ;{~OH7w Jl;d;.ǖG&A3<{=*=ҷeDd{J֗v#+_/[iɣa}/?l.Lg !"@$I%kSFbk.-+4PKo{i{Ιv۽W$|gg#yWVz0ʤJY>F~n{ ?(sV^)e嬧TWzLJj@ {fe3DJ6"D=nUWz2X,Z*k3jԽ=݊;?ޘ[xJʬ6!8Cps ɳHdcu}D9JGa=a-Z|]ŽWaAV2}I&LX|iSB>-3 * lE8~_\ daGlK6`GIXg@c cJVqP~Xq_lEq]Y"Wsf[Ւ!,;62 ;?C+wc)^x!jW$)d\)Qdie/ Zۊs:  ztcp}V@ȳ&'ϱ0@f 1;/2sͳkUT.F}&㌎\GQfyNZM{OF:]ocee 4g^PA+$*MRv(K|L:oARe9yu޻A FS8cE 9i[hT*axIOOQ%Q཰ZhՍA/x Rp*qon,ͦZc!(Y߉ҴLVx<:li/E"ϊT+h4XkxK&"޽0yZnft 8Ȩ7hWy +++j54 egFGFEse^:Ff%Jz-hEJ)8:/Sq,:{q9Keޯ` yٹ9$FD-_@fg(ӛ ,(#b^cumg'誦J]1`n1F$ a219Ϳs=m,|rEAM;A $IBwޡjqE%+z!y|OZqZ7C8WH_cvnkGGRZKXe!C6Q/^ \{GN>scZQQS3&wRq+c ^[m0+fCyG:’_^Y>`X6Rpn øc=3]wiwպs1kgjEQh8.+JiΉFpC\+lE <`#IV@e'q*R84M A1Ա{- EQT{ﶽߏoH&heq(w0^TWaAs8|ȡ`+H o~z衧$v``Ф$Ջ|߫<:$JGQ9u>S]o=}7/Ye|4MZ gȧUM*Jџw^II_N.\zK@i+LчwyRޡhTګ?.O`4;G\zm.|'ЭhۢއjIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/48x48/0000755000175000017500000000000014471213412017675 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/48x48/apps/0000755000175000017500000000000014471213412020640 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/48x48/apps/io.github.quodlibet.ExFalso.png0000664000175000017500000000535414244626671026613 0ustar00nicknickPNG  IHDR00W pHYs-ItEXtSoftwarewww.inkscape.org< yIDAThZ{pT}{nv7ABH $ZMu( :ڪc:*ZQZbNmjUvA"*A(h y}ܽ~n$LHν|s _b m`)qKʥ|BY !T' }zR>a^X'y3-IM:dj|\Bڝ?} b"0&@@['S\1cUOߖ4^q(^u;_J:JDtPsg}a*߶ɒ_($%i\]X"6 (ݰ}|H1anBenq,&"y\m훲=}d` !`lB%f04֗]9oLY7tzL `* F"ٞdb @/;$Ȧ 74 lo -㩒uϯ6d(TYR224( ظb.n\Z(V=dm 2@u͝c|%"=:J;r CÜT_6KJ0-3p ШCQ&Kx%k5. d#B]]!xxR,[\UO7 tx#km]Z[1 HIO^3xk=_ &NM A0B"c+P\K+OX@]ۢՍ]p\xU \C>$`9~'aqQ,%^BqQ6w3u{6"$FP/XΈ7˾U^5=ω;,.pEC@w '\I^a+LL9Ѫ04@@c=~ [Gއ\z󖅄K鑌! L >lodC/nG Ab$d>g/P*-lp3Z{b:IuXq5s! Cިz^=N!:0!]Fp$A01|r)ED I\u+8XxxTCLY=d $(JTEx՘?gZU6nO O+Yae) :i_b}#i \UQ辦OZsDP J 3/DT BS joLKa:wt`IɌQYw`ȋ҂lNIANf*v0|ЁC\A(KR%BPdkAU^C C%y(x4ct^.U5 T_IHqføB"'!0*%P B̝EŅJ3k^d;ja9nƶ^:J(R1F@݉'uo]q feюw>_atE[\CW@W[S/aqݕs@ÞC >(a:Ut #Sp 4ucu"1̮7Joz&;9¤8S@ϫ8\׊ը> $0.੩L `#z@$4dm B\o",w-ou\=kѡ풙&;҄{:&K&1Iz3) Cyu%Jϵ^ݒ-miDCgw\ 5@lͪsu~4Q]}h5.mޮ0NX0nYe<}\^*Y$+drD{tH'[KZZBe4iv`+,8'Ծަoh:1`kU9ʒPB& TdJ B4}RO{ѵzIcB4ŕ*omM{kWUKy}CX8߈B0K@U5 <[\t;(UF"(SAU-LO<)%0iX}k!\Ā H!{eR3;LEQ\@s@aA1L,X5qt%7QV/e Cp=BR%R0a!y?~Ј\s!1ǛS0]2fUp{MO .7fhfr\IBaO]3JK !,? 4%|VJȨB(Sqburj1u|#|tF <[HHpVM"ǩ}CBJBCo7W ]/!ђL@(! <]PlsC/5,@XOgN9R LX~Ǜ^~ *  i4éۺד[Y -Pk +≵Ppu] {LO l|6ؤF_QZ{ˊnnR\eIc.%Avo;[#  BH(9$ +;aO)EsD^O^\5wVx)a@cyl}i`+pE=Ȍ<}è6ͻbJv4ޫ=BGw?!F4 zXFWz{ǚ/0qh==?U?Owԗ n^v1B/aۼs6 x>0$vo`$B"?5PwMjaJ_d[CBX}i_י:j&$A /!9t\:&^EIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/48x48/status/0000755000175000017500000000000014471213412021220 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/48x48/status/quodlibet-missing-cover.png0000664000175000017500000000770314035600052026506 0ustar00nicknickPNG  IHDR00WsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{IDAThݙ$Ys؝=bV`b 1Ȑ.!K "Y1I@Q~@D@ FsHAa8V+z\=3}TwCuϱ5"Nzzz<qZE _|_("E8{<^9_w_c%0nZw9v]/f.~w߾+$1HZE^ayynP) g^CH)RBk=\zkzh?1rS!!#Ͼp"d|]oz=396{5[-E 4!{*'OSgY]Yf=<4Mj4Mzz=X\< F(ڨWܷ2|Otm)FcJZn,Q%%rPwBHj !Ħ51cZ9˜8qsqvVV(T\N’u>1D$A) YZ!3.^,r$"k,ctֆJZQoB{֚r6_z-..p`|xX!b)i's4uj(,^%+zxё)BDiRi4FijCq]w1|˳s7I1DpcXrG<)k@"hԩUT5.p4#Q.YΑ& "X]deִFZؿGy$IOqi o?1zބ >~Cer1dYk ,':1&V8HN!F&rJ)|l](IJR!/2q9󵧿SgxÁH!>",D}+Aɲ =>D֤*FT~XmH)ZBJ[H֚}?}k,/Qd9Nx|piB 1 Ξ#@*SO=tm1ɋ^=zc!znc(H)!LFDbrSX>΋ ^ZlSn7bC3gNs9:>J+.SOz+[lPù(pCPJJhzܵjw1YEV "ƈVJ%ݴpvp,/H Yqx(C(Ho=y\xPRRXbEVHܜeZ}x 1bT9j->Xk1FBDHQ:"!x)x1"9!(J(6gal9eɈB&x,U@!>uЮ%BZ< ?Nbffi49|fIgs)=@a7}h%ɳ^}f[9}z1֝bzz0X!1Be[WecG^EI >jbW Dڰ0??쵫( ,#فs% <?z=[D)\-Y3;7O^!(^76n R@9B Fu {]Z#ɽ54?} ϋLҭ"@h4NuRZ] pȑ )Z4MY_ŋeȰB\"`%sT46[JIe,,^˼!$傿r,OPIC 1fN73/̳z?Z-`*Cჱ~Oݦ30:RZA˧ex `ح][k!@Jzӝp8T EXi^Ø$I0K)EQ9jZ3y!3^xq;@ n|?bvni1MS_}n]r#B"sΜ9Jk4J)-cpyC&M1x*DD #̕ř)] 0v /?p߽uѻT'lZԪU)%o{UA !x&F^$& !2(hvh[$}Bctus-+\| q~GwTVkLLOF|vkk1n^=!DBD)e(+%R+ec}qo[]G^\_ P@TU}Ǐ31>6ƅ\e8}c B9PTR) BF)Kk7xM8u/}#B }я{cf!Yo;?%/>Ii:cq).BDAι䥗}"єa|=ypRD.Ͳ섳c'q$Kt1O}?,$trr?w?RJk51g RXwrZc!"(K?l CjH?~G+$bj>c|g8ܾ(WUFPQ"}W.]d5~CZPJ{E1B?֞>V(DfwڋfFsb(s$a+O?}cpTXkL왘-+'#h6ڷ._~G0E!H$I<|ǝ}DJ5922OM_u^,V38l]=~eS鷾Ir{%M:IY:B1/l_8PM^wsFڅF÷nXRF}`ɉ_xg^?rDʹ%s//~[F߸I"g"?QJglMZ! {Ň))ϋ?|ӟn1~~<o15IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/64x64/0000755000175000017500000000000014471213412017671 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/64x64/apps/0000755000175000017500000000000014471213412020634 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/64x64/apps/io.github.quodlibet.ExFalso.png0000664000175000017500000000753514244626671026612 0ustar00nicknickPNG  IHDR@@iq pHYsy(qtEXtSoftwarewww.inkscape.org<IDATx[ytTy{ߛU- C95bq7 qkc';nȭk'qs;%5'EqqYY!$@  4Y߻7O3$!7s-~Anʪ-1s"9!T/psfeooOUs|XrY&62+K\ _H>>S+檗rdK_Ge )x_<za@)BzVrdl Mh}JSý}ϟܶD+N֗${B,Ԩ*ƚxHKə:erx\ vda4Ƥe˪WdGw@nl$j YԨ.Obrk'B˺UkPKIs&auv*&B@ D'w5~\},Uj%k)&/\ Bps Yl喜}e+͒6٫Kez̏ ŅP!Ű0D ms)_0 Ė1c%5&! sanBX%+n󤫙Qr1RTzAgKY4 g:߀0T Be?iLUU1ّxE#?ct`ɼI1Gޤt i?â@Y,N ('Ke{E,BP@ bD">?"qW!0n[wYZOgX T(51sQY/kyD'T@YUEvd>{Wch@]n[l b}Q[^7,ʙHw$/'n!뛃ř]&*$"pw/nX -?ڶLdB eaBpPĒyGD@"KćduZ9mIԼ9 DtbRgu~㵸3'`@Q8z}ĶOO|mLWr>wt@٘ݍdO{ ( *L'$a^~e;ŘnUKKp<6z-[0;nOdGiE j~yDX2@eLA~S ح2|c1W\j>†5J]9~ow@B;LBJLܱ`l2P gy:c gyJ &H2L丰R=Q^4quR̽/8 %ѽ:.uyj,S@>dQ0cہ19DIU#b=#jd8gfaP8N\ ]F&8p@`eiJ?3h:ҩyκٮ>O=CIZ$JRʶd9:ٖ %%eENkqwnMiz1v|?=GN: [wJG>!ٰF(aTB,Iq_6t;|x ,Ph+^}Stz`D@41 RFW;LӶ# Lŏ7BCm@M0-|HQۏ\+s#i3Q8 zHM2{:JV(1#%jrJD(xxE9*& w~ DžҩY4)oc/Nr'faw0pS1Y@Ykdb,[l=+ Z ZGKrTjz{Kջ=Oރw5K m_#~THЈOHӺ8'c 9ZHe cکғ^XsasXe]Qo>\ AaTsDx ߯Hq dTa).YV(#cg:Տ{nޣH };Ԍ#â/:& U*J26,-DÚtɡmTS,6.[p>n,5S&|3)'7M%zUu"9{1 ذ/7Al-s Ũ)؎cM`@t!b܇ӼwDi@g23 /lދ֫CB̓fJy~/SjkIϯxb3 \#_7_ k{Tf} ~_ۈn!|0wn/z>v\sb7CrT(p6z.d]9+>fW \(&αr<Ԍ#A#)`Q{NM;yBaoI qBL7 ɑJM?Ž=%+M/Y3@ʻ@{hwjVDrzFA) gZM1 Qj>iĭ[nU梁\$I|YX-#oyщA]$9@u;ChhZc52#ZKYch!PeckQH֔W>7eI$m NڻP|5{I-k'z "6D 0a(D:UJ;[j7H*&JК~S)?1#~Nvٌt['=-0W4Ƙ4VU${;[^=#il|IXqřtAp5O]W_v?-0R򦊐{owQ.]ph䖯jWܲ/`L=+(ue\_pڱ6`:[ܶ{frU:'+x#LV떧$A]59SGPM=Ț~іoi 9rIŵq GhtN&$fsV}Si3W$<19&  uO䵭Lu޳MС\x [F~ޥjܟ׷fץ8vEgRI4>ݍ(4wڽ-{aP.__9晒-m3mںWn){j:)9}ٷWe4fO_<7V:a*= 7|ۑ=q*[]6qPÁ_͗ݍpL^MgdO]1{fÒU:a{ NqXEͭٷIa\  }nkm-Є4\OoŠ)f͝2{-bfK/fe2aR:!B'GUWՀ5i:o}Z>\Wk{CYnuˍ64O5f ~`ݡ٩Zn*+%G")g}%9GWBGUٛ6'N-ʩ(Oup I PJ4q5UJۓ))=-;]3\W1*׉ 7ˉُf{*R $۔+s40XYq8qN 8]oJ:ÞX~Ty} *""d-{ Zv3}Zr, =%fƂRcp (9ι.*9/|նwđpaC8!3EA~6v;aQsHTeߟcW<A{ NnF^;GS_ )L3LP@E%`:TrHZb{Jtq4{iRYr{ܒ$BыuI`@ہlzpt9#O鞐"Dv-%Tr`un}uykj|1Eh<cK& L'㍛mVBP2][U⟛ 7Ӊ9 OeH4 ~NΌŌ ̤T̵/Pc-c}8mEWo(N_aln8r쁊 S<|/&/Ðu.-! A$ AvA]mí@] 8B]Dc Y)K`c4P@E ~p3%99z8`x\G tNL::!j3@t`58G{g7O5cŒAY5G1iY ~ #&X>ǤX|l05@ЉDȶ]EAdi@]C+\x-Ǝ0.*D#̾ԝı%"(p\rLlBWt:B@@Qr&U 2vWx ^D2i Ћé5@! TY_/;aYU"U. zu7??X( ]Z0vF 3ZPWi1+akь!re1lm]HlFBMڮ"{0>j:bWEZ> N)ᓶjMA g \W4m&.P5;1tlpt,]xG AGNB3G)Ks!nxgנpӚzn3bl G 0|ϙ1ΝkW[s1oN!F ϊ)VϮGHA% EZ7 ($aS-X\!Q6b(*n;y}Ƒ߻ |`-*]--KH#6=67Svh0yw>G$z%8ۚyrZ?AE3gz*$p.7ZX"Uo'T *<;ַ|ћYD,Z- /OsCAgzRg9|ט=6;֖TXN(*HF(o=-5϶zy/Qz(TnAʼnF#h*JO]yǷfu`<;sz}LUΧԒ~^iO"l::PMK h'}vzY}.il= S6Hݺ~rZN>3XdjҖNo2H8gn$qB۹]9K ~g,=Pݎ7HVz{9c]F':ixdpOנA05tA4NsC>yΥoI9ѻ vo1y," {A2fBsi}Q˗R16m+dW7. y+ep^ o&q-?&G%9e<&j)vƝ>o8dr,Z6nʾ"msp-yݳ^};lMGC@Ƹ9wOW2Y,[ P-Q=Jz {NG~A)g:3G ά"AGA"D8\pMp l9`äX(\ F RANaxm:\Es=婱IbIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/64x64/status/0000755000175000017500000000000014471213412021214 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/64x64/status/quodlibet-missing-cover.png0000664000175000017500000001367614035600052026510 0ustar00nicknickPNG  IHDR@@iqsBIT|d pHYsctEXtSoftwarewww.inkscape.org<tEXtTitleMissing Album Cover Art{IDATxYeyUu33uȐA3Lt )6PNBd$DGņ'H,lZ,=$"(\tOO/~֪CsvOpZI{O}\!:fֵsq+d;VͿ|CK/\Ƀ~'WR},"KS,!KS4 h^[ @kc5[7 -c@94E BAHaHeE΄XP!Ğ՚fjjf|m0aэCs hҩc,:z{8w<+WWCA B=pnǀ3)]2iV$Rp=Ƙ'< F5f=t{ ,zŅc.<[̌ ?9˫G<Fk4 I䲠(4z !V*syJI\Z[inI@QaH匒hD F!EF\iRE `e6-Xy k 灅f(gƈJZq hLJ&m*qիWvcY^[oرceۿRR _VDZKe/ΰMR2&$m-%ND~Onw5K4)^^6Hӌz:w~;gΜ;> Xpֹ4c4 hMM0F6X m$2RXm[Do 01/JfDa@5a).Ld%;*t!X`D/QhDa),CQMކqM8J8tȊ }WV= хfasss"{,>5hL1*(rT,--qR D&ZEn Xi(ShmwNЅ7@ ں,C)JaW+ .tUi!F(|O.P.jɐ[F5FNw p'haIQA%/rVWW 'k]k] UTg!@y )c kf=*u֥ deA$Y{>5I&hǭPα*~ܵ4ƞ|99ғXCyE㶘nhXM|V!8[[YYjL]XUT$ohS0cØ'lj\naڀڌKb?PJѨ ac7|sFAu|c)%~NCC교F#(B:: ڕ@c|j6Rt . 7`0a| D(J)L<圌t &$e8yE $&0??,z}Ofq)^G[[ . CZLH7k W"r(` gfE`Ty Oy֖]Zc Qy8Nttz}g~k)RDQDb$(24eT&Zy(y=DUj\ 2,0eǸ<πS@ $6l+ SKK5:!k Z(j(zYȲ ajHA kQ$}U_c8i4Mu9 NNlc 9Hy-Χ/W`g~~T.EgyeRPcVc1F Ihd%2g?W>{NMM &},ezzڟj BZ竢`FYkEFZ@ό*4VJiZ)F) VJj?k`Wҵ>-/htQw'?fgyO٘"R#3W$BiZ+vJ(0BHyJWRYMk¦ {tc3g8ӰO#˃G+6 g>jZgqZ8I,š,+.i~ZyVJR 0aA)R1W^~hsc]?cG@g;ܷZۯ}~O"S'08 dۡVD9%bսn)ta,he+}Q~֥D+ et HEggQ<}?G{}[X0Ɉ>8O~;o{RIYfg96&I",$iy!<2jbBRͭ0ET $XIsʅu;;O/?;/!wOܸ֜ EfZ{ 2y~e1ߝdO;|T%`vzK'Ep8e}pYks^RJa}7R:ʥW>TcOu!ާ>~G+A!ZӜZ:h`<ƈ\y!.X!TZ!my:b})}( 2 Ɗr(^|.=瞓3wvŞloޠTkZNbZִ}+DB@e;{ *5?s^;x[m(`~nAH!eVc%ȰCa~ P욃bLToɓ'~QI5/ ' p4YV%t۝Os3 + sK $I2Xҕ+cOŸkf7mƕ9FW~'?}ͳrUVW/aVvۛq&W >6Sٟ} ?AWwv+ӵ/|駟^/ׂ7;J߷A+IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.947602 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/0000755000175000017500000000000014471213412020644 5ustar00nicknick././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/0000755000175000017500000000000014471213412021607 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg0000664000175000017500000000577214244626671031420 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg.in0000664000175000017500000000577214244626671032025 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso.svg0000664000175000017500000001422714244626671027574 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg0000664000175000017500000002006514244626671031737 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg.in0000664000175000017500000002006514244626671032344 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet.svg0000664000175000017500000002430014244626671030114 0ustar00nicknick image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/status/0000755000175000017500000000000014471213412022167 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/images/hicolor/scalable/status/quodlibet-missing-cover.svg0000664000175000017500000010427214035600052027467 0ustar00nicknick image/svg+xml Missing Album Cover Art cdrom missing artwork inlay Jakub Steiner ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/library/0000755000175000017500000000000014471213412015636 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1656278102.0 quodlibet-4.6.0/quodlibet/library/__init__.py0000664000175000017500000000430114256146126017757 0ustar00nicknick# Copyright 2006 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. """Various library classes. Libraries are (roughly) dicts of items, and in the case of Quod Libet, these items are songs. Libraries are in charge of alerting the rest of the program when songs have been added, changed, or removed. They can also be queried in various ways. """ import time from quodlibet import print_d, print_w, config from quodlibet.library.song import SongLibrary, SongFileLibrary from quodlibet.library.librarians import SongLibrarian from quodlibet.util.library import get_scan_dirs from quodlibet.util.path import mtime def init(cache_fn=None): """Set up the library and return the main one. Return a main library, and set a librarian for all future SongLibraries. """ SongFileLibrary.librarian = SongLibrary.librarian = SongLibrarian() watch = config.getboolean("library", "watch") library = SongFileLibrary("main", watch_dirs=get_scan_dirs() if watch else []) if cache_fn: library.load(cache_fn) return library def save(save_period=None): """Save all registered libraries that have a filename and are marked dirty. If `save_period` (seconds) is given the library will only be saved if it hasn't been in the last `save_period` seconds. """ print_d("Saving all libraries...") librarian = SongFileLibrary.librarian for lib in librarian.libraries.values(): filename = lib.filename if not filename or not lib.dirty: continue if not save_period or abs(time.time() - mtime(filename)) > save_period: lib.save() def destroy() -> None: """Destroy all registered libraries """ print_d("Destroying all libraries...") librarian = SongFileLibrary.librarian if librarian: for lib in list(librarian.libraries.values()): try: lib.destroy() except Exception as e: print_w(f"Couldn't destroy {lib} ({e!r})") librarian.destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1663102510.0 quodlibet-4.6.0/quodlibet/library/album.py0000644000175000017500000001036514310167056017321 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. from quodlibet import print_d from quodlibet.formats._audio import AlbumKey from quodlibet.library.base import Library from quodlibet.util.collection import Album class AlbumLibrary(Library[AlbumKey, Album]): """An AlbumLibrary listens to a SongLibrary and sorts its songs into albums. The library behaves like a dictionary: the keys are album_keys of AudioFiles, the values are Album objects. """ def __init__(self, library): self.librarian = None print_d("Initializing Album Library to watch %r" % library._name) super().__init__( "AlbumLibrary for %s" % library._name) self._library = library self._asig = library.connect('added', self.__added) self._rsig = library.connect('removed', self.__removed) self._csig = library.connect('changed', self.__changed) self.__added(library, library.values(), signal=False) def load(self): # deprecated pass def destroy(self): for sig in [self._asig, self._rsig, self._csig]: self._library.disconnect(sig) def _get(self, item): return self._contents.get(item) def __add(self, items): changed = set() new = set() for song in items: key = song.album_key if key in self._contents: changed.add(self._contents[key]) else: album = Album(song) self._contents[key] = album new.add(album) self._contents[key].songs.add(song) changed -= new return changed, new def __added(self, library, items, signal=True): changed, new = self.__add(items) for album in changed: album.finalize() if signal: if new: self.emit('added', new) if changed: self.emit('changed', changed) def __removed(self, library, items): changed = set() removed = set() for song in items: key = song.album_key album = self._contents[key] album.songs.remove(song) changed.add(album) if not album.songs: removed.add(album) del self._contents[key] changed -= removed for album in changed: album.finalize() if removed: self.emit('removed', removed) if changed: self.emit('changed', changed) def __changed(self, library, items): """Album keys could change between already existing ones... so we have to do it the hard way and search by id.""" print_d("Updating affected albums for %d items" % len(items)) changed = set() removed = set() to_add = [] for song in items: # in case the key hasn't changed key = song.album_key if key in self._contents and song in self._contents[key].songs: changed.add(self._contents[key]) else: # key changed... look for it in each album to_add.append(song) for key, album in self._contents.items(): if song in album.songs: album.songs.remove(song) if not album.songs: removed.add(album) else: changed.add(album) break # get new albums and changed ones because keys could have changed add_changed, new = self.__add(to_add) changed |= add_changed # check if albums that were empty at some point are still empty for album in removed: if not album.songs: del self._contents[album.key] changed.discard(album) for album in changed: album.finalize() if removed: self.emit("removed", removed) if changed: self.emit("changed", changed) if new: self.emit("added", new) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1672734865.0 quodlibet-4.6.0/quodlibet/library/base.py0000644000175000017500000002531714354764221017143 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2011-2022 Nick Boultbee # 2013,2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import shutil from typing import (Collection, TypeVar, Sequence, Iterable, Optional, Iterator, Generic, MutableMapping, Tuple, Set, Generator) from gi.repository import GObject import quodlibet from quodlibet import util from quodlibet.formats import (load_audio_files, dump_audio_files, SerializationError) from quodlibet.formats._audio import HasKey from quodlibet.util.atomic import atomic_save from quodlibet.util.collections import DictMixin from quodlibet.util.dprint import print_d, print_w from quodlibet.util.path import (mkdir, is_hidden) from senf import fsnative, path2fsn K = TypeVar("K", covariant=True) V = TypeVar("V", bound=HasKey) class Library(GObject.GObject, DictMixin, Generic[K, V]): """A Library contains useful objects. The only required method these objects support is a .key attribute, but specific types of libraries may require more advanced interfaces. Every method which takes a sequence of items expects items to implement __iter__, __len__ and __contains__. Likewise the signals emit sequences which implement __iter__, __len__ and __contains__ e.g. set(), list() or tuple(). WARNING: The library implements the dict interface with the exception that iterating over it yields values and not keys. """ __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'removed': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'added': (GObject.SignalFlags.RUN_LAST, None, (object,)), } librarian: Optional["quodlibet.library.librarians.Librarian"] = None """A librarian, if defined will be used for collaborating with other libraries""" dirty = False def __init__(self, name: Optional[str] = None): super().__init__() self._contents: MutableMapping[K, V] = {} self._name = name if self.librarian is not None and name is not None: self.librarian.register(self, name) def __str__(self): return f"<{type(self).__name__} @ {hex(id(self))}>" def destroy(self): if self.librarian is not None and self._name is not None: self.librarian._unregister(self, self._name) def changed(self, items: Collection[V]): """Alert other users that these items have changed. This causes a 'changed' signal. If a librarian is available this function will call its changed method instead, and all libraries that librarian manages may fire a 'changed' signal. The item list may be filtered to those items actually in the library. If a librarian is available, it will handle the filtering instead. That means if this method is delegated to the librarian, this library's changed signal may not fire, but another's might. """ if not items: return if self.librarian and self in self.librarian.libraries.values(): print_d(f"Changing {len(items)} items via librarian.", self._name) self.librarian.changed(items) else: items = {item for item in items if item in self} if not items: return print_d(f"Changing {len(items)} items directly.", self._name) self._changed(items) def _changed(self, items: Collection[V]): """Called by the changed method and Librarians.""" # assert isinstance(items, set) if not items: return print_d(f"Emitting changed for {len(items)} item(s) " f"(e.g. {list(items)[0].key!r}...)", self._name) self.dirty = True self.emit('changed', items) def __iter__(self) -> Iterator[V]: """Iterate over the items in the library.""" return iter(self._contents.values()) def iteritems(self) -> Iterator[Tuple[K, V]]: return iter(self._contents.items()) def iterkeys(self) -> Iterator[K]: return iter(self._contents.keys()) def itervalues(self) -> Iterator[V]: return iter(self._contents.values()) def __len__(self) -> int: """The number of items in the library.""" return len(self._contents) def __getitem__(self, key) -> V: """Find a item given its key.""" return self._contents[key] def __contains__(self, item): """Check if a key or item is in the library.""" try: return item in self._contents or item.key in self._contents except AttributeError: return False def get_content(self) -> Sequence[V]: """All items including hidden ones for saving the library (see FileLibrary with masked items) """ return list(self.values()) def keys(self) -> Iterable[K]: return self._contents.keys() def values(self) -> Iterable[V]: return self._contents.values() def _load_item(self, item: V) -> None: """Load (add) an item into this library""" # Subclasses should override this if they want to check # item validity; see `FileLibrary`. print_d(f"Loading {item.key!r}", self._name) self.dirty = True self._contents[item.key] = item def _load_init(self, items: Iterable[V]) -> None: """Load many items into the library (on start)""" # Subclasses should override this if they want to check # item validity; see `FileLibrary`. content = self._contents for item in items: content[item.key] = item def add(self, items: Iterable[V]) -> Set[V]: """Add items. This causes an 'added' signal. Return the sequence of items actually added, filtering out items already in the library. """ items = {item for item in items if item is not None and item not in self} if not items: return items if len(items) == 1: print_d(f"Adding {next(iter(items))}", self._name) else: print_d(f"Adding {len(items)} items.", self._name) for item in items: self._contents[item.key] = item self.dirty = True self.emit('added', items) return items def remove(self, items: Iterable[V]) -> Set[V]: """Remove items. This causes a 'removed' signal. Return the sequence of items actually removed. """ items = {item for item in items if item in self} if not items: return items print_d(f"Removing {len(items)} item(s).", self._name) for item in items: del self._contents[item.key] self.dirty = True self.emit('removed', items) return items def _load_items(filename) -> Iterable[V]: """Load items from disk. In case of an error returns default or an empty list. """ try: with open(filename, "rb") as fp: data = fp.read() except EnvironmentError: print_w("Couldn't load library file from: %r" % filename) return [] try: items = load_audio_files(data) except SerializationError: # there are too many ways this could fail util.print_exc() # move the broken file out of the way try: shutil.copy(filename, filename + ".not-valid") except EnvironmentError: util.print_exc() return [] return items class PicklingMixin: """A mixin to provide persistence of a library by pickling to disk""" filename = None def load(self, filename): """Load a library from a file, containing a picked list. Loading does not cause added, changed, or removed signals. """ self.filename = filename print_d("Loading contents of %r." % filename, self) items = _load_items(filename) # this loads all items without checking their validity, but makes # sure that non-mounted items are masked self._load_init(items) print_d(f"Done loading contents of {filename!r}", self._name) def save(self, filename=None): """Save the library to the given filename, or the default if `None`""" if filename is None: filename = self.filename print_d(f"Saving contents to {filename!r}", self._name) try: dirname = os.path.dirname(filename) mkdir(dirname) with atomic_save(filename, "wb") as fileobj: fileobj.write(dump_audio_files(self.get_content())) except SerializationError: # Can happen when we try to pickle while the library is being # modified, like in the periodic 15min save. # Ignore, as it should try again later or on program exit. util.print_exc() except EnvironmentError: print_w(f"Couldn't save library to path {filename!r}") else: self.dirty = False def iter_paths(root: fsnative, exclude: Optional[Iterable[fsnative]] = None, skip_hidden: bool = True) -> Generator[fsnative, None, None]: """Yields paths contained in root (symlinks dereferenced) Any path starting with any of the path parts included in exclude are ignored (before and after dereferencing symlinks) Directory symlinks are not followed (except root itself) Args: root: start here exclude: ignore any of these skip_hidden: Ignore files which are hidden or where any of the parent directories are hidden. Yields: fsnative: absolute dereferenced paths """ assert isinstance(root, fsnative) exclude = exclude or [] assert all((isinstance(p, fsnative) for p in exclude)) assert os.path.abspath(root) def skip(path): if skip_hidden and is_hidden(path): return True # FIXME: normalize paths.. return any((path.startswith(p) for p in exclude)) if skip_hidden and is_hidden(root): return for path, dnames, fnames in os.walk(root): if skip_hidden: dnames[:] = [d for d in dnames if not is_hidden(path2fsn(os.path.join(path, d)))] for filename in fnames: full_filename = path2fsn(os.path.join(path, filename)) if skip(full_filename): continue full_filename = path2fsn(os.path.realpath(full_filename)) if skip(full_filename): continue yield full_filename # type: ignore ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658692524.0 quodlibet-4.6.0/quodlibet/library/file.py0000644000175000017500000005620314267321654017150 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. import os import time from pathlib import Path from typing import Generator, Set, Iterable, Optional, Dict, Tuple, Union from gi.repository import Gio, GLib, GObject from quodlibet import print_d, print_w, _, formats from quodlibet.formats import AudioFileError, AudioFile from quodlibet.library.base import iter_paths, Library, PicklingMixin from quodlibet.qltk.notif import Task from quodlibet.util import copool, print_exc from quodlibet.util.library import get_exclude_dirs from quodlibet.util.path import ismount, unexpand, normalize_path from senf import fsn2text, fsnative class FileLibrary(Library[fsnative, AudioFile], PicklingMixin): """A library containing items on a local(-ish) filesystem. These must support the valid, exists, mounted, and reload methods, and have a mountpoint attribute. """ def __init__(self, name=None): super().__init__(name) self._masked = {} def _load_init(self, items): """Add many items to the library, check if the mountpoints are available and mark items as masked if not. Does not check if items are valid. """ mounts = {} contents = self._contents masked = self._masked for item in items: mountpoint = item.mountpoint if mountpoint not in mounts: is_mounted = ismount(mountpoint) # In case mountpoint is mounted through autofs we need to # access a sub path for it to mount # https://github.com/quodlibet/quodlibet/issues/2146 if not is_mounted: item.exists() is_mounted = ismount(mountpoint) mounts[mountpoint] = is_mounted # at least one not mounted, make sure masked has an entry if not is_mounted: masked.setdefault(mountpoint, {}) if mounts[mountpoint]: contents[item.key] = item else: masked[mountpoint][item.key] = item def _load_item(self, item, force=False): """Add an item, or refresh it if it's already in the library. No signals will be fired. Return a tuple of booleans: (changed, removed) """ print_d(f"Loading {item.key!r}", self._name) valid = item.valid() # The item is fine; add it if it's not present. if not force and valid: print_d(f"{item.key!r} is valid.", self._name) self._contents[item.key] = item return False, False else: # Either we should force a load, or the item is not okay. # We're going to reload; this could change the key. So # remove the item if it's currently in. try: del self._contents[item.key] except KeyError: present = False else: present = True # If the item still exists, reload it. if item.exists(): try: item.reload() except AudioFileError: print_w(f"Error reloading {item.key!r}", self._name) return False, True else: print_d(f"Reloaded {item.key!r}.", self._name) self._contents[item.key] = item return True, False elif not item.mounted(): # We don't know if the item is okay or not, since # it's not not mounted. If the item was present # we need to mark it as removed. print_d(f"Masking {item.key!r}", self._name) self._masked.setdefault(item.mountpoint, {}) self._masked[item.mountpoint][item.key] = item return False, present else: # The item doesn't exist at all anymore. Mark it as # removed if it was present, otherwise nothing. print_d(f"Ignoring (so removing) {item.key!r}.", self._name) return False, present def reload(self, item, changed=None, removed=None): """Reload a song, possibly noting its status. If sets are given, it assumes the caller will handle signals, and only updates the sets. Otherwise, it handles signals itself. It *always* handles library contents, so do not try to remove (again) a song that appears in the removed set. """ was_changed, was_removed = self._load_item(item, force=True) assert not (was_changed and was_removed) if was_changed: if changed is None: self.emit('changed', {item}) else: changed.add(item) elif was_removed: if removed is None: self.emit('removed', {item}) else: removed.add(item) def rebuild(self, paths, force=False, exclude=None, cofuncid=None): """Reload or remove songs if they have changed or been deleted. This generator rebuilds the library over the course of iteration. Any paths given will be scanned for new files, using the 'scan' method. Only items present in the library when the rebuild is started will be checked. If this function is copooled, set "cofuncid" to enable pause/stop buttons in the UI. """ print_d(f"Rebuilding, force is {force}", self._name) task = Task(_("Library"), _("Checking mount points")) if cofuncid: task.copool(cofuncid) for i, (point, items) in task.list(enumerate(self._masked.items())): if ismount(point): self._contents.update(items) del self._masked[point] self.emit('added', list(items.values())) yield True task = Task(_("Library"), _("Scanning library")) if cofuncid: task.copool(cofuncid) changed, removed = set(), set() for i, (key, item) in task.list(enumerate(sorted(self.items()))): if key in self._contents and force or not item.valid(): self.reload(item, changed, removed) # These numbers are pretty empirical. We should yield more # often than we emit signals; that way the main loop stays # interactive and doesn't get bogged down in updates. if len(changed) >= 200: self.emit('changed', changed) changed = set() if len(removed) >= 200: self.emit('removed', removed) removed = set() if len(changed) > 20 or i % 200 == 0: yield True print_d(f"Removing {len(removed)}, changing {len(changed)}).", self._name) if removed: self.emit('removed', removed) if changed: self.emit('changed', changed) for value in self.scan(paths, exclude, cofuncid): yield value def add_filename(self, filename: Union[str, Path], add: bool = True) -> Optional[AudioFile]: """Add a file based on its filename. Subclasses must override this to open the file correctly. :return: the audio file if added (or None) """ pass def contains_filename(self, filename) -> bool: """Returns if a song for the passed filename is in the library. """ key = normalize_path(filename, True) return key in self._contents def scan(self, paths: Iterable[fsnative], exclude: Optional[Iterable[fsnative]] = None, cofuncid=None): def need_yield(last_yield=[0]): current = time.time() if abs(current - last_yield[0]) > 0.015: last_yield[0] = current return True return False def need_added(last_added=[0]): current = time.time() if abs(current - last_added[0]) > 1.0: last_added[0] = current return True return False # first scan each path for new files paths_to_load = [] for scan_path in paths: print_d(f"Scanning {scan_path}", self._name) desc = _("Scanning %s") % (fsn2text(unexpand(scan_path))) with Task(_("Library"), desc) as task: if cofuncid: task.copool(cofuncid) for real_path in iter_paths(scan_path, exclude=exclude): if need_yield(): task.pulse() yield # skip unknown file extensions if not formats.filter(real_path): continue # already loaded if self.contains_filename(real_path): continue paths_to_load.append(real_path) yield # then (try to) load all new files with Task(_("Library"), _("Loading files")) as task: if cofuncid: task.copool(cofuncid) added = [] for real_path in task.gen(paths_to_load): item = self.add_filename(real_path, False) if item is not None: added.append(item) if len(added) > 100 or need_added(): self.add(added) added = [] yield if added and need_yield(): yield if added: self.add(added) added = [] yield True def get_content(self): """Return visible and masked items""" items = list(self.values()) for masked in self._masked.values(): items.extend(masked.values()) # Item keys are often based on filenames, in which case # sorting takes advantage of the filesystem cache when we # reload/rescan the files. items.sort(key=lambda item: item.key) return items def masked(self, item): """Return true if the item is in the library but masked.""" try: point = item.mountpoint except AttributeError: # Checking a key. for point in self._masked.values(): if item in point: return True else: # Checking a full item. return item in self._masked.get(point, {}).values() def unmask(self, point): print_d(f"Unmasking {point!r}", self._name) items = self._masked.pop(point, {}) if items: self.add(items.values()) def mask(self, point): print_d(f"Masking {point!r}", self._name) removed = {} for item in self.values(): if item.mountpoint == point: removed[item.key] = item if removed: self.remove(removed.values()) self._masked.setdefault(point, {}).update(removed) @property def masked_mount_points(self): """List of mount points that contain masked items""" return list(self._masked.keys()) def get_masked(self, mount_point): """List of items for a mount point""" return list(self._masked.get(mount_point, {}).values()) def remove_masked(self, mount_point): """Remove all songs for a masked point""" self._masked.pop(mount_point, {}) def move_root(self, old_root: str, new_root: fsnative, write_files: bool = True) -> Generator[None, None, None]: """ Move the root for all songs in a given (scan) directory. We avoid dereferencing the destination, to allow users things like: 1. Symlink new_path -> old_root 2. Move QL root to new_path 3. Remove symlink 4. Move audio files: old_root -> new_path """ # TODO: only move primary library old_path = Path(normalize_path(old_root, canonicalise=True)).expanduser() new_path = Path(normalize_path(new_root)).expanduser() if not old_path.is_dir(): print_w(f"Source dir {str(old_path)!r} doesn't exist, assuming that's OK", self._name) if not new_path.is_dir(): raise ValueError(f"Destination {new_path!r} is not a directory") print_d(f"Checking entire library for {str(old_path)!r}", self._name) missing: Set[AudioFile] = set() changed = set() total = len(self) if not total: return with Task(_("Library"), _("Moving library files")) as task: yield for i, song in enumerate(list(self.values())): task.update(i / total) key = normalize_path(song.key) path = Path(key) if old_path in path.parents: # TODO: more Pathlib-friendly dir replacement... new_key = key.replace(str(old_path), str(new_path), 1) new_key = normalize_path(new_key, canonicalise=False) if new_key == key: print_w(f"Substitution failed for {key!r}", self._name) # We need to update ~filename and ~mountpoint song.sanitize() if write_files: song.write() if self.move_song(song, new_key): changed.add(song) else: missing.add(song) elif not (i % 1000): print_d(f"Not moved, for example: {key!r}", self._name) if not i % 100: yield self.changed(changed) if missing: print_w(f"Couldn't find {len(list(missing))} files: {missing}", self._name) yield self.save() print_d(f"Done moving {len(changed)} track(s) (of {total}) " f"to {str(new_path)!r}.", self._name) def move_song(self, song: AudioFile, new_path: fsnative) -> bool: """Updates the location of a song, without touching the file. :returns: True if it was could be found (and moved) """ existed = True key = song.key print_d(f"Moving {key!r} -> {new_path!r}", self._name) try: del self._contents[key] # type: ignore except KeyError: existed = False # Continue - maybe it's already moved song.sanitize(new_path) self._contents[new_path] = song return existed def remove_roots(self, old_roots: Iterable[str]) -> Generator[None, None, None]: """Remove library roots (scandirs) entirely, and all their songs""" old_paths = [Path(normalize_path(root, canonicalise=True)).expanduser() for root in old_roots] total = len(self) removed = set() print_d(f"Removing library roots {old_roots}", self._name) yield with Task(_("Library"), _("Removing library files")) as task: for i, song in enumerate(list(self.values())): task.update(i / total) key = normalize_path(song.key) song_path = Path(key) if any(path in song_path.parents for path in old_paths): removed.add(song) if not i % 100: yield if removed: self.remove(removed) else: print_d(f"No tracks in {old_roots} to remove", self._name) Event = Gio.FileMonitorEvent class WatchedFileLibraryMixin(FileLibrary): """A File Library that sets up monitors on directories at refresh and handles changes sensibly""" def __init__(self, name=None): super().__init__(name) self._monitors: Dict[Path, Tuple[GObject.GObject, int]] = {} print_d(f"Initialised {self!r}") def monitor_dir(self, path: Path) -> None: """Monitors a single directory""" # Only add one monitor per absolute path... if path not in self._monitors: f = Gio.File.new_for_path(str(path)) try: monitor = f.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, None) except GLib.GError as e: print_w(f"Couldn't watch {path} ({e})", self._name) monitor = None if not monitor: return handler_id = monitor.connect("changed", self.__file_changed) # Don't destroy references - http://stackoverflow.com/q/4535227 self._monitors[path] = (monitor, handler_id) print_d(f"Monitoring {path!s}", self._name) def __file_changed(self, _monitor, main_file: Gio.File, other_file: Optional[Gio.File], event: Gio.FileMonitorEvent) -> None: if event == Event.CHANGES_DONE_HINT: # This seems to work fine on most Linux, but not on Windows / macOS # Or at least, not in CI anyway. # So shortcut the whole thing return try: file_path = main_file.get_path() if file_path is None: return file_path = normalize_path(file_path, True) song = self.get(file_path) file_path = Path(file_path) other_path = (Path(normalize_path(other_file.get_path(), True)) if other_file else None) if event in (Event.CREATED, Event.MOVED_IN): if file_path.is_dir(): self.monitor_dir(file_path) copool.add(self.scan, [str(file_path)]) elif not song: print_d(f"Auto-adding created file: {file_path}", self._name) self.add_filename(str(file_path)) elif event == Event.RENAMED: if not other_path: print_w(f"No destination found for rename of {file_path}", self._name) if song: print_d(f"Moving {file_path} to {other_path}...", self._name) if self.move_song(song, str(other_path)): # type:ignore print_w(f"Song {file_path} has gone") elif self.is_monitored_dir(file_path): if self.librarian: print_d(f"Moving tracks from {file_path} -> {other_path}...", self._name) copool.add(self.librarian.move_root, str(file_path), str(other_path), write_files=False, priority=GLib.PRIORITY_DEFAULT) self.unmonitor_dir(file_path) if other_path: self.monitor_dir(other_path) else: if other_path: print_w(f"Seems {file_path} is not a track (deleted?)", self._name) # On some (Windows?) systems CHANGED is called which can remove # before we get here, so let's try adding the new path back self.add_filename(other_path) elif event == Event.CHANGED: if song: # QL created (or knew about) this one; still check if it changed if not song.valid(): self.reload(song) else: print_d(f"Auto-adding new file: {file_path}", self._name) self.add_filename(file_path) elif event in (Event.MOVED_OUT, Event.DELETED): if song: print_d(f"...so deleting {file_path}", self._name) self.reload(song) else: # either not a song, or a song that was renamed by QL if self.is_monitored_dir(file_path): self.unmonitor_dir(file_path) # And try to remove all songs under that dir. Slowly. gone = set() for key, song in self.iteritems(): if file_path in Path(key).parents: gone.add(song) if gone: print_d(f"Removing {len(gone)} contained songs in {file_path}", self._name) actually_gone = self.remove(gone) if gone != actually_gone: print_w(f"Couldn't remove all: {gone - actually_gone}", self._name) else: print_d(f"Unhandled event {event} on {file_path} ({other_path})", self._name) return except Exception: print_w("Failed to run file monitor callback", self._name) print_exc() print_d(f"Finished handling {event}", self._name) def is_monitored_dir(self, path: Path) -> bool: return path in self._monitors def unmonitor_dir(self, path: Path) -> None: """Disconnect and remove any monitor for a directory, if found""" monitor, handler_id = self._monitors.get(path, (None, None)) if not monitor: print_d(f"Couldn't find path {path} in active monitors", self._name) return monitor.disconnect(handler_id) del self._monitors[path] def start_watching(self, paths: Iterable[fsnative]): print_d(f"Setting up file watches on {paths}...", self._name) exclude_dirs = [e for e in get_exclude_dirs() if e] def watching_producer(): # TODO: integrate this better with scanning. for fullpath in paths: desc = _("Adding watches for %s") % (fsn2text(unexpand(fullpath))) with Task(_("Library"), desc) as task: normalised = Path(normalize_path(fullpath, True)).expanduser() if any(Path(exclude) in normalised.parents for exclude in exclude_dirs): continue unpulsed = 0 self.monitor_dir(normalised) for path, dirs, files in os.walk(normalised): normalised = Path(normalize_path(path, True)) for d in dirs: self.monitor_dir(normalised / d) unpulsed += len(dirs) if unpulsed > 50: task.pulse() unpulsed = 0 yield copool.add(watching_producer, funcid="watch_library") def stop_watching(self): print_d(f"Removing watches on {len(self._monitors)} dirs", self._name) for monitor, handler_id in self._monitors.values(): monitor.disconnect(handler_id) self._monitors.clear() def destroy(self): self.stop_watching() super().destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1656278102.0 quodlibet-4.6.0/quodlibet/library/librarians.py0000664000175000017500000002123014256146126020346 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2012-2022 Nick Boultbee # 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """ Librarians for libraries. """ import itertools from typing import Dict, Iterable, Iterator, Generator from gi.repository import GObject from quodlibet.library.base import Library from quodlibet.library.playlist import PlaylistLibrary from quodlibet.util.dprint import print_d, print_w from senf import fsnative class Librarian(GObject.GObject): """The librarian is a nice interface to all active libraries. Librarians are a kind of meta-library. When any of their registered libraries fire a signal, they fire the same signal. Likewise, they provide various methods equivalent to the ones found in libraries that group the results of the real libraries. Attributes: libraries -- a dict mapping library names to libraries """ __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'removed': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'added': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self): super().__init__() self.libraries: Dict[str, Library] = {} self.__signals = {} def destroy(self) -> None: pass def register(self, library: Library, name: str) -> None: """Register a library with this librarian.""" if name in self.libraries or name in self.__signals: raise ValueError("library %r is already active" % name) added_sig = library.connect('added', self.__added) removed_sig = library.connect('removed', self.__removed) changed_sig = library.connect('changed', self.__changed) self.libraries[name] = library self.__signals[library] = [added_sig, removed_sig, changed_sig] def _unregister(self, library: Library, name: str) -> None: # This function, unlike register, should be private. # Libraries get unregistered at the discretion of the # librarian, not the libraries. del(self.libraries[name]) for signal_id in self.__signals[library]: library.disconnect(signal_id) del(self.__signals[library]) # FIXME: We can be smarter about this -- queue a list of items # and fire the signal after a short wait, to take advantage of # a case where many libraries fire a signal at the same time (or # one fires a signal often). def __changed(self, _library: Library, items: Iterable) -> None: self.emit('changed', items) def __added(self, _library: Library, items: Iterable) -> None: self.emit('added', items) def __removed(self, _library: Library, items: Iterable) -> None: self.emit('removed', items) def changed(self, items: Iterable) -> None: """Triage the items and inform their real libraries.""" for library in self.libraries.values(): in_library = set(item for item in items if item in library) if in_library: library._changed(in_library) def __getitem__(self, key): """Find a item given its key.""" for library in self.libraries.values(): try: return library[key] except KeyError: pass else: raise KeyError(key) def get(self, key, default=None): try: return self[key] except KeyError: return default def remove(self, items: Iterable): """Remove items from all libraries.""" for library in self.libraries.values(): library.remove(items) def __contains__(self, item) -> bool: """Check if a key or item is in the library.""" for library in self.libraries.values(): if item in library: return True else: return False def __iter__(self) -> Iterator: """Iterate over all items in all libraries.""" return itertools.chain(*self.libraries.values()) def move(self, items: Iterable, from_: Library, to: Library) -> None: """Move items from one library to another. This causes 'removed' signals on the from library, and 'added' signals on the 'to' library, but will not cause any signals to be emitted via this librarian. """ try: from_.handler_block(self.__signals[from_][1]) to.handler_block(self.__signals[to][0]) from_.remove(items) to.add(items) finally: from_.handler_unblock(self.__signals[from_][1]) to.handler_unblock(self.__signals[to][0]) def move_root(self, old_root: fsnative, new_root: fsnative, **kwargs) -> Generator: if old_root == new_root: print_d("Not moving to same root") return for library in self.libraries.values(): if hasattr(library, "move_root"): yield from library.move_root(old_root, new_root, **kwargs) def remove_roots(self, old_roots: Iterable[fsnative]) -> Generator: if not old_roots: return for library in self.libraries.values(): if hasattr(library, "remove_roots"): yield from library.remove_roots(old_roots) class SongLibrarian(Librarian): """A librarian for SongLibraries.""" def tag_values(self, tag): """Return a set of all values for the given tag.""" return {value for lib in self.libraries.values() for value in lib.tag_values(tag)} def rename(self, song, newname, changed=None): """Rename the song in all libraries it belongs to. The 'changed' signal will fire for any library the song is in except if a set() is passed as changed. """ # This needs to poke around inside the library directly. If # it uses add/remove to handle the songs it fires incorrect # signals. If it uses the library's rename method, it breaks # the call for future libraries because the item's key has # changed. So, it needs to reimplement the method. re_add = [] print_d(f"Renaming {song.key!r} to {newname!r}") for library in self.libraries.values(): try: del library._contents[song.key] except KeyError: pass else: re_add.append(library) song.rename(newname) for library in re_add: library._contents[song.key] = song if changed is None: library._changed({song}) else: changed.add(song) def reload(self, item, changed=None, removed=None): """Reload a song (for all libraries), possibly noting its status. If sets are given, it assumes the caller will handle signals, and only updates the sets. Otherwise, it handles signals itself. It *always* handles library contents, so do not try to remove (again) a song that appears in the removed set. """ had_item = [] print_d(f"Reloading {item.key!r}") for library in self.libraries.values(): try: del library._contents[item.key] except KeyError: pass else: had_item.append(library) try: library = had_item[0] except IndexError: return # Rely on the first library in the list to do the actual # load, then just inform the other libraries what happened. was_changed, was_removed = library._load_item(item, force=True) assert not (was_changed and was_removed) if was_removed: if removed is None: for library in had_item: library.emit('removed', {item}) else: removed.add(item) elif was_changed: for library in had_item: library._contents[item.key] = item if changed is None: for library in had_item: library.emit('changed', {item}) else: changed.add(item) @property def playlists(self): for lib in self.libraries.values(): if isinstance(lib, PlaylistLibrary): return lib try: return lib.playlists except AttributeError: pass print_w(f"No playlist library found: {self.libraries}") raise ValueError("No playlists library found") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1666907943.0 quodlibet-4.6.0/quodlibet/library/playlist.py0000644000175000017500000001502014326577447020073 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. import os import re from typing import Iterable, Generator, Optional import quodlibet from quodlibet import print_d, print_w, print_e, ngettext, _ from quodlibet.formats import AudioFile from quodlibet.library.base import Library from quodlibet.util.collection import (Playlist, XSPFBackedPlaylist, FileBackedPlaylist) from senf import text2fsn, _fsnative, fsn2text _DEFAULT_PLAYLIST_DIR = text2fsn(os.path.join(quodlibet.get_user_dir(), "playlists")) """Directory for playlist files""" HIDDEN_RE = re.compile(r'^\.\w[^.]*') """Hidden-like files, to ignored""" _MIN_NON_EMPTY_PL_BYTES = 4 """Arbitrary minimum file size for a legacy non-empty playlist file""" class PlaylistLibrary(Library[str, Playlist]): """A PlaylistLibrary listens to a SongLibrary, and keeps tracks of playlists of these songs. The library behaves like a dictionary: the keys are playlist names, the values are Playlist objects. """ def __init__(self, library: Library, pl_dir: _fsnative = _DEFAULT_PLAYLIST_DIR): self.librarian = None super().__init__(f"{type(self).__name__} for {library._name}") print_d(f"Initializing Playlist Library {self} to watch {library._name!r}") self.pl_dir = pl_dir if library is None: raise ValueError("Need a library to listen to") self._library = library self._read_playlists(library) self._rsig = library.connect('removed', self.__songs_removed) self._csig = library.connect('changed', self.__songs_changed) def _read_playlists(self, library) -> None: print_d(f"Reading playlist directory {self.pl_dir} (library: {library})") try: fns = os.listdir(self.pl_dir) except FileNotFoundError as e: print_w(f"No playlist dir found in {self.pl_dir!r}, creating. ({e})") os.mkdir(self.pl_dir) fns = [] # Populate this library by relying on existing signal passing. # Weird, but allows keeping the logic in one place failed = [] for fn in fns: full_path = os.path.join(self.pl_dir, fn) if os.path.isdir(full_path): continue if HIDDEN_RE.match(fsn2text(fn)): print_d(f"Ignoring hidden file {fn!r}") continue try: XSPFBackedPlaylist(self.pl_dir, fn, songs_lib=library, pl_lib=self) except TypeError as e: # Don't add to library - it's temporary legacy = FileBackedPlaylist(self.pl_dir, fn, songs_lib=library, pl_lib=None) if not len(legacy): try: size = os.stat(legacy._last_fn).st_size if size >= _MIN_NON_EMPTY_PL_BYTES: data = {"filename": fn, "size": size / 1024} print_w(_("No library songs found in legacy playlist " "%(filename)r (of size %(size).1f kB).") % data + " " + _("Have you changed library root dir(s), " "but not this playlist?")) continue except OSError: print_e(f"Problem reading {legacy._last_fn!r}") continue finally: failed.append(fn) print_w(f"Converting {fn!r} to XSPF format ({e})") XSPFBackedPlaylist.from_playlist(legacy, songs_lib=library, pl_lib=self) except EnvironmentError: print_w(f"Invalid Playlist {fn!r}") failed.append(fn) if failed: total = len(failed) print_e(ngettext("%d playlist failed to convert", "%d playlists failed to convert", total) % len(failed)) def create(self, name_base: Optional[str] = None) -> Playlist: if name_base: return XSPFBackedPlaylist.new(self.pl_dir, name_base, songs_lib=self._library, pl_lib=self) return XSPFBackedPlaylist.new(self.pl_dir, songs_lib=self._library, pl_lib=self) def create_from_songs(self, songs: Iterable[AudioFile], title=None) -> Playlist: """Creates a playlist visible to this library""" return XSPFBackedPlaylist.from_songs( self.pl_dir, songs, title=title, songs_lib=self._library, pl_lib=self) def destroy(self): for sig in [self._rsig, self._csig]: self._library.disconnect(sig) def playlists_featuring(self, song: AudioFile) -> Generator[Playlist, None, None]: """Returns a generator yielding playlists in which this song appears""" return (pl for pl in self if song in pl._list) def __songs_removed(self, library, songs): print_d(f"Removing {len(songs)} song(s) " f"across {len(self)} playlist(s) in {self}") changed = {pl for pl in self if pl.remove_songs(songs)} if changed: for pl in changed: pl.write() self.changed(changed) def __songs_changed(self, library, songs) -> None: # Q: what if the changes are entirely due to changes *from* this library? # A: seems safest to still emit 'changed' as collections can cache metadata etc changed = set() for playlist in self: for song in songs: if song in playlist.songs: changed.add(playlist) # It's definitely changed now, nothing else is interesting break if changed: # TODO: only write if anything *persisted* changes (#3622) # i.e. not internal stuff (notably: ~playlists itself) for pl in changed: pl.finalize() pl.write() self.changed(changed) def recreate(self, playlist: Playlist, songs: Iterable[AudioFile]): """Keep a playlist but entirely replace its contents This is useful for applying new external sorting etc""" playlist._list.clear() playlist._list.extend(songs) playlist.finalize() playlist.write() self.changed([playlist]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1664110870.0 quodlibet-4.6.0/quodlibet/library/song.py0000644000175000017500000001020414314050426017153 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. from pathlib import Path from typing import Optional, Set, Iterable, TypeVar, Union from quodlibet import util, print_d from quodlibet.formats import MusicFile, AudioFile from quodlibet.library.album import AlbumLibrary from quodlibet.library.base import Library, PicklingMixin, K from quodlibet.library.file import WatchedFileLibraryMixin from quodlibet.library.playlist import PlaylistLibrary from quodlibet.query import Query from quodlibet.util.path import normalize_path from senf import fsnative V = TypeVar("V", bound=AudioFile) class SongLibrary(Library[K, V], PicklingMixin): """A library for songs. Items in this kind of library must support (roughly) the AudioFile interface. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @util.cached_property def albums(self): return AlbumLibrary(self) @util.cached_property def playlists(self): pl_lib = PlaylistLibrary(self) print_d(f"Created playlist library {pl_lib}") return pl_lib def destroy(self): super().destroy() if "albums" in self.__dict__: self.albums.destroy() if "playlists" in self.__dict__: self.playlists.destroy() def tag_values(self, tag): """Return a set of all values for the given tag.""" return {value for song in self.values() for value in song.list(tag)} def rename(self, song, new_name, changed: Optional[Set] = None): """Rename a song. This requires a special method because it can change the song's key. The 'changed' signal may fire for this library or the changed song is added to the passed changed set(). If the song exists in multiple libraries you cannot use this method. Instead, use the librarian. """ if song.key == new_name: print_d(f"Nothing changed for {new_name!r}") return print_d(f"Renaming {song.key!r} to {new_name!r}", self) del self._contents[song.key] song.rename(new_name) self._contents[song.key] = song if changed is not None: changed.add(song) else: self.changed({song}) def query(self, text, sort=None, star=Query.STAR): """Query the library and return matching songs.""" if isinstance(text, bytes): text = text.decode('utf-8') songs = self.values() if text != "": search = Query(text, star).search songs = [s for s in songs if search(s)] return songs class SongFileLibrary(SongLibrary, WatchedFileLibraryMixin): """A library containing song files. Pickles contents to disk as `FileLibrary`""" def __init__(self, name=None, watch_dirs: Optional[Iterable[fsnative]] = None): print_d(f"Initializing {type(self)}: {name!r}") super().__init__(name) if watch_dirs: self.start_watching(watch_dirs) def get_filename(self, filename): key = normalize_path(filename, True) return self._contents.get(key) def add_filename(self, filename: Union[str, Path], add: bool = True) -> Optional[AudioFile]: """Add a song to the library based on filename. If 'add' is true, the song will be added and the 'added' signal may be fired. Example (add=False): load many songs and call Library.add(songs) to add all in one go. The song is returned if it is in the library after this call. Otherwise, None is returned. """ key = normalize_path(filename, True) song = None if key not in self._contents: song = MusicFile(filename) if song and add: self.add([song]) else: print_d(f"Already got file {filename!r}") song = self._contents[key] return song ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1689589142.0 quodlibet-4.6.0/quodlibet/main.py0000644000175000017500000001531714455212626015507 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012,2013 Christoph Reiter # 2010-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys import os from quodlibet import _ from quodlibet.cli import process_arguments, exit_ from quodlibet.util.dprint import print_d, print_, print_exc def main(argv=None): if argv is None: argv = sys.argv import quodlibet config_file = os.path.join(quodlibet.get_user_dir(), "config") quodlibet.init_cli(config_file=config_file) try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments(argv) finally: sys.modules.pop("gi.repository.Gtk", None) quodlibet.init() from quodlibet import app from quodlibet.qltk import add_signal_watch add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import util app.name = "Quod Libet" app.description = _("Music player and music library manager") app.id = "io.github.quodlibet.QuodLibet" app.process_name = "quodlibet" quodlibet.set_application_info(app) library_path = os.path.join(quodlibet.get_user_dir(), "songs") print_d("Initializing main library (%s)" % ( quodlibet.util.path.unexpand(library_path))) library = quodlibet.library.init(library_path) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = os.environ.get( "QUODLIBET_BACKEND", config.get("player", "backend")) try: player = quodlibet.player.init_player(wanted_backend, app.librarian) except PlayerError: print_exc() player = quodlibet.player.init_player("nullbe", app.librarian) app.player = player os.environ["PULSE_PROP_media.role"] = "music" os.environ["PULSE_PROP_application.icon_name"] = app.icon_name browsers.init() from quodlibet.qltk.songlist import SongList, get_columns headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("io.github.quodlibet.QuodLibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from quodlibet.plugins.query import QUERY_HANDLER QUERY_HANDLER.init_plugins() from gi.repository import GLib from quodlibet.commands import registry as cmd_registry, CommandError def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="", flush=True) from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) app.player_options = PlayerOptions(window) from quodlibet.qltk.window import Window from quodlibet.plugins.events import EventPluginHandler from quodlibet.plugins.gui import UserInterfacePluginHandler pm.register_handler(EventPluginHandler(library.librarian, player, app.window.songlist)) pm.register_handler(UserInterfacePluginHandler()) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = None mmkeys_handler = MMKeysHandler(app) mmkeys_handler.start() current_path = os.path.join(quodlibet.get_user_dir(), "current") fsiface = FSInterface(current_path, player, library) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) if DBusHandler is not None: DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet import session session_client = session.init(app) quodlibet.enable_periodic_save(save_library=True) if ("start-playing" in startup_actions or (config.getboolean("player", "restore_playing", False) and config.getboolean("player", "is_playing", False))): player.paused = False if "start-hidden" in startup_actions: Window.prevent_inital_show(True) # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.run(window, before_quit=before_quit) app.player_options.destroy() quodlibet.finish_first_session("quodlibet") mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() quodlibet.library.destroy() config.save() session_client.close() print_d("Finished shutdown.") if app.is_restarting: os.execv(sys.executable, [sys.executable] + sys.argv) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735241.994269 quodlibet-4.6.0/quodlibet/mmkeys/0000755000175000017500000000000014471213412015477 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/__init__.py0000664000175000017500000000725014035600052017612 0ustar00nicknick# Copyright 2014 Christoph Reiter # 2018 Ludovic Druette # # 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 2 of the License, or # (at your option) any later version. from quodlibet import config from quodlibet.util import print_d from ._base import MMKeysAction, MMKeysImportError def iter_backends(): if config.getboolean("settings", "disable_mmkeys"): return try: from .gnome import GnomeBackend, GnomeBackendOldName, MateBackend except MMKeysImportError: pass else: yield GnomeBackend yield GnomeBackendOldName yield MateBackend try: from .keybinder import KeybinderBackend except MMKeysImportError: pass else: yield KeybinderBackend try: from .winhook import WinHookBackend except MMKeysImportError: pass else: yield WinHookBackend try: from .osx import OSXBackend except MMKeysImportError: pass else: yield OSXBackend def find_active_backend(): print_d("Trying to find a mmkeys backend") for backend in iter_backends(): if backend.is_active(): print_d("Found %r" % backend.__name__) return backend class MMKeysHandler: """Manages multiple keybinding backends and translates the generated events to actions on the player backend. """ def __init__(self, app): self._backend = None self._window = app.window self._player = app.player self._player_options = app.player_options self._app_name = app.name def start(self): kind = find_active_backend() if not kind: return self._backend = kind(self._app_name, self._callback) # grab on start for cases when the window is hidden on start self._backend.grab() self._window.connect("notify::is-active", self._focus_event) def quit(self): if self._backend: self._backend.cancel() self._backend = None self._window = None self._player = None def _focus_event(self, window, param): if window.get_property(param.name) and self._backend: self._backend.grab() def _callback(self, action): print_d("Event %r from %r" % (action, type(self._backend).__name__)) def seek_relative(seconds): current = player.get_position() current += seconds * 1000 current = min(player.song("~#length") * 1000 - 1, current) current = max(0, current) player.seek(current) player = self._player player_options = self._player_options if action == MMKeysAction.PREV: player.previous(force=True) elif action == MMKeysAction.NEXT: player.next() elif action == MMKeysAction.STOP: player.stop() elif action == MMKeysAction.PLAY: player.play() elif action == MMKeysAction.PLAYPAUSE: player.playpause() elif action == MMKeysAction.PAUSE: player.paused = True elif action == MMKeysAction.FORWARD: if player.song: seek_relative(10) elif action == MMKeysAction.REWIND: if player.song: seek_relative(-10) elif action == MMKeysAction.REPEAT: player_options.repeat = not player_options.repeat elif action == MMKeysAction.SHUFFLE: player_options.shuffle = not player_options.shuffle else: assert 0, "unhandled event" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/_base.py0000664000175000017500000000242214035600052017120 0ustar00nicknick# Copyright 2014 Christoph Reiter # 2018 Ludovic Druette # # 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 2 of the License, or # (at your option) any later version. class MMKeysImportError(ImportError): pass class MMKeysAction: PLAY = "play" STOP = "stop" PAUSE = "pause" PREV = "prev" NEXT = "next" PLAYPAUSE = "playpause" FORWARD = "forward" REWIND = "rewind" REPEAT = "repeat" SHUFFLE = "shuffle" class MMKeysBackend: def __init_(self, name, callback): """Callback will be called in the main thread and gets passed an MMKeysAction. `name` should be the application name. """ raise NotImplementedError @classmethod def is_active(cls): """Should return if the backend should be used""" return True def grab(self): """Should tell the backend that the application was active (e.g. the main window got focused) """ pass def cancel(self): """After cancel returns the callback will no longer be called. Can be called multiple times. """ raise NotImplementedError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/gnome.py0000664000175000017500000001327514035600052017164 0ustar00nicknick# Copyright 2014 Christoph Reiter # 2018 Ludovic Druette # # 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 2 of the License, or # (at your option) any later version. import time from gi.repository import GLib, Gio from quodlibet.util import print_exc from ._base import MMKeysBackend, MMKeysAction def dbus_has_interface(dbus_name, dbus_path, dbus_interface): try: proxy = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, dbus_name, dbus_path, "org.freedesktop.DBus.Introspectable", None) xml = proxy.Introspect() node = Gio.DBusNodeInfo.new_for_xml(xml) for iface in node.interfaces: if iface.name == dbus_interface: return True return False except GLib.Error: return False class GnomeBackend(MMKeysBackend): DBUS_NAME = "org.gnome.SettingsDaemon.MediaKeys" DBUS_PATH = "/org/gnome/SettingsDaemon/MediaKeys" DBUS_IFACE = "org.gnome.SettingsDaemon.MediaKeys" _EVENTS = { "Next": MMKeysAction.NEXT, "Previous": MMKeysAction.PREV, "Play": MMKeysAction.PLAYPAUSE, "Pause": MMKeysAction.PAUSE, "Stop": MMKeysAction.STOP, "FastForward": MMKeysAction.FORWARD, "Rewind": MMKeysAction.REWIND, "Repeat": MMKeysAction.REPEAT, "Shuffle": MMKeysAction.SHUFFLE } def __init__(self, name, callback): self.__interface = None self.__watch = None self.__grab_time = -1 self.__name = name self.__key_pressed_sig = None self.__callback = callback self.__enable_watch() @classmethod def is_active(cls): """If the gsd plugin is active atm""" return dbus_has_interface(cls.DBUS_NAME, cls.DBUS_PATH, cls.DBUS_IFACE) def cancel(self): if self.__callback: self.__disable_watch() self.__release() self.__callback = None def grab(self, update=True): """Tells gsd that QL started or got the focus. update: whether to send the current time or the last one""" if update: # so this breaks every 50 days.. ok.. self.__grab_time = int((time.time() * 1000)) & 0xFFFFFFFF elif self.__grab_time < 0: # can not send the last event if there was none return iface = self.__update_interface() if not iface: return try: iface.GrabMediaPlayerKeys('(su)', self.__name, self.__grab_time) except GLib.Error: print_exc() def __update_interface(self): """If __interface is None, set a proxy interface object and connect to the key pressed signal.""" if self.__interface: return self.__interface try: iface = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_PATH, self.DBUS_IFACE, None) except GLib.Error: print_exc() else: self.__key_pressed_sig = iface.connect( 'g-signal', self.__on_signal) self.__interface = iface return self.__interface def __enable_watch(self): """Enable events for dbus name owner change""" if self.__watch: return # This also triggers for existing name owners self.__watch = Gio.bus_watch_name( Gio.BusType.SESSION, self.DBUS_NAME, Gio.BusNameWatcherFlags.NONE, self.__owner_appeared, self.__owner_vanished) def __disable_watch(self): """Disable name owner change events""" if self.__watch: Gio.bus_unwatch_name(self.__watch) self.__watch = None def __owner_appeared(self, bus, name, owner): """This gets called when the owner of the dbus name appears so we can handle gnome-settings-daemon restarts.""" if not self.__interface: # new owner, get a new interface object and # resend the last grab event self.grab(update=False) def __owner_vanished(self, bus, owner): """This gets called when the owner of the dbus name disappears so we can handle gnome-settings-daemon restarts.""" # owner gone, remove the signal matches/interface etc. self.__release() def __on_signal(self, proxy, sender, signal, args): if signal == 'MediaPlayerKeyPressed': application, action = tuple(args)[:2] self.__key_pressed(application, action) def __key_pressed(self, application, action): if application != self.__name: return if action in self._EVENTS: self.__callback(self._EVENTS[action]) def __release(self): """Tells gsd that we don't want events anymore and removes all signal matches""" if not self.__interface: return if self.__key_pressed_sig: self.__interface.disconnect(self.__key_pressed_sig) self.__key_pressed_sig = None try: self.__interface.ReleaseMediaPlayerKeys('(s)', self.__name) except GLib.Error: print_exc() self.__interface = None # https://mail.gnome.org/archives/desktop-devel-list/2017-April/msg00069.html class GnomeBackendOldName(GnomeBackend): DBUS_NAME = "org.gnome.SettingsDaemon" class MateBackend(GnomeBackend): DBUS_NAME = "org.mate.SettingsDaemon" DBUS_PATH = "/org/mate/SettingsDaemon/MediaKeys" DBUS_IFACE = "org.mate.SettingsDaemon.MediaKeys" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/keybinder.py0000664000175000017500000000311714035600052020025 0ustar00nicknick# Copyright 2014 Christoph Reiter # 2018 Ludovic Druette # # 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 2 of the License, or # (at your option) any later version. from ._base import MMKeysBackend, MMKeysAction, MMKeysImportError import gi try: gi.require_version("Keybinder", "3.0") except ValueError: raise MMKeysImportError try: from gi.repository import Keybinder except ImportError: raise MMKeysImportError Keybinder.init() class KeybinderBackend(MMKeysBackend): _EVENTS = { "XF86AudioPrev": MMKeysAction.PREV, "XF86AudioNext": MMKeysAction.NEXT, "XF86AudioStop": MMKeysAction.STOP, "XF86AudioPlay": MMKeysAction.PLAYPAUSE, "XF86AudioForward": MMKeysAction.FORWARD, "XF86AudioRewind": MMKeysAction.REWIND, "XF86AudioRepeat": MMKeysAction.REPEAT, "XF86AudioRandomPlay": MMKeysAction.SHUFFLE } def __init__(self, name, callback): self._callback = callback self._worked = [] for keystring, action in self._EVENTS.items(): if Keybinder.bind(keystring, self._bind_cb, None): self._worked.append(keystring) def _bind_cb(self, keystring, *args): self._callback(self._EVENTS[keystring]) def cancel(self): if not self._callback: return for keystring in self._worked: Keybinder.unbind(keystring) del self._worked[:] self._callback = None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/osx.py0000664000175000017500000001267614035600052016674 0ustar00nicknick# Copyright 2012 Martijn Pieters # Copyright 2014 Eric Le Lay elelay.fr:dev # # 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 2 of the License, or # (at your option) any later version. """ osxmmkey - Mac OS X Media Keys support -------------------------------------- Requires the PyObjC, with the Cocoa and Quartz bindings to be installed. Under macports, that's the `py27-pyobjc`, `py27-pyobjc-cocoa` and`py27-pyobjc-quartz` ports, or equivalents for the python version used by quodlibet. This plugin also requires that 'access for assistive devices' is enabled, see the Universal Access preference pane in the OS X System Prefences. We register a Quartz event tap to listen for the multimedia keys and intercept them to control QL and prevent iTunes to get them. """ import threading from gi.repository import GLib from ._base import MMKeysBackend, MMKeysAction, MMKeysImportError try: from AppKit import NSKeyUp, NSSystemDefined, NSEvent import Quartz except ImportError: raise MMKeysImportError class OSXBackend(MMKeysBackend): def __init__(self, name, callback): self.__eventsapp = MacKeyEventsTap(callback) self.__eventsapp.start() def cancel(self): if self.__eventsapp is not None: self.__eventsapp.stop() self.__eventsapp = None class MacKeyEventsTap(threading.Thread): # Quartz event tap, listens for media key events and translates these to # control messages for quodlibet. _EVENTS = { 16: MMKeysAction.PLAYPAUSE, 19: MMKeysAction.NEXT, 20: MMKeysAction.PREV, } def __init__(self, callback): super().__init__() self._callback = callback self._tap = None self._runLoopSource = None self._event = threading.Event() def _push_callback(self, action): # push to the main thread, ignore if we have been stopped by now def idle_call(action): if self._tap: self._callback(action) return False GLib.idle_add(idle_call, action) def _event_tap(self, proxy, type_, event, refcon): # evenTrap disabled by timeout or user input, re-enable if type_ == Quartz.kCGEventTapDisabledByUserInput or \ type_ == Quartz.kCGEventTapDisabledByTimeout: assert self._tap is not None Quartz.CGEventTapEnable(self._tap, True) return event # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() == 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._EVENTS: if keyState == NSKeyUp: self._push_callback(self._EVENTS[keyCode]) return None # swallow the event, so iTunes doesn't launch return event def _loop_start(self, observer, activiti, info): self._event.set() def run(self): self._tap = Quartz.CGEventTapCreate( Quartz.kCGSessionEventTap, # Session level is enough for our needs Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter # Active, to swallow the play/pause event is enough Quartz.kCGEventTapOptionDefault, # NSSystemDefined for media keys Quartz.CGEventMaskBit(NSSystemDefined), self._event_tap, None ) # the above can fail if self._tap is None: self._event.set() return self._loop = Quartz.CFRunLoopGetCurrent() # add an observer so we know when we can stop it # without a race condition self._observ = Quartz.CFRunLoopObserverCreate( None, Quartz.kCFRunLoopEntry, False, 0, self._loop_start, None) Quartz.CFRunLoopAddObserver( self._loop, self._observ, Quartz.kCFRunLoopCommonModes) # Create a runloop source and add it to the current loop self._runLoopSource = Quartz.CFMachPortCreateRunLoopSource( None, self._tap, 0) Quartz.CFRunLoopAddSource( self._loop, self._runLoopSource, Quartz.kCFRunLoopDefaultMode ) # Enable the tap Quartz.CGEventTapEnable(self._tap, True) # runrunrun Quartz.CFRunLoopRun() def stop(self): """Call once from the main thread to stop the thread. After this returns no callback will be called anymore. """ # wait until we fail or the observer tells us that the loop has started self._event.wait() # failed to create a tap, nothing to stop if self._tap is None: return # remove the runloop source Quartz.CFRunLoopRemoveSource( self._loop, self._runLoopSource, Quartz.kCFRunLoopDefaultMode ) self._runLoopSource = None # remove observer Quartz.CFRunLoopRemoveObserver( self._loop, self._observ, Quartz.kCFRunLoopCommonModes) self._observ = None # stop the loop Quartz.CFRunLoopStop(self._loop) self._loop = None # Disable the tap Quartz.CGEventTapEnable(self._tap, False) self._tap = None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/mmkeys/winhook.py0000664000175000017500000000503514035600052017530 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys import ctypes from quodlibet.util import winapi from ._base import MMKeysBackend, MMKeysAction, MMKeysImportError if sys.platform != "win32": raise MMKeysImportError class WinHookBackend(MMKeysBackend): def __init__(self, name, callback): self._callback = callback self._hhook = None self._kb_proc_ptr = None try: self._start() except WindowsError: pass def cancel(self): try: self._stop() except WindowsError: pass def _kb_proc(self, nCode, wParam, lParam): """A LowLevelKeyboardProc""" if nCode == winapi.HC_ACTION and wParam == winapi.WM_KEYDOWN: hstruct_ptr = ctypes.cast(lParam, winapi.LPKBDLLHOOKSTRUCT) assert hstruct_ptr hstruct = hstruct_ptr.contents vkCode = hstruct.vkCode STOP_PROCESSING = 1 if vkCode == winapi.VK_MEDIA_PLAY_PAUSE: self._callback(MMKeysAction.PLAYPAUSE) return STOP_PROCESSING elif vkCode == winapi.VK_MEDIA_STOP: self._callback(MMKeysAction.STOP) return STOP_PROCESSING elif vkCode == winapi.VK_MEDIA_NEXT_TRACK: self._callback(MMKeysAction.NEXT) return STOP_PROCESSING elif vkCode == winapi.VK_MEDIA_PREV_TRACK: self._callback(MMKeysAction.PREV) return STOP_PROCESSING return winapi.CallNextHookEx(self._hhook, nCode, wParam, lParam) def _start(self): """Start mmkey monitoring. Might raise WindowsError. """ kb_proc_ptr = winapi.LowLevelKeyboardProc(self._kb_proc) hhook = winapi.SetWindowsHookExW( winapi.WH_KEYBOARD_LL, kb_proc_ptr, None, 0) if not hhook: raise winapi.WinError() self._kb_proc_ptr = kb_proc_ptr self._hhook = hhook def _stop(self): """Stop mmkey monitoring. Can be called multiple times. Might raise WindowsError. """ if self._hhook is not None: if winapi.UnhookWindowsHookEx(self._hhook) == 0: raise winapi.WinError() self._hhook = None self._kb_proc_ptr = None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/operon/0000755000175000017500000000000014471213412015474 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/operon/__init__.py0000664000175000017500000000047714035600052017613 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .main import main main ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/operon/base.py0000664000175000017500000000517514035600052016766 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from typing import Type, List from optparse import OptionParser from quodlibet import _ from quodlibet.formats import MusicFile, AudioFileError from quodlibet.util import print_ class CommandError(Exception): pass class Command: """Base class for commands. Subclasses can override _add_options() and _execute() """ NAME = "" DESCRIPTION = "" USAGE = "" COMMANDS: "List[Type[Command]]" = [] @classmethod def register(cls, cmd_cls): cls.COMMANDS.append(cmd_cls) cls.COMMANDS.sort(key=lambda c: c.NAME) def __init__(self, main_cmd, options=None): self._main_cmd = main_cmd usage = "%s %s %s" % (main_cmd, self.NAME, self.USAGE) self.__parser = OptionParser(usage=usage, description=self.DESCRIPTION) if options is None: options = self.__parser.parse_args([])[0] self.__options = options self._add_options(self.__parser) def _add_options(self, parser): """Override to add options to the parser""" pass @property def verbose(self): return self.__options.verbose @verbose.setter def verbose(self, value): self.__options.verbose = bool(value) def log(self, text): """Print output if --verbose was passed""" if self.verbose: return print_(text, file=sys.stderr) def load_song(self, path): """Load a song. Raises CommandError in case it fails""" self.log("Load file: %r" % path) song = MusicFile(path) if not song: raise CommandError(_("Failed to load file: %r") % path) return song def save_songs(self, songs): """Save all passed songs""" self.log("Saving songs...") for song in songs: try: song.write() except AudioFileError as e: raise CommandError(e) def _execute(self, options, args): """Override to execute something""" raise NotImplementedError def print_help(self, file=None): """Print the help information about the command""" if file is None: file = sys.stdout self.__parser.print_help(file=file) def execute(self, args): """Execute the command""" options, args = self.__parser.parse_args(args) self._execute(options, args) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658680115.0 quodlibet-4.6.0/quodlibet/operon/commands.py0000644000175000017500000006050314267271463017670 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. # TODO: # RenameCommand # FillTracknumberCommand import os import re import shutil import subprocess import tempfile from senf import fsn2text from quodlibet import _ from quodlibet import util from quodlibet.formats import EmbeddedImage, AudioFileError from quodlibet.util.path import mtime from quodlibet.pattern import Pattern, error as PatternError from quodlibet.util.tags import USER_TAGS, sortkey, MACHINE_TAGS from quodlibet.util.tagsfrompath import TagsFromPattern from .base import Command, CommandError from .util import print_terse_table, copy_mtime, list_tags, print_table, \ get_editor_args @Command.register class ListCommand(Command): NAME = "list" DESCRIPTION = _("List tags") USAGE = "[-a] [-t] [-c ,...] " def _add_options(self, p): p.add_option("-t", "--terse", action="store_true", help=_("Print terse output")) p.add_option("-c", "--columns", action="store", type="string", help=_("Columns to display and order in terse mode (%s)") % "desc,value,tag") p.add_option("-a", "--all", action="store_true", help=_("Also list programmatic tags")) def _execute(self, options, args): if len(args) < 1: raise CommandError(_("Not enough arguments")) elif len(args) > 1: raise CommandError(_("Too many arguments")) path = args[0] headers = [_("Description"), _("Value"), _("Tag")] nicks = ["desc", "value", "tag"] if not options.columns: order = nicks else: order = [n.strip() for n in options.columns.split(",")] song = self.load_song(path) tags = list_tags(song, machine=options.all, terse=options.terse) if options.terse: print_terse_table(tags, nicks, order) else: print_table(tags, headers, nicks, order) @Command.register class TagsCommand(Command): NAME = "tags" DESCRIPTION = _("List all common tags") USAGE = "[-t] [-c ,...]" def _add_options(self, p): p.add_option("-t", "--terse", action="store_true", help=_("Print terse output")) p.add_option("-c", "--columns", action="store", type="string", help=_("Columns to display and order in terse mode (%s)") % "tag,desc") p.add_option("-a", "--all", action="store_true", help=_("Also list programmatic tags")) def _execute(self, options, args): if len(args) != 0: raise CommandError(_("Too many arguments")) headers = [_("Tag"), _("Description")] nicks = ["tag", "desc"] if not options.columns: order = nicks else: order = [n.strip() for n in options.columns.split(",")] tag_names = list(USER_TAGS) if options.all: tag_names.extend(MACHINE_TAGS) tags = [] for key in tag_names: tags.append((key, util.tag(key))) tags.sort() if not options.terse: print_table(tags, headers, nicks, order) else: print_terse_table(tags, nicks, order) @Command.register class CopyCommand(Command): NAME = "copy" DESCRIPTION = _("Copy tags from one file to another") USAGE = "[--dry-run] [--ignore-errors] " def _add_options(self, p): p.add_option("--dry-run", action="store_true", help=_("Show changes, don't apply them")) p.add_option("--ignore-errors", action="store_true", help=_("Skip tags that can't be written")) def _execute(self, options, args): if len(args) < 2: raise CommandError(_("Not enough arguments")) elif len(args) > 2: raise CommandError(_("Too many arguments")) if options.dry_run: self.verbose = True source_path = args[0] dest_path = args[1] source = self.load_song(source_path) dest = self.load_song(dest_path) for key in source.realkeys(): self.log("Copy %r" % key) if not options.ignore_errors and not dest.can_change(key): raise CommandError( _("Can't copy tag {tagname} to file: {filename}").format( tagname=repr(key), filename=repr(dest_path))) for value in source.list(key): dest.add(key, value) if not options.dry_run: self.save_songs([dest]) @Command.register class EditCommand(Command): NAME = "edit" DESCRIPTION = _("Edit tags in a text editor") USAGE = "[--dry-run] " # TODO: support editing multiple files def _add_options(self, p): p.add_option("--dry-run", action="store_true", help=_("Show changes, don't apply them")) def _song_to_text(self, song): # to text lines = [] for key in sorted(song.realkeys(), key=sortkey): for value in song.list(key): lines.append(u"%s=%s" % (key, value)) lines += [ u"", u"#" * 80, u"# Lines that are empty or start with '#' will be ignored", u"# File: %r" % fsn2text(song("~filename")), ] return u"\n".join(lines) def _text_to_song(self, text, song): assert isinstance(text, str) # parse tags = {} for line in text.splitlines(): if not line.strip() or line.startswith(u"#"): continue try: key, value = line.split(u"=", 1) except ValueError: continue tags.setdefault(key, []).append(value) # apply changes, sort to always have the same output for key in sorted(song.realkeys(), key=sortkey): new = tags.pop(key, []) old = song.list(key) for value in old: if value not in new: self.log("Remove %s=%s" % (key, value)) song.remove(key, value) for value in new: if value not in old: self.log("Add %s=%s" % (key, value)) song.add(key, value) for key, values in tags.items(): if not song.can_change(key): raise CommandError( "Can't change key '%(key-name)s'." % {"key-name": key}) for value in values: self.log("Add %s=%s" % (key, value)) song.add(key, value) def _execute(self, options, args): if len(args) < 1: raise CommandError(_("Not enough arguments")) elif len(args) > 1: raise CommandError(_("Too many arguments")) song = self.load_song(args[0]) dump = self._song_to_text(song).encode("utf-8") # write to tmp file fd, path = tempfile.mkstemp(suffix=".txt") try: try: os.write(fd, dump) finally: os.close(fd) # XXX: copy mtime here so we can test for changes in tests by # setting a out of date mtime on the source song file copy_mtime(args[0], path) # only parse the result if the editor returns 0 and the mtime has # changed old_mtime = mtime(path) editor_args = get_editor_args() self.log("Using editor: %r" % editor_args) try: subprocess.check_call(editor_args + [path]) except subprocess.CalledProcessError as e: self.log(str(e)) raise CommandError(_("Editing aborted")) except OSError as e: self.log(str(e)) raise CommandError( _("Starting text editor '%(editor-name)s' failed.") % { "editor-name": editor_args[0]}) was_changed = mtime(path) != old_mtime if not was_changed: raise CommandError(_("No changes detected")) with open(path, "rb") as h: data = h.read() finally: os.unlink(path) try: text = data.decode("utf-8") except ValueError as e: raise CommandError("Invalid data: %r" % e) if options.dry_run: self.verbose = True self._text_to_song(text, song) if not options.dry_run: self.save_songs([song]) @Command.register class SetCommand(Command): NAME = "set" DESCRIPTION = _("Set a tag and remove existing values") USAGE = "[--dry-run] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help=_("Show changes, don't apply them")) def _execute(self, options, args): if len(args) < 3: raise CommandError(_("Not enough arguments")) tag = fsn2text(args[0]) value = fsn2text(args[1]) paths = args[2:] songs = [] for path in paths: song = self.load_song(path) if not song.can_change(tag): vars = dict(tag=tag, format=type(song).format, file=song("~filename")) raise CommandError( _("Can not set %(tag)r for %(format)s file %(file)r") % vars) self.log("Set %r to %r" % (value, tag)) if tag in song: del song[tag] song.add(tag, value) songs.append(song) if not options.dry_run: self.save_songs(songs) @Command.register class ClearCommand(Command): NAME = "clear" DESCRIPTION = _("Remove tags") USAGE = "[--dry-run] [-a | -e | ] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help=_("Show changes, don't apply them")) p.add_option("-e", "--regexp", action="store", type="string", help=_("Value is a regular expression")) p.add_option("-a", "--all", action="store_true", help=_("Remove all tags")) def _execute(self, options, args): if options.all and options.regexp is not None: raise CommandError(_("Can't combine '--all' with '--regexp'")) if options.regexp is not None or options.all: if len(args) < 1: raise CommandError(_("Not enough arguments")) paths = args else: if len(args) < 2: raise CommandError(_("Not enough arguments")) paths = args[1:] if options.dry_run: self.verbose = True songs = [] for path in paths: song = self.load_song(path) tags = [] realkeys = song.realkeys() if options.all: tags.extend(realkeys) elif options.regexp is not None: e = re.compile(options.regexp) tags.extend(filter(e.match, realkeys)) else: tag = args[0] if tag in realkeys: tags.append(tag) for tag in tags: self.log("Remove tag %r" % tag) if not song.can_change(tag): raise CommandError( _("Can't remove {tagname} from {filename}").format( tagname=repr(tag), filename=repr(path))) del song[tag] if tags: songs.append(song) if not options.dry_run: self.save_songs(songs) @Command.register class RemoveCommand(Command): NAME = "remove" DESCRIPTION = _("Remove a tag value") USAGE = "[--dry-run] [-e | ] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help=_("Show changes, don't apply them")) p.add_option("-e", "--regexp", action="store", type="string", help=_("Value is a regular expression")) def _execute(self, options, args): if options.regexp is None: if len(args) < 3: raise CommandError(_("Not enough arguments")) else: if len(args) < 2: raise CommandError(_("Not enough arguments")) if options.dry_run: self.verbose = True tag = args[0] if options.regexp is not None: match = re.compile(options.regexp).match paths = args[1:] else: value = args[1] paths = args[2:] match = lambda v: v == value songs = [] for path in paths: song = self.load_song(path) if tag not in song: continue for v in song.list(tag): if match(v): self.log("Remove %r from %r" % (v, tag)) song.remove(tag, v) songs.append(song) if not options.dry_run: self.save_songs(songs) @Command.register class AddCommand(Command): NAME = "add" DESCRIPTION = _("Add a tag value") USAGE = " []" def _execute(self, options, args): if len(args) < 3: raise CommandError(_("Not enough arguments")) tag = fsn2text(args[0]) value = fsn2text(args[1]) paths = args[2:] songs = [] for path in paths: song = self.load_song(path) if not song.can_change(tag): raise CommandError(_("Can not set %r") % tag) self.log("Add %r to %r" % (value, tag)) song.add(tag, value) songs.append(song) self.save_songs(songs) @Command.register class InfoCommand(Command): NAME = "info" DESCRIPTION = _("List file information") USAGE = "[-t] [-c ,...] " def _add_options(self, p): p.add_option("-t", "--terse", action="store_true", help=_("Print terse output")) p.add_option("-c", "--columns", action="store", type="string", help=_("Columns to display and order in terse mode (%s)") % "desc,value") def _execute(self, options, args): if len(args) < 1: raise CommandError(_("Not enough arguments")) elif len(args) > 1: raise CommandError(_("Too many arguments")) path = args[0] song = self.load_song(path) headers = [_("Description"), _("Value")] nicks = ["desc", "value"] if not options.columns: order = nicks else: order = [n.strip() for n in options.columns.split(",")] if not options.terse: tags = [] for key in ["~format", "~codec", "~encoding", "~length", "~bitrate", "~filesize"]: tags.append((util.tag(key), str(song.comma(key)))) print_table(tags, headers, nicks, order) else: tags = [] for key in ["~format", "~codec", "~encoding", "~#length", "~#bitrate", "~#filesize"]: tags.append((key.lstrip("#~"), str(song(key)))) print_terse_table(tags, nicks, order) @Command.register class ImageSetCommand(Command): NAME = "image-set" DESCRIPTION = _("Set the provided image as primary embedded image and " "remove all other embedded images") USAGE = " []" def _execute(self, options, args): if len(args) < 2: raise CommandError(_("Not enough arguments")) image_path = args[0] paths = args[1:] image = EmbeddedImage.from_path(image_path) if not image: raise CommandError(_("Failed to load image file: %r") % image_path) songs = [self.load_song(p) for p in paths] for song in songs: if not song.can_change_images: raise CommandError( _("Image editing not supported for %(file_name)s " "(%(file_format)s)") % { "file_name": song("~filename"), "file_format": song("~format") }) for song in songs: try: song.set_image(image) except AudioFileError as e: raise CommandError(e) @Command.register class ImageClearCommand(Command): NAME = "image-clear" DESCRIPTION = _("Remove all embedded images") USAGE = " []" def _execute(self, options, args): if len(args) < 1: raise CommandError(_("Not enough arguments")) paths = args songs = [self.load_song(p) for p in paths] for song in songs: if not song.can_change_images: raise CommandError( _("Image editing not supported for %(file_name)s " "(%(file_format)s)") % { "file_name": song("~filename"), "file_format": song("~format") }) for song in songs: try: song.clear_images() except AudioFileError as e: raise CommandError(e) @Command.register class ImageExtractCommand(Command): NAME = "image-extract" DESCRIPTION = ( _("Extract embedded images to %(filepath)s") % { "filepath": "/-.(jpeg|png|..)" } ) USAGE = "[--dry-run] [--primary] [-d ] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help="don't save images") p.add_option("--primary", action="store_true", help="only extract the primary image") p.add_option("-d", "--destination", action="store", type="string", help=_("Path to where the images will be saved to " "(defaults to the working directory)")) def _execute(self, options, args): if len(args) < 1: raise CommandError(_("Not enough arguments")) # dry run implies verbose if options.dry_run: self.verbose = True paths = args for path in paths: song = self.load_song(path) # get the primary one or all of them if options.primary: image = song.get_primary_image() images = [image] if image else [] else: images = song.get_images() self.log("Images for %r: %r" % (path, images)) if not images: continue # get the basename from the song without the extension basename = os.path.basename(path) name = os.path.splitext(basename)[0] # at least two places, but same length for all images number_pattern = "%%0%dd" % (max(2, len(images) - 1)) for i, image in enumerate(images): # get a appropriate file extension or use fallback extensions = image.extensions ext = extensions[0] if extensions else ".image" if options.primary: # mysong.mp3 -> mysong.jpeg filename = "%s.%s" % (name, ext) else: # mysong.mp3 -> mysong-00.jpeg pattern = "%s-" + number_pattern + ".%s" filename = pattern % (name, i, ext) if options.destination is not None: filename = os.path.join(options.destination, filename) self.log("Saving image %r" % filename) if not options.dry_run: with open(filename, "wb") as h: shutil.copyfileobj(image.file, h) # @Command.register class RenameCommand(Command): NAME = "rename" DESCRIPTION = _("Rename files based on tags") USAGE = "[--dry-run] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help="show changes, don't apply them") def _execute(self, options, args): if len(args) < 1: raise CommandError("Not enough arguments") @Command.register class FillCommand(Command): NAME = "fill" DESCRIPTION = _("Fill tags based on the file path") USAGE = "[--dry-run] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help="show changes, don't apply them") def _execute(self, options, args): if len(args) < 2: raise CommandError("Not enough arguments") pattern_text = args[0] self.log("Using pattern: %r" % pattern_text) paths = args[1:] pattern = TagsFromPattern(pattern_text) songs = [] for path in paths: song = self.load_song(path) for header in pattern.headers: if not song.can_change(header): raise CommandError(_("Can not set %r") % header) songs.append(song) if options.dry_run: self.__preview(pattern, songs) else: self.__apply(pattern, songs) def __apply(self, pattern, songs): for song in songs: match = pattern.match(song) self.log("%r: %r" % (song("~basename"), match)) for header in pattern.headers: if header in match: value = match[header] song[header] = value self.save_songs(songs) def __preview(self, pattern, songs): rows = [] for song in songs: match = pattern.match(song) row = [fsn2text(song("~basename"))] for header in pattern.headers: row.append(match.get(header, u"")) rows.append(row) headers = [_("File")] + pattern.headers nicks = ["file"] + pattern.headers print_table(rows, headers, nicks, nicks) # @Command.register class FillTracknumberCommand(Command): NAME = "fill-tracknumber" DESCRIPTION = _("Fill tracknumbers for all files") USAGE = "[--dry-run] [--start] [--total] []" def _add_options(self, p): p.add_option("--dry-run", action="store_true", help="show changes, don't apply them") p.add_option("--start", action="store_true", help="tracknumber to start with") p.add_option("--total", action="store_true", help="total number of tracks") def _execute(self, options, args): if len(args) < 1: raise CommandError("Not enough arguments") @Command.register class PrintCommand(Command): NAME = "print" DESCRIPTION = _("Print tags based on the given pattern") USAGE = "[-p ] []" def _add_options(self, p): p.add_option("-p", "--pattern", action="store", type="string", help="use a custom pattern") def _execute(self, options, args): if len(args) < 1: raise CommandError("Not enough arguments") pattern = options.pattern if pattern is None: pattern = "" self.log("Using pattern: %r" % pattern) try: pattern = Pattern(pattern) except PatternError: raise CommandError("Invalid pattern: %r" % pattern) paths = args error = False for path in paths: try: util.print_(pattern % self.load_song(path)) except CommandError: error = True if error: raise CommandError("One or more files failed to load.") @Command.register class HelpCommand(Command): NAME = "help" DESCRIPTION = _("Display help information") USAGE = "[]" def _execute(self, options, args): if len(args) > 1: raise CommandError("Too many arguments") for cmd in Command.COMMANDS: if cmd.NAME == args[0]: cmd(self._main_cmd).print_help() break else: raise CommandError("Unknown command") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658440183.0 quodlibet-4.6.0/quodlibet/operon/main.py0000644000175000017500000000624414266344767017024 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys import os from optparse import OptionParser import quodlibet from quodlibet import const from quodlibet.util.dprint import print_ from .base import Command, CommandError from . import commands commands def _print_help(main_cmd, parser, file=None): """Print a short help list for all commands""" if file is None: file = sys.stdout parser.print_help(file=file) cl = ["", "Commands:"] for command in Command.COMMANDS: cl.append(" %-17s %s" % (command.NAME, command.DESCRIPTION)) cl.append("") cl.append("See '%s help ' for more information " "on a specific command." % main_cmd) print_("\n".join(cl), file=file) def main(argv=None): if argv is None: argv = sys.argv quodlibet.init_cli() main_cmd = os.path.basename(argv[0]) # the main optparser usage = "%s [--version] [--help] [--verbose] []" % main_cmd parser = OptionParser(usage=usage) parser.remove_option("--help") parser.add_option("-h", "--help", action="store_true") parser.add_option("--version", action="store_true", help="print version") parser.add_option("-v", "--verbose", action="store_true", help="verbose output") # no args, print help (might change in the future) if len(argv) <= 1: _print_help(main_cmd, parser, file=sys.stderr) return 1 # collect options for the main command and get the command offset offset = -1 pre_command = [] for i, a in enumerate(argv): if i == 0: continue elif a.startswith("-"): pre_command.append(a) else: offset = i break # parse the global options options = parser.parse_args(pre_command)[0] # --help somewhere if options.help: _print_help(main_cmd, parser) return 0 # --version somewhere if options.version: print_("%s version %s" % (main_cmd, const.VERSION)) return 0 # no sub command followed, help to stderr if offset == -1: _print_help(main_cmd, parser, file=sys.stderr) return 1 arg = argv[offset] # special case help and list all commands if arg == "help": # no command, list all commands if len(argv) == 2: _print_help(main_cmd, parser) return 0 # get the right sub command and pass the remaining args for command in Command.COMMANDS: if command.NAME == arg: cmd = command(main_cmd, options) try: cmd.execute(argv[offset + 1:]) except CommandError as e: print_(u"%s: %s" % (command.NAME, e), file=sys.stderr) return 1 break else: print_(u"Unknown command '%s'. See '%s help'." % (arg, main_cmd), file=sys.stderr) return 1 return 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658440183.0 quodlibet-4.6.0/quodlibet/operon/util.py0000644000175000017500000000764414266344767017062 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import stat import shlex import shutil from quodlibet import _ from quodlibet.util.tags import MACHINE_TAGS, sortkey from quodlibet.util.dprint import print_, Colorise from quodlibet import util from .base import CommandError def copy_mtime(src, dst): """Copy mtime/atime from src to dst. Might raise OSError.""" stat_src = os.stat(src) os.utime(dst, (stat_src[stat.ST_ATIME], stat_src[stat.ST_MTIME])) def filter_table(rows, nicks, order): """Returns a new table with rows filtered and reordered""" if nicks == order: return rows mapping = [] lower = [h.lower() for h in nicks] for o in order: try: index = lower.index(o.lower()) except ValueError: raise CommandError( _("'%(column-id)s' is not a valid column " "name (%(all-column-ids)s).") % { "column-id": o, "all-column-ids": ", ".join(nicks), }) else: mapping.append(index) if not mapping: return [] new_rows = [] for row in rows: new_rows.append([row[i] for i in mapping]) return new_rows def print_table(rows, headers, nicks, order): """Print a fancy table""" rows.insert(0, headers) rows = filter_table(rows, nicks, order) if not rows: return widths = [] for c in range(len(rows[0])): widths.append(max(map(lambda r: len(r[c]), rows))) seperator = " %s " % Colorise.gray("|") format_string = seperator.join(["%%-%ds" % w for w in widths]) header = [] for i, h in enumerate(rows.pop(0)): header.append(h.ljust(widths[i], " ")) line_width = len(" ".join(header)) + 2 header = [Colorise.bold(h) for h in header] header_line = " " + (" %s " % Colorise.gray("|")).join(header) print_(header_line.rstrip()) print_(Colorise.gray("-" * line_width)) for row in rows: print_(" " + (format_string % tuple(row)).rstrip()) def print_terse_table(rows, nicks, order): """Print a terse table""" for row in filter_table(rows, nicks, order): row = [r.replace("\\", "\\\\") for r in row] row = [r.replace(":", r"\:") for r in row] print_(":".join(row)) def list_tags(song, machine=False, terse=False): """Return a list of key, value pairs""" keys = set(song.realkeys()) if not machine: keys.difference_update(MACHINE_TAGS) tags = [] for key in sorted(keys, key=sortkey): for value in song.list(key): if not terse: # QL can't handle multiline values and splits them by \n. # Tags with Windows line endings leave a \r, messing up the # table layout value = value.rstrip("\r") # Normalize tab value = value.replace("\t", " ") tags.append((util.tag(key), value, key)) return tags def get_editor_args(fallback_command="nano"): """Returns a list starting with a command and optional arguments for editing text files. List is never empty. Can't fail, but the result might not be a valid/existing command. """ if "VISUAL" in os.environ: editor = os.environ["VISUAL"] elif "EDITOR" in os.environ: editor = os.environ["EDITOR"] elif shutil.which("editor"): editor = "editor" else: editor = fallback_command # to support VISUAL="geany -i" try: editor_args = shlex.split(editor) except ValueError: # well, no idea editor_args = [editor] if not editor_args: editor_args = [fallback_command] return editor_args ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/order/0000755000175000017500000000000014471213412015305 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1675520037.0 quodlibet-4.6.0/quodlibet/order/__init__.py0000644000175000017500000001304314367464045017435 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2016-17 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Any, Dict, List, Optional from gi.repository import Gtk from quodlibet import _, print_d class Order: """Base class for all play orders In all methods: `playlist` is a GTK+ `ListStore` containing at least an `AudioFile` as the first element in each row (in the future there may be more elements per row). `iter` is a `GtkTreeIter` for the song that just finished, if any. If the song is not in the list, this iter will be `None`. """ name: Optional[str] = "unknown_order" """The name by which this order is known""" display_name = _("Unknown") """The (translated) display name""" accelerated_name = _("_Unknown") """The (translated) display name with (optional) accelerators""" replaygain_profiles = ["track"] """The ReplayGain mode(s) to use with this order. Shuffled ones typically prefer track modes""" priority = 100 """The priority relative to other orders of its type. Larger numbers typically appear lower in lists.""" def __init__(self): """Must have a zero-arg constructor""" pass def next(self, playlist, iter): """Not called directly, but the default implementation of `next_explicit` and `next_implicit` both just call this. """ raise NotImplementedError def previous(self, playlist, iter): """Not called directly, but the default implementation of `previous_explicit` calls this. Right now there is no such thing as `previous_implicit`.""" raise NotImplementedError def set(self, playlist, iter): """Not called directly, but the default implementations of `set_explicit` and `set_implicit` call this. """ return iter def next_explicit(self, playlist, iter): """Not called directly, but the default implementations of `set_explicit` and `set_implicit` call this.""" return self.next(playlist, iter) def next_implicit(self, playlist, iter): """Called when a song ends passively, e.g. it plays through.""" return self.next(playlist, iter) def previous_explicit(self, playlist, iter): """Called when the user presses a "Previous" button.""" return self.previous(playlist, iter) def set_explicit(self, playlist, iter): """Called when the user manually selects a song (at `iter`). If desired the play order can override that, or just log it and return the iter again. Note that playlist.current_iter is the current iter, if any. If the play order returns `None`, no action will be taken by the player. """ return self.set(playlist, iter) def set_implicit(self, playlist, iter): """Called when the song is set by a means other than the UI.""" return self.set(playlist, iter) def reset(self, playlist): """Called when there is no song ready to prepare for a new order. Implementations should reset the state of the current order, e.g. forgetting history / clearing pre-cached orders.""" pass def __str__(self): """By default there is no interesting state""" return "<%s>" % self.display_name class OrderRemembered(Order): """Shared class for all the shuffle modes that keep a memory of their previously played songs.""" _played: List[Gtk.TreeIter] def __init__(self): super().__init__() self._played = [] def next(self, playlist, iter): if iter is not None: self._played.append(iter) def previous(self, playlist, iter): if self._played: return self._played.pop() return None def set(self, playlist, iter): if iter is not None: self._played.append(iter) return iter def reset(self, playlist): del(self._played[:]) def remaining(self, playlist) -> Dict[int, Any]: """Gets a map of all song indices to their song from the `playlist` that haven't yet been played""" def get_index(iter): return playlist.get_path(iter).get_indices()[0] played = set(map(get_index, self._played)) print_d("Played %d of %d song(s)" % (len(self._played), len(playlist))) remaining = ( (get_index(iter), value) for iter, value in playlist.iterrows()) return { index: song for (index, song) in remaining if index not in played} class OrderInOrder(Order): """Keep to the order of the supplied playlist""" name: Optional[str] = "in_order" display_name = _("In Order") accelerated_name = _("_In Order") replaygain_profiles = ["album", "track"] priority = 0 def next(self, playlist, iter): if iter is None: return playlist.get_iter_first() else: return playlist.iter_next(iter) def previous(self, playlist, iter): if len(playlist) == 0: return None elif iter is None: return playlist[(len(playlist) - 1,)].iter else: path = max(1, playlist.get_path(iter).get_indices()[0]) try: return playlist.get_iter((path - 1,)) except ValueError: return None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1675520037.0 quodlibet-4.6.0/quodlibet/order/reorder.py0000644000175000017500000000357514367464045017351 0ustar00nicknick# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import random from quodlibet import _ from quodlibet.order import Order, OrderRemembered class Reorder(Order): """Base class for all `Order`s that potentially reorder the playlist, and thus usually identify as a "shuffle" implementation.""" pass class OrderShuffle(Reorder, OrderRemembered): name = "random" display_name = _("Random") accelerated_name = _("_Random") def next(self, playlist, iter): super().next(playlist, iter) remaining = self.remaining(playlist) if not remaining: self.reset(playlist) return None index = random.choice(list(remaining)) return playlist.get_iter((index,)) class OrderWeighted(Reorder, OrderRemembered): name = "weighted" display_name = _("Prefer higher rated") accelerated_name = _("Prefer _higher rated") def next(self, playlist, iter): super().next(playlist, iter) remaining = self.remaining(playlist) # Don't try to search through an empty / played playlist. if not remaining: self.reset(playlist) return None total_score = sum([song('~#rating') for song in remaining.values()]) if total_score == 0: # When all songs are rated zero, fall back to unweighted shuffle return playlist.get_iter((random.choice(list(remaining)),)) choice = random.random() * total_score current = 0.0 for i, song in remaining.items(): current += song("~#rating") if current >= choice: return playlist.get_iter([i]) raise ValueError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/order/repeat.py0000664000175000017500000000421114231604332017136 0ustar00nicknick# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import print_d from quodlibet.order import Order class Repeat(Order): """Repeat, in some way, over a supplied `Order`""" def __init__(self, wrapped): super().__init__() assert isinstance(wrapped, Order) self.wrapped = wrapped def next(self, playlist, iter): raise NotImplementedError def set(self, playlist, iter): return self.wrapped.set(playlist, iter) def previous(self, playlist, iter): return self.wrapped.previous(playlist, iter) def reset(self, playlist): return self.wrapped.reset(playlist) def __str__(self): return "<%s ∘ %s>" % (self.display_name, self.wrapped.display_name) class RepeatSongForever(Repeat): """Repeats the same song forever (aka "repeat one"). Explicit next calls will "break out" of the repeat which is probably what the user wanted""" name = "repeat_song" display_name = _("Repeat this track") accelerated_name = _("Repeat _this track") def next(self, playlist, iter): return iter def next_explicit(self, playlist, iter): return self.wrapped.next_explicit(playlist, iter) class RepeatListForever(Repeat): """Repeats the playlist forever once it's finished""" name = "repeat_all" display_name = _("Repeat all") accelerated_name = _("Repeat _all") def next(self, playlist, iter): next = self.wrapped.next(playlist, iter) if next: return next self.wrapped.reset(playlist) print_d("Restarting songlist") return playlist.get_iter_first() class OneSong(Repeat): """Stops after the current song""" name = "one_song" display_name = _("One song") accelerated_name = _("One _song") priority = 400 def next(self, playlist, iter): print_d("Ending songlist.") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/0000755000175000017500000000000014471213412015750 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/README.rst0000664000175000017500000000036114035600052017435 0ustar00nicknickDon't change anything here as these are just copies of upstream releases. senf: PYPI: https://pypi.python.org/pypi/senf License: "MIT License" raven: PYPI: https://pypi.python.org/pypi/raven License: "BSD 3-Clause License" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/__init__.py0000664000175000017500000000046414035600052020063 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/raven/0000755000175000017500000000000014471213412017063 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/__init__.py0000664000175000017500000000232514035600052021174 0ustar00nicknick""" raven ~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import os import os.path __all__ = ('VERSION', 'Client', 'get_version') VERSION = '6.5.0' def _get_git_revision(path): revision_file = os.path.join(path, 'refs', 'heads', 'master') if os.path.exists(revision_file): with open(revision_file) as fh: return fh.read().strip()[:7] def get_revision(): """ :returns: Revision number of this branch/checkout, if available. None if no revision number can be determined. """ package_dir = os.path.dirname(__file__) checkout_dir = os.path.normpath(os.path.join(package_dir, os.pardir, os.pardir)) path = os.path.join(checkout_dir, '.git') if os.path.exists(path): return _get_git_revision(path) def get_version(): base = VERSION if __build__: base = '%s (%s)' % (base, __build__) return base __build__ = get_revision() __docformat__ = 'restructuredtext en' # Declare child imports last to prevent recursion from raven.base import * # NOQA from raven.conf import * # NOQA from raven.versioning import * # NOQA ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1661888861.0 quodlibet-4.6.0/quodlibet/packages/raven/base.py0000644000175000017500000007211314303464535020363 0ustar00nicknick""" raven.base ~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import zlib import logging import os import sys import time import uuid import warnings from datetime import datetime from inspect import isclass from random import Random from types import FunctionType from threading import local if sys.version_info >= (3, 2): import contextlib else: import contextlib2 as contextlib try: from thread import get_ident as get_thread_ident except ImportError: from _thread import get_ident as get_thread_ident import raven from raven.conf import defaults from raven.conf.remote import RemoteConfig from raven.exceptions import APIError, RateLimited from raven.utils import json, get_versions, get_auth_header, merge_dicts from raven.utils.compat import text_type, iteritems from raven.utils.encoding import to_unicode from raven.utils.serializer import transform from raven.utils.stacks import get_stack_info, iter_stack_frames from raven.utils.transaction import TransactionStack from raven.transport.registry import TransportRegistry, default_transports # enforce imports to avoid obscure stacktraces with MemoryError import raven.events # NOQA __all__ = ('Client',) __excepthook__ = None PLATFORM_NAME = 'python' SDK_VALUE = { 'name': 'raven-python', 'version': raven.VERSION, } # singleton for the client Raven = None if sys.version_info >= (3, 2): basestring = str def get_excepthook_client(): return getattr(sys.excepthook, 'raven_client', None) class ModuleProxyCache(dict): def __missing__(self, key): module, class_name = key.rsplit('.', 1) handler = getattr(__import__( module, {}, {}, [class_name]), class_name) self[key] = handler return handler class ClientState: ONLINE = 1 ERROR = 0 def __init__(self): self.status = self.ONLINE self.last_check = None self.retry_number = 0 self.retry_after = 0 def should_try(self): if self.status == self.ONLINE: return True interval = self.retry_after or min(self.retry_number, 6) ** 2 if time.time() - self.last_check > interval: return True return False def set_fail(self, retry_after=0): self.status = self.ERROR self.retry_number += 1 self.last_check = time.time() self.retry_after = retry_after def set_success(self): self.status = self.ONLINE self.last_check = None self.retry_number = 0 self.retry_after = 0 def did_fail(self): return self.status == self.ERROR class Client: """ The base Raven client. Will read default configuration from the environment variable ``SENTRY_DSN`` if available. >>> from raven import Client >>> # Read configuration from ``os.environ['SENTRY_DSN']`` >>> client = Client() >>> # Specify a DSN explicitly >>> client = Client(dsn='https://public_key:secret_key@sentry.local/project_id') >>> # Record an exception >>> try: >>> 1/0 >>> except ZeroDivisionError: >>> ident = client.get_ident(client.captureException()) >>> print "Exception caught; reference is %s" % ident """ logger = logging.getLogger('raven') protocol_version = '6' _registry = TransportRegistry(transports=default_transports) def __init__(self, dsn=None, raise_send_errors=False, transport=None, install_sys_hook=True, install_logging_hook=True, hook_libraries=None, enable_breadcrumbs=True, _random_seed=None, **options): global Raven o = options self._local_state = local() self.raise_send_errors = raise_send_errors # configure loggers first cls = self.__class__ self.state = ClientState() self.logger = logging.getLogger( '%s.%s' % (cls.__module__, cls.__name__)) self.error_logger = logging.getLogger('sentry.errors') self.uncaught_logger = logging.getLogger('sentry.errors.uncaught') self._transport_cache = {} self.set_dsn(dsn, transport) self.include_paths = set(o.get('include_paths') or []) self.exclude_paths = set(o.get('exclude_paths') or []) self.name = text_type(o.get('name') or o.get('machine') or defaults.NAME) self.auto_log_stacks = bool( o.get('auto_log_stacks') or defaults.AUTO_LOG_STACKS) self.capture_locals = bool( o.get('capture_locals', defaults.CAPTURE_LOCALS)) self.string_max_length = int( o.get('string_max_length') or defaults.MAX_LENGTH_STRING) self.list_max_length = int( o.get('list_max_length') or defaults.MAX_LENGTH_LIST) self.site = o.get('site') self.include_versions = o.get('include_versions', True) self.processors = o.get('processors') self.sanitize_keys = o.get('sanitize_keys') if self.processors is None: self.processors = defaults.PROCESSORS context = o.get('context') if context is None: context = {'sys.argv': getattr(sys, 'argv', [])[:]} self.extra = context self.tags = o.get('tags') or {} self.environment = o.get('environment') or None self.release = o.get('release') or os.environ.get('HEROKU_SLUG_COMMIT') self.repos = self._format_repos(o.get('repos')) self.sample_rate = ( o.get('sample_rate') if o.get('sample_rate') is not None else 1 ) self.transaction = TransactionStack() self.ignore_exceptions = set(o.get('ignore_exceptions') or ()) self.module_cache = ModuleProxyCache() self._random = Random(_random_seed) if not self.is_enabled(): self.logger.info( 'Raven is not configured (logging is disabled). Please see the' ' documentation for more information.') if Raven is None: Raven = self # We want to remember the creating thread id here because this # comes in useful for the context special handling self.main_thread_id = get_thread_ident() self.enable_breadcrumbs = enable_breadcrumbs from raven.context import Context self._context = Context(self) if install_sys_hook: self.install_sys_hook() if install_logging_hook: self.install_logging_hook() self.hook_libraries(hook_libraries) def _format_repos(self, value): result = {} if value: for path, config in iteritems(value): if path[0] != '/': # assume its a module path = os.path.abspath(__import__(path).__file__) result[path] = config return result def set_dsn(self, dsn=None, transport=None): if not dsn and os.environ.get('SENTRY_DSN'): msg = "Configuring Raven from environment variable 'SENTRY_DSN'" self.logger.debug(msg) dsn = os.environ['SENTRY_DSN'] if dsn not in self._transport_cache: if not dsn: result = RemoteConfig(transport=transport) else: result = RemoteConfig.from_string( dsn, transport=transport, transport_registry=self._registry, ) self._transport_cache[dsn] = result self.remote = result else: self.remote = self._transport_cache[dsn] self.logger.debug("Configuring Raven for host: {0}".format(self.remote)) def install_sys_hook(self): global __excepthook__ if __excepthook__ is None: __excepthook__ = sys.excepthook def handle_exception(*exc_info): self.captureException(exc_info=exc_info, level='fatal') __excepthook__(*exc_info) handle_exception.raven_client = self sys.excepthook = handle_exception def install_logging_hook(self): from raven.breadcrumbs import install_logging_hook install_logging_hook() def hook_libraries(self, libraries): from raven.breadcrumbs import hook_libraries hook_libraries(libraries) @classmethod def register_scheme(cls, scheme, transport_class): cls._registry.register_scheme(scheme, transport_class) def get_processors(self): for processor in self.processors: yield self.module_cache[processor](self) def get_module_versions(self): if not self.include_versions: return {} version_info = sys.version_info modules = get_versions(self.include_paths) modules['python'] = '{0}.{1}.{2}'.format( version_info[0], version_info[1], version_info[2], ) return modules def get_ident(self, result): """ Returns a searchable string representing a message. >>> result = client.capture(**kwargs) >>> ident = client.get_ident(result) """ warnings.warn('Client.get_ident is deprecated. The event ID is now ' 'returned as the result of capture.', DeprecationWarning) return result def get_handler(self, name): return self.module_cache[name](self) def get_public_dsn(self, scheme=None): """ Returns a public DSN which is consumable by raven-js >>> # Return scheme-less DSN >>> print client.get_public_dsn() >>> # Specify a scheme to use (http or https) >>> print client.get_public_dsn('https') """ if self.is_enabled(): url = self.remote.get_public_dsn() if scheme: return '%s:%s' % (scheme, url) return url def _get_exception_key(self, exc_info): # On certain celery versions the tb_frame attribute might # not exist or be `None`. code_id = last_id = 0 try: code_id = id(exc_info[2] and exc_info[2].tb_frame.f_code) last_id = exc_info[2] and exc_info[2].tb_lasti or 0 except (AttributeError, IndexError): pass return ( exc_info[0], id(exc_info[1]), code_id, id(exc_info[2]), last_id, ) def skip_error_for_logging(self, exc_info): key = self._get_exception_key(exc_info) return key in self.context.exceptions_to_skip def record_exception_seen(self, exc_info): key = self._get_exception_key(exc_info) self.context.exceptions_to_skip.add(key) def build_msg(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, public_key=None, tags=None, fingerprint=None, **kwargs): """ Captures, processes and serializes an event into a dict object The result of ``build_msg`` should be a standardized dict, with all default values available. """ # create ID client-side so that it can be passed to application event_id = uuid.uuid4().hex data = merge_dicts(self.context.data, data) data.setdefault('tags', {}) data.setdefault('extra', {}) if '.' not in event_type: # Assume it's a builtin event_type = 'raven.events.%s' % event_type handler = self.get_handler(event_type) result = handler.capture(**kwargs) # data (explicit) culprit takes over auto event detection culprit = result.pop('culprit', None) if data.get('culprit'): culprit = data['culprit'] for k, v in iteritems(result): if k not in data: data[k] = v # auto_log_stacks only applies to events that are not exceptions # due to confusion about which stack is which and the automatic # application of stacktrace to exception objects by Sentry if stack is None and 'exception' not in data: stack = self.auto_log_stacks if stack and 'stacktrace' not in data: if stack is True: frames = iter_stack_frames() else: frames = stack stack_info = get_stack_info( frames, transformer=self.transform, capture_locals=self.capture_locals, ) data.update({ 'stacktrace': stack_info, }) if self.include_paths: for frame in self._iter_frames(data): if frame.get('in_app') is not None: continue path = frame.get('module') if not path: continue if path.startswith('raven.'): frame['in_app'] = False else: frame['in_app'] = ( any(path.startswith(x) for x in self.include_paths) and not any(path.startswith(x) for x in self.exclude_paths) ) if not culprit: culprit = self.transaction.peek() if not data.get('level'): data['level'] = kwargs.get('level') or logging.ERROR if not data.get('server_name'): data['server_name'] = self.name if not data.get('modules'): data['modules'] = self.get_module_versions() if self.release is not None: data['release'] = self.release if self.environment is not None: data['environment'] = self.environment data['tags'] = merge_dicts(self.tags, data['tags'], tags) data['extra'] = merge_dicts(self.extra, data['extra'], extra) # Legacy support for site attribute site = data.pop('site', None) or self.site if site: data['tags'].setdefault('site', site) if culprit: data['culprit'] = culprit if fingerprint: data['fingerprint'] = fingerprint # Run the data through processors for processor in self.get_processors(): data.update(processor.process(data)) if 'message' not in data: data['message'] = kwargs.get('message', handler.to_string(data)) # tags should only be key=>u'value' for key, value in iteritems(data['tags']): data['tags'][key] = to_unicode(value) # extra data can be any arbitrary value for k, v in iteritems(data['extra']): data['extra'][k] = self.transform(v) # It's important date is added **after** we serialize data.setdefault('project', self.remote.project) data.setdefault('timestamp', date or datetime.utcnow()) data.setdefault('time_spent', time_spent) data.setdefault('event_id', event_id) data.setdefault('platform', PLATFORM_NAME) data.setdefault('sdk', SDK_VALUE) data.setdefault('repos', self.repos) # insert breadcrumbs if self.enable_breadcrumbs: crumbs = self.context.breadcrumbs.get_buffer() if crumbs: # Make sure we send the crumbs here as "values" as we use the # raven client internally in sentry and the alternative # submission option of a list here is not supported by the # internal sender. data.setdefault('breadcrumbs', {'values': crumbs}) return data def transform(self, data): return transform( data, list_max_length=self.list_max_length, string_max_length=self.string_max_length) @property def context(self): """ Updates this clients thread-local context for future events. >>> def view_handler(view_func, *args, **kwargs): >>> client.context.merge(tags={'key': 'value'}) >>> try: >>> return view_func(*args, **kwargs) >>> finally: >>> client.context.clear() """ return self._context def user_context(self, data): """ Update the user context for future events. >>> client.user_context({'email': 'foo@example.com'}) """ return self.context.merge({ 'user': data, }) def http_context(self, data, **kwargs): """ Update the http context for future events. >>> client.http_context({'url': 'http://example.com'}) """ return self.context.merge({ 'request': data, }) def extra_context(self, data, **kwargs): """ Update the extra context for future events. >>> client.extra_context({'foo': 'bar'}) """ return self.context.merge({ 'extra': data, }) def tags_context(self, data, **kwargs): """ Update the tags context for future events. >>> client.tags_context({'version': '1.0'}) """ return self.context.merge({ 'tags': data, }) def capture(self, event_type, data=None, date=None, time_spent=None, extra=None, stack=None, tags=None, sample_rate=None, **kwargs): """ Captures and processes an event and pipes it off to SentryClient.send. To use structured data (interfaces) with capture: >>> capture('raven.events.Message', message='foo', data={ >>> 'request': { >>> 'url': '...', >>> 'data': {}, >>> 'query_string': '...', >>> 'method': 'POST', >>> }, >>> 'logger': 'logger.name', >>> }, extra={ >>> 'key': 'value', >>> }) The finalized ``data`` structure contains the following (some optional) builtin values: >>> { >>> # the culprit and version information >>> 'culprit': 'full.module.name', # or /arbitrary/path >>> >>> # all detectable installed modules >>> 'modules': { >>> 'full.module.name': 'version string', >>> }, >>> >>> # arbitrary data provided by user >>> 'extra': { >>> 'key': 'value', >>> } >>> } :param event_type: the module path to the Event class. Builtins can use shorthand class notation and exclude the full module path. :param data: the data base, useful for specifying structured data interfaces. Any key which contains a '.' will be assumed to be a data interface. :param date: the datetime of this event :param time_spent: a integer value representing the duration of the event (in milliseconds) :param extra: a dictionary of additional standard metadata :param stack: a stacktrace for the event :param tags: dict of extra tags :param sample_rate: a float in the range [0, 1] to sample this message :return: a tuple with a 32-length string identifying this event """ if not self.is_enabled(): return exc_info = kwargs.get('exc_info') if exc_info is not None: if self.skip_error_for_logging(exc_info): return elif not self.should_capture(exc_info): self.logger.info( 'Not capturing exception due to filters: %s', exc_info[0], exc_info=sys.exc_info()) return self.record_exception_seen(exc_info) data = self.build_msg( event_type, data, date, time_spent, extra, stack, tags=tags, **kwargs) # should this event be sampled? if sample_rate is None: sample_rate = self.sample_rate if self._random.random() < sample_rate: self.send(**data) self._local_state.last_event_id = data['event_id'] return data['event_id'] def is_enabled(self): """ Return a boolean describing whether the client should attempt to send events. """ return self.remote.is_active() def _iter_frames(self, data): if 'stacktrace' in data: for frame in data['stacktrace']['frames']: yield frame if 'exception' in data: for frame in data['exception']['values'][-1]['stacktrace'].get('frames', []): yield frame def _successful_send(self): self.state.set_success() def _failed_send(self, exc, url, data): retry_after = 0 if isinstance(exc, APIError): if isinstance(exc, RateLimited): retry_after = exc.retry_after self.error_logger.error( 'Sentry responded with an API error: %s(%s)', type(exc).__name__, exc.message) else: self.error_logger.error( 'Sentry responded with an error: %s (url: %s)', exc, url, exc_info=True, extra={'data': data} ) self._log_failed_submission(data) self.state.set_fail(retry_after=retry_after) def _log_failed_submission(self, data): """ Log a reasonable representation of an event that should have been sent to Sentry """ message = data.pop('message', '') output = [message] if 'exception' in data and 'stacktrace' in data['exception']['values'][-1]: # try to reconstruct a reasonable version of the exception for frame in data['exception']['values'][-1]['stacktrace'].get('frames', []): output.append(' File "%(fn)s", line %(lineno)s, in %(func)s' % { 'fn': frame.get('filename', 'unknown_filename'), 'lineno': frame.get('lineno', -1), 'func': frame.get('function', 'unknown_function'), }) self.uncaught_logger.error(output) def send_remote(self, url, data, headers=None): # If the client is configured to raise errors on sending, # the implication is that the backoff and retry strategies # will be handled by the calling application if headers is None: headers = {} if not self.raise_send_errors and not self.state.should_try(): data = self.decode(data) self._log_failed_submission(data) return self.logger.debug('Sending message of length %d to %s', len(data), url) def failed_send(e): self._failed_send(e, url, self.decode(data)) try: transport = self.remote.get_transport() if transport.is_async: transport.async_send(url, data, headers, self._successful_send, failed_send) else: transport.send(url, data, headers) self._successful_send() except Exception as e: if self.raise_send_errors: raise failed_send(e) def send(self, auth_header=None, **data): """ Serializes the message and passes the payload onto ``send_encoded``. """ message = self.encode(data) return self.send_encoded(message, auth_header=auth_header) def send_encoded(self, message, auth_header=None, **kwargs): """ Given an already serialized message, signs the message and passes the payload off to ``send_remote``. """ client_string = 'raven-python/%s' % (raven.VERSION,) if not auth_header: timestamp = time.time() auth_header = get_auth_header( protocol=self.protocol_version, timestamp=timestamp, client=client_string, api_key=self.remote.public_key, api_secret=self.remote.secret_key, ) headers = { 'User-Agent': client_string, 'X-Sentry-Auth': auth_header, 'Content-Encoding': self.get_content_encoding(), 'Content-Type': 'application/octet-stream', } return self.send_remote( url=self.remote.store_endpoint, data=message, headers=headers, **kwargs ) def get_content_encoding(self): return 'deflate' def encode(self, data): """ Serializes ``data`` into a raw string. """ return zlib.compress(json.dumps(data).encode('utf8')) def decode(self, data): """ Unserializes a string, ``data``. """ return json.loads(zlib.decompress(data).decode('utf8')) def captureMessage(self, message, **kwargs): """ Creates an event from ``message``. >>> client.captureMessage('My event just happened!') """ return self.capture('raven.events.Message', message=message, **kwargs) def captureException(self, exc_info=None, **kwargs): """ Creates an event from an exception. >>> try: >>> exc_info = sys.exc_info() >>> client.captureException(exc_info) >>> finally: >>> del exc_info If exc_info is not provided, or is set to True, then this method will perform the ``exc_info = sys.exc_info()`` and the requisite clean-up for you. ``kwargs`` are passed through to ``.capture``. """ if exc_info is None or exc_info is True: exc_info = sys.exc_info() return self.capture( 'raven.events.Exception', exc_info=exc_info, **kwargs) def should_capture(self, exc_info): exc_type = exc_info[0] exc_name = '%s.%s' % (exc_type.__module__, exc_type.__name__) exclusions = self.ignore_exceptions string_exclusions = (e for e in exclusions if isinstance(e, basestring)) wildcard_exclusions = (e for e in string_exclusions if e.endswith('*')) class_exclusions = (e for e in exclusions if isclass(e)) if (exc_type in exclusions or exc_type.__name__ in exclusions or exc_name in exclusions or any(issubclass(exc_type, e) for e in class_exclusions) or any(exc_name.startswith(e[:-1]) for e in wildcard_exclusions)): return False return True def capture_exceptions(self, function_or_exceptions=None, **kwargs): """ Wrap a function or code block in try/except and automatically call ``.captureException`` if it raises an exception, then the exception is reraised. By default, it will capture ``Exception`` >>> @client.capture_exceptions >>> def foo(): >>> raise Exception() >>> with client.capture_exceptions(): >>> raise Exception() You can also specify exceptions to be caught specifically >>> @client.capture_exceptions((IOError, LookupError)) >>> def bar(): >>> ... >>> with client.capture_exceptions((IOError, LookupError)): >>> ... ``kwargs`` are passed through to ``.captureException``. """ function = None exceptions = (Exception,) if isinstance(function_or_exceptions, FunctionType): function = function_or_exceptions elif function_or_exceptions is not None: exceptions = function_or_exceptions # In python3.2 contextmanager acts both as contextmanager and decorator @contextlib.contextmanager def make_decorator(exceptions): try: yield except exceptions: self.captureException(**kwargs) raise decorator = make_decorator(exceptions) if function: return decorator(function) return decorator def captureQuery(self, query, params=(), engine=None, **kwargs): """ Creates an event for a SQL query. >>> client.captureQuery('SELECT * FROM foo') """ return self.capture( 'raven.events.Query', query=query, params=params, engine=engine, **kwargs) def captureExceptions(self, **kwargs): warnings.warn( 'captureExceptions is deprecated, used context() instead.', DeprecationWarning) return self.context(**kwargs) def captureBreadcrumb(self, *args, **kwargs): """ Records a breadcrumb with the current context. They will be sent with the next event. """ # Note: framework integration should not call this method but # instead use the raven.breadcrumbs.record_breadcrumb function # which will record to the correct client automatically. self.context.breadcrumbs.record(*args, **kwargs) capture_breadcrumb = captureBreadcrumb @property def last_event_id(self): return getattr(self._local_state, 'last_event_id', None) @last_event_id.setter def last_event_id(self, value): self._local_state.last_event_id = value class DummyClient(Client): """Sends messages into an empty void.""" def send(self, **kwargs): return None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/breadcrumbs.py0000664000175000017500000002656614035600052021743 0ustar00nicknickfrom __future__ import absolute_import import os import time import logging from types import FunctionType from raven.utils.compat import iteritems, get_code, text_type, string_types from raven.utils import once special_logging_handlers = [] special_logger_handlers = {} logger = logging.getLogger('raven') def event_payload_considered_equal(a, b): return ( a['type'] == b['type'] and a['level'] == b['level'] and a['message'] == b['message'] and a['category'] == b['category'] and a['data'] == b['data'] ) class BreadcrumbBuffer: def __init__(self, limit=100): self.buffer = [] self.limit = limit def record(self, timestamp=None, level=None, message=None, category=None, data=None, type=None, processor=None): if not (message or data or processor): raise ValueError('You must pass either `message`, `data`, ' 'or `processor`') if timestamp is None: timestamp = time.time() self.buffer.append(({ 'type': type or 'default', 'timestamp': timestamp, 'level': level, 'message': message, 'category': category, 'data': data, }, processor)) del self.buffer[:-self.limit] def clear(self): del self.buffer[:] def get_buffer(self): rv = [] for idx, (payload, processor) in enumerate(self.buffer): if processor is not None: try: processor(payload) except Exception: logger.exception('Failed to process breadcrumbs. Ignored') payload = None self.buffer[idx] = (payload, None) if payload is not None and \ (not rv or not event_payload_considered_equal(rv[-1], payload)): rv.append(payload) return rv class BlackholeBreadcrumbBuffer(BreadcrumbBuffer): def record(self, *args, **kwargs): pass def make_buffer(enabled=True): if enabled: return BreadcrumbBuffer() return BlackholeBreadcrumbBuffer() def record_breadcrumb(type, *args, **kwargs): # Legacy alias kwargs['type'] = type return record(*args, **kwargs) def record(message=None, timestamp=None, level=None, category=None, data=None, type=None, processor=None): """Records a breadcrumb for all active clients. This is what integration code should use rather than invoking the `captureBreadcrumb` method on a specific client. """ if timestamp is None: timestamp = time.time() for ctx in raven.context.get_active_contexts(): ctx.breadcrumbs.record(timestamp, level, message, category, data, type, processor) def _record_log_breadcrumb(logger, level, msg, *args, **kwargs): for handler in special_logging_handlers: if handler(logger, level, msg, args, kwargs): return handler = special_logger_handlers.get(logger.name) if handler is not None and handler(logger, level, msg, args, kwargs): return def processor(data): formatted_msg = msg # If people log bad things, this can happen. Then just don't do # anything. try: formatted_msg = text_type(msg) if args: formatted_msg = msg % args except Exception: pass # We do not want to include exc_info as argument because it often # lies (set to a constant value like 1 or True) or even if it's a # tuple it will not be particularly useful for us as we cannot # process it anyways. kwargs.pop('exc_info', None) data.update({ 'message': formatted_msg, 'category': logger.name, 'level': logging.getLevelName(level).lower(), 'data': kwargs, }) record(processor=processor) def _wrap_logging_method(meth, level=None): if not isinstance(meth, FunctionType): func = meth.im_func else: func = meth # We were patched for raven before if getattr(func, '__patched_for_raven__', False): return if level is None: args = ('level', 'msg') fwd = 'level, msg' else: args = ('msg',) fwd = '%d, msg' % level code = get_code(func) logging_srcfile = logging._srcfile if logging_srcfile is None: logging_srcfile = os.path.normpath( logging.currentframe.__code__.co_filename ) # This requires a bit of explanation why we're doing this. Due to how # logging itself works we need to pretend that the method actually was # created within the logging module. There are a few ways to detect # this and we fake all of them: we use the same function globals (the # one from the logging module), we create it entirely there which # means that also the filename is set correctly. This fools the # detection code in logging and it makes logging itself skip past our # code when determining the code location. # # Because we point the globals to the logging module we now need to # refer to our own functions (original and the crumb recording # function) through a closure instead of the global scope. # # We also add a lot of newlines in front of the code so that the # code location lines up again in case someone runs inspect.getsource # on the function. ns = {} eval(compile('''%(offset)sif 1: def factory(original, record_crumb): def %(name)s(self, %(args)s, *args, **kwargs): record_crumb(self, %(fwd)s, *args, **kwargs) return original(self, %(args)s, *args, **kwargs) return %(name)s \n''' % { 'offset': '\n' * (code.co_firstlineno - 3), 'name': func.__name__, 'args': ', '.join(args), 'fwd': fwd, 'level': level, }, logging_srcfile, 'exec'), logging.__dict__, ns) new_func = ns['factory'](meth, _record_log_breadcrumb) new_func.__doc__ = func.__doc__ assert code.co_firstlineno == get_code(func).co_firstlineno # In theory this should already be set correctly, but in some cases # it is not. So override it. new_func.__module__ == func.__module__ new_func.__name__ == func.__name__ new_func.__patched_for_raven__ = True return new_func def _patch_logger(): cls = logging.Logger methods = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'warn': logging.WARN, 'error': logging.ERROR, 'exception': logging.ERROR, 'critical': logging.CRITICAL, 'fatal': logging.FATAL } for method_name, level in iteritems(methods): new_func = _wrap_logging_method( getattr(cls, method_name), level) setattr(logging.Logger, method_name, new_func) logging.Logger.log = _wrap_logging_method( logging.Logger.log) @once def install_logging_hook(): """Installs the logging hook if it was not installed yet. Otherwise does nothing. """ _patch_logger() def ignore_logger(name_or_logger, allow_level=None): """Ignores a logger during breadcrumb recording. """ def handler(logger, level, msg, args, kwargs): if allow_level is not None and \ level >= allow_level: return False return True register_special_log_handler(name_or_logger, handler) def register_special_log_handler(name_or_logger, callback): """Registers a callback for log handling. The callback is invoked with given arguments: `logger`, `level`, `msg`, `args` and `kwargs` which are the values passed to the logging system. If the callback returns true value the default handling is disabled. Only one callback can be registered per one logger name. Logger tree is not traversed so calling this method with `spammy_module` argument will not silence messages from `spammy_module.child`. """ if isinstance(name_or_logger, string_types): name = name_or_logger else: name = name_or_logger.name special_logger_handlers[name] = callback def register_logging_handler(callback): """Registers a callback for log handling. The callback is invoked with given arguments: `logger`, `level`, `msg`, `args` and `kwargs` which are the values passed to the logging system. If the callback returns true value the default handling is disabled. Registering multiple handlers is allowed. """ special_logging_handlers.append(callback) hooked_libraries = {} def libraryhook(name): def decorator(f): f = once(f) hooked_libraries[name] = f return f return decorator @libraryhook('requests') def _hook_requests(): try: from requests.sessions import Session except ImportError: return real_send = Session.send def send(self, request, *args, **kwargs): def _record_request(response): record(type='http', category='requests', data={ 'url': request.url, 'method': request.method, 'status_code': response and response.status_code or None, 'reason': response and response.reason or None, }) try: resp = real_send(self, request, *args, **kwargs) except Exception: _record_request(None) raise else: _record_request(resp) return resp Session.send = send ignore_logger('requests.packages.urllib3.connectionpool', allow_level=logging.WARNING) @libraryhook('httplib') def _install_httplib(): try: from httplib import HTTPConnection except ImportError: from http.client import HTTPConnection real_putrequest = HTTPConnection.putrequest real_getresponse = HTTPConnection.getresponse def putrequest(self, method, url, *args, **kwargs): self._raven_status_dict = status = {} host = self.host port = self.port default_port = self.default_port def processor(data): real_url = url if not real_url.startswith(('http://', 'https://')): real_url = '%s://%s%s%s' % ( default_port == 443 and 'https' or 'http', host, port != default_port and ':%s' % port or '', url, ) data['data'] = { 'url': real_url, 'method': method, } data['data'].update(status) return data record(type='http', category='requests', processor=processor) return real_putrequest(self, method, url, *args, **kwargs) def getresponse(self, *args, **kwargs): rv = real_getresponse(self, *args, **kwargs) status = getattr(self, '_raven_status_dict', None) if status is not None and 'status_code' not in status: status['status_code'] = rv.status status['reason'] = rv.reason return rv HTTPConnection.putrequest = putrequest HTTPConnection.getresponse = getresponse def hook_libraries(libraries): if libraries is None: libraries = hooked_libraries.keys() for lib in libraries: func = hooked_libraries.get(lib) if func is None: raise RuntimeError('Unknown library %r for hooking' % lib) func() import raven.context ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/raven/conf/0000755000175000017500000000000014471213412020010 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/conf/__init__.py0000664000175000017500000000242614035600052022123 0ustar00nicknick""" raven.conf ~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import logging __all__ = ['setup_logging'] EXCLUDE_LOGGER_DEFAULTS = ( 'raven', 'gunicorn', 'south', 'sentry.errors', 'django.request', ) def setup_logging(handler, exclude=EXCLUDE_LOGGER_DEFAULTS): """ Configures logging to pipe to Sentry. - ``exclude`` is a list of loggers that shouldn't go to Sentry. For a typical Python install: >>> from raven.handlers.logging import SentryHandler >>> client = Sentry(...) >>> setup_logging(SentryHandler(client)) Within Django: >>> from raven.contrib.django.handlers import SentryHandler >>> setup_logging(SentryHandler()) Returns a boolean based on if logging was configured or not. """ logger = logging.getLogger() if handler.__class__ in map(type, logger.handlers): return False logger.addHandler(handler) # Add StreamHandler to sentry's default so you can catch missed exceptions for logger_name in exclude: logger = logging.getLogger(logger_name) logger.propagate = False logger.addHandler(logging.StreamHandler()) return True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/conf/defaults.py0000664000175000017500000000262414035600052022173 0ustar00nicknick""" raven.conf.defaults ~~~~~~~~~~~~~~~~~~~ Represents the default values for all Sentry settings. :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import os import os.path import socket ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), os.pardir)) TIMEOUT = 5 # TODO: this is specific to Django CLIENT = 'raven.contrib.django.DjangoClient' # Not all environments have access to socket module, for example Google App Engine # Need to check to see if the socket module has ``gethostname``, if it doesn't we # will set it to None and require it passed in to ``Client`` on initializtion. NAME = socket.gethostname() if hasattr(socket, 'gethostname') else None # The maximum number of elements to store for a list-like structure. MAX_LENGTH_LIST = 50 # The maximum length to store of a string-like structure. MAX_LENGTH_STRING = 400 # Automatically log frame stacks from all ``logging`` messages. AUTO_LOG_STACKS = False # Collect locals variables CAPTURE_LOCALS = True # Client-side data processors to apply PROCESSORS = ( 'raven.processors.SanitizePasswordsProcessor', ) try: # Try for certifi first since they likely keep their bundle more up to date import certifi CA_BUNDLE = certifi.where() except ImportError: CA_BUNDLE = os.path.join(ROOT, 'data', 'cacert.pem') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/conf/remote.py0000664000175000017500000001001214035600052021645 0ustar00nicknickfrom __future__ import absolute_import import logging import os import warnings from raven.utils.compat import PY2, text_type from raven.exceptions import InvalidDsn from raven.utils.encoding import to_string from raven.utils.urlparse import parse_qsl, urlparse ERR_UNKNOWN_SCHEME = 'Unsupported Sentry DSN scheme: {0} ({1})' logger = logging.getLogger('raven') def discover_default_transport(): from raven.transport.threaded import ThreadedHTTPTransport from raven.transport.http import HTTPTransport # Google App Engine # https://cloud.google.com/appengine/docs/python/how-requests-are-handled#Python_The_environment if 'CURRENT_VERSION_ID' in os.environ and 'INSTANCE_ID' in os.environ: logger.info('Detected environment to be Google App Engine. Using synchronous HTTP transport.') return HTTPTransport # AWS Lambda # https://alestic.com/2014/11/aws-lambda-environment/ if 'LAMBDA_TASK_ROOT' in os.environ: logger.info('Detected environment to be AWS Lambda. Using synchronous HTTP transport.') return HTTPTransport return ThreadedHTTPTransport DEFAULT_TRANSPORT = discover_default_transport() class RemoteConfig: def __init__(self, base_url=None, project=None, public_key=None, secret_key=None, transport=None, options=None): if base_url: base_url = base_url.rstrip('/') store_endpoint = '%s/api/%s/store/' % (base_url, project) else: store_endpoint = None self.base_url = base_url self.project = project self.public_key = public_key self.secret_key = secret_key self.options = options or {} self.store_endpoint = store_endpoint self._transport_cls = transport or DEFAULT_TRANSPORT def __unicode__(self): return text_type(self.base_url) def is_active(self): return all([self.base_url, self.project, self.public_key, self.secret_key]) def get_transport(self): if not self.store_endpoint: return if not hasattr(self, '_transport'): self._transport = self._transport_cls(**self.options) return self._transport def get_public_dsn(self): url = urlparse(self.base_url) netloc = url.hostname if url.port: netloc += ':%s' % url.port return '//%s@%s%s/%s' % (self.public_key, netloc, url.path, self.project) @classmethod def from_string(cls, value, transport=None, transport_registry=None): # in Python 2.x sending the DSN as a unicode value will eventually # cause issues in httplib if PY2: value = to_string(value) url = urlparse(value.strip()) if url.scheme not in ('http', 'https'): warnings.warn('Transport selection via DSN is deprecated. You should explicitly pass the transport class to Client() instead.') if transport is None: if not transport_registry: from raven.transport import TransportRegistry, default_transports transport_registry = TransportRegistry(default_transports) if not transport_registry.supported_scheme(url.scheme): raise InvalidDsn(ERR_UNKNOWN_SCHEME.format(url.scheme, value)) transport = transport_registry.get_transport_cls(url.scheme) netloc = url.hostname if url.port: netloc += ':%s' % url.port path_bits = url.path.rsplit('/', 1) if len(path_bits) > 1: path = path_bits[0] else: path = '' project = path_bits[-1] if not all([netloc, project, url.username, url.password]): raise InvalidDsn('Invalid Sentry DSN: %r' % url.geturl()) base_url = '%s://%s%s' % (url.scheme.rsplit('+', 1)[-1], netloc, path) return cls( base_url=base_url, project=project, public_key=url.username, secret_key=url.password, options=dict(parse_qsl(url.query)), transport=transport, ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/packages/raven/context.py0000664000175000017500000000737614231604332021137 0ustar00nicknick""" raven.context ~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import try: from collections import abc except ImportError: import collections as abc # type: ignore from threading import local from weakref import ref as weakref from raven.utils.compat import iteritems try: from thread import get_ident as get_thread_ident except ImportError: from _thread import get_ident as get_thread_ident _active_contexts = local() def get_active_contexts(): """Returns all the active contexts for the current thread.""" try: return list(_active_contexts.contexts) except AttributeError: return [] class Context(local, abc.Mapping, abc.Iterable): """ Stores context until cleared. >>> def view_handler(view_func, *args, **kwargs): >>> context = Context() >>> context.merge(tags={'key': 'value'}) >>> try: >>> return view_func(*args, **kwargs) >>> finally: >>> context.clear() """ def __init__(self, client=None): breadcrumbs = raven.breadcrumbs.make_buffer( client is None or client.enable_breadcrumbs) if client is not None: client = weakref(client) self._client = client # Because the thread auto activates the thread local this also # means that we auto activate this thing. Only if someone decides # to deactivate manually later another call to activate is # technically necessary. self.activate() self.data = {} self.exceptions_to_skip = set() self.breadcrumbs = breadcrumbs @property def client(self): if self._client is None: return None return self._client() def __hash__(self): return id(self) def __eq__(self, other): return self is other def __ne__(self, other): return not self.__eq__(other) def __getitem__(self, key): return self.data[key] def __iter__(self): return iter(self.data) def __len__(self): return len(self.data) def __repr__(self): return '<%s: %s>' % (type(self).__name__, self.data) def __enter__(self): self.activate() return self def __exit__(self, exc_type, exc_value, tb): self.deactivate() def activate(self, sticky=False): if sticky: self._sticky_thread = get_thread_ident() _active_contexts.__dict__.setdefault('contexts', set()).add(self) def deactivate(self): try: _active_contexts.contexts.discard(self) except AttributeError: pass def merge(self, data, activate=True): if activate: self.activate() d = self.data for key, value in iteritems(data): if key in ('tags', 'extra'): d.setdefault(key, {}) for t_key, t_value in iteritems(value): d[key][t_key] = t_value else: d[key] = value def set(self, data): self.data = data def get(self): return self.data def clear(self, deactivate=None): self.data = {} self.exceptions_to_skip.clear() self.breadcrumbs.clear() # If the caller did not specify if it wants to deactivate the # context for the thread we only deactivate it if we're not the # thread that created the context (main thread). if deactivate is None: client = self.client if client is not None: deactivate = get_thread_ident() != client.main_thread_id if deactivate: self.deactivate() import raven.breadcrumbs ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/events.py0000664000175000017500000001107114035600052020737 0ustar00nicknick""" raven.events ~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import logging import sys from raven.utils.encoding import to_unicode from raven.utils.stacks import get_stack_info, iter_traceback_frames __all__ = ('BaseEvent', 'Exception', 'Message', 'Query') class BaseEvent: def __init__(self, client): self.client = client self.logger = logging.getLogger(__name__) def to_string(self, data): raise NotImplementedError def capture(self, **kwargs): return { } def transform(self, value): return self.client.transform(value) # The __suppress_context__ attribute was added in Python 3.3. # See PEP 415 for details: # https://www.python.org/dev/peps/pep-0415/ if hasattr(Exception, '__suppress_context__'): def _chained_exceptions(exc_info): """ Return a generator iterator over an exception's chain. The exceptions are yielded from outermost to innermost (i.e. last to first when viewing a stack trace). """ yield exc_info exc_type, exc, exc_traceback = exc_info context = set() context.add(exc) while True: if exc.__suppress_context__: # Then __cause__ should be used instead. exc = exc.__cause__ else: exc = exc.__context__ if exc in context: break context.add(exc) if exc is None: break yield type(exc), exc, exc.__traceback__ else: # Then we do not support reporting exception chains. def _chained_exceptions(exc_info): yield exc_info class Exception(BaseEvent): """ Exceptions store the following metadata: - value: 'My exception value' - type: 'ClassName' - module '__builtin__' (i.e. __builtin__.TypeError) - frames: a list of serialized frames (see _get_traceback_frames) """ name = 'exception' def to_string(self, data): exc = data[self.name]['values'][-1] if exc['value']: return '%s: %s' % (exc['type'], exc['value']) return exc['type'] def _get_value(self, exc_type, exc_value, exc_traceback): """ Convert exception info to a value for the values list. """ stack_info = get_stack_info( iter_traceback_frames(exc_traceback), transformer=self.transform, capture_locals=self.client.capture_locals, ) exc_module = getattr(exc_type, '__module__', None) if exc_module: exc_module = str(exc_module) exc_type = getattr(exc_type, '__name__', '') return { 'value': to_unicode(exc_value), 'type': str(exc_type), 'module': to_unicode(exc_module), 'stacktrace': stack_info, } def capture(self, exc_info=None, **kwargs): if not exc_info or exc_info is True: exc_info = sys.exc_info() if not exc_info: raise ValueError('No exception found') values = [] for exc_info in _chained_exceptions(exc_info): value = self._get_value(*exc_info) values.insert(0, value) return { 'level': kwargs.get('level', logging.ERROR), self.name: {'values': values}, } class Message(BaseEvent): """ Messages store the following metadata: - message: 'My message from %s about %s' - params: ('foo', 'bar') """ name = 'sentry.interfaces.Message' def to_string(self, data): return data[self.name]['message'] def capture(self, message, params=(), formatted=None, **kwargs): message = to_unicode(message) data = { self.name: { 'message': message, 'params': self.transform(params), 'formatted': formatted, }, } if 'message' not in data: data['message'] = formatted or message return data class Query(BaseEvent): """ Messages store the following metadata: - query: 'SELECT * FROM table' - engine: 'postgesql_psycopg2' """ name = 'sentry.interfaces.Query' def to_string(self, data): sql = data[self.name] return sql['query'] def capture(self, query, engine, **kwargs): return { self.name: { 'query': to_unicode(query), 'engine': str(engine), } } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/exceptions.py0000664000175000017500000000113314035600052021612 0ustar00nicknickfrom __future__ import absolute_import from raven.utils.compat import text_type class APIError(Exception): def __init__(self, message, code=0): self.code = code self.message = message def __unicode__(self): return text_type("%s: %s" % (self.message, self.code)) class RateLimited(APIError): def __init__(self, message, retry_after=0): self.retry_after = retry_after super().__init__(message, 429) class InvalidGitRepository(Exception): pass class ConfigurationError(ValueError): pass class InvalidDsn(ConfigurationError): pass ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/raven/handlers/0000755000175000017500000000000014471213412020663 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/handlers/__init__.py0000664000175000017500000000030714035600052022772 0ustar00nicknick""" raven.handlers ~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/handlers/logbook.py0000664000175000017500000000635214035600052022675 0ustar00nicknick""" raven.handlers.logbook ~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from __future__ import print_function import logbook import sys import traceback from raven.utils.compat import string_types from raven.base import Client from raven.utils.encoding import to_string class SentryHandler(logbook.Handler): def __init__(self, *args, **kwargs): if len(args) == 1: arg = args[0] if isinstance(arg, string_types): self.client = kwargs.pop('client_cls', Client)(dsn=arg, **kwargs) elif isinstance(arg, Client): self.client = arg else: raise ValueError('The first argument to %s must be either a Client instance or a DSN, got %r instead.' % ( self.__class__.__name__, arg, )) args = [] else: try: self.client = kwargs.pop('client') except KeyError: raise TypeError('Expected keyword argument for SentryHandler: client') super().__init__(*args, **kwargs) def emit(self, record): try: # Avoid typical config issues by overriding loggers behavior if record.channel.startswith(('sentry.errors', 'raven')): print(to_string(self.format(record)), file=sys.stderr) return return self._emit(record) except Exception: if self.client.raise_send_errors: raise print("Top level Sentry exception caught - failed creating log record", file=sys.stderr) print(to_string(record.msg), file=sys.stderr) print(to_string(traceback.format_exc())) try: self.client.captureException() except Exception: pass def _emit(self, record): data = { 'level': logbook.get_level_name(record.level).lower(), 'logger': record.channel, } event_type = 'raven.events.Message' handler_kwargs = { 'message': record.msg, 'params': record.args, 'formatted': self.format(record), } if 'tags' in record.kwargs: handler_kwargs['tags'] = record.kwargs['tags'] # If there's no exception being processed, exc_info may be a 3-tuple of None # http://docs.python.org/library/sys.html#sys.exc_info if record.exc_info is True or (record.exc_info and all(record.exc_info)): handler = self.client.get_handler(event_type) data.update(handler.capture(**handler_kwargs)) event_type = 'raven.events.Exception' handler_kwargs['exc_info'] = record.exc_info extra = { 'lineno': record.lineno, 'filename': record.filename, 'function': record.func_name, 'process': record.process, 'process_name': record.process_name, } extra.update(record.extra) return self.client.capture(event_type, data=data, extra=extra, **handler_kwargs ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/packages/raven/handlers/logging.py0000664000175000017500000001366214231604332022674 0ustar00nicknick""" raven.handlers.logging ~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from __future__ import print_function import datetime import logging import sys import traceback from raven.utils.compat import string_types, iteritems, text_type from raven.base import Client from raven.utils.encoding import to_string from raven.utils.stacks import iter_stack_frames RESERVED = frozenset(( 'stack', 'name', 'module', 'funcName', 'args', 'msg', 'levelno', 'exc_text', 'exc_info', 'data', 'created', 'levelname', 'msecs', 'relativeCreated', 'tags', 'message', )) CONTEXTUAL = frozenset(( 'user', 'culprit', 'server_name', 'fingerprint' )) def extract_extra(record, reserved=RESERVED, contextual=CONTEXTUAL): data = {} extra = getattr(record, 'data', None) if not isinstance(extra, dict): if extra: extra = {'data': extra} else: extra = {} for k, v in iteritems(vars(record)): if k in reserved: continue if k.startswith('_'): continue if '.' not in k and k not in contextual: extra[k] = v else: data[k] = v return data, extra class SentryHandler(logging.Handler): def __init__(self, *args, **kwargs): client = kwargs.get('client_cls', Client) if len(args) == 1: arg = args[0] if isinstance(arg, string_types): self.client = client(dsn=arg, **kwargs) elif isinstance(arg, Client): self.client = arg else: raise ValueError('The first argument to %s must be either a ' 'Client instance or a DSN, got %r instead.' % (self.__class__.__name__, arg,)) elif 'client' in kwargs: self.client = kwargs['client'] else: self.client = client(*args, **kwargs) self.tags = kwargs.pop('tags', None) logging.Handler.__init__(self, level=kwargs.get('level', logging.NOTSET)) def can_record(self, record): return not ( record.name == 'raven' or record.name.startswith(('sentry.errors', 'raven.')) ) def emit(self, record): try: # Beware to python3 bug (see #10805) if exc_info is (None, None, None) self.format(record) if not self.can_record(record): print(to_string(record.message), file=sys.stderr) return return self._emit(record) except Exception: if self.client.raise_send_errors: raise print("Top level Sentry exception caught - failed " "creating log record", file=sys.stderr) print(to_string(record.msg), file=sys.stderr) print(to_string(traceback.format_exc()), file=sys.stderr) def _get_targetted_stack(self, stack, record): # we might need to traverse this multiple times, so coerce it to a list stack = list(stack) frames = [] started = False last_mod = '' for item in stack: if isinstance(item, (list, tuple)): frame, lineno = item else: frame, lineno = item, item.f_lineno if not started: f_globals = getattr(frame, 'f_globals', {}) module_name = f_globals.get('__name__', '') if ((last_mod and last_mod.startswith('logging')) and not module_name.startswith('logging')): started = True else: last_mod = module_name continue frames.append((frame, lineno)) # We failed to find a starting point if not frames: return stack return frames def _emit(self, record, **kwargs): data, extra = extract_extra(record) stack = getattr(record, 'stack', None) if stack is True: stack = iter_stack_frames() if stack: stack = self._get_targetted_stack(stack, record) date = datetime.datetime.utcfromtimestamp(record.created) event_type = 'raven.events.Message' handler_kwargs = { 'params': record.args, } try: handler_kwargs['message'] = text_type(record.msg) except UnicodeDecodeError: # Handle binary strings where it should be unicode... handler_kwargs['message'] = repr(record.msg)[1:-1] try: handler_kwargs['formatted'] = text_type(record.message) except UnicodeDecodeError: # Handle binary strings where it should be unicode... handler_kwargs['formatted'] = repr(record.message)[1:-1] # If there's no exception being processed, exc_info may be a 3-tuple of None # http://docs.python.org/library/sys.html#sys.exc_info if record.exc_info and all(record.exc_info): # capture the standard message first so that we ensure # the event is recorded as an exception, in addition to having our # message interface attached handler = self.client.get_handler(event_type) data.update(handler.capture(**handler_kwargs)) event_type = 'raven.events.Exception' handler_kwargs = {'exc_info': record.exc_info} data['level'] = record.levelno data['logger'] = record.name kwargs['tags'] = tags = {} if self.tags: tags.update(self.tags) tags.update(getattr(record, 'tags', {})) kwargs.update(handler_kwargs) sample_rate = extra.pop('sample_rate', None) return self.client.capture( event_type, stack=stack, data=data, extra=extra, date=date, sample_rate=sample_rate, **kwargs) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/middleware.py0000664000175000017500000000700214035600052021547 0ustar00nicknick""" raven.middleware ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from contextlib import contextmanager from raven.utils.compat import Iterator, next from raven.utils.wsgi import ( get_current_url, get_headers, get_environ) @contextmanager def common_exception_handling(environ, client): try: yield except (StopIteration, GeneratorExit): # Make sure we do this explicitly here. At least GeneratorExit # is handled implicitly by the rest of the logic but we want # to make sure this does not regress raise except Exception: client.handle_exception(environ) raise except KeyboardInterrupt: client.handle_exception(environ) raise except SystemExit as e: if e.code != 0: client.handle_exception(environ) raise class ClosingIterator(Iterator): """ An iterator that is implements a ``close`` method as-per WSGI recommendation. """ def __init__(self, sentry, iterable, environ): self.sentry = sentry self.environ = environ self._close = getattr(iterable, 'close', None) self.iterable = iter(iterable) self.closed = False def __iter__(self): return self def __next__(self): try: with common_exception_handling(self.environ, self.sentry): return next(self.iterable) except StopIteration: # We auto close here if we reach the end because some WSGI # middleware does not really like to close things. To avoid # massive leaks we just close automatically at the end of # iteration. self.close() raise def close(self): if self.closed: return try: if self._close is not None: with common_exception_handling(self.environ, self.sentry): self._close() finally: self.sentry.client.context.clear() self.sentry.client.transaction.clear() self.closed = True class Sentry: """ A WSGI middleware which will attempt to capture any uncaught exceptions and send them to Sentry. >>> from raven.base import Client >>> application = Sentry(application, Client()) """ def __init__(self, application, client=None): self.application = application if client is None: from raven.base import Client client = Client() self.client = client def __call__(self, environ, start_response): # TODO(dcramer): ideally this is lazy, but the context helpers must # support callbacks first self.client.http_context(self.get_http_context(environ)) with common_exception_handling(environ, self): iterable = self.application(environ, start_response) return ClosingIterator(self, iterable, environ) def get_http_context(self, environ): return { 'method': environ.get('REQUEST_METHOD'), 'url': get_current_url(environ, strip_querystring=True), 'query_string': environ.get('QUERY_STRING'), # TODO # 'data': environ.get('wsgi.input'), 'headers': dict(get_headers(environ)), 'env': dict(get_environ(environ)), } def handle_exception(self, environ=None): return self.client.captureException() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/processors.py0000664000175000017500000001234414035600052021641 0ustar00nicknick""" raven.core.processors ~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import re import warnings from raven.utils.compat import string_types, text_type, PY3 from raven.utils import varmap class Processor: def __init__(self, client): self.client = client def get_data(self, data, **kwargs): return def process(self, data, **kwargs): resp = self.get_data(data, **kwargs) if resp: data = resp if 'exception' in data: if 'values' in data['exception']: for value in data['exception'].get('values', []): if 'stacktrace' in value: self.filter_stacktrace(value['stacktrace']) if 'request' in data: self.filter_http(data['request']) if 'extra' in data: data['extra'] = self.filter_extra(data['extra']) return data def filter_stacktrace(self, data): pass def filter_http(self, data): pass def filter_extra(self, data): return data class RemovePostDataProcessor(Processor): """Removes HTTP post data.""" def filter_http(self, data, **kwargs): data.pop('data', None) class RemoveStackLocalsProcessor(Processor): """Removes local context variables from stacktraces.""" def filter_stacktrace(self, data, **kwargs): for frame in data.get('frames', []): frame.pop('vars', None) class SanitizeKeysProcessor(Processor): """ Asterisk out things that correspond to a configurable set of keys. """ MASK = '*' * 8 @property def sanitize_keys(self): keys = getattr(self.client, 'sanitize_keys') if keys is None: raise ValueError('The sanitize_keys setting must be present to use SanitizeKeysProcessor') return keys def sanitize(self, item, value): if value is None: return if not item: # key can be a NoneType return value # Just in case we have bytes here, we want to make them into text # properly without failing so we can perform our check. if isinstance(item, bytes): item = item.decode('utf-8', 'replace') else: item = text_type(item) item = item.lower() for key in self.sanitize_keys: if key in item: # store mask as a fixed length for security return self.MASK return value def filter_stacktrace(self, data): for frame in data.get('frames', []): if 'vars' not in frame: continue frame['vars'] = varmap(self.sanitize, frame['vars']) def filter_http(self, data): for n in ('data', 'cookies', 'headers', 'env', 'query_string'): if n not in data: continue # data could be provided as bytes if PY3 and isinstance(data[n], bytes): data[n] = data[n].decode('utf-8', 'replace') if isinstance(data[n], string_types) and '=' in data[n]: # at this point we've assumed it's a standard HTTP query # or cookie if n == 'cookies': delimiter = ';' else: delimiter = '&' data[n] = self._sanitize_keyvals(data[n], delimiter) else: data[n] = varmap(self.sanitize, data[n]) if n == 'headers' and 'Cookie' in data[n]: data[n]['Cookie'] = self._sanitize_keyvals( data[n]['Cookie'], ';' ) def filter_extra(self, data): return varmap(self.sanitize, data) def _sanitize_keyvals(self, keyvals, delimiter): sanitized_keyvals = [] for keyval in keyvals.split(delimiter): keyval = keyval.split('=') if len(keyval) == 2: sanitized_keyvals.append((keyval[0], self.sanitize(*keyval))) else: sanitized_keyvals.append(keyval) return delimiter.join('='.join(keyval) for keyval in sanitized_keyvals) class SanitizePasswordsProcessor(SanitizeKeysProcessor): """ Asterisk out things that look like passwords, credit card numbers, and API keys in frames, http, and basic extra data. """ KEYS = frozenset([ 'password', 'secret', 'passwd', 'authorization', 'api_key', 'apikey', 'sentry_dsn', 'access_token', ]) VALUES_RE = re.compile(r'^(?:\d[ -]*?){13,16}$') @property def sanitize_keys(self): return self.KEYS @property def FIELDS(self): warnings.warn( "`SanitizePasswordsProcessor.Fields` has been deprecated. Use " "`SanitizePasswordsProcessor.KEYS` or `SanitizePasswordsProcessor.sanitize_keys` " "instead", DeprecationWarning, ) return self.KEYS def sanitize(self, item, value): value = super().sanitize(item, value) if isinstance(value, string_types) and self.VALUES_RE.match(value): return self.MASK return value ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/raven/scripts/0000755000175000017500000000000014471213412020552 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/scripts/__init__.py0000664000175000017500000000030014035600052022652 0ustar00nicknick""" raven.scripts ~~~~~~~~~~~~~ :copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/scripts/runner.py0000664000175000017500000000623414035600052022440 0ustar00nicknick""" raven.scripts.runner ~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from __future__ import print_function import logging import os import sys import time from optparse import OptionParser from raven import Client, get_version from raven.utils.json import json def store_json(option, opt_str, value, parser): try: value = json.loads(value) except ValueError: print("Invalid JSON was used for option %s. Received: %s" % (opt_str, value)) sys.exit(1) setattr(parser.values, option.dest, value) def get_loadavg(): if hasattr(os, 'getloadavg'): return os.getloadavg() return None def get_uid(): try: import pwd except ImportError: return None return pwd.getpwuid(os.geteuid())[0] def send_test_message(client, options): sys.stdout.write("Client configuration:\n") for k in ('base_url', 'project', 'public_key', 'secret_key'): sys.stdout.write(' %-15s: %s\n' % (k, getattr(client.remote, k))) sys.stdout.write('\n') remote_config = client.remote if not remote_config.is_active(): sys.stdout.write("Error: DSN configuration is not valid!\n") sys.exit(1) if not client.is_enabled(): sys.stdout.write('Error: Client reports as being disabled!\n') sys.exit(1) data = options.get('data', { 'culprit': 'raven.scripts.runner', 'logger': 'raven.test', 'request': { 'method': 'GET', 'url': 'http://example.com', } }) sys.stdout.write('Sending a test message... ') sys.stdout.flush() ident = client.captureMessage( message='This is a test message generated using ``raven test``', data=data, level=logging.INFO, stack=True, tags=options.get('tags', {}), extra={ 'user': get_uid(), 'loadavg': get_loadavg(), }, ) sys.stdout.write('Event ID was %r\n' % (ident,)) def main(): root = logging.getLogger('sentry.errors') root.setLevel(logging.DEBUG) # if len(root.handlers) == 0: # root.addHandler(logging.StreamHandler()) parser = OptionParser(version=get_version()) parser.add_option("--data", action="callback", callback=store_json, type="string", nargs=1, dest="data") parser.add_option("--tags", action="callback", callback=store_json, type="string", nargs=1, dest="tags") (opts, args) = parser.parse_args() dsn = ' '.join(args[1:]) or os.environ.get('SENTRY_DSN') if not dsn: print("Error: No configuration detected!") print("You must either pass a DSN to the command, or set the SENTRY_DSN environment variable.") sys.exit(1) print("Using DSN configuration:") print(" ", dsn) print() client = Client(dsn, include_paths=['raven']) send_test_message(client, opts.__dict__) # TODO(dcramer): correctly support async models time.sleep(3) if client.state.did_fail(): sys.stdout.write('error!\n') sys.exit(1) sys.stdout.write('success!\n') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735241.9976022 quodlibet-4.6.0/quodlibet/packages/raven/transport/0000755000175000017500000000000014471213412021117 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/__init__.py0000664000175000017500000000142014035600052023223 0ustar00nicknick""" raven.transport ~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ # TODO: deprecate this namespace and force non-default (sync + threaded) to # manually import/register transports somehow from __future__ import absolute_import from raven.transport.base import * # NOQA from raven.transport.eventlet import * # NOQA from raven.transport.exceptions import * # NOQA from raven.transport.gevent import * # NOQA from raven.transport.http import * # NOQA from raven.transport.requests import * # NOQA from raven.transport.registry import * # NOQA from raven.transport.twisted import * # NOQA from raven.transport.threaded import * # NOQA from raven.transport.tornado import * # NOQA ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/base.py0000664000175000017500000000227314035600052022405 0ustar00nicknick""" raven.transport.base ~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import # Helper for external transports has_newstyle_transports = True class Transport: """ All transport implementations need to subclass this class You must implement a send method (or an async_send method if sub-classing AsyncTransport). """ is_async = False scheme = [] def send(self, url, data, headers): """ You need to override this to do something with the actual data. Usually - this is sending to a server """ raise NotImplementedError class AsyncTransport(Transport): """ All asynchronous transport implementations should subclass this class. You must implement a async_send method. """ is_async = True def async_send(self, url, data, headers, success_cb, error_cb): """ Override this method for asynchronous transports. Call `success_cb()` if the send succeeds or `error_cb(exception)` if the send fails. """ raise NotImplementedError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/eventlet.py0000664000175000017500000000274414035600052023324 0ustar00nicknick""" raven.transport.eventlet ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import sys from raven.transport.http import HTTPTransport try: import eventlet try: from eventlet.green import urllib2 as eventlet_urllib2 except ImportError: from eventlet.green.urllib import request as eventlet_urllib2 has_eventlet = True except ImportError: has_eventlet = False class EventletHTTPTransport(HTTPTransport): scheme = ['eventlet+http', 'eventlet+https'] def __init__(self, pool_size=100, **kwargs): if not has_eventlet: raise ImportError('EventletHTTPTransport requires eventlet.') super().__init__(**kwargs) def _send_payload(self, payload): url, data, headers = payload req = eventlet_urllib2.Request(url, headers=headers) try: if sys.version_info < (2, 6): response = eventlet_urllib2.urlopen(req, data).read() else: response = eventlet_urllib2.urlopen(req, data, self.timeout).read() return response except Exception as err: return err def send(self, url, data, headers): """ Spawn an async request to a remote webserver. """ eventlet.spawn(self._send_payload, (url, data, headers)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/exceptions.py0000664000175000017500000000100514035600052023644 0ustar00nicknick""" raven.transport.exceptions ~~~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import class InvalidScheme(ValueError): """ Raised when a transport is constructed using a URI which is not handled by the transport """ class DuplicateScheme(Exception): """ Raised when registering a handler for a particular scheme which is already registered """ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/gevent.py0000664000175000017500000000310414035600052022755 0ustar00nicknick""" raven.transport.gevent ~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.transport.base import AsyncTransport from raven.transport.http import HTTPTransport try: import gevent # gevent 1.0bN renamed coros to lock try: from gevent.lock import Semaphore except ImportError: from gevent.coros import Semaphore # NOQA has_gevent = True except ImportError: has_gevent = None class GeventedHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['gevent+http', 'gevent+https'] def __init__(self, maximum_outstanding_requests=100, *args, **kwargs): if not has_gevent: raise ImportError('GeventedHTTPTransport requires gevent.') self._lock = Semaphore(maximum_outstanding_requests) super().__init__(*args, **kwargs) def async_send(self, url, data, headers, success_cb, failure_cb): """ Spawn an async request to a remote webserver. """ # this can be optimized by making a custom self.send that does not # read the response since we don't use it. self._lock.acquire() return gevent.spawn( super().send, url, data, headers ).link(lambda x: self._done(x, success_cb, failure_cb)) def _done(self, greenlet, success_cb, failure_cb, *args): self._lock.release() if greenlet.successful(): success_cb() else: failure_cb(greenlet.exception) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/http.py0000664000175000017500000000343314035600052022451 0ustar00nicknick""" raven.transport.http ~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.utils.compat import string_types, urllib2 from raven.conf import defaults from raven.exceptions import APIError, RateLimited from raven.transport.base import Transport from raven.utils.http import urlopen class HTTPTransport(Transport): scheme = ['sync+http', 'sync+https'] def __init__(self, timeout=defaults.TIMEOUT, verify_ssl=True, ca_certs=defaults.CA_BUNDLE): if isinstance(timeout, string_types): timeout = int(timeout) if isinstance(verify_ssl, string_types): verify_ssl = bool(int(verify_ssl)) self.timeout = timeout self.verify_ssl = verify_ssl self.ca_certs = ca_certs def send(self, url, data, headers): """ Sends a request to a remote webserver using HTTP POST. """ req = urllib2.Request(url, headers=headers) try: response = urlopen( url=req, data=data, timeout=self.timeout, verify_ssl=self.verify_ssl, ca_certs=self.ca_certs, ) except urllib2.HTTPError as exc: msg = exc.headers.get('x-sentry-error') code = exc.getcode() if code == 429: try: retry_after = int(exc.headers.get('retry-after')) except (ValueError, TypeError): retry_after = 0 raise RateLimited(msg, retry_after) elif msg: raise APIError(msg, code) else: raise return response ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/registry.py0000664000175000017500000000504614035600052023344 0ustar00nicknick""" raven.transport.registry ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import # TODO(dcramer): we really should need to import all of these by default from raven.transport.eventlet import EventletHTTPTransport from raven.transport.exceptions import DuplicateScheme from raven.transport.http import HTTPTransport from raven.transport.gevent import GeventedHTTPTransport from raven.transport.requests import RequestsHTTPTransport from raven.transport.threaded import ThreadedHTTPTransport from raven.transport.threaded_requests import ThreadedRequestsHTTPTransport from raven.transport.twisted import TwistedHTTPTransport from raven.transport.tornado import TornadoHTTPTransport from raven.utils import urlparse class TransportRegistry: def __init__(self, transports=None): # setup a default list of senders self._schemes = {} self._transports = {} if transports: for transport in transports: self.register_transport(transport) def register_transport(self, transport): if not hasattr(transport, 'scheme') or not hasattr(transport.scheme, '__iter__'): raise AttributeError('Transport %s must have a scheme list', transport.__class__.__name__) for scheme in transport.scheme: self.register_scheme(scheme, transport) def register_scheme(self, scheme, cls): """ It is possible to inject new schemes at runtime """ if scheme in self._schemes: raise DuplicateScheme() urlparse.register_scheme(scheme) # TODO (vng): verify the interface of the new class self._schemes[scheme] = cls def supported_scheme(self, scheme): return scheme in self._schemes def get_transport(self, parsed_url, **options): full_url = parsed_url.geturl() if full_url not in self._transports: # Remove the options from the parsed_url parsed_url = urlparse.urlparse(full_url.split('?')[0]) self._transports[full_url] = self._schemes[parsed_url.scheme](parsed_url, **options) return self._transports[full_url] def get_transport_cls(self, scheme): return self._schemes[scheme] default_transports = [ HTTPTransport, ThreadedHTTPTransport, GeventedHTTPTransport, TwistedHTTPTransport, RequestsHTTPTransport, ThreadedRequestsHTTPTransport, TornadoHTTPTransport, EventletHTTPTransport, ] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/requests.py0000664000175000017500000000174514035600052023351 0ustar00nicknick""" raven.transport.requests ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.transport.http import HTTPTransport try: import requests has_requests = True except ImportError: has_requests = False class RequestsHTTPTransport(HTTPTransport): scheme = ['requests+http', 'requests+https'] def __init__(self, *args, **kwargs): if not has_requests: raise ImportError('RequestsHTTPTransport requires requests.') super().__init__(*args, **kwargs) def send(self, url, data, headers): if self.verify_ssl: # If SSL verification is enabled use the provided CA bundle to # perform the verification. self.verify_ssl = self.ca_certs requests.post(url, data=data, headers=headers, verify=self.verify_ssl, timeout=self.timeout) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/threaded.py0000664000175000017500000001171314035600052023252 0ustar00nicknick""" raven.transport.threaded ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import atexit import logging import threading import os from time import sleep, time from raven.transport.base import AsyncTransport from raven.transport.http import HTTPTransport from raven.utils.compat import Queue, check_threads DEFAULT_TIMEOUT = 10 logger = logging.getLogger('sentry.errors') class AsyncWorker: _terminator = object() def __init__(self, shutdown_timeout=DEFAULT_TIMEOUT): check_threads() self._queue = Queue(-1) self._lock = threading.Lock() self._thread = None self._thread_for_pid = None self.options = { 'shutdown_timeout': shutdown_timeout, } self.start() def is_alive(self): if self._thread_for_pid != os.getpid(): return False return self._thread and self._thread.is_alive() def _ensure_thread(self): if self.is_alive(): return self.start() def main_thread_terminated(self): with self._lock: if not self.is_alive(): # thread not started or already stopped - nothing to do return # wake the processing thread up self._queue.put_nowait(self._terminator) timeout = self.options['shutdown_timeout'] # wait briefly, initially initial_timeout = min(0.1, timeout) if not self._timed_queue_join(initial_timeout): # if that didn't work, wait a bit longer # NB that size is an approximation, because other threads may # add or remove items size = self._queue.qsize() print("Sentry is attempting to send %i pending error messages" % size) print("Waiting up to %s seconds" % timeout) if os.name == 'nt': print("Press Ctrl-Break to quit") else: print("Press Ctrl-C to quit") self._timed_queue_join(timeout - initial_timeout) self._thread = None def _timed_queue_join(self, timeout): """ implementation of Queue.join which takes a 'timeout' argument returns true on success, false on timeout """ deadline = time() + timeout queue = self._queue queue.all_tasks_done.acquire() try: while queue.unfinished_tasks: delay = deadline - time() if delay <= 0: # timed out return False queue.all_tasks_done.wait(timeout=delay) return True finally: queue.all_tasks_done.release() def start(self): """ Starts the task thread. """ self._lock.acquire() try: if not self.is_alive(): self._thread = threading.Thread(target=self._target, name="raven.AsyncWorker") self._thread.setDaemon(True) self._thread.start() self._thread_for_pid = os.getpid() finally: self._lock.release() atexit.register(self.main_thread_terminated) def stop(self, timeout=None): """ Stops the task thread. Synchronous! """ with self._lock: if self._thread: self._queue.put_nowait(self._terminator) self._thread.join(timeout=timeout) self._thread = None self._thread_for_pid = None def queue(self, callback, *args, **kwargs): self._ensure_thread() self._queue.put_nowait((callback, args, kwargs)) def _target(self): while True: record = self._queue.get() try: if record is self._terminator: break callback, args, kwargs = record try: callback(*args, **kwargs) except Exception: logger.error('Failed processing job', exc_info=True) finally: self._queue.task_done() sleep(0) class ThreadedHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['http', 'https', 'threaded+http', 'threaded+https'] def get_worker(self): if not hasattr(self, '_worker') or not self._worker.is_alive(): self._worker = AsyncWorker() return self._worker def send_sync(self, url, data, headers, success_cb, failure_cb): try: super().send(url, data, headers) except Exception as e: failure_cb(e) else: success_cb() def async_send(self, url, data, headers, success_cb, failure_cb): self.get_worker().queue( self.send_sync, url, data, headers, success_cb, failure_cb) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/threaded_requests.py0000664000175000017500000000204314035600052025201 0ustar00nicknick""" raven.transport.threaded_requests ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.transport.base import AsyncTransport from raven.transport import RequestsHTTPTransport from raven.transport.threaded import AsyncWorker class ThreadedRequestsHTTPTransport(AsyncTransport, RequestsHTTPTransport): scheme = ['threaded+requests+http', 'threaded+requests+https'] def get_worker(self): if not hasattr(self, '_worker'): self._worker = AsyncWorker() return self._worker def send_sync(self, url, data, headers, success_cb, failure_cb): try: super().send(url, data, headers) except Exception as e: failure_cb(e) else: success_cb() def async_send(self, url, data, headers, success_cb, failure_cb): self.get_worker().queue( self.send_sync, url, data, headers, success_cb, failure_cb) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/tornado.py0000664000175000017500000000341714035600052023142 0ustar00nicknick""" raven.transport.tornado ~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from functools import partial from raven.transport.base import AsyncTransport from raven.transport.http import HTTPTransport try: from tornado import ioloop from tornado.httpclient import AsyncHTTPClient, HTTPClient has_tornado = True except ImportError: has_tornado = False class TornadoHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['tornado+http', 'tornado+https'] def __init__(self, *args, **kwargs): if not has_tornado: raise ImportError('TornadoHTTPTransport requires tornado.') super().__init__(*args, **kwargs) def async_send(self, url, data, headers, success_cb, failure_cb): kwargs = dict(method='POST', headers=headers, body=data) kwargs["validate_cert"] = self.verify_ssl kwargs["connect_timeout"] = self.timeout kwargs["ca_certs"] = self.ca_certs # only use async if ioloop is running, otherwise it will never send if ioloop.IOLoop.initialized(): client = AsyncHTTPClient() kwargs['callback'] = None future = client.fetch(url, **kwargs) ioloop.IOLoop.current().add_future(future, partial(self.handler, success_cb, failure_cb)) else: client = HTTPClient() try: client.fetch(url, **kwargs) success_cb() except Exception as e: failure_cb(e) @staticmethod def handler(success, error, future): try: future.result() success() except Exception as e: error(e) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/transport/twisted.py0000664000175000017500000000437014035600052023156 0ustar00nicknick""" raven.transport.twisted ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.utils.compat import BytesIO from raven.transport.base import AsyncTransport from raven.transport.http import HTTPTransport try: from twisted.web.client import ( Agent, FileBodyProducer, HTTPConnectionPool, ResponseNeverReceived, readBody, ) from twisted.web.http_headers import Headers has_twisted = True except ImportError: has_twisted = False class TwistedHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['twisted+http', 'twisted+https'] def __init__(self, *args, **kwargs): if not has_twisted: raise ImportError('TwistedHTTPTransport requires twisted.web.') super().__init__(*args, **kwargs) # Import reactor as late as possible. from twisted.internet import reactor # Use a persistent connection pool. self._agent = Agent(reactor, pool=HTTPConnectionPool(reactor)) def async_send(self, url, data, headers, success_cb, failure_cb): d = self._agent.request( b"POST", url, bodyProducer=FileBodyProducer(BytesIO(data)), headers=Headers(dict((k, [v]) for k, v in headers.items())) ) def on_failure(failure): ex = failure.check(ResponseNeverReceived) if ex: # ResponseNeverReceived wraps the actual error(s). failure_cb([f.value for f in failure.value.reasons]) else: failure_cb(failure.value) def on_success(response): """ Success only means that the request succeeded, *not* that the actual submission was successful. """ if response.code == 200: success_cb() else: def on_error_body(body): failure_cb(Exception(response.code, response.phrase, body)) return readBody(response).addCallback( on_error_body, ) d.addCallback( on_success, ).addErrback( on_failure, ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/packages/raven/utils/0000755000175000017500000000000014471213412020223 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/__init__.py0000664000175000017500000001127114035600052022334 0ustar00nicknick""" raven.utils ~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.utils.compat import iteritems, string_types import logging import threading from functools import update_wrapper try: import pkg_resources except ImportError: pkg_resources = None # NOQA import sys logger = logging.getLogger('raven.errors') def merge_dicts(*dicts): out = {} for d in dicts: if not d: continue for k, v in iteritems(d): out[k] = v return out def varmap(func, var, context=None, name=None): """ Executes ``func(key_name, value)`` on all values recurisively discovering dict and list scoped values. """ if context is None: context = {} objid = id(var) if objid in context: return func(name, '<...>') context[objid] = 1 if isinstance(var, dict): ret = dict((k, varmap(func, v, context, k)) for k, v in iteritems(var)) elif isinstance(var, (list, tuple)): ret = [varmap(func, f, context, name) for f in var] else: ret = func(name, var) del context[objid] return ret # We store a cache of module_name->version string to avoid # continuous imports and lookups of modules _VERSION_CACHE = {} def get_version_from_app(module_name, app): version = None # Try to pull version from pkg_resource first # as it is able to detect version tagged with egg_info -b if pkg_resources is not None: # pull version from pkg_resources if distro exists try: return pkg_resources.get_distribution(module_name).version except Exception: pass if hasattr(app, 'get_version'): version = app.get_version elif hasattr(app, '__version__'): version = app.__version__ elif hasattr(app, 'VERSION'): version = app.VERSION elif hasattr(app, 'version'): version = app.version if callable(version): version = version() if not isinstance(version, (string_types, list, tuple)): version = None if version is None: return None if isinstance(version, (list, tuple)): version = '.'.join(map(str, version)) return str(version) def get_versions(module_list=None): if not module_list: return {} ext_module_list = set() for m in module_list: parts = m.split('.') ext_module_list.update('.'.join(parts[:idx]) for idx in range(1, len(parts) + 1)) versions = {} for module_name in ext_module_list: if module_name not in _VERSION_CACHE: try: __import__(module_name) except ImportError: continue try: app = sys.modules[module_name] except KeyError: continue try: version = get_version_from_app(module_name, app) except Exception as e: logger.exception(e) version = None _VERSION_CACHE[module_name] = version else: version = _VERSION_CACHE[module_name] if version is not None: versions[module_name] = version return versions def get_auth_header(protocol, timestamp, client, api_key, api_secret=None, **kwargs): header = [ ('sentry_timestamp', timestamp), ('sentry_client', client), ('sentry_version', protocol), ('sentry_key', api_key), ] if api_secret: header.append(('sentry_secret', api_secret)) return 'Sentry %s' % ', '.join('%s=%s' % (k, v) for k, v in header) class memoize: """ Memoize the result of a property call. >>> class A: >>> @memoize >>> def func(self): >>> return 'foo' """ def __init__(self, func): self.__name__ = func.__name__ self.__module__ = func.__module__ self.__doc__ = func.__doc__ self.func = func def __get__(self, obj, type=None): if obj is None: return self d, n = vars(obj), self.__name__ if n not in d: d[n] = self.func(obj) return d[n] def once(func): """Runs a thing once and once only.""" lock = threading.Lock() def new_func(*args, **kwargs): if new_func.called: return with lock: if new_func.called: return rv = func(*args, **kwargs) new_func.called = True return rv new_func = update_wrapper(new_func, func) new_func.called = False return new_func ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/compat.py0000664000175000017500000001304414035600052022060 0ustar00nicknick""" raven.utils.compat ~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2016 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. Utilities for writing code that runs on Python 2 and 3 """ # flake8: noqa # Copyright (c) 2010-2013 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of # the Software, and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import absolute_import import operator import sys import types PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 if PY3: string_types = str, integer_types = int, class_types = type, text_type = str binary_type = bytes else: string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str try: advance_iterator = next except NameError: def advance_iterator(it): return it.next() next = advance_iterator try: callable = callable except NameError: def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) if PY3: Iterator = object else: class Iterator: def next(self): return type(self).__next__(self) if PY3: def iterkeys(d, **kw): return iter(d.keys(**kw)) def itervalues(d, **kw): return iter(d.values(**kw)) def iteritems(d, **kw): return iter(d.items(**kw)) def iterlists(d, **kw): return iter(d.lists(**kw)) else: def iterkeys(d, **kw): return d.iterkeys(**kw) def itervalues(d, **kw): return d.itervalues(**kw) def iteritems(d, **kw): return d.iteritems(**kw) def iterlists(d, **kw): return d.iterlists(**kw) if PY3: def b(s): return s.encode("latin-1") def u(s): return s import io StringIO = io.StringIO BytesIO = io.BytesIO else: def b(s): return s # Workaround for standalone backslash def u(s): return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") import StringIO StringIO = BytesIO = StringIO.StringIO if PY3: exec_ = getattr(__import__('builtins'), 'exec') def reraise(tp, value, tb=None): try: if value is None: value = tp() if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value finally: value = None tb = None else: def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" if _globs_ is None: frame = sys._getframe(1) _globs_ = frame.f_globals if _locs_ is None: _locs_ = frame.f_locals del frame elif _locs_ is None: _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): try: raise tp, value, tb finally: tb = None """) if sys.version_info[:2] == (3, 2): exec_("""def raise_from(value, from_value): try: if from_value is None: raise value raise value from from_value finally: value = None """) elif sys.version_info[:2] > (3, 2): exec_("""def raise_from(value, from_value): try: raise value from from_value finally: value = None """) else: def raise_from(value, from_value): raise value if PY3: from urllib.error import HTTPError from http import client as httplib import urllib.request as urllib2 from queue import Queue from urllib.parse import quote as urllib_quote from urllib import parse as urlparse else: from urllib2 import HTTPError import httplib import urllib2 from Queue import Queue from urllib import quote as urllib_quote import urlparse def get_code(func): rv = getattr(func, '__code__', getattr(func, 'func_code', None)) if rv is None: raise TypeError('Could not get code from %r' % type(func).__name__) return rv def check_threads(): try: from uwsgi import opt except ImportError: return # When `threads` is passed in as a uwsgi option, # `enable-threads` is implied on. if 'threads' in opt: return if str(opt.get('enable-threads', '0')).lower() in ('false', 'off', 'no', '0'): from warnings import warn warn(Warning('We detected the use of uwsgi with disabled threads. ' 'This will cause issues with the transport you are ' 'trying to use. Please enable threading for uwsgi. ' '(Enable the "enable-threads" flag).')) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/conf.py0000664000175000017500000000444714035600052021531 0ustar00nicknickfrom __future__ import absolute_import import copy import os from raven.utils.compat import string_types from raven.utils.imports import import_string def convert_options(settings, defaults=None): """ Convert a settings object (or dictionary) to parameters which may be passed to a new ``Client()`` instance. """ if defaults is None: defaults = {} if isinstance(settings, dict): def getopt(key, default=None): return settings.get( 'SENTRY_%s' % key.upper(), defaults.get(key, default) ) options = copy.copy( settings.get('SENTRY_CONFIG') or settings.get('RAVEN_CONFIG') or {} ) else: def getopt(key, default=None): return getattr(settings, 'SENTRY_%s' % key.upper(), defaults.get(key, default)) options = copy.copy( getattr(settings, 'SENTRY_CONFIG', None) or getattr(settings, 'RAVEN_CONFIG', None) or {} ) options.setdefault('include_paths', getopt('include_paths', [])) options.setdefault('exclude_paths', getopt('exclude_paths', [])) options.setdefault('timeout', getopt('timeout')) options.setdefault('name', getopt('name')) options.setdefault('auto_log_stacks', getopt('auto_log_stacks')) options.setdefault('string_max_length', getopt('string_max_length')) options.setdefault('list_max_length', getopt('list_max_length')) options.setdefault('site', getopt('site')) options.setdefault('processors', getopt('processors')) options.setdefault('sanitize_keys', getopt('sanitize_keys')) options.setdefault('dsn', getopt('dsn', os.environ.get('SENTRY_DSN'))) options.setdefault('context', getopt('context')) options.setdefault('tags', getopt('tags')) options.setdefault('release', getopt('release')) options.setdefault('repos', getopt('repos')) options.setdefault('environment', getopt('environment')) options.setdefault('ignore_exceptions', getopt('ignore_exceptions')) options.setdefault('sample_rate', getopt('sample_rate')) transport = getopt('transport') or options.get('transport') if isinstance(transport, string_types): transport = import_string(transport) options['transport'] = transport return options ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/encoding.py0000664000175000017500000000634714035600052022373 0ustar00nicknick""" raven.utils.encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import, unicode_literals import warnings from raven.utils.compat import integer_types, text_type, binary_type, \ string_types, PY2 def is_protected_type(obj): """Determine if the object instance is of a protected type. Objects of protected types are preserved as-is when passed to force_text(strings_only=True). """ import Decimal import datetime return isinstance(obj, integer_types + (type(None), float, Decimal, datetime.datetime, datetime.date, datetime.time)) def force_text(s, encoding='utf-8', strings_only=False, errors='strict'): """ Similar to smart_text, except that lazy instances are resolved to strings, rather than kept as lazy objects. If strings_only is True, don't convert (some) non-string-like objects. """ # Handle the common case first, saves 30-40% when s is an instance of # text_type. This function gets called often in that setting. if isinstance(s, text_type): return s if strings_only and is_protected_type(s): return s try: if not isinstance(s, string_types): if hasattr(s, '__unicode__'): s = s.__unicode__() else: if not PY2: if isinstance(s, bytes): s = text_type(s, encoding, errors) else: s = text_type(s) else: s = text_type(bytes(s), encoding, errors) else: # Note: We use .decode() here, instead of text_type(s, encoding, # errors), so that if s is a SafeBytes, it ends up being a # SafeText at the end. s = s.decode(encoding, errors) except UnicodeDecodeError as e: if not isinstance(s, Exception): raise UnicodeDecodeError(*e.args) else: # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII bytestring data without a # working unicode method. Try to handle this without raising a # further exception by individually forcing the exception args # to unicode. s = ' '.join([force_text(arg, encoding, strings_only, errors) for arg in s]) return s def transform(value): from raven.utils.serializer import transform warnings.warn('You should switch to raven.utils.serializer.' 'transform', DeprecationWarning) return transform(value) def to_unicode(value): try: value = text_type(force_text(value)) except (UnicodeEncodeError, UnicodeDecodeError): value = '(Error decoding value)' except Exception: # in some cases we get a different exception try: value = text_type(force_text(repr(type(value)))) except Exception: value = '(Error decoding value)' return value def to_string(value): try: return binary_type(value.decode('utf-8').encode('utf-8')) except Exception: return to_unicode(value).encode('utf-8') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/http.py0000664000175000017500000000372014035600052021554 0ustar00nicknick""" raven.utils.http ~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import socket import ssl import sys from raven.conf import defaults from raven.utils.compat import urllib2, httplib from raven.utils.ssl_match_hostname import match_hostname def urlopen(url, data=None, timeout=defaults.TIMEOUT, ca_certs=None, verify_ssl=False, assert_hostname=None): class ValidHTTPSConnection(httplib.HTTPConnection): default_port = httplib.HTTPS_PORT def __init__(self, *args, **kwargs): httplib.HTTPConnection.__init__(self, *args, **kwargs) def connect(self): sock = socket.create_connection( address=(self.host, self.port), timeout=self.timeout, ) if self._tunnel_host: self.sock = sock self._tunnel() self.sock = ssl.wrap_socket( sock, ca_certs=ca_certs, cert_reqs=ssl.CERT_REQUIRED) if assert_hostname is not None: match_hostname(self.sock.getpeercert(), self.assert_hostname or self.host) class ValidHTTPSHandler(urllib2.HTTPSHandler): def https_open(self, req): return self.do_open(ValidHTTPSConnection, req) if verify_ssl: handlers = [ValidHTTPSHandler] else: try: handlers = [urllib2.HTTPSHandler( context=ssl._create_unverified_context())] except AttributeError: handlers = [] opener = urllib2.build_opener(*handlers) if sys.version_info < (2, 6): default_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(timeout) try: return opener.open(url, data) finally: socket.setdefaulttimeout(default_timeout) return opener.open(url, data, timeout) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/imports.py0000664000175000017500000000062414035600052022272 0ustar00nicknickfrom __future__ import absolute_import from raven.utils.compat import PY2 def import_string(key): # HACK(dcramer): Ensure a unicode key is still importable if PY2: key = str(key) if '.' not in key: return __import__(key) module_name, class_name = key.rsplit('.', 1) module = __import__(module_name, {}, {}, [class_name], 0) return getattr(module, class_name) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/json.py0000664000175000017500000000503614035600052021550 0ustar00nicknick""" raven.utils.json ~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import codecs import datetime import uuid import json try: JSONDecodeError = json.JSONDecodeError except AttributeError: JSONDecodeError = ValueError class BetterJSONEncoder(json.JSONEncoder): ENCODER_BY_TYPE = { uuid.UUID: lambda o: o.hex, datetime.datetime: lambda o: o.strftime('%Y-%m-%dT%H:%M:%SZ'), set: list, frozenset: list, bytes: lambda o: o.decode('utf-8', errors='replace') } def default(self, obj): try: encoder = self.ENCODER_BY_TYPE[type(obj)] except KeyError: try: return super().default(obj) except TypeError: return repr(obj) return encoder(obj) def better_decoder(data): return data def dumps(value, **kwargs): try: return json.dumps(value, cls=BetterJSONEncoder, **kwargs) except Exception: kwargs['encoding'] = 'safe-utf-8' return json.dumps(value, cls=BetterJSONEncoder, **kwargs) def loads(value, **kwargs): return json.loads(value, object_hook=better_decoder) _utf8_encoder = codecs.getencoder('utf-8') def safe_encode(input, errors='backslashreplace'): return _utf8_encoder(input, errors) _utf8_decoder = codecs.getdecoder('utf-8') def safe_decode(input, errors='replace'): return _utf8_decoder(input, errors) class Codec(codecs.Codec): def encode(self, input, errors='backslashreplace'): return safe_encode(input, errors) def decode(self, input, errors='replace'): return safe_decode(input, errors) class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input, final=False): return safe_encode(input, self.errors)[0] class IncrementalDecoder(codecs.IncrementalDecoder): def decode(self, input, final=False): return safe_decode(input, self.errors)[0] class StreamWriter(Codec, codecs.StreamWriter): pass class StreamReader(Codec, codecs.StreamReader): pass def getregentry(name): if name == 'safe-utf-8': return codecs.CodecInfo( name=name, encode=safe_encode, decode=safe_decode, incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamreader=StreamReader, streamwriter=StreamWriter, ) codecs.register(getregentry) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/packages/raven/utils/serializer/0000755000175000017500000000000014471213412022374 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/serializer/__init__.py0000664000175000017500000000047714035600052024513 0ustar00nicknick""" raven.utils.serializer ~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.utils.serializer.base import * # NOQA from raven.utils.serializer.manager import * # NOQA ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/serializer/base.py0000664000175000017500000001255714035600052023670 0ustar00nicknick# -*- coding: utf-8 -*- """ raven.utils.serializer.base ~~~~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import itertools import types from raven.utils.compat import text_type, binary_type, string_types, iteritems, \ class_types, PY2, PY3 from raven.utils.encoding import to_unicode from .manager import manager as serialization_manager __all__ = ('Serializer',) def has_sentry_metadata(value): try: return callable(value.__getattribute__('__sentry__')) except Exception: return False class Serializer: types = () def __init__(self, manager): self.manager = manager def can(self, value): """ Given ``value``, return a boolean describing whether this serializer can operate on the given type """ return isinstance(value, self.types) def serialize(self, value, **kwargs): """ Given ``value``, coerce into a JSON-safe type. """ return value def recurse(self, value, max_depth=6, _depth=0, **kwargs): """ Given ``value``, recurse (using the parent serializer) to handle coercing of newly defined values. """ string_max_length = kwargs.get('string_max_length', None) _depth += 1 if _depth >= max_depth: try: value = text_type(repr(value))[:string_max_length] except Exception as e: import traceback traceback.print_exc() self.manager.logger.exception(e) return text_type(type(value)) return self.manager.transform(value, max_depth=max_depth, _depth=_depth, **kwargs) class IterableSerializer(Serializer): types = (tuple, list, set, frozenset) def serialize(self, value, **kwargs): list_max_length = kwargs.get('list_max_length') or float('inf') return tuple( self.recurse(o, **kwargs) for n, o in itertools.takewhile(lambda x: x[0] < list_max_length, enumerate(value)) ) class DictSerializer(Serializer): types = (dict,) def make_key(self, key): if not isinstance(key, string_types): return to_unicode(key) return key def serialize(self, value, **kwargs): list_max_length = kwargs.get('list_max_length') or float('inf') return dict( (self.make_key(self.recurse(k, **kwargs)), self.recurse(v, **kwargs)) for n, (k, v) in itertools.takewhile(lambda x: x[0] < list_max_length, enumerate( iteritems(value))) ) class UnicodeSerializer(Serializer): types = (text_type,) def serialize(self, value, **kwargs): # try to return a reasonable string that can be decoded # correctly by the server so it doesn't show up as \uXXX for each # unicode character # e.g. we want the output to be like: "u'רונית מגן'" string_max_length = kwargs.get('string_max_length', None) return repr(text_type('%s')) % (value[:string_max_length],) class StringSerializer(Serializer): types = (binary_type,) def serialize(self, value, **kwargs): string_max_length = kwargs.get('string_max_length', None) if PY3: return repr(value[:string_max_length]) try: # Python2 madness: let's try to recover from developer's issues # Try to process the string as if it was a unicode. return "'" + value.decode('utf8')[:string_max_length] \ .encode('utf8') + "'" except UnicodeDecodeError: pass return repr(value[:string_max_length]) class TypeSerializer(Serializer): types = class_types def can(self, value): return not super().can(value) \ and has_sentry_metadata(value) def serialize(self, value, **kwargs): return self.recurse(value.__sentry__(), **kwargs) class BooleanSerializer(Serializer): types = (bool,) def serialize(self, value, **kwargs): return bool(value) class FloatSerializer(Serializer): types = (float,) def serialize(self, value, **kwargs): return float(value) class IntegerSerializer(Serializer): types = (int,) def serialize(self, value, **kwargs): return int(value) class FunctionSerializer(Serializer): types = (types.FunctionType,) def serialize(self, value, **kwargs): return '' % ( value.__name__, value.__module__, id(value)) if PY2: class LongSerializer(Serializer): types = (long,) # noqa def serialize(self, value, **kwargs): return long(value) # noqa # register all serializers, order matters serialization_manager.register(IterableSerializer) serialization_manager.register(DictSerializer) serialization_manager.register(UnicodeSerializer) serialization_manager.register(StringSerializer) serialization_manager.register(TypeSerializer) serialization_manager.register(BooleanSerializer) serialization_manager.register(FloatSerializer) serialization_manager.register(IntegerSerializer) serialization_manager.register(FunctionSerializer) if PY2: serialization_manager.register(LongSerializer) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/serializer/manager.py0000664000175000017500000000513714035600052024364 0ustar00nicknick""" raven.utils.serializer.manager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import logging from contextlib import closing from raven.utils.compat import text_type __all__ = ('register', 'transform') logger = logging.getLogger('sentry.errors.serializer') class SerializationManager: logger = logger def __init__(self): self.__registry = [] self.__serializers = {} @property def serializers(self): # XXX: Would serializers ever need state that we shouldn't cache them? for serializer in self.__registry: yield serializer def register(self, serializer): if serializer not in self.__registry: self.__registry.append(serializer) return serializer class Serializer: logger = logger def __init__(self, manager): self.manager = manager self.context = set() self.serializers = [] for serializer in manager.serializers: self.serializers.append(serializer(self)) def close(self): del self.serializers del self.context def transform(self, value, **kwargs): """ Primary function which handles recursively transforming values via their serializers """ if value is None: return None objid = id(value) if objid in self.context: return '<...>' self.context.add(objid) try: for serializer in self.serializers: try: if serializer.can(value): return serializer.serialize(value, **kwargs) except Exception as e: logger.exception(e) return text_type(type(value)) # if all else fails, lets use the repr of the object try: return repr(value) except Exception as e: logger.exception(e) # It's common case that a model's __unicode__ definition # may try to query the database which if it was not # cleaned up correctly, would hit a transaction aborted # exception return text_type(type(value)) finally: self.context.remove(objid) manager = SerializationManager() register = manager.register def transform(value, manager=manager, **kwargs): with closing(Serializer(manager)) as serializer: return serializer.transform(value, **kwargs) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/ssl_match_hostname.py0000664000175000017500000000701614035600052024452 0ustar00nicknick"""The match_hostname() function from Python 3.2, essential when using SSL.""" from __future__ import absolute_import import re __version__ = '3.2.2' class CertificateError(ValueError): pass def _dnsname_match(dn, hostname, max_wildcards=1): """Matching according to RFC 6125, section 6.4.3 http://tools.ietf.org/html/rfc6125#section-6.4.3 """ pats = [] if not dn: return False parts = dn.split(r'.') leftmost = parts[0] wildcards = leftmost.count('*') if wildcards > max_wildcards: # Issue #17980: avoid denials of service by refusing more # than one wildcard per fragment. A survery of established # policy among SSL implementations showed it to be a # reasonable choice. raise CertificateError( "too many wildcards in certificate DNS name: " + repr(dn)) # speed up common case w/o wildcards if not wildcards: return dn.lower() == hostname.lower() # RFC 6125, section 6.4.3, subitem 1. # The client SHOULD NOT attempt to match a presented identifier in which # the wildcard character comprises a label other than the left-most label. if leftmost == '*': # When '*' is a fragment by itself, it matches a non-empty dotless # fragment. pats.append('[^.]+') elif leftmost.startswith('xn--') or hostname.startswith('xn--'): # RFC 6125, section 6.4.3, subitem 3. # The client SHOULD NOT attempt to match a presented identifier # where the wildcard character is embedded within an A-label or # U-label of an internationalized domain name. pats.append(re.escape(leftmost)) else: # Otherwise, '*' matches any dotless string, e.g. www* pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) # add the remaining fragments, ignore any wildcards for frag in parts[1:]: pats.append(re.escape(frag)) pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) return pat.match(hostname) def match_hostname(cert, hostname): """Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 rules are followed, but IP addresses are not accepted for *hostname*. CertificateError is raised on failure. On success, the function returns nothing. """ if not cert: raise ValueError("empty or no certificate") dnsnames = [] san = cert.get('subjectAltName', ()) for key, value in san: if key == 'DNS': if _dnsname_match(value, hostname): return dnsnames.append(value) if not dnsnames: # The subject is only checked when there is no dNSName entry # in subjectAltName for sub in cert.get('subject', ()): for key, value in sub: # XXX according to RFC 2818, the most specific Common Name # must be used. if key == 'commonName': if _dnsname_match(value, hostname): return dnsnames.append(value) if len(dnsnames) > 1: raise CertificateError( "hostname %r doesn't match either of %s" % ( hostname, ', '.join(map(repr, dnsnames))) ) elif len(dnsnames) == 1: raise CertificateError( "hostname %r doesn't match %r" % (hostname, dnsnames[0]) ) else: raise CertificateError( "no appropriate commonName or subjectAltName fields were found" ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/stacks.py0000664000175000017500000002345214035600052022071 0ustar00nicknick""" raven.utils.stacks ~~~~~~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import, division import inspect import linecache import re import os import sys from raven.utils.serializer import transform from raven.utils.compat import iteritems _coding_re = re.compile(r'coding[:=]\s*([-\w.]+)') def get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None): """ Returns context_lines before and after lineno from file. Returns (pre_context_lineno, pre_context, context_line, post_context). """ source = None if loader is not None and hasattr(loader, "get_source"): try: source = loader.get_source(module_name) except (ImportError, IOError): # Traceback (most recent call last): # File "/Users/dcramer/Development/django-sentry/sentry/client/handlers.py", line 31, in emit # get_client().create_from_record(record, request=request) # File "/Users/dcramer/Development/django-sentry/sentry/client/base.py", line 325, in create_from_record # data['__sentry__']['frames'] = varmap(shorten, get_stack_info(stack)) # File "/Users/dcramer/Development/django-sentry/sentry/utils/stacks.py", line 112, in get_stack_info # pre_context_lineno, pre_context, context_line, post_context = get_lines_from_file(filename, lineno, 7, loader, module_name) # File "/Users/dcramer/Development/django-sentry/sentry/utils/stacks.py", line 24, in get_lines_from_file # source = loader.get_source(module_name) # File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pkgutil.py", line 287, in get_source # fullname = self._fix_name(fullname) # File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pkgutil.py", line 262, in _fix_name # "module %s" % (self.fullname, fullname)) # ImportError: Loader for module cProfile cannot handle module __main__ source = None if source is not None: source = source.splitlines() if source is None: try: source = linecache.getlines(filename) except (OSError, IOError): return None, None, None if not source: return None, None, None lower_bound = max(0, lineno - context_lines) upper_bound = min(lineno + 1 + context_lines, len(source)) try: pre_context = [ line.strip('\r\n') for line in source[lower_bound:lineno] ] context_line = source[lineno].strip('\r\n') post_context = [ line.strip('\r\n') for line in source[(lineno + 1):upper_bound] ] except IndexError: # the file may have changed since it was loaded into memory return None, None, None return ( slim_string(pre_context), slim_string(context_line), slim_string(post_context) ) def _getitem_from_frame(f_locals, key, default=None): """ f_locals is not guaranteed to have .get(), but it will always support __getitem__. Even if it doesn't, we return ``default``. """ try: return f_locals[key] except Exception: return default def to_dict(dictish): """ Given something that closely resembles a dictionary, we attempt to coerce it into a propery dictionary. """ if hasattr(dictish, 'iterkeys'): m = dictish.iterkeys elif hasattr(dictish, 'keys'): m = dictish.keys else: raise ValueError(dictish) return dict((k, dictish[k]) for k in m()) def iter_traceback_frames(tb): """ Given a traceback object, it will iterate over all frames that do not contain the ``__traceback_hide__`` local variable. """ # Some versions of celery have hacked traceback objects that might # miss tb_frame. while tb and hasattr(tb, 'tb_frame'): # support for __traceback_hide__ which is used by a few libraries # to hide internal frames. f_locals = getattr(tb.tb_frame, 'f_locals', {}) if not _getitem_from_frame(f_locals, '__traceback_hide__'): yield tb.tb_frame, getattr(tb, 'tb_lineno', None) tb = tb.tb_next def iter_stack_frames(frames=None): """ Given an optional list of frames (defaults to current stack), iterates over all frames that do not contain the ``__traceback_hide__`` local variable. """ if not frames: frames = inspect.stack()[1:] for frame, lineno in ((f[0], f[2]) for f in frames): f_locals = getattr(frame, 'f_locals', {}) if not _getitem_from_frame(f_locals, '__traceback_hide__'): yield frame, lineno def get_frame_locals(frame, transformer=transform, max_var_size=4096): f_locals = getattr(frame, 'f_locals', None) if not f_locals: return None if not isinstance(f_locals, dict): # XXX: Genshi (and maybe others) have broken implementations of # f_locals that are not actually dictionaries try: f_locals = to_dict(f_locals) except Exception: return None f_vars = {} f_size = 0 for k, v in iteritems(f_locals): v = transformer(v) v_size = len(repr(v)) if v_size + f_size < max_var_size: f_vars[k] = v f_size += v_size return f_vars def slim_frame_data(frames, frame_allowance=25): """ Removes various excess metadata from middle frames which go beyond ``frame_allowance``. Returns ``frames``. """ frames_len = 0 app_frames = [] system_frames = [] for frame in frames: frames_len += 1 if frame.get('in_app'): app_frames.append(frame) else: system_frames.append(frame) if frames_len <= frame_allowance: return frames remaining = frames_len - frame_allowance app_count = len(app_frames) system_allowance = max(frame_allowance - app_count, 0) if system_allowance: half_max = int(system_allowance / 2) # prioritize trimming system frames for frame in system_frames[half_max:-half_max]: frame.pop('vars', None) frame.pop('pre_context', None) frame.pop('post_context', None) remaining -= 1 else: for frame in system_frames: frame.pop('vars', None) frame.pop('pre_context', None) frame.pop('post_context', None) remaining -= 1 if remaining: app_allowance = app_count - remaining half_max = int(app_allowance / 2) for frame in app_frames[half_max:-half_max]: frame.pop('vars', None) frame.pop('pre_context', None) frame.pop('post_context', None) return frames def slim_string(value, length=512): if not value: return value if len(value) > length: return value[:length - 3] + '...' return value[:length] def get_stack_info(frames, transformer=transform, capture_locals=True, frame_allowance=25): """ Given a list of frames, returns a list of stack information dictionary objects that are JSON-ready. We have to be careful here as certain implementations of the _Frame class do not contain the necessary data to lookup all of the information we want. """ __traceback_hide__ = True # NOQA result = [] for frame_info in frames: # Old, terrible API if isinstance(frame_info, (list, tuple)): frame, lineno = frame_info else: frame = frame_info lineno = frame_info.f_lineno # Support hidden frames f_locals = getattr(frame, 'f_locals', {}) if _getitem_from_frame(f_locals, '__traceback_hide__'): continue f_globals = getattr(frame, 'f_globals', {}) f_code = getattr(frame, 'f_code', None) if f_code: abs_path = frame.f_code.co_filename function = frame.f_code.co_name else: abs_path = None function = None loader = _getitem_from_frame(f_globals, '__loader__') module_name = _getitem_from_frame(f_globals, '__name__') if lineno: lineno -= 1 if lineno is not None and abs_path: pre_context, context_line, post_context = \ get_lines_from_file(abs_path, lineno, 5, loader, module_name) else: pre_context, context_line, post_context = None, None, None # Try to pull a relative file path # This changes /foo/site-packages/baz/bar.py into baz/bar.py try: base_filename = sys.modules[module_name.split('.', 1)[0]].__file__ filename = abs_path.split( base_filename.rsplit(os.sep, 2)[0], 1)[-1].lstrip(os.sep) except Exception: filename = abs_path if not filename: filename = abs_path frame_result = { 'abs_path': abs_path, 'filename': filename, 'module': module_name or None, 'function': function or '', 'lineno': lineno + 1, } if capture_locals: f_vars = get_frame_locals(frame, transformer=transformer) if f_vars: frame_result['vars'] = f_vars if context_line is not None: frame_result.update({ 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, }) result.append(frame_result) stackinfo = { 'frames': slim_frame_data(result, frame_allowance=frame_allowance), } return stackinfo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/testutils.py0000664000175000017500000000124514035600052022635 0ustar00nicknick""" raven.utils.testutils ~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2010-2013 by the Sentry Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import raven from exam import Exam try: from unittest2 import TestCase as BaseTestCase except ImportError: from unittest import TestCase as BaseTestCase # NOQA class TestCase(Exam, BaseTestCase): pass class InMemoryClient(raven.Client): def __init__(self, **kwargs): self.events = [] super().__init__(**kwargs) def is_enabled(self): return True def send(self, **kwargs): self.events.append(kwargs) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/transaction.py0000664000175000017500000000207014035600052023117 0ustar00nicknickfrom __future__ import absolute_import from threading import local class TransactionContext: def __init__(self, stack, context): self.stack = stack self.context = context def __enter__(self): self.stack.push(self.context) return self def __exit__(self, *exc_info): self.stack.pop(self.context) class TransactionStack(local): def __init__(self): self.stack = [] def __len__(self): return len(self.stack) def __iter__(self): return iter(self.stack) def __call__(self, context): return TransactionContext(self, context) def clear(self): self.stack = [] def peek(self): try: return self.stack[-1] except IndexError: return None def push(self, context): self.stack.append(context) return context def pop(self, context=None): if context is None: return self.stack.pop() while self.stack: if self.stack.pop() is context: return context ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/urlparse.py0000664000175000017500000000073414035600052022434 0ustar00nicknickfrom __future__ import absolute_import # Can't use the compat module here because of an import loop try: import urlparse as _urlparse except ImportError: from urllib import parse as _urlparse def register_scheme(scheme): for method in filter(lambda s: s.startswith('uses_'), dir(_urlparse)): uses = getattr(_urlparse, method) if scheme not in uses: uses.append(scheme) urlparse = _urlparse.urlparse parse_qsl = _urlparse.parse_qsl ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/utils/wsgi.py0000664000175000017500000000722314035600052021550 0ustar00nicknick""" This module implements WSGI related helpers adapted from ``werkzeug.wsgi`` :copyright: (c) 2010 by the Werkzeug Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from raven.utils.compat import iteritems, urllib_quote # `get_headers` comes from `werkzeug.datastructures.EnvironHeaders` def get_headers(environ): """ Returns only proper HTTP headers. """ for key, value in iteritems(environ): key = str(key) if key.startswith('HTTP_') and key not in \ ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'): yield key[5:].replace('_', '-').title(), value elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'): yield key.replace('_', '-').title(), value def get_environ(environ): """ Returns our whitelisted environment variables. """ for key in ('REMOTE_ADDR', 'SERVER_NAME', 'SERVER_PORT'): if key in environ: yield key, environ[key] # `get_host` comes from `werkzeug.wsgi` def get_host(environ): """Return the real host for the given WSGI environment. This takes care of the `X-Forwarded-Host` header. :param environ: the WSGI environment to get the host of. """ scheme = environ.get('wsgi.url_scheme') if 'HTTP_X_FORWARDED_HOST' in environ: result = environ['HTTP_X_FORWARDED_HOST'] elif 'HTTP_HOST' in environ: result = environ['HTTP_HOST'] else: result = environ['SERVER_NAME'] if (scheme, str(environ['SERVER_PORT'])) not \ in (('https', '443'), ('http', '80')): result += ':' + environ['SERVER_PORT'] if result.endswith(':80') and scheme == 'http': result = result[:-3] elif result.endswith(':443') and scheme == 'https': result = result[:-4] return result # `get_current_url` comes from `werkzeug.wsgi` def get_current_url(environ, root_only=False, strip_querystring=False, host_only=False): """A handy helper function that recreates the full URL for the current request or parts of it. Here an example: >>> from werkzeug import create_environ >>> env = create_environ("/?param=foo", "http://localhost/script") >>> get_current_url(env) 'http://localhost/script/?param=foo' >>> get_current_url(env, root_only=True) 'http://localhost/script/' >>> get_current_url(env, host_only=True) 'http://localhost/' >>> get_current_url(env, strip_querystring=True) 'http://localhost/script/' :param environ: the WSGI environment to get the current URL from. :param root_only: set `True` if you only want the root URL. :param strip_querystring: set to `True` if you don't want the querystring. :param host_only: set to `True` if the host URL should be returned. """ tmp = [environ['wsgi.url_scheme'], '://', get_host(environ)] cat = tmp.append if host_only: return ''.join(tmp) + '/' cat(urllib_quote(environ.get('SCRIPT_NAME', '').rstrip('/'))) if root_only: cat('/') else: cat(urllib_quote('/' + environ.get('PATH_INFO', '').lstrip('/'))) if not strip_querystring: qs = environ.get('QUERY_STRING') if qs: cat('?' + qs) return ''.join(tmp) def get_client_ip(environ): """ Naively yank the first IP address in an X-Forwarded-For header and assume this is correct. Note: Don't use this in security sensitive situations since this value may be forged from a client. """ try: return environ['HTTP_X_FORWARDED_FOR'].split(',')[0].strip() except (KeyError, IndexError): return environ.get('REMOTE_ADDR') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/raven/versioning.py0000664000175000017500000000467614035600052021633 0ustar00nicknickfrom __future__ import absolute_import import os.path try: import pkg_resources except ImportError: # pkg_resource is not available on Google App Engine pkg_resources = None from raven.utils.compat import text_type from .exceptions import InvalidGitRepository __all__ = ('fetch_git_sha', 'fetch_package_version') def fetch_git_sha(path, head=None): """ >>> fetch_git_sha(os.path.dirname(__file__)) """ if not head: head_path = os.path.join(path, '.git', 'HEAD') if not os.path.exists(head_path): raise InvalidGitRepository( 'Cannot identify HEAD for git repository at %s' % (path,)) with open(head_path, 'r') as fp: head = text_type(fp.read()).strip() if head.startswith('ref: '): head = head[5:] revision_file = os.path.join( path, '.git', *head.split('/') ) else: return head else: revision_file = os.path.join(path, '.git', 'refs', 'heads', head) if not os.path.exists(revision_file): if not os.path.exists(os.path.join(path, '.git')): raise InvalidGitRepository( '%s does not seem to be the root of a git repository' % (path,)) # Check for our .git/packed-refs' file since a `git gc` may have run # https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery packed_file = os.path.join(path, '.git', 'packed-refs') if os.path.exists(packed_file): with open(packed_file) as fh: for line in fh: line = line.rstrip() if line and line[:1] not in ('#', '^'): try: revision, ref = line.split(' ', 1) except ValueError: continue if ref == head: return text_type(revision) raise InvalidGitRepository( 'Unable to find ref to head "%s" in repository' % (head,)) with open(revision_file) as fh: return text_type(fh.read()).strip() def fetch_package_version(dist_name): """ >>> fetch_package_version('sentry') """ if pkg_resources is None: raise NotImplementedError('pkg_resources is not available ' 'on this Python install') dist = pkg_resources.get_distribution(dist_name) return dist.version ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/packages/senf/0000755000175000017500000000000014471213412016703 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/__init__.py0000664000175000017500000000521014035600052021010 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from ._fsnative import fsnative, path2fsn, fsn2text, fsn2bytes, \ bytes2fsn, uri2fsn, fsn2uri, text2fsn, fsn2norm from ._print import print_, input_, supports_ansi_escape_codes from ._stdlib import sep, pathsep, curdir, pardir, altsep, extsep, devnull, \ defpath, getcwd, expanduser, expandvars from ._argv import argv from ._environ import environ, getenv, unsetenv, putenv from ._temp import mkstemp, gettempdir, gettempprefix, mkdtemp fsnative, print_, getcwd, getenv, unsetenv, putenv, environ, expandvars, \ path2fsn, fsn2text, fsn2bytes, bytes2fsn, uri2fsn, fsn2uri, mkstemp, \ gettempdir, gettempprefix, mkdtemp, input_, expanduser, text2fsn, \ supports_ansi_escape_codes, fsn2norm version = (1, 5, 0) """Tuple[`int`, `int`, `int`]: The version tuple (major, minor, micro)""" version_string = ".".join(map(str, version)) """`str`: A version string""" argv = argv """List[`fsnative`]: Like `sys.argv` but contains unicode under Windows + Python 2 """ sep = sep """`fsnative`: Like `os.sep` but a `fsnative`""" pathsep = pathsep """`fsnative`: Like `os.pathsep` but a `fsnative`""" curdir = curdir """`fsnative`: Like `os.curdir` but a `fsnative`""" pardir = pardir """`fsnative`: Like `os.pardir` but a fsnative""" altsep = altsep """`fsnative` or `None`: Like `os.altsep` but a `fsnative` or `None`""" extsep = extsep """`fsnative`: Like `os.extsep` but a `fsnative`""" devnull = devnull """`fsnative`: Like `os.devnull` but a `fsnative`""" defpath = defpath """`fsnative`: Like `os.defpath` but a `fsnative`""" __all__ = [] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/__init__.pyi0000664000175000017500000000417414035600052021171 0ustar00nicknickimport sys import os from typing import Text, Union, Any, Optional, Tuple, List, Dict if sys.version_info[0] == 2: _pathlike = Union[Text, bytes] else: _pathlike = Union[Text, bytes, 'os.PathLike[Any]'] _uri = Union[Text, str] if sys.version_info[0] == 2: if sys.platform == "win32": _base = Text else: _base = bytes else: _base = Text class fsnative(_base): def __init__(self, object: Text=u"") -> None: ... _fsnative = Union[fsnative, _base] if sys.platform == "win32": _bytes_default_encoding = str else: _bytes_default_encoding = Optional[str] def path2fsn(path: _pathlike) -> _fsnative: ... def fsn2text(path: _fsnative, strict: bool=False) -> Text: ... def text2fsn(text: Text) -> _fsnative: ... def fsn2bytes(path: _fsnative, encoding: _bytes_default_encoding="utf-8") -> bytes: ... def bytes2fsn(data: bytes, encoding: _bytes_default_encoding="utf-8") -> _fsnative: ... def uri2fsn(uri: _uri) -> _fsnative: ... def fsn2uri(path: _fsnative) -> Text: ... def fsn2norm(path: _fsnative) -> _fsnative: ... sep: _fsnative pathsep: _fsnative curdir: _fsnative pardir: _fsnative altsep: _fsnative extsep: _fsnative devnull: _fsnative defpath: _fsnative def getcwd() -> _fsnative: ... def getenv(key: _pathlike, value: Optional[_fsnative]=None) -> Optional[_fsnative]: ... def putenv(key: _pathlike, value: _pathlike): ... def unsetenv(key: _pathlike) -> None: ... def supports_ansi_escape_codes(fd: int) -> bool: ... def expandvars(path: _pathlike) -> _fsnative: ... def expanduser(path: _pathlike) -> _fsnative: ... environ: Dict[_fsnative,_fsnative] argv: List[_fsnative] def gettempdir() -> _fsnative: pass def mkstemp(suffix: Optional[_pathlike]=None, prefix: Optional[_pathlike]=None, dir: Optional[_pathlike]=None, text: bool=False) -> Tuple[int, _fsnative]: ... def mkdtemp(suffix: Optional[_pathlike]=None, prefix: Optional[_pathlike]=None, dir: Optional[_pathlike]=None) -> _fsnative: ... version_string: str version: Tuple[int, int, int] print_ = print def input_(prompt: Any=None) -> _fsnative: ... ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_argv.py0000664000175000017500000000653114035600052020356 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import sys import ctypes try: from collections import abc except ImportError: import collections as abc # type: ignore from functools import total_ordering from ._compat import PY2, string_types from ._fsnative import is_win, _fsn2legacy, path2fsn from . import _winapi as winapi def _get_win_argv(): """Returns a unicode argv under Windows and standard sys.argv otherwise Returns: List[`fsnative`] """ assert is_win argc = ctypes.c_int() try: argv = winapi.CommandLineToArgvW( winapi.GetCommandLineW(), ctypes.byref(argc)) except WindowsError: return [] if not argv: return [] res = argv[max(0, argc.value - len(sys.argv)):argc.value] winapi.LocalFree(argv) return res @total_ordering class Argv(abc.MutableSequence): """List[`fsnative`]: Like `sys.argv` but contains unicode keys and values under Windows + Python 2. Any changes made will be forwarded to `sys.argv`. """ def __init__(self): if PY2 and is_win: self._argv = _get_win_argv() else: self._argv = sys.argv def __getitem__(self, index): return self._argv[index] def __setitem__(self, index, value): if isinstance(value, string_types): value = path2fsn(value) self._argv[index] = value if sys.argv is not self._argv: try: if isinstance(value, string_types): sys.argv[index] = _fsn2legacy(value) else: sys.argv[index] = [_fsn2legacy(path2fsn(v)) for v in value] except IndexError: pass def __delitem__(self, index): del self._argv[index] try: del sys.argv[index] except IndexError: pass def __eq__(self, other): return self._argv == other def __lt__(self, other): return self._argv < other def __len__(self): return len(self._argv) def __repr__(self): return repr(self._argv) def insert(self, index, value): value = path2fsn(value) self._argv.insert(index, value) if sys.argv is not self._argv: sys.argv.insert(index, _fsn2legacy(value)) argv = Argv() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_compat.py0000664000175000017500000000347414035600052020705 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import sys PY2 = sys.version_info[0] == 2 PY3 = not PY2 if PY2: from urlparse import urlparse, urlunparse urlparse, urlunparse from urllib import quote, unquote quote, unquote from StringIO import StringIO BytesIO = StringIO from io import StringIO as TextIO TextIO string_types = (str, unicode) text_type = unicode iteritems = lambda d: d.iteritems() elif PY3: from urllib.parse import urlparse, quote, unquote, urlunparse urlparse, quote, unquote, urlunparse from io import StringIO StringIO = StringIO TextIO = StringIO from io import BytesIO BytesIO = BytesIO string_types = (str,) text_type = str iteritems = lambda d: iter(d.items()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_environ.py0000664000175000017500000001530714035600052021100 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import ctypes try: from collections import abc except ImportError: import collections as abc # type: ignore from ._compat import text_type, PY2 from ._fsnative import path2fsn, is_win, _fsn2legacy, fsnative from . import _winapi as winapi def get_windows_env_var(key): """Get an env var. Raises: WindowsError """ if not isinstance(key, text_type): raise TypeError("%r not of type %r" % (key, text_type)) buf = ctypes.create_unicode_buffer(32767) stored = winapi.GetEnvironmentVariableW(key, buf, 32767) if stored == 0: raise ctypes.WinError() return buf[:stored] def set_windows_env_var(key, value): """Set an env var. Raises: WindowsError """ if not isinstance(key, text_type): raise TypeError("%r not of type %r" % (key, text_type)) if not isinstance(value, text_type): raise TypeError("%r not of type %r" % (value, text_type)) status = winapi.SetEnvironmentVariableW(key, value) if status == 0: raise ctypes.WinError() def del_windows_env_var(key): """Delete an env var. Raises: WindowsError """ if not isinstance(key, text_type): raise TypeError("%r not of type %r" % (key, text_type)) status = winapi.SetEnvironmentVariableW(key, None) if status == 0: raise ctypes.WinError() def read_windows_environ(): """Returns a unicode dict of the Windows environment. Raises: WindowsEnvironError """ res = winapi.GetEnvironmentStringsW() if not res: raise ctypes.WinError() res = ctypes.cast(res, ctypes.POINTER(ctypes.c_wchar)) done = [] current = u"" i = 0 while 1: c = res[i] i += 1 if c == u"\x00": if not current: break done.append(current) current = u"" continue current += c dict_ = {} for entry in done: try: key, value = entry.split(u"=", 1) except ValueError: continue key = _norm_key(key) dict_[key] = value status = winapi.FreeEnvironmentStringsW(res) if status == 0: raise ctypes.WinError() return dict_ def _norm_key(key): assert isinstance(key, fsnative) if is_win: key = key.upper() return key class Environ(abc.MutableMapping): """Dict[`fsnative`, `fsnative`]: Like `os.environ` but contains unicode keys and values under Windows + Python 2. Any changes made will be forwarded to `os.environ`. """ def __init__(self): if is_win and PY2: try: env = read_windows_environ() except WindowsError: env = {} else: env = os.environ self._env = env def __getitem__(self, key): key = _norm_key(path2fsn(key)) return self._env[key] def __setitem__(self, key, value): key = _norm_key(path2fsn(key)) value = path2fsn(value) if is_win and PY2: # this calls putenv, so do it first and replace later try: os.environ[_fsn2legacy(key)] = _fsn2legacy(value) except OSError: raise ValueError try: set_windows_env_var(key, value) except WindowsError: # py3+win fails for invalid keys. try to do the same raise ValueError try: self._env[key] = value except OSError: raise ValueError def __delitem__(self, key): key = _norm_key(path2fsn(key)) if is_win and PY2: try: del_windows_env_var(key) except WindowsError: pass try: del os.environ[_fsn2legacy(key)] except KeyError: pass del self._env[key] def __iter__(self): return iter(self._env) def __len__(self): return len(self._env) def __repr__(self): return repr(self._env) def copy(self): return self._env.copy() environ = Environ() def getenv(key, value=None): """Like `os.getenv` but returns unicode under Windows + Python 2 Args: key (pathlike): The env var to get value (object): The value to return if the env var does not exist Returns: `fsnative` or `object`: The env var or the passed value if it doesn't exist """ key = path2fsn(key) if is_win and PY2: return environ.get(key, value) return os.getenv(key, value) def unsetenv(key): """Like `os.unsetenv` but takes unicode under Windows + Python 2 Args: key (pathlike): The env var to unset """ key = path2fsn(key) if is_win: # python 3 has no unsetenv under Windows -> use our ctypes one as well try: del_windows_env_var(key) except WindowsError: pass else: os.unsetenv(key) def putenv(key, value): """Like `os.putenv` but takes unicode under Windows + Python 2 Args: key (pathlike): The env var to get value (pathlike): The value to set Raises: ValueError """ key = path2fsn(key) value = path2fsn(value) if is_win and PY2: try: set_windows_env_var(key, value) except WindowsError: # py3 + win fails here raise ValueError else: try: os.putenv(key, value) except OSError: # win + py3 raise here for invalid keys which is probably a bug. # ValueError seems better raise ValueError ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1661931628.0 quodlibet-4.6.0/quodlibet/packages/senf/_fsnative.py0000644000175000017500000004461614303610154021244 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import sys import ctypes import codecs from . import _winapi as winapi from ._compat import text_type, PY3, PY2, urlparse, quote, unquote, urlunparse is_win = os.name == "nt" is_unix = not is_win is_darwin = sys.platform == "darwin" _surrogatepass = "strict" if PY2 else "surrogatepass" def _normalize_codec(codec, _cache={}): """Raises LookupError""" try: return _cache[codec] except KeyError: _cache[codec] = codecs.lookup(codec).name return _cache[codec] def _swap_bytes(data): """swaps bytes for 16 bit, leaves remaining trailing bytes alone""" a, b = data[1::2], data[::2] data = bytearray().join(bytearray(x) for x in zip(a, b)) if len(b) > len(a): data += b[-1:] return bytes(data) def _decode_surrogatepass(data, codec): """Like data.decode(codec, 'surrogatepass') but makes utf-16-le/be work on Python 2. https://bugs.python.org/issue27971 Raises UnicodeDecodeError, LookupError """ try: return data.decode(codec, _surrogatepass) except UnicodeDecodeError: if PY2: if _normalize_codec(codec) == "utf-16-be": data = _swap_bytes(data) codec = "utf-16-le" if _normalize_codec(codec) == "utf-16-le": buffer_ = ctypes.create_string_buffer(data + b"\x00\x00") value = ctypes.wstring_at(buffer_, len(data) // 2) if value.encode("utf-16-le", _surrogatepass) != data: raise return value else: raise else: raise def _merge_surrogates(text): """Returns a copy of the text with all surrogate pairs merged""" return _decode_surrogatepass( text.encode("utf-16-le", _surrogatepass), "utf-16-le") def fsn2norm(path): """ Args: path (fsnative): The path to normalize Returns: `fsnative` Normalizes an fsnative path. The same underlying path can have multiple representations as fsnative (due to surrogate pairs and variable length encodings). When concatenating fsnative the result might be different than concatenating the serialized form and then deserializing it. This returns the normalized form i.e. the form which os.listdir() would return. This is useful when you alter fsnative but require that the same underlying path always maps to the same fsnative value. All functions like :func:`bytes2fsn`, :func:`fsnative`, :func:`text2fsn` and :func:`path2fsn` always return a normalized path, independent of their input. """ native = _fsn2native(path) if is_win: return _merge_surrogates(native) elif PY3: return bytes2fsn(native, None) else: return path def _fsn2legacy(path): """Takes a fsnative path and returns a path that can be put into os.environ or sys.argv. Might result in a mangled path on Python2 + Windows. Can't fail. Args: path (fsnative) Returns: str """ if PY2 and is_win: return path.encode(_encoding, "replace") return path def _fsnative(text): if not isinstance(text, text_type): raise TypeError("%r needs to be a text type (%r)" % (text, text_type)) if is_unix: # First we go to bytes so we can be sure we have a valid source. # Theoretically we should fail here in case we have a non-unicode # encoding. But this would make everything complicated and there is # no good way to handle a failure from the user side. Instead # fall back to utf-8 which is the most likely the right choice in # a mis-configured environment encoding = _encoding try: path = text.encode(encoding, _surrogatepass) except UnicodeEncodeError: path = text.encode("utf-8", _surrogatepass) if b"\x00" in path: path = path.replace(b"\x00", fsn2bytes(_fsnative(u"\uFFFD"), None)) if PY3: return path.decode(_encoding, "surrogateescape") return path else: if u"\x00" in text: text = text.replace(u"\x00", u"\uFFFD") text = fsn2norm(text) return text def _create_fsnative(type_): # a bit of magic to make fsnative(u"foo") and isinstance(path, fsnative) # work class meta(type): def __instancecheck__(self, instance): return _typecheck_fsnative(instance) def __subclasscheck__(self, subclass): return issubclass(subclass, type_) class impl: """fsnative(text=u"") Args: text (text): The text to convert to a path Returns: fsnative: The new path. Raises: TypeError: In case something other then `text` has been passed This type is a virtual base class for the real path type. Instantiating it returns an instance of the real path type and it overrides instance and subclass checks so that `isinstance` and `issubclass` checks work: :: isinstance(fsnative(u"foo"), fsnative) == True issubclass(type(fsnative(u"foo")), fsnative) == True The real returned type is: - **Python 2 + Windows:** :obj:`python:unicode`, with ``surrogates``, without ``null`` - **Python 2 + Unix:** :obj:`python:str`, without ``null`` - **Python 3 + Windows:** :obj:`python3:str`, with ``surrogates``, without ``null`` - **Python 3 + Unix:** :obj:`python3:str`, with ``surrogates``, without ``null``, without code points not encodable with the locale encoding Constructing a `fsnative` can't fail. Passing a `fsnative` to :func:`open` will never lead to `ValueError` or `TypeError`. Any operation on `fsnative` can also use the `str` type, as long as the `str` only contains ASCII and no NULL. """ def __new__(cls, text=u""): return _fsnative(text) new_type = meta("fsnative", (object,), dict(impl.__dict__)) new_type.__module__ = "senf" return new_type fsnative_type = text_type if is_win or PY3 else bytes fsnative = _create_fsnative(fsnative_type) def _typecheck_fsnative(path): """ Args: path (object) Returns: bool: if path is a fsnative """ if not isinstance(path, fsnative_type): return False if PY3 or is_win: if u"\x00" in path: return False if is_unix: try: path.encode(_encoding, "surrogateescape") except UnicodeEncodeError: return False elif b"\x00" in path: return False return True def _fsn2native(path): """ Args: path (fsnative) Returns: `text` on Windows, `bytes` on Unix Raises: TypeError: in case the type is wrong or the ´str` on Py3 + Unix can't be converted to `bytes` This helper allows to validate the type and content of a path. To reduce overhead the encoded value for Py3 + Unix is returned so it can be reused. """ if not isinstance(path, fsnative_type): raise TypeError("path needs to be %s, not %s" % ( fsnative_type.__name__, type(path).__name__)) if is_unix: if PY3: try: path = path.encode(_encoding, "surrogateescape") except UnicodeEncodeError: # This look more like ValueError, but raising only one error # makes things simpler... also one could say str + surrogates # is its own type raise TypeError( "path contained Unicode code points not valid in" "the current path encoding. To create a valid " "path from Unicode use text2fsn()") if b"\x00" in path: raise TypeError("fsnative can't contain nulls") else: if u"\x00" in path: raise TypeError("fsnative can't contain nulls") return path def _get_encoding(): """The encoding used for paths, argv, environ, stdout and stdin""" encoding = sys.getfilesystemencoding() if encoding is None: if is_darwin: encoding = "utf-8" elif is_win: encoding = "mbcs" else: encoding = "ascii" encoding = _normalize_codec(encoding) return encoding _encoding = _get_encoding() def path2fsn(path): """ Args: path (pathlike): The path to convert Returns: `fsnative` Raises: TypeError: In case the type can't be converted to a `fsnative` ValueError: In case conversion fails Returns a `fsnative` path for a `pathlike`. """ # allow mbcs str on py2+win and bytes on py3 if PY2: if is_win: if isinstance(path, bytes): path = path.decode(_encoding) else: if isinstance(path, text_type): path = path.encode(_encoding) if "\x00" in path: raise ValueError("embedded null") else: path = getattr(os, "fspath", lambda x: x)(path) if isinstance(path, bytes): if b"\x00" in path: raise ValueError("embedded null") path = path.decode(_encoding, "surrogateescape") elif is_unix and isinstance(path, str): # make sure we can encode it and this is not just some random # unicode string data = path.encode(_encoding, "surrogateescape") if b"\x00" in data: raise ValueError("embedded null") path = fsn2norm(path) else: if u"\x00" in path: raise ValueError("embedded null") path = fsn2norm(path) if not isinstance(path, fsnative_type): raise TypeError("path needs to be %s", fsnative_type.__name__) return path def fsn2text(path, strict=False): """ Args: path (fsnative): The path to convert strict (bool): Fail in case the conversion is not reversible Returns: `text` Raises: TypeError: In case no `fsnative` has been passed ValueError: In case ``strict`` was True and the conversion failed Converts a `fsnative` path to `text`. Can be used to pass a path to some unicode API, like for example a GUI toolkit. If ``strict`` is True the conversion will fail in case it is not reversible. This can be useful for converting program arguments that are supposed to be text and erroring out in case they are not. Encoding with a Unicode encoding will always succeed with the result. """ path = _fsn2native(path) errors = "strict" if strict else "replace" if is_win: return path.encode("utf-16-le", _surrogatepass).decode("utf-16-le", errors) else: return path.decode(_encoding, errors) def text2fsn(text): """ Args: text (text): The text to convert Returns: `fsnative` Raises: TypeError: In case no `text` has been passed Takes `text` and converts it to a `fsnative`. This operation is not reversible and can't fail. """ return fsnative(text) def fsn2bytes(path, encoding="utf-8"): """ Args: path (fsnative): The path to convert encoding (`str`): encoding used for Windows Returns: `bytes` Raises: TypeError: If no `fsnative` path is passed ValueError: If encoding fails or the encoding is invalid Converts a `fsnative` path to `bytes`. The passed *encoding* is only used on platforms where paths are not associated with an encoding (Windows for example). For Windows paths, lone surrogates will be encoded like normal code points and surrogate pairs will be merged before encoding. In case of ``utf-8`` or ``utf-16-le`` this is equal to the `WTF-8 and WTF-16 encoding `__. """ path = _fsn2native(path) if is_win: if encoding is None: raise ValueError("invalid encoding %r" % encoding) if PY2: try: return path.encode(encoding) except LookupError: raise ValueError("invalid encoding %r" % encoding) else: try: return path.encode(encoding) except LookupError: raise ValueError("invalid encoding %r" % encoding) except UnicodeEncodeError: # Fallback implementation for text including surrogates # merge surrogate codepoints if _normalize_codec(encoding).startswith("utf-16"): # fast path, utf-16 merges anyway return path.encode(encoding, _surrogatepass) return _merge_surrogates(path).encode(encoding, _surrogatepass) else: return path def bytes2fsn(data, encoding="utf-8"): """ Args: data (bytes): The data to convert encoding (`str`): encoding used for Windows Returns: `fsnative` Raises: TypeError: If no `bytes` path is passed ValueError: If decoding fails or the encoding is invalid Turns `bytes` to a `fsnative` path. The passed *encoding* is only used on platforms where paths are not associated with an encoding (Windows for example). For Windows paths ``WTF-8`` is accepted if ``utf-8`` is used and ``WTF-16`` accepted if ``utf-16-le`` is used. """ if not isinstance(data, bytes): raise TypeError("data needs to be bytes") if is_win: if encoding is None: raise ValueError("invalid encoding %r" % encoding) try: path = _decode_surrogatepass(data, encoding) except LookupError: raise ValueError("invalid encoding %r" % encoding) if u"\x00" in path: raise ValueError("contains nulls") return path else: if b"\x00" in data: raise ValueError("contains nulls") if PY2: return data else: return data.decode(_encoding, "surrogateescape") def uri2fsn(uri): """ Args: uri (`text` or :obj:`python:str`): A file URI Returns: `fsnative` Raises: TypeError: In case an invalid type is passed ValueError: In case the URI isn't a valid file URI Takes a file URI and returns a `fsnative` path """ if PY2: if isinstance(uri, text_type): uri = uri.encode("utf-8") if not isinstance(uri, bytes): raise TypeError("uri needs to be ascii str or unicode") else: if not isinstance(uri, str): raise TypeError("uri needs to be str") parsed = urlparse(uri) scheme = parsed.scheme netloc = parsed.netloc parsed_path = parsed.path if scheme != "file": raise ValueError("Not a file URI: %r" % uri) if not parsed_path: raise ValueError("Invalid file URI: %r" % uri) uri = urlunparse(parsed)[7:] if is_win: try: drive, rest = uri.split(":", 1) except ValueError: path = "" rest = uri.replace("/", "\\") else: path = drive[-1] + ":" rest = rest.replace("/", "\\") if PY2: path += unquote(rest) else: path += unquote(rest, encoding="utf-8", errors="surrogatepass") if netloc or parsed_path.startswith("//"): path = "\\\\" + path if PY2: path = path.decode("utf-8") if u"\x00" in path: raise ValueError("embedded null") return path else: if PY2: path = unquote(uri) else: path = unquote(uri, encoding=_encoding, errors="surrogateescape") if "\x00" in path: raise ValueError("embedded null") return path def fsn2uri(path): """ Args: path (fsnative): The path to convert to an URI Returns: `text`: An ASCII only URI Raises: TypeError: If no `fsnative` was passed ValueError: If the path can't be converted Takes a `fsnative` path and returns a file URI. On Windows non-ASCII characters will be encoded using utf-8 and then percent encoded. """ path = _fsn2native(path) def _quote_path(path): # RFC 2396 path = quote(path, "/:@&=+$,") if PY2: path = path.decode("ascii") return path if is_win: buf = ctypes.create_unicode_buffer(winapi.INTERNET_MAX_URL_LENGTH) length = winapi.DWORD(winapi.INTERNET_MAX_URL_LENGTH) flags = 0 try: winapi.UrlCreateFromPathW(path, buf, ctypes.byref(length), flags) except WindowsError as e: raise ValueError(e) uri = buf[:length.value] # https://bitbucket.org/pypy/pypy/issues/3133 uri = _merge_surrogates(uri) # For some reason UrlCreateFromPathW escapes some chars outside of # ASCII and some not. Unquote and re-quote with utf-8. if PY3: # latin-1 maps code points directly to bytes, which is what we want uri = unquote(uri, "latin-1") else: # Python 2 does what we want by default uri = unquote(uri) return _quote_path(uri.encode("utf-8", _surrogatepass)) else: return u"file://" + _quote_path(path) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_print.py0000664000175000017500000003011614035600052020547 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import sys import os import ctypes import re from ._fsnative import _encoding, is_win, is_unix, _surrogatepass, bytes2fsn from ._compat import text_type, PY2, PY3 from ._winansi import AnsiState, ansi_split from . import _winapi as winapi def print_(*objects, **kwargs): """print_(*objects, sep=None, end=None, file=None, flush=False) Args: objects (object): zero or more objects to print sep (str): Object separator to use, defaults to ``" "`` end (str): Trailing string to use, defaults to ``"\\n"``. If end is ``"\\n"`` then `os.linesep` is used. file (object): A file-like object, defaults to `sys.stdout` flush (bool): If the file stream should be flushed Raises: EnvironmentError Like print(), but: * Supports printing filenames under Unix + Python 3 and Windows + Python 2 * Emulates ANSI escape sequence support under Windows * Never fails due to encoding/decoding errors. Tries hard to get everything on screen as is, but will fall back to "?" if all fails. This does not conflict with ``colorama``, but will not use it on Windows. """ sep = kwargs.get("sep") sep = sep if sep is not None else " " end = kwargs.get("end") end = end if end is not None else "\n" file = kwargs.get("file") file = file if file is not None else sys.stdout flush = bool(kwargs.get("flush", False)) if is_win: _print_windows(objects, sep, end, file, flush) else: _print_unix(objects, sep, end, file, flush) def _print_unix(objects, sep, end, file, flush): """A print_() implementation which writes bytes""" encoding = _encoding if isinstance(sep, text_type): sep = sep.encode(encoding, "replace") if not isinstance(sep, bytes): raise TypeError if isinstance(end, text_type): end = end.encode(encoding, "replace") if not isinstance(end, bytes): raise TypeError if end == b"\n": end = os.linesep if PY3: end = end.encode("ascii") parts = [] for obj in objects: if not isinstance(obj, text_type) and not isinstance(obj, bytes): obj = text_type(obj) if isinstance(obj, text_type): if PY2: obj = obj.encode(encoding, "replace") else: try: obj = obj.encode(encoding, "surrogateescape") except UnicodeEncodeError: obj = obj.encode(encoding, "replace") assert isinstance(obj, bytes) parts.append(obj) data = sep.join(parts) + end assert isinstance(data, bytes) file = getattr(file, "buffer", file) try: file.write(data) except TypeError: if PY3: # For StringIO, first try with surrogates surr_data = data.decode(encoding, "surrogateescape") try: file.write(surr_data) except (TypeError, ValueError): file.write(data.decode(encoding, "replace")) else: # for file like objects with don't support bytes file.write(data.decode(encoding, "replace")) if flush: file.flush() ansi_state = AnsiState() def _print_windows(objects, sep, end, file, flush): """The windows implementation of print_()""" h = winapi.INVALID_HANDLE_VALUE try: fileno = file.fileno() except (EnvironmentError, AttributeError): pass else: if fileno == 1: h = winapi.GetStdHandle(winapi.STD_OUTPUT_HANDLE) elif fileno == 2: h = winapi.GetStdHandle(winapi.STD_ERROR_HANDLE) encoding = _encoding parts = [] for obj in objects: if isinstance(obj, bytes): obj = obj.decode(encoding, "replace") if not isinstance(obj, text_type): obj = text_type(obj) parts.append(obj) if isinstance(sep, bytes): sep = sep.decode(encoding, "replace") if not isinstance(sep, text_type): raise TypeError if isinstance(end, bytes): end = end.decode(encoding, "replace") if not isinstance(end, text_type): raise TypeError if end == u"\n": end = os.linesep text = sep.join(parts) + end assert isinstance(text, text_type) is_console = True if h == winapi.INVALID_HANDLE_VALUE: is_console = False else: # get the default value info = winapi.CONSOLE_SCREEN_BUFFER_INFO() if not winapi.GetConsoleScreenBufferInfo(h, ctypes.byref(info)): is_console = False if is_console: # make sure we flush before we apply any console attributes file.flush() # try to force a utf-8 code page, use the output CP if that fails cp = winapi.GetConsoleOutputCP() try: encoding = "utf-8" if winapi.SetConsoleOutputCP(65001) == 0: encoding = None for is_ansi, part in ansi_split(text): if is_ansi: ansi_state.apply(h, part) else: if encoding is not None: data = part.encode(encoding, _surrogatepass) else: data = _encode_codepage(cp, part) os.write(fileno, data) finally: # reset the code page to what we had before winapi.SetConsoleOutputCP(cp) else: # try writing bytes first, so in case of Python 2 StringIO we get # the same type on all platforms try: file.write(text.encode("utf-8", _surrogatepass)) except (TypeError, ValueError): file.write(text) if flush: file.flush() def _readline_windows(): """Raises OSError""" try: fileno = sys.stdin.fileno() except (EnvironmentError, AttributeError): fileno = -1 # In case stdin is replaced, read from that if fileno != 0: return _readline_windows_fallback() h = winapi.GetStdHandle(winapi.STD_INPUT_HANDLE) if h == winapi.INVALID_HANDLE_VALUE: return _readline_windows_fallback() buf_size = 1024 buf = ctypes.create_string_buffer(buf_size * ctypes.sizeof(winapi.WCHAR)) read = winapi.DWORD() text = u"" while True: if winapi.ReadConsoleW( h, buf, buf_size, ctypes.byref(read), None) == 0: if not text: return _readline_windows_fallback() raise ctypes.WinError() data = buf[:read.value * ctypes.sizeof(winapi.WCHAR)] text += data.decode("utf-16-le", _surrogatepass) if text.endswith(u"\r\n"): return text[:-2] def _decode_codepage(codepage, data): """ Args: codepage (int) data (bytes) Returns: `text` Decodes data using the given codepage. If some data can't be decoded using the codepage it will not fail. """ assert isinstance(data, bytes) if not data: return u"" # get the required buffer length first length = winapi.MultiByteToWideChar(codepage, 0, data, len(data), None, 0) if length == 0: raise ctypes.WinError() # now decode buf = ctypes.create_unicode_buffer(length) length = winapi.MultiByteToWideChar( codepage, 0, data, len(data), buf, length) if length == 0: raise ctypes.WinError() return buf[:] def _encode_codepage(codepage, text): """ Args: codepage (int) text (text) Returns: `bytes` Encode text using the given code page. Will not fail if a char can't be encoded using that codepage. """ assert isinstance(text, text_type) if not text: return b"" size = (len(text.encode("utf-16-le", _surrogatepass)) // ctypes.sizeof(winapi.WCHAR)) # get the required buffer size length = winapi.WideCharToMultiByte( codepage, 0, text, size, None, 0, None, None) if length == 0: raise ctypes.WinError() # decode to the buffer buf = ctypes.create_string_buffer(length) length = winapi.WideCharToMultiByte( codepage, 0, text, size, buf, length, None, None) if length == 0: raise ctypes.WinError() return buf[:length] def _readline_windows_fallback(): # In case reading from the console failed (maybe we get piped data) # we assume the input was generated according to the output encoding. # Got any better ideas? assert is_win cp = winapi.GetConsoleOutputCP() data = getattr(sys.stdin, "buffer", sys.stdin).readline().rstrip(b"\r\n") return _decode_codepage(cp, data) def _readline_default(): assert is_unix data = getattr(sys.stdin, "buffer", sys.stdin).readline().rstrip(b"\r\n") if PY3: return data.decode(_encoding, "surrogateescape") else: return data def _readline(): if is_win: return _readline_windows() else: return _readline_default() def input_(prompt=None): """ Args: prompt (object): Prints the passed object to stdout without adding a trailing newline Returns: `fsnative` Raises: EnvironmentError Like :func:`python3:input` but returns a `fsnative` and allows printing filenames as prompt to stdout. Use :func:`fsn2text` on the result if you just want to deal with text. """ if prompt is not None: print_(prompt, end="") return _readline() def _get_file_name_for_handle(handle): """(Windows only) Returns a file name for a file handle. Args: handle (winapi.HANDLE) Returns: `text` or `None` if no file name could be retrieved. """ assert is_win assert handle != winapi.INVALID_HANDLE_VALUE size = winapi.FILE_NAME_INFO.FileName.offset + \ winapi.MAX_PATH * ctypes.sizeof(winapi.WCHAR) buf = ctypes.create_string_buffer(size) if winapi.GetFileInformationByHandleEx is None: # Windows XP return None status = winapi.GetFileInformationByHandleEx( handle, winapi.FileNameInfo, buf, size) if status == 0: return None name_info = ctypes.cast( buf, ctypes.POINTER(winapi.FILE_NAME_INFO)).contents offset = winapi.FILE_NAME_INFO.FileName.offset data = buf[offset:offset + name_info.FileNameLength] return bytes2fsn(data, "utf-16-le") def supports_ansi_escape_codes(fd): """Returns whether the output device is capable of interpreting ANSI escape codes when :func:`print_` is used. Args: fd (int): file descriptor (e.g. ``sys.stdout.fileno()``) Returns: `bool` """ if os.isatty(fd): return True if not is_win: return False # Check for cygwin/msys terminal handle = winapi._get_osfhandle(fd) if handle == winapi.INVALID_HANDLE_VALUE: return False if winapi.GetFileType(handle) != winapi.FILE_TYPE_PIPE: return False file_name = _get_file_name_for_handle(handle) match = re.match( "^\\\\(cygwin|msys)-[a-z0-9]+-pty[0-9]+-(from|to)-master$", file_name) return match is not None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_stdlib.py0000664000175000017500000001052614035600052020677 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import re import os from ._fsnative import path2fsn, fsnative, is_win from ._compat import PY2 from ._environ import environ sep = path2fsn(os.sep) pathsep = path2fsn(os.pathsep) curdir = path2fsn(os.curdir) pardir = path2fsn(os.pardir) altsep = path2fsn(os.altsep) if os.altsep is not None else None extsep = path2fsn(os.extsep) devnull = path2fsn(os.devnull) defpath = path2fsn(os.defpath) def getcwd(): """Like `os.getcwd` but returns a `fsnative` path Returns: `fsnative` """ if is_win and PY2: return os.getcwdu() return os.getcwd() def _get_userdir(user=None): """Returns the user dir or None""" if user is not None and not isinstance(user, fsnative): raise TypeError if is_win: if "USERPROFILE" in environ: path = environ["USERPROFILE"] elif "HOMEPATH" in environ and "HOMEDRIVE" in environ: path = os.path.join(environ["HOMEDRIVE"], environ["HOMEPATH"]) else: return path = os.path.normpath(path) if user is None: return path else: return os.path.join(os.path.dirname(path), user) else: import pwd if user is None: if "HOME" in environ: return environ["HOME"] else: try: return path2fsn(pwd.getpwuid(os.getuid()).pw_dir) except KeyError: return else: try: return path2fsn(pwd.getpwnam(user).pw_dir) except KeyError: return def expanduser(path): """ Args: path (pathlike): A path to expand Returns: `fsnative` Like :func:`python:os.path.expanduser` but supports unicode home directories under Windows + Python 2 and always returns a `fsnative`. """ path = path2fsn(path) if path == "~": return _get_userdir() elif path.startswith("~" + sep) or ( altsep is not None and path.startswith("~" + altsep)): userdir = _get_userdir() if userdir is None: return path return userdir + path[1:] elif path.startswith("~"): sep_index = path.find(sep) if altsep is not None: alt_index = path.find(altsep) if alt_index != -1 and alt_index < sep_index: sep_index = alt_index if sep_index == -1: user = path[1:] rest = "" else: user = path[1:sep_index] rest = path[sep_index:] userdir = _get_userdir(user) if userdir is not None: return userdir + rest else: return path else: return path def expandvars(path): """ Args: path (pathlike): A path to expand Returns: `fsnative` Like :func:`python:os.path.expandvars` but supports unicode under Windows + Python 2 and always returns a `fsnative`. """ path = path2fsn(path) def repl_func(match): return environ.get(match.group(1), match.group(0)) path = re.compile(r"\$(\w+)", flags=re.UNICODE).sub(repl_func, path) if os.name == "nt": path = re.sub(r"%([^%]+)%", repl_func, path) return re.sub(r"\$\{([^\}]+)\}", repl_func, path) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_temp.py0000664000175000017500000000632214035600052020362 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import tempfile from ._fsnative import path2fsn, fsnative def gettempdir(): """ Returns: `fsnative` Like :func:`python3:tempfile.gettempdir`, but always returns a `fsnative` path """ # FIXME: I don't want to reimplement all that logic, reading env vars etc. # At least for the default it works. return path2fsn(tempfile.gettempdir()) def gettempprefix(): """ Returns: `fsnative` Like :func:`python3:tempfile.gettempprefix`, but always returns a `fsnative` path """ return path2fsn(tempfile.gettempprefix()) def mkstemp(suffix=None, prefix=None, dir=None, text=False): """ Args: suffix (`pathlike` or `None`): suffix or `None` to use the default prefix (`pathlike` or `None`): prefix or `None` to use the default dir (`pathlike` or `None`): temp dir or `None` to use the default text (bool): if the file should be opened in text mode Returns: Tuple[`int`, `fsnative`]: A tuple containing the file descriptor and the file path Raises: EnvironmentError Like :func:`python3:tempfile.mkstemp` but always returns a `fsnative` path. """ suffix = fsnative() if suffix is None else path2fsn(suffix) prefix = gettempprefix() if prefix is None else path2fsn(prefix) dir = gettempdir() if dir is None else path2fsn(dir) return tempfile.mkstemp(suffix, prefix, dir, text) def mkdtemp(suffix=None, prefix=None, dir=None): """ Args: suffix (`pathlike` or `None`): suffix or `None` to use the default prefix (`pathlike` or `None`): prefix or `None` to use the default dir (`pathlike` or `None`): temp dir or `None` to use the default Returns: `fsnative`: A path to a directory Raises: EnvironmentError Like :func:`python3:tempfile.mkstemp` but always returns a `fsnative` path. """ suffix = fsnative() if suffix is None else path2fsn(suffix) prefix = gettempprefix() if prefix is None else path2fsn(prefix) dir = gettempdir() if dir is None else path2fsn(dir) return tempfile.mkdtemp(suffix, prefix, dir) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1661931628.0 quodlibet-4.6.0/quodlibet/packages/senf/_winansi.py0000644000175000017500000002451714303610154021073 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import ctypes import re import atexit from . import _winapi as winapi def ansi_parse(code): """Returns command, (args)""" return code[-1:], tuple([int(v or "0") for v in code[2:-1].split(";")]) def ansi_split(text, _re=re.compile(u"(\x1b\\[(\\d*;?)*\\S)")): """Yields (is_ansi, text)""" for part in _re.split(text): if part: yield (bool(_re.match(part)), part) class AnsiCommand: TEXT = "m" MOVE_UP = "A" MOVE_DOWN = "B" MOVE_FORWARD = "C" MOVE_BACKWARD = "D" SET_POS = "H" SET_POS_ALT = "f" SAVE_POS = "s" RESTORE_POS = "u" class TextAction: RESET_ALL = 0 SET_BOLD = 1 SET_DIM = 2 SET_ITALIC = 3 SET_UNDERLINE = 4 SET_BLINK = 5 SET_BLINK_FAST = 6 SET_REVERSE = 7 SET_HIDDEN = 8 RESET_BOLD = 21 RESET_DIM = 22 RESET_ITALIC = 23 RESET_UNDERLINE = 24 RESET_BLINK = 25 RESET_BLINK_FAST = 26 RESET_REVERSE = 27 RESET_HIDDEN = 28 FG_BLACK = 30 FG_RED = 31 FG_GREEN = 32 FG_YELLOW = 33 FG_BLUE = 34 FG_MAGENTA = 35 FG_CYAN = 36 FG_WHITE = 37 FG_DEFAULT = 39 FG_LIGHT_BLACK = 90 FG_LIGHT_RED = 91 FG_LIGHT_GREEN = 92 FG_LIGHT_YELLOW = 93 FG_LIGHT_BLUE = 94 FG_LIGHT_MAGENTA = 95 FG_LIGHT_CYAN = 96 FG_LIGHT_WHITE = 97 BG_BLACK = 40 BG_RED = 41 BG_GREEN = 42 BG_YELLOW = 43 BG_BLUE = 44 BG_MAGENTA = 45 BG_CYAN = 46 BG_WHITE = 47 BG_DEFAULT = 49 BG_LIGHT_BLACK = 100 BG_LIGHT_RED = 101 BG_LIGHT_GREEN = 102 BG_LIGHT_YELLOW = 103 BG_LIGHT_BLUE = 104 BG_LIGHT_MAGENTA = 105 BG_LIGHT_CYAN = 106 BG_LIGHT_WHITE = 107 class AnsiState: def __init__(self): self.default_attrs = None self.bold = False self.bg_light = False self.fg_light = False self.saved_pos = (0, 0) def do_text_action(self, attrs, action): # In case the external state has changed, apply it it to ours. # Mostly the first time this is called. if attrs & winapi.FOREGROUND_INTENSITY and not self.fg_light \ and not self.bold: self.fg_light = True if attrs & winapi.BACKGROUND_INTENSITY and not self.bg_light: self.bg_light = True dark_fg = { TextAction.FG_BLACK: 0, TextAction.FG_RED: winapi.FOREGROUND_RED, TextAction.FG_GREEN: winapi.FOREGROUND_GREEN, TextAction.FG_YELLOW: winapi.FOREGROUND_GREEN | winapi.FOREGROUND_RED, TextAction.FG_BLUE: winapi.FOREGROUND_BLUE, TextAction.FG_MAGENTA: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_RED, TextAction.FG_CYAN: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_GREEN, TextAction.FG_WHITE: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_GREEN | winapi.FOREGROUND_RED, } dark_bg = { TextAction.BG_BLACK: 0, TextAction.BG_RED: winapi.BACKGROUND_RED, TextAction.BG_GREEN: winapi.BACKGROUND_GREEN, TextAction.BG_YELLOW: winapi.BACKGROUND_GREEN | winapi.BACKGROUND_RED, TextAction.BG_BLUE: winapi.BACKGROUND_BLUE, TextAction.BG_MAGENTA: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_RED, TextAction.BG_CYAN: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_GREEN, TextAction.BG_WHITE: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_GREEN | winapi.BACKGROUND_RED, } light_fg = { TextAction.FG_LIGHT_BLACK: 0, TextAction.FG_LIGHT_RED: winapi.FOREGROUND_RED, TextAction.FG_LIGHT_GREEN: winapi.FOREGROUND_GREEN, TextAction.FG_LIGHT_YELLOW: winapi.FOREGROUND_GREEN | winapi.FOREGROUND_RED, TextAction.FG_LIGHT_BLUE: winapi.FOREGROUND_BLUE, TextAction.FG_LIGHT_MAGENTA: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_RED, TextAction.FG_LIGHT_CYAN: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_GREEN, TextAction.FG_LIGHT_WHITE: winapi.FOREGROUND_BLUE | winapi.FOREGROUND_GREEN | winapi.FOREGROUND_RED, } light_bg = { TextAction.BG_LIGHT_BLACK: 0, TextAction.BG_LIGHT_RED: winapi.BACKGROUND_RED, TextAction.BG_LIGHT_GREEN: winapi.BACKGROUND_GREEN, TextAction.BG_LIGHT_YELLOW: winapi.BACKGROUND_GREEN | winapi.BACKGROUND_RED, TextAction.BG_LIGHT_BLUE: winapi.BACKGROUND_BLUE, TextAction.BG_LIGHT_MAGENTA: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_RED, TextAction.BG_LIGHT_CYAN: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_GREEN, TextAction.BG_LIGHT_WHITE: winapi.BACKGROUND_BLUE | winapi.BACKGROUND_GREEN | winapi.BACKGROUND_RED, } if action == TextAction.RESET_ALL: attrs = self.default_attrs self.bold = self.fg_light = self.bg_light = False elif action == TextAction.SET_BOLD: self.bold = True elif action == TextAction.RESET_BOLD: self.bold = False elif action == TextAction.SET_DIM: self.bold = False elif action == TextAction.SET_REVERSE: attrs |= winapi.COMMON_LVB_REVERSE_VIDEO elif action == TextAction.RESET_REVERSE: attrs &= ~winapi.COMMON_LVB_REVERSE_VIDEO elif action == TextAction.SET_UNDERLINE: attrs |= winapi.COMMON_LVB_UNDERSCORE elif action == TextAction.RESET_UNDERLINE: attrs &= ~winapi.COMMON_LVB_UNDERSCORE elif action == TextAction.FG_DEFAULT: attrs = (attrs & ~0xF) | (self.default_attrs & 0xF) self.fg_light = False elif action == TextAction.BG_DEFAULT: attrs = (attrs & ~0xF0) | (self.default_attrs & 0xF0) self.bg_light = False elif action in dark_fg: attrs = (attrs & ~0xF) | dark_fg[action] self.fg_light = False elif action in dark_bg: attrs = (attrs & ~0xF0) | dark_bg[action] self.bg_light = False elif action in light_fg: attrs = (attrs & ~0xF) | light_fg[action] self.fg_light = True elif action in light_bg: attrs = (attrs & ~0xF0) | light_bg[action] self.bg_light = True if self.fg_light or self.bold: attrs |= winapi.FOREGROUND_INTENSITY else: attrs &= ~winapi.FOREGROUND_INTENSITY if self.bg_light: attrs |= winapi.BACKGROUND_INTENSITY else: attrs &= ~winapi.BACKGROUND_INTENSITY return attrs def apply(self, handle, code): buffer_info = winapi.CONSOLE_SCREEN_BUFFER_INFO() if not winapi.GetConsoleScreenBufferInfo(handle, ctypes.byref(buffer_info)): return attrs = buffer_info.wAttributes # We take the first attrs we see as default if self.default_attrs is None: self.default_attrs = attrs # Make sure that like with linux terminals the program doesn't # affect the prompt after it exits atexit.register( winapi.SetConsoleTextAttribute, handle, self.default_attrs) cmd, args = ansi_parse(code) if cmd == AnsiCommand.TEXT: for action in args: attrs = self.do_text_action(attrs, action) winapi.SetConsoleTextAttribute(handle, attrs) elif cmd in (AnsiCommand.MOVE_UP, AnsiCommand.MOVE_DOWN, AnsiCommand.MOVE_FORWARD, AnsiCommand.MOVE_BACKWARD): coord = buffer_info.dwCursorPosition x, y = coord.X, coord.Y amount = max(args[0], 1) if cmd == AnsiCommand.MOVE_UP: y -= amount elif cmd == AnsiCommand.MOVE_DOWN: y += amount elif cmd == AnsiCommand.MOVE_FORWARD: x += amount elif cmd == AnsiCommand.MOVE_BACKWARD: x -= amount x = max(x, 0) y = max(y, 0) winapi.SetConsoleCursorPosition(handle, winapi.COORD(x, y)) elif cmd in (AnsiCommand.SET_POS, AnsiCommand.SET_POS_ALT): args = list(args) while len(args) < 2: args.append(0) x, y = args[:2] win_rect = buffer_info.srWindow x += win_rect.Left - 1 y += win_rect.Top - 1 x = max(x, 0) y = max(y, 0) winapi.SetConsoleCursorPosition(handle, winapi.COORD(x, y)) elif cmd == AnsiCommand.SAVE_POS: win_rect = buffer_info.srWindow coord = buffer_info.dwCursorPosition x, y = coord.X, coord.Y x -= win_rect.Left y -= win_rect.Top self.saved_pos = (x, y) elif cmd == AnsiCommand.RESTORE_POS: win_rect = buffer_info.srWindow x, y = self.saved_pos x += win_rect.Left y += win_rect.Top winapi.SetConsoleCursorPosition(handle, winapi.COORD(x, y)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/senf/_winapi.py0000664000175000017500000001605014035600052020703 0ustar00nicknick# -*- coding: utf-8 -*- # Copyright 2016 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import sys import ctypes if sys.platform == 'win32': from ctypes import WinDLL, CDLL, wintypes shell32 = WinDLL("shell32") kernel32 = WinDLL("kernel32") shlwapi = WinDLL("shlwapi") msvcrt = CDLL("msvcrt") GetCommandLineW = kernel32.GetCommandLineW GetCommandLineW.argtypes = [] GetCommandLineW.restype = wintypes.LPCWSTR CommandLineToArgvW = shell32.CommandLineToArgvW CommandLineToArgvW.argtypes = [ wintypes.LPCWSTR, ctypes.POINTER(ctypes.c_int)] CommandLineToArgvW.restype = ctypes.POINTER(wintypes.LPWSTR) LocalFree = kernel32.LocalFree LocalFree.argtypes = [wintypes.HLOCAL] LocalFree.restype = wintypes.HLOCAL # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx LPCTSTR = ctypes.c_wchar_p LPWSTR = wintypes.LPWSTR LPCWSTR = ctypes.c_wchar_p LPTSTR = LPWSTR PCWSTR = ctypes.c_wchar_p PCTSTR = PCWSTR PWSTR = ctypes.c_wchar_p PTSTR = PWSTR LPVOID = wintypes.LPVOID WCHAR = wintypes.WCHAR LPSTR = ctypes.c_char_p BOOL = wintypes.BOOL LPBOOL = ctypes.POINTER(BOOL) UINT = wintypes.UINT WORD = wintypes.WORD DWORD = wintypes.DWORD SHORT = wintypes.SHORT HANDLE = wintypes.HANDLE ULONG = wintypes.ULONG LPCSTR = wintypes.LPCSTR STD_INPUT_HANDLE = DWORD(-10) STD_OUTPUT_HANDLE = DWORD(-11) STD_ERROR_HANDLE = DWORD(-12) INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value INTERNET_MAX_SCHEME_LENGTH = 32 INTERNET_MAX_PATH_LENGTH = 2048 INTERNET_MAX_URL_LENGTH = ( INTERNET_MAX_SCHEME_LENGTH + len("://") + INTERNET_MAX_PATH_LENGTH) FOREGROUND_BLUE = 0x0001 FOREGROUND_GREEN = 0x0002 FOREGROUND_RED = 0x0004 FOREGROUND_INTENSITY = 0x0008 BACKGROUND_BLUE = 0x0010 BACKGROUND_GREEN = 0x0020 BACKGROUND_RED = 0x0040 BACKGROUND_INTENSITY = 0x0080 COMMON_LVB_REVERSE_VIDEO = 0x4000 COMMON_LVB_UNDERSCORE = 0x8000 UrlCreateFromPathW = shlwapi.UrlCreateFromPathW UrlCreateFromPathW.argtypes = [ PCTSTR, PTSTR, ctypes.POINTER(DWORD), DWORD] UrlCreateFromPathW.restype = ctypes.HRESULT SetEnvironmentVariableW = kernel32.SetEnvironmentVariableW SetEnvironmentVariableW.argtypes = [LPCTSTR, LPCTSTR] SetEnvironmentVariableW.restype = wintypes.BOOL GetEnvironmentVariableW = kernel32.GetEnvironmentVariableW GetEnvironmentVariableW.argtypes = [LPCTSTR, LPTSTR, DWORD] GetEnvironmentVariableW.restype = DWORD GetEnvironmentStringsW = kernel32.GetEnvironmentStringsW GetEnvironmentStringsW.argtypes = [] GetEnvironmentStringsW.restype = ctypes.c_void_p FreeEnvironmentStringsW = kernel32.FreeEnvironmentStringsW FreeEnvironmentStringsW.argtypes = [ctypes.c_void_p] FreeEnvironmentStringsW.restype = ctypes.c_bool GetStdHandle = kernel32.GetStdHandle GetStdHandle.argtypes = [DWORD] GetStdHandle.restype = HANDLE class COORD(ctypes.Structure): _fields_ = [ ("X", SHORT), ("Y", SHORT), ] class SMALL_RECT(ctypes.Structure): _fields_ = [ ("Left", SHORT), ("Top", SHORT), ("Right", SHORT), ("Bottom", SHORT), ] class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): _fields_ = [ ("dwSize", COORD), ("dwCursorPosition", COORD), ("wAttributes", WORD), ("srWindow", SMALL_RECT), ("dwMaximumWindowSize", COORD), ] GetConsoleScreenBufferInfo = kernel32.GetConsoleScreenBufferInfo GetConsoleScreenBufferInfo.argtypes = [ HANDLE, ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)] GetConsoleScreenBufferInfo.restype = BOOL GetConsoleOutputCP = kernel32.GetConsoleOutputCP GetConsoleOutputCP.argtypes = [] GetConsoleOutputCP.restype = UINT SetConsoleOutputCP = kernel32.SetConsoleOutputCP SetConsoleOutputCP.argtypes = [UINT] SetConsoleOutputCP.restype = BOOL GetConsoleCP = kernel32.GetConsoleCP GetConsoleCP.argtypes = [] GetConsoleCP.restype = UINT SetConsoleCP = kernel32.SetConsoleCP SetConsoleCP.argtypes = [UINT] SetConsoleCP.restype = BOOL SetConsoleTextAttribute = kernel32.SetConsoleTextAttribute SetConsoleTextAttribute.argtypes = [HANDLE, WORD] SetConsoleTextAttribute.restype = BOOL SetConsoleCursorPosition = kernel32.SetConsoleCursorPosition SetConsoleCursorPosition.argtypes = [HANDLE, COORD] SetConsoleCursorPosition.restype = BOOL ReadConsoleW = kernel32.ReadConsoleW ReadConsoleW.argtypes = [ HANDLE, LPVOID, DWORD, ctypes.POINTER(DWORD), LPVOID] ReadConsoleW.restype = BOOL MultiByteToWideChar = kernel32.MultiByteToWideChar MultiByteToWideChar.argtypes = [ UINT, DWORD, LPCSTR, ctypes.c_int, LPWSTR, ctypes.c_int] MultiByteToWideChar.restype = ctypes.c_int WideCharToMultiByte = kernel32.WideCharToMultiByte WideCharToMultiByte.argtypes = [ UINT, DWORD, LPCWSTR, ctypes.c_int, LPSTR, ctypes.c_int, LPCSTR, LPBOOL] WideCharToMultiByte.restype = ctypes.c_int MoveFileW = kernel32.MoveFileW MoveFileW.argtypes = [LPCTSTR, LPCTSTR] MoveFileW.restype = BOOL GetFileInformationByHandleEx = None if hasattr(kernel32, "GetFileInformationByHandleEx"): GetFileInformationByHandleEx = kernel32.GetFileInformationByHandleEx GetFileInformationByHandleEx.argtypes = [ HANDLE, ctypes.c_int, ctypes.c_void_p, DWORD] GetFileInformationByHandleEx.restype = BOOL else: # Windows XP pass MAX_PATH = 260 FileNameInfo = 2 class FILE_NAME_INFO(ctypes.Structure): _fields_ = [ ("FileNameLength", DWORD), ("FileName", WCHAR), ] _get_osfhandle = msvcrt._get_osfhandle _get_osfhandle.argtypes = [ctypes.c_int] _get_osfhandle.restype = HANDLE GetFileType = kernel32.GetFileType GetFileType.argtypes = [HANDLE] GetFileType.restype = DWORD FILE_TYPE_PIPE = 0x0003 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/packages/update.sh0000775000175000017500000000064214035600052017571 0ustar00nicknick#!/bin/bash set -e DIR="$( cd "$( dirname "$0" )" && pwd )" rm -Rf "senf" pip3 install --system --no-compile --no-deps --target="$DIR/tmp" "senf==1.5.0" mv "$DIR/tmp/senf" "$DIR" rm -R "$DIR/tmp" rm "$DIR/senf/py.typed" rm -Rf "raven" pip3 install --system --no-compile --no-deps --target="$DIR/tmp" "raven==6.5.0" mv "$DIR/tmp/raven" "$DIR" rm -R "$DIR/tmp" rm -R "$DIR/raven/contrib/" rm -R "$DIR/raven/data/" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/pattern/0000755000175000017500000000000014471213412015647 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/pattern/__init__.py0000664000175000017500000000100714035600052017754 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. from ._pattern import (Pattern, FileFromPattern, XMLFromPattern, XMLFromMarkupPattern, error, ArbitraryExtensionFileFromPattern, URLFromPattern) URLFromPattern ArbitraryExtensionFileFromPattern FileFromPattern Pattern XMLFromMarkupPattern XMLFromPattern error ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1665307309.0 quodlibet-4.6.0/quodlibet/pattern/_pattern.py0000644000175000017500000003676014320511255020050 0ustar00nicknick# Copyright 2004-2010 Joe Wreschnig, Michael Urman # Copyright 2010,2013 Christoph Reiter # Copyright 2013-2015 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. # Pattern := ( | )* # String := ([^<>|\\]|\\.)+, a string # Tags := "<" String [ "|" Pattern [ "|" Pattern ] ] ">" import os import re from collections import OrderedDict from re import Scanner # type: ignore from urllib.parse import quote_plus from senf import fsnative from quodlibet import util from quodlibet.query import Query from quodlibet.util.path import strip_win32_incompat_from_path, limit_path from quodlibet.formats._audio import decode_value, FILESYSTEM_TAGS # Token types. (OPEN, CLOSE, TEXT, COND, EOF) = range(5) class error(ValueError): pass class ParseError(error): pass class LexerError(error): pass class PatternLexeme: _reverse = {OPEN: "OPEN", CLOSE: "CLOSE", TEXT: "TEXT", COND: "COND", EOF: "EOF"} def __init__(self, typ, lexeme): self.type = typ self.lexeme = lexeme def __repr__(self): return (super().__repr__().split()[0] + " type=" + repr(self.type) + " (" + str(self._reverse[self.type]) + "), lexeme=" + repr(self.lexeme) + ">") class PatternLexer(Scanner): def __init__(self, s): self.string = s Scanner.__init__(self, [(r"([^<>|\\]|\\.)+", self.text), (r"[<>|]", self.table), ]) def text(self, scanner, string): return PatternLexeme(TEXT, re.sub(r"\\([|<>\\])", r"\1", string)) def table(self, scanner, string): return PatternLexeme( {"|": COND, "<": OPEN, ">": CLOSE}[string], string) def __iter__(self): s = self.scan(self.string) if s[1] != "": raise LexerError("characters left over in string") else: return iter(s[0] + [PatternLexeme(EOF, "")]) class PatternNode: def __init__(self): self.children = [] def __repr__(self): return "Pattern(%s)" % (", ".join(map(repr, self.children))) class TextNode: def __init__(self, text): self.text = text def __repr__(self): return "Text(\"%s\")" % self.text class ConditionNode: def __init__(self, expr, ifcase, elsecase): self.expr = expr self.ifcase = ifcase self.elsecase = elsecase def __repr__(self): t, i, e = self.expr, repr(self.ifcase), repr(self.elsecase) return "Condition(expression: \"%s\", if: %s, else: %s)" % (t, i, e) class TagNode: def __init__(self, tag): self.tag = tag def __repr__(self): return "Tag(\"%s\")" % self.tag class PatternParser: def __init__(self, tokens): self.tokens = iter(tokens) self.lookahead = next(self.tokens) self.node = self.Pattern() def Pattern(self): node = PatternNode() while self.lookahead.type in [OPEN, TEXT]: la = self.lookahead self.match(TEXT, OPEN) if la.type == TEXT: node.children.append(TextNode(la.lexeme)) elif la.type == OPEN: node.children.extend(self.Tags()) return node def Tags(self): nodes = [] tag = self.lookahead.lexeme # fix bad tied tags if tag[:1] != "~" and "~" in tag: tag = "~" + tag try: self.match(TEXT) except ParseError: while self.lookahead.type not in [CLOSE, EOF]: self.match(self.lookahead.type) return nodes if self.lookahead.type == COND: self.match(COND) ifcase = self.Pattern() if self.lookahead.type == COND: self.match(COND) elsecase = self.Pattern() else: elsecase = None nodes.append(ConditionNode(tag, ifcase, elsecase)) try: self.match(CLOSE) except ParseError: nodes.pop(-1) while self.lookahead.type not in [EOF, OPEN]: self.match(self.lookahead.type) else: nodes.append(TagNode(tag)) try: self.match(CLOSE) except ParseError: nodes.pop(-1) while self.lookahead.type not in [EOF, OPEN]: self.match(self.lookahead.type) return nodes def match(self, *tokens): if tokens != [EOF] and self.lookahead.type == EOF: raise ParseError("The search string ended, but more " "tokens were expected.") try: if self.lookahead.type in tokens: self.lookahead = next(self.tokens) else: raise ParseError("The token '%s' is not the type expected." % ( self.lookahead.lexeme)) except StopIteration: self.lookahead = PatternLexeme(EOF, "") class PatternFormatter: _format = None _post = None _text = None def __init__(self, func, list_func, tags): self.__func = func self.__list_func = list_func self.tags = util.list_unique(tags) self.format(self.Dummy()) # Validate string class Dummy(dict): def __call__(self, key, *args): if key in FILESYSTEM_TAGS: return fsnative(u"_") if key[:2] == "~#" and "~" not in key[2:]: return 0 return u"_" def comma(self, key, *args): return u"_" def list_separate(self, key): return [u""] class SongProxy: def __init__(self, realsong, formatter): self.__song = realsong self.__formatter = formatter def __call__(self, key, *args): return self.__song(key, *args) def get(self, key, default=None): return self.__song.get(key, default) def comma(self, key): value = self.__song.comma(key) if isinstance(value, (int, float)): value = decode_value(key, value) if self.__formatter: return self.__formatter(key, value) return value def list_separate(self, key): if key.startswith("~#") and "~" not in key[2:]: value = self.__song(key) value = decode_value(key, value) if self.__formatter: value = self.__formatter(key, value) values = [(value, value)] else: values = self.__song.list_separate(key) if self.__formatter: return [(self.__formatter(key, v[0]), self.__formatter(key, v[1])) for v in values] return values def format(self, song): value = u"".join(self.__func(self.SongProxy(song, self._format))) if self._post: return self._post(value, song) return value def format_list(self, song): """Formats the output of a list pattern, generating all the combinations always returns pairs of display and sort values. The returned set will never be empty (e.g. for an empty pattern). """ vals = [(u"", u"")] for val in self.__list_func(self.SongProxy(song, self._format)): if not val: continue if isinstance(val, list): # list of strings or pairs vals = [(r[0] + part[0], r[1] + part[1]) for part in val for r in vals] else: # just a display string to concatenate vals = [(r[0] + val, r[1] + val) for r in vals] if self._post: vals = ((self._post(v[0], song), self._post(v[1], song)) for v in vals) return set(vals) __mod__ = format class PatternCompiler: def __init__(self, root): self.__root = root.node def compile(self, song_func, text_formatter=None): tags = [] queries = {} content = [ "def f(s):", " x = s." + song_func, " r = []", " a = r.append"] content.extend( self.__tag(self.__root, {}, {}, tags, queries, text_formatter)) content.append(" return r") code = "\n".join(content) scope = dict(queries.values()) if text_formatter: scope["_format"] = text_formatter exec(compile(code, "", "exec"), scope) return scope["f"], tags def __get_value(self, text, scope, tag): if tag not in scope: t_var = 'v%d' % len(scope) scope[tag] = t_var text.append('%s = x(%r)' % (t_var, tag)) else: t_var = scope[tag] return t_var def __get_query(self, text, scope, qscope, query, queries): if query not in qscope: if query in queries: q_var = queries[query][0] r_var = 'r%d' % len(qscope) text.append('%s = %s(s)' % (r_var, q_var)) qscope[query] = r_var else: q = Query.StrictQueryMatcher(query) if q is not None: q_var = 'q%d' % len(queries) r_var = 'r%d' % len(qscope) queries[query] = (q_var, q.search) text.append('%s = %s(s)' % (r_var, q_var)) qscope[query] = r_var else: r_var = self.__get_value(text, scope, query) else: r_var = qscope[query] return r_var def __tag(self, node, scope, qscope, tags, queries, text_formatter): text = [] if isinstance(node, TextNode): if text_formatter: text.append('a(_format(%r))' % node.text) else: text.append('a(%r)' % node.text) elif isinstance(node, ConditionNode): var = self.__get_query(text, scope, qscope, node.expr, queries) ic = self.__tag( node.ifcase, dict(scope), dict(qscope), tags, queries, text_formatter) ec = self.__tag( node.elsecase, dict(scope), dict(qscope), tags, queries, text_formatter) if not ic and not ec: text.pop(-1) elif ic: text.append('if %s:' % var) text.extend(ic) if ec: text.append('else:') text.extend(ec) else: text.append('if not %s:' % var) text.extend(ec) elif isinstance(node, TagNode): tags.extend(util.tagsplit(node.tag)) var = self.__get_value(text, scope, node.tag) text.append('a(%s)' % var) elif isinstance(node, PatternNode): for child in node.children: for line in self.__tag(child, scope, qscope, tags, queries, text_formatter): text.append(" " + line) return text def Pattern(string, Kind=PatternFormatter, MAX_CACHE_SIZE=100, cache=OrderedDict()): if (Kind, string) not in cache: while len(cache) >= MAX_CACHE_SIZE: cache.popitem(last=False) comp = PatternCompiler(PatternParser(PatternLexer(string))) func, tags = comp.compile("comma", Kind._text) list_func, tags = comp.compile("list_separate", Kind._text) cache[(Kind, string)] = Kind(func, list_func, tags) else: # promote recently accessed items to front of cache cache.move_to_end((Kind, string)) return cache[(Kind, string)] def _number(key, value): if key == "tracknumber": parts = value.split("/") try: decimals = len(str(int(parts[1]))) except (IndexError, ValueError): decimals = 2 try: return "%0*d" % (max(2, decimals), int(parts[0])) except (TypeError, ValueError): return value elif key == "discnumber": parts = value.split("/") try: return "%02d" % int(parts[0]) except (TypeError, ValueError): return value else: return value class _FileFromPattern(PatternFormatter): def _format(self, key, value): value = _number(key, value) value = value.replace(os.sep, "_") value = value.replace(u"\uff0f", "_") value = value.strip() return value def _post(self, value, song, keep_extension=True): if value: assert isinstance(value, str) value = fsnative(value) if keep_extension: fn = song.get("~filename", ".") ext = fn[fn.rfind("."):].lower() val_ext = value[-len(ext):].lower() if not ext == val_ext: value += ext.lower() if os.name == "nt": assert isinstance(value, str) value = strip_win32_incompat_from_path(value) value = os.path.expanduser(value) value = limit_path(value) if os.sep in value and not os.path.isabs(value): raise ValueError("Pattern is not rooted") return value else: return fsnative(value) class _ArbitraryExtensionFileFromPattern(_FileFromPattern): """Allows filename-like output with extensions different from the song.""" def _post(self, value, song, keep_extension=False): return super()._post(value, song, keep_extension) class _XMLFromPattern(PatternFormatter): def _format(self, key, value): return util.escape(value) def replace_nt_seps(string): """On Windows, users may use backslashes in patterns as path separators. Since Windows filenames can't use '<>|' anyway, preserving backslash escapes is unnecessary, so we just replace them blindly.""" return string.replace("\\", r"\\") if os.name == 'nt' else string def FileFromPattern(string): """Gives fsnative, not unicode""" return Pattern(replace_nt_seps(string), _FileFromPattern) def ArbitraryExtensionFileFromPattern(string): return Pattern(replace_nt_seps(string), _ArbitraryExtensionFileFromPattern) def XMLFromPattern(string): return Pattern(string, _XMLFromPattern) class _XMLFromMarkupPattern(_XMLFromPattern): @classmethod def _text(cls, string): tags = ["b", "big", "i", "s", "sub", "sup", "small", "tt", "u", "span", "a"] pat = "(?:%s)" % "|".join(tags) def repl_func(match): orig, pre, body = match.group(0, 1, 2) if len(pre) % 2: return orig[1:] return r"%s<%s>" % (pre, body) string = re.sub(r"(\\*)\[(/?%s\s*)\]" % pat, repl_func, string) string = re.sub(r"(\\*)\[((a|span)\s+.*?)\]", repl_func, string) return string def XMLFromMarkupPattern(string): """Like XMLFromPattern but allows using [] instead of \\<\\> for pango markup to get rid of all the escaping in the common case. To get text like "[b]" escape the first '[' like "\\[b]" """ return Pattern(string, _XMLFromMarkupPattern) class _URLFromPattern(PatternFormatter): def _format(self, key, value): return quote_plus(value.encode('utf8')) def URLFromPattern(string): return Pattern(string, _URLFromPattern) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/player/0000755000175000017500000000000014471213412015466 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/player/__init__.py0000664000175000017500000000341014035600052017573 0ustar00nicknick# Copyright 2007 Joe Wreschnig # 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import importlib from quodlibet import util class PlayerError(Exception): """Error raised by player loading/initialization and emitted by the error signal during playback. Both short_desc and long_desc are meant for displaying in the UI. They should be unicode. """ def __init__(self, short_desc, long_desc=None): self.short_desc = short_desc self.long_desc = long_desc def __str__(self): return self.short_desc + ( u"\n" + self.long_desc if self.long_desc else u"") def __bytes__(self): return str(self).encode('utf-8') def __repr__(self): return "%s(%r, %r)" % ( type(self).__name__, repr(self.short_desc), repr(self.long_desc)) def init_player(backend_name, librarian): """Loads the specified backend and initializes it. Returns a BasePlayer implementation instance. Raises PlayerError in case of an error. """ backend = init_backend(backend_name) return backend.init(librarian) def init_backend(backend_name): """Imports the player backend module for the given name. Raises PlayerError if the import fails. the module provides the following functions: init(librarian) -> new player instance """ modulename = "quodlibet.player." + backend_name try: backend = importlib.import_module(modulename) except ImportError as e: util.reraise(PlayerError, str(e)) else: return backend ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1663102510.0 quodlibet-4.6.0/quodlibet/player/_base.py0000644000175000017500000002242514310167056017122 0ustar00nicknick# Copyright 2007-2008 Joe Wreschnig # 2009,2010 Steven Robertson # 2009-2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from typing import List from gi.repository import GObject from quodlibet.formats import AudioFile from quodlibet.util import print_d, format_time from quodlibet import config class Equalizer: _eq_values: List[int] = [] @property def eq_bands(self): """read-only list of equalizer bands (in Hz) supported.""" return [] @property def eq_values(self): """The list of equalizer values, in the range (-24dB, 12dB).""" return self._eq_values @eq_values.setter def eq_values(self, value): self._eq_values[:] = value self.update_eq_values() def update_eq_values(self): """Override to apply equalizer values""" pass class BasePlayer(GObject.GObject, Equalizer): """Interfaces between a QL PlaylistModel and a GSt playbin. Attributes: paused -- True or False, set to pause/unpause the player volume -- current volume, 0.0 to 1.0 song -- current song, or None if not playing info -- current stream information, or None if not playing. This is usually the same as song, unless the user is listening to a stream with multiple songs in it. If you're going to show things, use .info. If you're going to change things, use .song. """ name = "" version_info = "" song = None info = None # if the current song couldn't be played because of an error # gets reset automatically after 'song-ended' gets emitted error = False # Replay Gain profiles are a list of values to be tried in order; # Four things can set them: rg menu, browser, play order, and a default. replaygain_profiles = [None, None, None, ["none"]] _paused = True _source = None __gsignals__ = { 'song-started': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'song-ended': (GObject.SignalFlags.RUN_LAST, None, (object, bool)), 'seek': (GObject.SignalFlags.RUN_LAST, None, (object, int)), 'paused': (GObject.SignalFlags.RUN_LAST, None, ()), 'unpaused': (GObject.SignalFlags.RUN_LAST, None, ()), # (song, PlayerError) 'error': (GObject.SignalFlags.RUN_LAST, None, (object, object)), } __gproperties__ = { 'volume': (float, 'player volume', 'the volume of the player', 0.0, 1.0, 1.0, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), 'seekable': (bool, 'seekable', 'if the stream is seekable', True, GObject.ParamFlags.READABLE), 'mute': (bool, 'mute', 'if the stream is muted', False, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } def __init__(self, *args, **kwargs): super().__init__() def destroy(self): """Free resources""" if self.song is not self.info: self.emit("song-ended", self.info, True) self.emit("song-ended", self.song, True) self._source = None self._destroy() def calc_replaygain_volume(self, volume): """Returns a new float volume for the given volume. Takes into account the global active replaygain profile list, the user specified replaygain settings and the tags available for that song. Args: volume (float): 0.0..1.0 Returns: float: adjusted volume, can be outside 0.0..0.1 """ if self.song and config.getboolean("player", "replaygain"): profiles = list(filter(None, self.replaygain_profiles))[0] fb_gain = config.getfloat("player", "fallback_gain") pa_gain = config.getfloat("player", "pre_amp_gain") scale = self.song.replay_gain(profiles, pa_gain, fb_gain) else: scale = 1 return volume * scale def _reset_replaygain(self): self.volume = self.volume def reset_replaygain(self): """Call in case something affecting the replaygain adjustment has changed to change the output volume """ self._reset_replaygain() @property def has_external_volume(self): """If setting the volume will affect anything outside of QL and if the volume can change without any event in QL. """ return False @property def volume(self): """Use a cubic scale for the externally exposed volume""" return self.props.volume ** (1.0 / 3.0) @volume.setter def volume(self, v): self.props.volume = min(1.0, max(0.0, v ** 3.0)) @property def mute(self): return self.props.mute @mute.setter def mute(self, v): self.props.mute = v @property def paused(self): raise NotImplementedError @property def seekable(self): """If the current song can be seeked, in case it's not clear defaults to True. See the "seekable" GObject property for notifications. """ return self.props.seekable def _destroy(self): """Clean up""" raise NotImplementedError def _end(self, stopped, next_song=None): """Start playing the current song from the source or next_song if it isn't None. """ raise NotImplementedError def setup(self, source, song, seek_pos, explicit=True): """Connect to a PlaylistModel, and load a song. seek_pos in millisecs """ assert source is not None if self._source is None: self.emit("song-started", song) self._source = source self.go_to(song, explicit) if seek_pos: self.seek(seek_pos) def seek(self, position): """Seek to absolute position in milliseconds. If position is larger than the duration start the next song """ raise NotImplementedError def sync(self, timeout): """Tries to finish any pending operations. Mainly for testing. timeout in seconds. """ pass def get_position(self): """The current position in milliseconds""" raise NotImplementedError def remove(self, song): """Make sure the song isn't played anymore""" if song and self.song is song: self._source.next() self._end(True) def stop(self): """Stop playback and reset the position. Might release the audio device """ self.paused = True self.seek(0) def play(self): """If a song is active then unpause else reset the source and start playing. """ if self.song is None: self._reset() else: self.paused = False def playpause(self): """If a song is active then toggle the pause mode else reset the source and start playing. """ if self.song is None: self._reset() else: self.paused ^= True def _reset(self): """Reset the source and start playing if possible""" self._source.reset() if self._source.current is not None: self._end(True) if self.song: self.paused = False def next(self): """Move to the next song""" self._source.next() self._end(True) if self.song: self.paused = False def previous(self, force=False): """Go back if standing at the beginning of the song otherwise restart the current song. If force is True always go back. """ if force or self.get_position() < 1500 or not self.seekable: self._source.previous() self._end(True) else: self.seek(0) if self.song: self.paused = False def go_to(self, song_or_iter, explicit=False, source=None): """Activate the song or iter in the playlist if possible and play it. Explicit if the action comes from the user. Returns True if there is an active song after the call returns. """ print_d("Going to %r" % getattr(song_or_iter, "key", song_or_iter)) if self._source.go_to(song_or_iter, explicit, source): self._end(True) else: if isinstance(song_or_iter, AudioFile): self._end(True, song_or_iter) else: # FIXME: this is for the queue only plugin. the play order # should return if it has handled set() itself instead if explicit: return self._end(True) return self.song is not None def can_play_uri(self, uri): """Whether the player supports playing the given URI scheme""" raise NotImplementedError def with_elapsed_info(self, song: AudioFile) -> AudioFile: """Enhance the passed song with elapsed time information""" seconds = self.get_position() / 1000 cs = AudioFile(song) cs["~#elapsed"] = seconds cs["~elapsed"] = format_time(seconds) return cs ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0009356 quodlibet-4.6.0/quodlibet/player/gstbe/0000755000175000017500000000000014471213412016572 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/player/gstbe/__init__.py0000664000175000017500000000061614035600052020704 0ustar00nicknick# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Steven Robertson, # 2011-2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .player import init init = init ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1666468141.0 quodlibet-4.6.0/quodlibet/player/gstbe/player.py0000644000175000017500000010770514325044455020461 0ustar00nicknick# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Steven Robertson, # 2011-2014 Christoph Reiter # 2020-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import gi try: gi.require_version("Gst", "1.0") gi.require_version("GstPbutils", "1.0") except ValueError as e: raise ImportError(e) from gi.repository import Gst, GLib, GstPbutils from quodlibet import const from quodlibet import config from quodlibet import util from quodlibet import app from quodlibet import _ from quodlibet.util import fver, sanitize_tags, MainRunner, MainRunnerError, \ MainRunnerAbortedError, MainRunnerTimeoutError, print_w, print_d, \ print_e, print_ from quodlibet.util.path import uri2gsturi from quodlibet.player import PlayerError from quodlibet.player._base import BasePlayer from quodlibet.qltk.notif import Task from quodlibet.formats.mod import ModFile from .util import (parse_gstreamer_taglist, TagListWrapper, iter_to_list, GStreamerSink, link_many, bin_debug, AudioSinks) from .plugins import GStreamerPluginHandler from .prefs import GstPlayerPreferences STATE_CHANGE_TIMEOUT = Gst.SECOND * 4 const.MinVersions.GSTREAMER.check(Gst.version()) class BufferingWrapper: """A wrapper for a Gst.Element (usually GstPlayBin) which pauses the elmement in case buffering is needed, but hides the fact that it does. Probably not perfect... You have to call destroy() before it gets gc'd """ def __init__(self, bin_, player): """ bin_ -- the GstPlaybin instance to wrap player -- the GStreamerPlayer instance used for aborting the buffer process """ self.bin = bin_ self._wanted_state = None self._task = None self._inhibit_play = False self._player = player bus = self.bin.get_bus() bus.add_signal_watch() self.__bus_id = bus.connect('message', self.__message) def __message(self, bus, message): if message.type == Gst.MessageType.BUFFERING: percent = message.parse_buffering() self.__update_buffering(percent) def __getattr__(self, name): return getattr(self.bin, name) def __update_buffering(self, percent): """Call this with buffer percent values from the bus""" if self._task: self._task.update(percent / 100.0) self.__set_inhibit_play(percent < 100) def __set_inhibit_play(self, inhibit): """Change the inhibit state""" if inhibit == self._inhibit_play: return self._inhibit_play = inhibit # task management if inhibit: if not self._task: def stop_buf(*args): self._player.paused = True self._task = Task(_("Stream"), _("Buffering"), stop=stop_buf) elif self._task: self._task.finish() self._task = None # state management if inhibit: # save the current state status, state, pending = self.bin.get_state( timeout=STATE_CHANGE_TIMEOUT) if status == Gst.StateChangeReturn.SUCCESS and \ state == Gst.State.PLAYING: self._wanted_state = state else: # no idea, at least don't play self._wanted_state = Gst.State.PAUSED self.bin.set_state(Gst.State.PAUSED) else: # restore the old state self.bin.set_state(self._wanted_state) self._wanted_state = None def set_state(self, state): if self._inhibit_play: # PLAYING, PAUSED change the state for after buffering is finished, # everything else aborts buffering if state not in (Gst.State.PLAYING, Gst.State.PAUSED): # abort self.__set_inhibit_play(False) self.bin.set_state(state) return self._wanted_state = state else: self.bin.set_state(state) def get_state(self, *args, **kwargs): # get_state also is a barrier (seek/positioning), # so call every time but ignore the result in the inhibit case res = self.bin.get_state(*args, **kwargs) if self._inhibit_play: return (Gst.StateChangeReturn.SUCCESS, self._wanted_state, Gst.State.VOID_PENDING) return res def destroy(self): if self.__bus_id: bus = self.bin.get_bus() bus.disconnect(self.__bus_id) bus.remove_signal_watch() self.__bus_id = None self.__set_inhibit_play(False) self.bin = None def sink_has_external_state(sink: Gst.Element) -> bool: try: sink_type = AudioSinks(sink.get_factory().get_name()) except TypeError: return False if sink_type == AudioSinks.WASAPI: # https://bugzilla.gnome.org/show_bug.cgi?id=796386 return hasattr(sink.props, "volume") return sink_type == AudioSinks.PULSE def sink_state_is_valid(sink): if not sink_has_external_state(sink): return True # pulsesink volume is only valid in PAUSED/PLAYING # https://bugzilla.gnome.org/show_bug.cgi?id=748577 current_state = sink.get_state(0)[1] return current_state >= Gst.State.PAUSED class Seeker: """Manages async seeking and position reporting for a pipeline. You have to call destroy() before it gets gc'd """ def __init__(self, playbin, player): self._player = player self._playbin = playbin self._last_position = 0 self._seek_requests = [] self._active_seeks = [] self._seekable = False bus = playbin.get_bus() bus.add_signal_watch() self._bus_id = bus.connect('message', self._on_message) player.notify("seekable") @property def seekable(self): """If the current stream is seekable""" return self._seekable def destroy(self): """This needs to be called before it gets GC'ed""" del self._seek_requests[:] del self._active_seeks[:] if self._bus_id: bus = self._playbin.get_bus() bus.disconnect(self._bus_id) bus.remove_signal_watch() self._bus_id = None self._player = None self._playbin = None def set_position(self, pos): """Set the position. Async and might not succeed. Args: pos (int): position in milliseconds """ pos = max(0, int(pos)) # We need at least a paused state to seek, if there is non active # or pending, request one async. res, next_state, pending = self._playbin.get_state(timeout=0) if pending != Gst.State.VOID_PENDING: next_state = pending if next_state < Gst.State.PAUSED: self._playbin.set_state(Gst.State.PAUSED) self._set_position(self._player.song, pos) def get_position(self): """Get the position Returns: int: the position in milliseconds """ if self._seek_requests: self._last_position = self._seek_requests[-1][1] elif self._active_seeks: self._last_position = self._active_seeks[-1][1] else: # While we are actively seeking return the last wanted position. # query_position() returns 0 while in this state ok, p = self._playbin.query_position(Gst.Format.TIME) if ok: p //= Gst.MSECOND # During stream seeking querying the position fails. # Better return the last valid one instead of 0. self._last_position = p return self._last_position def reset(self): """In case the underlying stream has changed, call this to abort any pending seeking actions and update the seekable state """ self._last_position = 0 del self._seek_requests[:] del self._active_seeks[:] self._refresh_seekable() def _refresh_seekable(self): query = Gst.Query.new_seeking(Gst.Format.TIME) if self._playbin.query(query): seekable = query.parse_seeking()[1] elif self._player.song is None: seekable = False else: seekable = True if seekable != self._seekable: self._seekable = seekable self._player.notify("seekable") def _on_message(self, bus, message): if message.type == Gst.MessageType.ASYNC_DONE: # we only get one ASYNC_DONE for multiple seeks, so flush all if self._active_seeks: song, pos = self._active_seeks[-1] if song is self._player.song: self._player.emit("seek", song, pos) del self._active_seeks[:] elif message.type == Gst.MessageType.STATE_CHANGED: if message.src is self._playbin.bin: new_state = message.parse_state_changed()[1] if new_state >= Gst.State.PAUSED: self._refresh_seekable() if self._seek_requests: song, pos = self._seek_requests[-1] if song is self._player.song: self._set_position(song, pos) del self._seek_requests[:] def _set_position(self, song, pos): event = Gst.Event.new_seek( 1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH, Gst.SeekType.SET, pos * Gst.MSECOND, Gst.SeekType.NONE, 0) if self._playbin.send_event(event): self._active_seeks.append((song, pos)) else: self._seek_requests.append((song, pos)) class GStreamerPlayer(BasePlayer, GStreamerPluginHandler): def PlayerPreferences(self): return GstPlayerPreferences(self, const.DEBUG) def __init__(self, librarian=None): GStreamerPluginHandler.__init__(self) BasePlayer.__init__(self) self._librarian = librarian self.version_info = "GStreamer: %s" % fver(Gst.version()) self._pipeline_desc = None self._volume = 1.0 self._paused = True self._mute = False self._in_gapless_transition = False self._active_error = False self.bin = None self._seeker = None self._int_vol_element = None self._ext_vol_element = None self._ext_mute_element = None self._use_eq = False self._eq_element = None self.__info_buffer = None self._lib_id = librarian.connect("changed", self.__songs_changed) self.__atf_id = None self.__bus_id = None self._runner = MainRunner() def __songs_changed(self, librarian, songs): # replaygain values might have changed, recalc volume if self.song and self.song in songs: self._reset_replaygain() def _destroy(self): self._librarian.disconnect(self._lib_id) self._runner.abort() self.__destroy_pipeline() @property def name(self): name = "GStreamer" if self._pipeline_desc: name += " (%s)" % self._pipeline_desc return name @property def has_external_volume(self): ext = self._ext_vol_element if ext is None or not sink_has_external_state(ext): return False return True def _set_buffer_duration(self, duration): """Set the stream buffer duration in msecs""" config.set("player", "gst_buffer", float(duration) / 1000) if self.bin: value = duration * Gst.MSECOND self.bin.set_property('buffer-duration', value) def _print_pipeline(self): """Print debug information for the active pipeline to stdout (elements, formats, ...) """ if self.bin: # self.bin is just a wrapper, so get the real one for line in bin_debug([self.bin.bin]): print_(line) else: print_e("No active pipeline.") def _make(self, el, name=None): return Gst.ElementFactory.make(el, name) def __init_pipeline(self): """Creates a gstreamer pipeline. Returns True on success.""" if self.bin: return True # reset error state self.error = False pipeline = config.get("player", "gst_pipeline") print_d(f"User pipeline (from player.gst_pipeline): {pipeline!r}") try: pipeline, self._pipeline_desc = GStreamerSink(pipeline) except PlayerError as e: self._error(e) return False if self._use_eq and Gst.ElementFactory.find('equalizer-10bands'): # The equalizer only operates on 16-bit ints or floats, and # will only pass these types through even when inactive. # We push floats through to this point, then let the second # audioconvert handle pushing to whatever the rest of the # pipeline supports. As a bonus, this seems to automatically # select the highest-precision format supported by the # rest of the chain. print_d("Setting up Gstreamer equalizer") filt = self._make('capsfilter', None) filt.set_property('caps', Gst.Caps.from_string('audio/x-raw,format=F32LE')) eq = self._make('equalizer-10bands', None) self._eq_element = eq self.update_eq_values() conv = self._make('audioconvert', None) resample = self._make('audioresample', None) pipeline = [filt, eq, conv, resample] + pipeline # playbin2 has started to control the volume through pulseaudio, # which means the volume property can change without us noticing. # Use our own volume element for now until this works with PA. self._int_vol_element = self._make('volume', None) pipeline.insert(0, self._int_vol_element) # Get all plugin elements and append audio converters. # playbin already includes one at the end plugin_pipeline = [] for plugin in self._get_plugin_elements(): plugin_pipeline.append(plugin) plugin_pipeline.append( self._make('audioconvert', None)) plugin_pipeline.append( self._make('audioresample', None)) print_d(f"GStreamer plugin pipeline: {plugin_pipeline}") pipeline = plugin_pipeline + pipeline bufbin = Gst.Bin() for element in pipeline: assert element is not None, pipeline bufbin.add(element) if len(pipeline) > 1: try: link_many(pipeline) except OSError as e: print_w("Linking the GStreamer pipeline failed") self._error( PlayerError(_("Could not create GStreamer pipeline (%s)" % e))) return False # see if the sink provides a volume property, if yes, use it sink_element = pipeline[-1] if isinstance(sink_element, Gst.Bin): sink_element = iter_to_list(sink_element.iterate_recurse)[-1] self._ext_vol_element = None if hasattr(sink_element.props, "volume"): self._ext_vol_element = sink_element # In case we use the sink volume directly we can increase buffering # without affecting the volume change delay too much and save some # CPU time... (2x default for now). if hasattr(sink_element.props, "buffer_time"): sink_element.set_property("buffer-time", 400000) def ext_volume_notify(*args): # gets called from a thread GLib.idle_add(self.notify, "volume") self._ext_vol_element.connect("notify::volume", ext_volume_notify) self._ext_mute_element = None if hasattr(sink_element.props, "mute") and \ sink_element.get_factory().get_name() != "directsoundsink": # directsoundsink has a mute property but it doesn't work # https://bugzilla.gnome.org/show_bug.cgi?id=755106 self._ext_mute_element = sink_element def mute_notify(*args): # gets called from a thread GLib.idle_add(self.notify, "mute") self._ext_mute_element.connect("notify::mute", mute_notify) # Make the sink of the first element the sink of the bin gpad = Gst.GhostPad.new('sink', pipeline[0].get_static_pad('sink')) bufbin.add_pad(gpad) bin_ = self._make('playbin', None) assert bin_ self.bin = BufferingWrapper(bin_, self) self._seeker = Seeker(self.bin, self) bus = bin_.get_bus() bus.add_signal_watch() self.__bus_id = bus.connect('message', self.__message, self._librarian) self.__atf_id = self.bin.connect('about-to-finish', self.__about_to_finish) # set buffer duration duration = config.getfloat("player", "gst_buffer") self._set_buffer_duration(int(duration * 1000)) # connect playbin to our plugin / volume / EQ pipeline self.bin.set_property('audio-sink', bufbin) # by default playbin will render video -> suppress using fakesink vsink = self._make(AudioSinks.FAKE.value, None) self.bin.set_property('video-sink', vsink) # disable all video/text decoding in playbin GST_PLAY_FLAG_VIDEO = 1 << 0 GST_PLAY_FLAG_TEXT = 1 << 2 flags = self.bin.get_property("flags") flags &= ~(GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT) self.bin.set_property("flags", flags) if not self.has_external_volume: # Restore volume/ReplayGain and mute state self.props.volume = self._volume self.mute = self._mute # ReplayGain information gets lost when destroying self._reset_replaygain() if self.song: self._set_uri(self.song("~uri")) return True def _set_uri(self, uri: str) -> None: self.bin.set_property("uri", uri2gsturi(uri)) def __destroy_pipeline(self): print_d("Destroying Gstreamer pipeline") self._remove_plugin_elements() if self.__bus_id: bus = self.bin.get_bus() bus.disconnect(self.__bus_id) bus.remove_signal_watch() self.__bus_id = None if self.__atf_id: self.bin.disconnect(self.__atf_id) self.__atf_id = None if self._seeker is not None: self._seeker.destroy() self._seeker = None self.notify("seekable") if self.bin: self.bin.set_state(Gst.State.NULL) self.bin.get_state(timeout=STATE_CHANGE_TIMEOUT) # BufferingWrapper cleanup self.bin.destroy() self.bin = None self._in_gapless_transition = False self._ext_vol_element = None self._int_vol_element = None self._ext_mute_element = None self._eq_element = None def _rebuild_pipeline(self): """If a pipeline is active, rebuild it and restore vol, position etc""" if not self.bin: return paused = self.paused pos = self.get_position() self.__destroy_pipeline() self.paused = True self.__init_pipeline() self.paused = paused self.seek(pos) def __message(self, bus, message, librarian): if message.type == Gst.MessageType.EOS: print_d("Stream EOS") if not self._in_gapless_transition: self._source.next_ended() self._end(False) elif message.type == Gst.MessageType.TAG: self.__tag(message.parse_tag(), librarian) elif message.type == Gst.MessageType.ERROR: gerror, debug_info = message.parse_error() message = u"" if gerror: message = gerror.message.rstrip(".") details = None if debug_info: # strip the first line, not user friendly debug_info = "\n".join(debug_info.splitlines()[1:]) # can contain paths, so not sure if utf-8 in all cases details = debug_info self._error(PlayerError(message, details)) elif message.type == Gst.MessageType.STATE_CHANGED: # pulsesink doesn't notify a volume change on startup # and the volume is only valid in > paused states. if message.src is self._ext_vol_element: self.notify("volume") if message.src is self._ext_mute_element: self.notify("mute") elif message.type == Gst.MessageType.STREAM_START: if self._in_gapless_transition: print_d("Stream changed") self._end(False) elif message.type == Gst.MessageType.ELEMENT: message_name = message.get_structure().get_name() if message_name == "missing-plugin": self.__handle_missing_plugin(message) elif message.type == Gst.MessageType.CLOCK_LOST: print_d("Clock lost") self.bin.set_state(Gst.State.PAUSED) self.bin.set_state(Gst.State.PLAYING) elif message.type == Gst.MessageType.LATENCY: print_d("Recalculate latency") self.bin.recalculate_latency() elif message.type == Gst.MessageType.REQUEST_STATE: state = message.parse_request_state() print_d("State requested: %s" % Gst.Element.state_get_name(state)) self.bin.set_state(state) elif message.type == Gst.MessageType.DURATION_CHANGED: if self.song.fill_length: ok, p = self.bin.query_duration(Gst.Format.TIME) if ok: p /= float(Gst.SECOND) self.song["~#length"] = p librarian.changed([self.song]) def __handle_missing_plugin(self, message): get_installer_detail = \ GstPbutils.missing_plugin_message_get_installer_detail get_description = GstPbutils.missing_plugin_message_get_description details = get_installer_detail(message) if details is None: return self.stop() format_desc = get_description(message) title = _(u"No GStreamer element found to handle media format") error_details = _(u"Media format: %(format-description)s") % { "format-description": format_desc} def install_done_cb(plugins_return, *args): print_d("Gstreamer plugin install return: %r" % plugins_return) Gst.update_registry() context = GstPbutils.InstallPluginsContext.new() # new in 1.6 if hasattr(context, "set_desktop_id"): from gi.repository import Gtk context.set_desktop_id(app.id) # new in 1.6 if hasattr(context, "set_startup_notification_id"): current_time = Gtk.get_current_event_time() context.set_startup_notification_id("_TIME%d" % current_time) gdk_window = app.window.get_window() if gdk_window: try: xid = gdk_window.get_xid() except AttributeError: # non X11 pass else: context.set_xid(xid) res = GstPbutils.install_plugins_async( [details], context, install_done_cb, None) print_d("Gstreamer plugin install result: %r" % res) if res in (GstPbutils.InstallPluginsReturn.HELPER_MISSING, GstPbutils.InstallPluginsReturn.INTERNAL_FAILURE): self._error(PlayerError(title, error_details)) def __about_to_finish_sync(self): """Returns the next song uri to play or None""" print_d("About to finish (sync)") # Chained oggs falsely trigger a gapless transition. # At least for radio streams we can safely ignore it because # transitions don't occur there. # https://github.com/quodlibet/quodlibet/issues/1454 # https://bugzilla.gnome.org/show_bug.cgi?id=695474 if self.song and self.song.multisong: print_d("This is a multisong - so ignoring 'about to finish' signal") return # mod + gapless deadlocks # https://github.com/quodlibet/quodlibet/issues/2780 if isinstance(self.song, ModFile): return if config.getboolean("player", "gst_disable_gapless"): print_d("Gapless disabled") return # this can trigger twice, see issue 987 if self._in_gapless_transition: return self._in_gapless_transition = True print_d("Select next song in mainloop..") self._source.next_ended() print_d("..done.") song = self._source.current if song is not None: return song("~uri") def __about_to_finish(self, playbin): print_d("About to finish (async)") try: uri = self._runner.call(self.__about_to_finish_sync, priority=GLib.PRIORITY_HIGH, timeout=0.5) except MainRunnerTimeoutError as e: # Due to some locks being held during this signal we can get # into a deadlock when a seek or state change event happens # in the mainloop before our function gets scheduled. # In this case abort and do nothing, which results # in a non-gapless transition. print_e("About to finish (async): %s" % e) return except MainRunnerAbortedError as e: print_e("About to finish (async): %s" % e) return except MainRunnerError: util.print_exc() return if uri is not None: print_d("About to finish (async): setting uri") self._set_uri(uri) print_d("About to finish (async): done") def stop(self): super().stop() print_d("Stop playing") self.__destroy_pipeline() def do_get_property(self, property): if property.name == 'volume': if self._ext_vol_element is not None and \ sink_has_external_state(self._ext_vol_element) and \ sink_state_is_valid(self._ext_vol_element): # never read back the volume if we don't have to, e.g. # directsoundsink maps volume to an int which makes UI # sliders jump if we read the value back self._volume = self._ext_vol_element.get_property("volume") return self._volume elif property.name == "mute": if self._ext_mute_element is not None and \ sink_has_external_state(self._ext_mute_element) and \ sink_state_is_valid(self._ext_mute_element): self._mute = self._ext_mute_element.get_property("mute") return self._mute elif property.name == "seekable": if self._seeker is not None: return self._seeker.seekable return False else: raise AttributeError def _reset_replaygain(self): if not self.bin: return v = 1.0 if self._ext_vol_element is not None else self._volume v = self.calc_replaygain_volume(v) v = min(10.0, max(0.0, v)) self._int_vol_element.set_property('volume', v) def do_set_property(self, property, v): if property.name == 'volume': self._volume = v if self._ext_vol_element: v = min(10.0, max(0.0, v)) self._ext_vol_element.set_property("volume", v) else: v = self.calc_replaygain_volume(v) if self.bin: v = min(10.0, max(0.0, v)) self._int_vol_element.set_property('volume', v) elif property.name == 'mute': self._mute = v if self._ext_mute_element is not None: self._ext_mute_element.set_property("mute", v) else: if self.bin: self._int_vol_element.set_property("mute", v) else: raise AttributeError def get_position(self): """Return the current playback position in milliseconds, or 0 if no song is playing.""" if self._seeker: return self._seeker.get_position() return 0 @property def paused(self): return self._paused @paused.setter def paused(self, paused): if paused == self._paused: return self._paused = paused self.emit((paused and 'paused') or 'unpaused') # in case a signal handler changed the paused state, abort this if self._paused != paused: return if paused: if self.bin: if not self.song: # Something wants us to pause between songs, or when # we've got no song playing (probably StopAfterMenu). self.__destroy_pipeline() elif self.seekable: self.bin.set_state(Gst.State.PAUSED) else: q = Gst.Query.new_buffering(Gst.Format.DEFAULT) if self.bin.query(q): # destroy so that we rebuffer on resume i.e. we don't # want to continue unseekable streams from where we # paused but from where we unpaused. self.__destroy_pipeline() else: self.bin.set_state(Gst.State.PAUSED) else: if self.song and self.__init_pipeline(): self.bin.set_state(Gst.State.PLAYING) def _error(self, player_error): """Destroy the pipeline and set the error state. The passed PlayerError will be emitted through the 'error' signal. """ # prevent recursive errors if self._active_error: return self._active_error = True self.__destroy_pipeline() self.error = True self.paused = True print_w(player_error) self.emit('error', self.song, player_error) self._active_error = False def seek(self, pos): """Seek to a position in the song, in milliseconds.""" # Don't allow seeking during gapless. We can't go back to the old song. if not self.song or self._in_gapless_transition: return if self.__init_pipeline(): self._seeker.set_position(pos) def sync(self, timeout): if self.bin is not None: # XXX: This is flaky, try multiple times for i in range(5): self.bin.get_state(Gst.SECOND * timeout) # we have some logic in the main loop, so iterate there while GLib.MainContext.default().iteration(False): pass def _end(self, stopped, next_song=None): print_d("End song") song, info = self.song, self.info # set the new volume before the signals to avoid delays if self._in_gapless_transition: self.song = self._source.current self._reset_replaygain() # We need to set self.song to None before calling our signal # handlers. Otherwise, if they try to end the song they're given # (e.g. by removing it), then we get in an infinite loop. self.__info_buffer = self.song = self.info = None if song is not info: self.emit('song-ended', info, stopped) self.emit('song-ended', song, stopped) current = next_song if next_song else (self._source and self._source.current) # Then, set up the next song. self.song = self.info = current if self.song is not None: if not self._in_gapless_transition: # Due to extensive problems with playbin2, we destroy the # entire pipeline and recreate it each time we're not in # a gapless transition. self.__destroy_pipeline() self.__init_pipeline() if self.bin: if self.paused: self.bin.set_state(Gst.State.PAUSED) else: # something unpaused while no song was active if song is None: self.emit("unpaused") self.bin.set_state(Gst.State.PLAYING) else: self.__destroy_pipeline() self._in_gapless_transition = False if self._seeker is not None: # we could have a gapless transition to a non-seekable -> update self._seeker.reset() self.emit('song-started', self.song) if self.song is None: self.paused = True def __tag(self, tags, librarian): if self.song and self.song.multisong: self._fill_stream(tags, librarian) elif self.song and self.song.fill_metadata: pass def _fill_stream(self, tags, librarian): # get a new remote file new_info = self.__info_buffer if not new_info: new_info = type(self.song)(self.song["~filename"]) new_info.multisong = False new_info.streamsong = True # copy from the old songs # we should probably listen to the library for self.song changes new_info.update(self.song) new_info.update(self.info) changed = False info_changed = False tags = TagListWrapper(tags, merge=True) tags = parse_gstreamer_taglist(tags) for key, value in sanitize_tags(tags, stream=False).items(): if self.song.get(key) != value: changed = True self.song[key] = value for key, value in sanitize_tags(tags, stream=True).items(): if new_info.get(key) != value: info_changed = True new_info[key] = value if info_changed: # in case the title changed, make self.info a new instance # and emit ended/started for the old/new one if self.info.get("title") != new_info.get("title"): if self.info is not self.song: self.emit('song-ended', self.info, False) self.info = new_info self.__info_buffer = None self.emit('song-started', self.info) else: # in case title didn't change, update the values of the # old instance if there is one and tell the library. if self.info is not self.song: self.info.update(new_info) librarian.changed([self.info]) else: # So we don't lose all tags before the first title # save it for later self.__info_buffer = new_info if changed: librarian.changed([self.song]) @property def eq_bands(self): if Gst.ElementFactory.find('equalizer-10bands'): return [29, 59, 119, 237, 474, 947, 1889, 3770, 7523, 15011] else: return [] def update_eq_values(self): need_eq = any(self._eq_values) if need_eq != self._use_eq: self._use_eq = need_eq self._rebuild_pipeline() if self._eq_element: for band, val in enumerate(self._eq_values): self._eq_element.set_property('band%d' % band, val) def can_play_uri(self, uri): if not Gst.uri_is_valid(uri): return False try: Gst.Element.make_from_uri(Gst.URIType.SRC, uri, '') except GLib.GError: return False return True def init(librarian): # Enable error messages by default if Gst.debug_get_default_threshold() == Gst.DebugLevel.NONE: Gst.debug_set_default_threshold(Gst.DebugLevel.ERROR) return GStreamerPlayer(librarian) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/player/gstbe/plugins.py0000664000175000017500000000516214035600052020627 0ustar00nicknick# Copyright 2011 Christoph Reiter # 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _ from quodlibet import util from quodlibet.plugins import PluginManager, PluginHandler from quodlibet.plugins.gstelement import GStreamerPlugin class GStreamerPluginHandler(PluginHandler): def init_plugins(self): PluginManager.instance.register_handler(self) def __init__(self): self.__plugins = [] self.__elements = {} def __get_plugin_element(self, plugin): """Setup element and cache it, so we can pass the linked/active one to the plugin for live updates""" if plugin not in self.__elements: element = None # make sure the plugin doesn't take us down try: element = plugin.setup_element() except Exception: util.print_exc() if not element: util.print_w( _("GStreamer plugin '%(name)s' could not be initialized") % {"name": plugin.PLUGIN_ID}) return plugin.update_element(element) self.__elements[plugin] = element return self.__elements[plugin] def plugin_handle(self, plugin): if not issubclass(plugin.cls, GStreamerPlugin): return False plugin.cls._handler = self return True def plugin_enable(self, plugin): self.__plugins.append(plugin.cls) self._rebuild_pipeline() def plugin_disable(self, plugin): try: self.__elements.pop(plugin.cls) except KeyError: pass self.__plugins.remove(plugin.cls) self._rebuild_pipeline() def _remove_plugin_elements(self): """Call on pipeline destruction to remove element references""" self.__elements.clear() def _get_plugin_elements(self): """Return a list of plugin elements""" for plugin in self.__plugins: self.__get_plugin_element(plugin) items = sorted(self.__elements.items(), key=lambda x: x[0].priority, reverse=True) return [p[1] for p in items] def _queue_update(self, plugin): # If we have an instance, apply settings, otherwise # this will be done on creation if plugin in self.__elements: plugin.update_element(self.__elements[plugin]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/player/gstbe/prefs.py0000644000175000017500000001112614327505043020270 0ustar00nicknick# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Steven Robertson, # 2011-2014 Christoph Reiter # 2020-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config from quodlibet import _ from quodlibet.qltk.ccb import ConfigCheckButton, ConfigSwitch from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.x import Button from quodlibet.qltk import Icons from quodlibet.util import connect_obj class GstPlayerPreferences(Gtk.VBox): def __init__(self, player, debug=False): super().__init__(spacing=12) e = UndoEntry() e.set_tooltip_text(_("The GStreamer output pipeline used for " "playback. Leave blank for the default pipeline. " "If the pipeline contains a sink, " "it will be used instead of the default one.")) e.set_text(config.get('player', 'gst_pipeline')) def changed(entry): config.set('player', 'gst_pipeline', entry.get_text()) e.connect('changed', changed) pipe_label = Gtk.Label(label=_('_Output pipeline:')) pipe_label.set_use_underline(True) pipe_label.set_mnemonic_widget(e) apply_button = Button(_("_Apply"), Icons.VIEW_REFRESH) def format_buffer(scale, value): # Translators: s = seconds return _("%.1f s") % value def scale_changed(scale): duration_msec = int(scale.get_value() * 1000) player._set_buffer_duration(duration_msec) duration = config.getfloat("player", "gst_buffer") scale = Gtk.HScale.new(Gtk.Adjustment(value=duration, lower=0.2, upper=10)) scale.set_value_pos(Gtk.PositionType.LEFT) scale.set_show_fill_level(True) scale.connect('format-value', format_buffer) scale.connect('value-changed', scale_changed) buffer_label = Gtk.Label(label=_('_Buffer duration:')) buffer_label.set_use_underline(True) buffer_label.set_mnemonic_widget(scale) def rebuild_pipeline(*args): player._rebuild_pipeline() apply_button.connect('clicked', rebuild_pipeline) gapless_button = ConfigSwitch( _('Disable _gapless playback'), "player", "gst_disable_gapless", populate=True, tooltip=_("Disabling gapless playback can avoid track changing problems " "with some GStreamer versions")) jack_button = ConfigSwitch( _('Use JACK for playback if available'), "player", "gst_use_jack", populate=True, tooltip=_("Uses `jackaudiosink` for playbin sink if it can be detected")) jack_connect = ConfigSwitch( _('Auto-connect to JACK output devices'), "player", "gst_jack_auto_connect", populate=True, tooltip=_("Tells `jackaudiosink` to auto-connect")) def _jack_activated(widget: ConfigCheckButton, *args) -> None: jack_connect.set_sensitive(widget.get_active()) jack_button.connect("notify::active", _jack_activated) _jack_activated(jack_button, None) hb = self._create_pipeline_box(pipe_label, e, apply_button) self.pack_start(hb, False, False, 0) # Buffer hb = self._create_buffer_box(buffer_label, scale) self.pack_start(hb, False, False, 0) self.pack_start(gapless_button, False, False, 0) self.pack_start(jack_button, False, False, 0) self.pack_start(jack_connect, False, False, 0) if debug: def print_bin(player): player._print_pipeline() b = Button("Print Pipeline", Icons.DIALOG_INFORMATION) connect_obj(b, 'clicked', print_bin, player) hb = Gtk.Box(spacing=6) hb.pack_end(b, False, False, 0) self.pack_start(hb, False, False, 0) def _create_buffer_box(self, label: Gtk.Label, scale: Gtk.HScale): hb = Gtk.Box(spacing=6) hb.pack_start(label, False, False, 0) hb.pack_end(scale, True, True, 0) return hb def _create_pipeline_box(self, pipe_label: Gtk.Label, e: Gtk.Widget, apply_button: Gtk.Button): hb = Gtk.Box(spacing=12) hb.pack_start(pipe_label, False, False, 0) hb.pack_start(e, True, True, 0) hb.pack_end(apply_button, False, False, 0) return hb ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/player/gstbe/util.py0000664000175000017500000002146414231604332020131 0ustar00nicknick# Copyright 2009-2011 Steven Robertson, Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. try: from collections import abc except ImportError: import collections as abc # type: ignore import subprocess from enum import Enum from typing import Iterable, Tuple from gi.repository import GLib, Gst from quodlibet import _, print_d, config from quodlibet.util.string import decode from quodlibet.util import is_linux, is_windows from quodlibet.player import PlayerError class AudioSinks(Enum): """Relevant Gstreamer sink elements""" FAKE = "fakesink" DIRECTSOUND = "directsoundsink" PULSE = "pulsesink" """from plugins-good""" ALSA = "alsasink" """from plugins-base""" AUTO = "autoaudiosink" """from plugins-good""" JACK = "jackaudiosink" """from plugins-good""" WASAPI = "wasapisink" def pulse_is_running(): """Returns whether pulseaudio is running""" # If we have a pulsesink we can get the server presence through # setting the ready state element = Gst.ElementFactory.make(AudioSinks.PULSE.value, None) if element is not None: element.set_state(Gst.State.READY) res = element.get_state(0)[0] element.set_state(Gst.State.NULL) return res != Gst.StateChangeReturn.FAILURE # In case we don't have it call the pulseaudio binary try: subprocess.check_call(["pulseaudio", "--check"]) except subprocess.CalledProcessError: return False except OSError: return False return True def jack_is_running() -> bool: """:returns: whether Jack is running""" element = Gst.ElementFactory.make(AudioSinks.JACK.value, "test sink") if element: element.set_state(Gst.State.READY) res = element.get_state(0)[0] element.set_state(Gst.State.NULL) return res != Gst.StateChangeReturn.FAILURE return False def link_many(elements: Iterable[Gst.Element]) -> None: """Links all elements together :raises OSError: if they can't all be linked""" last = None print_d(f"Attempting to link Gstreamer element(s): " f"{[type(e).__name__ for e in elements]}") for element in elements: if last: if not Gst.Element.link(last, element): raise OSError(f"Failed on element: {type(element).__name__}") last = element def unlink_many(elements): last = None for element in elements: if last: if not Gst.Element.unlink(last, element): return False last = element return True def iter_to_list(func): objects = [] iter_ = func() while 1: status, value = iter_.next() if status == Gst.IteratorResult.OK: objects.append(value) else: break return objects def find_audio_sink() -> Tuple[Gst.Element, str]: """Get the best audio sink available. Returns (element, description) or raises PlayerError. """ def sink_options(): # People with Jack running probably want it more than any other options if config.getboolean("player", "gst_use_jack") and jack_is_running(): print_d("Using JACK output via Gstreamer") return [AudioSinks.JACK] elif is_windows(): return [AudioSinks.DIRECTSOUND] elif is_linux() and pulse_is_running(): return [AudioSinks.PULSE] else: return [ AudioSinks.AUTO, AudioSinks.PULSE, AudioSinks.ALSA, ] options = sink_options() for sink in options: element = Gst.ElementFactory.make(sink.value, "player") if (sink == AudioSinks.JACK and not config.getboolean("player", "gst_jack_auto_connect")): # Disable the auto-connection to outputs (e.g. maybe there's scripting) element.set_property("connect", "none") if element is not None: return element, sink.value else: details = ', '.join(s.value for s in options) if options else "[]" raise PlayerError(_("No GStreamer audio sink found. Tried: %s") % details) def GStreamerSink(pipeline_desc): """Returns a list of unlinked gstreamer elements ending with an audio sink and a textual description of the pipeline. `pipeline_desc` can be gst-launch syntax for multiple elements with or without an audiosink. In case of an error, raises PlayerError """ pipe = None if pipeline_desc: try: pipe = [Gst.parse_launch(e) for e in pipeline_desc.split('!')] except GLib.GError as e: message = e.message raise PlayerError(_("Invalid GStreamer output pipeline"), message) if pipe: # In case the last element is linkable with a fakesink # it is not an audiosink, so we append the default one fake = Gst.ElementFactory.make(AudioSinks.FAKE.value, None) try: link_many([pipe[-1], fake]) except OSError: pass else: unlink_many([pipe[-1], fake]) default_elm, default_desc = find_audio_sink() pipe += [default_elm] pipeline_desc += " ! " + default_desc else: elm, pipeline_desc = find_audio_sink() pipe = [elm] return pipe, pipeline_desc class TagListWrapper(abc.Mapping): def __init__(self, taglist, merge=False): self._list = taglist self._merge = merge def __len__(self): return self._list.n_tags() def __iter__(self): for i in range(len(self)): yield self._list.nth_tag_name(i) def __getitem__(self, key): if not Gst.tag_exists(key): raise KeyError values = [] index = 0 while 1: value = self._list.get_value_index(key, index) if value is None: break values.append(value) index += 1 if not values: raise KeyError if self._merge: try: return " - ".join(values) except TypeError: return values[0] return values def parse_gstreamer_taglist(tags): """Takes a GStreamer taglist and returns a dict containing only numeric and unicode values and str keys.""" merged = {} for key in tags.keys(): value = tags[key] # extended-comment sometimes contains a single vorbiscomment or # a list of them ["key=value", "key=value"] if key == "extended-comment": if not isinstance(value, list): value = [value] for val in value: if not isinstance(val, str): continue split = val.split("=", 1) sub_key = split[0] val = split[-1] if sub_key in merged: sub_val = merged[sub_key] if not isinstance(sub_val, str): continue if val not in sub_val.split("\n"): merged[sub_key] += "\n" + val else: merged[sub_key] = val elif isinstance(value, Gst.DateTime): value = value.to_iso8601_string() merged[key] = value else: if isinstance(value, (int, float)): merged[key] = value continue if isinstance(value, bytes): value = decode(value) if not isinstance(value, str): value = str(value) if key in merged: merged[key] += "\n" + value else: merged[key] = value return merged def bin_debug(elements, depth=0, lines=None): """Takes a list of gst.Element that are part of a prerolled pipeline, and recursively gets the children and all caps between the elements. Returns a list of text lines suitable for printing. """ from quodlibet.util.dprint import Colorise if lines is None: lines = [] else: lines.append(" " * (depth - 1) + "\\") for i, elm in enumerate(elements): for pad in iter_to_list(elm.iterate_sink_pads): caps = pad.get_current_caps() if caps: lines.append("%s| %s" % (" " * depth, caps.to_string())) name = elm.get_name() cls = Colorise.blue(type(elm).__name__.split(".", 1)[-1]) lines.append("%s|-%s (%s)" % (" " * depth, cls, name)) if isinstance(elm, Gst.Bin): children = reversed(iter_to_list(elm.iterate_sorted)) bin_debug(children, depth + 1, lines) return lines ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/player/nullbe.py0000664000175000017500000000572414231604332017332 0ustar00nicknick# Copyright 2004 Joe Wreschnig, Michael Urman # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.player._base import BasePlayer from quodlibet.player import PlayerError class NullPlayer(BasePlayer): version_info = "Null Player Backend" name = "Null" def __init__(self, sinkname="", librarian=None): super().__init__() self._paused = True self._source = None self._volume = 1.0 self._mute = False self._position = 0 def _destroy(self): pass def get_position(self): """Return the current playback position in milliseconds, or 0 if no song is playing.""" return self._position @property def paused(self): return self._paused @paused.setter def paused(self, paused): if paused == self._paused: return self._paused = paused self.emit((paused and 'paused') or 'unpaused') def do_get_property(self, property): if property.name == 'volume': return self._volume elif property.name == 'seekable': if self.song is None: return False return True elif property.name == 'mute': return self._mute else: raise AttributeError def do_set_property(self, property, v): if property.name == 'volume': self._volume = v elif property.name == 'mute': self._mute = v else: raise AttributeError def _error(self, message): self.paused = True self.emit('error', self.song, PlayerError(message)) def seek(self, pos): """Seek to a position in the song, in milliseconds.""" self._position = pos if self.song: self.emit('seek', self.song, pos) def _end(self, stopped, next_song=None): # We need to set self.song to None before calling our signal # handlers. Otherwise, if they try to end the song they're given # (e.g. by removing it), then we get in an infinite loop. song = self.song self.song = self.info = None self.emit('song-ended', song, stopped) current = next_song if next_song else (self._source and self._source.current) # Then, set up the next song. self._position = 0 self.song = self.info = current self.emit('song-started', self.song) if self.song is None: self.paused = True if not self.paused and song is None: self.emit("unpaused") # seekable might change if we change to None, so notify just in case self.notify("seekable") def can_play_uri(self, uri): return True def init(librarian): return NullPlayer(librarian) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735242.004269 quodlibet-4.6.0/quodlibet/player/xinebe/0000755000175000017500000000000014471213412016740 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/player/xinebe/__init__.py0000664000175000017500000000050314035600052021045 0ustar00nicknick# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .player import init init = init ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/player/xinebe/cdefs.py0000664000175000017500000002315014035600052020375 0ustar00nicknick# Copyright 2006 Lukas Lalinsky # # 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 2 of the License, or # (at your option) any later version. import ctypes from quodlibet.util import load_library try: _libxine, name = load_library(["libxine.so.2", "libxine.so.1"]) except OSError as e: raise ImportError(e) if name.endswith("2"): _version = 2 else: _version = 1 class xine_event_t(ctypes.Structure): if _version == 1: _fields_ = [ ('type', ctypes.c_int), ('stream', ctypes.c_void_p), ('data', ctypes.c_void_p), ('data_length', ctypes.c_int), ] elif _version == 2: _fields_ = [ ('stream', ctypes.c_void_p), ('data', ctypes.c_void_p), ('data_length', ctypes.c_int), ('type', ctypes.c_int), ] class xine_ui_message_data_t(ctypes.Structure): _fields_ = [ ('compatibility_num_buttons', ctypes.c_int), ('compatibility_str_len', ctypes.c_int), ('compatibility_str', 256 * ctypes.c_char), ('type', ctypes.c_int), ('explanation', ctypes.c_int), ('num_parameters', ctypes.c_int), ('parameters', ctypes.c_void_p), ('messages', ctypes.c_char), ] # event listener callback type xine_event_listener_cb_t = ctypes.CFUNCTYPE( ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(xine_event_t)) # event types XINE_EVENT_UI_PLAYBACK_FINISHED = 1 XINE_EVENT_UI_CHANNELS_CHANGED = 2 XINE_EVENT_UI_SET_TITLE = 3 XINE_EVENT_UI_MESSAGE = 4 XINE_EVENT_FRAME_FORMAT_CHANGE = 5 XINE_EVENT_AUDIO_LEVEL = 6 XINE_EVENT_QUIT = 7 XINE_EVENT_PROGRESS = 8 # stream parameters XINE_PARAM_SPEED = 1 # see below XINE_PARAM_AV_OFFSET = 2 # unit: 1/90000 ses XINE_PARAM_AUDIO_CHANNEL_LOGICAL = 3 # -1 => auto, -2 => off XINE_PARAM_SPU_CHANNEL = 4 XINE_PARAM_VIDEO_CHANNEL = 5 XINE_PARAM_AUDIO_VOLUME = 6 # 0..100 XINE_PARAM_AUDIO_MUTE = 7 # 1=>mute, 0=>unmute XINE_PARAM_AUDIO_COMPR_LEVEL = 8 # <100=>off, % compress otherw XINE_PARAM_AUDIO_AMP_LEVEL = 9 # 0..200, 100=>100% (default) XINE_PARAM_AUDIO_REPORT_LEVEL = 10 # 1=>send events, 0=> don't XINE_PARAM_VERBOSITY = 11 # control console output XINE_PARAM_SPU_OFFSET = 12 # unit: 1/90000 sec XINE_PARAM_IGNORE_VIDEO = 13 # disable video decoding XINE_PARAM_IGNORE_AUDIO = 14 # disable audio decoding XINE_PARAM_IGNORE_SPU = 15 # disable spu decoding XINE_PARAM_BROADCASTER_PORT = 16 # 0: disable, x: server port XINE_PARAM_METRONOM_PREBUFFER = 17 # unit: 1/90000 sec XINE_PARAM_EQ_30HZ = 18 # equalizer gains -100..100 XINE_PARAM_EQ_60HZ = 19 # equalizer gains -100..100 XINE_PARAM_EQ_125HZ = 20 # equalizer gains -100..100 XINE_PARAM_EQ_250HZ = 21 # equalizer gains -100..100 XINE_PARAM_EQ_500HZ = 22 # equalizer gains -100..100 XINE_PARAM_EQ_1000HZ = 23 # equalizer gains -100..100 XINE_PARAM_EQ_2000HZ = 24 # equalizer gains -100..100 XINE_PARAM_EQ_4000HZ = 25 # equalizer gains -100..100 XINE_PARAM_EQ_8000HZ = 26 # equalizer gains -100..100 XINE_PARAM_EQ_16000HZ = 27 # equalizer gains -100..100 XINE_PARAM_AUDIO_CLOSE_DEVICE = 28 # force closing audio device XINE_PARAM_AUDIO_AMP_MUTE = 29 # 1=>mute, 0=>unmute XINE_PARAM_FINE_SPEED = 30 # 1.000.000 => normal speed XINE_PARAM_EARLY_FINISHED_EVENT = 31 # send event when demux finish XINE_PARAM_GAPLESS_SWITCH = 32 # next stream only gapless swi XINE_PARAM_DELAY_FINISHED_EVENT = 33 # 1/10sec,0=>disable,-1=>forev # speeds XINE_SPEED_PAUSE = 0 XINE_SPEED_SLOW_4 = 1 XINE_SPEED_SLOW_2 = 2 XINE_SPEED_NORMAL = 4 XINE_SPEED_FAST_2 = 8 XINE_SPEED_FAST_4 = 16 # metadata XINE_META_INFO_TITLE = 0 XINE_META_INFO_COMMENT = 1 XINE_META_INFO_ARTIST = 2 XINE_META_INFO_GENRE = 3 XINE_META_INFO_ALBUM = 4 XINE_META_INFO_YEAR = 5 XINE_META_INFO_VIDEOCODEC = 6 XINE_META_INFO_AUDIOCODEC = 7 XINE_META_INFO_SYSTEMLAYER = 8 XINE_META_INFO_INPUT_PLUGIN = 9 # statuses XINE_STATUS_IDLE = 0 XINE_STATUS_STOP = 1 XINE_STATUS_PLAY = 2 XINE_STATUS_QUIT = 3 XINE_MSG_NO_ERROR = 0 # (messages to UI) XINE_MSG_GENERAL_WARNING = 1 # (warning message) XINE_MSG_UNKNOWN_HOST = 2 # (host name) XINE_MSG_UNKNOWN_DEVICE = 3 # (device name) XINE_MSG_NETWORK_UNREACHABLE = 4 # none XINE_MSG_CONNECTION_REFUSED = 5 # (host name) XINE_MSG_FILE_NOT_FOUND = 6 # (file name or mrl) XINE_MSG_READ_ERROR = 7 # (device/file/mrl) XINE_MSG_LIBRARY_LOAD_ERROR = 8 # (library/decoder) XINE_MSG_ENCRYPTED_SOURCE = 9 # none XINE_MSG_SECURITY = 10 # (security message) XINE_MSG_AUDIO_OUT_UNAVAILABLE = 11 # none XINE_MSG_PERMISSION_ERROR = 12 # (file name or mrl) XINE_MSG_FILE_EMPTY = 13 # file is empty XINE_MSG_AUTHENTICATION_NEEDED = 14 # (mrl, likely http); added in 1.2 # xine_t *xine_new(void) xine_new = _libxine.xine_new xine_new.restype = ctypes.c_void_p # void xine_init(xine_t *self) xine_init = _libxine.xine_init xine_init.argtypes = [ctypes.c_void_p] # void xine_exit(xine_t *self) xine_exit = _libxine.xine_exit xine_exit.argtypes = [ctypes.c_void_p] # void xine_config_load(xine_t *self, const char *cfg_filename) xine_config_load = _libxine.xine_config_load xine_config_load.argtypes = [ctypes.c_void_p, ctypes.c_char_p] # const char *xine_get_homedir(void) xine_get_homedir = _libxine.xine_get_homedir xine_get_homedir.restype = ctypes.c_char_p # xine_audio_port_t *xine_open_audio_driver(xine_t *self, const char *id, # void *data) xine_open_audio_driver = _libxine.xine_open_audio_driver xine_open_audio_driver.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p] xine_open_audio_driver.restype = ctypes.c_void_p # void xine_close_audio_driver(xine_t *self, xine_audio_port_t *driver) xine_close_audio_driver = _libxine.xine_close_audio_driver xine_close_audio_driver.argtypes = [ctypes.c_void_p, ctypes.c_void_p] # xine_stream_t *xine_stream_new(xine_t *self, # xine_audio_port_t *ao, xine_video_port_t *vo) xine_stream_new = _libxine.xine_stream_new xine_stream_new.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] xine_stream_new.restype = ctypes.c_void_p # void xine_close(xine_sxine_event_create_listener_threadtream_t *stream) xine_close = _libxine.xine_close xine_close.argtypes = [ctypes.c_void_p] # int xine_open (xine_stream_t *stream, const char *mrl) xine_open = _libxine.xine_open xine_open.argtypes = [ctypes.c_void_p, ctypes.c_char_p] xine_open.restype = ctypes.c_int # int xine_play(xine_stream_t *stream, int start_pos, int start_time) xine_play = _libxine.xine_play xine_play.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] xine_play.restype = ctypes.c_int # void xine_stop(xine_stream_t *stream) xine_stop = _libxine.xine_stop xine_stop.argtypes = [ctypes.c_void_p] # void xine_dispose(xine_stream_t *stream) xine_dispose = _libxine.xine_dispose xine_dispose.argtypes = [ctypes.c_void_p] # xine_event_queue_t *xine_event_new_queue(xine_stream_t *stream) xine_event_new_queue = _libxine.xine_event_new_queue xine_event_new_queue.argtypes = [ctypes.c_void_p] xine_event_new_queue.restype = ctypes.c_void_p # void xine_event_dispose_queue(xine_event_queue_t *queue) xine_event_dispose_queue = _libxine.xine_event_dispose_queue xine_event_dispose_queue.argtypes = [ctypes.c_void_p] # void xine_event_create_listener_thread(xine_event_queue_t *queue, # xine_event_listener_cb_t callback, # void *user_data) _xine_event_create_listener_thread = _libxine.xine_event_create_listener_thread _xine_event_create_listener_thread.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] xine_usec_sleep = _libxine.xine_usec_sleep xine_usec_sleep.argtypes = [ctypes.c_int] xine_set_param = _libxine.xine_set_param xine_set_param.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] xine_get_param = _libxine.xine_get_param xine_get_param.argtypes = [ctypes.c_void_p, ctypes.c_int] xine_get_param.restype = ctypes.c_int xine_get_meta_info = _libxine.xine_get_meta_info xine_get_meta_info.argtypes = [ctypes.c_void_p, ctypes.c_int] xine_get_meta_info.restype = ctypes.c_char_p xine_get_status = _libxine.xine_get_status xine_get_status.argtypes = [ctypes.c_void_p] xine_get_status.restype = ctypes.c_int _xine_get_pos_length = _libxine.xine_get_pos_length _xine_get_pos_length.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)] xine_get_version_string = _libxine.xine_get_version_string xine_get_version_string.restype = ctypes.c_char_p xine_get_file_extensions = _libxine.xine_get_file_extensions xine_get_file_extensions.argtypes = [ctypes.c_void_p] xine_get_file_extensions.restype = ctypes.c_char_p xine_get_mime_types = _libxine.xine_get_mime_types xine_get_mime_types.argtypes = [ctypes.c_void_p] xine_get_mime_types.restype = ctypes.c_char_p xine_list_input_plugins = _libxine.xine_list_input_plugins xine_list_input_plugins.argtypes = [ctypes.c_void_p] xine_list_input_plugins.restype = ctypes.POINTER(ctypes.c_char_p) xine_check_version = _libxine.xine_check_version xine_check_version.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int] xine_check_version.restype = ctypes.c_int _callbacks = [] def xine_event_create_listener_thread(queue, callback, user_data): cb = xine_event_listener_cb_t(callback) _callbacks.append(cb) _xine_event_create_listener_thread(queue, cb, user_data) def xine_get_pos_length(stream): _pos_stream = ctypes.c_int() _pos_time = ctypes.c_int() _length_time = ctypes.c_int() result = _xine_get_pos_length(stream, ctypes.byref(_pos_stream), ctypes.byref(_pos_time), ctypes.byref(_length_time)) if result: return _pos_stream.value, _pos_time.value, _length_time.value else: return 0, 0, 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/quodlibet/player/xinebe/player.py0000664000175000017500000002763414244626671020641 0ustar00nicknick# Copyright 2006-2007 Lukas Lalinsky # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GLib from quodlibet import _ from quodlibet import config from quodlibet.player import PlayerError from quodlibet.player._base import BasePlayer from quodlibet.util.string import decode from . import cdefs from .cdefs import XINE_PARAM_SPEED, XINE_PARAM_GAPLESS_SWITCH, xine_dispose, \ XINE_SPEED_PAUSE, xine_play, xine_close, xine_set_param, xine_get_param, \ xine_get_status, xine_open, xine_stop, XINE_PARAM_EARLY_FINISHED_EVENT, \ XINE_META_INFO_ARTIST, xine_ui_message_data_t, XINE_EVENT_UI_SET_TITLE, \ XINE_PARAM_AUDIO_AMP_MUTE, XINE_PARAM_AUDIO_AMP_LEVEL, xine_new, \ XINE_EVENT_UI_PLAYBACK_FINISHED, xine_event_dispose_queue, xine_init, \ XINE_PARAM_IGNORE_VIDEO, XINE_PARAM_IGNORE_SPU, xine_config_load, \ xine_check_version, xine_get_homedir, xine_list_input_plugins, xine_exit, \ xine_open_audio_driver, xine_close_audio_driver, XINE_STATUS_PLAY, \ XINE_SPEED_NORMAL, xine_get_pos_length, XINE_MSG_NO_ERROR, \ XINE_EVENT_UI_MESSAGE, xine_get_meta_info, XINE_META_INFO_ALBUM, \ XINE_META_INFO_TITLE, xine_stream_new, xine_get_version_string, \ xine_event_new_queue, xine_event_create_listener_thread class XineHandle: def __init__(self): _xine = xine_new() xine_config_load(_xine, xine_get_homedir() + b"/.xine/config") xine_init(_xine) self._xine = _xine def list_input_plugins(self): """ Returns: List[str] """ plugins = [] for plugin in xine_list_input_plugins(self._xine): if not plugin: break plugins.append(decode(plugin)) return plugins def exit(self): xine_exit(self._xine) def open_audio_driver(self, identifier, data): return xine_open_audio_driver(self._xine, identifier, data) def close_audio_driver(self, driver): xine_close_audio_driver(self._xine, driver) def stream_new(self, audio_port, video_port): return xine_stream_new(self._xine, audio_port, video_port) class XinePlaylistPlayer(BasePlayer): """Xine playlist player.""" _paused = True def __init__(self, driver, librarian): """May raise PlayerError""" super().__init__() self.name = "xine" self.version_info = "xine-lib: " + decode(xine_get_version_string()) self._volume = 1.0 self._handle = XineHandle() self._supports_gapless = xine_check_version(1, 1, 1) == 1 self._event_queue = None self._new_stream(driver) self._librarian = librarian self._destroyed = False def _new_stream(self, driver): assert driver is None or isinstance(driver, bytes) self._audio_port = self._handle.open_audio_driver(driver, None) if not self._audio_port: raise PlayerError( _("Unable to create audio output"), _("The audio device %r was not found. Check your Xine " "settings in ~/.quodlibet/config.") % driver) self._stream = self._handle.stream_new(self._audio_port, None) xine_set_param(self._stream, XINE_PARAM_IGNORE_VIDEO, 1) xine_set_param(self._stream, XINE_PARAM_IGNORE_SPU, 1) self.update_eq_values() if self._supports_gapless: xine_set_param(self._stream, XINE_PARAM_EARLY_FINISHED_EVENT, 1) if self._event_queue: xine_event_dispose_queue(self._event_queue) self._event_queue = xine_event_new_queue(self._stream) xine_event_create_listener_thread(self._event_queue, self._event_listener, None) def _destroy(self): self._destroyed = True if self._stream: xine_close(self._stream) xine_dispose(self._stream) self._stream = None if self._event_queue: xine_event_dispose_queue(self._event_queue) if self._audio_port: self._handle.close_audio_driver(self._audio_port) self._handle.exit() def _playback_finished(self): if self._destroyed: return False self._source.next_ended() self._end(False, None, gapless=True) return False def _update_metadata(self): if self._destroyed: return False if not self.song or not self.song.multisong: return False if self.info is self.song: self.info = type(self.song)(self.song["~filename"]) self.info.multisong = False changed = False meta = [ (XINE_META_INFO_TITLE, 'title'), (XINE_META_INFO_ARTIST, 'artist'), (XINE_META_INFO_ALBUM, 'album'), ] for info, name in meta: text = xine_get_meta_info(self._stream, info) if not text: continue text = text.decode('UTF-8', 'replace') if self.info.get(name) != text: self.info[name] = text changed = True if changed: self.emit('song-started', self.info) if self._librarian is not None: self._librarian.changed([self.song]) return False def _event_listener(self, user_data, event): event = event.contents if event.type == XINE_EVENT_UI_PLAYBACK_FINISHED: GLib.idle_add(self._playback_finished, priority=GLib.PRIORITY_HIGH) elif event.type == XINE_EVENT_UI_SET_TITLE: GLib.idle_add(self._update_metadata, priority=GLib.PRIORITY_HIGH) elif event.type == XINE_EVENT_UI_MESSAGE: from ctypes import POINTER, cast, string_at, addressof msg = cast(event.data, POINTER(xine_ui_message_data_t)).contents if msg.type != XINE_MSG_NO_ERROR: if msg.explanation: message = string_at(addressof(msg) + msg.explanation) else: message = "xine error %s" % msg.type message = message.decode("utf-8", errors="replace") GLib.idle_add(self._error, PlayerError(message)) return True def do_get_property(self, property): if property.name == 'volume': return self._volume elif property.name == 'seekable': if self.song is None: return False return True elif property.name == 'mute': if not self._destroyed: return xine_get_param(self._stream, XINE_PARAM_AUDIO_AMP_MUTE) return False else: raise AttributeError def do_set_property(self, property, v): if property.name == 'volume': self._volume = v v = self.calc_replaygain_volume(v) v = min(100, int(v * 100)) if not self._destroyed: xine_set_param(self._stream, XINE_PARAM_AUDIO_AMP_LEVEL, v) elif property.name == 'mute': if not self._destroyed: xine_set_param(self._stream, XINE_PARAM_AUDIO_AMP_MUTE, v) else: raise AttributeError def get_position(self): """Return the current playback position in milliseconds, or 0 if no song is playing.""" pos_stream, pos_time, length_time = xine_get_pos_length(self._stream) return pos_time def _stop(self): xine_stop(self._stream) def _pause(self): xine_set_param(self._stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE) def _play(self): if (xine_get_param(self._stream, XINE_PARAM_SPEED) != XINE_SPEED_NORMAL): xine_set_param(self._stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL) if xine_get_status(self._stream) != XINE_STATUS_PLAY: xine_play(self._stream, 0, 0) @property def paused(self): return self._paused @paused.setter def paused(self, paused): if paused == self._paused: return self._paused = paused self.emit((paused and 'paused') or 'unpaused') if self._paused != paused: return if self.song: if paused: if not self.song.is_file: xine_close(self._stream) xine_open(self._stream, self.song("~uri").encode("ascii")) else: self._pause() else: self._play() def _error(self, player_error=None): if self._destroyed: return False if self.error: return False self.error = True self.paused = True if player_error: self.emit('error', self.song, player_error) def seek(self, pos): """Seek to a position in the song, in milliseconds.""" if xine_get_param(self._stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE: xine_play(self._stream, 0, int(pos)) xine_set_param(self._stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE) else: xine_play(self._stream, 0, int(pos)) self.emit('seek', self.song, pos) def _end(self, stopped, next_song=None, gapless=False): # We need to set self.song to None before calling our signal # handlers. Otherwise, if they try to end the song they're given # (e.g. by removing it), then we get in an infinite loop. song = self.song self.song = self.info = None self.emit('song-ended', song, stopped) # reset error state self.error = False current = next_song if next_song else (self._source and self._source.current) # Then, set up the next song. self.song = self.info = current self.emit('song-started', self.song) if self.song is not None: self.volume = self.volume if gapless and self._supports_gapless: xine_set_param(self._stream, XINE_PARAM_GAPLESS_SWITCH, 1) xine_open(self._stream, self.song("~uri").encode("ascii")) if self._paused: self._pause() else: if song is None: self.emit("unpaused") self._play() if gapless and self._supports_gapless: xine_set_param(self._stream, XINE_PARAM_GAPLESS_SWITCH, 0) else: self.paused = True xine_stop(self._stream) # seekable might change if we change to None, so notify just in case self.notify("seekable") def setup(self, playlist, song, seek_pos, explicit=True): super().setup(playlist, song, seek_pos, explicit=explicit) # xine's declining to seek so soon after startup; try again in 100ms if seek_pos: GLib.timeout_add(100, self.seek, seek_pos) @property def eq_bands(self): # These are taken straight from Xine's API return [30, 60, 125, 250, 500, 1000, 2000, 4000, 8000, 16000] def update_eq_values(self): bands = self.eq_bands need_eq = any(self._eq_values) for band, val in enumerate(self._eq_values): param = getattr(cdefs, 'XINE_PARAM_EQ_%dHZ' % bands[band]) # between 1..200; 100 is the default gain; 0 means no EQ filter # only negative gain seems to work val = (int(val * 100 / 24.0) + 100) or 1 val *= int(need_eq) xine_set_param(self._stream, param, val) def can_play_uri(self, uri): for plugin in self._handle.list_input_plugins(): if uri.startswith(plugin.lower()): return True return False def init(librarian): """May raise PlayerError""" try: driver = config.getbytes("settings", "xine_driver") except: driver = None return XinePlaylistPlayer(driver, librarian) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735242.004269 quodlibet-4.6.0/quodlibet/plugins/0000755000175000017500000000000014471213412015653 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1663102510.0 quodlibet-4.6.0/quodlibet/plugins/__init__.py0000644000175000017500000004202314310167056017771 0ustar00nicknick# Copyright 2012 - 2020 Christoph Reiter, Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Optional, Iterable from quodlibet import _ from quodlibet import config from quodlibet import util from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.util import escape from quodlibet.util.config import ConfigProxy from quodlibet.util.dprint import print_d from quodlibet.util.modulescanner import ModuleScanner def init(folders=None, disable_plugins=False): """folders: list of paths to look for plugins disable_plugins: disables all plugins, but does not forget which plugins are enabled. """ if disable_plugins: folders = [] manager = PluginManager.instance = PluginManager(folders) return manager def quit(): PluginManager.instance.save() PluginManager.instance.quit() PluginManager.instance = None class PluginImportException(Exception): desc = "" def __init__(self, desc, *args, **kwargs): super().__init__(desc) self.desc = desc def should_show(self): """If the error description should be shown to the user""" return True class PluginNotSupportedError(PluginImportException): """To hide the plugin (e.g. on Windows)""" def __init__(self, msg=None): msg = "not supported: %s" % (msg or "unknown reason") super().__init__(msg) def should_show(self): return False class MissingModulePluginException(PluginImportException): """Consistent Exception for reporting missing modules for plugins""" def __init__(self, module_name): msg = (_("Couldn't find module '{module}'. Perhaps you need to " "install the package?").format(module=module_name)) super().__init__(msg) class MissingGstreamerElementPluginException(PluginImportException): """Consistent Exception for reporting missing Gstreamer elements for plugins""" def __init__(self, element_name): msg = (_("Couldn't find GStreamer element '{element}'.") .format(element=element_name)) super().__init__(msg) def migrate_old_config(): active = [] old_keys = ["songsmenuplugins", "eventplugins", "editingplugins", "playorderplugins"] for key in old_keys: key = "active_" + key try: active.extend(config.get("plugins", key).splitlines()) except config.Error: pass else: config._config.remove_option("plugins", key) if active: config.set("plugins", "active_plugins", "\n".join(active)) def list_plugins(module): """Return all objects of the module that satisfy the basic plugin needs: id, name and don't start with '_' If '__all__' is defined, only plugins in '__all__' will be loaded. """ try: objs = [getattr(module, attr) for attr in module.__all__] except AttributeError: objs = [getattr(module, attr) for attr in vars(module) if not attr.startswith("_")] ok = [] for obj in objs: if hasattr(obj, "PLUGIN_ID"): if not hasattr(obj, "PLUGIN_NAME"): obj.PLUGIN_NAME = obj.PLUGIN_ID ok.append(obj) return ok class PluginModule: def __init__(self, name, module): self.name = name self.module = module self.plugins = [Plugin(cls) for cls in list_plugins(module)] class Plugin: def __init__(self, plugin_cls): self.cls = plugin_cls self.handlers = [] self.instance = None def __repr__(self): return "<%s id=%r name=%r>" % (type(self).__name__, self.id, self.name) @property def can_enable(self): return getattr(self.cls, "PLUGIN_CAN_ENABLE", True) @property def id(self): return self.cls.PLUGIN_ID @property def name(self): return self.cls.PLUGIN_NAME @property def description(self): return getattr(self.cls, "PLUGIN_DESC", None) @property def description_markup(self): try: return getattr(self.cls, "PLUGIN_DESC_MARKUP") except AttributeError: return escape(self.description) @property def tags(self): tags = getattr(self.cls, "PLUGIN_TAGS", []) if isinstance(tags, str): tags = [tags] return tags @property def icon(self): return getattr(self.cls, "PLUGIN_ICON", None) def get_instance(self): """A singleton""" if not getattr(self.cls, "PLUGIN_INSTANCE", False): return if self.instance is None: try: obj = self.cls() except: util.print_exc() return self.instance = obj return self.instance class PluginHandler: """A plugin handler can choose to handle plugins, as well as control their enabled state.""" def plugin_handle(self, plugin): """Returns `True` IFF this handler can handle `plugin`""" raise NotImplementedError def plugin_enable(self, plugin): """Called to enable / register `plugin`""" raise NotImplementedError def plugin_disable(self, plugin): """Called to disable / de-register `plugin`""" raise NotImplementedError class PluginManager: """ The manager takes care of plugin loading/reloading. Interested plugin handlers can register them self to get called when plugins get enabled or disabled. Plugins get exposed when at least one handler shows interest in them (by returning True in the handle method). Plugins have to be a class which defines PLUGIN_ID, PLUGIN_NAME. Plugins that have a true PLUGIN_INSTANCE attribute get instantiated on enable and the enabled/disabled methods get called. If plugin handlers want a plugin instance, they have to call Plugin.get_instance() to get a singleton. handlers need to implement the following methods: handler.plugin_handle(plugin) Needs to return True if the handler should be called whenever the plugin's enabled status changes. handler.plugin_enable(plugin) Gets called if the plugin gets enabled. handler.plugin_disable(plugin) Gets called if the plugin gets disabled. Should remove all references. """ CONFIG_SECTION = "plugins" CONFIG_OPTION = "active_plugins" instance: Optional["PluginManager"] = None """Default instance""" def __init__(self, folders=None): """folders is a list of paths that will be scanned for plugins. Plugins in later paths will be preferred if they share a name. """ super().__init__() if folders is None: folders = [] self.__scanner = ModuleScanner(folders) self.__modules = {} # name: PluginModule self.__handlers = [] # handler list self.__enabled = set() # (possibly) enabled plugin IDs self.__restore() def rescan(self): """Scan for plugin changes or to initially load all plugins""" print_d("Rescanning..") removed, added = self.__scanner.rescan() # remember IDs of enabled plugin that get reloaded, so we can enable # them again reload_ids = [] for name in removed: if name not in added: continue mod = self.__modules[name] for plugin in mod.plugins: if self.enabled(plugin): reload_ids.append(plugin.id) for name in removed: # share the namespace with ModuleScanner for now self.__remove_module(name) # restore enabled state self.__enabled.update(reload_ids) for name in added: new_module = self.__scanner.modules[name] self.__add_module(name, new_module.module) print_d("Rescanning done.") @property def _modules(self): return self.__scanner.modules.values() @property def _plugins(self) -> Iterable[Plugin]: """All registered plugins""" return (plugin for module in self.__modules.values() for plugin in module.plugins) @property def plugins(self): """Returns a list of plugins with active handlers""" return [p for p in self._plugins if p.handlers] def register_handler(self, handler): """ Registers a handler, attaching it to any current plugins it advertises that it can handle `handler` should probably be a `PluginHandler` """ print_d("Registering handler: %r" % type(handler).__name__) self.__handlers.append(handler) for plugin in self._plugins: if not handler.plugin_handle(plugin): continue if plugin.handlers: plugin.handlers.append(handler) if self.enabled(plugin): handler.plugin_enable(plugin) else: plugin.handlers.append(handler) if self.enabled(plugin): self.enable(plugin, True, force=True) def save(self): print_d("Saving plugins: %d active" % len(self.__enabled)) config.set(self.CONFIG_SECTION, self.CONFIG_OPTION, "\n".join(self.__enabled)) def enabled(self, plugin): """Returns if the plugin is enabled.""" if not plugin.handlers: return False return plugin.id in self.__enabled def enable(self, plugin, status, force=False): """Enable or disable a plugin.""" if not force and self.enabled(plugin) == bool(status): return if not status: print_d("Disable %r" % plugin.id) for handler in plugin.handlers: handler.plugin_disable(plugin) self.__enabled.discard(plugin.id) instance = plugin.instance if instance and hasattr(instance, "disabled"): try: instance.disabled() except Exception: util.print_exc() else: print_d("Enable %r" % plugin.id) obj = plugin.get_instance() if obj and hasattr(obj, "enabled"): try: obj.enabled() except Exception: util.print_exc() for handler in plugin.handlers: handler.plugin_enable(plugin) self.__enabled.add(plugin.id) @property def failures(self): """module name: list of error message text lines""" errors = {} for name, error in self.__scanner.failures.items(): exception = error.exception if isinstance(exception, PluginImportException): if not exception.should_show(): continue errors[name] = [exception.desc] else: errors[name] = error.traceback return errors def quit(self): """Disable plugins and tell all handlers to clean up""" for name in list(self.__modules.keys()): self.__remove_module(name) def __remove_module(self, name): plugin_module = self.__modules.pop(name) for plugin in plugin_module.plugins: if plugin.handlers: self.enable(plugin, False) def __add_module(self, name, module): plugin_mod = PluginModule(name, module) self.__modules[name] = plugin_mod for plugin in plugin_mod.plugins: handlers = [] for handler in self.__handlers: if handler.plugin_handle(plugin): handlers.append(handler) if handlers: plugin.handlers = handlers if self.enabled(plugin): self.enable(plugin, True, force=True) def __restore(self): migrate_old_config() active = config.get(self.CONFIG_SECTION, self.CONFIG_OPTION, "").splitlines() self.__enabled.update(active) print_d("Restoring plugins: %d" % len(self.__enabled)) for plugin in self._plugins: if self.enabled(plugin): self.enable(plugin, True, force=True) PM = PluginManager def plugin_enabled(plugin): """Returns true if the plugin is enabled (or "always" enabled)""" pm = PluginManager.instance enabled = pm.enabled(plugin) or not plugin.can_enable return enabled class PluginConfig(ConfigProxy): """A proxy for a Config object that can be used by plugins. Provides some methods of the Config class but doesn't need a section and prefixes the config option name. """ def __init__(self, prefix, _config=None, _defaults=True): self._prefix = prefix if _config is None: _config = config._config super().__init__( _config, PM.CONFIG_SECTION, _defaults) def _new_defaults(self, real_default_config): return PluginConfig(self._prefix, real_default_config, False) def _option(self, name): return "%s_%s" % (self._prefix, name) def ConfigCheckButton(self, label, option, **kwargs): return ConfigCheckButton(label, PM.CONFIG_SECTION, self._option(option), **kwargs) class PluginConfigMixin: """ Mixin for storage and editing of plugin config in a standard way. """ CONFIG_SECTION = "" """If defined, the section for storing config, otherwise, it will based on a munged `PLUGIN_ID`""" @classmethod def _config_key(cls, name): return cls._get_config_option(name) @classmethod def _get_config_option(cls, option): prefix = cls.CONFIG_SECTION if not prefix: prefix = cls.PLUGIN_ID.lower().replace(" ", "_") return "%s_%s" % (prefix, option) @classmethod def config_get(cls, name, default=""): """Gets a config string value for this plugin""" return config.get(PM.CONFIG_SECTION, cls._config_key(name), default) @classmethod def config_set(cls, name, value): """Saves a config string value for this plugin""" try: config.set(PM.CONFIG_SECTION, cls._config_key(name), value) except config.Error: print_d("Couldn't set config item '%s' to %r" % (name, value)) @classmethod def config_get_bool(cls, name, default=False): """Gets a config boolean for this plugin""" return config.getboolean(PM.CONFIG_SECTION, cls._config_key(name), default) @classmethod def config_get_stringlist(cls, name, default=False): """Gets a config string list for this plugin""" return config.getstringlist(PM.CONFIG_SECTION, cls._config_key(name), default) def config_entry_changed(self, entry, key): """React to a change in a gtk.Entry (by saving it to config)""" if entry.get_property('sensitive'): self.config_set(key, entry.get_text()) @classmethod def ConfigCheckButton(cls, label, name, default=False): """ Create a new `ConfigCheckButton` for `name`, pre-populated correctly """ option = cls._config_key(name) try: config.getboolean(PM.CONFIG_SECTION, option) except config.Error: cls.config_set(name, default) return ConfigCheckButton(label, PM.CONFIG_SECTION, option, populate=True) class ConfProp: def __init__(self, conf, name, default): self._conf = conf self._name = name self._conf.defaults.set(name, default) def __get__(self, *args, **kwargs): return self._conf.get(self._name) def __set__(self, obj, value): self._conf.set(self._name, value) class BoolConfProp(ConfProp): def __get__(self, *args, **kwargs): return self._conf.getboolean(self._name) class IntConfProp(ConfProp): def __get__(self, *args, **kwargs): return self._conf.getint(self._name) class FloatConfProp(ConfProp): def __get__(self, *args, **kwargs): return self._conf.getfloat(self._name) def str_to_color_tuple(s): """Raises ValueError""" lst = [float(p) for p in s.split()] while len(lst) < 4: lst.append(0.0) return tuple(lst) def color_tuple_to_str(t): return " ".join(map(str, t)) class ColorConfProp(ConfProp): def __init__(self, conf, name, default): self._conf = conf self._name = name self._conf.defaults.set(name, color_tuple_to_str(default)) def __get__(self, *args, **kwargs): s = self._conf.get(self._name) try: return str_to_color_tuple(s) except ValueError: return str_to_color_tuple(self._conf.defaults.get(self._name)) def __set__(self, obj, value): self._conf.set(self._name, color_tuple_to_str(value)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1663102510.0 quodlibet-4.6.0/quodlibet/plugins/cover.py0000644000175000017500000001412514310167056017352 0ustar00nicknick# Copyright 2013 Simonas Kazlauskas # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from os import path, makedirs from hashlib import sha1 from gi.repository import GObject from quodlibet import get_cache_dir from quodlibet.qltk import Icons from quodlibet.util.path import escape_filename from quodlibet.util import print_w class CoverSourcePlugin(GObject.Object): """ Plugins that given a song should provide a cover art. The plugin should override following methods and properties: @staticmethod priority() @property cover_path(self) fetch_cover(self) Refer to default function implementation's documentation in order to understand their role. """ __gsignals__ = { 'fetch-success': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'fetch-failure': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'search-complete': (GObject.SignalFlags.RUN_LAST, None, (object,)) } PLUGIN_ICON = Icons.EMBLEM_DOWNLOADS @property def name(self): """Human name of the source""" return type(self).__name__ def __str__(self): return f"<{self.name} for {self.group_by(self.song)!r}>" embedded = False """Whether the source is an embedded one""" def __init__(self, song, cancellable=None): self.song = song self.cancellable = cancellable super().__init__() @classmethod def group_by(cls, song): """Returns a hashable for a song, for grouping songs in groups where only one song per group needs to be searched. Grouping might reduce the chance of finding covers in exchange for performance. This default implementation gives one group for all songs. """ return @staticmethod def priority(): """ Should return float in range [0.0, 1.0] suggesting priority of the cover source. Whether value returned by this method is respected or not is not guaranteed. As a rule of thumb, source's reliability and quality should be compared with other sources and given score between two sources that come close in quality and reliability. There's a table of value ranges sources should respect: * (0.7, 1.0] - local covers; * (0.4, 0.7] - accurate (> 99%) source of high quality (>= 200x200) covers; * (0.2, 0.4] - accurate (> 99%) source of low quality (< 200x200) covers; * (0.0, 0.2] - not very accurate (<= 99%) source of covers, even if they're high quality; * 0.0 - reserved for the fallback cover source. """ return 0.0 @property def cover_directory(self): return cover_dir @property def cover_filename(self): """ Return the filename of the cover which hopefully should not change between songs in the same album and still be unique enough to uniquely identify most (or even better – all) of the albums. The string returned must not contain any characters illegal in most common filesystems. These include /, ?, <, >, \\, :, *, |, ” and ^. Staying in the bounds of ASCII is highly encouraged. Perchance the song lacks data to generate the filename of cover for this provider, None shall be returned. """ key = sha1() # Should be fine as long as the same interpreter is used. data = repr(self.song.album_key) if not isinstance(data, bytes): data = data.encode("utf-8") key.update(data) return escape_filename(key.hexdigest()) @property def cover_path(self): """ Should return the path where cover is expected to be cached. The location should be based in common cache location available in variable `cover_dir` of this module. It doesn't necessarily mean the cover is actually at the returned location neither that it will be stored there at any later time. """ return path.join(self.cover_directory, self.cover_filename) @property def cover(self): """ Method to get cover file from cover provider for a specific song. Should always return a file-like object opened as read-only if any and None otherwise. """ cp = self.cover_path try: return open(cp, 'rb') if cp and path.isfile(cp) else None except IOError: print_w('Failed reading album art "{}"'.format(path)) def search(self): """ Start searching for cover art from a source. After search is completed the `search-complete` event must be emitted regardless of search outcome with a list of dictionaries containing `album`, `artist` and `cover` keys as an argument. If search was unsuccessful, empty list should be returned. By convention better quality and more accurate covers are expected to appear first in the list. """ self.emit('search-complete', []) def fetch_cover(self): """ Method to ask source fetch the cover from its source into location at `self.cover_path`. If this method succeeds in putting the image from its source into `self.cover_path`, `fetch-success` signal shall be emitted and `fetch-failure` otherwise. Return value of this function doesn't have any meaning whatsoever. """ self.fail('This source is incapable of fetching covers') def fail(self, message): """ Shorthand method for emitting `fetch-failure` signals. Most common use pattern would be: return self.fail("Failure message") """ self.emit('fetch-failure', message) cover_dir = path.join(get_cache_dir(), 'covers') try: makedirs(cover_dir) except OSError: pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/editing.py0000664000175000017500000001311114035600052017643 0ustar00nicknick# Copyright 2005 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. from typing import List from gi.repository import Gtk from quodlibet.util import connect_obj from quodlibet.util.misc import total_ordering @total_ordering class RenameFilesPlugin: """Plugins of this type must subclass a GTK widget. They will be packed into the RenameFiles pane (currently a ScrolledWindow hidden with an expander, but that might change). The 'filter' function will be called with the song's original filename as a string (probably in the local filesystem encoding) and the proposed new filename as a unicode object. It should return an appropriate-transformed filename, still as a unicode object. The plugin must provide either a 'changed' or 'preview'. 'preview' causes the entire display to be re-previewed. 'changed' causes the Preview button to made sensitive, and Save to be disabled. If the 'active' attribute is false, the filter will not be called. This is particularly useful for gtk.CheckButtons. The '_order' attribute decides the sort order of the plugin. The default filters have orders between 1 and 2. Plugins have order 0 by default. Plugins with equal orders are sorted by class name.""" _order = 0 active = False def filter(self, original_filename, value): return value def filter_list(self, origs, names): return list(map(self.filter, origs, names)) def __eq__(self, other): return (self._order, type(self).__name__) == \ (other._order, type(other).__name__) def __lt__(self, other): return (self._order, type(self).__name__) < \ (other._order, type(other).__name__) @total_ordering class TagsFromPathPlugin: """Plugins of this type must subclass a GTK widget. They will be packed into the TagsFromPath pane (currently a ScrolledWindow hidden with an expander, but that might change). The 'filter' function will be called with the tag and proposed value as a unicode object. It should return an appropriate-transformed filename, still as a unicode object. If you need to work on a set of filenames at once, you should instead overload the 'filter_list' function, which takes two lists; one of original filenames, the other of proposed new filenames. The default filter_list function calls filter on each item. The plugin must provide either a 'changed' or 'preview'. 'preview' causes the entire display to be re-previewed. 'changed' causes the Preview button to made sensitive, and Save to be disabled. If the 'active' attribute is false, the filter will not be called. This is particularly useful for gtk.CheckButtons. The '_order' attribute decides the sort order of the plugin. The default filters have orders between 1 and 2. Plugins have order 0 by default. Plugins with equal orders are sorted by class name.""" _order = 0 active = False def filter(self, tag, value): return value def __eq__(self, other): return (self._order, type(self).__name__) == \ (other._order, type(other).__name__) def __lt__(self, other): return (self._order, type(self).__name__) < \ (other._order, type(other).__name__) class EditTagsPlugin(Gtk.ImageMenuItem): """Plugins of this type are subclasses of gtk.ImageMenuItem. They will be added to the context menu of the EditTags tree view. The 'tags' attribute is a list of tags this plugin should appear on, or false if it should appear for all tags. This must be a class attribute, as it is checked before instantiation. The 'needs' attribute is a list of tags that must be editable in the currently selected songs for the plugin to be sensitive. The constructor is called with the tag and value for that row. This can be used to set the sensitivity of the menu item, or change its text. When clicked, the 'activated' function is called on the object, again with the tag name and value. It should return a list of (tag, value) tuples to replace the previous tag/value with. The '_order' attribute decides the sort order of the plugin. The default items have orders between 0 and 1. Plugins have order 2.0 by default. Plugins with equal orders are sorted by class name. How to Handle Submenus ---------------------- If the menu item is given a submenu, magic happens. In particular, the callbacks are proxied to the submenu's items, and are attached, via connect_object, to make sure activated is called on the original item. So, to handle submenus, 1. Make a submenu and attach it to your menu item.2 2. To each item in the submenu, attach its 'activate' signal to something appropriate to prepare the original item's activated method, 3. Because that method will be called after the subitem is clicked on, and your activate handler runs. """ tags: List[str] = [] needs: List[str] = [] _order = 2.0 def activated(self, tag, value): return [(tag, value)] def connect(self, signal, callback, *args, **kwargs): if self.get_submenu(): for item in self.get_submenu().get_children(): connect_obj(item, signal, callback, self, *args, **kwargs) else: super().connect( signal, callback, *args, **kwargs) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/plugins/events.py0000644000175000017500000001164114327505043017540 0ustar00nicknick# Copyright 2005 Michael Urman, Joe Wreschnig # 2014, 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GObject from quodlibet.util.dprint import print_e from quodlibet.plugins import PluginHandler from quodlibet.util.songwrapper import SongWrapper, ListWrapper from quodlibet.util.songwrapper import check_wrapper_changed from quodlibet.util import connect_obj from quodlibet.errorreport import errorhook class EventPlugin: """Plugins that run in the background and receive events. Event plugins, unlike other plugins, are instantiated on startup and the same instance is used even when the plugin is enabled or disabled. Methods `plugin_on_*` can be overridden to provide behaviour hooks """ def plugin_on_song_started(self, song): pass def plugin_on_song_ended(self, song, stopped): pass def plugin_on_added(self, songs): pass def plugin_on_changed(self, songs): pass def plugin_on_removed(self, songs): pass def plugin_on_paused(self): pass def plugin_on_unpaused(self): pass def plugin_on_seek(self, song, msec): pass def plugin_on_error(self, song, error): pass def plugin_on_songs_selected(self, songs): """Called when the selection in main songlist changes""" pass PLUGIN_INSTANCE = True def enabled(self): """Called when the plugin is enabled.""" pass def disabled(self): """Called when the plugin is disabled.""" pass def list_signal_names(type_): """List of supported signal names for a GType, instance or class""" type_ = getattr(type_, "__gtype__", type_) names = [] if not type_.is_instantiatable() and not type_.is_interface(): return names names.extend(GObject.signal_list_names(type_)) if type_.parent: names.extend(list_signal_names(type_.parent)) for iface in type_.interfaces: names.extend(list_signal_names(iface)) return names def _map_signals(obj, prefix="plugin_on_", blacklist=None): sigs = list_signal_names(obj) if blacklist is None: blacklist = [] sigs = [s for s in sigs if s not in blacklist] sigs = [(s, prefix + s.replace('-', '_')) for s in sigs] return sigs class EventPluginHandler(PluginHandler): def __init__(self, librarian=None, player=None, songlist=None): if librarian: sigs = _map_signals(librarian, blacklist=("notify",)) for event, handle in sigs: def handler(librarian, *args): self.__invoke(librarian, args[-1], *args[:-1]) librarian.connect(event, handler, event) if librarian and player: sigs = _map_signals(player, blacklist=("notify",)) for event, handle in sigs: def cb_handler(librarian, *args): self.__invoke(librarian, args[-1], *args[:-1]) connect_obj(player, event, cb_handler, librarian, event) if songlist: def __selection_changed_cb(songlist, selection): songs = songlist.get_selected_songs() self.__invoke(self.librarian, "songs_selected", songs) songlist.connect("selection-changed", __selection_changed_cb) self.librarian = librarian self.__plugins = {} self.__sidebars = {} def __invoke(self, librarian, event, *args): args = list(args) if args and args[0]: if isinstance(args[0], dict): args[0] = SongWrapper(args[0]) elif isinstance(args[0], (set, list)): args[0] = ListWrapper(args[0]) for plugin in list(self.__plugins.values()): method_name = 'plugin_on_' + event.replace('-', '_') handler = getattr(plugin, method_name, None) def overridden(obj, name): return name in type(obj).__dict__ if overridden(plugin, method_name): try: handler(*args) except Exception: print_e("Error during %s on %s" % (method_name, type(plugin))) errorhook() if event not in ["removed", "changed"] and args: songs = args[0] if not isinstance(songs, (set, list)): songs = [songs] songs = filter(None, songs) check_wrapper_changed(librarian, songs) def plugin_handle(self, plugin): return issubclass(plugin.cls, EventPlugin) def plugin_enable(self, plugin): self.__plugins[plugin.cls] = plugin.get_instance() def plugin_disable(self, plugin): self.__plugins.pop(plugin.cls) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/gstelement.py0000664000175000017500000000252514035600052020376 0ustar00nicknick# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. class GStreamerPlugin: """GStreamer Plugins define an element that gets inserted into the GStreamer pipeline before the audio sink and after the playbin. The method setup_element should return a new element instance or None: self.setup_element() One optional method can be implemented: self.update_element(element) update_element should apply all settings and will be called after queue_update or on pipeline creation etc. All plugin elements will be sorted by their priority attribute (higher priority elements come first) To notify setting changes, call queue_update. """ PLUGIN_ICON = "audio-volume-high" _handler = None priority = 0 @classmethod def setup_element(cls): """Return a new element instance or None""" return None @classmethod def update_element(cls, element): """Apply settings to the instance""" pass @classmethod def queue_update(cls): """Call if you want to update settings""" cls._handler._queue_update(cls) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/gui.py0000664000175000017500000000666714035600052017026 0ustar00nicknick# Copyright 2014, 2016 Nick Boultbee # 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet import config, print_d, app from quodlibet.plugins import PluginHandler from quodlibet.qltk import get_menu_item_top_parent from quodlibet.qltk import Icons from gi.repository import Gtk class UserInterfacePlugin: """Plugins that provide a (Gtk+ Widget) to display as a side bar (currently) in the main Quod Libet Window. These can be combined well with an EventPlugin to listen for current song or selection changes. TODO: generalise this better. See #152, #2273, #1991. """ PLUGIN_INSTANCE = True def create_sidebar(self): """If defined, returns a Gtk.Box to populate the sidebar""" pass class UserInterfacePluginHandler(PluginHandler): def __init__(self): self.__plugins = {} self.__sidebars = {} def plugin_handle(self, plugin): return issubclass(plugin.cls, UserInterfacePlugin) def plugin_enable(self, plugin): self.__plugins[plugin.cls] = pl_obj = plugin.get_instance() sidebar = pl_obj.create_sidebar() app.window.hide_side_book() if sidebar: print_d("Enabling sidebar for %s" % plugin.cls) self.__sidebars[plugin] = app.window.add_sidebar( sidebar, name=plugin.name) sidebar.show_all() def plugin_disable(self, plugin): widget = self.__sidebars.get(plugin) if widget: print_d("Removing sidebar %s" % widget) app.window.remove_sidebar(widget) self.__plugins.pop(plugin.cls) class MenuItemPlugin(Gtk.ImageMenuItem): """ A base plugin that appears in a menu, typically. During plugin callbacks, `self.plugin_window` will be available. This is the `Gtk.Window` that the plugin was invoked from. It provides access to two important widgets, `self.plugin_window.browser` and `self.plugin_window.songlist`. """ MAX_INVOCATIONS = config.getint("plugins", "default_max_invocations", 30) """An upper limit on how many instances of the plugin should be launched at once without warning. Heavyweight plugins should override this value to prevent users killing their performance by opening on many songs.""" REQUIRES_ACTION = False """This plugin will run a user interface first (e.g. dialog) requiring action from the user. The menu entry may be altered accordingly""" def __init__(self): label = self.PLUGIN_NAME + ("…" if self.REQUIRES_ACTION else "") super().__init__(label=label) self.__set_icon() self.__initialized = True @property def plugin_window(self): return get_menu_item_top_parent(self) def __set_icon(self): """Sets the GTK icon for this plugin item""" icon = getattr(self, "PLUGIN_ICON", Icons.SYSTEM_RUN) image = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.MENU) self.set_always_show_image(True) self.set_image(image) @property def initialized(self): # If the GObject __init__ method is bypassed, it can cause segfaults. # This explicitly prevents a bad plugin from taking down the app. return self.__initialized ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/playlist.py0000664000175000017500000001674114035600052020075 0ustar00nicknick# Copyright 2013-2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import ngettext, _ from quodlibet.qltk import get_top_parent, get_menu_item_top_parent from quodlibet.qltk.msg import ConfirmationPrompt from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.util import print_exc, format_int_locale from quodlibet.util.dprint import print_d, print_e from quodlibet.plugins import PluginHandler, PluginManager from quodlibet.plugins.gui import MenuItemPlugin def confirm_multi_playlist_invoke(parent, plugin_name, count): """Dialog to confirm invoking a plugin with X playlists in case X is high """ params = {"name": plugin_name, "count": format_int_locale(count)} title = ngettext("Run the plugin \"%(name)s\" on %(count)s playlist?", "Run the plugin \"%(name)s\" on %(count)s playlists?", count) % params description = "" ok_text = _("_Run Plugin") prompt = ConfirmationPrompt(parent, title, description, ok_text).run() return prompt == ConfirmationPrompt.RESPONSE_INVOKE class PlaylistPlugin(MenuItemPlugin): """ Playlist plugins are much like songsmenu plugins, and provide one or more of the following instance methods: self.plugin_single_playlist(playlist) self.plugin_playlist(song) self.plugin_playlists(songs) All matching provided callables on a single object are called in the above order if they match until one returns a true value. The `single_` variant is only called if a single song/album is selected. The singular version is called once for each selected playlist, but the plural version is called with a list of playlists. Returning `True` from these signifies a change was made and the UI / library should update; otherwise this isn't guaranteed. Currently (01/2016) only the singular forms are actually supported in the UI, but this won't always be the case. To make your plugin insensitive if unsupported playlists are selected, a method that takes a list of songs and returns True or False to set the sensitivity of the menu entry: self.plugin_handles(playlists) All of this is managed by the constructor, so make sure it gets called if you override it (you shouldn't have to). Note: If inheriting both `PlaylistPlugin` and `SongsMenuPlugin`, it (currently) needs to be done in that order. """ plugin_single_playlist = None plugin_playlist = None plugin_playlists = None def __init__(self, playlists=None, library=None): super().__init__() self._library = library self._playlists = playlists or [] self.set_sensitive(bool(self.plugin_handles(playlists))) def plugin_handles(self, playlists): return True class PlaylistPluginHandler(PluginHandler): """Handles PlaylistPlugins""" def init_plugins(self): PluginManager.instance.register_handler(self) def __init__(self, confirmer=None): """Takes an optional `confirmer`, mainly for testing""" self.__plugins = [] self._confirm_multiple = (confirmer or confirm_multi_playlist_invoke) def populate_menu(self, menu, library, browser, playlists): """Appends items onto `menu` for each enabled playlist plugin, separated as necessary. """ attrs = ['plugin_playlist', 'plugin_playlists'] if len(playlists) == 1: attrs.append('plugin_single_playlist') items = [] kinds = self.__plugins kinds.sort(key=lambda plugin: plugin.PLUGIN_ID) print_d("Found %d Playlist plugin(s): %s" % (len(kinds), kinds)) for Kind in kinds: usable = any([callable(getattr(Kind, s)) for s in attrs]) if usable: try: items.append(Kind(playlists=playlists, library=library)) except: print_e("Couldn't initialise playlist plugin %s: " % Kind) print_exc() items = [i for i in items if i.initialized] if items: menu.append(SeparatorMenuItem()) for item in items: try: menu.append(item) args = (library, browser, playlists) if item.get_submenu(): for subitem in item.get_submenu().get_children(): subitem.connect( 'activate', self.__on_activate, item, *args) else: item.connect( 'activate', self.__on_activate, item, *args) except: print_exc() item.destroy() def handle(self, plugin_id, library, browser, playlists): """Start a plugin directly without a menu""" for plugin in self.__plugins: if plugin.PLUGIN_ID == plugin_id: try: plugin = plugin(playlists, library) except Exception: print_exc() else: parent = get_top_parent(browser) self.__handle(plugin, library, browser, playlists, parent) return def __on_activate(self, item, plugin, library, browser, playlists): parent = get_menu_item_top_parent(item) self.__handle(plugin, library, browser, playlists, parent) def __handle(self, plugin, library, browser, playlists, parent): if len(playlists) == 0: return if (len(playlists) == 1 and callable(plugin.plugin_single_playlist)): pl = playlists[0] try: ret = plugin.plugin_single_playlist(pl) except Exception: print_exc() else: if ret: print_d("Updating %s" % pl) browser.changed(pl) browser.activate() return if callable(plugin.plugin_playlist): total = len(playlists) if total > plugin.MAX_INVOCATIONS: if not self._confirm_multiple( parent, plugin.PLUGIN_NAME, total): return try: ret = map(plugin.plugin_playlist, playlists) if ret: for update, pl in zip(ret, playlists): if update: print_d("Updating %s" % pl) browser.changed(pl) browser.activate() except Exception: print_exc() else: if any(ret): return if callable(plugin.plugin_playlists): try: if plugin.plugin_playlists(playlists): browser.activate() except Exception: print_exc() for pl in playlists: browser.changed(pl) def plugin_handle(self, plugin): return issubclass(plugin.cls, PlaylistPlugin) def plugin_enable(self, plugin): self.__plugins.append(plugin.cls) def plugin_disable(self, plugin): self.__plugins.remove(plugin.cls) # Single instance PLAYLIST_HANDLER = PlaylistPluginHandler() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/playorder.py0000664000175000017500000000423014035600052020223 0ustar00nicknick# Copyright 2007 Joe Wreschnig # 2016-17 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Optional import quodlibet.qltk.playorder class PlayOrderPlugin(quodlibet.qltk.playorder.Order): """Play order plugins define alternate play orders for Quod Libet, of the two types: Reorder (aka Shuffle) and Repeat. Implementations must choose to subclass `RepeatPlugin` or `ShufflePlugin`. They appear, when enabled, in the combo boxes in the lower left of the main window, as well as in the tray icon context menu. If explicit "next song" button presses should be handled differently than reaching the end of a song, use: def next_implicit(self, playlist, iter): ... def next_explicit(self, playlist, iter): ... def previous_explicit(self, playlist, iter): ... def previous_implicit(self, playlist, iter): ... """ # Note these values unset the base versions, as the plugin handler logic # does some auto-setting of these, based on PLUGIN_NAME, if they're None name: Optional[str] = None display_name = None accelerated_name = None priority = 200 """Plugins default to lower priority than built-ins""" class RepeatPlugin(PlayOrderPlugin, quodlibet.qltk.playorder.Repeat): """Repeat plugins add new ways to repeat an existing, possibly shuffled playlist. Note that they must delegate to the underlying `Order` (typically a `Reorder`) in order for the UI to function as intended. As such, the only method necessary to implement from `Repeat` is def next(self, playlist, iter): ... """ pass class ShufflePlugin(PlayOrderPlugin, quodlibet.qltk.playorder.Reorder): """Shuffle plugins add new ways to reorder a given song list Shuffle / plugins must define at least two missing methods from `Reorder`, i.e. def next(self, playlist, iter): ... def previous(self, playlist, iter): ... """ pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/plugins/query.py0000664000175000017500000000622414231604332017377 0ustar00nicknick# Copyright 2016 Ryan Dellenbaugh # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Optional, Any from gi.repository import Gtk from quodlibet import _ from quodlibet import util from quodlibet.formats import AudioFile from quodlibet.plugins import PluginHandler, PluginManager from quodlibet.qltk import Icons, Align, Frame def markup_for_syntax(text: str) -> str: return f"{util.escape(text)}" class QueryPlugin: """ Query plugins provide extensions to the search query syntax used in '@' queries, like '@(name: body)' The plugin must provide the search instance method: self.search(song, body) The plugin may optionally provide the parse_body method: self.parse_body(body) This method will be called once, when the query is parsed, with the body string from the query, or None if the query contained no body. It should return a value representing the parsed body, to be used in self.search. If the provided body is invalid, the method may raise a QueryPluginError to indicate that all matches should fail. In this case search will not be called. """ def search(self, song: AudioFile, body: Optional[Any]) -> bool: """Whether to match the given song :param song: the song in question :param body: the query body :returns: whether the song matches the query for the given body. """ raise NotImplementedError key: Optional[str] = None """The name used for query syntax, if not the name of the plugin""" PLUGIN_ICON = Icons.EDIT_FIND usage: Optional[str] = None """Override this markup to show example usage for users""" def parse_body(self, body: str) -> str: return body @classmethod def PluginPreferences(cls, window): if not cls.usage: return Gtk.VBox() label = Gtk.Label(label=cls.usage, use_markup=True, xalign=0.0, yalign=0.5, wrap=True, width_chars=30, selectable=True) return Frame(_("Usage"), child=Align(label, border=9, halign=Gtk.Align.START, valign=Gtk.Align.START)) class QueryPluginError(Exception): pass class QueryPluginHandler(PluginHandler): """Maintains a dictionary of enabled Query Plugins by key""" def init_plugins(self): PluginManager.instance.register_handler(self) def __init__(self): self.plugins = {} def plugin_handle(self, plugin): return issubclass(plugin.cls, QueryPlugin) def plugin_enable(self, plugin): self.plugins[plugin.cls.key or plugin.name] = plugin.cls() def plugin_disable(self, plugin): del self.plugins[plugin.cls.key or plugin.name] def get_plugin(self, key): return self.plugins[key] QUERY_HANDLER = QueryPluginHandler() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/plugins/songshelpers.py0000664000175000017500000000202314035600052020734 0ustar00nicknick# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. """Various `plugin_handles` helpers""" def is_a_file(song): return song.is_file def is_writable(song): return bool(song.can_change()) and song.is_writable def is_finite(song): return not song.multisong def can_be_queued(song): return not song.can_add def has_writable_image(song): return song.can_change_images def has_bookmark(song): return bool(song.bookmarks) # Higher order functions def any_song(*song_funcs): return __handles_factory(any, song_funcs) def each_song(*song_funcs): return __handles_factory(all, song_funcs) def __handles_factory(reducer, song_funcs): def handles(_, songs): return reducer(all(f(s) for f in song_funcs) for s in songs) return handles ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/plugins/songsmenu.py0000644000175000017500000000533014327505043020250 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2013-2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.plugins.gui import MenuItemPlugin from quodlibet.util.songwrapper import check_wrapper_changed class SongsMenuPlugin(MenuItemPlugin): """Plugins of this type are subclasses of Gtk.ImageMenuItem. They will be added, in alphabetical order, to the "Plugins" menu that appears when songs or lists of songs are right-clicked. They provide one or more of the following instance methods: self.plugin_single_song(song) self.plugin_song(song) self.plugin_songs(songs) self.plugin_single_album(album) self.plugin_album(album) self.plugin_albums(albums) All matching provided callables on a single object are called in the above order if they match until one returns a true value. They are not called with real AudioFile objects, but rather wrappers that automatically detect metadata or disk changes, and save or reload the files as appropriate. If the wrappers get changed after the above methods return, call self.plugin_finish() to check for changes. The single_ variant is only called if a single song/album is selected. The singular version is called once for each selected song/album, whereas the plural version is called with a list of songs/albums. An album is a list of songs all with the same album, labelid, and/or musicbrainz_albumid tags (like in the Album List). To make your plugin insensitive if unsupported songs are selected, a method that takes a list of songs and returns True or False to set the sensitivity of the menu entry: self.plugin_handles(songs) All of this is managed by the constructor for SongsMenuPlugin, so make sure it gets called if you override it (you shouldn't have to). """ plugin_single_song = None plugin_song = None plugin_songs = None plugin_single_album = None plugin_album = None plugin_albums = None def __init__(self, songs=None, library=None): super().__init__() self.__library = library self.__songs = songs or [] self.set_sensitive(bool(self.plugin_handles(songs))) def plugin_handles(self, songs): return True @property def handles_albums(self): return any(map(callable, [self.plugin_single_album, self.plugin_album, self.plugin_albums])) def plugin_finish(self): check_wrapper_changed(self.__library, self.__songs) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692735242.0076022 quodlibet-4.6.0/quodlibet/qltk/0000755000175000017500000000000014471213412015145 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/qltk/__init__.py0000644000175000017500000004232314327505043017266 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2012 Christoph Reiter # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import signal import socket from typing import Union from urllib.parse import urlparse import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib, GObject, PangoCairo from senf import fsn2bytes, bytes2fsn, uri2fsn from quodlibet.util import print_d, print_w, is_windows, is_osx def show_uri(label, uri): """Shows a URI. The URI can be anything handled by GIO or a quodlibet specific one. Currently handled quodlibet uris: - quodlibet:///prefs/plugins/ Args: label (str) uri (str) the uri to show Returns: True on success, False on error """ parsed = urlparse(uri) if parsed.scheme == "quodlibet": if parsed.netloc != "": print_w("Unknown QuodLibet URL format (%s)" % uri) return False else: return __show_quodlibet_uri(parsed) elif parsed.scheme == "file" and (is_windows() or is_osx()): # Gio on non-Linux can't handle file URIs for some reason, # fall back to our own implementation for now from quodlibet.qltk.showfiles import show_files try: filepath = uri2fsn(uri) except ValueError: return False else: return show_files(filepath, []) else: # Gtk.show_uri_on_window exists since 3.22 try: if hasattr(Gtk, "show_uri_on_window"): from quodlibet.qltk import get_top_parent return Gtk.show_uri_on_window(get_top_parent(label), uri, 0) else: return Gtk.show_uri(None, uri, 0) except GLib.Error: return False def __show_quodlibet_uri(uri): if uri.path.startswith("/prefs/plugins/"): from .pluginwin import PluginWindow print_d("Showing plugin prefs resulting from URI (%s)" % (uri, )) return PluginWindow().move_to(uri.path[len("/prefs/plugins/"):]) else: return False def get_fg_highlight_color(widget): """Returns a color useable for highlighting things on top of the standard background color. Args: widget (Gtk.Widget) Returns: Gdk.RGBA """ context = widget.get_style_context() if hasattr(Gtk.StateFlags, "LINK"): # gtk+ >=3.12 context.save() context.set_state(Gtk.StateFlags.LINK) color = context.get_color(context.get_state()) context.restore() else: value = GObject.Value() value.init(Gdk.Color) value.set_boxed(None) context.get_style_property("link-color", value) color = Gdk.RGBA() old_color = value.get_boxed() if old_color is not None: color.parse(old_color.to_string()) return color def get_primary_accel_mod(): """Returns the primary Gdk.ModifierType modifier. cmd on osx, ctrl everywhere else. """ return Gtk.accelerator_parse("")[1] def redraw_all_toplevels(): """A hack to trigger redraws for all windows and widgets.""" for widget in Gtk.Window.list_toplevels(): if not widget.get_realized(): continue if widget.is_active(): widget.queue_draw() continue sensitive = widget.get_sensitive() widget.set_sensitive(not sensitive) widget.set_sensitive(sensitive) def selection_set_songs(selection_data, songs): """Stores filenames of the passed songs in a Gtk.SelectionData""" filenames = [] for filename in (song["~filename"] for song in songs): filenames.append(fsn2bytes(filename, "utf-8")) type_ = Gdk.atom_intern("text/x-quodlibet-songs", True) selection_data.set(type_, 8, b"\x00".join(filenames)) def selection_get_filenames(selection_data): """Extracts the filenames of songs set with selection_set_songs() from a Gtk.SelectionData. """ data_type = selection_data.get_data_type() assert data_type.name() == "text/x-quodlibet-songs" items = selection_data.get_data().split(b"\x00") return [bytes2fsn(i, "utf-8") for i in items] def get_top_parent(widget): """Return the ultimate parent of a widget; the assumption that code using this makes is that it will be a Gtk.Window, i.e. the widget is fully packed when this is called.""" parent = widget and widget.get_toplevel() if parent and parent.is_toplevel(): return parent else: return None def get_menu_item_top_parent(widget): """Returns the toplevel for a menu item or None if the menu and none of its parents isn't attached to a widget """ while isinstance(widget, Gtk.MenuItem): menu = widget.get_parent() if not menu: return widget = menu.get_attach_widget() return get_top_parent(widget) def find_widgets(widget, type_): """Given a widget, find all children that are a subclass of type_ (including itself) Args: widget (Gtk.Widget) type_ (type) Returns: List[Gtk.Widget] """ found = [] if isinstance(widget, type_): found.append(widget) if isinstance(widget, Gtk.Container): for child in widget.get_children(): found.extend(find_widgets(child, type_)) return found def menu_popup(menu, shell, item, func, *args): """Wrapper to fix API break: https://git.gnome.org/browse/gtk+/commit/?id=8463d0ee62b4b22fa """ if func is not None: def wrap_pos_func(menu, *args): return func(menu, args[-1]) else: wrap_pos_func = None return menu.popup(shell, item, wrap_pos_func, *args) def _popup_menu_at_widget(menu, widget, button, time, under): def pos_func(menu, data, widget=widget): screen = widget.get_screen() ref = get_top_parent(widget) menu.set_screen(screen) x, y = widget.translate_coordinates(ref, 0, 0) dx, dy = ref.get_window().get_origin()[1:] wa = widget.get_allocation() # fit menu to screen, aligned per text direction screen_width = screen.get_width() screen_height = screen.get_height() menu.realize() ma = menu.get_allocation() menu_y_under = y + dy + wa.height menu_y_above = y + dy - ma.height if under: menu_y = menu_y_under if menu_y + ma.height > screen_height and menu_y_above > 0: menu_y = menu_y_above else: menu_y = menu_y_above if menu_y < 0 and menu_y_under + ma.height < screen_height: menu_y = menu_y_under if Gtk.Widget.get_default_direction() == Gtk.TextDirection.LTR: menu_x = min(x + dx, screen_width - ma.width) else: menu_x = max(0, x + dx - ma.width + wa.width) return (menu_x, menu_y, True) # x, y, move_within_screen menu_popup(menu, None, None, pos_func, None, button, time) def _ensure_menu_attached(menu, widget): assert widget is not None # Workaround the menu inheriting the wrong colors with the Ubuntu 12.04 # default themes. Attaching to the parent kinda works... submenus still # have the wrong color. if isinstance(widget, Gtk.Button): widget = widget.get_parent() or widget attached_widget = menu.get_attach_widget() if attached_widget is widget: return if attached_widget is not None: menu.detach() menu.attach_to_widget(widget, None) def popup_menu_under_widget(menu, widget, button, time): _ensure_menu_attached(menu, widget) _popup_menu_at_widget(menu, widget, button, time, True) def popup_menu_above_widget(menu, widget, button, time): _ensure_menu_attached(menu, widget) _popup_menu_at_widget(menu, widget, button, time, False) def popup_menu_at_widget(menu, widget, button, time): _ensure_menu_attached(menu, widget) menu_popup(menu, None, None, None, None, button, time) def add_fake_accel(widget, accel): """Accelerators are only for window menus and global keyboard shortcuts. Since we want to use them in context menus as well, to indicate which key events the parent widget knows about, we use a global fake accelgroup without any actions.. """ if not hasattr(add_fake_accel, "_group"): add_fake_accel._group = Gtk.AccelGroup() group = add_fake_accel._group key, val = Gtk.accelerator_parse(accel) assert key is not None assert val is not None widget.add_accelerator( 'activate', group, key, val, Gtk.AccelFlags.VISIBLE) def is_accel(event, *accels): """Checks if the given keypress Gdk.Event matches any of accelerator strings. example: is_accel(event, "z") Args: *accels: one ore more `str` Returns: bool Raises: ValueError: in case any of the accels could not be parsed """ assert accels if event.type != Gdk.EventType.KEY_PRESS: return False # ctrl+shift+x gives us ctrl+shift+X and accelerator_parse returns # lowercase values for matching, so lowercase it if possible keyval = event.keyval if not keyval & ~0xFF: keyval = ord(chr(keyval).lower()) default_mod = Gtk.accelerator_get_default_mod_mask() keymap = Gdk.Keymap.get_default() for accel in accels: accel_keyval, accel_mod = Gtk.accelerator_parse(accel) if accel_keyval == 0 and accel_mod == 0: raise ValueError("Invalid accel: %s" % accel) # If the accel contains non default modifiers matching will # never work and since no one should use them, complain non_default = accel_mod & ~default_mod if non_default: print_w("Accelerator '%s' contains a non default modifier '%s'." % (accel, Gtk.accelerator_name(0, non_default) or "")) # event.state contains the real mod mask + the virtual one, while # we usually pass only virtual one as text. # This adds the real one so that they match in the end. accel_mod = keymap.map_virtual_modifiers(accel_mod)[1] # Remove everything except default modifiers and compare if (accel_keyval, accel_mod) == (keyval, event.state & default_mod): return True return False def add_css(widget: Gtk.Widget, css: Union[bytes, str]): """Add css for the widget, overriding the theme. Can raise GLib.GError in case the css is invalid """ if not isinstance(css, bytes): css = css.encode("utf-8") provider = Gtk.CssProvider() provider.load_from_data(css) context = widget.get_style_context() context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) def remove_padding(widget): """Removes padding on supplied widget""" return add_css(widget, " * { padding: 0px; } ") def is_instance_of_gtype_name(instance, name): """Returns False if the gtype can't be found""" try: gtype = GObject.type_from_name(name) except Exception: return False else: pytype = gtype.pytype if pytype is None: return False return isinstance(instance, pytype) def is_wayland(): display = Gdk.Display.get_default() if display is None: return False return is_instance_of_gtype_name(display, "GdkWaylandDisplay") def get_backend_name(): """The GDK backend name""" display = Gdk.Display.get_default() if display is not None: name = display.__gtype__.name if name.startswith("Gdk"): name = name[3:] if name.endswith("Display"): name = name[:-7] return name return u"Unknown" def get_font_backend_name() -> str: """The PangoCairo font backend name""" font_map = PangoCairo.FontMap.get_default() name = font_map.__gtype__.name.lower() name = name.split("pangocairo")[-1].split("fontmap")[0] if name == "fc": name = "fontconfig" return name gtk_version = (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) pygobject_version = gi.version_info def io_add_watch(fd, prio, condition, func, *args, **kwargs): try: # The new gir bindings don't fail with an invalid fd, # and we can't do the same with the static ones (return a valid # source ID…) so fail with newer pygobject as well. if isinstance(fd, int) and fd < 0: raise ValueError("invalid fd") elif hasattr(fd, "fileno") and fd.fileno() < 0: raise ValueError("invalid fd") return GLib.io_add_watch(fd, prio, condition, func, *args, **kwargs) except TypeError: # older pygi kwargs["priority"] = prio return GLib.io_add_watch(fd, condition, func, *args, **kwargs) def add_signal_watch(signal_action, _sockets=[]): """Catches signals which should exit the program and calls `signal_action` after the main loop has started, even if the signal occurred before the main loop has started. """ # See https://bugzilla.gnome.org/show_bug.cgi?id=622084 for details sig_names = ["SIGINT", "SIGTERM", "SIGHUP"] if os.name == "nt": sig_names = ["SIGINT", "SIGTERM"] signals = {} for name in sig_names: id_ = getattr(signal, name, None) if id_ is None: continue signals[id_] = name for signum, name in signals.items(): # Before the mainloop starts we catch signals in python # directly and idle_add the app.quit def idle_handler(signum, frame): print_d("Python signal handler activated: %s" % signals[signum]) GLib.idle_add(signal_action, priority=GLib.PRIORITY_HIGH) print_d("Register Python signal handler: %r" % name) signal.signal(signum, idle_handler) read_socket, write_socket = socket.socketpair() for sock in [read_socket, write_socket]: sock.setblocking(False) # prevent it from being GCed and leak it _sockets.append(sock) def signal_notify(source, condition): if condition & GLib.IOCondition.IN: try: return bool(read_socket.recv(1)) except EnvironmentError: return False else: return False if os.name == "nt": channel = GLib.IOChannel.win32_new_socket(read_socket.fileno()) else: channel = GLib.IOChannel.unix_new(read_socket.fileno()) io_add_watch(channel, GLib.PRIORITY_HIGH, (GLib.IOCondition.IN | GLib.IOCondition.HUP | GLib.IOCondition.NVAL | GLib.IOCondition.ERR), signal_notify) signal.set_wakeup_fd(write_socket.fileno()) def enqueue(songs): songs = [s for s in songs if s.can_add] if songs: from quodlibet import app app.window.playlist.enqueue(songs) class ThemeOverrider: """Allows registering global Gtk.StyleProviders for a specific theme. They get activated when the theme gets active and removed when the theme changes to something else. """ def __init__(self): self._providers = {} self._active_providers = [] settings = Gtk.Settings.get_default() settings.connect("notify::gtk-theme-name", self._on_theme_name_notify) self._update_providers() def register_provider(self, theme_name, provider): """ Args: theme_name (str): A gtk+ theme name e.g. "Adwaita" or empty to apply to all themes provider (Gtk.StyleProvider) """ self._providers.setdefault(theme_name, []).append(provider) self._update_providers() def _update_providers(self): settings = Gtk.Settings.get_default() theme_name = settings.get_property("gtk-theme-name") wanted_providers = \ self._providers.get(theme_name, []) + self._providers.get("", []) for provider in list(self._active_providers): if provider not in wanted_providers: Gtk.StyleContext.remove_provider_for_screen( Gdk.Screen.get_default(), provider) self._active_providers.remove(provider) for provider in wanted_providers: if provider not in self._active_providers: Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) self._active_providers.append(provider) def _on_theme_name_notify(self, settings, gparam): self._update_providers() from .msg import Message, ErrorMessage, WarningMessage from .x import Align, Button, ToggleButton, Notebook, SeparatorMenuItem, \ WebImage, MenuItem, Frame, EntryCompletion from .icons import Icons from .window import Window, UniqueWindow, Dialog from .paned import ConfigRPaned, ConfigRHPaned Message, ErrorMessage, WarningMessage Align, Button, ToggleButton, Notebook, SeparatorMenuItem, \ WebImage, MenuItem, Frame, EntryCompletion Icons Window, UniqueWindow, Dialog ConfigRPaned, ConfigRHPaned ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/qltk/_editutils.py0000644000175000017500000001437214327505043017677 0ustar00nicknick# Copyright 2004-2006 Joe Wreschnig, Michael Urman, Iñigo Serna # 2014 Nick Boultbee # 2017 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from typing import Optional, Type from gi.repository import Gtk, GObject from senf import fsn2text from quodlibet import config from quodlibet import util from quodlibet import _ from quodlibet.plugins import PluginHandler from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk.msg import WarningMessage, ErrorMessage from quodlibet.qltk import Icons from quodlibet.util import connect_obj, connect_destroy from quodlibet.errorreport import errorhook class OverwriteWarning(WarningMessage): RESPONSE_SAVE = 1 def __init__(self, parent, song): title = _("Tag may not be accurate") fn_format = util.bold(fsn2text(song("~basename"))) description = _("%(file-name)s changed while the program was running. " "Saving without refreshing your library may " "overwrite other changes to the song.") % {"file-name": fn_format} super().__init__( parent, title, description, buttons=Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, self.RESPONSE_SAVE) self.set_default_response(Gtk.ResponseType.CANCEL) class WriteFailedError(ErrorMessage): def __init__(self, parent, song): title = _("Unable to save song") fn_format = util.bold(fsn2text(song("~basename"))) description = _("Saving %(file-name)s failed." "The file may be read-only, corrupted, or you do not have " "permission to edit it.") % {"file-name": fn_format} super().__init__(parent, title, description, escape_desc=False) class EditingPluginHandler(GObject.GObject, PluginHandler): __gsignals__ = { "changed": (GObject.SignalFlags.RUN_LAST, None, ()) } Kind: Optional[Type] = None def __init__(self): super().__init__() self.__plugins = [] @property def plugins(self): return list(self.__plugins) def plugin_handle(self, plugin): return issubclass(plugin.cls, self.Kind) def plugin_enable(self, plugin): self.__plugins.append(plugin.cls) self.changed() def plugin_disable(self, plugin): self.__plugins.remove(plugin.cls) self.changed() def changed(self): self.emit("changed") class FilterCheckButton(ConfigCheckButton): __gsignals__ = { "preview": (GObject.SignalFlags.RUN_LAST, None, ()) } _tooltip = None def __init__(self): super().__init__( self._label, self._section, self._key, tooltip=self._tooltip) try: self.set_active(config.getboolean(self._section, self._key)) except: pass connect_obj(self, 'toggled', self.emit, 'preview') @property def active(self): return self.get_active() def filter(self, original, filename): raise NotImplementedError def filter_list(self, origs, names): return list(map(self.filter, origs, names)) def __lt__(self, other): return (self._order, type(self).__name__) < \ (other._order, type(other).__name__) class FilterPluginBox(Gtk.VBox): __gsignals__ = { # the list should be updated "changed": (GObject.SignalFlags.RUN_LAST, None, ()), # the preview button should be made sensitive "preview": (GObject.SignalFlags.RUN_LAST, None, ()), } def __init__(self, plugin_handler, filter_types=None): super().__init__() # static filters if filter_types is None: filter_types = [] filters = [Kind() for Kind in filter_types] filters.sort() for f in filters: self.pack_start(f, True, True, 0) self.__filters = filters # plugins self.__plugins = [] hb = Gtk.HBox() expander = Gtk.Expander(label=_(u"_More options…")) expander.set_use_underline(True) expander.set_no_show_all(True) hb.pack_start(expander, True, True, 0) self.pack_start(hb, False, True, 0) for filt in filters: filt.connect('preview', lambda *x: self.emit("preview")) vbox = Gtk.VBox() expander.add(vbox) connect_destroy(plugin_handler, "changed", self.__refresh_plugins, vbox, expander) expander.connect("notify::expanded", self.__notify_expanded, vbox) expander.set_expanded(False) for child in self.get_children(): child.show() plugin_handler.changed() def __notify_expanded(self, expander, event, vbox): vbox.set_property('visible', expander.get_property('expanded')) def __refresh_plugins(self, handler, vbox, expander): instances = [] for Kind in handler.plugins: try: f = Kind() except: errorhook() continue else: instances.append(f) instances.sort() for child in vbox.get_children(): child.destroy() del self.__plugins[:] for f in instances: try: vbox.pack_start(f, True, True, 0) except: errorhook() f.destroy() continue try: f.connect('preview', lambda *x: self.emit('preview')) except: try: f.connect('changed', lambda *x: self.emit('changed')) except: errorhook() continue self.__plugins.append(f) vbox.show_all() # Don't display the expander if there aren't any plugins. if not self.__plugins: expander.set_expanded(False) expander.hide() else: expander.show() @property def filters(self): return self.__filters + self.__plugins ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/quodlibet/qltk/about.py0000664000175000017500000000201114231604332016624 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk import quodlibet from quodlibet import const class AboutDialog(Gtk.AboutDialog): def __init__(self, parent, app): super().__init__() self.set_transient_for(parent) self.set_program_name(app.name) self.set_version(quodlibet.get_build_description()) self.set_authors(const.AUTHORS) self.set_artists(const.ARTISTS) self.set_logo_icon_name(app.icon_name) self.set_comments(app.description) self.set_license_type(Gtk.License.GPL_2_0) self.set_translator_credits("\n".join(const.TRANSLATORS)) self.set_website(const.WEBSITE) self.set_copyright(f"{const.COPYRIGHT}\n{const.SUPPORT_EMAIL}") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/qltk/appwindow.py0000664000175000017500000000200114035600052017516 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. class AppWindow: """The shared interface provided by both QL and EF""" def open_file(self, filename): """Open the specified file and play it. The file can be missing or a directory.. Args: filename (fsnative) Returns: bool: If opening worked """ return False def get_is_persistent(self): """If closing this window should shut down the application Returns: bool """ return True def set_as_osx_window(self, osx_app): """Set up the passed in osx app instance FIXME: split this into getters.. Args: osx_app (GtkosxApplication.Application) """ pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658776081.0 quodlibet-4.6.0/quodlibet/qltk/bookmarks.py0000644000175000017500000002023114267565021017516 0ustar00nicknick# Copyright 2006 Joe Wreschnig # 2016-17 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. # FIXME: Only allow one bookmark window per song. from gi.repository import Gtk, Pango from quodlibet import qltk, print_w from quodlibet import util from quodlibet import _ from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.util import connect_obj from quodlibet.qltk import Icons def MenuItems(marks, player, seekable): sizes = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.HORIZONTAL) items = [] if not marks or marks[0][0] != 0: # Translators: Refers to the beginning of the playing song. marks.insert(0, (0, _("Beginning"))) for time, mark in marks: i = Gtk.MenuItem() # older pygobject (~3.2) added a child on creation if i.get_child(): i.remove(i.get_child()) connect_obj(i, 'activate', player.seek, time * 1000) i.set_sensitive(time >= 0 and seekable) hbox = Gtk.HBox(spacing=12) i.add(hbox) if time < 0: l = Gtk.Label(label=_("N/A")) else: l = Gtk.Label(label=util.format_time(time)) l.set_alignment(0.0, 0.5) sizes.add_widget(l) hbox.pack_start(l, False, True, 0) text = Gtk.Label(mark) text.set_max_width_chars(80) text.set_ellipsize(Pango.EllipsizeMode.END) text.set_alignment(0.0, 0.5) hbox.pack_start(text, True, True, 0) i.show_all() items.append(i) return items class EditBookmarksPane(Gtk.VBox): def __init__(self, library, song, close=False): super().__init__(spacing=6) hb = Gtk.HBox(spacing=12) self.time = time = Gtk.Entry() time.set_width_chars(5) self.markname = name = Gtk.Entry() add = qltk.Button(_("_Add"), Icons.LIST_ADD, Gtk.IconSize.MENU) hb.pack_start(time, False, True, 0) hb.pack_start(name, True, True, 0) hb.pack_start(add, False, True, 0) self.pack_start(hb, False, True, 0) model = Gtk.ListStore(int, str) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(RCMHintedTreeView(model=model)) render = Gtk.CellRendererText() def cdf(column, cell, model, iter, data): if model[iter][0] < 0: cell.set_property('text', _("N/A")) else: cell.set_property('text', util.format_time(model[iter][0])) render.set_property('editable', True) render.connect('edited', self.__edit_time, model) col = Gtk.TreeViewColumn(_("Time"), render) col.set_cell_data_func(render, cdf, None) sw.get_child().append_column(col) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn(_("Bookmark Name"), render, text=1) render.set_property('editable', True) render.connect('edited', self.__edit_name, model) sw.get_child().append_column(col) self.pack_start(sw, True, True, 0) self.accels = Gtk.AccelGroup() hbox = Gtk.HButtonBox() remove = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) remove.set_sensitive(False) hbox.pack_start(remove, True, True, 0) if close: self.close = qltk.Button(_("_Close"), Icons.WINDOW_CLOSE) hbox.pack_start(self.close, True, True, 0) else: hbox.set_layout(Gtk.ButtonBoxStyle.END) self.pack_start(hbox, False, True, 0) connect_obj(add, 'clicked', self.__add, model, time, name) model.set_sort_column_id(0, Gtk.SortType.ASCENDING) model.connect('row-changed', self._set_bookmarks, library, song) model.connect('row-inserted', self._set_bookmarks, library, song) selection = sw.get_child().get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect('changed', self.__check_selection, remove) remove.connect('clicked', self.__remove, selection, library, song) connect_obj(time, 'changed', self.__check_entry, add, time, name) connect_obj(name, 'changed', self.__check_entry, add, time, name) connect_obj(name, 'activate', Gtk.Button.clicked, add) time.set_text(_("MM:SS")) connect_obj(time, 'activate', Gtk.Entry.grab_focus, name) name.set_text(_("Bookmark Name")) menu = Gtk.Menu() remove = qltk.MenuItem(_("_Remove"), Icons.LIST_REMOVE) remove.connect('activate', self.__remove, selection, library, song) keyval, mod = Gtk.accelerator_parse("Delete") remove.add_accelerator( 'activate', self.accels, keyval, mod, Gtk.AccelFlags.VISIBLE) menu.append(remove) menu.show_all() sw.get_child().connect('popup-menu', self.__popup, menu) sw.get_child().connect('key-press-event', self.__view_key_press, remove) connect_obj(self, 'destroy', Gtk.Menu.destroy, menu) self.__fill(model, song) def __view_key_press(self, view, event, remove): if event.keyval == Gtk.accelerator_parse("Delete")[0]: remove.activate() def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __edit_name(self, render, path, new, model): if new: model[path][1] = new def __edit_time(self, render, path, new, model): try: time = util.parse_time(new, None) except: pass else: model[path][0] = time def __check_entry(self, add, time, name): try: util.parse_time(time.get_text(), None) except: add.set_sensitive(False) else: add.set_sensitive(bool(name.get_text())) def __add(self, model, time, name): try: time = util.parse_time(time.get_text(), None) except: pass else: model.append([time, name.get_text()]) def __check_selection(self, selection, remove): remove.set_sensitive(bool(selection.get_selected_rows()[1])) def __remove(self, remove, selection, library, song): model, paths = selection.get_selected_rows() if model: for path in paths: model.remove(model.get_iter(path)) self._set_bookmarks(model, None, None, library, song) def _set_bookmarks(self, model, a, b, library, song): def stringify(s): return s.decode('utf-8') if isinstance(s, bytes) else s try: song.bookmarks = [(t, stringify(l)) for t, l in model] except (AttributeError, ValueError) as e: print_w("Couldn't save bookmark for %s (%s)" % (song("~filename"), e)) else: if library is not None: library.changed([song]) def __fill(self, model, song): model.clear() for time, mark in song.bookmarks: model.append([time, mark]) class EditBookmarks(qltk.Window): def __init__(self, parent, library, player): super().__init__() self.set_transient_for(qltk.get_top_parent(parent)) self.set_border_width(12) self.set_default_size(350, 250) self.set_title(_("Bookmarks") + " - %s" % player.song.comma("title")) pane = EditBookmarksPane(library, player.song, close=True) self.add(pane) s = library.connect('removed', self.__check_lock, player.song) connect_obj(self, 'destroy', library.disconnect, s) position = player.get_position() // 1000 pane.time.set_text(util.format_time(position)) pane.markname.grab_focus() pane.close.connect('clicked', lambda *x: self.destroy()) self.get_child().show_all() def __check_lock(self, library, songs, song): if song in songs: for c in self.get_child().get_children()[:-1]: c.set_sensitive(False) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1692646566.0 quodlibet-4.6.0/quodlibet/qltk/browser.py0000644000175000017500000003031114470736246017216 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2016-23 Nick Boultbee # 2018 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango from quodlibet import config, print_d from quodlibet import util from quodlibet import browsers from quodlibet import app from quodlibet import _ from quodlibet.qltk.songlist import SongList from quodlibet.qltk.x import ScrolledWindow, Action from quodlibet.qltk import Icons from quodlibet.qltk.window import Window, PersistentWindowMixin from quodlibet.util.library import background_filter class FilterMenu: MENU = """ """ __OUTER_MENU = """ %s """ % MENU def __init__(self, library, player, ui=None): self._browser = None self._library = library self._player = player self._standalone = not ui ag = Gtk.ActionGroup.new('QuodLibetFilterActions') for name, icon_name, label, cb in [ ('Filters', "", _("_Filters"), None), ("PlayedRecently", Icons.EDIT_FIND, _("Recently _Played"), self.__filter_menu_actions), ("AddedRecently", Icons.EDIT_FIND, _("Recently _Added"), self.__filter_menu_actions), ("TopRated", Icons.EDIT_FIND, _("_Top 40"), self.__filter_menu_actions), ("All", Icons.EDIT_FIND, _("All _Songs"), self.__filter_menu_actions)]: action = Action(name=name, icon_name=icon_name, label=label) if cb: action.connect('activate', cb) ag.add_action(action) for tag_, lab in [ ("genre", _("On Current _Genre(s)")), ("artist", _("On Current _Artist(s)")), ("album", _("On Current Al_bum"))]: act = Action( name="Filter%s" % util.capitalize(tag_), label=lab, icon_name=Icons.EDIT_SELECT_ALL) act.connect('activate', self.__filter_on, tag_, None, player) ag.add_action(act) for (tag_, accel, label) in [ ("genre", "G", _("Random _Genre")), ("artist", "T", _("Random _Artist")), ("album", "M", _("Random Al_bum"))]: act = Action(name="Random%s" % util.capitalize(tag_), label=label, icon_name=Icons.DIALOG_QUESTION) act.connect('activate', self.__random, tag_) ag.add_action_with_accel(act, "" + accel) if self._standalone: ui = Gtk.UIManager() ui.add_ui_from_string(self.__OUTER_MENU) ui.insert_action_group(ag, -1) self._ui = ui self._get_child_widget("TopRated").set_tooltip_text( _("The 40 songs you've played most (more than 40 may " "be chosen if there are ties)")) # https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79 menu_item = self._get_child_widget('/Menu/Filters') if isinstance(menu_item, Gtk.ImageMenuItem): menu_item.set_image(None) self._player_id = player.connect("song-started", self._on_song_started) self.set_song(player.song) self._hide_menus() def destroy(self): if self._player: self._player.disconnect(self._player_id) self._player = None self._browser = None self._library = None def _on_song_started(self, player, song): self.set_song(song) def __random(self, item, key): self._browser.filter_random(key) def __filter_on(self, action, header, songs, player): # Fall back to the playing song if songs is None: if player.song: songs = [player.song] else: return self._browser.filter_on(songs, header) def __filter_menu_actions(self, menuitem): name = menuitem.get_name() if name == "PlayedRecently": self._make_query(u"#(lastplayed < 7 days ago)") elif name == "AddedRecently": self._make_query(u"#(added < 7 days ago)") elif name == "TopRated": bg = background_filter() songs = (bg and filter(bg, self._library)) or self._library songs = [song.get("~#playcount", 0) for song in songs] if len(songs) == 0: return songs.sort() if len(songs) < 40: self._make_query(u"#(playcount > %d)" % (songs[0] - 1)) else: self._make_query(u"#(playcount > %d)" % (songs[-40] - 1)) elif name == "All": self._browser.unfilter() def _make_query(self, query): assert isinstance(query, str) if self._browser.can_filter_text(): self._browser.filter_text(query) self._browser.activate() def _hide_menus(self): menus = { 'genre': [ "FilterGenre", "RandomGenre", ], 'artist': [ "FilterArtist", "RandomArtist", ], 'album': [ "FilterAlbum", "RandomAlbum", ], None: [ "PlayedRecently", "AddedRecently", "TopRated", "All", ], } for key, widget_names in menus.items(): if self._browser: can_filter = self._browser.can_filter(key) else: can_filter = False for name in widget_names: self._get_child_widget(name).set_property('visible', can_filter) def set_browser(self, browser): self._browser = browser self._hide_menus() def set_song(self, song): for wid in ["FilterAlbum", "FilterArtist", "FilterGenre"]: self._get_child_widget(wid).set_sensitive(bool(song)) if song: for h in ['genre', 'artist', 'album']: widget = self._get_child_widget("Filter%s" % h.capitalize()) widget.set_sensitive(h in song) def _get_child_widget(self, name=None): path = '/Menu%s/Filters' % ('' if self._standalone else '/Browse') if name: path += "/" + name return self._ui.get_widget(path) def get_widget(self): path = '/Menu' if self._standalone else '/Menu/Browse' return self._ui.get_widget(path) def get_accel_group(self): return self._ui.get_accel_group() class LibraryBrowser(Window, util.InstanceTracker, PersistentWindowMixin): @classmethod def open(cls, Kind, library, player): """Creates and shows a new browser instance""" browser = cls(Kind, library, player) browser.show() return browser @classmethod def save(cls): """See which browser windows are open and save their names so we can restore them on start. """ config.set("memory", "open_browsers", "\n".join(browser.name for browser in cls.instances())) @classmethod def restore(cls, library, player): """restore saved browser windows""" value = config.get("memory", "open_browsers", "") for name in value.split(): kind = browsers.get(name) browser = cls(kind, library, player) browser.show_maybe() def __init__(self, Kind, library, player): super().__init__(dialog=False) self._register_instance() self.name = Kind.__name__ self.set_default_size(600, 400) self.enable_window_tracking("browser_" + self.name) self.set_title(Kind.name + " - Quod Libet") self.add(Gtk.VBox()) view = SongList(library, update=True) view.info.connect("changed", self.__set_totals) self.songlist = view self.songlist.sortable = not Kind.can_reorder sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.browser = browser = Kind(library) if browser.can_reorder: view.enable_drop() elif browser.dropped: view.enable_drop(False) if browser.accelerators: self.add_accel_group(browser.accelerators) self.__container = browser.pack(sw) self.get_child().pack_start(self.__container, True, True, 0) main = self.get_child() bottom = Gtk.HBox() main.pack_end(bottom, False, True, 0) self._filter_menu = filter_menu = FilterMenu(library, player) filter_menu.set_browser(self.browser) self.add_accel_group(filter_menu.get_accel_group()) bottom.pack_start(filter_menu.get_widget(), False, True, 0) filter_menu.get_widget().show() self.__statusbar = Gtk.Label() self.__statusbar.set_alignment(1.0, 0.5) self.__statusbar.set_padding(6, 3) self.__statusbar.set_ellipsize(Pango.EllipsizeMode.START) bottom.pack_end(self.__statusbar, True, True, 0) self.__statusbar.show() bottom.show() browser.connect('songs-selected', self.__browser_cb) browser.finalize(False) view.connect('popup-menu', self.__menu, library) view.connect('drag-data-received', self.__drag_data_recv) view.connect('row-activated', self.__enqueue, player) if browser.headers is not None: view.connect('columns-changed', self.__cols_changed, browser) self.__cols_changed(view, browser) sw.show_all() for c in self.get_child().get_children(): c.show() self.get_child().show() self.connect("destroy", self._on_destroy) def _on_destroy(self, *args): self._filter_menu.destroy() def __browser_cb(self, browser, songs, sorted): if browser.background: bg = background_filter() if bg: songs = list(filter(bg, songs)) print_d(f"Setting {len(songs)} songs...") self.songlist.set_songs(songs, sorted) def __enqueue(self, view, path, column, player): app.window.playlist.enqueue([view.get_model()[path][0]]) if player.song is None: player.next() def __drag_data_recv(self, view, *args): if self.browser.can_reorder: songs = view.get_songs() self.browser.reordered(songs) view.clear_sort() def __cols_changed(self, view, browser): for header in view.get_columns(): tag = header.header_name for t in util.tagsplit(tag): if t in browser.headers: header.set_visible(True) break else: header.set_visible(False) def __menu(self, view, library): path, col = view.get_cursor() header = col.header_name menu = view.Menu(header, self.browser, library) if menu is not None: view.popup_menu(menu, 0, Gtk.get_current_event_time()) return True def __set_totals(self, info, songs): i = len(songs) length = sum(song.get("~#length", 0) for song in songs) t = self.browser.status_text(count=i, time=util.format_time_preferred(length)) self.__statusbar.set_text(t) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1672734865.0 quodlibet-4.6.0/quodlibet/qltk/cbes.py0000644000175000017500000003573214354764221016456 0ustar00nicknick# Copyright 2005-2020 Joe Wreschnig, Michael Urman, Christoph Reiter, # Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from typing import Dict from gi.repository import Gtk, Pango, GObject, GLib from quodlibet import _, config, util from quodlibet import qltk from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk.util import GSignals from quodlibet.util import connect_obj, escape from quodlibet.qltk import entry, add_css from quodlibet.qltk import Icons class _KeyValueEditor(qltk.Window): """Base class for key-value edit widgets""" _WIDTH = 500 _HEIGHT = 400 def __init__(self, title, validator=None): super().__init__() self.set_border_width(12) self.set_title(title) self.set_default_size(self._WIDTH, self._HEIGHT) self.add(Gtk.VBox(spacing=6)) t = Gtk.Table(n_rows=2, n_columns=3) t.set_row_spacings(6) t.set_col_spacing(0, 3) t.set_col_spacing(1, 12) l = Gtk.Label(label=_("_Name:")) name = entry.UndoEntry() l.set_mnemonic_widget(name) l.set_use_underline(True) l.set_alignment(0.0, 0.5) t.attach(l, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) t.attach(name, 1, 2, 0, 1) l = Gtk.Label(label=_("_Value:")) self.value = entry.ValidatingEntry(validator) l.set_mnemonic_widget(self.value) l.set_use_underline(True) l.set_alignment(0.0, 0.5) t.attach(l, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) t.attach(self.value, 1, 2, 1, 2) add = qltk.Button(_("_Add"), Icons.LIST_ADD) add.set_sensitive(False) t.attach(add, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.FILL) self.get_child().pack_start(t, False, True, 0) # Set up the model for this widget self.model = Gtk.ListStore(str, str) self.fill_values() view = RCMHintedTreeView(model=self.model) view.set_headers_visible(False) view.set_reorderable(True) view.set_rules_hint(True) render = Gtk.CellRendererText() render.props.ellipsize = Pango.EllipsizeMode.END render.set_padding(3, 3) column = Gtk.TreeViewColumn("", render) column.set_cell_data_func(render, self.__cdf, None) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(view) self.get_child().pack_start(sw, True, True, 3) menu = Gtk.Menu() remove = qltk.MenuItem(_("_Remove"), Icons.LIST_REMOVE) connect_obj(remove, 'activate', self.__remove, view) qltk.add_fake_accel(remove, "Delete") menu.append(remove) menu.show_all() bbox = Gtk.HButtonBox() rem_b = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) rem_b.set_sensitive(False) bbox.pack_start(rem_b, True, True, 0) self.use_header_bar() close = qltk.Button(_("_Close"), Icons.WINDOW_CLOSE) if not self.has_close_button(): bbox.pack_start(close, True, True, 0) else: bbox.set_layout(Gtk.ButtonBoxStyle.START) self.get_child().pack_start(bbox, False, True, 0) selection = view.get_selection() connect_obj(name, 'activate', Gtk.Entry.grab_focus, self.value) connect_obj(self.value, 'activate', Gtk.Button.clicked, add) self.value.connect('changed', self.__changed, [add]) connect_obj(add, 'clicked', self.__add, selection, name, self.value, self.model) selection.connect('changed', self.__set_text, name, self.value, rem_b) view.connect('popup-menu', self.__popup, menu) connect_obj(rem_b, 'clicked', self.__remove, view) connect_obj(close, 'clicked', qltk.Window.destroy, self) view.connect('key-press-event', self.__view_key_press) connect_obj(self, 'destroy', Gtk.Menu.destroy, menu) name.grab_focus() self.get_child().show_all() def fill_values(self): """Responsible for populating self.model (eg with values from disk)""" raise NotImplementedError def __view_key_press(self, view, event): if qltk.is_accel(event, "Delete"): self.__remove(view) def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __remove(self, view): view.remove_selection() def __set_text(self, selection, name, value, remove): model, iter = selection.get_selected() remove.set_sensitive(bool(iter)) if iter is not None: name.set_text(model[iter][1]) value.set_text(model[iter][0]) def __cdf(self, column, cell, model, iter, data): row = model[iter] content, name = row cell.set_property("markup", util.bold(name) + "\n" + util.monospace(content)) def __changed(self, entry, buttons): for b in buttons: b.set_sensitive(bool(entry.get_text())) def __add(self, selection, name, value, model): value = value.get_text() if value: name = name.get_text() or value iter = model.append(row=[value, name]) selection.select_iter(iter) class CBESEditor(_KeyValueEditor): def __init__(self, cbes, title, validator=None): # Do this before calling parent constructor self.cbes = cbes super().__init__(title, validator) self.set_transient_for(qltk.get_top_parent(cbes)) connect_obj(self, 'destroy', self.__finish, cbes) self.value.set_text(cbes.get_child().get_text()) def fill_values(self): for row in self.cbes.get_model(): if row[2] is not None: break else: self.model.append((row[0], row[1])) def __finish(self, cbes): cbes_model = cbes.get_model() iter = cbes_model.get_iter_first() while cbes_model[iter][2] is None: cbes_model.remove(iter) iter = cbes_model.get_iter_first() for row in self.model: cbes_model.insert_before(iter, row=[row[0], row[1], None]) cbes.write() class StandaloneEditor(_KeyValueEditor): """A key-value pair editor that can be used without CBES. Saves to disk in a single file of the same format with suffix '.saved' """ @classmethod def load_values(cls, filename): """Returns a list of tuples representing k,v pairs of the given file""" ret = [] if os.path.exists(filename): fileobj = open(filename, "r", encoding="utf-8") lines = list(fileobj.readlines()) for i in range(len(lines) // 2): ret.append((lines[i * 2 + 1].strip(), lines[i * 2].strip())) return ret def __init__(self, filename, title, initial=None, validator=None): self.filename = filename self.initial = initial or [] super().__init__(title, validator) connect_obj(self, 'destroy', self.write, True) def fill_values(self): filename = self.filename + ".saved" if os.path.exists(filename): fileobj = open(filename, "r", encoding="utf-8") lines = list(fileobj.readlines()) lines.reverse() while len(lines) > 1: self.model.prepend( row=[lines.pop(1).strip(), lines.pop(0).strip()]) if not len(self.model) and self.initial: for (k, v) in self.initial: self.model.append(row=[v.strip(), k.strip()]) def write(self, create=True): """Save to a filename. If create is True, any needed parent directories will be created.""" try: if create: if not os.path.isdir(os.path.dirname(self.filename)): os.makedirs(os.path.dirname(self.filename)) with open(self.filename + ".saved", "w", encoding="utf-8") as saved: for row in self.model: saved.write(row[0] + "\n") saved.write(row[1] + "\n") except EnvironmentError: pass def clone_css_classes(src, dest): """Makes dest have the same css classes as src""" src_ctx = src.get_style_context() dest_ctx = dest.get_style_context() for class_ in dest_ctx.list_classes(): dest_ctx.remove_class(class_) for class_ in src_ctx.list_classes(): dest_ctx.add_class(class_) class ComboBoxEntrySave(Gtk.ComboBox): """A ComboBoxEntry that remembers the past 'count' strings entered, and can save itself to (and load itself from) a filename or file-like.""" # gets emitted if the text entry changes # mainly to filter out model changes that don't have any effect __gsignals__: GSignals = { 'text-changed': (GObject.SignalFlags.RUN_LAST, None, ()), } __models: Dict[str, Gtk.TreeModel] = {} __last = "" def __init__(self, filename=None, initial=[], count=5, id=None, validator=None, title=_("Saved Values"), edit_title=_(u"Edit saved values…")): self.count = count self.filename = filename id = filename or id try: model = self.__models[id] except KeyError: model = type(self).__models[id] = Gtk.ListStore(str, str, str) super().__init__( model=model, entry_text_column=0, has_entry=True) self.clear() render = Gtk.CellRendererPixbuf() self.pack_start(render, False) self.add_attribute(render, 'icon-name', 2) render = Gtk.CellRendererText() self.pack_start(render, True) self.add_attribute(render, 'text', 1) self.set_row_separator_func(self.__separator_func, None) if not len(model): self.__fill(filename, initial, edit_title) old_entry = self.get_child() new_entry = entry.ValidatingEntry(validator) clone_css_classes(old_entry, new_entry) old_entry.destroy() use_mono = config.getboolean("settings", "monospace_query") font = "font-family: monospace; " if use_mono else "" size = escape(config.gettext("settings", "query_font_size")) add_css(new_entry, f"entry {{ {font} font-size: {size} }}") self.add(new_entry) if validator: # Call once more to ensure correct theme colours GLib.idle_add(new_entry._set_color, None, validator) connect_obj(self, 'destroy', self.set_model, None) connect_obj(self, 'changed', self.__changed, model, validator, title) def enable_clear_button(self): self.get_child().enable_clear_button() def __changed(self, model, validator, title): iter = self.get_active_iter() if iter: if model[iter][2]: self.get_child().set_text(self.__last) win = CBESEditor(self, title, validator) win.show() self.set_active(-1) else: self.__focus_entry() new = self.get_child().get_text() if new != self.__last: self.emit("text-changed") self.__last = new def __focus_entry(self): self.get_child().grab_focus() self.get_child().emit('move-cursor', Gtk.MovementStep.BUFFER_ENDS, 0, False) def __fill(self, filename, initial, edit_title): model = self.get_model() model.append(row=["", edit_title, Icons.DOCUMENT_PROPERTIES]) model.append(row=[None, None, None]) if filename is None: return if os.path.exists(filename + ".saved"): with open(filename + ".saved", "r", encoding="utf-8") as fileobj: lines = list(fileobj.readlines()) lines.reverse() while len(lines) > 1: model.prepend( row=[lines.pop(1).strip(), lines.pop(0).strip(), None]) if os.path.exists(filename): with open(filename, "r", encoding="utf-8") as fileobj: for line in fileobj.readlines(): line = line.strip() model.append(row=[line, line, None]) for c in initial: model.append(row=[c, c, None]) self.__shorten() def __separator_func(self, model, iter, userdata): return model[iter][1] is None def __shorten(self): model = self.get_model() for row in model: if row[0] is None: offset = row.path.get_indices()[0] + 1 break to_remove = (len(model) - offset) - self.count while to_remove > 0: model.remove(model.get_iter((len(model) - 1,))) to_remove -= 1 def write(self, filename=None, create=True): """Save to a filename. If create is True, any needed parent directories will be created.""" if filename is None: filename = self.filename try: if create: if not os.path.isdir(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) with open(filename + ".saved", "w", encoding="utf-8") as saved: with open(filename, "w", encoding="utf-8") as memory: target = saved for row in self.get_model(): if row[0] is None: target = memory elif row[2] is None: target.write(row[0] + "\n") if target is saved: target.write(row[1] + "\n") except EnvironmentError: pass def __remove_if_present(self, text): # Removes an item from the list if it's present in the remembered # values, or returns true if it's in the saved values. removable = False model = self.get_model() for row in model: if row[0] is None: # Not found in the saved values, so if we find it from now # on, remove it and return false. removable = True elif row[2] is None and row[0] == text: # Found the value, and it's not the magic value -- remove # it if necessary, and return whether or not to continue. if removable: model.remove(row.iter) return not removable def prepend_text(self, text): # If we find the value in the saved values, don't prepend it. if self.__remove_if_present(text): return model = self.get_model() for row in model: if row[0] is None: model.insert_after(row.iter, row=[text, text, None]) break self.__shorten() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1677753347.0 quodlibet-4.6.0/quodlibet/qltk/ccb.py0000644000175000017500000000662014400076003016245 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2012-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import config class ConfigCheckButton(Gtk.CheckButton): """A CheckButton that connects to QL's config module, and toggles a boolean configuration value when it is toggled. It is initialised to the current config value if `populate` is set True.""" def __init__(self, label, section, option, populate=False, tooltip=None, default=None): super().__init__(label=label, use_underline=True) if default is None: default = config._config.defaults.getboolean(section, option, True) if populate: self.set_active(config.getboolean(section, option, default)) if tooltip: self.set_tooltip_text(tooltip) self.connect('toggled', ConfigCheckButton.__toggled, section, option) def __toggled(self, section, option): config.set(section, option, str(bool(self.get_active())).lower()) class ConfigSwitch(Gtk.Box): """A Switch that connects to QL's config module, and toggles a boolean configuration value when it is toggled. It is initialised to the current config value if `populate` is set True.""" def __init__(self, label, section, option, populate=False, tooltip=None, default=None): super().__init__() self.label = Gtk.Label(label, use_underline=True) self.switch = Gtk.Switch() self.label.set_mnemonic_widget(self.switch) eb = Gtk.EventBox() eb.add(self.label) self.pack_start(eb, False, True, 0) self.pack_end(self.switch, False, True, 0) if default is None: default = config._config.defaults.getboolean(section, option, True) if populate: self.set_active(config.getboolean(section, option, default)) if tooltip: self.label.set_tooltip_text(tooltip) self.switch.connect('notify::active', self.__activated, section, option) eb.connect('button_press_event', lambda *_: self.switch.set_state(not self.switch.get_state())) def set_active(self, value: bool): self.switch.set_active(value) def get_active(self) -> bool: return self.switch.get_active() def connect(self, *args, **kwargs): self.switch.connect(*args, **kwargs) def __activated(self, switch, state, section, option): config.set(section, option, str(switch.get_active()).lower()) class ConfigCheckMenuItem(Gtk.CheckMenuItem): """A CheckMenuItem that connects to QL's config module, and toggles a boolean configuration value when it is toggled. It is initialised to the current config value if `populate` is set True.""" def __init__(self, label, section, option, populate=False, default=False): super().__init__( label=label, use_underline=True) if populate: self.set_active(config.getboolean(section, option, default)) self.connect('toggled', ConfigCheckMenuItem.__toggled, section, option) def __toggled(self, section, option): config.set(section, option, str(bool(self.get_active())).lower()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658680115.0 quodlibet-4.6.0/quodlibet/qltk/chooser.py0000644000175000017500000001533314267271463017203 0ustar00nicknick# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import contextlib from gi.repository import Gtk from senf import fsnative, path2fsn, fsn2bytes, bytes2fsn from quodlibet import _ from quodlibet import config from quodlibet.qltk import get_top_parent, gtk_version from quodlibet.util.path import get_home_dir from quodlibet.util import is_windows def _get_chooser(accept_label, cancel_label): """ Args: accept_label (str) cancel_label (str) Returns: Gtk.FileChooser """ if hasattr(Gtk, "FileChooserNative"): FileChooser = Gtk.FileChooserNative else: FileChooser = Gtk.FileChooserDialog # https://github.com/quodlibet/quodlibet/issues/2406 if is_windows() and gtk_version < (3, 22, 16): FileChooser = Gtk.FileChooserDialog chooser = FileChooser() if hasattr(chooser, "set_accept_label"): chooser.set_accept_label(accept_label) else: chooser.add_button(accept_label, Gtk.ResponseType.ACCEPT) chooser.set_default_response(Gtk.ResponseType.ACCEPT) if hasattr(chooser, "set_cancel_label"): chooser.set_cancel_label(cancel_label) else: chooser.add_button(cancel_label, Gtk.ResponseType.CANCEL) return chooser _response = None @contextlib.contextmanager def with_response(resp): # for testing global _response _response = resp yield _response = None def _run_chooser(parent, chooser): """Run the chooser ("blocking") and return a list of paths. Args: parent (Gtk.Widget) chooser (Gtk.FileChooser) Returns: List[fsnative] """ chooser.set_current_folder(get_current_dir()) chooser.set_transient_for(get_top_parent(parent)) if _response is not None: response = _response while Gtk.events_pending(): Gtk.main_iteration() else: response = chooser.run() if response == Gtk.ResponseType.ACCEPT: result = [fn for fn in chooser.get_filenames()] current_dir = chooser.get_current_folder() if current_dir: set_current_dir(current_dir) else: result = [] chooser.destroy() return result def find_nearest_dir(path): """Given a path return the closes existing directory. Either itself or a parent. In case it can't find one it returns None. Returns: fsnative or None """ path = os.path.abspath(path) def is_ok(p): return os.path.exists(p) and os.path.isdir(p) while not is_ok(path): dirname = os.path.dirname(path) if dirname == path: return None path = dirname return path def get_current_dir(): """Returns the currently active chooser directory path. The path might not actually exist. Returns: fsnative """ data = config.getbytes("memory", "chooser_dir", b"") try: path = bytes2fsn(data, "utf-8") or None except ValueError: path = None # the last user dir might not be there any more, try showing a parent # instead if path is not None: path = find_nearest_dir(path) if path is None: path = get_home_dir() return path def set_current_dir(path): """Set the current chooser directory. Args: path (fsnative) """ assert isinstance(path, fsnative) data = fsn2bytes(path, "utf-8") config.setbytes("memory", "chooser_dir", data) def create_chooser_filter(name, patterns): """Create a Gtk.FileFilter that also works on Windows Args: name (str): The name of the filter patterns (List[pathlike]): A list of glob patterns Returns: Gtk.FileFilter """ # The Windows FileChooserNative implementation only supports patterns filter_ = Gtk.FileFilter() filter_.set_name(name) for pattern in sorted(set(patterns)): filter_.add_pattern(path2fsn(pattern)) return filter_ def choose_folders(parent, title, action_title, allow_multiple=True): """Opens a folder chooser widget and returns a list of folders selected. Args: parent (Gtk.Widget) title (str): The window title action_title (str): The button title Returns: List[fsnative] """ chooser = _get_chooser(action_title, _("_Cancel")) chooser.set_title(title) chooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER) chooser.set_local_only(True) chooser.set_select_multiple(allow_multiple) return _run_chooser(parent, chooser) def choose_files(parent, title, action_title, filter_=None): """Opens a folder chooser widget and returns a list of folders selected. Args: parent (Gtk.Widget) title (str): The window title action_title (str): The button title filter_ (Gtk.FileFilter or None) Returns: List[fsnative] """ chooser = _get_chooser(action_title, _("_Cancel")) chooser.set_title(title) chooser.set_action(Gtk.FileChooserAction.OPEN) chooser.set_local_only(True) chooser.set_select_multiple(True) if filter_ is not None: chooser.add_filter(filter_) return _run_chooser(parent, chooser) def choose_target_file(parent, title, action_title, name_suggestion=None): """Opens a file chooser for saving a file. Args: parent (Gtk.Widget) title (str): The window title action_title (str): The button title name_suggestion (str): The suggested file name (not fsnative) Returns: fsnative or None """ chooser = _get_chooser(action_title, _("_Cancel")) chooser.set_title(title) chooser.set_action(Gtk.FileChooserAction.SAVE) chooser.set_local_only(True) if name_suggestion is not None: chooser.set_current_name(name_suggestion) result = _run_chooser(parent, chooser) if result: return result[0] def choose_target_folder(parent, title, action_title, name_suggestion=None): """Opens a file chooser for choosing a directory. Args: parent (Gtk.Widget) title (str): The window title action_title (str): The button title name_suggestion (str): The suggested folder name (not fsnative) Returns: fsnative or None """ chooser = _get_chooser(action_title, _("_Cancel")) chooser.set_title(title) chooser.set_action(Gtk.FileChooserAction.CREATE_FOLDER) chooser.set_local_only(True) if name_suggestion is not None: chooser.set_current_name(name_suggestion) result = _run_chooser(parent, chooser) if result: return result[0] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618773137.0 quodlibet-4.6.0/quodlibet/qltk/color.py0000664000175000017500000000131014037102221016623 0ustar00nicknick# Copyright 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gdk def mix(src: Gdk.RGBA, dest: Gdk.RGBA, ratio: float) -> Gdk.RGBA: """Mixes two Gdk colours into a result""" ratio = min(1.0, max(0.0, ratio)) inv = 1.0 - ratio return Gdk.RGBA(inv * src.red + ratio * dest.red, inv * src.green + ratio * dest.green, inv * src.blue + ratio * dest.blue, inv * src.alpha + ratio * dest.alpha) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1656357949.0 quodlibet-4.6.0/quodlibet/qltk/completion.py0000664000175000017500000001356714256402075017714 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman, # 2011 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Set from gi.repository import Gtk from quodlibet import formats, config, print_d from quodlibet.util import copool, massagers from quodlibet.util.tags import MACHINE_TAGS class EntryWordCompletion(Gtk.EntryCompletion): """Entry completion for simple words, where a word boundary is roughly equivalent to the separators in the QL query language. You need to manually set a model containing the available words.""" leftsep = ["&(", "|(", ",", ", "] rightsep = [" ", ")", ","] def __init__(self): super().__init__() self.set_match_func(self.__match_filter, None) self.connect('match-selected', self.__match_selected) def __match_filter(self, completion, entrytext, iter, data): model = completion.get_model() entry = self.get_entry() if entry is None: return False cursor = entry.get_position() if (cursor != len(entrytext) and not max([entrytext[cursor:].startswith(s) for s in self.rightsep])): return False # find the border to the left left, f = max( [(entrytext.rfind(c, 0, cursor), c) for c in self.leftsep]) if left < 0: left += 1 else: left += len(f) if left == cursor: return False key = entrytext[left:cursor] value = model.get_value(iter, self.get_property('text-column')) return bool(value and value.startswith(key)) def __match_selected(self, completion, model, iter): value = model.get_value(iter, self.get_property('text-column')) entry = self.get_entry() cursor = entry.get_position() text = entry.get_text() left, f = max( [(text.rfind(c, 0, cursor), c) for c in self.leftsep]) if left == -1: left += 1 else: left += len(f) offset = cursor - left entry.insert_text(value[offset:], cursor) entry.set_position(left + len(value)) return True class LibraryTagCompletion(EntryWordCompletion): """A completion for text entries tied to a library's tag list.""" __tags: Set[str] = set() def __init__(self, library): super().__init__() try: model = self.__model except AttributeError: model = type(self).__model = Gtk.ListStore(str) library.connect('changed', self.__update_song, model) library.connect('added', self.__update_song, model) library.connect('removed', self.__update_song, model) copool.add(self.__build_model, library, model) self.set_model(model) self.set_text_column(0) @classmethod def __update_song(klass, library, songs, model): if not songs: return tags = klass.__tags for song in songs: for tag in song.keys(): if not (tag.startswith("~#") or tag in MACHINE_TAGS or tag in tags): klass.__tags.add(tag) model.append([tag]) print_d("Updated tag model for %d songs" % len(songs)) @classmethod def __build_model(klass, library, model): print_d("Updating tag model for whole library") all_tags = klass.__tags model.clear() tags = set() songs = list(library) for count, song in enumerate(songs): for tag in song.keys(): if not (tag.startswith("~#") or tag in MACHINE_TAGS): tags.add(tag) if count % 500 == 0 or count + 1 == len(songs): tags -= all_tags for tag in tags: model.append([tag]) all_tags.update(tags) tags.clear() yield True tags.update(["~dirname", "~basename", "~people", "~format"]) for tag in ["track", "disc", "playcount", "skipcount", "lastplayed", "mtime", "added", "rating", "length"]: tags.add("#(" + tag) for tag in ["date", "bpm"]: if tag in all_tags: tags.add("#(" + tag) tags -= all_tags for tag in tags: model.append([tag]) all_tags.update(tags) print_d("Done updating tag model for whole library") class LibraryValueCompletion(Gtk.EntryCompletion): """Entry completion for a library value, for a specific tag. Will add valid values from the tag massager where available""" def __init__(self, tag, library): super().__init__() self.set_model(Gtk.ListStore(str)) self.set_text_column(0) self.set_tag(tag, library) def set_tag(self, tag, library): if not config.getboolean("settings", "eager_search"): return elif tag is None: return elif tag in ("bpm date discnumber isrc originaldate recordingdate " "tracknumber title").split() + MACHINE_TAGS: return elif tag in formats.PEOPLE: tag = "~people" copool.add(self.__fill_tag, tag, library) def __fill_tag(self, tag, library): model = self.get_model() model.clear() yield True # Issue 439: pre-fill with valid values if available values = massagers.get_options(tag) values = sorted(set(values) | library.tag_values(tag)) self.set_minimum_key_length(int(len(values) > 100)) yield True for count, value in enumerate(values): model.append(row=[value]) if count % 1000 == 0: yield True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1655124478.0 quodlibet-4.6.0/quodlibet/qltk/controls.py0000664000175000017500000002463514251630776017412 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk, GObject from quodlibet import config from quodlibet import qltk from quodlibet import _ from quodlibet.util import connect_obj, connect_destroy from quodlibet.qltk.x import SymbolicIconImage, RadioMenuItem from quodlibet.qltk.util import GSignals from quodlibet.qltk.seekbutton import SeekButton from quodlibet.util.dprint import print_e class Volume(Gtk.VolumeButton): def __init__(self, player): super().__init__(size=Gtk.IconSize.MENU, use_symbolic=True) # https://bugzilla.gnome.org/show_bug.cgi?id=781605 scales = qltk.find_widgets(self.get_popup(), Gtk.Scale) if scales: scales[0].props.round_digits = -1 self.set_relief(Gtk.ReliefStyle.NORMAL) self.set_adjustment(Gtk.Adjustment.new(0, 0, 1, 0.05, 0.1, 0)) popup = self.get_popup() if hasattr(Gtk, "Popover") and isinstance(popup, Gtk.Popover): popup.set_position(Gtk.PositionType.BOTTOM) self._id = self.connect('value-changed', self.__volume_changed, player) self._id2 = player.connect('notify::volume', self.__volume_notify) self._id3 = player.connect('notify::mute', self.__mute_notify) self._orig_icon_list = self.props.icons player.notify("volume") player.notify("mute") self.connect("event", self._on_button_event, player) replaygain_menu = VolumeMenu(player) self.connect('popup-menu', self.__popup, replaygain_menu) connect_obj(self, 'button-press-event', self.__volume_button_press, replaygain_menu, player) def __popup(self, widget, menu): time = Gtk.get_current_event_time() button = 3 qltk.popup_menu_under_widget(menu, widget, button, time) return True def __volume_button_press(self, menu, event, player): if event.type != Gdk.EventType.BUTTON_PRESS: return False if event.button == Gdk.BUTTON_SECONDARY: qltk.popup_menu_at_widget(menu, self, event.button, event.time) return True elif event.button == Gdk.BUTTON_MIDDLE: # toggle the muted state, if the backend doesn't support it # this action will just be ignored player.mute = not player.mute return True def __iadd__(self, v): self.set_value(self.get_value() + v) return self def __isub__(self, v): self.set_value(self.get_value() - v) return self def __volume_changed(self, button, volume, player): player.handler_block(self._id2) player.volume = volume player.handler_unblock(self._id2) def __volume_notify(self, player, prop): self.handler_block(self._id) self.set_value(player.volume) self.handler_unblock(self._id) def __mute_notify(self, player, prop): self._update_mute(player) def _update_mute(self, player): if player.mute: # remove all icons except the mute one to show a muted state # that is not affected by the volume slider self.props.icons = [self._orig_icon_list[0]] else: self.props.icons = self._orig_icon_list def _on_button_event(self, widget, event, player): # pulsesink doesn't emit volume changes when it's paused, but # fetching the value works. To prevent user volume changes based on a # false starting point update the slider on any action on the # volume button. self.handler_block(self._id) self.set_value(player.volume) self.handler_unblock(self._id) # same with mute self._update_mute(player) class VolumeMenu(Gtk.Menu): __modes = ( ("auto", _("Auto_matic"), None), ("track", _("_Track Mode"), ["track"]), ("album", _("_Album Mode"), ["album", "track"]) ) def __init__(self, player): super().__init__() # ubuntu 12.04.. if hasattr(player, "bind_property"): # Translators: player state, no action item = Gtk.CheckMenuItem(label=_("_Mute"), use_underline=True) player.bind_property("mute", item, "active", GObject.BindingFlags.BIDIRECTIONAL) self.append(item) item.show() item = Gtk.MenuItem(label=_("_Replay Gain Mode"), use_underline=True) self.append(item) item.show() # Set replaygain mode as saved in configuration replaygain_mode = config.gettext("player", "replaygain_mode", "auto") self.__set_mode(player, replaygain_mode) rg = Gtk.Menu() rg.show() item.set_submenu(rg) item = None for mode, title, profile in self.__modes: item = RadioMenuItem(group=item, label=title, use_underline=True) rg.append(item) item.connect("toggled", self.__changed, player, mode) if replaygain_mode == mode: item.set_active(True) item.show() def __set_mode(self, player, mode): selected_mode = next((m for m in self.__modes if m[0] == mode), None) if selected_mode is None: print_e("Invalid selected replaygain mode: %r" % mode) selected_mode = self.__modes[0] print_e("Falling back to replaygain mode: %r" % selected_mode[0]) player.replaygain_profiles[0] = selected_mode[2] player.reset_replaygain() def __changed(self, item, player, mode): if item.get_active(): config.settext("player", "replaygain_mode", mode) self.__set_mode(player, mode) def popup(self, *args): gain = config.getboolean("player", "replaygain") for child in self.get_children(): child.set_sensitive(gain) return super().popup(*args) class PlayPauseButton(Gtk.Button): __gsignals__: GSignals = { 'toggled': (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__(relief=Gtk.ReliefStyle.NONE) self._pause_image = SymbolicIconImage("media-playback-pause", Gtk.IconSize.LARGE_TOOLBAR) self._play_image = SymbolicIconImage("media-playback-start", Gtk.IconSize.LARGE_TOOLBAR) self._set_active(False) self.connect("clicked", self._on_clicked) def _on_clicked(self, *args): self.set_active(not self.get_active()) def _set_active(self, is_active): if self.get_child(): self.remove(self.get_child()) if is_active: self.add(self._pause_image) else: self.add(self._play_image) self.get_child().show() self.emit("toggled") def set_active(self, is_active): if self.get_active() == is_active: return config.set("player", "is_playing", is_active) self._set_active(is_active) def get_active(self): return self.get_child() is self._pause_image class PlayControls(Gtk.VBox): def __init__(self, player, library): super().__init__(spacing=3) upper = Gtk.Table(n_rows=1, n_columns=3, homogeneous=True) upper.set_row_spacings(3) upper.set_col_spacings(3) prev = Gtk.Button(relief=Gtk.ReliefStyle.NONE) prev.add(SymbolicIconImage("media-skip-backward", Gtk.IconSize.LARGE_TOOLBAR)) upper.attach(prev, 0, 1, 0, 1) play = PlayPauseButton() upper.attach(play, 1, 2, 0, 1) next_ = Gtk.Button(relief=Gtk.ReliefStyle.NONE) next_.add(SymbolicIconImage("media-skip-forward", Gtk.IconSize.LARGE_TOOLBAR)) upper.attach(next_, 2, 3, 0, 1) lower = Gtk.Table(n_rows=1, n_columns=3, homogeneous=True) lower.set_row_spacings(3) lower.set_col_spacings(3) self.volume = Volume(player) self.volume.set_relief(Gtk.ReliefStyle.NONE) lower.attach(self.volume, 0, 1, 0, 1) # XXX: Adwaita defines a different padding for GtkVolumeButton # We force it to 0 here, which works because the other (normal) buttons # in the grid set the width/height qltk.add_css(self.volume, """ .button { padding: 0px; } """) seekbutton = SeekButton(player, library) seekbutton.set_relief(Gtk.ReliefStyle.NONE) lower.attach(seekbutton, 1, 3, 0, 1) self.pack_start(upper, False, True, 0) self.pack_start(lower, False, True, 0) connect_obj(prev, 'clicked', self.__previous, player) self._toggle_id = play.connect('toggled', self.__playpause, player) play.add_events(Gdk.EventMask.SCROLL_MASK) connect_obj(play, 'scroll-event', self.__scroll, player) connect_obj(next_, 'clicked', self.__next, player) connect_destroy( player, 'song-started', self.__song_started, next_, play) connect_destroy( player, 'paused', self.__on_set_paused_unpaused, play, False) connect_destroy( player, 'unpaused', self.__on_set_paused_unpaused, play, True) def __on_set_paused_unpaused(self, player, button, state): # block to prevent a signal cycle in case the paused signal and state # get out of sync (shouldn't happen.. but) button.handler_block(self._toggle_id) button.set_active(state) button.handler_unblock(self._toggle_id) def __scroll(self, player, event): if event.direction in [Gdk.ScrollDirection.UP, Gdk.ScrollDirection.LEFT]: player.previous() elif event.direction in [Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.RIGHT]: player.next() def __song_started(self, player, song, next, play): play.set_active(not player.paused) def __playpause(self, button, player): if button.get_active(): player.play() else: player.paused = True def __previous(self, player): player.previous() def __next(self, player): player.next() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1655124478.0 quodlibet-4.6.0/quodlibet/qltk/cover.py0000664000175000017500000002413714251630776016662 0ustar00nicknick# Copyright 2004-2017 Joe Wreschnig, Michael Urman, Iñigo Serna, # Christoph Reiter, Nick Boultbee, Simonas Kazlauskas # 2018-2019 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib, Gdk, GdkPixbuf, Gio, GObject from senf import fsnative from quodlibet import qltk from quodlibet import app from quodlibet.util import thumbnails, print_w from quodlibet.qltk.image import pixbuf_from_file, \ calc_scale_size, scale, add_border_widget, get_surface_for_pixbuf # TODO: neater way of managing dependency on this particular plugin ALBUM_ART_PLUGIN_ID = "Download Album Art" class BigCenteredImage(qltk.Window): """Load an image and display it, scaling it down to the parent window size. """ def __init__(self, title, fileobj, parent, scale=0.5): super().__init__(type=Gtk.WindowType.POPUP) self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) assert parent parent = qltk.get_top_parent(parent) self.set_transient_for(parent) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) #If image fails to set, abort construction. if not self.set_image(fileobj, parent, scale): self.destroy() return event_box = Gtk.EventBox() event_box.add(self.__image) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.OUT) frame.add(event_box) self.add(frame) event_box.connect('button-press-event', self.__destroy) event_box.connect('key-press-event', self.__destroy) self.get_child().show_all() def set_image(self, file, parent, scale=0.5): scale_factor = self.get_scale_factor() (width, height) = self.__calculate_screen_width(parent, scale) pixbuf = None try: pixbuf = pixbuf_from_file(file, (width, height), scale_factor) except GLib.GError: return False # failed to load, abort if not pixbuf: return False self.__image = Gtk.Image() self.__image.set_from_surface(get_surface_for_pixbuf(self, pixbuf)) return True def __calculate_screen_width(self, parent, scale=0.5): width, height = parent.get_size() width = int(width * scale) height = int(height * scale) return (width, height) def __destroy(self, *args): self.destroy() def get_no_cover_pixbuf(width, height, scale_factor=1): """A no-cover pixbuf at maximum width x height""" # win32 workaround: https://bugzilla.gnome.org/show_bug.cgi?id=721062 width *= scale_factor height *= scale_factor size = max(width, height) theme = Gtk.IconTheme.get_default() icon_info = theme.lookup_icon("quodlibet-missing-cover", size, 0) if icon_info is None: return filename = icon_info.get_filename() try: return GdkPixbuf.Pixbuf.new_from_file_at_size(filename, width, height) except GLib.GError: return class ResizeImage(Gtk.Bin): def __init__(self, resize=False, size=1): Gtk.Bin.__init__(self) self._dirty = True self._path = None self._file = None self._pixbuf = None self._no_cover = None self._size = size self._resize = resize def set_file(self, fileobj): if fileobj is None: path = None else: path = fileobj.name assert isinstance(path, fsnative) # XXX: Don't reload if the file path is the same. # Could prevent updates if fileobj.name isn't defined if self._path == path: return self._file = fileobj self._path = path self._dirty = True self.queue_resize() def _get_pixbuf(self): if not self._dirty: return self._pixbuf self._dirty = False max_size = 256 * self.get_scale_factor() self._pixbuf = None if self._file: self._pixbuf = thumbnails.get_thumbnail_from_file( self._file, (max_size, max_size)) if not self._pixbuf: self._pixbuf = get_no_cover_pixbuf(max_size, max_size) return self._pixbuf def _get_size(self, max_width, max_height): pixbuf = self._get_pixbuf() if not pixbuf: return 0, 0 width, height = pixbuf.get_width(), pixbuf.get_height() return calc_scale_size((max_width, max_height), (width, height)) def do_get_request_mode(self): if self._resize: return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH return Gtk.SizeRequestMode.CONSTANT_SIZE def do_get_preferred_width(self): if self._resize: return (0, 0) else: width, height = self._get_size(self._size, self._size) return (width, width) def do_get_preferred_height(self): if self._resize: return (0, 0) else: width, height = self._get_size(self._size, self._size) return (height, height) def do_get_preferred_width_for_height(self, req_height): width, height = self._get_size(300, req_height) if width > 256: width = width return (width, width) def do_draw(self, cairo_context): pixbuf = self._get_pixbuf() if not pixbuf: return alloc = self.get_allocation() width, height = alloc.width, alloc.height scale_factor = self.get_scale_factor() width *= scale_factor height *= scale_factor if self._path: if width < (2 * scale_factor) or height < (2 * scale_factor): return pixbuf = scale( pixbuf, (width - 2 * scale_factor, height - 2 * scale_factor)) pixbuf = add_border_widget(pixbuf, self) else: pixbuf = scale(pixbuf, (width, height)) style_context = self.get_style_context() if not pixbuf: print_w(f"Failed to scale pixbuf for {self._path}") return surface = get_surface_for_pixbuf(self, pixbuf) Gtk.render_icon_surface(style_context, cairo_context, surface, 0, 0) class CoverImage(Gtk.EventBox): __gsignals__ = { # We do not necessarily display cover at the same instant this widget # is created or set_song is called. This signal allows callers know # when the cover is visible for sure. The signal argument tells whether # cover shown is not the fallback image. 'cover-visible': (GObject.SignalFlags.RUN_LAST, None, (bool,)) } def __init__(self, resize=False, size=70, song=None): super().__init__() self.set_visible_window(False) self.__song = None self.__file = None self.__current_bci = None self.__cancellable = None self._scale = 0.9 self.add(ResizeImage(resize, size)) self.connect('button-press-event', self.__album_clicked) self.set_song(song) self.get_child().show_all() def set_image(self, _file): if _file is not None and not _file.name: print_w('Got file which is not in the filesystem!') self.__file = _file self.get_child().set_file(_file) def set_song(self, song): self.__song = song self.set_image(None) if self.__cancellable: self.__cancellable.cancel() cancellable = self.__cancellable = Gio.Cancellable() if song: def cb(success, result): if success: try: self.set_image(result) self.emit('cover-visible', success) self.update_bci(result) # If this widget is already 'destroyed', we will get # following error. except AttributeError: pass else: self.update_bci(None) app.cover_manager.acquire_cover(cb, cancellable, song) def refresh(self): self.set_song(self.__song) def update_bci(self, albumfile): # If there's a big image displaying, it should update. if self.__current_bci is not None: self.__current_bci.destroy() if albumfile: if self._scale: self.__show_cover(self.__song, self._scale) else: self.__show_cover(self.__song) def __nonzero__(self): return bool(self.__file) def __reset_bci(self, bci): self.__current_bci = None def __album_clicked(self, box, event): song = self.__song if not song: return if (event.type != Gdk.EventType.BUTTON_PRESS or event.button == Gdk.BUTTON_MIDDLE): return False return self.__show_cover(song, scale=self._scale) def __show_cover(self, song, scale=0.5): """Show the cover as a detached BigCenteredImage. If one is already showing, destroy it instead If there is no image, run the AlbumArt plugin """ if not self.__file and song.is_file: from quodlibet.qltk.songsmenu import SongsMenu from quodlibet import app SongsMenu.plugins.handle(ALBUM_ART_PLUGIN_ID, app.library, qltk.get_top_parent(self), [song]) return True if self.__current_bci is not None: # We're displaying it; destroy it. self.__current_bci.destroy() return True if not self.__file: return False try: self.__current_bci = BigCenteredImage( song.comma("album"), self.__file, parent=self, scale=scale) except GLib.GError: # reload in case the image file is gone self.refresh() else: self.__current_bci.show() self.__current_bci.connect('destroy', self.__reset_bci) return True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/qltk/data_editors.py0000644000175000017500000003530714327505043020175 0ustar00nicknick# Copyright 2012-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Iterable from gi.repository import Gtk from gi.repository import Pango from quodlibet import _ from quodlibet import qltk, util from quodlibet.qltk.entry import UndoEntry, ValidatingEntry from quodlibet.qltk.views import RCMHintedTreeView, HintedTreeView from quodlibet.qltk.x import MenuItem, Button, Align from quodlibet.qltk import Icons from quodlibet.query import Query from quodlibet.util.json_data import JSONObjectDict from quodlibet.util import connect_obj from quodlibet.qltk.getstring import GetStringDialog class JSONBasedEditor(qltk.UniqueWindow): """ Flexible editor for objects extending `JSONObject` (held in a `JSONObjectDict`) TODO: validation, especially for name. """ _WIDTH = 800 _HEIGHT = 400 def __init__(self, Prototype, values, filename, title): if self.is_not_unique(): return super().__init__() self.Prototype = Prototype self.current = None self.filename = filename self.name = Prototype.NAME or Prototype.__name__ self.input_entries = {} self.set_border_width(12) self.set_title(title) self.set_default_size(self._WIDTH, self._HEIGHT) self.add(Gtk.HBox(spacing=6)) self.get_child().set_homogeneous(True) self.accels = Gtk.AccelGroup() # Set up the model for this widget self.model = Gtk.ListStore(object) self._fill_values(values) # The browser for existing data self.view = view = RCMHintedTreeView(model=self.model) view.set_headers_visible(False) view.set_reorderable(True) view.set_rules_hint(True) render = Gtk.CellRendererText() render.set_padding(3, 6) render.props.ellipsize = Pango.EllipsizeMode.END column = Gtk.TreeViewColumn("", render) column.set_cell_data_func(render, self.__cdf) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(view) self.get_child().pack_start(sw, True, True, 0) vbox = Gtk.VBox(spacing=6) # Input for new ones. frame = self.__build_input_frame() vbox.pack_start(frame, False, True, 0) # Add context menu menu = Gtk.Menu() rem = MenuItem(_("_Remove"), Icons.LIST_REMOVE) keyval, mod = Gtk.accelerator_parse("Delete") rem.add_accelerator( 'activate', self.accels, keyval, mod, Gtk.AccelFlags.VISIBLE) connect_obj(rem, 'activate', self.__remove, view) menu.append(rem) menu.show_all() view.connect('popup-menu', self.__popup, menu) view.connect('key-press-event', self.__view_key_press) connect_obj(self, 'destroy', Gtk.Menu.destroy, menu) # New and Close buttons bbox = Gtk.HButtonBox() self.remove_but = Button(_("_Remove"), Icons.LIST_REMOVE) self.remove_but.set_sensitive(False) self.new_but = Button(_("_New"), Icons.DOCUMENT_NEW) self.new_but.connect('clicked', self._new_item) bbox.pack_start(self.new_but, True, True, 0) close = Button(_("_Close"), Icons.WINDOW_CLOSE) connect_obj(close, 'clicked', qltk.Window.destroy, self) bbox.pack_start(close, True, True, 0) vbox.pack_end(bbox, False, True, 0) self.get_child().pack_start(vbox, True, True, 0) # Initialise self.selection = view.get_selection() self.selection.connect('changed', self.__select) self.connect('destroy', self.__finish) self.get_child().show_all() def _find(self, name): for row in self.model: if row[0].name == name: return row[0] def _new_item(self, button): # Translators: New Command/Entry/Item/... current_name = name = _("New %s") % self.name n = 2 while True: if self._find(current_name): current_name = "%s (%d)" % (name, n) n += 1 continue break self.model.append(row=(self.Prototype(name=current_name),)) def _new_widget(self, key, val): """ Creates a Gtk.Entry subclass appropriate for a field named `key` with value `val` """ callback = signal = None if isinstance(val, bool): entry = Gtk.CheckButton() callback = self.__toggled_widget signal = "toggled" elif isinstance(val, int): adj = Gtk.Adjustment.new(0, 0, 9999, 1, 10, 0) entry = Gtk.SpinButton(adjustment=adj) entry.set_numeric(True) callback = self.__changed_numeric_widget elif "pattern" in key: entry = ValidatingEntry(validator=Query.validator) else: entry = UndoEntry() entry.connect(signal or "changed", callback or self.__changed_widget, key) return entry def __refresh_view(self): model, iter = self.selection.get_selected() self.model.emit("row-changed", model[iter].path, iter) def __changed_widget(self, entry, key): if self.current: setattr(self.current, key, str(entry.get_text())) self.__refresh_view() def __changed_numeric_widget(self, entry, key): if self.current: setattr(self.current, key, int(entry.get_text() or 0)) self.__refresh_view() def __toggled_widget(self, entry, key): if self.current: setattr(self.current, key, bool(entry.get_active())) self.__refresh_view() def _populate_fields(self, obj): """Populates the input fields based on the `JSONData` object `obj`""" for fn, val in obj.data: widget = self.input_entries[fn] widget.set_sensitive(True) # TODO: link this logic better with the creational stuff if isinstance(val, bool): widget.set_active(val) elif isinstance(val, int): widget.set_value(int(val)) elif isinstance(val, str): widget.set_text(val or "") def __build_input_frame(self): t = Gtk.Table(n_rows=2, n_columns=3) t.set_row_spacings(6) t.set_col_spacing(0, 3) t.set_col_spacing(1, 12) empty = self.Prototype("empty") for i, (key, val) in enumerate(empty.data): field = empty.field(key) field_name = self.get_field_name(field, key) l = Gtk.Label(label=field_name + ":") entry = self._new_widget(key, val) entry.set_sensitive(False) if field.doc: entry.set_tooltip_text(field.doc) # Store these away in a map for later access self.input_entries[key] = entry l.set_mnemonic_widget(entry) l.set_use_underline(True) l.set_alignment(0.0, 0.5) if isinstance(val, (int, bool)): align = Align(entry, halign=Gtk.Align.START) t.attach(align, 1, 2, i, i + 1) else: t.attach(entry, 1, 2, i, i + 1) t.attach(l, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) frame = qltk.Frame(label=self.name, child=t) self.input_entries["name"].grab_focus() return frame @staticmethod def get_field_name(field, key): field_name = (field.human_name or (key and key.replace("_", " "))) return field_name and util.capitalize(field_name) or _("(unknown)") def _fill_values(self, data): if not data: return for (name, obj) in data.items(): self.model.append(row=[obj]) def _update_current(self, new_selection=None): if new_selection: self.selection = new_selection model, iter = self.selection.get_selected() if iter: self.current = model[iter][0] def __select(self, selection): self._update_current(selection) self.remove_but.set_sensitive(bool(iter)) if iter is not None: self._populate_fields(self.current) def __remove(self, view): view.remove_selection() def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __view_key_press(self, view, event): if event.keyval == Gtk.accelerator_parse("Delete")[0]: self.__remove(view) def __cdf(self, column, cell, model, iter, data): row = model[iter] obj = row[0] obj_name = util.escape(obj.name) obj_description = util.escape(str(obj)) markup = f"{util.bold(obj_name)}\n{obj_description}" cell.markup = markup cell.set_property('markup', markup) def __finish(self, widget): # TODO: Warn about impending deletion of nameless items, or something all = JSONObjectDict.from_list( [row[0] for row in self.model if row[0].name]) all.save(filename=self.filename) class TagListEditor(qltk.Window): """Dialog to edit a list of tag names.""" _WIDTH = 600 _HEIGHT = 300 def __init__(self, title, values=None): super().__init__() self.use_header_bar() self.set_border_width(12) self.set_title(title) self.set_default_size(self._WIDTH, self._HEIGHT) vbox = Gtk.VBox(spacing=12) hbox = Gtk.HBox(spacing=12) # Set up the model for this widget self.model = Gtk.ListStore(str) self.__fill_values(values or []) def on_row_activated(view, path, column): self._renderer.set_property('editable', True) view.set_cursor(path, view.get_columns()[0], start_editing=True) # Main view view = self.view = HintedTreeView(model=self.model) view.set_fixed_height_mode(True) view.set_headers_visible(False) view.connect("row-activated", on_row_activated) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_size_request(-1, max(sw.size_request().height, 100)) hbox.pack_start(sw, True, True, 0) self.__setup_column(view) # Context menu menu = Gtk.Menu() remove_item = MenuItem(_("_Remove"), Icons.LIST_REMOVE) menu.append(remove_item) menu.show_all() view.connect('popup-menu', self.__popup, menu) connect_obj(remove_item, 'activate', self.__remove, view) # Add and Remove buttons vbbox = Gtk.VButtonBox() vbbox.set_layout(Gtk.ButtonBoxStyle.START) vbbox.set_spacing(6) add = Button(_("_Add…"), Icons.LIST_ADD) add.connect("clicked", self.__add) vbbox.pack_start(add, False, True, 0) remove = Button(_("_Remove"), Icons.LIST_REMOVE) remove.connect("clicked", self.__remove) vbbox.pack_start(remove, False, True, 0) edit = Button(_("_Edit"), Icons.LIST_EDIT) edit.connect("clicked", self.__edit) vbbox.pack_start(edit, False, True, 0) hbox.pack_start(vbbox, False, True, 0) vbox.pack_start(hbox, True, True, 0) # Close buttons bbox = Gtk.HButtonBox() self.remove_but = Button(_("_Remove"), Icons.LIST_REMOVE) self.remove_but.set_sensitive(False) close = Button(_("_Close"), Icons.WINDOW_CLOSE) connect_obj(close, 'clicked', qltk.Window.destroy, self) bbox.set_layout(Gtk.ButtonBoxStyle.END) if not self.has_close_button(): bbox.pack_start(close, True, True, 0) vbox.pack_start(bbox, False, True, 0) # Finish up self.add(vbox) self.get_child().show_all() def __start_editing(self, _render, editable, path): editable.set_text(self.model[path][0]) def __edited(self, _render, path, new_name): self.model[path][0] = new_name self.model.row_changed(path, self.model.get_iter(path)) def __setup_column(self, view): def tag_cdf(column, cell, model, iter, data): row = model[iter] if row: cell.set_property('text', row[0]) def desc_cdf(column, cell, model, iter, data): row = model[iter] if row: cell.set_property('markup', util.italic(util.tag(row[0]))) def __create_cell_renderer(): r = Gtk.CellRendererText() r.connect('editing-started', self.__start_editing) r.connect('edited', self.__edited) return r self._renderer = renderer = __create_cell_renderer() column = Gtk.TreeViewColumn(_("Tag expression"), renderer) column.set_cell_data_func(renderer, tag_cdf) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_expand(True) view.append_column(column) renderer = Gtk.CellRendererText() renderer.set_property('ellipsize', Pango.EllipsizeMode.END) renderer.set_property('sensitive', False) column = Gtk.TreeViewColumn(_("Description"), renderer) column.set_cell_data_func(renderer, desc_cdf) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_expand(True) view.append_column(column) view.set_headers_visible(True) def __fill_values(self, data: Iterable[str]): for s in data: self.model.append(row=[s]) @property def tags(self): """Returns the tag names as edited""" return [row[0] for row in self.model if row] def __remove(self, *args): self.view.remove_selection() def __add(self, *args): tooltip = _('Tag expression e.g. people:real or ~album~year') dialog = GetStringDialog(self, _("Enter new tag"), "", button_icon=None, tooltip=tooltip) new = dialog.run() if new: self.model.append(row=[new]) def __edit(self, *args): path, col = self.view.get_cursor() tooltip = _('Tag expression e.g. people:real or ~album~year') dialog = GetStringDialog(self, _("Edit tag expression"), "", button_icon=None, tooltip=tooltip) edited = dialog.run(text=self.model[path][0]) if edited: self.model[path][0] = edited def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()).show() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/qltk/dbus_.py0000664000175000017500000001525514035600052016621 0ustar00nicknick# Copyright 2006 Federico Pelloni # 2013 Christoph Reiter # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GLib from gi.repository import Gio from quodlibet import commands, app from quodlibet.util import dbusutils from quodlibet.query import Query from quodlibet.qltk.songlist import SongList from quodlibet.formats import decode_value class DBusHandler: """ """ BUS_NAME = 'net.sacredchao.QuodLibet' PATH = '/net/sacredchao/QuodLibet' def __init__(self, player, library): try: self._registered_ids = [] self._method_outargs = {} self.library = library self.conn = Gio.bus_get_sync(Gio.BusType.SESSION, None) Gio.bus_own_name_on_connection(self.conn, self.BUS_NAME, Gio.BusNameOwnerFlags.NONE, None, self.__on_name_lost) self.__register_ifaces() except GLib.Error: pass else: player.connect('song-started', self.__song_started) player.connect('song-ended', self.__song_ended) player.connect('paused', lambda player: self.Paused()) player.connect('unpaused', lambda player: self.Unpaused()) self._player = player def __on_name_lost(self, connection, name): for _id in self._registered_ids: connection.unregister_object(_id) def __register_ifaces(self): info = Gio.DBusNodeInfo.new_for_xml(self.__doc__) for interface in info.interfaces: for method in interface.methods: self._method_outargs[method.name] = '({})'.format( ''.join([arg.signature for arg in method.out_args])) _id = self.conn.register_object( object_path=self.PATH, interface_info=interface, method_call_closure=self.__on_method_call) self._registered_ids.append(_id) def __on_method_call(self, connection, sender, object_path, interface_name, method_name, parameters, invocation): args = list(parameters.unpack()) result = getattr(self, method_name)(*args) if not isinstance(result, tuple): result = (result,) out_args = self._method_outargs[method_name] if out_args != '()': variant = GLib.Variant(out_args, result) invocation.return_value(variant) else: invocation.return_value(None) @staticmethod def __dict(song): dict = {} for key, value in (song or {}).items(): value = decode_value(key, value) dict[key] = dbusutils.dbus_unicode_validate(value) if song: dict["~uri"] = song("~uri") return dict def __song_started(self, player, song): if song is not None: song = self.__dict(song) self.SongStarted(song) def __song_ended(self, player, song, skipped): if song is not None: song = self.__dict(song) self.SongEnded(song, skipped) def Introspect(self): return self.__doc__ def SongStarted(self, song): self.conn.emit_signal(None, self.PATH, 'net.sacredchao.QuodLibet', 'SongStarted', GLib.Variant('(a{ss})', (song,))) def SongEnded(self, song, skipped): self.conn.emit_signal(None, self.PATH, 'net.sacredchao.QuodLibet', 'SongEnded', GLib.Variant('(a{ss}b)', (song, skipped))) def Paused(self): self.conn.emit_signal(None, self.PATH, 'net.sacredchao.QuodLibet', 'Paused', None) def Unpaused(self): self.conn.emit_signal(None, self.PATH, 'net.sacredchao.QuodLibet', 'Unpaused', None) def GetPosition(self): return self._player.get_position() def IsPlaying(self): return not self._player.paused def CurrentSong(self): return self.__dict(self._player.song) def Rate(self, rating: str): """ Rates the currently playing song :param rating: A value between 0 and 1. Prefix with +/- to indicate a relative change """ commands._rating(app, rating) def Next(self): self._player.next() def Previous(self): self._player.previous() def Pause(self): self._player.paused = True def Play(self): self._player.play() def PlayPause(self): self._player.playpause() return self._player.paused def Query(self, text): if text is not None: query = Query(text, star=SongList.star) if query.is_parsable: return [self.__dict(s) for s in self.library.values() if query.search(s)] return None ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1692733642.0 quodlibet-4.6.0/quodlibet/qltk/delete.py0000644000175000017500000002107314471210312016760 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2013-2017 Nick Boultbee # 2013,2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """ Functions for deleting files and songs with user interaction. Only use trash_files() or trash_songs() and TrashMenuItem(). """ import os from gi.repository import Gtk from senf import fsn2text from quodlibet import _ from quodlibet import print_w from quodlibet.util import trash from quodlibet.qltk import get_top_parent from quodlibet.qltk import Icons from quodlibet.qltk.msg import ErrorMessage, WarningMessage from quodlibet.qltk.wlw import WaitLoadWindow from quodlibet.qltk.x import MenuItem, Align from quodlibet.util.i18n import numeric_phrase from quodlibet.util.path import unexpand class FileListExpander(Gtk.Expander): """A widget for showing a static list of file paths""" def __init__(self, paths): super().__init__(label=_("Files:")) self.set_resize_toplevel(True) paths = [fsn2text(unexpand(p)) for p in paths] lab = Gtk.Label(label="\n".join(paths)) lab.set_alignment(0.0, 0.0) lab.set_selectable(True) win = Gtk.ScrolledWindow() win.add_with_viewport(Align(lab, border=6)) win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) win.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) win.set_size_request(-1, 100) self.add(win) win.show_all() class DeleteDialog(WarningMessage): RESPONSE_DELETE = 1 """Return value of DeleteDialog.run() in case the passed files should be deleted""" @classmethod def for_songs(cls, parent, songs): """Create a delete dialog for deleting songs""" description = _("The selected songs will be removed from the " "library and their files deleted from disk.") paths = [s("~filename") for s in songs] return cls(parent, paths, description) @classmethod def for_files(cls, parent, paths): """Create a delete dialog for deleting files""" description = _("The selected files will be deleted from disk.") return cls(parent, paths, description) def __init__(self, parent, paths, description): title = numeric_phrase("Delete %(file_count)d file permanently?", "Delete %(file_count)d files permanently?", len(paths), "file_count") super().__init__( get_top_parent(parent), title, description, buttons=Gtk.ButtonsType.NONE) area = self.get_message_area() exp = FileListExpander(paths) exp.show() area.pack_start(exp, False, True, 0) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Delete Files"), Icons.EDIT_DELETE, self.RESPONSE_DELETE) self.set_default_response(Gtk.ResponseType.CANCEL) class TrashDialog(WarningMessage): RESPONSE_TRASH = 1 """Return value of TrashDialog.run() in case the passed files should be moved to the trash""" @classmethod def for_songs(cls, parent, songs): """Create a trash dialog for trashing songs""" description = _("The selected songs will be removed from the " "library and their files moved to the trash.") paths = [s("~filename") for s in songs] return cls(parent, paths, description) @classmethod def for_files(cls, parent, paths): """Create a trash dialog for trashing files""" description = _("The selected files will be moved to the trash.") return cls(parent, paths, description) def __init__(self, parent, paths, description): title = numeric_phrase("Move %(file_count)d file to the trash?", "Move %(file_count)d files to the trash?", len(paths), "file_count") super().__init__( get_top_parent(parent), title, description, buttons=Gtk.ButtonsType.NONE) area = self.get_message_area() exp = FileListExpander(paths) exp.show() area.pack_start(exp, False, True, 0) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Move to Trash"), Icons.USER_TRASH, self.RESPONSE_TRASH) self.set_default_response(Gtk.ResponseType.CANCEL) def TrashMenuItem(): if trash.use_trash(): return MenuItem(_("_Move to Trash"), Icons.USER_TRASH) else: return MenuItem(_("_Delete"), Icons.EDIT_DELETE) def _do_trash_songs(parent, songs, librarian): dialog = TrashDialog.for_songs(parent, songs) resp = dialog.run() if resp != TrashDialog.RESPONSE_TRASH: return window_title = _("Moving %(current)d/%(total)d.") w = WaitLoadWindow(parent, len(songs), window_title) w.show() ok = [] failed = [] for song in songs: filename = song("~filename") try: trash.trash(filename) except trash.TrashError as e: print_w("Couldn't trash file (%s)" % e) failed.append(song) else: ok.append(song) w.step() w.destroy() if failed: ErrorMessage(parent, _("Unable to move to trash"), _("Moving one or more files to the trash failed.") ).run() if ok: librarian.remove(ok) def _do_trash_files(parent, paths): dialog = TrashDialog.for_files(parent, paths) resp = dialog.run() if resp != TrashDialog.RESPONSE_TRASH: return window_title = _("Moving %(current)d/%(total)d.") w = WaitLoadWindow(parent, len(paths), window_title) w.show() ok = [] failed = [] for path in paths: try: trash.trash(path) except trash.TrashError: failed.append(path) else: ok.append(path) w.step() w.destroy() if failed: ErrorMessage(parent, _("Unable to move to trash"), _("Moving one or more files to the trash failed.") ).run() def _do_delete_songs(parent, songs, librarian): dialog = DeleteDialog.for_songs(parent, songs) resp = dialog.run() if resp != DeleteDialog.RESPONSE_DELETE: return window_title = _("Deleting %(current)d/%(total)d.") w = WaitLoadWindow(parent, len(songs), window_title) w.show() ok = [] failed = [] for song in songs: filename = song("~filename") try: os.unlink(filename) except EnvironmentError: failed.append(song) else: ok.append(song) w.step() w.destroy() if failed: ErrorMessage(parent, _("Unable to delete files"), _("Deleting one or more files failed.") ).run() if ok: librarian.remove(ok) def _do_delete_files(parent, paths): dialog = DeleteDialog.for_files(parent, paths) resp = dialog.run() if resp != DeleteDialog.RESPONSE_DELETE: return window_title = _("Deleting %(current)d/%(total)d.") w = WaitLoadWindow(parent, len(paths), window_title) w.show() ok = [] failed = [] for path in paths: try: os.unlink(path) except EnvironmentError: failed.append(path) else: ok.append(path) w.step() w.destroy() if failed: ErrorMessage(parent, _("Unable to delete files"), _("Deleting one or more files failed.") ).run() def trash_files(parent, paths): """Will try to move the files to the trash, or if not possible, delete them permanently. Will ask for confirmation in each case. """ if not paths: return # depends on the platform if we can if trash.use_trash(): _do_trash_files(parent, paths) else: _do_delete_files(parent, paths) def trash_songs(parent, songs, librarian): """Will try to move the files associated with the songs to the trash, or if not possible, delete them permanently. Will ask for confirmation in each case. The deleted songs will be removed from the librarian. """ if not songs: return # depends on the platform if we can if trash.use_trash(): _do_trash_songs(parent, songs, librarian) else: _do_delete_songs(parent, songs, librarian) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658867493.0 quodlibet-4.6.0/quodlibet/qltk/download.py0000644000175000017500000000654414270047445017347 0ustar00nicknick# Copyright 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from os.path import splitext from pathlib import Path from time import sleep from typing import Tuple, Collection, Any, Set from urllib.parse import urlparse from gi.repository import Soup, GObject from quodlibet import print_d, print_w, _, print_e from quodlibet.formats import AudioFile from quodlibet.qltk.notif import Task from quodlibet.util import http, format_size from quodlibet.util.path import escape_filename class DownloadProgress(GObject.Object): """Downloads songs asynchronously, updating a Task""" __gsignals__ = { 'finished': (GObject.SignalFlags.RUN_LAST, None, (object, object)), } def __init__(self, songs: Collection[AudioFile], task=None) -> None: super().__init__() self.songs = songs self.successful: Set[AudioFile] = set() self.failed: Set[AudioFile] = set() self.task = task or Task(_("Browser"), _("Downloading files")) def success(self, song: AudioFile) -> None: self.successful.add(song) self._update() def failure(self, song: AudioFile) -> None: self.failed.add(song) self._update() def _update(self) -> None: frac = self.frac print_d(f"At {frac * 100:.0f}% ({len(self.successful)}, {len(self.failed)})") self.task.update(frac) @property def frac(self): frac = (len(self.successful) + len(self.failed)) / len(self.songs) return frac def _downloaded(self, msg: Soup.Message, result: Any, data: Tuple) -> None: path, song = data try: headers = msg.get_property('response-headers') size = int(headers.get('content-length')) content_type = headers.get('content-type') print_d( f"Downloaded {format_size(size)} of {content_type}: {song('title')}") _, ext = splitext(urlparse(song("~uri")).path) fn = (escape_filename(song("~artist~title")[:100], safe=b" ,';") or song("~basename") or f"download-{hash(song('~filename'))}") path = path / Path(fn + ext) if path.is_file() and path.stat(): print_w(f"{path!s} already exists. Skipping download") self.success(song) return with open(path, "wb") as f: f.write(result) self.success(song) print_d(f"Downloaded to {path} successfully!") except Exception as e: print_e(f"Failed download ({e})") self.failure(song) def _failed(self, _req: Any, _exc: Exception, data: Tuple) -> None: path, song = data self.failure(song) def download_songs(self, path: Path): for s in self.songs: msg = Soup.Message.new('GET', s("~uri")) http.download(msg, cancellable=None, callback=self._downloaded, failure_callback=self._failed, data=(path, s)) yield while self.frac < 1 and self.task: sleep(0.1) yield self.task.finish() self.emit("finished", len(self.successful), len(self.failed)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1684762879.0 quodlibet-4.6.0/quodlibet/qltk/edittags.py0000644000175000017500000012157614432670377017355 0ustar00nicknick# Copyright 2004-2012 Joe Wreschnig, Michael Urman, Iñigo Serna # 2011-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys from typing import Optional, Type, Sequence from gi.repository import Gtk, Pango, Gdk from quodlibet import C_, _, ngettext, print_e, print_d from quodlibet import app from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet.formats import AudioFileError from quodlibet.plugins import PluginManager from quodlibet.plugins.editing import EditTagsPlugin from quodlibet.qltk import Icons from quodlibet.qltk._editutils import EditingPluginHandler, OverwriteWarning from quodlibet.qltk._editutils import WriteFailedError from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk.completion import LibraryValueCompletion from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.tagscombobox import TagsComboBox, TagsComboBoxEntry from quodlibet.qltk.views import RCMHintedTreeView, TreeViewColumn, BaseView from quodlibet.qltk.window import Dialog from quodlibet.qltk.wlw import WritingWindow from quodlibet.qltk.x import SeparatorMenuItem, Button, MenuItem from quodlibet.util import connect_obj from quodlibet.util import massagers from quodlibet.util.i18n import numeric_phrase from quodlibet.util.string.splitters import (split_value, split_title, split_people, split_album) from quodlibet.util.tags import USER_TAGS, MACHINE_TAGS, sortkey as tagsortkey class Comment: """A summary of a collection of values for one tag""" def __init__(self, text, have=1, total=1, shared=True): """ Args: text: the first or only text value have: amount of songs that have a value total: total amount of songs shared: if all songs that have a value, have the same one """ self.complete = have == total self.shared = shared self.total = total self.missing = total - have self.have = have self.text = text def _paren(self): if self.shared: return numeric_phrase('missing from %d song', 'missing from %d songs', self.missing) elif self.complete: return numeric_phrase('different across %d song', 'different across %d songs', self.total) else: d = numeric_phrase('different across %d song', 'different across %d songs', self.have) m = numeric_phrase('missing from %d song', 'missing from %d songs', self.missing) return ", ".join([d, m]) def is_special(self): return not self.shared or not self.complete def is_missing(self): return not self.complete def get_shared_text(self): if self.shared: return util.escape(self.text) return '' def get_markup(self): """Returns pango markup for displaying""" if self.shared and self.complete: return util.escape(self.text) elif self.shared: return "\n".join( [f"{util.escape(s)}{util.italic(' ' + self._paren())}" for s in self.text.split("\n")]) else: return util.italic(self._paren()) def get_default_tags(): """Returns a list of tags that should be displayed even if not present in the file. """ text = config.get("editing", "default_tags").strip() if not text: return [] return text.split(",") class AudioFileGroup(dict): """Values are a list of Comment instances""" def __init__(self, songs, real_keys_only=True): keys = {} first = {} all = {} total = len(songs) self.songs = songs self.is_file = True can_multi = True can_change = True for song in songs: self.is_file &= song.is_file if real_keys_only: iter_func = song.iterrealitems else: iter_func = song.items for comment, val in iter_func(): keys[comment] = keys.get(comment, 0) + 1 first.setdefault(comment, val) all[comment] = all.get(comment, True) and first[comment] == val song_can_multi = song.can_multiple_values() if song_can_multi is not True: if can_multi is True: can_multi = set(song_can_multi) else: can_multi.intersection_update(song_can_multi) song_can_change = song.can_change() if song_can_change is not True: if can_change is True: can_change = set(song_can_change) else: can_change.intersection_update(song_can_change) self._can_multi = can_multi self._can_change = can_change # collect comment representations for tag, count in keys.items(): first_value = first[tag] if not isinstance(first_value, str): first_value = str(first_value) shared = all[tag] complete = count == total if shared and complete: values = first_value.split("\n") else: values = [first_value] for v in values: self.setdefault(tag, []).append( Comment(v, count, total, shared)) def can_multiple_values(self, key=None): """If no arguments passed returns a set of tags that have multi value support for all contained songs. If key is given returns if all songs support multi value tags for that key. """ if key is None: return self._can_multi return all(song.can_multiple_values(key) for song in self.songs) def can_change(self, key=None): """See can_multiple_values()""" if key is None: return self._can_change return all(song.can_change(key) for song in self.songs) class TagSplitter(EditTagsPlugin): """Splits tag values into other tags""" pass class SplitValues(TagSplitter): def __init__(self, tag, value): super().__init__( label=_("Split into _Multiple Values"), use_underline=True) self.set_image(Gtk.Image.new_from_icon_name( Icons.EDIT_FIND_REPLACE, Gtk.IconSize.MENU)) spls = config.gettext("editing", "split_on").split() vals = [val if len(val) <= 64 else val[:64] + "…" for val in split_value(value, spls)] string = ", ".join(["{}={}".format(tag, val) for val in vals]) self.set_label(string) self.set_sensitive(len(vals) > 1) def activated(self, tag, value): spls = config.gettext("editing", "split_on").split() return [(tag, v) for v in split_value(value, spls)] class SplitDisc(TagSplitter): tags = ["album"] needs = ["discnumber"] _order = 0.5 def __init__(self, tag, value): super().__init__( label=_("Split Disc out of _Album"), use_underline=True) self.set_image(Gtk.Image.new_from_icon_name( Icons.EDIT_FIND_REPLACE, Gtk.IconSize.MENU)) album, disc = split_album(value) if disc is not None: album = album if len(album) <= 64 else album[:64] + "…" self.set_label("{}={}, {}={}".format(tag, album, self.needs[0], disc)) self.set_sensitive(disc is not None) def activated(self, tag, value): album, disc = split_album(value) return [(tag, album), ("discnumber", disc)] class SplitTitle(TagSplitter): tags = ["title"] needs = ["version"] _order = 0.5 def __init__(self, tag, value): super().__init__( label=_("Split _Version out of Title"), use_underline=True) self.set_image(Gtk.Image.new_from_icon_name( Icons.EDIT_FIND_REPLACE, Gtk.IconSize.MENU)) tag_spls = config.gettext("editing", "split_on").split() sub_spls = config.gettext("editing", "sub_split_on").split() title, versions = split_title(value, tag_spls, sub_spls) if versions: title = title if len(title) <= 64 else title[:64] + "…" versions = [ver if len(ver) <= 64 else ver[:64] + "…" for ver in versions] string = (", ".join(["{}={}".format(tag, title)] + ["{}={}".format(self.needs[0], ver) for ver in versions])) self.set_label(string) self.set_sensitive(bool(versions)) def activated(self, tag, value): tag_spls = config.gettext("editing", "split_on").split() sub_spls = config.gettext("editing", "sub_split_on").split() title, versions = split_title(value, tag_spls, sub_spls) return [(tag, title)] + [("version", v) for v in versions] class SplitPerson(TagSplitter): tags = ["artist"] _order = 0.5 def __init__(self, tag, value): super().__init__(label=self.title, use_underline=True) self.set_image(Gtk.Image.new_from_icon_name( Icons.EDIT_FIND_REPLACE, Gtk.IconSize.MENU)) tag_spls = config.gettext("editing", "split_on").split() sub_spls = config.gettext("editing", "sub_split_on").split() artist, others = split_people(value, tag_spls, sub_spls) if others: artist = artist if len(artist) <= 64 else artist[:64] + "…" others = [other if len(other) <= 64 else other[:64] + "…" for other in others] string = (", ".join(["{}={}".format(tag, artist)] + ["{}={}".format(self.needs[0], o) for o in others])) self.set_label(string) self.set_sensitive(bool(others)) def activated(self, tag, value): tag_spls = config.gettext("editing", "split_on").split() sub_spls = config.gettext("editing", "sub_split_on").split() artist, others = split_people(value, tag_spls, sub_spls) return [(tag, artist)] + [(self.needs[0], o) for o in others] class SplitArranger(SplitPerson): needs = ["arranger"] title = _("Split Arranger out of Ar_tist") class SplitPerformer(SplitPerson): needs = ["performer"] title = _("Split _Performer out of Artist") class SplitPerformerFromTitle(SplitPerson): tags = ["title"] needs = ["performer"] title = _("Split _Performer out of Title") class SplitOriginalArtistFromTitle(SplitPerson): tags = ["title"] needs = ["originalartist"] title = _("Split _Originalartist out of Title") class AddTagDialog(Dialog): def __init__(self, parent, can_change, library): super().__init__( title=_("Add a Tag"), transient_for=qltk.get_top_parent(parent), use_header_bar=True) self.set_border_width(6) self.set_resizable(False) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) add = self.add_icon_button(_("_Add"), Icons.LIST_ADD, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) table = Gtk.Table(n_rows=2, n_columns=2) table.set_row_spacings(12) table.set_col_spacings(6) table.set_border_width(6) self.__tag = (TagsComboBoxEntry() if can_change is True else TagsComboBox(can_change)) label = Gtk.Label() label.set_alignment(0.0, 0.5) label.set_text(_("_Tag:")) label.set_use_underline(True) label.set_mnemonic_widget(self.__tag) table.attach(label, 0, 1, 0, 1) table.attach(self.__tag, 1, 2, 0, 1) self.__val = Gtk.Entry() self.__val.set_completion(LibraryValueCompletion("", library)) label = Gtk.Label() label.set_text(_("_Value:")) label.set_alignment(0.0, 0.5) label.set_use_underline(True) label.set_mnemonic_widget(self.__val) valuebox = Gtk.EventBox() table.attach(label, 0, 1, 1, 2) table.attach(valuebox, 1, 2, 1, 2) hbox = Gtk.HBox() valuebox.add(hbox) hbox.pack_start(self.__val, True, True, 0) hbox.set_spacing(6) invalid = Gtk.Image.new_from_icon_name( Icons.DIALOG_WARNING, Gtk.IconSize.SMALL_TOOLBAR) hbox.pack_start(invalid, True, True, 0) self.vbox.pack_start(table, True, True, 0) self.get_child().show_all() invalid.hide() for entry in [self.__tag, self.__val]: entry.connect( 'changed', self.__validate, add, invalid, valuebox) self.__tag.connect('changed', self.__set_value_completion, library) self.__set_value_completion(self.__tag, library) if can_change is True: connect_obj(self.__tag.get_child(), 'activate', Gtk.Entry.grab_focus, self.__val) def __set_value_completion(self, tag, library): completion = self.__val.get_completion() if completion: completion.set_tag(self.__tag.tag, library) def get_tag(self): try: return self.__tag.tag except AttributeError: return self.__tag.tag def get_value(self): return self.__val.get_text() def __validate(self, editable, add, invalid, box): tag = self.get_tag() value = self.get_value() valid = massagers.is_valid(tag, value) add.set_sensitive(valid) if valid: invalid.hide() box.set_tooltip_text("") else: invalid.show() box.set_tooltip_text(massagers.error_message(tag, value)) def run(self): self.show() self.__val.set_activates_default(True) self.__tag.grab_focus() return super().run() class EditTagsPluginHandler(EditingPluginHandler): from quodlibet.plugins.editing import EditTagsPlugin Kind = EditTagsPlugin class ListEntry: """Holds a Comment and some state for the editing process""" tag = None value = None edited = False canedit = True deleted = False origvalue = None renamed = False origtag = None def __init__(self, tag, value): self.tag = tag self.value = value class EditTags(Gtk.VBox): handler = EditTagsPluginHandler() _SPLITTERS: Sequence[Type[TagSplitter]] = sorted( [SplitDisc, SplitTitle, SplitPerformer, SplitArranger, SplitValues, SplitPerformerFromTitle, SplitOriginalArtistFromTitle], key=lambda item: (item._order, item.__name__)) @classmethod def init_plugins(cls): PluginManager.instance.register_handler(cls.handler) def __init__(self, parent, library): super().__init__(spacing=12) self.title = _("Edit Tags") self.set_border_width(12) self._group_info = None model = ObjectStore() view = RCMHintedTreeView(model=model) self._view = view selection = view.get_selection() render = Gtk.CellRendererPixbuf() column = TreeViewColumn() column.pack_start(render, True) column.set_fixed_width(24) column.set_expand(False) def cdf_write(col, rend, model, iter_, *args): entry = model.get_value(iter_) rend.set_property('sensitive', entry.edited or entry.deleted) if entry.canedit or entry.deleted: if entry.deleted: rend.set_property('icon-name', Icons.EDIT_DELETE) else: rend.set_property('icon-name', Icons.EDIT) else: rend.set_property('icon-name', Icons.CHANGES_PREVENT) column.set_cell_data_func(render, cdf_write) view.append_column(column) render = Gtk.CellRendererText() column = TreeViewColumn(title=_('Tag')) column.pack_start(render, True) def cell_data_tag(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.tag) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_tag) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) render.set_property('editable', True) render.connect('edited', self.__edit_tag_name, model) render.connect( 'editing-started', self.__tag_editing_started, model, library) view.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) render.set_property('editable', True) render.connect('edited', self.__edit_tag, model) render.connect( 'editing-started', self.__value_editing_started, model, library) column = TreeViewColumn(title=_('Value')) column.pack_start(render, True) def cell_data_value(column, cell, model, iter_, data): entry = model.get_value(iter_) markup = entry.value.get_markup() cell.markup = markup cell.set_property("markup", markup) cell.set_property("editable", entry.canedit) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_value) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) self.pack_start(sw, True, True, 0) cb = ConfigCheckButton( _("Show _programmatic tags"), 'editing', 'alltags', populate=True, tooltip=_("Access all tags, including machine-generated " "ones e.g. MusicBrainz or Replay Gain tags")) cb.connect('toggled', self.__checkbox_toggled) hb = Gtk.HBox() hb.pack_start(cb, False, True, 0) cb = ConfigCheckButton( _("Show _multi-line tags"), "editing", "show_multi_line_tags", populate=True, tooltip=_("Show potentially multi-line tags (e.g 'lyrics') here too")) cb.connect('toggled', self.__checkbox_toggled) hb.pack_start(cb, False, True, 12) self.pack_start(hb, False, True, 0) # Add and Remove [tags] buttons buttonbox = Gtk.HBox(spacing=18) bbox1 = Gtk.HButtonBox() bbox1.set_spacing(6) bbox1.set_layout(Gtk.ButtonBoxStyle.START) add = qltk.Button(_("_Add…"), Icons.LIST_ADD) add.set_focus_on_click(False) self._add = add add.connect('clicked', self.__add_tag, model, library) bbox1.pack_start(add, True, True, 0) # Remove button remove = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) remove.set_focus_on_click(False) remove.connect('clicked', self.__remove_tag, view) remove.set_sensitive(False) self._remove = remove bbox1.pack_start(remove, True, True, 0) # Revert and save buttons # Both can have customised translated text (and thus accels) bbox2 = Gtk.HButtonBox() bbox2.set_spacing(6) bbox2.set_layout(Gtk.ButtonBoxStyle.END) # Translators: Revert button in the tag editor revert = Button(C_("edittags", "_Revert"), Icons.DOCUMENT_REVERT) self._revert = revert revert.set_sensitive(False) # Translators: Save button in the tag editor save = Button(C_("edittags", "_Save"), Icons.DOCUMENT_SAVE) save.set_sensitive(False) self._save = save bbox2.pack_start(revert, True, True, 0) bbox2.pack_start(save, True, True, 0) buttonbox.pack_start(bbox1, True, True, 0) buttonbox.pack_start(bbox2, True, True, 0) self.pack_start(buttonbox, False, True, 0) self._buttonbox = buttonbox parent.connect('changed', self.__parent_changed) revert.connect('clicked', lambda *x: self._update()) connect_obj(revert, 'clicked', parent.set_pending, None) save.connect('clicked', self.__save_files, revert, model, library) connect_obj(save, 'clicked', parent.set_pending, None) for sig in ['row-inserted', 'row-deleted', 'row-changed']: model.connect(sig, self.__enable_save, [save, revert]) connect_obj(model, sig, parent.set_pending, save) view.connect('popup-menu', self._popup_menu, parent) view.connect('button-press-event', self.__button_press) view.connect('key-press-event', self.__view_key_press_event) selection.connect('changed', self.__tag_select, remove) selection.set_mode(Gtk.SelectionMode.MULTIPLE) self._parent = parent for child in self.get_children(): child.show_all() def __checkbox_toggled(self, *args): self._update() def __view_key_press_event(self, view, event): if qltk.is_accel(event, "Delete"): self.__remove_tag(view, view) return Gdk.EVENT_STOP elif qltk.is_accel(event, "s"): # Issue 697: allow Ctrl-s to save. self._save.emit('clicked') return Gdk.EVENT_STOP elif qltk.is_accel(event, "c"): self.__copy_tag_value(event, view) return Gdk.EVENT_STOP return Gdk.EVENT_PROPAGATE def __enable_save(self, *args): buttons = args[-1] for b in buttons: b.set_sensitive(True) def __paste(self, clip, text, args): rend, path = args if text: rend.emit('edited', path, text.strip()) def __menu_activate(self, activator, view): model, (path,) = view.get_selection().get_selected_rows() entry = model[path][0] tag = entry.tag comment = entry.value value = comment.text vals = activator.activated(tag, value) replaced = False if vals and (len(vals) != 1 or vals[0][1] != value): for atag, aval in vals: if atag == tag and not replaced: replaced = True entry.value = Comment(aval) entry.edited = True model.path_changed(path) else: self.__add_new_tag(model, atag, aval) elif vals: replaced = True if not replaced: entry.edited = entry.deleted = True model.path_changed(path) def __item_for(self, view: BaseView, Item: Type[EditTagsPlugin], tag: str, text: str) -> Optional[EditTagsPlugin]: try: item = Item(tag, text) except Exception as e: print_e(f"Couldn't create menu item from {Item} ({e})") return None else: item.connect('activate', self.__menu_activate, view) return item def _popup_menu(self, view: BaseView, _parent): menu = Gtk.Menu() view.ensure_popup_selection() model, rows = view.get_selection().get_selected_rows() can_change = all(model[path][0].canedit for path in rows) if len(rows) == 1: row = model[rows[0]] entry = row[0] comment = entry.value text = comment.text split_menu = Gtk.Menu() for Item in self._SPLITTERS: if Item.tags and entry.tag not in Item.tags: continue item = self.__item_for(view, Item, entry.tag, text) if not item: continue vals = item.activated(entry.tag, text) changeable = any(not self._group_info.can_change(k) for k in item.needs) fixed = changeable or comment.is_special() if fixed: item.set_sensitive(False) if len(vals) > 1 and vals[1][1]: split_menu.append(item) if split_menu.get_children(): split_menu.append(SeparatorMenuItem()) plugins = self.handler.plugins print_d(f"Adding {len(plugins)} plugin(s) to menu: " f"{', '.join(p.__name__ for p in plugins)}") for p_cls in plugins: item = self.__item_for(view, p_cls, entry.tag, text) if not item: continue results = item.activated(entry.tag, text) # Only enable for the user if the plugin would do something item.set_sensitive(results != [(entry.tag, text)]) menu.append(item) pref_item = MenuItem(_("_Configure"), Icons.PREFERENCES_SYSTEM) split_menu.append(pref_item) def show_prefs(parent): from quodlibet.qltk.exfalsowindow import ExFalsoWindow if isinstance(app.window, ExFalsoWindow): from quodlibet.qltk.exfalsowindow import PreferencesWindow window = PreferencesWindow(parent) else: from quodlibet.qltk.prefs import PreferencesWindow window = PreferencesWindow(parent, open_page="tagging") window.show() connect_obj(pref_item, "activate", show_prefs, self) split_item = MenuItem(_("_Split Tag"), Icons.EDIT_FIND_REPLACE) if split_menu.get_children(): split_item.set_submenu(split_menu) else: split_item.set_sensitive(False) menu.append(split_item) copy_b = MenuItem(_("_Copy Value(s)"), Icons.EDIT_COPY) copy_b.connect('activate', self.__copy_tag_value, view) qltk.add_fake_accel(copy_b, "c") menu.append(copy_b) remove_b = MenuItem(_("_Remove"), Icons.LIST_REMOVE) remove_b.connect('activate', self.__remove_tag, view) qltk.add_fake_accel(remove_b, "Delete") menu.append(remove_b) menu.show_all() # Setting the menu itself to be insensitive causes it to not # be dismissed; see #473. for c in menu.get_children(): c.set_sensitive(can_change and c.get_property('sensitive')) copy_b.set_sensitive(True) remove_b.set_sensitive(True) menu.connect('selection-done', lambda m: m.destroy()) # XXX: Keep reference self.__menu = menu return view.popup_menu(menu, 3, Gtk.get_current_event_time()) def __tag_select(self, selection, remove): model, rows = selection.get_selected_rows() remove.set_sensitive(bool(rows)) def __add_new_tag(self, model, tag, value): assert isinstance(value, str) iters = [i for (i, v) in model.iterrows() if v.tag == tag] if iters and not self._group_info.can_multiple_values(tag): title = _("Unable to add tag") msg = _("Unable to add %s") % util.bold(tag) msg += "\n\n" msg += _("The files currently" " selected do not support multiple values for %s." ) % util.bold(tag) qltk.ErrorMessage(self, title, msg, escape_desc=False).run() return entry = ListEntry(tag, Comment(value)) entry.edited = True if len(iters): model.insert_after(iters[-1], row=[entry]) else: model.append(row=[entry]) def __add_tag(self, activator, model, library): add = AddTagDialog(self, self._group_info.can_change(), library) while True: resp = add.run() if resp != Gtk.ResponseType.OK: break tag = add.get_tag() value = add.get_value() assert isinstance(value, str) value = massagers.validate(tag, value) assert isinstance(value, str) if not self._group_info.can_change(tag): title = ngettext("Invalid tag", "Invalid tags", 1) msg = ngettext("Invalid tag %s\n\nThe files currently " "selected do not support editing this tag.", "Invalid tags %s\n\nThe files currently " "selected do not support editing these tags.", 1 ) % util.bold(tag) qltk.ErrorMessage(self, title, msg).run() else: self.__add_new_tag(model, tag, value) break add.destroy() def __remove_tag(self, activator, view): model, paths = view.get_selection().get_selected_rows() # Since the iteration can modify path numbers, we need accurate # rows (= iters) before we start. rows = [model[path] for path in paths] for row in rows: entry = row[0] if entry.origvalue is not None: entry.edited = entry.deleted = True model.row_changed(row.path, row.iter) else: model.remove(row.iter) def __copy_tag_value(self, activator, view): model, paths = view.get_selection().get_selected_rows() rows = [model[path] for path in paths] values = [] for row in rows: entry_text = row[0].value.get_shared_text() if entry_text: values.append(entry_text) text = '\n'.join(values) if len(text) > 0: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard.set_text(text, -1) def __save_files(self, save, revert, model, library): updated = {} deleted = {} added = {} renamed = {} for entry in model.values(): if entry.edited and not (entry.deleted or entry.renamed): if entry.origvalue is not None: l = updated.setdefault(entry.tag, []) l.append((entry.value, entry.origvalue)) else: l = added.setdefault(entry.tag, []) l.append(entry.value) if entry.edited and entry.deleted: if entry.origvalue is not None: l = deleted.setdefault(entry.tag, []) l.append(entry.origvalue) if entry.edited and entry.renamed and not entry.deleted: l = renamed.setdefault(entry.tag, []) l.append((entry.origtag, entry.value, entry.origvalue)) was_changed = set() songs = self._group_info.songs win = WritingWindow(self, len(songs)) win.show() all_done = False for song in songs: if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break changed = False for key, values in updated.items(): for (new_value, old_value) in values: if song.can_change(key): if old_value is None: song.add(key, new_value.text) else: song.change(key, old_value.text, new_value.text) changed = True for key, values in added.items(): for value in values: if song.can_change(key): song.add(key, value.text) changed = True for key, values in deleted.items(): for value in values: if not value.shared: # In case it isn't shared we don't know the actual # values to remove. But we know that in that case # we merge all values into one Comment so just removing # everything for that key is OK. song.remove(key, None) changed = True elif key in song: song.remove(key, value.text) changed = True save_rename = [] for new_tag, values in renamed.items(): for old_tag, new_value, old_value in values: if (song.can_change(new_tag) and old_tag in song): if not new_value.is_special(): song.remove(old_tag, old_value.text) save_rename.append((new_tag, new_value)) elif new_value.is_missing(): song.remove(old_tag, old_value) save_rename.append((new_tag, new_value)) else: save_rename.append( (new_tag, Comment(song[old_tag]))) song.remove(old_tag, None) changed = True for tag, value in save_rename: song.add(tag, value.text) if changed: try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True win.destroy() library.changed(was_changed) for b in [save, revert]: b.set_sensitive(not all_done) def __edit_tag(self, renderer, path, new_value, model): #pfps leaving the newline should be OK # new_value = ', '.join(new_value.splitlines()) path = Gtk.TreePath.new_from_string(path) entry = model[path][0] error_dialog = None if not massagers.is_valid(entry.tag, new_value): error_dialog = qltk.WarningMessage( self, _("Invalid value"), _("Invalid value: %(value)s\n\n%(error)s") % { "value": util.bold(new_value), "error": massagers.error_message(entry.tag, new_value)}) else: new_value = massagers.validate(entry.tag, new_value) comment = entry.value changed = comment.text != new_value identical = comment.shared and comment.complete if (changed and (identical or new_value)) \ or (new_value and not identical): # only give an error if we would have applied the value if error_dialog is not None: error_dialog.run() return entry.value = Comment(new_value) entry.edited = True entry.deleted = False model.path_changed(path) def __edit_tag_name(self, renderer, path, new_tag, model): new_tag = ' '.join(new_tag.splitlines()).lower() path = Gtk.TreePath.new_from_string(path) entry = model[path][0] if new_tag == entry.tag: return elif not self._group_info.can_change(new_tag): # Can't add the new tag. title = ngettext("Invalid tag", "Invalid tags", 1) msg = ngettext("Invalid tag %s\n\nThe files currently " "selected do not support editing this tag.", "Invalid tags %s\n\nThe files currently " "selected do not support editing these tags.", 1 ) % util.bold(new_tag) qltk.ErrorMessage(self, title, msg, escape_desc=False).run() else: # FIXME: In case this is a special one we only # validate one value and never write it back.. text = entry.value.text if not massagers.is_valid(new_tag, text): qltk.WarningMessage( self, _("Invalid value"), _("Invalid value: %(value)s\n\n%(error)s") % { "value": util.bold(text), "error": massagers.error_message(new_tag, text)}).run() return text = massagers.validate(new_tag, text) if entry.origvalue is None: # The tag hasn't been saved yet, so we can just update # the name in the model, and the value, since it # may have been re-validated. entry.tag = new_tag entry.value = Comment(text) else: # The tag has been saved, so delete the old tag and # add a new one with the old (or sanitized) value. entry.renamed = entry.edited = True entry.origtag = entry.tag entry.tag = new_tag if not entry.value.is_special(): entry.value = Comment(text) entry.canedit = True model.row_changed(path, model.get_iter(path)) def __button_press(self, view, event): if event.button not in [Gdk.BUTTON_PRIMARY, Gdk.BUTTON_MIDDLE]: return Gdk.EVENT_PROPAGATE x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: return Gdk.EVENT_PROPAGATE if event.button == Gdk.BUTTON_MIDDLE and \ col == view.get_columns()[2]: display = Gdk.DisplayManager.get().get_default_display() selection = Gdk.SELECTION_PRIMARY if sys.platform == "win32": selection = Gdk.SELECTION_CLIPBOARD clipboard = Gtk.Clipboard.get_for_display(display, selection) for rend in col.get_cells(): if rend.get_property('editable'): clipboard.request_text(self.__paste, (rend, path.get_indices()[0])) return Gdk.EVENT_STOP else: return Gdk.EVENT_PROPAGATE else: return Gdk.EVENT_PROPAGATE def _update(self, songs=None): if songs is None: songs = self._group_info.songs else: self._group_info = AudioFileGroup(songs) info = self._group_info keys = list(info.keys()) default_tags = get_default_tags() keys = set(keys + default_tags) def custom_sort(key): try: prio = default_tags.index(key) except ValueError: prio = len(default_tags) return (prio, tagsortkey(key)) if not config.getboolean("editing", "alltags"): keys = filter(lambda k: k not in MACHINE_TAGS, keys) if not config.getboolean("editing", "show_multi_line_tags"): tags = config.getstringlist("editing", "multi_line_tags") keys = filter(lambda k: k not in tags, keys) if not songs: keys = [] with self._view.without_model() as model: model.clear() for tag in sorted(keys, key=custom_sort): canedit = info.can_change(tag) # default tags if tag not in info: entry = ListEntry(tag, Comment(u"")) entry.canedit = canedit model.append(row=[entry]) continue for value in info[tag]: entry = ListEntry(tag, value) entry.origvalue = value entry.edited = False entry.canedit = canedit entry.deleted = False entry.renamed = False entry.origtag = "" model.append(row=[entry]) self._buttonbox.set_sensitive(bool(info.can_change())) self._revert.set_sensitive(False) self._remove.set_sensitive(False) self._save.set_sensitive(False) self._add.set_sensitive(bool(songs)) self._parent.set_pending(None) def __parent_changed(self, parent, songs): self._update(songs) def __value_editing_started(self, render, editable, path, model, library): if not editable.get_completion(): tag = model[path][0].tag completion = LibraryValueCompletion(tag, library) editable.set_completion(completion) if isinstance(editable, Gtk.Entry): comment = model[path][0].value if comment.shared: editable.set_text(comment.text) else: editable.set_text(u"") def __tag_editing_started(self, render, editable, path, model, library): if not editable.get_completion(): tags = self._group_info.can_change() if tags is True: tags = USER_TAGS completion = qltk.EntryCompletion(tags) editable.set_completion(completion) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1659024836.0 quodlibet-4.6.0/quodlibet/qltk/entry.py0000664000175000017500000002124514270532704016673 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2011, 2012 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import math from gi.repository import Gtk, GObject, Gdk, Gio, Pango from quodlibet import _, config from quodlibet.qltk import is_accel, add_fake_accel from quodlibet.qltk.color import mix from quodlibet.qltk.x import SeparatorMenuItem, MenuItem from quodlibet.qltk import Icons class EditableUndo: """A simple undo/redo implementation for gtk widgets that support the gtk.Editable interface""" def set_undo(self, val): if val: self.__enable_undo() else: self.__disable_undo() def reset_undo(self): self.__history = [] self.__re_history = [] self.__in_pos = -1 self.__del_pos = -1 self.__last_space = False def undo(self): self.__do(self.__history, self.__re_history) def redo(self): self.__do(self.__re_history, self.__history) def can_undo(self): return self.__can_do(self.__history) def can_redo(self): return self.__can_do(self.__re_history) def __enable_undo(self): self.reset_undo() self.__handlers = [ self.connect("insert-text", self.__insert_before), self.connect("delete-text", self.__delete_before), self.connect('populate-popup', self.__popup), self.connect('key-press-event', self.__key_press), ] def __key_press(self, entry, event): if is_accel(event, "z"): self.undo() return True elif is_accel(event, "z"): self.redo() return True return False def __disable_undo(self): for handler in self.__handlers: self.disconnect(handler) del self.__history del self.__re_history del self.__last_space del self.__in_pos del self.__del_pos def __popup(self, entry, menu): undo = MenuItem(_("_Undo"), Icons.EDIT_UNDO) add_fake_accel(undo, "z") redo = MenuItem(_("_Redo"), Icons.EDIT_REDO) add_fake_accel(redo, "z") sep = SeparatorMenuItem() for widget in [sep, redo, undo]: widget.show() undo.connect('activate', lambda *x: self.undo()) redo.connect('activate', lambda *x: self.redo()) undo.set_sensitive(self.can_undo()) redo.set_sensitive(self.can_redo()) for item in [sep, redo, undo]: menu.prepend(item) def __all(self): text = self.get_chars(0, -1) pos = self.get_position() return [text, pos] def __add(self): self.__history.append(self.__all()) self.__re_history = [] def __insert_before(self, entry, text, length, position): self.__del_pos = -1 pos = self.get_position() if pos != self.__in_pos or (self.__last_space and text != " ") \ or length > 1: self.__add() self.__last_space = (text == " ") self.__in_pos = pos + 1 def __delete_before(self, entry, start, end): self.__in_pos = -1 text = self.get_chars(start, end) length = end - start pos = self.get_position() if pos != self.__del_pos or (self.__last_space and text != " ") \ or length > 1: self.__add() self.__last_space = (text == " ") self.__del_pos = end - 1 def __inhibit(self): for handler in self.__handlers: self.handler_block(handler) def __uninhibit(self): for handler in self.__handlers: self.handler_unblock(handler) def __can_do(self, source): return bool(source) def __do(self, source, target): if not self.__can_do(source): return self.__del_pos = self.__in_pos = -1 self.__inhibit() now = self.__all() last = source.pop(-1) if now != last: target.append(now) text, pos = last self.delete_text(0, -1) self.insert_text(text, 0) self.set_position(pos) self.__uninhibit() class Entry(Gtk.Entry): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._max_width_chars = -1 # the default is way too much self.set_width_chars(5) def set_max_width_chars(self, value): """Works with GTK+ <3.12""" self._max_width_chars = value self.queue_resize() def do_get_preferred_width(self): minimum, natural = Gtk.Entry.do_get_preferred_width(self) if self._max_width_chars >= 0: # based on gtkentry.c style_context = self.get_style_context() style_context.save() style_context.set_state(Gtk.StateFlags.NORMAL) border = style_context.get_border(style_context.get_state()) padding = style_context.get_padding(style_context.get_state()) style_context.restore() pango_context = self.get_pango_context() metrics = pango_context.get_metrics( pango_context.get_font_description(), pango_context.get_language()) char_width = metrics.get_approximate_char_width() digit_width = metrics.get_approximate_digit_width() char_pixels = int(math.ceil( float(max(char_width, digit_width)) / Pango.SCALE)) space = border.left + border.right + padding.left + padding.right nat_width = self._max_width_chars * char_pixels + space natural = max(nat_width, minimum) return (minimum, natural) class UndoEntry(Entry, EditableUndo): def __init__(self, *args): super().__init__(*args) self.set_undo(True) def set_text(self, *args): super().set_text(*args) self.reset_undo() class ClearEntryMixin: """A clear icon mixin supporting newer Gtk.Entry or a separate clear button as a fallback. """ __gsignals__ = { 'clear': (GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, ()) } def enable_clear_button(self): """Enables the clear icon in the entry""" gicon = Gio.ThemedIcon.new_from_names( ["edit-clear-symbolic", "edit-clear"]) self.set_icon_from_gicon(Gtk.EntryIconPosition.SECONDARY, gicon) self.connect("icon-release", self.__clear) def clear(self): self.__do_clear() def __clear(self, button, *args): self.__do_clear() def __do_clear(self): # TODO: don't change the order.. we connect to clear and remove all # timeouts added for text change in the searchbar self.delete_text(0, -1) self.emit('clear') class ClearEntry(UndoEntry, ClearEntryMixin): __gsignals__ = ClearEntryMixin.__gsignals__ class ValidatingEntryMixin(Gtk.Widget): """An entry with visual feedback as to whether it is valid or not. The given validator function gets a string and returns True (green), False (red), or None (black). """ ALPHA = 1.0 INVALID = Gdk.RGBA(0.85, 0.0, 0.05, ALPHA) VALID = Gdk.RGBA(0.0, 0.65, 0.1, ALPHA) def set_validate(self, validator=None): if validator: self.connect('changed', self._set_color, validator) def _default_color(self) -> Gdk.RGBA: # Don't use our *own* context here if possible else it changes as we mutate... # Don't cache, as theme switching is async parent = self.get_parent() ctx = parent.get_style_context() if parent else self.get_style_context() col = ctx.get_color(Gtk.StateType.NORMAL) return col def _set_color(self, _widget, validator): value = validator(self.get_text()) default = self._default_color() amount = config.getfloat("settings", "validator_colorise") if value is True: color = mix(default, self.VALID, amount) elif value is False: color = mix(default, self.INVALID, amount) else: color = Gdk.RGBA(default.red, default.green, default.blue, self.ALPHA) if color and self.get_property('sensitive'): self.override_color(Gtk.StateType.NORMAL, color) else: self.override_color(Gtk.StateType.NORMAL, None) class ValidatingEntry(ClearEntry, ValidatingEntryMixin): def __init__(self, validator=None, *args): super().__init__(*args) self.set_validate(validator) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658776081.0 quodlibet-4.6.0/quodlibet/qltk/exfalsowindow.py0000644000175000017500000002232114267565021020421 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk, GObject, Pango from senf import fsnative from quodlibet import ngettext, _ from quodlibet import config from quodlibet import formats from quodlibet import qltk from quodlibet import app from quodlibet.qltk.appwindow import AppWindow from quodlibet.formats import AudioFileError from quodlibet.plugins import PluginManager from quodlibet.qltk.delete import trash_files, TrashMenuItem from quodlibet.qltk.edittags import EditTags from quodlibet.qltk.filesel import MainFileSelector from quodlibet.qltk.pluginwin import PluginWindow from quodlibet.qltk.renamefiles import RenameFiles from quodlibet.qltk.tagsfrompath import TagsFromPath from quodlibet.qltk.tracknumbers import TrackNumbers from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.about import AboutDialog from quodlibet.qltk.songsmenu import SongsMenuPluginHandler from quodlibet.qltk.x import Align, SeparatorMenuItem, ConfigRHPaned, \ SymbolicIconImage, MenuItem from quodlibet.qltk.window import PersistentWindowMixin, Window from quodlibet.qltk.msg import CancelRevertSave from quodlibet.qltk.prefs import PreferencesWindow as QLPreferencesWindow from quodlibet.qltk import Icons from quodlibet.util.i18n import numeric_phrase from quodlibet.util.path import mtime, normalize_path from quodlibet.util import connect_obj, connect_destroy, format_int_locale from quodlibet.update import UpdateDialog class ExFalsoWindow(Window, PersistentWindowMixin, AppWindow): __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), } pm = SongsMenuPluginHandler() @classmethod def init_plugins(cls): PluginManager.instance.register_handler(cls.pm) def __init__(self, library, dir=None): super().__init__(dialog=False) self.set_title("Ex Falso") self.set_default_size(750, 475) self.enable_window_tracking("exfalso") self.__library = library hp = ConfigRHPaned("memory", "exfalso_paned_position", 1.0) hp.set_border_width(0) hp.set_position(250) hp.show() self.add(hp) vb = Gtk.VBox() bbox = Gtk.HBox(spacing=6) def prefs_cb(*args): window = PreferencesWindow(self) window.show() def plugin_window_cb(*args): window = PluginWindow(self) window.show() def about_cb(*args): about = AboutDialog(self, app) about.run() about.destroy() def update_cb(*args): d = UpdateDialog(self) d.run() d.destroy() menu = Gtk.Menu() about_item = MenuItem(_("_About"), Icons.HELP_ABOUT) about_item.connect("activate", about_cb) menu.append(about_item) check_item = MenuItem(_("_Check for Updates…"), Icons.NETWORK_SERVER) check_item.connect("activate", update_cb) menu.append(check_item) menu.append(SeparatorMenuItem()) plugin_item = MenuItem(_("_Plugins"), Icons.SYSTEM_RUN) plugin_item.connect("activate", plugin_window_cb) menu.append(plugin_item) pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) pref_item.connect("activate", prefs_cb) menu.append(pref_item) menu.show_all() menu_button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.BUTTON), arrow=True, down=False) menu_button.set_menu(menu) bbox.pack_start(menu_button, False, True, 0) l = Gtk.Label() l.set_alignment(1.0, 0.5) l.set_ellipsize(Pango.EllipsizeMode.END) bbox.pack_start(l, True, True, 0) self._fs = fs = MainFileSelector() vb.pack_start(fs, True, True, 0) vb.pack_start(Align(bbox, border=6), False, True, 0) vb.show_all() hp.pack1(vb, resize=True, shrink=False) nb = qltk.Notebook() nb.props.scrollable = True nb.show() for Page in [EditTags, TagsFromPath, RenameFiles, TrackNumbers]: page = Page(self, self.__library) page.show() nb.append_page(page) hp.pack2(nb, resize=True, shrink=False) fs.connect('changed', self.__changed, l) if dir: fs.go_to(dir) connect_destroy(self.__library, 'changed', self.__library_changed, fs) self.__save = None connect_obj(self, 'changed', self.set_pending, None) for c in fs.get_children(): c.get_child().connect('button-press-event', self.__pre_selection_changed, fs, nb) c.get_child().connect('focus', self.__pre_selection_changed, fs, nb) fs.get_children()[1].get_child().connect('popup-menu', self.__popup_menu, fs) self.emit('changed', []) self.get_child().show() self.__ag = Gtk.AccelGroup() key, mod = Gtk.accelerator_parse("Q") self.__ag.connect(key, mod, 0, lambda *x: self.destroy()) self.add_accel_group(self.__ag) # GtkosxApplication assumes the menu bar is mapped, so add # it but don't show it. self._dummy_osx_menu_bar = Gtk.MenuBar() vb.pack_start(self._dummy_osx_menu_bar, False, False, 0) def __library_changed(self, library, songs, fs): fs.rescan() def set_as_osx_window(self, osx_app): osx_app.set_menu_bar(self._dummy_osx_menu_bar) def get_is_persistent(self): return False def open_file(self, filename): assert isinstance(filename, fsnative) if not os.path.isdir(filename): return False self._fs.go_to(filename) def set_pending(self, button, *excess): self.__save = button def __pre_selection_changed(self, view, event, fs, nb): if self.__save: resp = CancelRevertSave(self).run() if resp == Gtk.ResponseType.YES: self.__save.clicked() elif resp == Gtk.ResponseType.NO: fs.rescan() else: nb.grab_focus() return True # cancel or closed def __popup_menu(self, view, fs): # get all songs for the selection filenames = [normalize_path(f, canonicalise=True) for f in fs.get_selected_paths()] maybe_songs = [self.__library.get(f) for f in filenames] songs = [s for s in maybe_songs if s] if songs: menu = self.pm.Menu(self.__library, songs) if menu is None: menu = Gtk.Menu() else: menu.prepend(SeparatorMenuItem()) else: menu = Gtk.Menu() b = TrashMenuItem() b.connect('activate', self.__delete, filenames, fs) menu.prepend(b) def selection_done_cb(menu): menu.destroy() menu.connect('selection-done', selection_done_cb) menu.show_all() return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __delete(self, item, paths, fs): trash_files(self, paths) fs.rescan() def __changed(self, selector, selection, label): model, rows = selection.get_selected_rows() files = [] if len(rows) < 2: count = len(model or []) else: count = len(rows) label.set_text(numeric_phrase("%d song", "%d songs", count)) for row in rows: filename = model[row][0] if not os.path.exists(filename): pass elif filename in self.__library: song = self.__library[filename] if song("~#mtime") + 1. < mtime(filename): try: song.reload() except AudioFileError: pass files.append(song) else: files.append(formats.MusicFile(filename)) files = list(filter(None, files)) if len(files) == 0: self.set_title("Ex Falso") elif len(files) == 1: self.set_title("%s - Ex Falso" % files[0].comma("title")) else: params = ({'title': files[0].comma("title"), 'count': format_int_locale(len(files) - 1)}) self.set_title( "%s - Ex Falso" % (ngettext("%(title)s and %(count)s more", "%(title)s and %(count)s more", len(files) - 1) % params)) self.__library.add(files) self.emit('changed', files) class PreferencesWindow(QLPreferencesWindow): def __init__(self, parent): if self.is_not_unique(): return super().__init__(parent, all_pages=False) # Seems nicer when there's only one page self.set_resizable(True) self.set_title(_("Ex Falso Preferences")) self.get_child().show_all() def __destroy(self): config.save() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1667140131.0 quodlibet-4.6.0/quodlibet/qltk/filesel.py0000644000175000017500000005354714327505043017164 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. import os import errno from urllib.parse import urlsplit from gi.repository import Gtk, GObject, Gdk, Gio, Pango from senf import uri2fsn, fsnative, fsn2text, bytes2fsn from quodlibet import formats, print_d, util from quodlibet import qltk from quodlibet import _ from quodlibet.util import windows from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.views import AllTreeView, RCMHintedTreeView, \ MultiDragTreeView from quodlibet.qltk.views import TreeViewColumn from quodlibet.qltk.x import ScrolledWindow, Paned from quodlibet.qltk.models import ObjectStore, ObjectTreeStore from quodlibet.qltk import Icons from quodlibet.util.path import listdir, \ xdg_get_user_dirs, get_home_dir, xdg_get_config_home from quodlibet.util import connect_obj def search_func(model, column, key, iter_, handledirs): check = model.get_value(iter_, 0) if check is None: return True elif not handledirs or os.sep not in key: check = os.path.basename(check) or os.sep return key not in check.lower() and key not in check def is_image(filename): IMAGES = [".jpg", ".png", ".jpeg"] for ext in IMAGES: if filename.lower().endswith(ext): return True return False def filesel_filter(filename): if formats.filter(filename): return True else: return is_image(filename) def _get_win_favorites(): """Returns a list of paths for commonly used directories. e.g. My Music, Desktop etc. """ assert os.name == "nt" folders = [] funcs = [windows.get_desktop_dir, windows.get_personal_dir, windows.get_music_dir] for func in funcs: path = func() if path is not None: folders.append(path) # try to extract the favorites listed in explorer and add them # if not already present links = windows.get_links_dir() if links is not None: try: link_entries = os.listdir(links) except OSError: link_entries = [] for entry in link_entries: if entry.endswith(".lnk"): try: target = windows.get_link_target( os.path.join(links, entry)) except WindowsError: pass else: if target: # RecentPlaces.lnk resolves # to an empty string for example folders.append(target) # remove duplicated entries filtered = [] for path in folders: if path not in filtered: filtered.append(path) return filtered def get_favorites(): """A list of paths of commonly used folders (Desktop,..) Paths don't have to exist. """ if os.name == "nt": return _get_win_favorites() else: paths = [get_home_dir()] xfg_user_dirs = xdg_get_user_dirs() for key in ["XDG_DESKTOP_DIR", "XDG_DOWNLOAD_DIR", "XDG_MUSIC_DIR"]: if key in xfg_user_dirs: path = xfg_user_dirs[key] if path not in paths: paths.append(path) return paths def get_drives(): """A list of accessible drives""" paths = [] for mount in Gio.VolumeMonitor.get().get_mounts(): path = mount.get_root().get_path() if path is not None: paths.append(path) if os.name != "nt": paths.append("/") return sorted(paths) def parse_gtk_bookmarks(data): """ Args: data (bytes) Retruns: List[fsnative] Raises: ValueError """ assert isinstance(data, bytes) paths = [] for line in data.splitlines(): parts = line.split() if not parts: continue folder_url = parts[0] paths.append(bytes2fsn(urlsplit(folder_url)[2], "utf-8")) return paths def get_gtk_bookmarks(): """A list of paths from the GTK+ bookmarks. The paths don't have to exist. Returns: List[fsnative] """ if os.name == "nt": return [] path = os.path.join(xdg_get_config_home(), "gtk-3.0", "bookmarks") folders = [] try: with open(path, "rb") as f: folders = parse_gtk_bookmarks(f.read()) except (EnvironmentError, ValueError): pass return folders class DirectoryTree(RCMHintedTreeView, MultiDragTreeView): """A tree view showing multiple folder hierarchies""" def __init__(self, initial=None, folders=None): """ initial -- the path to select/scroll to folders -- a list of paths to show in the tree view, None will result in a separator. """ model = ObjectTreeStore() super().__init__(model=model) if initial is not None: assert isinstance(initial, fsnative) column = TreeViewColumn(title=_("Folders")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) render = Gtk.CellRendererPixbuf() render.set_property('icon-name', Icons.FOLDER) render.props.xpad = 3 column.pack_start(render, False) render = Gtk.CellRendererText() if self.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(render, True) def cell_data(column, cell, model, iter_, userdata): value = model.get_value(iter_) if value is not None: text = fsn2text(os.path.basename(value) or value) cell.set_property('text', text) column.set_cell_data_func(render, cell_data) self.append_column(column) self.set_search_equal_func(search_func, True) self.set_search_column(0) if folders is None: folders = [] for path in folders: niter = model.append(None, [path]) if path is not None: assert isinstance(path, fsnative) model.append(niter, [fsnative(u"dummy")]) self.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.connect( 'test-expand-row', DirectoryTree.__expanded, model) self.set_row_separator_func( lambda model, iter_, data: model.get_value(iter_) is None, None) if initial: self.go_to(initial) menu = self._create_menu() connect_obj(self, 'popup-menu', self._popup_menu, menu) # Allow to drag and drop files from outside targets = [ ("text/uri-list", 0, 42) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) self.connect('drag-data-received', self.__drag_data_received) def _create_menu(self): menu = Gtk.Menu() m = qltk.MenuItem(_(u"_New Folder…"), Icons.DOCUMENT_NEW) m.connect('activate', self.__mkdir) menu.append(m) m = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE) m.connect('activate', self.__rmdir) menu.append(m) m = qltk.MenuItem(_("_Refresh"), Icons.VIEW_REFRESH) m.connect('activate', self.__refresh) menu.append(m) m = qltk.MenuItem(_("_Select all Sub-Folders"), Icons.FOLDER) m.connect('activate', self.__expand) menu.append(m) menu.show_all() return menu def get_selected_paths(self): """A list of fs paths""" selection = self.get_selection() model, paths = selection.get_selected_rows() return [model[p][0] for p in paths] def go_to(self, path_to_go): assert isinstance(path_to_go, fsnative) # The path should be normalized in normal situations. # On some systems and special environments (pipenv) there might be # a non-normalized path at least during tests, though. path_to_go = os.path.normpath(path_to_go) model = self.get_model() # Find the top level row which has the largest common # path with the path we want to go to roots = dict((p, i) for (i, p) in model.iterrows(None)) head, tail = path_to_go, fsnative(u"") to_find = [] while head and head not in roots: new_head, tail = os.path.split(head) # this can happen for invalid paths on Windows if head == new_head: break head = new_head to_find.append(tail) if head not in roots: return start_iter = roots[head] # expand until we find the right directory or the last valid one # and select/scroll to it def search(view, model, iter_, to_find): tree_path = model.get_path(iter_) # we are where we want, select and scroll if not to_find: view.set_cursor(tree_path) view.scroll_to_cell(tree_path) return # expand the row view.expand_row(tree_path, False) next_ = to_find.pop(-1) for sub_iter, path in model.iterrows(iter_): if os.path.basename(path) == next_: search(view, model, sub_iter, to_find) break else: # we haven't found the right sub folder, select the parent # and stop search(view, model, iter_, []) search(self, model, start_iter, to_find) def __drag_data_received(self, widget, drag_ctx, x, y, data, info, time): if info == 42: uris = data.get_uris() if uris: try: filename = uri2fsn(uris[0]) except ValueError: pass else: self.go_to(filename) Gtk.drag_finish(drag_ctx, True, False, time) return Gtk.drag_finish(drag_ctx, False, False, time) def _popup_menu(self, menu): model, paths = self.get_selection().get_selected_rows() directories = [model[path][0] for path in paths] menu_items = menu.get_children() delete = menu_items[1] try: is_empty = not any(len(os.listdir(d)) for d in directories) delete.set_sensitive(is_empty) except OSError as err: if err.errno == errno.ENOENT: model.remove(model.get_iter(paths[0])) return False new_folder = menu_items[0] new_folder.set_sensitive(len(paths) == 1) selection = self.get_selection() selection.unselect_all() for path in paths: selection.select_path(path) return self.popup_menu(menu, 0, Gtk.get_current_event_time()) def __mkdir(self, button): model, paths = self.get_selection().get_selected_rows() if len(paths) != 1: return path = paths[0] directory = model[path][0] dir_ = GetStringDialog( None, _("New Folder"), _("Enter a name for the new folder:")).run() if not dir_: return fullpath = os.path.realpath(os.path.join(directory, dir_)) try: os.makedirs(fullpath) except EnvironmentError as err: error = f"{util.bold(err.filename)}: {util.escape(err.strerror)}" qltk.ErrorMessage( None, _("Unable to create folder"), error, escape_desc=False).run() return self.emit('test-expand-row', model.get_iter(path), path) self.expand_row(path, False) def __rmdir(self, button): model, paths = self.get_selection().get_selected_rows() directories = [model[path][0] for path in paths] print_d("Deleting %d empty directories" % len(directories)) for directory in directories: try: os.rmdir(directory) except EnvironmentError as err: error = f"{util.bold(err.filename)}: {err.strerror}" qltk.ErrorMessage( None, _("Unable to delete folder"), error, escape_desc=False).run() return ppath = Gtk.TreePath(paths[0][:-1]) expanded = self.row_expanded(ppath) self.emit('test-expand-row', model.get_iter(ppath), ppath) if expanded: self.expand_row(ppath, False) def __expand(self, button): selection = self.get_selection() model, paths = selection.get_selected_rows() for path in paths: iter_ = model.get_iter(path) self.expand_row(path, False) last = self.__select_children(iter_, model, selection) selection.select_range(path, last) def __select_children(self, iter_, model, selection): nchildren = model.iter_n_children(iter_) last = model.get_path(iter_) for i in range(nchildren): child = model.iter_nth_child(iter_, i) self.expand_row(model.get_path(child), False) last = self.__select_children(child, model, selection) return last def __refresh(self, button): model, rows = self.get_selection().get_selected_rows() expanded = set() self.map_expanded_rows( lambda s, iter, data: expanded.add(model[iter][0]), None) needs_expanding = [] for row in rows: if self.row_expanded(row): self.emit('test-expand-row', model.get_iter(row), row) self.expand_row(row, False) needs_expanding.append(row) while len(needs_expanding) > 0: child = model.iter_children(model.get_iter(needs_expanding.pop())) while child is not None: if model[child][0] in expanded: path = model.get_path(child) self.emit('test-expand-row', child, path) self.expand_row(path, False) needs_expanding.append(path) child = model.iter_next(child) def __expanded(self, iter, path, model): window = self.get_window() if window: window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) Gtk.main_iteration_do(False) try: try: if model is None: return while model.iter_has_child(iter): model.remove(model.iter_children(iter)) folder = model[iter][0] for path in listdir(folder): try: if not os.path.isdir(path): continue for filename in listdir(path): if os.path.isdir(filename): niter = model.append(iter, [path]) model.append(niter, ["dummy"]) break else: model.append(iter, [path]) except OSError: pass if not model.iter_has_child(iter): return True except OSError: pass finally: if window: window.set_cursor(None) class FileSelector(Paned): """A file selector widget consisting of a folder tree and a file list below. """ __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (Gtk.TreeSelection,)) } def __init__(self, initial=None, filter=filesel_filter, folders=None): """ initial -- a path to a file which should be shown initially filter -- a function which filters paths shown in the file list folders -- list of shown folders in the directory tree """ super().__init__( orientation=Gtk.Orientation.VERTICAL) self.__filter = filter if initial is not None: assert isinstance(initial, fsnative) if initial and os.path.isfile(initial): initial = os.path.dirname(initial) dirlist = DirectoryTree(initial, folders=folders) model = ObjectStore() filelist = AllTreeView(model=model) filelist.connect("draw", self.__restore_scroll_pos_on_draw) column = TreeViewColumn(title=_("Songs")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) render = Gtk.CellRendererPixbuf() render.props.xpad = 3 def cell_icon(column, cell, model, iter_, userdata): value = model.get_value(iter_) if is_image(value): cell.set_property('icon-name', Icons.IMAGE_X_GENERIC) else: cell.set_property('icon-name', Icons.AUDIO_X_GENERIC) column.set_cell_data_func(render, cell_icon) column.pack_start(render, False) render = Gtk.CellRendererText() if filelist.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(render, True) def cell_data(column, cell, model, iter_, userdata): value = model.get_value(iter_) cell.set_property('text', fsn2text(os.path.basename(value))) column.set_cell_data_func(render, cell_data) filelist.append_column(column) filelist.set_rules_hint(True) filelist.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) filelist.set_search_equal_func(search_func, False) filelist.set_search_column(0) self.__sig = filelist.get_selection().connect( 'changed', self.__changed) dirlist.get_selection().connect( 'changed', self.__dir_selection_changed, filelist) dirlist.get_selection().emit('changed') def select_all_files(view, path, col, fileselection): view.expand_row(path, False) fileselection.select_all() dirlist.connect('row-activated', select_all_files, filelist.get_selection()) sw = ScrolledWindow() sw.add(dirlist) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) self.pack1(sw, resize=True) sw = ScrolledWindow() sw.add(filelist) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) self.pack2(sw, resize=True) def go_to(self, *args, **kwargs): dirlist = self.get_child1().get_child() dirlist.go_to(*args, **kwargs) def get_selected_paths(self): """A list of fs paths""" filelist = self.get_child2().get_child() selection = filelist.get_selection() model, paths = selection.get_selected_rows() return [model[p][0] for p in paths] def rescan(self): """Refill the file list for the current directory selection""" dirlist = self.get_child1().get_child() filelist = self.get_child2().get_child() dir_selection = dirlist.get_selection() self.__dir_selection_changed(dir_selection, filelist) def __changed(self, selection): # forward file list selection changed signals self.emit('changed', selection) def __dir_selection_changed(self, selection, filelist): # dir selection changed, refill the file list fselect = filelist.get_selection() fselect.handler_block(self.__sig) fmodel, frows = fselect.get_selected_rows() selected = [fmodel[row][0] for row in frows] fmodel = filelist.get_model() fmodel.clear() dmodel, rows = selection.get_selected_rows() dirs = [dmodel[row][0] for row in rows] for dir_ in dirs: try: files = filter(self.__filter, listdir(dir_)) for file_ in sorted(files): filename = os.path.join(dir_, file_) if (os.access(filename, os.R_OK) and not os.path.isdir(filename)): fmodel.append([filename]) except OSError: pass for iter_, filename in fmodel.iterrows(): if filename in selected: fselect.select_iter(iter_) fselect.handler_unblock(self.__sig) fselect.emit('changed') self._saved_scroll_pos = filelist.get_vadjustment().get_value() def __restore_scroll_pos_on_draw(self, treeview, context): if self._saved_scroll_pos: vadj = treeview.get_vadjustment() vadj.set_value(self._saved_scroll_pos) self._saved_scroll_pos = None def _get_main_folders(): def filter_exists(paths): return [p for p in paths if os.path.isdir(p)] folders = [] favs = filter_exists(get_favorites()) if favs: folders += favs drives = filter_exists(get_drives()) if folders and drives: folders += [None] if drives: folders += drives bookmarks = filter_exists(get_gtk_bookmarks()) if folders and bookmarks: folders += [None] if bookmarks: folders += bookmarks return folders class MainFileSelector(FileSelector): """The main file selector used in EF. Shows a useful list of directories in the directory tree. """ def __init__(self, initial=None): folders = _get_main_folders() super().__init__( initial, filesel_filter, folders=folders) class MainDirectoryTree(DirectoryTree): """The main directory tree used in QL. Shows a useful list of directories. """ def __init__(self, initial=None, folders=None): if folders is None: folders = [] main = _get_main_folders() if folders and main: folders += [None] if main: folders += main super().__init__( initial=initial, folders=folders) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/quodlibet/qltk/getstring.py0000664000175000017500000000532014035600052017523 0ustar00nicknick# Copyright 2005 Joe Wreschnig, Michael Urman # 2013, 2015 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk from quodlibet import _ from quodlibet.qltk.window import Dialog from quodlibet.qltk import Icons from quodlibet.qltk.entry import UndoEntry class GetStringDialog(Dialog): """Simple dialog to return a string from the user""" def __init__(self, parent, title, text, button_label=_("_OK"), button_icon=Icons.DOCUMENT_OPEN, tooltip=None): super().__init__( title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_resizable(True) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(button_label, button_icon, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() if tooltip: self._val.set_tooltip_text(tooltip) self._val.set_max_width_chars(50) box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all() def _verify_clipboard(self, text): """Return an altered text or None if the content was invalid.""" return def run(self, text="", clipboard=False, test=False): """Shows the dialog and returns the entered value. If clipboard is set, the initial value will be pulled from the clipboard and can be verified/altered by _verify_clipboard. In case the verification fails text will be used as fallback""" self.show() if clipboard: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clip = clipboard.wait_for_text() if clip is not None: clip = self._verify_clipboard(clip) if clip is not None: text = clip self._val.set_text(text) self._val.set_activates_default(True) self._val.grab_focus() resp = Gtk.ResponseType.OK if not test: resp = super().run() if resp == Gtk.ResponseType.OK: value = self._val.get_text() else: value = None self.destroy() return value ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1666295006.0 quodlibet-4.6.0/quodlibet/qltk/icons.py0000644000175000017500000001115114324322336016634 0ustar00nicknick# Copyright 2014 Christoph Reiter # 2016 Nick Boultbee # 2020 Daniel Petrescu # # 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 2 of the License, or # (at your option) any later version. """A list of icon names. Mainly to see which ones we define and for looking up the standardized ones. Also reduces the chance of making a typo. http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html https://docs.google.com/spreadsheet/pub? key=0AsPAM3pPwxagdGF4THNMMUpjUW5xMXZfdUNzMXhEa2c """ from quodlibet.util.enum import enum @enum class Icons(str): NONE = "" # these we have in our fallback icon theme QUODLIBET = "io.github.quodlibet.QuodLibet" EXFALSO = "exfalso" QUODLIBET_MISSING_COVER = "quodlibet-missing-cover" # stock icon I couldn't think of a replacement for now EDIT = "gtk-edit" # these only come from an icon theme APPLICATION_EXIT = "application-exit" # "_Quit" APPLICATION_INTERNET = "applications-internet" APPLICATION_UTILITIES = "applications-utilities" APPOINTMENT_NEW = "appointment-new" AUDIO_CARD = "audio-card" AUDIO_INPUT_MICROPHONE = "audio-input-microphone" AUDIO_VOLUME_MUTED = "audio-volume-muted" AUDIO_X_GENERIC = "audio-x-generic" CHANGES_PREVENT = "changes-prevent" DIALOG_ERROR = "dialog-error" # "Error" DIALOG_INFORMATION = "dialog-information" # "Information" DIALOG_PASSWORD = "dialog-password" DIALOG_QUESTION = "dialog-question" # "Question" DIALOG_WARNING = "dialog-warning" # "Warning" DOCUMENT_NEW = "document-new" # "_New" DOCUMENT_OPEN = "document-open" # "_Open" DOCUMENT_PROPERTIES = "document-properties" # "_Properties" DOCUMENT_REVERT = "document-revert" # "_Revert" DOCUMENT_SAVE = "document-save" # "_Save" DOCUMENT_SAVE_AS = "document-save-as" # "_Save" DOCUMENT_SEND = "document-send" DRIVE_REMOVABLE_MEDIA = "drive-removable-media" EDIT_CLEAR = "edit-clear" # "_Clear" EDIT_COPY = "edit-copy" # "_Copy" EDIT_PASTE = "edit-paste" # "_Paste" EDIT_DELETE = "edit-delete" # "_Delete" EDIT_FIND = "edit-find" # "_Find" EDIT_FIND_REPLACE = "edit-find-replace" # "Find and _Replace" EDIT_REDO = "edit-redo" # "_Redo" EDIT_SELECT_ALL = "edit-select-all" EDIT_UNDO = "edit-undo" # "_Undo" EMBLEM_DOWNLOADS = "emblem-downloads" EMBLEM_SHARED = "emblem-shared" EMBLEM_SYSTEM = "emblem-system" FACE_SMILE = "face-smile" FAVORITE = "emblem-favorite" FOLDER = "folder" FOLDER_DRAG_ACCEPT = "folder-drag-accept" FOLDER_OPEN = "folder-open" FORMAT_JUSTIFY_FILL = "format-justify-fill" GO_JUMP = "go-jump" # "_Jump to" HELP_ABOUT = "help-about" # "_About" HELP_BROWSER = "help-browser" # "_Help" IMAGE_X_GENERIC = "image-x-generic" INSERT_IMAGE = "insert-image" INSERT_TEXT = "insert-text" LIST_ADD = "list-add" # "_Add" LIST_EDIT = "document-edit" # "_Edit" LIST_REMOVE = "list-remove" # "_Remove" MEDIA_EJECT = "media-eject" MEDIA_OPTICAL = "media-optical" # "_CD-ROM" MEDIA_PLAYBACK_PAUSE = "media-playback-pause" # "P_ause" MEDIA_PLAYBACK_START = "media-playback-start" # "_Play" MEDIA_PLAYBACK_STOP = "media-playback-stop" # "_Stop" MEDIA_PLAYLIST_REPEAT = "media-playlist-repeat" MEDIA_PLAYLIST_SHUFFLE = "media-playlist-shuffle" MEDIA_RECORD = "media-record" MEDIA_SKIP_BACKWARD = "media-skip-backward" # "Pre_vious" MEDIA_SKIP_FORWARD = "media-skip-forward" # "_Next" MULTIMEDIA_PLAYER = "multimedia-player" MULTIMEDIA_VOLUME_CONTROL = "multimedia-volume-control" NETWORK_WORKGROUP = "network-workgroup" # "_Network" NETWORK_SERVER = "network-server" NETWORK_TRANSMIT = "network-transmit" PREFERENCES_SYSTEM = "preferences-system" # "_Preferences" PREFERENCES_DESKTOP_SCREENSAVER = "preferences-desktop-screensaver" PREFERENCES_DESKTOP_THEME = "preferences-desktop-theme" PROCESS_STOP = "process-stop" # "_Stop" SYSTEM_LOCK_SCREEN = "system-lock-screen" SYSTEM_RUN = "system-run" # "_Execute" SYSTEM_SEARCH = "system-search" TEXT_HTML = "text-html" TOOLS_CHECK_SPELLING = "tools-check-spelling" # "_Spell Check" USER_BOOKMARKS = "user-bookmarks" # Looks like a rating USER_DESKTOP = "user-desktop" USER_TRASH = "user-trash" # "Trash" UTILITIES_TERMINAL = "utilities-terminal" VIEW_LIST = "view-list" # VIEW_REFRESH = "view-refresh" # "_Refresh" WINDOW_CLOSE = "window-close" # "_Close" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1661154814.0 quodlibet-4.6.0/quodlibet/qltk/image.py0000644000175000017500000001270314300632776016615 0ustar00nicknick# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Some helper function for loading and converting image data.""" import math from typing import Optional from gi.repository import GdkPixbuf, Gtk, Gdk, GLib import cairo def get_surface_for_pixbuf(widget: Gtk.Widget, pixbuf: Optional[GdkPixbuf.Pixbuf])\ -> Optional[cairo.Surface]: """:returns: a cairo surface, if possible""" if not pixbuf: return None scale_factor = widget.get_scale_factor() return Gdk.cairo_surface_create_from_pixbuf( pixbuf, scale_factor, widget.get_window()) def get_surface_extents(surface): """Gives (x, y, width, height) for a surface, scale independent""" ctx = cairo.Context(surface) x1, y1, x2, y2 = ctx.clip_extents() x1 = int(math.floor(x1)) y1 = int(math.floor(y1)) x2 = int(math.ceil(x2)) y2 = int(math.ceil(y2)) x2 -= x1 y2 -= y1 return (x1, y1, x2, y2) def get_border_radius(_widgets=[]): """Returns the border radius commonly used in the current theme. If there are no rounded corners 0 will be returned. """ if not _widgets: b = Gtk.Button() b.show() e = Gtk.Entry() e.show() _widgets += [b, e] radii = [] for widget in _widgets: style_context = widget.get_style_context() radii.append(style_context.get_property( Gtk.STYLE_PROPERTY_BORDER_RADIUS, style_context.get_state())) radius = max(radii) # Doesn't work on the default Ubuntu theme. # Not sure why, so fix manually for now theme_name = Gtk.Settings.get_default().props.gtk_theme_name if theme_name in ("Ambiance", "Radiance"): radius = int(radius / 1.5) return radius def add_border(pixbuf, color, width=1, radius=0): """Add a border to the pixbuf and round of the edges. color is a Gdk.RGBA The resulting pixbuf will be width * 2px higher and wider. Can not fail. """ pi = math.pi def new_border_path(ctx, w, h, r, margin=0): d = r + margin ctx.new_path() ctx.arc(w - d, d, r, -pi / 2, 0) ctx.arc(w - d, h - d, r, 0, pi / 2) ctx.arc(d, h - d, r, pi / 2, pi) ctx.arc(d, d, r, pi, pi * 3 / 2) ctx.close_path() w = pixbuf.get_width() + width * 2 h = pixbuf.get_height() + width * 2 r = min(radius, min(w, h) / 2) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) ctx = cairo.Context(surface) new_border_path(ctx, w, h, r + width) ctx.clip() ctx.set_source_rgba(color.red, color.green, color.blue, color.alpha) ctx.paint() new_border_path(ctx, w, h, r, width) Gdk.cairo_set_source_pixbuf(ctx, pixbuf, width, width) ctx.fill() return Gdk.pixbuf_get_from_surface(surface, 0, 0, w, h) def add_border_widget(pixbuf, widget): """Like add_border() but uses the widget to get a border color and a border width. """ context = widget.get_style_context() color = context.get_color(context.get_state()) color.alpha *= 0.1 scale_factor = widget.get_scale_factor() border_radius = get_border_radius() * scale_factor return add_border(pixbuf, color, width=scale_factor, radius=border_radius) def scale(pixbuf, boundary, scale_up=True, force_copy=False): """Scale a pixbuf so it fits into the boundary. (preserves image aspect ratio) If `scale_up` is True, the resulting pixbuf can be larger than the original one. If `force_copy` is False the resulting pixbuf might be the passed one. Can not fail. """ size = pixbuf.get_width(), pixbuf.get_height() scale_w, scale_h = calc_scale_size(boundary, size, scale_up) if (scale_w, scale_h) == size: if force_copy: return pixbuf.copy() return pixbuf return pixbuf.scale_simple(scale_w, scale_h, GdkPixbuf.InterpType.BILINEAR) def calc_scale_size(boundary, size, scale_up=True): """Returns the biggest possible size to fit into the boundary, respecting the aspect ratio. If `scale_up` is True the result can be larger than size. All sizes have to be > 0. """ bwidth, bheight = boundary iwidth, iheight = size if bwidth <= 0 or bheight <= 0 or iwidth <= 0 or iheight <= 0: raise ValueError scale_w, scale_h = iwidth, iheight if iwidth > bwidth or iheight > bheight or scale_up: bratio = float(bwidth) / bheight iratio = float(iwidth) / iheight if iratio > bratio: scale_w = bwidth scale_h = int(bwidth / iratio) else: scale_w = int(bheight * iratio) scale_h = bheight return scale_w, scale_h def pixbuf_from_file(fileobj, boundary, scale_factor=1): """Returns a pixbuf with the maximum size defined by boundary. Can raise GLib.GError and return None """ try: pixbuf = GdkPixbuf.Pixbuf.new_from_file(fileobj.name) except GLib.GError: try: loader = GdkPixbuf.PixbufLoader() loader.write(fileobj.read()) loader.close() fileobj.seek(0, 0) pixbuf = loader.get_pixbuf() except EnvironmentError: return w, h = boundary w *= scale_factor h *= scale_factor return scale(pixbuf, (w, h), scale_up=True) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1645050081.0 quodlibet-4.6.0/quodlibet/qltk/info.py0000664000175000017500000001362614203274341016465 0ustar00nicknick# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2011-2020 Nick Boultbee # 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk, Gdk, Pango from quodlibet import _ from quodlibet import print_w from quodlibet import qltk from quodlibet.player._base import BasePlayer from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.x import SeparatorMenuItem, Align from quodlibet.qltk import Icons from quodlibet.util import connect_destroy from quodlibet.pattern import XMLFromMarkupPattern from quodlibet.qltk.textedit import PatternEdit class SongInfo(Gtk.EventBox): """A widget for showing information about the currently playing song. Provides a way to change the display pattern for formatting the song information and a song context menu. """ _pattern = (u"""\ [span weight='bold' size='large'][/span]\ <~length| (<~length>)><version| [small][b]<version>[/b][/small]><~people| %(people)s><album| [b]<album>[/b]<discnumber| - %(disc)s>\ <discsubtitle| - [b]<discsubtitle>[/b]><tracknumber| - %(track)s>>""" % { # Translators: As in "by Artist Name" "people": _("by %s") % "<~people>", "disc": _("Disc %s") % "<discnumber>", "track": _("Track %s") % "<tracknumber>" }) _not_playing = "<span size='xx-large'>%s</span>" % _("Not playing") def __init__(self, library, player, pattern_filename): super().__init__() self._pattern_filename = pattern_filename self.set_visible_window(False) align = Align(halign=Gtk.Align.START, valign=Gtk.Align.START) label = Gtk.Label() label.set_ellipsize(Pango.EllipsizeMode.MIDDLE) label.set_track_visited_links(False) label.set_selectable(True) align.add(label) label.set_alignment(0.0, 0.0) self._label = label connect_destroy(library, 'changed', self._on_library_changed, player) connect_destroy(player, 'song-started', self._on_song_started) label.connect('populate-popup', self._on_label_popup, player, library) self.connect('key-press-event', self._on_key_press_event, player) self.connect('button-press-event', self._on_button_press_event, player, library) try: with open(self._pattern_filename, "rb") as h: self._pattern = h.read().strip().decode("utf-8") except (EnvironmentError, UnicodeDecodeError): pass self._compiled = XMLFromMarkupPattern(self._pattern) align.show_all() self.add(align) def _on_key_press_event(self, widget, event, player: BasePlayer): if qltk.is_accel(event, "space"): player.playpause() def _on_button_press_event(self, widget, event, player, library): if event.button == Gdk.BUTTON_SECONDARY: menu = self._get_menu(player, library) menu.attach_to_widget(widget, None) menu.popup(None, None, None, None, event.button, event.time) return True return False def _on_label_popup(self, label, menu, player, library): song_menu = self._get_menu(player, library) has_selection = label.get_selection_bounds()[0] if not has_selection: for child in menu.get_children(): child.destroy() for item in song_menu: song_menu.remove(item) menu.append(item) else: sub = Gtk.MenuItem.new_with_mnemonic(_("Current _Song")) sub.set_submenu(song_menu) sub.set_sensitive(player.song is not None) sub.show_all() sep = SeparatorMenuItem() sep.show() menu.append(sep) menu.append(sub) def _get_menu(self, player, library): item = qltk.MenuItem(_(u"_Edit Display…"), Icons.EDIT) item.connect('activate', self._on_edit_display, player) songs = [player.song] if player.song else [] song_menu = SongsMenu(library, songs, remove=False, delete=True, accels=False, items=[[item]]) song_menu.show_all() return song_menu def _on_edit_display(self, menu_item, player): editor = PatternEdit( self, SongInfo._pattern, alternative_markup=True, links=True) editor.text = self._pattern editor.apply.connect('clicked', self._on_set_pattern, editor, player) editor.show() def _on_set_pattern(self, button, edit, player): self._pattern = edit.text.rstrip() if self._pattern == SongInfo._pattern: try: os.unlink(self._pattern_filename) except OSError: pass else: try: with open(self._pattern_filename, "wb") as h: h.write(self._pattern.encode("utf-8") + b"\n") except EnvironmentError as e: print_w("Couldn't save display pattern '%s' (%s)" % (self._pattern, e)) self._compiled = XMLFromMarkupPattern(self._pattern) self._update_info(player) def _on_library_changed(self, library, songs, player): if player.info in songs: self._update_info(player) def _on_song_started(self, player, song): self._update_info(player) def _update_info(self, player, _last={}): text = (self._not_playing if player.info is None else self._compiled % player.info) # some radio streams update way too often and updating the label # destroys the text selection if text not in _last: self._label.set_markup(text) _last.clear() _last[text] = True ����������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/information.py�������������������������������������������������������0000644�0001750�0001750�00000055446�14327505043�020066� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2016-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import time from collections import defaultdict from gi.repository import Gtk, Pango from quodlibet.formats import PEOPLE from senf import fsn2text from quodlibet import ngettext, _ from quodlibet import qltk from quodlibet import util from quodlibet import app from quodlibet.qltk.bookmarks import EditBookmarksPane from quodlibet.qltk.cover import CoverImage from quodlibet.qltk.lyrics import LyricsPane from quodlibet.qltk.window import Window, PersistentWindowMixin from quodlibet.qltk.x import Align from quodlibet.util import tag, connect_destroy from quodlibet.util.i18n import numeric_phrase from quodlibet.util.tags import readable from quodlibet.util.path import filesize, unexpand def Label(label=None, markup=None, ellipsize=False): if markup: l = Gtk.Label() l.set_markup(markup) else: l = Gtk.Label(label=label) l.set_selectable(True) l.set_alignment(0, 0) if ellipsize: l.set_ellipsize(Pango.EllipsizeMode.END) return l class TitleLabel(Gtk.Label): def __init__(self, text, is_markup=False): super().__init__() self.set_ellipsize(Pango.EllipsizeMode.END) markup = text if is_markup else (util.italic(text)) markup = "<span size='xx-large'>%s</span>" % markup self.set_markup(markup) self.set_selectable(True) class ReactiveCoverImage(CoverImage): def __init__(self, resize=False, size=125, song=None, tooltip=None): super().__init__(resize, size, song) self.set_property('no-show-all', True) def show_cover(cover, success): if success: cover.show() cover.disconnect(signal_id) signal_id = self.connect('cover-visible', show_cover) self.set_song(song) if tooltip: self.get_child().set_tooltip_text(tooltip) def Frame(name, widget): def hx(value): return hex(int(value * 255))[2:] f = Gtk.Frame() qltk.add_css(f, '* {opacity: 0.9}') l = Gtk.Label() l.set_markup(util.escape(name)) qltk.add_css(l, " * {opacity: 0.6; padding: 0px 2px;}") f.set_label_widget(l) a = Align(top=6, left=12, bottom=6, right=6) f.add(a) a.add(widget) return f def Table(rows): # Gtk.Table doesn't allow 0 rows t = Gtk.Table(n_rows=max(rows, 1), n_columns=2) t.set_col_spacings(6) t.set_row_spacings(6) t.set_homogeneous(False) return t def SW(): swin = Gtk.ScrolledWindow() swin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) return swin class NoSongs(Gtk.Label): def __init__(self): super().__init__(label=_("No songs are selected.")) self.title = _("No Songs") class OneSong(qltk.Notebook): def __init__(self, library, song, lyrics=True, bookmarks=True): super().__init__() vbox = Gtk.VBox(spacing=12) vbox.set_border_width(12) self._title(song, vbox) self._album(song, vbox) self._people(song, vbox) self._library(song, vbox) self._file(song, vbox) self._additional(song, vbox) sw = SW() sw.title = _("Information") sw.add_with_viewport(vbox) self.append_page(sw) if lyrics: lyrics = LyricsPane(song) lyrics.title = _("Lyrics") self.append_page(lyrics) if bookmarks: bookmarks = EditBookmarksPane(None, song) bookmarks.title = _("Bookmarks") bookmarks.set_border_width(12) self.append_page(bookmarks) connect_destroy(library, 'changed', self.__check_changed, vbox, song) def _switch_to_lyrics(self): self.set_current_page(1) def __check_changed(self, library, songs, vbox, song): if song in songs: for c in vbox.get_children(): vbox.remove(c) c.destroy() self._title(song, vbox) self._album(song, vbox) self._people(song, vbox) self._library(song, vbox) self._file(song, vbox) self._additional(song, vbox) parent = qltk.get_top_parent(self) if parent: parent.set_title(self.title + " - Quod Libet") vbox.show_all() def _title(self, song, box): text = song.comma("title") if "version" in song: text += "\n" + util.escape(song.comma("version")) box.pack_start(TitleLabel(text), False, False, 0) self.title = song.comma("title") def _album(self, song, box): if "album" not in song: return text = [f"<span size='x-large'>{util.italic(song.comma('album'))}</span>"] secondary = [] if "discnumber" in song: secondary.append(_("Disc %s") % song["discnumber"]) if "discsubtitle" in song: secondary.append(util.italic(song.comma("discsubtitle"))) if "tracknumber" in song: secondary.append(_("Track %s") % song["tracknumber"]) if secondary: text.append(" - ".join(secondary)) if "date" in song: text.append(util.escape(song.comma("date"))) if "organization" in song or "labelid" in song: t = util.escape(song.comma("~organization~labelid")) text.append(t) if "producer" in song: text.append(_("Produced by %s") % ( util.escape(song.comma("producer")))) w = Label(markup="\n".join(text), ellipsize=True) hb = Gtk.HBox(spacing=12) hb.pack_start(w, True, True, 0) box.pack_start(Frame(tag("album"), hb), False, False, 0) cover = ReactiveCoverImage(song=song) hb.pack_start(cover, False, True, 0) def _people(self, song, box): data = [] if "artist" in song: title = (_("artist") if len(song.list("artist")) == 1 else _("artists")) title = util.capitalize(title) data.append((title, song["artist"])) for tag_ in ["performer", "lyricist", "arranger", "composer", "conductor", "author"]: if tag_ in song: name = (tag(tag_) if len(song.list(tag_)) == 1 else readable(tag_, plural=True)) data.append((name, song[tag_])) performers = defaultdict(list) for tag_ in song: if "performer:" in tag_: for person in song.list(tag_): role = util.title(tag_.split(':', 1)[1]) performers[role].append(person) if performers: text = '\n'.join("%s (%s)" % (', '.join(names), part) for part, names in performers.items()) name = (tag("performer") if len(performers) == 1 else _("performers")) data.append((name, text)) table = Table(len(data)) for i, (key, text) in enumerate(data): key = util.capitalize(util.escape(key) + ":") table.attach(Label(markup=key), 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) label = Label(text, ellipsize=True) table.attach(label, 1, 2, i, i + 1) box.pack_start(Frame(tag("~people"), table), False, False, 0) def _library(self, song, box): def counter(i): return _("Never") if i == 0 \ else numeric_phrase("%(n)d time", "%(n)d times", i, "n") def ftime(t): if t == 0: return _("Unknown") else: return str(time.strftime("%c", time.localtime(t))) playcount = counter(song.get("~#playcount", 0)) skipcount = counter(song.get("~#skipcount", 0)) lastplayed = ftime(song.get("~#lastplayed", 0)) if lastplayed == _("Unknown"): lastplayed = _("Never") added = ftime(song.get("~#added", 0)) rating = song("~rating") has_rating = "~#rating" in song t = Table(5) table = [(_("added"), added, True), (_("last played"), lastplayed, True), (_("plays"), playcount, True), (_("skips"), skipcount, True), (_("rating"), rating, has_rating)] for i, (l, r, s) in enumerate(table): l = util.capitalize(l + ":") lab = Label(l) t.attach(lab, 0, 1, i + 1, i + 2, xoptions=Gtk.AttachOptions.FILL) label = Label(r) label.set_sensitive(s) t.attach(label, 1, 2, i + 1, i + 2) box.pack_start(Frame(_("Library"), t), False, False, 0) def _file(self, song, box): def ftime(t): if t == 0: return _("Unknown") else: return str(time.strftime("%c", time.localtime(t))) fn = fsn2text(unexpand(song["~filename"])) length = util.format_time_preferred(song.get("~#length", 0)) size = util.format_size( song.get("~#filesize") or filesize(song["~filename"])) mtime = ftime(util.path.mtime(song["~filename"])) format_ = song("~format") codec = song("~codec") encoding = song.comma("~encoding") bitrate = song("~bitrate") table = [(_("path"), fn), (_("length"), length), (_("format"), format_), (_("codec"), codec), (_("encoding"), encoding), (_("bitrate"), bitrate), (_("file size"), size), (_("modified"), mtime)] t = Table(len(table)) for i, (tag_, text) in enumerate(table): tag_ = util.capitalize(util.escape(tag_) + ":") lab = Label(text) lab.set_ellipsize(Pango.EllipsizeMode.MIDDLE) t.attach(Label(tag_), 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) t.attach(lab, 1, 2, i, i + 1) box.pack_start(Frame(_("File"), t), False, False, 0) def _additional(self, song, box): if "website" not in song and "comment" not in song: return markup_data = [] if "comment" in song: comments = song.list("comment") markups = [util.italic(c) for c in comments] markup_data.append(("comment", markups)) if "website" in song: markups = ["<a href=\"%(url)s\">%(text)s</a>" % {"text": util.escape(website), "url": util.escape(website)} for website in song.list("website")] markup_data.append(("website", markups)) table = Table(1) for i, (key, markups) in enumerate(markup_data): title = readable(key, plural=len(markups) > 1) lab = Label(markup=util.capitalize(util.escape(title) + ":")) table.attach(lab, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) lab = Label(markup="\n".join(markups), ellipsize=True) table.attach(lab, 1, 2, i, i + 1) box.pack_start(Frame(_("Additional"), table), False, False, 0) class OneAlbum(qltk.Notebook): def __init__(self, songs): super().__init__() swin = SW() swin.title = _("Information") vbox = Gtk.VBox(spacing=12) vbox.set_border_width(12) swin.add_with_viewport(vbox) # Needed to get proper track/disc/part ordering songs = sorted(songs) self._title(songs, vbox) self._album(songs, vbox) self._people(songs, vbox) self._description(songs, vbox) self.append_page(swin) def _title(self, songs, box): song = songs[0] self.title = text = song["album"] markup = util.italic(text) if "date" in song: markup += " <small>(%s)</small>" % util.escape(song("~year")) box.pack_start(TitleLabel(markup, is_markup=True), False, False, 0) def _album(self, songs, box): text = [] discs = {} for song in songs: try: discs[song("~#disc")] = int( song["tracknumber"].split("/")[1]) except (AttributeError, ValueError, IndexError, KeyError): discs[song("~#disc")] = max([ song("~#track", discs.get(song("~#disc"), 0))]) tracks = sum(discs.values()) discs = len(discs) length = sum([song.get("~#length", 0) for song in songs]) if tracks == 0 or tracks < len(songs): tracks = len(songs) parts = [] if discs > 1: parts.append( ngettext("%d disc", "%d discs", discs) % discs) parts.append( ngettext("%d track", "%d tracks", tracks) % tracks) if tracks != len(songs): parts.append(ngettext("%d selected", "%d selected", len(songs)) % len(songs)) text.append(", ".join(parts)) text.append("(%s)" % util.format_time_preferred(length)) if "location" in song: text.append(util.escape(song["location"])) if "organization" in song or "labelid" in song: t = util.escape(song.comma("~organization~labelid")) text.append(t) if "producer" in song: text.append(_("Produced by %s") % ( util.escape(song.comma("producer")))) w = Label(markup="\n".join(text), ellipsize=True) hb = Gtk.HBox(spacing=12) hb.pack_start(w, True, True, 0) hb.pack_start(ReactiveCoverImage(song=song), False, True, 0) box.pack_start(hb, False, False, 0) def _people(self, songs, box): tags_ = PEOPLE people = defaultdict(set) for song in songs: for t in tags_: if t in song: people[t] |= set(song.list(t)) data = [] # Preserve order of people for tag_ in tags_: values = people.get(tag_) if values: name = readable(tag_, plural=len(values) > 1) data.append((name, "\n".join(values))) table = Table(len(data)) for i, (key, text) in enumerate(data): key = util.capitalize(util.escape(key) + ":") table.attach(Label(markup=key), 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL) label = Label(text, ellipsize=True) table.attach(label, 1, 2, i, i + 1) box.pack_start(Frame(tag("~people"), table), False, False, 0) def _description(self, songs, box): text = [] cur_disc = songs[0]("~#disc", 1) - 1 cur_part = None cur_track = songs[0]("~#track", 1) - 1 for song in songs: track = song("~#track", 0) disc = song("~#disc", 0) part = song.get("part") if disc != cur_disc: if cur_disc: text.append("") cur_track = song("~#track", 1) - 1 cur_part = None cur_disc = disc if disc: text.append("%s" % (_("Disc %s") % disc)) if part != cur_part: ts = " " * bool(disc) cur_part = part if part: text.append("%s%s" % (ts, util.escape(part))) cur_track += 1 ts = " " * (bool(disc) + bool(part)) while cur_track < track: text.append("{ts}{cur: >2}. {text}".format( ts=ts, cur=cur_track, text=_("Track unavailable"))) cur_track += 1 title = util.italic(song.comma("~title~version")) text.append(f"{ts}{track: >2}. {title}") l = Label(markup="\n".join(text), ellipsize=True) box.pack_start(Frame(_("Track List"), l), False, False, 0) class OneArtist(qltk.Notebook): def __init__(self, songs): super().__init__() swin = SW() swin.title = _("Information") vbox = Gtk.VBox(spacing=12) vbox.set_border_width(12) swin.add_with_viewport(vbox) self._title(songs, vbox) self._album(songs, vbox) self.append_page(swin) def _title(self, songs, box): self.title = songs[0]("artist") l = TitleLabel(self.title) box.pack_start(l, False, False, 0) def _album(self, songs, box): albums, noalbum = _sort_albums(songs) def format(args): date, song, album = args markup = f"<big>{util.italic(album)}</big>" return "%s (%s)" % (markup, date[:4]) if date else markup get_cover = app.cover_manager.get_cover covers = [(a, get_cover(s), s) for d, s, a in albums] albums = [format(a) for a in albums] if noalbum: albums.append(ngettext("%d song with no album", "%d songs with no album", noalbum) % noalbum) l = Label(markup="\n".join(albums), ellipsize=True) box.pack_start(Frame(_("Selected Discography"), l), False, False, 0) covers = [ac for ac in covers if bool(ac[1])] t = Gtk.Table(n_rows=4, n_columns=(len(covers) // 4) + 1) t.set_col_spacings(12) t.set_row_spacings(12) added = set() for i, (album, cover, song) in enumerate(covers): if cover.name in added: continue cov = ReactiveCoverImage(song=song, tooltip=album) c = i % 4 r = i // 4 t.attach(cov, c, c + 1, r, r + 1, xoptions=Gtk.AttachOptions.EXPAND, yoptions=0) added.add(cover.name) box.pack_start(t, True, True, 0) def _sort_albums(songs): """:return: a tuple of (albums, count) where count is the number of album-less songs and albums is a list of (date, song, album), sorted""" no_album_count = 0 albums = {} for song in songs: if "album" in song: albums[song.list("album")[0]] = song else: no_album_count += 1 albums = [(song.get("date", ""), song, album) for album, song in albums.items()] albums.sort() return albums, no_album_count class ManySongs(qltk.Notebook): def __init__(self, songs): super().__init__() swin = SW() swin.title = _("Information") vbox = Gtk.VBox(spacing=12) vbox.set_border_width(12) swin.add_with_viewport(vbox) self._title(songs, vbox) self._people(songs, vbox) self._album(songs, vbox) self._file(songs, vbox) self.append_page(swin) def _title(self, songs, box): self.title = ngettext("%d song", "%d songs", len(songs)) % len(songs) markup = util.escape(self.title) box.pack_start(TitleLabel(markup, is_markup=True), False, False, 0) def _people(self, songs, box): artists = set() none = 0 for song in songs: if "artist" in song: artists.update(song.list("artist")) else: none += 1 artists = sorted(artists) num_artists = len(artists) if none: artists.append(ngettext("%d song with no artist", "%d songs with no artist", none) % none) label = Label(markup=util.escape("\n".join(artists)), ellipsize=True) frame = Frame("%s (%d)" % (util.capitalize(_("artists")), num_artists), label) box.pack_start(frame, False, False, 0) def _album(self, songs, box): albums = set() none = 0 for song in songs: if "album" in song: albums.update(song.list("album")) else: none += 1 albums = sorted(albums) num_albums = len(albums) markup = "\n".join(util.italic(a) for a in albums) if none: text = ngettext("%d song with no album", "%d songs with no album", none) % none markup += f"\n{util.escape(text)}" label = Label() label.set_markup(markup) albums = util.capitalize(_('albums')) box.pack_start(Frame(f"{albums} ({num_albums})", label), False, False, 0) def _file(self, songs, box): length = 0 size = 0 for song in songs: length += song.get("~#length", 0) try: size += filesize(song["~filename"]) except EnvironmentError: pass table = Table(2) table.attach(Label(_("Total length:")), 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) table.attach( Label(util.format_time_preferred(length)), 1, 2, 0, 1) table.attach(Label(_("Total size:")), 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) table.attach(Label(util.format_size(size)), 1, 2, 1, 2) box.pack_start(Frame(_("Files"), table), False, False, 0) class Information(Window, PersistentWindowMixin): def __init__(self, library, songs, parent=None): super().__init__(dialog=False) self.set_default_size(400, 400) self.set_transient_for(qltk.get_top_parent(parent)) self.enable_window_tracking("quodlibet_information") if len(songs) > 1: connect_destroy(library, 'changed', self.__check_changed) if len(songs) > 0: connect_destroy(library, 'removed', self.__check_removed) self.__songs = songs self.__update(library) self.get_child().show_all() def __check_changed(self, library, songs): changed = set(songs) for song in self.__songs: if song in changed: self.__update(library) break def __check_removed(self, library, songs): gone = set(songs) old = len(self.__songs) self.__songs = [s for s in self.__songs if s not in gone] if len(self.__songs) != old: self.__update(library) def __update(self, library): songs = self.__songs if self.get_child(): self.get_child().destroy() self.__songs = songs if not songs: self.add(NoSongs()) elif len(songs) == 1: self.add(OneSong(library, songs[0])) else: tags = [(s.get("artist", ""), s.get("album", "")) for s in songs] artists, albums = zip(*tags) if min(albums) == max(albums) and albums[0]: self.add(OneAlbum(songs)) elif min(artists) == max(artists) and artists[0]: self.add(OneArtist(songs)) else: self.add(ManySongs(songs)) self.set_title(self.get_child().title + " - Quod Libet") self.get_child().show_all() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/lyrics.py������������������������������������������������������������0000664�0001750�0001750�00000011511�14244626671�017042� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Eduardo Gonzalez, Joe Wreschnig # 2017-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. # FIXME: Too many buttons -- saving should be automatic? import os from urllib.parse import quote from gi.repository import Gtk from quodlibet import _, print_d, print_w, app from quodlibet import qltk from quodlibet import util from quodlibet.errorreport import errorhook from quodlibet.formats import AudioFileError from quodlibet.qltk import Icons from quodlibet.util import connect_obj class LyricsPane(Gtk.VBox): def __init__(self, song): super().__init__(spacing=12) self.set_border_width(12) view = Gtk.TextView() sw = Gtk.ScrolledWindow() sw.add(view) save = qltk.Button(_("_Save"), Icons.DOCUMENT_SAVE) delete = qltk.Button(_("_Delete"), Icons.EDIT_DELETE) view_online = qltk.Button(_("_View online"), Icons.APPLICATION_INTERNET) view.set_wrap_mode(Gtk.WrapMode.WORD) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) buffer = view.get_buffer() save.connect('clicked', self.__save, song, buffer, delete) delete.connect('clicked', self.__delete, song, save) view_online.connect('clicked', self.__view_online, song) sw.set_shadow_type(Gtk.ShadowType.IN) self.pack_start(sw, True, True, 0) bbox = Gtk.HButtonBox() bbox.pack_start(save, True, True, 0) bbox.pack_start(delete, True, True, 0) bbox.pack_start(view_online, True, True, 0) self.pack_start(bbox, False, True, 0) save.set_sensitive(False) view_online.set_sensitive(True) lyrics = song("~lyrics") if lyrics: buffer.set_text(lyrics) else: buffer.set_text(_("No lyrics found for this song.")) connect_obj(buffer, 'changed', save.set_sensitive, True) def __view_online(self, add, song): # TODO: make this modular and plugin-friendly (#54, #3642 etc) def sanitise(s: str) -> str: return quote(s.replace(" ", "-") .replace(".", "") .replace("'", "") .replace('"', "") .replace(",", "-") .lower() .encode('utf-8')) artist = sanitise(song.list('artist')[0]) title = sanitise(song.comma('title')) util.website(f"https://genius.com/{artist}-{title}-lyrics") def __save(self, save, song, buffer, delete): start, end = buffer.get_bounds() text = buffer.get_text(start, end, True) self._save_lyrics(song, text) delete.set_sensitive(True) save.set_sensitive(False) def _save_lyrics(self, song, text): # First, try writing to the tags. if "lyrics" not in song and "unsyncedlyrics" in song: tag = "unsyncedlyrics" else: tag = "lyrics" song[tag] = text try: song.write() except AudioFileError as e: print_w(f"Couldn't write embedded lyrics ({e!r})") self._save_to_file(song, text) else: print_d(f"Wrote embedded lyrics into {song('~filename')}") app.librarian.emit('changed', [song]) fn = song.lyric_filename if fn: self._delete_file(fn) def _save_to_file(self, song, text): lyric_fn = song.lyric_filename if not lyric_fn: print_w("No lyrics file to save to, ignoring.") return try: os.makedirs(os.path.dirname(lyric_fn), exist_ok=True) except EnvironmentError: errorhook() try: with open(lyric_fn, "wb") as f: f.write(text.encode("utf-8")) print_d(f"Saved lyrics to file {lyric_fn!r}") except EnvironmentError: errorhook() def __delete(self, delete, song, save): # First, delete from the tags. song.remove("lyrics") try: song.write() except AudioFileError: util.print_exc() self._delete_file(song.lyric_filename) delete.set_sensitive(False) save.set_sensitive(True) def _delete_file(self, filename): if not filename: return try: os.unlink(filename) print_d(f"Removed lyrics file {filename!r}") except EnvironmentError: pass lyric_dir = os.path.dirname(filename) try: os.rmdir(lyric_dir) print_d(f"Removed lyrics directory {lyric_dir}") except EnvironmentError: pass ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/maskedbox.py���������������������������������������������������������0000644�0001750�0001750�00000011264�14267565021�017511� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango from senf import fsn2text from quodlibet import ngettext, _ from quodlibet import qltk from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk import Icons from quodlibet.util import connect_obj class ConfirmMaskedRemoval(qltk.Message): def __init__(self, parent): title = _("Are you sure you want to remove all songs?") description = _("The selected songs will be removed from the library.") super().__init__( Gtk.MessageType.WARNING, parent, title, description, Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Delete"), Icons.EDIT_DELETE, Gtk.ResponseType.YES) class MaskedBox(Gtk.HBox): def __init__(self, library): super().__init__(spacing=6) self.model = model = Gtk.ListStore(object) view = RCMHintedTreeView(model=model) view.set_fixed_height_mode(True) view.set_headers_visible(False) self.view = view menu = Gtk.Menu() unhide_item = qltk.MenuItem(_("Unhide"), Icons.LIST_ADD) connect_obj(unhide_item, 'activate', self.__unhide, view, library) menu.append(unhide_item) remove_item = qltk.MenuItem(_("_Remove"), Icons.LIST_REMOVE) connect_obj(remove_item, 'activate', self.__remove, view, library) menu.append(remove_item) menu.show_all() view.connect('popup-menu', self.__popup, menu) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_size_request(-1, max(sw.size_request().height, 80)) def cdf(column, cell, model, iter, data): row = model[iter] cell.set_property('text', fsn2text(row[0])) def cdf_count(column, cell, model, iter, data): mount = model[iter][0] song_count = len(library.get_masked(mount)) text = ngettext("%d song", "%d songs", song_count) % song_count cell.set_property('text', text) column = Gtk.TreeViewColumn(None) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(render, True) column.set_cell_data_func(render, cdf) render = Gtk.CellRendererText() render.props.sensitive = False column.pack_start(render, False) column.set_cell_data_func(render, cdf_count) view.append_column(column) unhide = qltk.Button(_("_Unhide"), Icons.LIST_ADD) connect_obj(unhide, "clicked", self.__unhide, view, library) remove = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) selection = view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect("changed", self.__select_changed, remove, unhide) selection.emit("changed") connect_obj(remove, "clicked", self.__remove, view, library) vbox = Gtk.VBox(spacing=6) vbox.pack_start(unhide, False, True, 0) vbox.pack_start(remove, False, True, 0) self.pack_start(sw, True, True, 0) self.pack_start(vbox, False, True, 0) for path in library.masked_mount_points: model.append(row=[path]) if not len(model): self.set_sensitive(False) for child in self.get_children(): child.show_all() def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __unhide(self, view, library): selection = view.get_selection() model, paths = selection.get_selected_rows() for path in paths: library.unmask(model[path][0]) view.remove_selection() def __select_changed(self, selection, *buttons): active = bool(selection.count_selected_rows()) for button in buttons: button.set_sensitive(active) def __remove(self, view, library): dialog = ConfirmMaskedRemoval(self) response = dialog.run() if response == Gtk.ResponseType.YES: selection = view.get_selection() model, paths = selection.get_selected_rows() for path in paths: library.remove_masked(model[path][0]) view.remove_selection() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/matchdialog.py�������������������������������������������������������0000664�0001750�0001750�00000022060�14231604507�020000� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2021 Joschua Gandert # # 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 2 of the License, or # (at your option) any later version. from dataclasses import dataclass from gi.repository import Gtk, Pango from typing import List, Optional, Generic, TypeVar, Callable from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.views import HintedTreeView from quodlibet.qltk import Icons from quodlibet import _, app from quodlibet.qltk.window import PersistentWindowMixin, Dialog MATCH_DESC = _("Check if the columns on the left side approximately match the ones on " "the right side. If they don't, you can change the order here (use _ " "for rows that shouldn't be matched):") T = TypeVar("T") @dataclass class ColumnSpec(Generic[T]): """Simple data class for specifying the behavior and content of a column""" title: str cell_text_getter: Callable[[T], str] is_resizable: bool = True # We're using a Dialog, since a ConfirmationPrompt looks really ugly at such a width class MatchListsDialog(Dialog, PersistentWindowMixin, Generic[T]): """ A prompt whose run method returns the chosen order, or an empty list if the user pressed cancel. """ def __init__(self, a_items: List[T], b_items: List[T], b_order: List[Optional[int]], columns: List[ColumnSpec[T]], title: str, ok_button_text: str, ok_button_icon: str = Icons.DOCUMENT_SAVE, description: str = MATCH_DESC, parent=app.window, id_for_window_tracking: Optional[str] = None): super().__init__(title=title, transient_for=parent, modal=True, destroy_with_parent=True) # A lot of information to display, so make resizable and maximize self.set_resizable(True) self.set_default_size(750, 500) self.maximize() if id_for_window_tracking is not None: self.enable_window_tracking(id_for_window_tracking) vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8) self.get_content_area().pack_start(vb, True, True, 0) vb.set_spacing(24) self.set_border_width(5) desc_lbl = Gtk.Label(f'\n{description}\n', wrap=True) vb.pack_start(desc_lbl, False, False, 0) self.add_button(_("_Cancel"), Gtk.ResponseType.REJECT) self.add_icon_button(ok_button_text, ok_button_icon, Gtk.ResponseType.OK) order_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8) lbl = Gtk.Label(_("Right side order:")) order_box.pack_start(lbl, False, True, 0) self.order_entry = Gtk.Entry() order_box.pack_start(self.order_entry, True, True, 0) vb.pack_start(order_box, False, True, 1) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) vb.pack_start(sw, True, True, 1) tree = MatchListsTreeView(a_items, b_items, columns) self._tree = tree sw.add(tree) tree.b_order = b_order default_order_text = ', '.join( ('_' if i is None else str(i + 1)) for i in b_order) self.order_entry.set_text(default_order_text) legal_characters = set(default_order_text) legal_characters.add('_') def changed_order_entry(widget): text = widget.get_text() # remove illegal characters new_text = ''.join(c for c in text if c in legal_characters) widget.set_text(new_text) num_tracks = len(b_items) reordered = one_indexed_csv_to_unique_indices(new_text, num_tracks) if reordered: tree.b_order = reordered self.order_entry.connect("changed", changed_order_entry) def run(self, destroy=True) -> List[Optional[int]]: self.show_all() resp = super().run() if destroy: self.destroy() return self.order if resp == Gtk.ResponseType.OK else [] @property def order(self): return self._tree.b_order def one_indexed_csv_to_unique_indices(text, target_length, char_for_none_matching='_', require_target_length_elements=False): """ :return: List of indices from the comma separated list of one-indexed numbers. List will be empty if any index is repeated or out of bounds. By default '_' can be used to specify that a position has no match, which will be represented in the returned list with None. """ # remove trailing commas, then split nums = text.strip(', ').split(',') if require_target_length_elements and len(nums) != target_length: return [] reordered = [] for n in nums: n = n.strip() if n == char_for_none_matching: i = None else: try: i = int(n) - 1 except ValueError: return [] # i is not in range and/or not unique if i < 0 or i >= target_length or i in reordered: return [] reordered.append(i) return reordered class MatchListsTreeView(HintedTreeView, Generic[T]): _b_order: List[Optional[int]] def __init__(self, a_items: List[T], b_items: List[T], columns: List[ColumnSpec[T]]): self.model = ObjectStore() self.model.append_many(a_items) self._b_items = b_items super().__init__(self.model) self.set_headers_clickable(False) self.set_rules_hint(True) self.set_reorderable(False) self.get_selection().set_mode(Gtk.SelectionMode.NONE) def show_id(col, cell, model, itr, data): idx = model.get_path(itr)[0] imp_idx = self._b_order[idx] num = '_' if imp_idx is None else imp_idx + 1 cell.set_property('markup', f'<span weight="bold">{num}</span>') def df_for_a_items(a_attr_getter): def data_func(col, cell, model, itr, data): a_item = model[itr][0] text = '' if a_item is not None: text = a_attr_getter(a_item) cell.set_property('text', text) return data_func def df_for_b_items(b_attr_getter): def data_func(col, cell, model, itr, data): self._set_text(model, itr, cell, b_attr_getter) return data_func for c in columns: self._add_col(c.title, df_for_a_items(c.cell_text_getter), c.is_resizable) self._add_col('#', show_id, False) for c in columns: self._add_col(c.title, df_for_b_items(c.cell_text_getter), c.is_resizable) self._b_order = [] # Initialize the backing field of b_order self.b_order = list(range(len(b_items))) # Update it and rows self.update_b_items(b_items) def _add_col(self, title, func, resize): render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn(title, render) col.set_cell_data_func(render, func) col.set_resizable(resize) col.set_expand(resize) self.append_column(col) def _set_text(self, model, itr, cell, get_attr): idx = model.get_path(itr)[0] text = '' if idx < len(self._b_order): it_idx = self._b_order[idx] if it_idx is not None: text = get_attr(self._b_items[it_idx]) cell.set_property('text', text) def update_b_items(self, b_items: List[T]): """ Updates the TreeView, handling results with a different number of b_items than there are a_items. """ self._b_items = b_items for i in range(len(self.model), len(b_items)): self.model.append((None,)) for i in range(len(self.model), len(b_items), -1): if self.model[-1][0] is not None: break itr = self.model.get_iter_from_string(str(len(self.model) - 1)) self.model.remove(itr) self._rows_changed() self.columns_autosize() def _rows_changed(self): for row in self.model: self.model.row_changed(row.path, row.iter) @property def b_order(self) -> List[Optional[int]]: return list(self._b_order) @b_order.setter def b_order(self, order: List[Optional[int]]): """ Supports a partial order list. For example, if there are 5 elements in the b_items list, you could supply [4, 1, 2]. This will result in an ascending order for the last 2 rows, so [0, 3]. """ if order == self._b_order: return b_len = len(self._b_items) if len(order) < b_len: # add missing indices for i in range(b_len): if i not in order: order.append(i) while len(order) < len(self.model): order.append(None) self._b_order = order self._rows_changed() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1659014435.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/menubutton.py��������������������������������������������������������0000644�0001750�0001750�00000002554�14270506443�017733� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011, 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from . import add_css class MenuButton(Gtk.MenuButton): """TODO: remove. This used to be an implementation of Gtk.MenuButton when it wasn't available in gtk+ """ def __init__(self, widget=None, arrow=False, down=True): super().__init__() bbox = Gtk.HBox(spacing=3) if widget: bbox.pack_start(widget, True, True, 0) if arrow: arrow_type = Gtk.ArrowType.DOWN if down else Gtk.ArrowType.UP bbox.pack_start( Gtk.Arrow.new(arrow_type, Gtk.ShadowType.IN), True, True, 0) self.add(bbox) self.set_direction(Gtk.ArrowType.DOWN if down else Gtk.ArrowType.UP) def get_menu(self): return self.get_popup() def set_menu(self, menu): self.set_popup(menu) class SmallMenuButton(MenuButton): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.set_size_request(26, 26) add_css(self, """ * { padding: 0px 4px; } """) ����������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660856910.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/models.py������������������������������������������������������������0000644�0001750�0001750�00000020225�14277525116�017016� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013, 2014 Christoph Reiter # 2015, 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GObject from quodlibet.util import cmp _auto_types = [float, bool, GObject.Object, int, str] def _gets_marshaled_to_pyobject(obj, _types=tuple(_auto_types)): """Python objects get automarshalled to GValues which is faster than doing it in python but also has its own mapping, because it doesn't know the column type of the model. This returns if the python objects get marshalled to PYOBJECT by the C code. The GType logic can be found in 'pyg_type_from_object_strict' in PyGObject. """ if obj is None: return False return not isinstance(obj, _types) class _ModelMixin: ATOMIC = True """Guard against unintentional non-atomic row inserts. Set to False if you know what you're doing. """ def get_value(self, iter_, column=0, _base=Gtk.TreeModel.get_value): return _base(self, iter_, column) def get_n_columns(self): return 1 def iter_changed(self, iter_): """Like row_changed(), but only needs a Gtk.TreeIter""" self.row_changed(self.get_path(iter_), iter_) def path_changed(self, path): """Like row_changed(), but only needs a Gtk.TreePath""" self.row_changed(path, self.get_iter(path)) def itervalues(self, iter_=None): """Yields all values""" iter_ = self.iter_children(iter_) getv = self.get_value inext = self.iter_next while iter_: yield getv(iter_) iter_ = inext(iter_) def values(self): """Largely for Py2 -> Py3 compatibility""" return list(self.itervalues()) def iterrows(self, iter_=None): """Yields (iter, value) tuples""" iter_ = self.iter_children(iter_) getv = self.get_value inext = self.iter_next while iter_: yield iter_, getv(iter_) iter_ = inext(iter_) def is_empty(self): return not self.get_iter_first() _value = GObject.Value() _value.init(GObject.TYPE_PYOBJECT) def _get_marshalable(self, obj, _value=_value): if _gets_marshaled_to_pyobject(obj): return obj _value.set_boxed(obj) return _value del _value class ObjectModelFilter(_ModelMixin, Gtk.TreeModelFilter): pass class ObjectModelSort(_ModelMixin, Gtk.TreeModelSort): pass class ObjectTreeStore(_ModelMixin, Gtk.TreeStore): def __init__(self, *args): if len(args) > 1: raise ValueError if args and object not in args and GObject.TYPE_PYOBJECT not in args: raise ValueError if not args: args = [object] super().__init__(*args) def append(self, parent, row=None): if row is not None: value = self._get_marshalable(row[0]) return self.insert_with_values(parent, -1, [0], [value]) else: assert not self.ATOMIC return super().append(parent) def insert(self, parent, position, row=None): if row is not None: value = self._get_marshalable(row[0]) return self.insert_with_values(parent, position, [0], [value]) else: assert not self.ATOMIC return super().insert(parent, position) def prepend(self, parent, row=None): return self.insert(parent, 0, row) def insert_before(self, parent, sibling, row=None): if row is not None: value = self._get_marshalable(row[0]) if sibling is None: position = -1 else: if parent is None: parent = self.iter_parent(sibling) position = self.get_path(sibling)[-1] return self.insert_with_values(parent, position, [0], [value]) assert not self.ATOMIC return super().insert_before(parent, sibling) def insert_after(self, parent, sibling, row=None): if row is not None: value = self._get_marshalable(row[0]) if sibling is None: position = 0 else: if parent is None: parent = self.iter_parent(sibling) position = self.get_path(sibling)[-1] + 1 return self.insert_with_values(parent, position, [0], [value]) assert not self.ATOMIC return super().insert_after(parent, sibling) class ObjectStore(_ModelMixin, Gtk.ListStore): """Like a ListStore but only supports single column object lists Performance related API additions: - append_many(), insert_many() - itervalues() """ @staticmethod def _sort_on_value(m, a, b, data): """Sorts two items in an ObjectStore, suitable for passing to `set_default_sort_func`""" return cmp(m[a][0], m[b][0]) def __init__(self, *args): if len(args) > 1: raise ValueError if args and object not in args and GObject.TYPE_PYOBJECT not in args: raise ValueError if not args: args = [object] super().__init__(*args) def append(self, row=None): if row: value = self._get_marshalable(row[0]) return self.insert_with_valuesv(-1, [0], [value]) else: assert not self.ATOMIC return super().append(row) def insert(self, position, row=None): if row: value = self._get_marshalable(row[0]) return self.insert_with_valuesv(position, [0], [value]) else: assert not self.ATOMIC return super().insert(position) def iter_append_many(self, objects): """Append a list of python objects, yield iters""" insert_with_valuesv = self.insert_with_valuesv get_marshalable = self._get_marshalable columns = [0] try: first = next(objects) except TypeError: try: first = next(iter(objects)) except StopIteration: return except StopIteration: return else: value = get_marshalable(first) yield insert_with_valuesv(-1, columns, [value]) # fast path for auto-marshalling if _gets_marshaled_to_pyobject(first): for obj in objects: yield insert_with_valuesv(-1, columns, [obj]) else: for obj in objects: value = get_marshalable(obj) yield insert_with_valuesv(-1, columns, [value]) def append_many(self, objects): """Append a list of python objects""" for i in self.iter_append_many(objects): pass def insert_many(self, position, objects): if position == -1 or position > len(self): self.append_many(objects) return insert_with_valuesv = self.insert_with_valuesv get_marshalable = self._get_marshalable columns = [0] for i, obj in enumerate(objects): value = get_marshalable(obj) insert_with_valuesv(position + i, columns, [value]) def insert_before(self, sibling, row=None): if row is not None: value = self._get_marshalable(row[0]) if sibling is None: position = -1 else: position = self.get_path(sibling)[0] return self.insert_with_valuesv(position, [0], [value]) assert not self.ATOMIC return super().insert_before(sibling) def insert_after(self, sibling, row=None): if row is not None: value = self._get_marshalable(row[0]) if sibling is None: position = 0 else: position = self.get_path(sibling)[0] + 1 return self.insert_with_valuesv(position, [0], [value]) assert not self.ATOMIC return super().insert_after(sibling, row) def prepend(self, row=None): return self.insert(0, row) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684387440.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/msg.py���������������������������������������������������������������0000644�0001750�0001750�00000010114�14431333160�016301� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2021-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from typing import Type from gi.repository import Gtk from quodlibet import _ from quodlibet import util from quodlibet.qltk import get_top_parent from quodlibet.qltk.icons import Icons from quodlibet.qltk.window import Dialog from quodlibet.util import escape from senf import fsn2text, path2fsn class Message(Gtk.MessageDialog, Dialog): """A message dialog that destroys itself after it is run, uses markup, and defaults to an 'OK' button.""" def __init__(self, kind: Type, parent: Gtk.Widget, title: str, description: str, buttons: Gtk.ButtonsType = Gtk.ButtonsType.OK, escape_desc: bool = True): parent = get_top_parent(parent) markup = (f"<span weight='bold' size='larger'>{escape(title)}</span>\n\n" + escape(description) if escape_desc else description) super().__init__( transient_for=parent, modal=True, destroy_with_parent=True, message_type=kind, buttons=buttons) self.set_markup(markup) def run(self, destroy=True): resp = super().run() if destroy: self.destroy() return resp class CancelRevertSave(Gtk.MessageDialog, Dialog): def __init__(self, parent): title = _("Discard tag changes?") description = _("Tags have been changed but not saved. Save these " "files, or revert and discard changes?") text = ("<span weight='bold' size='larger'>%s</span>\n\n%s" % (title, description)) parent = get_top_parent(parent) super().__init__( transient_for=parent, flags=0, message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.NONE) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.YES) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Revert"), Icons.DOCUMENT_REVERT, Gtk.ResponseType.NO) self.set_default_response(Gtk.ResponseType.NO) self.set_markup(text) def run(self): resp = super().run() self.destroy() return resp class ErrorMessage(Message): """Like Message, but uses an error-indicating picture.""" def __init__(self, *args, **kwargs): super().__init__( Gtk.MessageType.ERROR, *args, **kwargs) class WarningMessage(Message): """Like Message, but uses a warning-indicating picture.""" def __init__(self, *args, **kwargs): super().__init__( Gtk.MessageType.WARNING, *args, **kwargs) class ConfirmationPrompt(WarningMessage): """Dialog to confirm actions, given a parent, title, description, and OK-button text""" RESPONSE_INVOKE = Gtk.ResponseType.YES def __init__(self, parent, title, description, ok_button_text, ok_button_icon=Icons.SYSTEM_RUN): super().__init__(parent, title, description, buttons=Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(ok_button_text, ok_button_icon, self.RESPONSE_INVOKE) self.set_default_response(Gtk.ResponseType.CANCEL) class ConfirmFileReplace(WarningMessage): RESPONSE_REPLACE = 1 def __init__(self, parent, path): title = _("File exists") fn_format = util.bold(fsn2text(path2fsn(path))) description = _("Replace %(file-name)s?") % {"file-name": fn_format} super().__init__( parent, title, description, buttons=Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Replace File"), Icons.DOCUMENT_SAVE, self.RESPONSE_REPLACE) self.set_default_response(Gtk.ResponseType.CANCEL) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/notif.py�������������������������������������������������������������0000644�0001750�0001750�00000024425�14327505043�016651� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010 Steven Robertson # 2020-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. """ This module will provide a unified notification area for informational messages and active tasks. This will eventually handle interactions with active tasks (e.g. pausing a copooled task), and provide shortcuts for copooling or threading a task with a status notification. It will also provide the UI for the planned global undo feature. Of course, right now it does none of these things. """ # This module is still experimental and may change or be removed. # TODO: Make copooling things with notifications easier (optional) # TODO: Make Ex Falso use this # TODO: Port WaitLoadWindow to use this (and not block) # TODO: Port Media browser to use this # TODO: Port Download Manager to use this # TODO: Add basic notification support # TODO: Add notification history # TODO: Add notification button/callback support (prereq for global undo) # TODO: Optimize performance (deferred signals, etc) from gi.repository import Gtk, GLib, Pango from quodlibet import _, util from quodlibet.util import copool from quodlibet.qltk.x import SmallImageToggleButton, SmallImageButton, Align from quodlibet.qltk import Icons, add_css class ParentProperty: """ A property which provides a thin layer of protection against accidental reparenting: you must first 'unparent' an instance by setting this property to 'None' before you can set a new parent. """ def __get__(self, inst, owner): return getattr(inst, '_parent', None) def __set__(self, inst, value): if getattr(inst, '_parent', None) is not None and value is not None: raise ValueError("Cannot set parent property without first " "setting it to 'None'.") inst._parent = value class Task: def __init__(self, source, desc, known_length=True, controller=None, pause=None, stop=None): self.source = source self.desc = desc if known_length: self.frac = 0. else: self.frac = None if controller: self.controller = controller else: self.controller = TaskController.default_instance self._pause = pause self._stop = stop self.pausable = bool(pause) self.stoppable = bool(stop) self._paused = False self.controller.add_task(self) def update(self, frac): """ Update a task's progress. """ self.frac = frac self.controller.update() def pulse(self): """ Indicate progress on a task of unknown length. """ self.update(None) def finish(self): """ Mark a task as finished, and remove it from the list of active tasks. """ self.frac = 1.0 self.controller.finish(self) @property def paused(self): return self._paused @paused.setter def paused(self, value): if self.pausable: self._pause(value) self._paused = value def stop(self): if self._stop: self._stop() self.finish() def gen(self, gen): """ Act as a generator pass-through, updating and finishing the task's progress automatically. If 'gen' has a __len__ property, it will be used to set the fraction accordingly. """ try: if hasattr(gen, '__len__'): for i, x in enumerate(gen): self.update(float(i) / len(gen)) yield x else: for x in gen: yield x finally: self.finish() def list(self, l): """ Evaluates the iterable argument before passing to 'gen'. """ return self.gen(list(l)) def copool(self, funcid, pause=True, stop=True): """ Convenience function: set the Task's 'pause' and 'stop' callbacks to act upon the copool with the given funcid. """ if pause: def pause_func(state): if state != self._paused: if state: copool.pause(funcid) else: copool.resume(funcid) self._pause = pause_func self.pausable = True if stop: self._stop = lambda: copool.remove(funcid) self.stoppable = True # Support context managers: # >>> with Task(...) as t: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.finish() return False class TaskController: """ Controller logic for displaying and managing a list of Tasks. Also implements the full Task interface to act as a pass-through or summary of all tasks in flight on this controller. """ parent = ParentProperty() default_instance: "TaskController" def __init__(self): self.active_tasks = [] self._parent = None self.update() def add_task(self, task): self.active_tasks.append(task) self.update() @property def source(self): if len(self.active_tasks) == 1: return self.active_tasks[0].source return _("Active tasks") @property def desc(self): if len(self.active_tasks) == 1: return self.active_tasks[0].desc return _("%d tasks running") % len(self.active_tasks) @property def frac(self): fracs = [t.frac for t in self.active_tasks if t.frac is not None] if fracs: return sum(fracs) / len(self.active_tasks) return None @property def paused(self): pausable = [t for t in self.active_tasks if t.pausable] if not pausable: return False return not [t for t in pausable if not t.paused] @paused.setter def paused(self, val): for t in self.active_tasks: if t.pausable: t.paused = val def stop(self): [t.stop() for t in self.active_tasks if t.stoppable] @property def pausable(self): return [t for t in self.active_tasks if t.pausable] @property def stoppable(self): return [t for t in self.active_tasks if t.stoppable] def update(self): if self._parent is not None: self._parent.update() def finish(self, finished_task): self.active_tasks = [t for t in self.active_tasks if t is not finished_task] self.update() # Oh so deliciously hacky. TaskController.default_instance = TaskController() class TaskWidget(Gtk.HBox): """ Displays a task. """ def __init__(self, task): super().__init__(spacing=3) self.task = task self.label = Gtk.Label() self.label.set_alignment(1.0, 0.5) self.label.set_ellipsize(Pango.EllipsizeMode.END) self.pack_start(self.label, True, False, 3) self.progress = Gtk.ProgressBar() self.progress.set_size_request(200, 12) add_css(self.progress, "progress, trough { min-height: 12px }") vb = Gtk.VBox(valign=Gtk.Align.CENTER) vb.pack_start(self.progress, True, True, 0) self.pack_start(vb, True, True, 3) self.pause = SmallImageToggleButton() self.pause.add( Gtk.Image.new_from_icon_name(Icons.MEDIA_PLAYBACK_PAUSE, Gtk.IconSize.MENU)) self.pause.connect('toggled', self.__pause_toggled) self.pack_start(self.pause, False, True, 3) self.stop = SmallImageButton() self.stop.add( Gtk.Image.new_from_icon_name(Icons.MEDIA_PLAYBACK_STOP, Gtk.IconSize.MENU)) self.stop.connect('clicked', self.__stop_clicked) self.pack_start(self.stop, False, True, 0) def __pause_toggled(self, btn): if self.task.pausable: self.task.paused = btn.props.active def __stop_clicked(self, btn): if self.task.stoppable: self.task.stop() def update(self): formatted_label = f"{util.bold(self.task.source)} – {self.task.desc}" self.label.set_markup(formatted_label) if self.task.frac is not None: self.progress.set_fraction(self.task.frac) else: self.progress.pulse() if self.pause.props.sensitive != self.task.pausable: self.pause.props.sensitive = self.task.pausable show_as_active = (self.task.pausable and self.task.paused) if self.pause.props.active != show_as_active: self.pause.props.active = show_as_active if self.stop.props.sensitive != self.task.stoppable: self.stop.props.sensitive = self.task.stoppable class StatusBar(Gtk.HBox): def __init__(self, task_controller): super().__init__() self.__dirty = False self.set_spacing(12) self.task_controller = task_controller self.task_controller.parent = self self.default_label = Gtk.Label(selectable=True) self.default_label.set_ellipsize(Pango.EllipsizeMode.END) self.pack_start( Align(self.default_label, halign=Gtk.Align.END), True, True, 0) self.task_widget = TaskWidget(task_controller) self.pack_start(self.task_widget, False, False, 0) self.show_all() self.set_no_show_all(True) self.__set_shown('default') self.connect("destroy", self.__destroy) def __destroy(self, *args): self.task_controller.parent = None def __set_shown(self, type): if type == 'default': self.default_label.show() else: self.default_label.hide() if type == 'task': self.task_widget.show() else: self.task_widget.hide() def set_default_text(self, text): self.default_label.set_text(text) def __update(self): self.__dirty = False if self.task_controller.active_tasks: self.__set_shown('task') self.task_widget.update() else: self.__set_shown('default') def update(self): if not self.__dirty: self.__dirty = True GLib.idle_add(self.__update) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/paned.py�������������������������������������������������������������0000664�0001750�0001750�00000021775�14035600052�016620� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2017 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from typing import Type, Optional from gi.repository import Gtk from quodlibet import config from . import add_css, gtk_version class Paned(Gtk.Paned): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ensure_wide_handle() def ensure_wide_handle(self): if gtk_version >= (3, 19): self.props.wide_handle = True add_css(self, """ paned separator { border-width: 0; min-height: 5px; min-width: 5px; background-image: none; } """) return if hasattr(self.props, "wide_handle"): # gtk 3.16 self.props.wide_handle = True add_css(self, """ GtkPaned { border-width: 0; background: none; } """) return # gtk 3.14 add_css(self, """ GtkPaned { -GtkPaned-handle-size: 6; background-image: none; margin: 0; border-width: 0; } """) class RPaned(Paned): """A Paned that supports relative (percentage) width/height setting.""" ORIENTATION: Gtk.Orientation = None def __init__(self, *args, **kwargs): if self.ORIENTATION is not None: kwargs["orientation"] = self.ORIENTATION super().__init__(*args, **kwargs) # before first alloc: save value in relative and set on the first alloc # after the first alloc: use the normal properties self.__alloced = False self.__relative = None def _get_max(self): alloc = self.get_allocation() if self.get_orientation() == Gtk.Orientation.HORIZONTAL: return alloc.width else: return alloc.height def set_relative(self, v): """Set the relative position of the separator, [0..1].""" if v < 0 or v > 1: raise ValueError("v must be in [0..1]") if self.__alloced: max_pos = self._get_max() self.set_position(int(round(v * max_pos))) else: self.__relative = v def get_relative(self): """Return the relative position of the separator, [0..1].""" if self.__alloced: rel = float(self.get_position()) / self._get_max() if 0 <= rel <= 1: return rel if self.__relative is not None: return self.__relative # before first alloc and set_relative not called return 0.5 def do_size_allocate(self, *args): ret = Gtk.HPaned.do_size_allocate(self, *args) if not self.__alloced and self.__relative is not None: self.__alloced = True self.set_relative(self.__relative) # call again so the children get alloced ret = Gtk.HPaned.do_size_allocate(self, *args) self.__alloced = True return ret class RHPaned(RPaned): ORIENTATION = Gtk.Orientation.HORIZONTAL class RVPaned(RPaned): ORIENTATION = Gtk.Orientation.VERTICAL class ConfigRPaned(RPaned): def __init__(self, section, option, default, *args, **kwargs): super().__init__(*args, **kwargs) self.set_relative(config.getfloat(section, option, default)) self.connect('notify::position', self.__changed, section, option) def __changed(self, widget, event, section, option): if self.get_property('position-set'): config.set(section, option, str(self.get_relative())) class ConfigRHPaned(ConfigRPaned): ORIENTATION = Gtk.Orientation.HORIZONTAL class ConfigRVPaned(ConfigRPaned): ORIENTATION = Gtk.Orientation.VERTICAL class MultiRPaned: """A Paned that supports an unlimited number of panes.""" # The Paned type (horizontal or vertical) PANED: Optional[Type[RPaned]] = None def __init__(self): self._root_paned = None if self.PANED is None: explanation = ("PANED is None. Do not directly" "instantiate MultiRPaned, use" "one of its subclasses.") raise AttributeError(explanation) def set_widgets(self, widgets): """Put a list of widgets in separate panes.""" # root_paned will be the root of a nested paned structure. # if we have three panes - p1, p2 and p3 - root_paned will # eventually look like this: Paned(p1, Paned(p2, p3)) self._root_paned = self.PANED() curr_paned = self._root_paned for widget in widgets: # the last widget completes the last paned if widget is widgets[-1]: curr_paned.pack2(widget, True, False) break curr_paned.pack1(widget, True, False) # the second last widget ends the nesting if widget is widgets[-2]: continue tmp_paned = self.PANED() curr_paned.pack2(tmp_paned, True, False) curr_paned = tmp_paned def get_paned(self): """Get the GTK Paned used for displaying.""" return self._root_paned def make_pane_widths_equal(self): paneds = self._get_paneds() # the relative paned widths must be equal to the reciprocal (1/i) of # their respective indices (i) in reverse order (from right to left) # to make the pane widths equal. (i + 2) because +1 from changing # from zero- to one-indexed, and +1 for compensating that the last # paned contains two panes for i, paned in enumerate(reversed(paneds)): width = min(1.0 / (i + 2), 0.5) paned.set_relative(width) def change_orientation(self, horizontal): """Change the orientation of the paned.""" hor = Gtk.Orientation.HORIZONTAL ver = Gtk.Orientation.VERTICAL for paned in self._get_paneds(): paned.props.orientation = hor if horizontal else ver def destroy(self): if self._root_paned: self._root_paned.destroy() def show_all(self): self._root_paned.show_all() def _get_paneds(self): """Get all internal paneds in a flat, ordered list.""" paneds = [self._root_paned] # gather all the paneds in the nested structure curr_paned = self._root_paned while True: child = curr_paned.get_child2() if type(child) is self.PANED: paneds.append(child) curr_paned = child else: break return paneds class MultiRHPaned(MultiRPaned): PANED = RHPaned class MultiRVPaned(MultiRPaned): PANED = RVPaned class ConfigMultiRPaned(MultiRPaned): def __init__(self, section, option): super().__init__() self.section = section self.option = option def set_widgets(self, widgets): super().set_widgets(widgets) paneds = self._get_paneds() # Connect all paneds for paned in paneds: paned.connect('notify::position', self.__changed) self._restore_widths() def save_widths(self): """Save all current paned widths.""" paneds = self._get_paneds() if len(paneds) == 1 and not paneds[0].get_child1(): # If there's only one pane (i.e. the only paned has just one # child), do not save the paned width, as this will cause # a later added second pane to get the width of the previous # second pane widths = [] else: widths = [str(p.get_relative()) for p in paneds] config.setstringlist(self.section, self.option, widths) def _restore_widths(self): """Restore pane widths from the config.""" widths = config.getstringlist(self.section, self.option, []) paneds = self._get_paneds() if not widths: # If no widths are saved, save the current widths self.__changed() else: # Restore as many widths as we have saved # (and convert them from str to float) for i, width in enumerate(map(float, widths)): if i >= len(paneds): break paneds[i].set_relative(width) self.__changed() def __changed(self, widget=None, event=None): """Callback function for individual paneds. Saves all current paned widths. Widget and event default to None, as they aren't really used. They are just required for GTK. """ self.save_widths() class ConfigMultiRHPaned(ConfigMultiRPaned): PANED = RHPaned class ConfigMultiRVPaned(ConfigMultiRPaned): PANED = RVPaned ���././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1665307309.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/playorder.py���������������������������������������������������������0000644�0001750�0001750�00000027411�14320511255�017524� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GObject from quodlibet import _ from quodlibet import config from quodlibet import qltk from quodlibet.order import Order, OrderInOrder from quodlibet.order.reorder import OrderShuffle, OrderWeighted, Reorder from quodlibet.order.repeat import RepeatListForever, RepeatSongForever, \ Repeat, OneSong from quodlibet.qltk import Icons from quodlibet.qltk.x import SymbolicIconImage, RadioMenuItem, \ SeparatorMenuItem, HighlightToggleButton from quodlibet.plugins import PluginManager from quodlibet.util.dprint import print_w, print_d class Orders(GObject.Object): """ A minimal list-like container for Order objects that signals on changes """ __gsignals__ = { 'updated': (GObject.SignalFlags.RUN_LAST, None, ()), } def __init__(self, initial=None): super().__init__() self.items = initial or [] def by_name(self, name): if not name: return None for cls in self.items: if cls.name == name: return cls return None def __getitem__(self, y): return self.items.__getitem__(y) def __len__(self): return self.items.__len__() def append(self, x): self.items.append(x) self.emit('updated') def remove(self, x): self.items.remove(x) self.emit('updated') def __contains__(self, y): return self.items.__contains__(y) def __str__(self): return "<%s of %s>" % (type(self).__name__, self.items) class PluggableOrders(Orders, PluginManager): """Registers as a Plugin Handler for various types of `Order` plugins""" def __init__(self, orders, base_cls): assert issubclass(base_cls, Order) super().__init__(orders) self.base_cls = base_cls if PluginManager.instance: PluginManager.instance.register_handler(self) else: print_w("No plugin manager found") def plugin_handle(self, plugin): return issubclass(plugin.cls, self.base_cls) def plugin_enable(self, plugin): plugin_cls = plugin.cls if plugin_cls.name is None: plugin_cls.name = plugin.name if plugin_cls.display_name is None: plugin_cls.display_name = str(plugin.name).capitalize() if plugin_cls.accelerated_name is None: plugin_cls.accelerated_name = plugin_cls.display_name self.append(plugin_cls) def plugin_disable(self, plugin): self.remove(plugin.cls) DEFAULT_SHUFFLE_ORDERS = [OrderShuffle, OrderWeighted] DEFAULT_REPEAT_ORDERS = [RepeatSongForever, RepeatListForever, OneSong] class ToggledPlayOrderMenu(Gtk.Box): """A toggle button with a menu button. Items displayed are all `PlayOrder` When the button is toggled, a `toggled` signal gets emitted. """ __gsignals__ = { 'toggled': (GObject.SignalFlags.RUN_LAST, None, ()), 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self, icon_name, orders, current_order, enabled=False, tooltip=None, arrow_down=False): """arrow_down -- the direction of the menu and arrow icon""" assert issubclass(current_order, Order) if current_order not in orders: raise ValueError("%s is not supported by %s" % (current_order.__name__, orders)) super().__init__() self.__inhibit = True context = self.get_style_context() context.add_class(Gtk.STYLE_CLASS_LINKED) self._toggle_button = toggle = HighlightToggleButton( image=SymbolicIconImage(icon_name, Gtk.IconSize.SMALL_TOOLBAR)) if tooltip: toggle.set_tooltip_text(tooltip) toggle.set_active(enabled) toggle.show_all() qltk.remove_padding(toggle) toggle.set_size_request(26, 26) self.pack_start(toggle, True, True, 0) def forward_signal(*args): if not self.__inhibit: self.emit("toggled") toggle.connect("toggled", forward_signal) self._toggle_button = toggle from quodlibet.qltk.menubutton import MenuButton arrow = MenuButton(arrow=True, down=arrow_down) arrow.show_all() arrow.set_size_request(20, 26) qltk.remove_padding(arrow) self.pack_start(arrow, True, True, 0) self._menu_button = arrow self.__current = current_order self.__orders = orders self.__rebuild_menu() self.__inhibit = False @property def enabled(self): """Returns True if toggle button is active""" return self._toggle_button.get_active() @enabled.setter def enabled(self, value): """Set button to be active or inactive""" self.__inhibit = True self._toggle_button.set_active(bool(value)) self.emit("toggled") self.__inhibit = False @property def orders(self): return self.__orders @orders.setter def orders(self, values): self.__orders = values if self.__current not in self.orders: self.__current = None # if current order has become invalid, deactivate self.enabled = False self.__rebuild_menu() @property def current(self): return self.__current @current.setter def current(self, value): if value not in self.orders: raise ValueError( "Unknown order %s. Try: %s" % (value, ", ".join([o.__name__ for o in self.__orders]))) self.__current = value if not self.__inhibit: self.emit('changed', self.__current) self.__rebuild_menu() def set_active_by_name(self, name): for cls in self.__orders: if cls.name == name: self.current = cls return raise ValueError("Unknown order named \"%s\". Try: %s" % (name, [o.name for o in self.__orders])) def set_orders(self, orders): self.orders = orders def __rebuild_menu(self): def toggled_cb(item, order): if item.get_active(): self.current = order menu = Gtk.Menu() group = None prev_priority = None def ui_sorted(items): return sorted(items, key=lambda k: (k.priority, k.display_name)) for order in ui_sorted(self.__orders): if prev_priority and order.priority > prev_priority: menu.append(SeparatorMenuItem()) prev_priority = order.priority group = RadioMenuItem( label=order.accelerated_name, use_underline=True, group=group) group.set_active(order == self.__current) group.connect("toggled", toggled_cb, order) menu.append(group) menu.show_all() self._menu_button.set_menu(menu) class PlayOrderWidget(Gtk.HBox): """A combined play order selection widget. Whenever something changes the 'changed' signal gets emitted. """ __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, ()), } def __init__(self, model, player): super().__init__(spacing=6) self.order = None self.__inhibit = True self.__playlist = model self.__player = player def create_shuffle(orders): shuffle = ToggledPlayOrderMenu( Icons.MEDIA_PLAYLIST_SHUFFLE, orders=orders, current_order=self.__get_shuffle_class(), enabled=(config.getboolean("memory", "shuffle", False)), tooltip=_("Toggle shuffle mode")) shuffle.connect('changed', self.__shuffle_updated) shuffle.connect('toggled', self.__shuffle_toggled) return shuffle self._shuffle_orders = PluggableOrders(DEFAULT_SHUFFLE_ORDERS, Reorder) self.__shuffle_widget = create_shuffle(self._shuffle_orders) self._shuffle_orders.connect('updated', self.__shuffle_widget.set_orders) def create_repeat(orders): repeat = ToggledPlayOrderMenu( Icons.MEDIA_PLAYLIST_REPEAT, orders=orders, current_order=self.__get_repeat_class(), enabled=config.getboolean("memory", "repeat", False), tooltip=_("Toggle repeat mode")) repeat.connect('changed', self.__repeat_updated) repeat.connect('toggled', self.__repeat_toggled) return repeat self._repeat_orders = PluggableOrders(DEFAULT_REPEAT_ORDERS, Repeat) self.__repeat_widget = create_repeat(self._repeat_orders) self._repeat_orders.connect('updated', self.__repeat_widget.set_orders) self.__compose_order() self.pack_start(self.__shuffle_widget, False, True, 0) self.pack_start(self.__repeat_widget, False, True, 0) self.__inhibit = False @property def shuffler(self): return self.__shuffle_widget.current @shuffler.setter def shuffler(self, cls): assert issubclass(cls, Reorder) self.__shuffle_widget.current = cls @property def repeater(self): return self.__repeat_widget.current @repeater.setter def repeater(self, cls): assert issubclass(cls, Repeat) self.__repeat_widget.current = cls @property def shuffled(self): return self.__shuffle_widget.enabled @shuffled.setter def shuffled(self, enabled): self.__shuffle_widget.enabled = bool(enabled) @property def repeated(self): return self.__repeat_widget.enabled @repeated.setter def repeated(self, enabled): self.__repeat_widget.enabled = bool(enabled) def __repeat_updated(self, widget, repeat_cls): if self.__inhibit: return print_d("New repeat mode: %s" % repeat_cls.name) config.set("memory", "repeat_mode", repeat_cls.name) self.__compose_order() def __shuffle_updated(self, widget, shuffle_cls): if self.__inhibit: return print_d("New shuffle mode: %s" % shuffle_cls.name) config.set("memory", "shuffle_mode", shuffle_cls.name) self.__compose_order() def __shuffle_toggled(self, widget): if self.__inhibit: return config.set("memory", "shuffle", widget.enabled) self.__compose_order() def __repeat_toggled(self, widget): if self.__inhibit: return config.set("memory", "repeat", widget.enabled) self.__compose_order() def __compose_order(self): old_order = self.order repeat_cls = self.__get_repeat_class() shuffle_cls = self.__get_shuffle_class() shuffler = (shuffle_cls() if self.shuffled else OrderInOrder()) self.order = repeat_cls(shuffler) if self.repeated else shuffler print_d("Updating %s order to %s" % (type(self.__playlist).__name__, self.order)) self.__playlist.order = self.order self.__player.replaygain_profiles[2] = shuffler.replaygain_profiles self.__player.reset_replaygain() if self.order != old_order: self.emit('changed') def __get_shuffle_class(self): name = config.get("memory", "shuffle_mode", None) return self._shuffle_orders.by_name(name) or OrderShuffle def __get_repeat_class(self): name = config.get("memory", "repeat_mode", None) return self._repeat_orders.by_name(name) or RepeatSongForever �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684166838.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/pluginwin.py���������������������������������������������������������0000644�0001750�0001750�00000046751�14430454266�017561� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2016-2020 Nick Boultbee # 2022 Jej@github # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango, GObject, Gdk from quodlibet import _ from quodlibet import config from quodlibet import const from quodlibet import qltk from quodlibet import util from quodlibet.plugins import PluginManager, plugin_enabled, Plugin from quodlibet.plugins.cover import CoverSourcePlugin from quodlibet.plugins.editing import EditTagsPlugin, RenameFilesPlugin from quodlibet.plugins.events import EventPlugin from quodlibet.plugins.gstelement import GStreamerPlugin from quodlibet.plugins.playlist import PlaylistPlugin from quodlibet.plugins.playorder import PlayOrderPlugin from quodlibet.plugins.query import QueryPlugin from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.qltk import Icons, is_accel, show_uri from quodlibet.qltk.entry import UndoEntry from quodlibet.qltk.models import ObjectStore, ObjectModelFilter from quodlibet.qltk.views import HintedTreeView from quodlibet.qltk.window import UniqueWindow, PersistentWindowMixin from quodlibet.qltk.x import Align, Paned, Button, ScrolledWindow from quodlibet.util import connect_obj from quodlibet.util.string.filter import remove_diacritics PLUGIN_CATEGORIES = { _("Songs"): SongsMenuPlugin, _("Playlists"): PlaylistPlugin, _("Events"): EventPlugin, _("Play Order"): PlayOrderPlugin, _("Editing"): EditTagsPlugin, _("Renaming"): RenameFilesPlugin, _("Querying"): QueryPlugin, _("Effects"): GStreamerPlugin, _("Covers"): CoverSourcePlugin } def category_of(plugin: Plugin) -> str: try: return next(cat for cat, cls in PLUGIN_CATEGORIES.items() if issubclass(plugin.cls, cls)) except StopIteration: return _("Unknown") class UndoSearchEntry(Gtk.SearchEntry, UndoEntry): pass class PluginErrorWindow(UniqueWindow): def __init__(self, parent, failures): if self.is_not_unique(): return super().__init__() self.set_title(_("Plugin Errors")) self.set_border_width(6) self.set_transient_for(parent) self.set_default_size(520, 300) scrolledwin = Gtk.ScrolledWindow() vbox = Gtk.VBox(spacing=6) vbox.set_border_width(6) scrolledwin.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolledwin.add_with_viewport(vbox) keys = failures.keys() show_expanded = len(keys) <= 3 for key in sorted(keys): expander = Gtk.Expander(label=util.bold(key)) expander.set_use_markup(True) if show_expanded: expander.set_expanded(True) # second line is always the __rescan line; don't show it message = failures[key][0:1] + failures[key][3:] failure = Gtk.Label(label=''.join(message).strip()) failure.set_alignment(0, 0) failure.set_padding(12, 6) failure.set_selectable(True) failure.set_line_wrap(True) vbox.pack_start(expander, False, True, 0) expander.add(failure) self.use_header_bar() if not self.has_close_button(): vbox2 = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) vbox2.pack_start(scrolledwin, True, True, 0) vbox2.pack_start(b, False, True, 0) self.add(vbox2) close.grab_focus() else: self.add(scrolledwin) self.get_child().show_all() class EnabledType: TAG, ALL, NO, DIS, EN, SEP = range(6) class PluginEnabledFilterCombo(Gtk.ComboBox): def __init__(self): combo_store = Gtk.ListStore(str, int) super().__init__(model=combo_store) cell = Gtk.CellRendererText() cell.props.ellipsize = Pango.EllipsizeMode.END self.pack_start(cell, True) self.add_attribute(cell, "text", 0) def combo_sep(model, iter_, data): return model[iter_][1] == EnabledType.SEP self.set_row_separator_func(combo_sep, None) def refill(self, tags, no_tags): """Fill with a sequence of tags. If no_tags is true display display the extra category for it. """ active = max(self.get_active(), 0) combo_store = self.get_model() combo_store.clear() combo_store.append([_("Any state"), EnabledType.ALL]) combo_store.append(["", EnabledType.SEP]) combo_store.append([_("Enabled"), EnabledType.EN]) combo_store.append([_("Disabled"), EnabledType.DIS]) if tags: combo_store.append(["", EnabledType.SEP]) for tag in sorted(tags): combo_store.append([tag, EnabledType.TAG]) if no_tags: combo_store.append([_("No category"), EnabledType.NO]) self.set_active(active) def get_active_row(self): iter_ = self.get_active_iter() if iter_: model = self.get_model() return list(model[iter_]) class PluginTypeFilterCombo(Gtk.ComboBox): def __init__(self): combo_store = Gtk.ListStore(str, object) super().__init__(model=combo_store) cell = Gtk.CellRendererText() cell.props.ellipsize = Pango.EllipsizeMode.END self.pack_start(cell, True) self.add_attribute(cell, "text", 0) def combo_sep(model, iter_, data): return model[iter_][1] is None self.set_row_separator_func(combo_sep, None) self.__refill() def __refill(self): """Fill with plugin types""" active = max(self.get_active(), 0) combo_store = self.get_model() combo_store.clear() combo_store.append([_("Any category"), object]) combo_store.append(["", None]) for name, cls in PLUGIN_CATEGORIES.items(): combo_store.append([name, cls]) self.set_active(active) def get_active_type(self): iter_ = self.get_active_iter() if iter_: model = self.get_model() return model[iter_][1] class PluginListView(HintedTreeView): __gsignals__ = { # model, iter, enabled "plugin-toggled": (GObject.SignalFlags.RUN_LAST, None, (object, object, bool)) } def __init__(self): super().__init__() self.set_headers_visible(False) render = Gtk.CellRendererToggle() render.set_padding(6, 3) def cell_data(col, render, model, iter_, data): plugin = model.get_value(iter_) pm = PluginManager.instance render.set_activatable(plugin.can_enable) # If it can't be enabled because it's an always-on kinda thing, # show it as enabled so it doesn't look broken. render.set_active(pm.enabled(plugin) or not plugin.can_enable) render.connect('toggled', self.__toggled) column = Gtk.TreeViewColumn("enabled", render) column.set_cell_data_func(render, cell_data) self.append_column(column) render = Gtk.CellRendererPixbuf() render.set_padding(1, 1) def cell_data2(col, render, model, iter_, data): plugin = model.get_value(iter_) icon = plugin.icon or Icons.SYSTEM_RUN render.set_property('icon-name', icon) render.set_property('stock-size', Gtk.IconSize.LARGE_TOOLBAR) column = Gtk.TreeViewColumn("image", render) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) column.set_cell_data_func(render, cell_data2) self.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) render.set_property('xalign', 0.0) render.set_padding(6, 6) column = Gtk.TreeViewColumn("name", render) def cell_data3(col, render, model, iter_, data): plugin = model.get_value(iter_) render.set_property('text', plugin.name) column.set_cell_data_func(render, cell_data3) column.set_expand(True) self.append_column(column) def do_key_press_event(self, event): if is_accel(event, "space", "KP_Space"): selection = self.get_selection() fmodel, fiter = selection.get_selected() plugin = fmodel.get_value(fiter) if plugin.can_enable: self._emit_toggled(fmodel.get_path(fiter), not plugin_enabled(plugin)) self.get_model().iter_changed(fiter) else: Gtk.TreeView.do_key_press_event(self, event) def __toggled(self, render, path): render.set_active(not render.get_active()) self._emit_toggled(path, render.get_active()) def _emit_toggled(self, path, value): model = self.get_model() iter_ = model.get_iter(path) self.emit("plugin-toggled", model, iter_, value) def select_by_plugin_id(self, plugin_id): def restore_sel(row): return row[0].id == plugin_id if not self.select_by_func(restore_sel, one=True): self.set_cursor((0,)) def refill(self, plugins): selection = self.get_selection() fmodel, fiter = selection.get_selected() model = fmodel.get_model() # get the ID of the selected plugin selected = None if fiter: plugin = fmodel.get_value(fiter) selected = plugin.id model.clear() for plugin in sorted(plugins, key=lambda x: x.name): it = model.append(row=[plugin]) if plugin.id == selected: ok, fit = fmodel.convert_child_iter_to_iter(it) selection.select_iter(fit) class PluginPreferencesContainer(Gtk.VBox): def __init__(self): super().__init__(spacing=12) self.desc = desc = Gtk.Label() desc.set_line_wrap(True) # Ensure a reasonable minimum height request for long descriptions desc.set_width_chars(30) desc.set_alignment(0, 0.5) desc.set_selectable(True) self.pack_start(desc, False, True, 0) self.prefs = prefs = Gtk.Frame() prefs.set_shadow_type(Gtk.ShadowType.NONE) self.pack_start(prefs, False, True, 0) def set_no_plugins(self): self.set_plugin(None) self.desc.set_text(_("No plugins found.")) def set_plugin(self, plugin): label = self.desc if plugin is None: label.set_markup("") else: name = util.escape(plugin.name) category = category_of(plugin).lower() text = (f"<big><b>{name}</b> " f"<span alpha='40%'> – {category}</span>" f"</big>") markup = plugin.description_markup if markup: text += f"<span font='4'>\n\n</span>{markup}" label.set_markup(text) label.connect("activate-link", show_uri) frame = self.prefs if frame.get_child(): frame.get_child().destroy() if plugin is None: frame.hide() else: instance_or_cls = plugin.get_instance() or plugin.cls if plugin and hasattr(instance_or_cls, 'PluginPreferences'): try: prefs = instance_or_cls.PluginPreferences(self) except: util.print_exc() frame.hide() else: if isinstance(prefs, Gtk.Window): b = Button(_("_Preferences"), Icons.PREFERENCES_SYSTEM) connect_obj(b, 'clicked', Gtk.Window.show, prefs) connect_obj(b, 'destroy', Gtk.Window.destroy, prefs) frame.add(b) frame.get_child().set_border_width(6) else: frame.add(prefs) frame.show_all() class PluginWindow(UniqueWindow, PersistentWindowMixin): def __init__(self, parent=None): if self.is_not_unique(): return on_top = config.getboolean("settings", "plugins_window_on_top", False) super().__init__(dialog=on_top) self.set_title(_("Plugins")) self.set_default_size(750, 500) if parent and on_top: self.set_transient_for(parent) self.set_type_hint(Gdk.WindowTypeHint.NORMAL) self.enable_window_tracking("plugin_prefs") model = ObjectStore() filter_model = ObjectModelFilter(child_model=model) self._list_view = plv = PluginListView() plv.set_model(filter_model) plv.set_rules_hint(True) plv.connect("plugin-toggled", self.__plugin_toggled) sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) sw.add(plv) sw.set_shadow_type(Gtk.ShadowType.IN) fb = Gtk.HBox(spacing=6) enabled_combo = PluginEnabledFilterCombo() enabled_combo.connect("changed", lambda s: filter_model.refilter()) enabled_combo.set_tooltip_text(_("Filter by plugin state / tag")) fb.pack_start(enabled_combo, True, True, 0) self._enabled_combo = enabled_combo type_combo = PluginTypeFilterCombo() type_combo.connect("changed", lambda s: filter_model.refilter()) type_combo.set_tooltip_text(_("Filter by plugin type")) fb.pack_start(type_combo, True, True, 0) self._type_combo = type_combo self._filter_entry = fe = UndoSearchEntry() fe.set_tooltip_text(_("Filter by plugin name or description")) fe.connect("changed", lambda s: filter_model.refilter()) errors = qltk.Button(_("Show _Errors"), Icons.DIALOG_WARNING) errors.set_focus_on_click(False) errors.connect('clicked', self.__show_errors) errors.show() errors = Align(errors, top=6, bottom=6) errors.set_no_show_all(True) bbox = Gtk.VBox() bbox.pack_start(errors, True, True, 0) pref_box = PluginPreferencesContainer() if const.DEBUG: refresh = qltk.Button(_("_Refresh"), Icons.VIEW_REFRESH) refresh.set_focus_on_click(False) refresh.connect('clicked', self.__refresh, plv, pref_box, errors, enabled_combo) bbox.pack_start(refresh, True, True, 0) filter_box = Gtk.VBox(spacing=6) filter_box.pack_start(fb, False, True, 0) filter_box.pack_start(fe, False, True, 0) vbox = Gtk.VBox() vbox.pack_start(Align(filter_box, border=6, right=-6), False, False, 0) vbox.pack_start(sw, True, True, 0) vbox.pack_start(Align(bbox, left=3, right=3, top=0), False, False, 3) paned = Paned() paned.pack1(vbox, False, False) close = qltk.Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) bb_align = Align(halign=Gtk.Align.END, valign=Gtk.Align.END) bb = Gtk.HButtonBox() bb.set_layout(Gtk.ButtonBoxStyle.END) bb.pack_start(close, True, True, 0) bb_align.add(bb) selection = plv.get_selection() selection.connect('changed', self.__selection_changed, pref_box) selection.emit('changed') right_box = Gtk.VBox() right_box.pack_start(pref_box, True, True, 0) if not self.has_close_button(): right_box.pack_start(bb_align, True, True, 0) align = Align(right_box, left=6, right=15, top=12, bottom=3) paned.pack2(align, True, False) paned.set_position(290) self.add(paned) self.__refill(plv, pref_box, errors, enabled_combo) self.connect('destroy', self.__destroy) filter_model.set_visible_func( self.__filter, (fe, enabled_combo, type_combo)) self.get_child().show_all() fe.grab_focus() restore_id = config.get("memory", "plugin_selection") plv.select_by_plugin_id(restore_id) def __filter(self, model, iter_, data): """Filter a single row""" plugin = model.get_value(iter_) if not plugin: return False entry, state_combo, type_combo = data plugin_type = type_combo.get_active_type() if not issubclass(plugin.cls, plugin_type): return False tag_row = state_combo.get_active_row() if tag_row: plugin_tags = plugin.tags tag, flag = tag_row enabled = plugin_enabled(plugin) if (flag == EnabledType.NO and plugin_tags or flag == EnabledType.TAG and tag not in plugin_tags or flag == EnabledType.EN and not enabled or flag == EnabledType.DIS and enabled): return False def matches(text, filter_): return all(p in remove_diacritics(text.lower()) for p in filter_.lower().split()) filter_ = remove_diacritics(entry.get_text()) return (matches(plugin.name, filter_) or matches(plugin.id, filter_) or matches((plugin.description or ""), filter_)) def __destroy(self, *args): config.save() def __selection_changed(self, selection, container): model, iter_ = selection.get_selected() if not iter_: container.set_plugin(None) return plugin = model.get_value(iter_) config.set("memory", "plugin_selection", plugin.id) container.set_plugin(plugin) def unfilter(self): """Clears all filters applied to the list""" self._enabled_combo.set_active(0) self._type_combo.set_active(0) self._filter_entry.set_text(u"") def move_to(self, plugin_id): def selector(r): return r[0].id == plugin_id if self._list_view.select_by_func(selector): return True else: self.unfilter() return self._list_view.select_by_func(selector) def __plugin_toggled(self, tv, model, iter_, enabled): plugin = model.get_value(iter_) pm = PluginManager.instance pm.enable(plugin, enabled) pm.save() rmodel = model.get_model() riter = model.convert_iter_to_child_iter(iter_) rmodel.row_changed(rmodel.get_path(riter), riter) def __refill(self, view, prefs, errors, state_combo): pm = PluginManager.instance # refill plugin list view.refill(pm.plugins) # get all tags and refill tag-based (state) combobox tags = set() no_tags = False for plugin in pm.plugins: if not plugin.tags: no_tags = True tags.update(plugin.tags) state_combo.refill(tags, no_tags) if not len(pm.plugins): prefs.set_no_plugins() errors.set_visible(bool(pm.failures)) def __refresh(self, activator, view, prefs, errors, state_combo): pm = PluginManager.instance pm.rescan() self.__refill(view, prefs, errors, state_combo) def __show_errors(self, activator): pm = PluginManager.instance window = PluginErrorWindow(self, pm.failures) window.show() �����������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681489057.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/prefs.py�������������������������������������������������������������0000644�0001750�0001750�00000105237�14416276241�016656� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Iñigo Serna, # Steven Robertson # 2011-2022 Nick Boultbee # 2013 Christoph Reiter # 2014 Jan Path # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gio from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet import app from quodlibet import C_, _ from quodlibet.config import RATINGS, DurationFormat, DURATION from quodlibet.qltk.ccb import ConfigSwitch as CS from quodlibet.qltk.data_editors import TagListEditor from quodlibet.qltk.entry import ValidatingEntry, UndoEntry, ClearEntry from quodlibet.query._query import Query from quodlibet.qltk.scanbox import ScanBox from quodlibet.qltk.maskedbox import MaskedBox from quodlibet.qltk.songlist import SongList, get_columns from quodlibet.qltk.window import UniqueWindow from quodlibet.qltk.x import Button, Align from quodlibet.qltk import Icons, add_css from quodlibet.util import copool, format_time_preferred from quodlibet.util.dprint import print_d from quodlibet.util.library import emit_signal, get_scan_dirs, scan_library from quodlibet.util import connect_obj MARGIN = 12 TOP_MARGIN = 3 class PreferencesWindow(UniqueWindow): """The tabbed container window for the main preferences GUI. Individual tabs are encapsulated as inner classes inheriting from `VBox`""" class SongList(Gtk.VBox): name = "songlist" PREDEFINED_TAGS = [ ("~#disc", _("_Disc")), ("~#track", _("_Track")), ("grouping", _("Grou_ping")), ("artist", _("_Artist")), ("album", _("Al_bum")), ("title", util.tag("title")), ("genre", _("_Genre")), ("date", _("_Date")), ("~basename", _("_Filename")), ("~#length", _("_Length")), ("~rating", _("_Rating")), ("~#filesize", util.tag("~#filesize"))] def __init__(self): def create_behavior_frame(): vbox = Gtk.VBox(spacing=12) jump_button = CS(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) autosort_button = CS(_("_Sort songs when tags are modified"), 'song_list', 'auto_sort', populate=True, tooltip=_("Automatically re-sort songs in " "the song list when tags are modified")) always_sortable = CS(_("Always allow sorting"), 'song_list', 'always_allow_sorting', populate=True, tooltip=_("Allow sorting by column headers, " "even for playlists etc")) def refresh_browser(*args): app.window.set_sortability() always_sortable.connect("notify::active", refresh_browser) vbox.pack_start(jump_button, False, True, 0) vbox.pack_start(always_sortable, False, True, 0) vbox.pack_start(autosort_button, False, True, 0) return qltk.Frame(_("Behavior"), child=vbox) def create_visible_columns_widgets(): buttons = {} vbox = Gtk.VBox(spacing=12) grid = Gtk.FlowBox(column_spacing=24) for i, (k, t) in enumerate(self.PREDEFINED_TAGS): buttons[k] = Gtk.CheckButton(label=t, use_underline=True) grid.add(buttons[k]) vbox.pack_start(grid, False, True, 0) # Other columns hbox = Gtk.HBox(spacing=12) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Button(_("_Edit…"), Icons.EDIT) edit_button.connect("clicked", self.__config_cols, buttons) edit_button.set_tooltip_text( _("Add or remove additional column headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) vbox.pack_start(hbox, False, True, 0) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(edit_button, True, True, 0) vbox.pack_start(b, True, True, 0) return qltk.Frame(_("Visible Columns"), child=vbox), buttons def create_columns_prefs_frame(): tiv = Gtk.Switch() aio = Gtk.Switch() aip = Gtk.Switch() fip = Gtk.Switch() self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] def pack_with_label(vb: Gtk.Box, widget: Gtk.Widget, text: str): hb = Gtk.Box(spacing=12) label = Gtk.Label(label=text, use_underline=True) hb.pack_start(label, False, False, 0) hb.pack_end(widget, False, False, 0) vb.pack_start(hb, False, False, 0) vb = Gtk.VBox(spacing=12) pack_with_label(vb, tiv, _("Title includes _version")) pack_with_label(vb, aip, _("Album includes _disc subtitle")) pack_with_label(vb, aio, _("Artist includes all _people")) pack_with_label(vb, fip, _("Filename includes _folder")) return qltk.Frame(_("Column Preferences"), child=vb) def create_update_columns_button(): apply = Button(_("_Update Columns"), Icons.VIEW_REFRESH) apply.set_tooltip_text( _("Apply current configuration to song list, " "adding new columns to the end")) apply.connect('clicked', self.__apply, buttons) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) return b super().__init__(spacing=12) # Store ordered columns self._columns = [] self.set_border_width(12) self.title = _("Song List") visible_columns_frame, buttons = create_visible_columns_widgets() self.pack_start(create_behavior_frame(), False, True, TOP_MARGIN) self.pack_start(visible_columns_frame, False, True, MARGIN) self.pack_start(create_columns_prefs_frame(), False, True, MARGIN) self.pack_start(create_update_columns_button(), False, False, 0) # Run it now self.__update(buttons, self._toggle_data, get_columns()) for child in self.get_children(): child.show_all() def __update(self, buttons, toggle_data, columns): """Updates all widgets based on the passed column list""" self._columns = columns columns = list(columns) for key, widget in buttons.items(): widget.set_active(key in columns) if key in columns: columns.remove(key) for (check, off, on) in toggle_data: if on in columns: buttons[off].set_active(True) check.set_active(True) columns.remove(on) self.others.set_text(", ".join(columns)) self.other_cols = columns def __get_current_columns(self, buttons): """Given the current column list and the widgets states compute a new column list. """ new_headers = set() # Get the checked headers for key, name in self.PREDEFINED_TAGS: if buttons[key].get_active(): new_headers.add(key) # And the customs new_headers.update(set(self.other_cols)) on_to_off = dict((on, off) for (w, off, on) in self._toggle_data) result = [] cur_cols = get_columns() for h in cur_cols: if h in new_headers: result.append(h) else: try: alternative = on_to_off[h] if alternative in new_headers: result.append(alternative) except KeyError: pass # Add new ones, trying to preserve order for new in new_headers - set(result): try: idx = self._columns.index(new) except ValueError: idx = len(self._columns) result.insert(idx, new) # After this, do the substitutions for (check, off, on) in self._toggle_data: if check.get_active(): try: result[result.index(off)] = on except ValueError: pass return result def __apply(self, button, buttons): result = self.__get_current_columns(buttons) SongList.set_all_column_headers(result) def __config_cols(self, button, buttons): def __closed(widget): self.__update(buttons, self._toggle_data, widget.tags) columns = self.__get_current_columns(buttons) m = TagListEditor(_("Edit Columns"), columns) m.set_transient_for(qltk.get_top_parent(self)) m.connect('destroy', __closed) m.show() class Browsers(Gtk.VBox): name = "browser" def __init__(self): def create_display_frame(): vbox = Gtk.VBox(spacing=MARGIN) model = Gtk.ListStore(str, str) def on_changed(combo): it = combo.get_active_iter() if it is None: return DURATION.format = model[it][0] app.window.songlist.info.refresh() app.window.qexpander.refresh() # TODO: refresh info windows ideally too (but see #2019) def draw_duration(column, cell, model, it, data): df, example = model[it] cell.set_property('text', example) for df in sorted(DurationFormat.values): # 4954s == longest ever CD, FWIW model.append([df, format_time_preferred(4954, df)]) duration = Gtk.ComboBox(model=model) cell = Gtk.CellRendererText() duration.pack_start(cell, True) duration.set_cell_data_func(cell, draw_duration, None) index = sorted(DurationFormat.values).index(DURATION.format) duration.set_active(index) duration.connect('changed', on_changed) hbox = Gtk.HBox(spacing=MARGIN) label = Gtk.Label(label=_("Duration totals") + ":", use_underline=True) label.set_mnemonic_widget(duration) hbox.pack_start(label, False, True, 0) hbox.pack_start(duration, False, True, 0) vbox.pack_start(hbox, False, True, 0) return qltk.Frame(_("Display"), child=vbox) def create_search_frame(): vb = Gtk.VBox(spacing=MARGIN) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.validator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) vb.pack_start(hbox_for(l, e), False, True, 0) # Translators: The heading of the preference group, no action return qltk.Frame(C_("heading", "Search"), child=vb) super().__init__(spacing=MARGIN) self.set_border_width(MARGIN) self.title = _("Browsers") self.pack_start(create_search_frame(), False, True, TOP_MARGIN) self.pack_start(create_display_frame(), False, True, MARGIN) # Ratings c1 = CS(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CS(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=MARGIN) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, MARGIN) vb = Gtk.VBox(spacing=MARGIN) # Filename choice algorithm config sw = CS(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(sw, False, True, 0) preferred_image_filename_tooltip = _( "The album art image file(s) to use when available " "(supports wildcards). If you want to supply more " "than one, separate them with commas.") sw = CS(_("_Preferred fixed image filename(s)"), 'albumart', 'force_filename', populate=True, tooltip=preferred_image_filename_tooltip) vb.pack_start(sw, False, True, 0) entry = UndoEntry() entry.set_tooltip_text(preferred_image_filename_tooltip) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(sw.get_active()) sw.connect('notify::active', self.__activated_force_filename, entry) self.__activated_force_filename(sw, None, entry) hb = Gtk.Box() entry.set_size_request(250, -1) hb.pack_start(entry, False, True, 12) vb.pack_start(hb, False, False, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, MARGIN) for child in self.get_children(): child.show_all() def __changed_text(self, entry, name): config.set('albumart', name, entry.get_text()) def __activated_force_filename(self, switch, state, fn_entry): fn_entry.set_sensitive(switch.get_active()) def _entry(self, entry, name, section="settings"): config.set(section, name, entry.get_text()) class Player(Gtk.VBox): name = "playback" def _gain_scale_for(self, adj: Gtk.Adjustment) -> Gtk.Scale: def format_gain(scale, value): return f"{value:.0f} dB" scale = Gtk.Scale.new(Gtk.Orientation.HORIZONTAL, adj) scale.set_hexpand(True) scale.set_show_fill_level(True) scale.set_property("round-digits", 0) scale.set_value_pos(Gtk.PositionType.LEFT) scale.connect('format-value', format_gain) return scale def __init__(self): super().__init__(spacing=MARGIN) self.set_border_width(12) self.title = _("Playback") self.pack_start(self.create_behavior_frame(), False, True, TOP_MARGIN) # player backend if app.player and hasattr(app.player, 'PlayerPreferences'): player_prefs = app.player.PlayerPreferences() f = qltk.Frame(_("Output Configuration"), child=player_prefs) self.pack_start(f, False, True, MARGIN) fallback_gain = config.getfloat("player", "fallback_gain", 0.0) adj = Gtk.Adjustment.new(fallback_gain, -12.0, 6.0, 0.5, 1, 0.0) adj.connect('value-changed', self.__changed, 'player', 'fallback_gain') fb_scale = self._gain_scale_for(adj) fb_scale.set_tooltip_text(_("If no Replay Gain information is available " "for a song, scale the volume by this value")) fb_label = Gtk.Label(label=_("_Fall-back gain:")) fb_label.set_use_underline(True) fb_label.set_alignment(0, 0.5) fb_label.set_mnemonic_widget(fb_scale) pre_amp_gain = config.getfloat("player", "pre_amp_gain", 0.0) adj = Gtk.Adjustment.new(pre_amp_gain, -12, 12, 0.5, 1, 0) adj.connect('value-changed', self.__changed, 'player', 'pre_amp_gain') pre_scale = self._gain_scale_for(adj) pre_scale.set_tooltip_text(_("Scale volume for all songs by this value, " "as long as the result will not clip")) pre_label = Gtk.Label(label=_("_Pre-amp gain:")) pre_label.set_use_underline(True) pre_label.set_alignment(0, 0.5) pre_label.set_mnemonic_widget(pre_scale) widgets = [pre_label, pre_scale, fb_label, fb_scale] enable_rg = CS(_("_Enable Replay Gain volume adjustment"), "player", "replaygain", populate=True) enable_rg.connect('notify::active', self.__activated_gain, widgets) self.__activated_gain(enable_rg, None, widgets) # packing vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) vb.pack_start(enable_rg, False, False, 0) grid = Gtk.Grid(column_spacing=6, row_spacing=3) grid.attach(fb_label, 0, 0, 1, 1) grid.attach(fb_scale, 1, 0, 1, 1) grid.attach(pre_label, 0, 1, 1, 1) grid.attach(pre_scale, 1, 1, 1, 1) hb = Gtk.Box() hb.pack_start(grid, True, True, 12) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Replay Gain Volume Adjustment"), child=vb) self.pack_start(f, False, True, MARGIN) for child in self.get_children(): child.show_all() def create_behavior_frame(self): vbox = Gtk.VBox() continue_play = CS(_("_Continue playback on startup"), "player", "restore_playing", populate=True, tooltip=_( "If music is playing on shutdown, automatically " "start playing on next startup")) vbox.pack_start(continue_play, False, False, 0) return qltk.Frame(_("Behavior"), child=vbox) def __activated_gain(self, activator, state, widgets): if app.player: # tests app.player.reset_replaygain() for widget in widgets: widget.set_sensitive(activator.get_active()) def __changed(self, adj, section, name): config.set(section, name, str(adj.get_value())) app.player.reset_replaygain() class Tagging(Gtk.VBox): name = "tagging" def ratings_vbox(self): """Returns a new VBox containing all ratings widgets""" vb = Gtk.VBox(spacing=12) # Default Rating model = Gtk.ListStore(float) default_combo = Gtk.ComboBox(model=model) default_lab = Gtk.Label(label=_("_Default rating:")) default_lab.set_use_underline(True) default_lab.set_alignment(0, 0.5) def draw_rating(column, cell, model, it, data): num = model[it][0] text = "%0.2f: %s" % (num, util.format_rating(num)) cell.set_property('text', text) def default_rating_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.default = model[it][0] qltk.redraw_all_toplevels() def populate_default_rating_model(combo, num): model = combo.get_model() model.clear() deltas = [] default = RATINGS.default precision = RATINGS.precision for i in range(0, num + 1): r = i * precision model.append(row=[r]) deltas.append((abs(default - r), i)) active = sorted(deltas)[0][1] print_d("Choosing #%d (%.2f), closest to current %.2f" % (active, precision * active, default)) combo.set_active(active) cell = Gtk.CellRendererText() default_combo.pack_start(cell, True) default_combo.set_cell_data_func(cell, draw_rating, None) default_combo.connect('changed', default_rating_changed, model) default_lab.set_mnemonic_widget(default_combo) def refresh_default_combo(num): populate_default_rating_model(default_combo, num) # Rating Scale model = Gtk.ListStore(int) scale_combo = Gtk.ComboBox(model=model) scale_lab = Gtk.Label(label=_("Rating _scale:")) scale_lab.set_use_underline(True) scale_lab.set_mnemonic_widget(scale_combo) cell = Gtk.CellRendererText() scale_combo.pack_start(cell, False) num = RATINGS.number for i in [1, 2, 3, 4, 5, 6, 8, 10]: it = model.append(row=[i]) if i == num: scale_combo.set_active_iter(it) def draw_rating_scale(column, cell, model, it, data): num_stars = model[it][0] text = "%d: %s" % (num_stars, RATINGS.full_symbol * num_stars) cell.set_property('text', text) def rating_scale_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.number = num = model[it][0] refresh_default_combo(num) refresh_default_combo(RATINGS.number) scale_combo.set_cell_data_func(cell, draw_rating_scale, None) scale_combo.connect('changed', rating_scale_changed, model) default_align = Align(halign=Gtk.Align.START) default_align.add(default_lab) scale_align = Align(halign=Gtk.Align.START) scale_align.add(scale_lab) grid = create_grid() grid.add(scale_align) grid.add(scale_combo) grid.attach(default_align, 0, 1, 1, 1) grid.attach(default_combo, 1, 1, 1, 1) vb.pack_start(grid, False, False, 12) # Bayesian Factor bayesian_factor = config.getfloat("settings", "bayesian_rating_factor", 0.0) adj = Gtk.Adjustment.new(bayesian_factor, 0.0, 10.0, 0.5, 0.5, 0.0) bayes_spin = Gtk.SpinButton(adjustment=adj, numeric=True) bayes_spin.set_digits(1) bayes_spin.connect('changed', self.__changed_and_signal_library, 'settings', 'bayesian_rating_factor') bayes_spin.set_tooltip_text( _("Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that " "albums with few tracks will have less extreme ratings. " "Changing this value triggers a re-calculation for all " "albums.")) bayes_label = Gtk.Label(label=_("_Bayesian averaging amount:")) bayes_label.set_use_underline(True) bayes_label.set_mnemonic_widget(bayes_spin) # Save Ratings vb.pack_start(hbox_for(bayes_label, bayes_spin, False), True, True, 0) sw = CS(_("Save ratings and play _counts in tags"), "editing", "save_to_songs", populate=True) def update_entry(widget, state, email_entry): email_entry.set_sensitive(widget.get_active()) vb.pack_start(sw, True, True, 0) lab = Gtk.Label(label=_("_Email:")) entry = UndoEntry() entry.set_tooltip_text(_("Ratings and play counts will be saved " "in tags for this email address")) entry.set_text(config.get("editing", "save_email")) entry.connect('changed', self.__changed, 'editing', 'save_email') # Disable the entry if not saving to tags sw.connect('notify::active', update_entry, entry) update_entry(sw, None, entry) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb.pack_start(hbox_for(lab, entry), True, True, 0) return vb def tag_editing_vbox(self): """Returns a new VBox containing all tag editing widgets""" vbox = Gtk.VBox(spacing=12) sw = CS(_("_Auto-save tag changes"), 'editing', 'auto_save_changes', populate=True, tooltip=_("Save changes to tags without confirmation " "when editing multiple files")) vbox.pack_start(sw, False, False, 0) def revert_split(entry, button, _, section, option): config.reset(section, option) entry.set_text(config.get(section, option)) split_entry = ClearEntry() gicon = Gio.ThemedIcon.new_from_names(["edit-clear-symbolic", "edit-clear"]) split_entry.set_icon_from_gicon(Gtk.EntryIconPosition.SECONDARY, gicon) split_entry.connect("icon-release", revert_split, "editing", "split_on") split_entry.set_text(config.get("editing", "split_on")) split_entry.connect('changed', self.__changed, 'editing', 'split_on') split_entry.set_tooltip_text( _("A set of separators to use when splitting tag values " "in the tag editor. " "The list is space-separated.")) split_label = Gtk.Label(label=_("Split _tag on:")) split_label.set_use_underline(True) split_label.set_mnemonic_widget(split_entry) vbox.pack_start(hbox_for(split_label, split_entry), False, False, 0) sub_entry = ClearEntry() sub_entry.enable_clear_button() sub_entry.set_text(config.get("editing", "sub_split_on")) sub_entry.connect('changed', self.__changed, 'editing', 'sub_split_on') sub_entry.connect("icon-release", revert_split, "editing", "sub_split_on") sub_entry.set_tooltip_text( _("A set of separators to use when extracting subtags from " "tags in the tag editor. " "The list is space-separated, and each entry must only " "contain two characters.")) sub_label = Gtk.Label(label=_("Split _subtag on:")) sub_label.set_use_underline(True) sub_label.set_mnemonic_widget(split_entry) vbox.pack_start(hbox_for(sub_label, sub_entry), False, False, 0) return vbox def __init__(self): super().__init__(spacing=MARGIN) self.set_border_width(12) self.title = _("Tags") self._songs = [] f = qltk.Frame(_("Tag Editing"), child=(self.tag_editing_vbox())) self.pack_start(f, False, True, TOP_MARGIN) f = qltk.Frame(_("Ratings"), child=self.ratings_vbox()) self.pack_start(f, False, True, MARGIN) for child in self.get_children(): child.show_all() def __changed(self, entry, section, name): config.set(section, name, entry.get_text()) def __changed_and_signal_library(self, entry, section, name): config.set(section, name, str(entry.get_value())) print_d("Signalling \"changed\" to entire library. Hold tight...") # Cache over clicks self._songs = self._songs or list(app.library.values()) copool.add(emit_signal, self._songs, funcid="library changed", name=_("Updating for new ratings")) class Library(Gtk.VBox): name = "library" def __init__(self): super().__init__(spacing=MARGIN) self.set_border_width(12) self.title = _("Library") def refresh_cb(button): scan_library(app.library, force=False) refresh = qltk.Button(_("_Scan Library"), Icons.VIEW_REFRESH) refresh.connect("clicked", refresh_cb) refresh.set_tooltip_text(_("Check for changes in your library")) def reload_cb(button): scan_library(app.library, force=True) reload_ = qltk.Button(_("Re_build Library"), Icons.DOCUMENT_NEW) reload_.connect("clicked", reload_cb) reload_.set_tooltip_text( _("Reload all songs in your library. " "This can take a long time.")) vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) hbox = Gtk.Box() hbox.pack_end(reload_, False, True, 0) hbox.pack_end(refresh, False, True, 12) vb.pack_start(hbox, False, True, 0) self.pack_start(self.create_behavior_frame(), False, False, TOP_MARGIN) self.pack_start(self.create_scandirs_frame(), False, True, MARGIN) # during testing if app.library is not None: masked = MaskedBox(app.library) f = qltk.Frame(_("Hidden Songs"), child=masked) self.pack_start(f, False, True, 12) for child in self.get_children(): child.show_all() def create_behavior_frame(self): vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) scan_at_start_sw = CS(_("Scan library _on start"), "library", "refresh_on_start", populate=True) req_restart = _("A restart is required for any changes to take effect") watch_lib_sw = CS( _("_Watch directories for changes"), "library", "watch", populate=True, tooltip=_("Watch library directories for external file additions, " "deletions and renames.") + "\n" + req_restart) vb.pack_start(watch_lib_sw, False, True, 0) vb.pack_start(scan_at_start_sw, False, True, 0) return qltk.Frame(_("Behavior"), child=vb) def create_scandirs_frame(self): vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) scan_dirs = ScanBox() vb.pack_start(scan_dirs, True, True, 0) f = qltk.Frame(_("Scan Directories"), child=vb) return f def __init__(self, parent, open_page=None, all_pages=True): if self.is_not_unique(): return super().__init__() self.current_scan_dirs = get_scan_dirs() self.set_title(_("Preferences")) self.set_resizable(True) self.set_transient_for(qltk.get_top_parent(parent)) self.__notebook = notebook = qltk.Notebook() add_css(notebook, "tab { padding: 6px 24px } ") pages = [self.Tagging] if all_pages: pages = [self.SongList, self.Browsers, self.Player, self.Library] + pages for Page in pages: page = Page() page.show() notebook.append_page(page) if open_page in [page.name for page in pages]: self.set_page(open_page) else: page_name = config.get("memory", "prefs_page", "") self.set_page(page_name) def on_switch_page(notebook, page, page_num): config.set("memory", "prefs_page", page.name) notebook.connect("switch-page", on_switch_page) close = Button(_("_Close"), Icons.WINDOW_CLOSE) connect_obj(close, 'clicked', lambda x: x.destroy(), self) button_box = Gtk.HButtonBox() button_box.set_layout(Gtk.ButtonBoxStyle.END) button_box.pack_start(close, True, True, 0) self.use_header_bar() if self.has_close_button(): self.set_border_width(0) notebook.set_show_border(False) self.add(notebook) else: self.set_border_width(12) vbox = Gtk.VBox(spacing=12) vbox.pack_start(notebook, True, True, 0) vbox.pack_start(button_box, False, True, 0) self.add(vbox) connect_obj(self, 'destroy', PreferencesWindow.__destroy, self) self.get_child().show_all() def set_page(self, name): notebook = self.__notebook for p in range(notebook.get_n_pages()): if notebook.get_nth_page(p).name == name: notebook.set_current_page(p) def __destroy(self): config.save() new_dirs = set(get_scan_dirs()) gone_dirs = set(self.current_scan_dirs) - new_dirs if new_dirs - set(self.current_scan_dirs): print_d("Library paths have been added, re-scanning...") scan_library(app.library, force=False) elif gone_dirs: copool.add(app.librarian.remove_roots, gone_dirs) def create_grid(column_spacing: int = 12, row_spacing: int = 6): table = Gtk.Grid(row_spacing=row_spacing, column_spacing=column_spacing) return table def hbox_for(label: Gtk.Label, entry: Gtk.Entry, expand_entry: bool = True) -> Gtk.Box: hb = Gtk.Box(spacing=12) hb.pack_start(label, False, False, 0) hb.pack_end(entry, expand_entry, True, 0) return hb �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/properties.py��������������������������������������������������������0000664�0001750�0001750�00000015423�14035600052�017716� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Nick Boultbee # 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GObject, Pango from senf import fsn2text from quodlibet import ngettext, _ from quodlibet import qltk from quodlibet import config from quodlibet.qltk.edittags import EditTags from quodlibet.qltk.renamefiles import RenameFiles from quodlibet.qltk.tagsfrompath import TagsFromPath from quodlibet.qltk.tracknumbers import TrackNumbers from quodlibet.qltk.views import HintedTreeView from quodlibet.qltk.window import PersistentWindowMixin from quodlibet.qltk.x import ScrolledWindow, ConfigRPaned from quodlibet.qltk.models import ObjectStore, ObjectModelSort from quodlibet.qltk.msg import CancelRevertSave from quodlibet.util import connect_destroy, cmp class _ListEntry: def __init__(self, song): self.song = song @property def name(self): return fsn2text(self.song("~basename")) class SongProperties(qltk.Window, PersistentWindowMixin): __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)) } def __init__(self, library, songs, parent=None): super().__init__(dialog=False) self.set_transient_for(qltk.get_top_parent(parent)) default_width = 600 config_suffix = "" if len(songs) <= 1: default_width -= 200 config_suffix += "single" self.set_default_size(default_width, 400) self.enable_window_tracking("quodlibet_properties", size_suffix=config_suffix) self.auto_save_on_change = config.getboolean( 'editing', 'auto_save_changes', False) paned = ConfigRPaned("memory", "quodlibet_properties_pos", 0.4) notebook = qltk.Notebook() notebook.props.scrollable = True pages = [] pages.extend([Ctr(self, library) for Ctr in [EditTags, TagsFromPath, RenameFiles]]) if len(songs) > 1: pages.append(TrackNumbers(self, library)) for page in pages: page.show() notebook.append_page(page) fbasemodel = ObjectStore() fmodel = ObjectModelSort(model=fbasemodel) fview = HintedTreeView(model=fmodel) fview.connect('button-press-event', self.__pre_selection_changed) fview.set_rules_hint(True) selection = fview.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self.__save = None render = Gtk.CellRendererText() c1 = Gtk.TreeViewColumn(_('File'), render) if fview.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) render.set_property('xpad', 3) def cell_data(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property('text', entry.name) c1.set_cell_data_func(render, cell_data) def sort_func(model, a, b, data): a = model.get_value(a) b = model.get_value(b) return cmp(a.name, b.name) fmodel.set_sort_func(100, sort_func) c1.set_sort_column_id(100) fview.append_column(c1) sw = ScrolledWindow() sw.add(fview) sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) # only show the list if there are is more than one song if len(songs) > 1: sw.show_all() paned.pack1(sw, shrink=False, resize=True) for song in songs: fbasemodel.append(row=[_ListEntry(song)]) self.connect("changed", self.__on_changed) selection.select_all() paned.pack2(notebook, shrink=False, resize=True) csig = selection.connect('changed', self.__selection_changed) connect_destroy(library, 'changed', self.__on_library_changed, fbasemodel, fview) connect_destroy(library, 'removed', self.__on_library_removed, fbasemodel, selection, csig) self.emit('changed', songs) self.add(paned) paned.set_position(175) notebook.show() paned.show() def __on_library_removed(self, library, songs, model, selection, sig): selection.handler_block(sig) rows = selection.get_selected_rows()[1] to_remove = [] changed = False for row in model: if row[0].song in songs: to_remove.append(row.iter) changed = changed or (row.path in rows) for iter_ in to_remove: model.remove(iter_) selection.handler_unblock(sig) if changed: selection.emit('changed') def __on_changed(self, widget, songs): if songs: if len(songs) == 1: title = songs[0].comma("title") else: title = ngettext( "%(title)s and %(count)d more", "%(title)s and %(count)d more", len(songs) - 1) % {'title': songs[0].comma("title"), 'count': len(songs) - 1} self.set_title("%s - %s" % (title, _("Properties"))) else: self.set_title(_("Properties")) self.set_pending(None) def __on_library_changed(self, library, songs, model, view): # in case the library changes, sync the model and emit # selection changed if one of the selected was changed paths = view.get_selection().get_selected_rows()[1] changed = False for row in model: song = row[0].song if song in songs: model.row_changed(row.path, row.iter) changed = changed or (row.path in paths) if changed: view.get_selection().emit('changed') def set_pending(self, button, *excess): self.__save = button def __pre_selection_changed(self, view, event): if self.__save: if self.auto_save_on_change: self.__save.clicked() return resp = CancelRevertSave(self).run() if resp == Gtk.ResponseType.YES: self.__save.clicked() elif resp == Gtk.ResponseType.NO: return False else: return True # cancel or closed def __selection_changed(self, selection): model = selection.get_tree_view().get_model() model, paths = selection.get_selected_rows() songs = [model[path][0].song for path in paths] self.emit('changed', songs) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681489057.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/queue.py�������������������������������������������������������������0000644�0001750�0001750�00000043426�14416276241�016664� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2016-2023 Nick Boultbee # 2017 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. import os import time from typing import Any, Optional, Sequence from gi.repository import Gtk, Gdk, Pango, GLib from quodlibet.library.base import Library from quodlibet.player._base import BasePlayer from senf import bytes2fsn, fsn2bytes import quodlibet from quodlibet import ngettext, _, print_e, print_w, print_d from quodlibet import config from quodlibet import qltk from quodlibet import app from quodlibet.util import (connect_destroy, connect_after_destroy, format_time_preferred, print_exc, DeferredSignal) from quodlibet.qltk import Icons, gtk_version, add_css from quodlibet.qltk.ccb import ConfigCheckMenuItem from quodlibet.qltk.songlist import SongList, DND_QL, DND_URI_LIST from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.menubutton import SmallMenuButton from quodlibet.qltk.songmodel import PlaylistModel from quodlibet.qltk.playorder import OrderInOrder, OrderShuffle from quodlibet.qltk.x import ScrolledWindow, SymbolicIconImage, \ SmallImageButton, SmallImageToggleButton, MenuItem, RadioMenuItem from quodlibet.qltk.songlistcolumns import CurrentColumn QUEUE = os.path.join(quodlibet.get_user_dir(), "queue") class PlaybackStatusIcon(Gtk.Box): """A widget showing a play/pause/stop symbolic icon""" def __init__(self): super().__init__() self._icons = {} def _set(self, name): if name not in self._icons: image = SymbolicIconImage(name, Gtk.IconSize.MENU) self._icons[name] = image image.show() else: image = self._icons[name] children = self.get_children() if children: self.remove(children[0]) self.add(image) def play(self): self._set("media-playback-start") def stop(self): self._set("media-playback-stop") def pause(self): self._set("media-playback-pause") class ExpandBoxHack(Gtk.HBox): def do_get_preferred_width(self): # Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=765602 # set_label_fill() no longer works since 3.20. Fake a natural size # which is larger than the expander can be to force the parent to # allocate to us the whole space. min_, nat = Gtk.HBox.do_get_preferred_width(self) if gtk_version > (3, 19): # if we get too large gtk calcs will overflow.. nat = max(nat, 2 ** 16) return (min_, nat) class QueueExpander(Gtk.Expander): def __init__(self, library, player): super().__init__(spacing=3) sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) save_interval_secs = config.getint("autosave", "queue_interval") self.queue = PlayQueue(library, player, save_interval_secs) self.queue.props.expand = True sw.add(self.queue) add_css(self, ".ql-expanded title { margin-bottom: 5px; }") outer = ExpandBoxHack() left = Gtk.HBox(spacing=12) hb2 = Gtk.HBox(spacing=3) state_icon = PlaybackStatusIcon() state_icon.stop() state_icon.show() hb2.pack_start(state_icon, True, True, 0) name_label = Gtk.Label(label=_("_Queue"), use_underline=True) name_label.set_size_request(-1, 24) hb2.pack_start(name_label, True, True, 0) left.pack_start(hb2, False, True, 0) menu = Gtk.Menu() self.count_label = count_label = Gtk.Label() self.count_label.set_property("ellipsize", Pango.EllipsizeMode.END) self.count_label.set_width_chars(10) self.count_label.get_style_context().add_class("dim-label") left.pack_start(count_label, False, True, 0) outer.pack_start(left, True, True, 0) self.set_label_fill(True) clear_item = SmallImageButton( image=SymbolicIconImage(Icons.USER_TRASH, Gtk.IconSize.MENU), relief=Gtk.ReliefStyle.NONE, tooltip_text=_("Clear Queue")) clear_item.connect("clicked", self.__clear_queue) outer.pack_start(clear_item, False, False, 3) toggle = SmallImageToggleButton( image=SymbolicIconImage(Icons.SYSTEM_LOCK_SCREEN, Gtk.IconSize.MENU), relief=Gtk.ReliefStyle.NONE, tooltip_text=_( "Disable queue - the queue will be ignored when playing")) disabled = config.getboolean("memory", "queue_disable", False) toggle.props.active = disabled self.__queue_disable(disabled) toggle.connect('toggled', lambda b: self.__queue_disable(b.props.active)) outer.pack_start(toggle, False, False, 3) mode_menu = Gtk.Menu() norm_mode_item = RadioMenuItem( label=_("Ephemeral"), tooltip_text=_("Remove songs from the queue after playing them"), group=None) mode_menu.append(norm_mode_item) norm_mode_item.set_active(True) norm_mode_item.connect("toggled", lambda _: self.__keep_songs_enable(False)) keep_mode_item = RadioMenuItem( label=_("Persistent"), tooltip_text=_("Keep songs in the queue after playing them"), group=norm_mode_item) mode_menu.append(keep_mode_item) keep_mode_item.connect("toggled", lambda b: self.__keep_songs_enable(True)) keep_mode_item.set_active( config.getboolean("memory", "queue_keep_songs", False)) mode_item = MenuItem(_("Mode"), Icons.SYSTEM_RUN) mode_item.set_submenu(mode_menu) menu.append(mode_item) rand_checkbox = ConfigCheckMenuItem( _("_Random"), "memory", "shufflequeue", populate=True) rand_checkbox.connect('toggled', self.__queue_shuffle) self.set_shuffled(rand_checkbox.get_active()) menu.append(rand_checkbox) stop_checkbox = ConfigCheckMenuItem( _("Stop at End"), "memory", "queue_stop_at_end", populate=True) menu.append(stop_checkbox) button = SmallMenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_relief(Gtk.ReliefStyle.NORMAL) button.show_all() button.hide() button.set_no_show_all(True) menu.show_all() button.set_menu(menu) outer.pack_start(button, False, False, 3) close_button = SmallImageButton( image=SymbolicIconImage("window-close", Gtk.IconSize.MENU), relief=Gtk.ReliefStyle.NONE) close_button.connect("clicked", lambda *x: self.hide()) outer.pack_start(close_button, False, False, 6) self.set_label_widget(outer) self.add(sw) self.connect('notify::expanded', self.__expand, button) self.connect('notify::expanded', self.__expand, button) targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) self.connect('drag-motion', self.__motion) self.connect('drag-data-received', self.__drag_data_received) self.queue.model.connect_after('row-inserted', DeferredSignal(self.__check_expand), count_label) self.queue.model.connect_after('row-deleted', DeferredSignal(self.__update_count), count_label) self.__update_count(self.model, None, count_label) connect_destroy( player, 'song-started', self.__update_state_icon, state_icon) connect_destroy( player, 'paused', self.__update_state_icon_pause, state_icon, True) connect_destroy( player, 'unpaused', self.__update_state_icon_pause, state_icon, False) connect_destroy( player, 'song-started', self.__song_started, self.queue.model) connect_destroy( player, 'song-ended', self.__update_queue_stop, self.queue.model) # to make the children clickable if mapped # ....no idea why, but works def hack(expander): label = expander.get_label_widget() if label: label.unmap() label.map() self.connect("map", hack) self.set_expanded(config.getboolean("memory", "queue_expanded")) self.notify("expanded") for child in self.get_children(): child.show_all() @property def model(self): return self.queue.model def refresh(self): self.__update_count(self.model, None, self.count_label) def __update_state_icon(self, player, song, state_icon): if self.model.sourced: state_icon.play() else: state_icon.stop() def __update_state_icon_pause(self, player, state_icon, paused): if self.model.sourced: if paused: state_icon.pause() else: state_icon.play() else: state_icon.stop() def __clear_queue(self, activator): self.model.clear() def __keep_songs_enable(self, enabled): config.set("memory", "queue_keep_songs", enabled) if enabled: self.queue.set_first_column_type(CurrentColumn) else: for col in self.queue.get_columns(): # Remove the CurrentColum if it exists if isinstance(col, CurrentColumn): self.queue.set_first_column_type(None) break def __motion(self, wid, context, x, y, time): Gdk.drag_status(context, Gdk.DragAction.COPY, time) return True def __update_count(self, model, path, lab): if len(model) == 0: text = "" else: time = sum([row[0].get("~#length", 0) for row in model]) text = ngettext("%(count)d song (%(time)s)", "%(count)d songs (%(time)s)", len(model)) % { "count": len(model), "time": format_time_preferred(time)} lab.set_text(text) def __check_expand(self, model, path, iter, lab): self.__update_count(model, path, lab) self.show() def __drag_data_received(self, expander, *args): self.queue.emit('drag-data-received', *args) def __queue_shuffle(self, button): self.set_shuffled(button.get_active()) def set_shuffled(self, is_shuffled): self.queue.model.order = (OrderShuffle() if is_shuffled else OrderInOrder()) def __update_queue_stop(self, player, song, stopped, model): enabled = config.getboolean("memory", "queue_stop_at_end", False) songs_left = len(model.get()) if (enabled and not stopped and songs_left == 0 and self._queue_sourced): app.player.stop() def __song_started(self, player, song, model): self._queue_sourced = model.sourced def __expand(self, widget, prop, menu_button): expanded = self.get_expanded() style_context = self.get_style_context() if expanded: style_context.add_class("ql-expanded") else: style_context.remove_class("ql-expanded") menu_button.set_property('visible', expanded) config.set("memory", "queue_expanded", str(expanded)) def __queue_disable(self, disabled): config.set("memory", "queue_disable", disabled) self.queue.set_sensitive(not disabled) class QueueModel(PlaylistModel): """ A play list model for queues. In contrast to `PlaylistModel`, when new songs have been set, its play order will disregard the current song from the old set of songs and start from scratch. """ __reset = False def set(self, songs: Sequence[Any]): self.__reset = True super().set(songs) def next(self): print_d(f"Using {self.order}.next_explicit() to get next song") iter_ = None if self.__reset else self.current_iter self.__reset = False self.current_iter = self.order.next_explicit(self, iter_) def previous(self): iter_ = None if self.__reset else self.current_iter self.__reset = False self.current_iter = self.order.previous_explicit(self, iter_) def go_to(self, song_or_iter, explicit=False, source=None): self.__reset = False return super().go_to(song_or_iter, explicit, source) class PlayQueue(SongList): _activated = False _MAX_PENDING = 5 """Maximum number of queue items to leave unpersisted (batching)""" def __init__(self, library: Library, player: BasePlayer, autosave_interval_secs: Optional[int] = None): super().__init__(library, player, model_cls=QueueModel, sortable=False) self._updated_time = time.time() self.autosave_interval = autosave_interval_secs self._pending = 0 keep_song = config.getboolean("memory", "queue_keep_songs", False) if keep_song: self.set_first_column_type(CurrentColumn) self.set_size_request(-1, 120) self.connect('row-activated', self.__go_to, player) def reset_activated(*args): self._activated = False connect_after_destroy(player, 'song-started', reset_activated) self.connect('popup-menu', self.__popup, library) self.enable_drop() def write(*args, **kwargs): self._write(self, self.model) return True self.connect('destroy', self.__destroy) if self.autosave_interval: self._tid = GLib.timeout_add(self.autosave_interval * 1000, write) else: self._tid = None connect_after_destroy(self.model, "row-inserted", write) connect_after_destroy(self.model, "row-deleted", write) self.__fill(library) self.connect('key-press-event', self.__delete_key_pressed) def __destroy(self, widget): self._write(widget, self.model, force=True) if self._tid: GLib.source_remove(self._tid) self._tid = None print_d("Stopped autosave") def __delete_key_pressed(self, widget, event): if qltk.is_accel(event, "Delete"): self.__remove() return True return False def __go_to(self, view, path, column, player): self._activated = True if player.go_to(self.model.get_iter(path), explicit=True, source=self.model): player.paused = False def __fill(self, library): try: with open(QUEUE, "rb") as f: lines = f.readlines() except EnvironmentError: return filenames = [] for line in lines: line = line.strip() if not line: continue try: filename = bytes2fsn(line, "utf-8") except ValueError: print_exc() continue filenames.append(filename) if library.librarian: library = library.librarian songs = filter(None, map(library.get, filenames)) for song in songs: self.model.append([song]) def _write(self, _widget: Gtk.Widget, model: QueueModel, force=False): diff = time.time() - self._updated_time if not self._should_write(force, diff): self._pending += 1 return print_d(f"Saving play queue after {diff:.1f}s") filenames = [row[0]["~filename"] for row in model] try: with open(QUEUE, "wb") as f: for filename in filenames: try: line = fsn2bytes(filename, "utf-8") except ValueError as e: print_w(f"Ignoring queue save error ({e})") continue f.write(line + b"\n") except EnvironmentError as e: print_e(f"Error saving queue ({e})") self._updated_time = time.time() self._pending = 0 def _should_write(self, force: bool, diff: float): """Whether it's appropriate to write (flush) Either it's disabled by config, in which case we use batching, or we respect the last write time and the delta """ if force: return True if self.autosave_interval: # Generally only save if there are *known* pending updates, # but these don´t catch everything, so save regardless every now and again. return ((diff > self.autosave_interval and self._pending) or diff > self.autosave_interval * 5) return self._pending >= self._MAX_PENDING def __popup(self, widget, library): songs = self.get_selected_songs() if not songs: return menu = SongsMenu( library, songs, queue=False, remove=False, delete=False, ratings=False) menu.preseparate() remove = MenuItem(_("_Remove"), Icons.LIST_REMOVE) qltk.add_fake_accel(remove, "Delete") remove.connect('activate', self.__remove) menu.prepend(remove) menu.show_all() return self.popup_menu(menu, 0, Gtk.get_current_event_time()) def __remove(self, *args): self.remove_selection() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/quodlibetwindow.py���������������������������������������������������0000644�0001750�0001750�00000143771�14470736246�020772� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2012-2023 Nick Boultbee # 2017 Uriel Zajaczkovski # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk, Gdk, GLib, Gio, GObject from senf import uri2fsn, fsnative, path2fsn import quodlibet from quodlibet import browsers from quodlibet import config from quodlibet import const from quodlibet import formats from quodlibet import qltk from quodlibet import util from quodlibet import app from quodlibet import ngettext from quodlibet import _ from quodlibet.qltk.paned import ConfigRHPaned from quodlibet.qltk.appwindow import AppWindow from quodlibet.update import UpdateDialog from quodlibet.formats.remote import RemoteFile from quodlibet.qltk.browser import LibraryBrowser, FilterMenu from quodlibet.qltk.chooser import choose_folders, choose_files, \ create_chooser_filter from quodlibet.qltk.controls import PlayControls from quodlibet.qltk.cover import CoverImage from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.bookmarks import EditBookmarks from quodlibet.qltk.shortcuts import show_shortcuts from quodlibet.qltk.info import SongInfo from quodlibet.qltk.information import Information from quodlibet.qltk.msg import ErrorMessage, WarningMessage from quodlibet.qltk.notif import StatusBar, TaskController from quodlibet.qltk.playorder import PlayOrderWidget, RepeatSongForever, \ RepeatListForever from quodlibet.qltk.pluginwin import PluginWindow from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.prefs import PreferencesWindow from quodlibet.qltk.queue import QueueExpander from quodlibet.qltk.songlist import SongList, get_columns, set_columns from quodlibet.qltk.songmodel import PlaylistMux from quodlibet.qltk.x import RVPaned, Align, ScrolledWindow, Action from quodlibet.qltk.x import ToggleAction, RadioAction, HighlightToggleButton from quodlibet.qltk.x import SeparatorMenuItem, MenuItem from quodlibet.qltk import Icons from quodlibet.qltk.about import AboutDialog from quodlibet.util import copool, connect_destroy, connect_after_destroy from quodlibet.util.library import get_scan_dirs from quodlibet.util import connect_obj, print_d from quodlibet.util.library import background_filter, scan_library from quodlibet.util.path import uri_is_valid from quodlibet.qltk.window import PersistentWindowMixin, Window, on_first_map from quodlibet.qltk.songlistcolumns import CurrentColumn class PlayerOptions(GObject.Object): """Provides a simplified interface for playback options. This currently provides a limited view on the play order state which is useful for external interfaces (mpd, mpris, etc.) and for reducing the dependency on the state holding widgets in the main window. Usable as long as the main window is not destroyed, or until `destroy()` is called. """ __gproperties__ = { 'shuffle': (bool, '', '', False, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), 'repeat': (bool, '', '', False, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), 'single': (bool, '', '', False, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), 'stop-after': ( bool, '', '', False, GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } def __init__(self, window): """`window` is a QuodLibetWindow""" super().__init__() self._stop_after = window.stop_after self._said = self._stop_after.connect( "toggled", lambda *x: self.notify("stop-after")) def order_changed(*args): self.notify("shuffle") self.notify("single") self._order_widget = window.order self._oid = self._order_widget.connect("changed", order_changed) window.connect("destroy", self._window_destroy) def _window_destroy(self, window): self.destroy() def destroy(self): if self._order_widget: self._order_widget.disconnect(self._oid) self._order_widget = None if self._stop_after: self._stop_after.disconnect(self._said) self._stop_after = None def do_get_property(self, param): return getattr(self, param.name.replace("-", "_")) def do_set_property(self, param, value): setattr(self, param.name.replace("-", "_"), value) @property def single(self): """If only the current song is considered as next track When `repeat` is False the playlist will end after this song finishes. When `repeat` is True the current song will be replayed. """ return (self._order_widget and self._order_widget.repeated and self._order_widget.repeater is RepeatSongForever) @single.setter def single(self, value): if value: self.repeat = True self._order_widget.repeater = RepeatSongForever else: self.repeat = False self._order_widget.repeater = RepeatListForever @property def shuffle(self): """If a shuffle-like (reordering) play order is active""" return self._order_widget.shuffled @shuffle.setter def shuffle(self, value): self._order_widget.shuffled = value @property def repeat(self): """If the player is in some kind of repeat mode""" return self._order_widget.repeated @repeat.setter def repeat(self, value): print_d("setting repeated to %s" % value) self._order_widget.repeated = value @property def stop_after(self): """If the player will pause after the current song ends""" return self._stop_after.get_active() @stop_after.setter def stop_after(self, value): self._stop_after.set_active(value) class DockMenu(Gtk.Menu): """Menu used for the OSX dock and the tray icon""" def __init__(self, app): super().__init__() player = app.player play_item = MenuItem(_("_Play"), Icons.MEDIA_PLAYBACK_START) play_item.connect("activate", self._on_play, player) pause_item = MenuItem(_("P_ause"), Icons.MEDIA_PLAYBACK_PAUSE) pause_item.connect("activate", self._on_pause, player) self.append(play_item) self.append(pause_item) previous = MenuItem(_("Pre_vious"), Icons.MEDIA_SKIP_BACKWARD) previous.connect('activate', lambda *args: player.previous()) self.append(previous) next_ = MenuItem(_("_Next"), Icons.MEDIA_SKIP_FORWARD) next_.connect('activate', lambda *args: player.next()) self.append(next_) browse = qltk.MenuItem(_("_Browse Library"), Icons.EDIT_FIND) browse_sub = Gtk.Menu() for Kind in browsers.browsers: i = Gtk.MenuItem(label=Kind.accelerated_name, use_underline=True) connect_obj(i, 'activate', LibraryBrowser.open, Kind, app.library, app.player) browse_sub.append(i) browse.set_submenu(browse_sub) self.append(SeparatorMenuItem()) self.append(browse) self.show_all() self.hide() def _on_play(self, item, player): player.paused = False def _on_pause(self, item, player): player.paused = True class MainSongList(SongList): """SongList for the main browser's displayed songs.""" _activated = False def __init__(self, library, player): super().__init__(library, player, update=True) self.set_first_column_type(CurrentColumn) self.connect('row-activated', self.__select_song, player) # ugly.. so the main window knows if the next song-started # comes from an row-activated or anything else. def reset_activated(*args): self._activated = False connect_after_destroy(player, 'song-started', reset_activated) self.connect("orders-changed", self.__orders_changed) def __orders_changed(self, *args): l = [] for tag, reverse in self.get_sort_orders(): l.append("%d%s" % (int(reverse), tag)) config.setstringlist('memory', 'sortby', l) def __select_song(self, widget, indices, col, player): self._activated = True iter = self.model.get_iter(indices) if player.go_to(iter, explicit=True, source=self.model): player.paused = False class TopBar(Gtk.Toolbar): def __init__(self, parent, player, library): super().__init__() # play controls control_item = Gtk.ToolItem() self.insert(control_item, 0) t = PlayControls(player, library.librarian) self.volume = t.volume # only restore the volume in case it is managed locally, otherwise # this could affect the system volume if not player.has_external_volume: player.volume = config.getfloat("memory", "volume") connect_destroy(player, "notify::volume", self._on_volume_changed) control_item.add(t) self.insert(Gtk.SeparatorToolItem(), 1) info_item = Gtk.ToolItem() self.insert(info_item, 2) info_item.set_expand(True) box = Gtk.Box(spacing=6) info_item.add(box) qltk.add_css(self, "GtkToolbar {padding: 3px;}") self._pattern_box = Gtk.VBox(spacing=3) # song text info_pattern_path = os.path.join(quodlibet.get_user_dir(), "songinfo") text = SongInfo(library.librarian, player, info_pattern_path) self._pattern_box.pack_start(text, True, True, 0) box.pack_start(self._pattern_box, True, True, 0) # cover image self.image = CoverImage(resize=True) connect_destroy(player, 'song-started', self.__new_song) # FIXME: makes testing easier if app.cover_manager: connect_destroy( app.cover_manager, 'cover-changed', self.__song_art_changed, library) box.pack_start(Align(self.image, top=3, right=3), False, True, 0) # On older Gtk+ (3.4, at least) # setting a margin on CoverImage leads to errors and result in the # QL window not being visible for some reason. assert self.image.props.margin == 0 for child in self.get_children(): child.show_all() context = self.get_style_context() context.add_class("primary-toolbar") def set_seekbar_widget(self, widget): children = self._pattern_box.get_children() if len(children) > 1: self._pattern_box.remove(children[-1]) if widget: self._pattern_box.pack_start(widget, False, True, 0) def _on_volume_changed(self, player, *args): config.set("memory", "volume", str(player.volume)) def __new_song(self, player, song): self.image.set_song(song) def __song_art_changed(self, player, songs, library): self.image.refresh() class QueueButton(HighlightToggleButton): def __init__(self): # XXX: view-list isn't part of the fdo spec, so fall back t justify.. gicon = Gio.ThemedIcon.new_from_names( ["view-list-symbolic", "format-justify-fill-symbolic", "view-list", "format-justify"]) image = Gtk.Image.new_from_gicon(gicon, Gtk.IconSize.SMALL_TOOLBAR) super().__init__(image=image) self.set_name("ql-queue-button") qltk.add_css(self, """ #ql-queue-button { padding: 0px; } """) self.set_size_request(26, 26) self.set_tooltip_text(_("Toggle queue visibility")) class StatusBarBox(Gtk.HBox): def __init__(self, play_order, queue): super().__init__(spacing=6) self.pack_start(play_order, False, True, 0) self.statusbar = StatusBar(TaskController.default_instance) self.pack_start(self.statusbar, True, True, 0) queue_button = QueueButton() queue_button.bind_property("active", queue, "visible", GObject.BindingFlags.BIDIRECTIONAL) queue_button.props.active = queue.props.visible self.pack_start(queue_button, False, True, 0) class PlaybackErrorDialog(ErrorMessage): def __init__(self, parent, player_error): add_full_stop = lambda s: s and (s.rstrip(".") + ".") description = add_full_stop(util.escape(player_error.short_desc)) details = add_full_stop(util.escape(player_error.long_desc or "")) if details: description += " " + details super().__init__( parent, _("Playback Error"), description) class ConfirmLibDirSetup(WarningMessage): RESPONSE_SETUP = 1 def __init__(self, parent): title = _("Set up library directories?") description = _("You don't have any music library set up. " "Would you like to do that now?") super().__init__( parent, title, description, buttons=Gtk.ButtonsType.NONE) self.add_button(_("_Not Now"), Gtk.ResponseType.CANCEL) self.add_button(_("_Set Up"), self.RESPONSE_SETUP) self.set_default_response(Gtk.ResponseType.CANCEL) MENU = """ <ui> <menubar name='Menu'> <menu action='File'> <menuitem action='AddFolders' always-show-image='true'/> <menuitem action='AddFiles' always-show-image='true'/> <menuitem action='AddLocation' always-show-image='true'/> <separator/> <menuitem action='Preferences' always-show-image='true'/> <menuitem action='Plugins' always-show-image='true'/> <separator/> <menuitem action='RefreshLibrary' always-show-image='true'/> <separator/> <menuitem action='Quit' always-show-image='true'/> </menu> <menu action='Song'> <menuitem action='EditBookmarks' always-show-image='true'/> <menuitem action='EditTags' always-show-image='true'/> <separator/> <menuitem action='Information' always-show-image='true'/> <separator/> <menuitem action='Jump' always-show-image='true'/> </menu> <menu action='Control'> <menuitem action='Previous' always-show-image='true'/> <menuitem action='PlayPause' always-show-image='true'/> <menuitem action='Next' always-show-image='true'/> <menuitem action='Stop' always-show-image='true'/> <menuitem action='StopAfter' always-show-image='true'/> </menu> <menu action='Browse'> %(filters_menu)s <separator/> <menu action='BrowseLibrary' always-show-image='true'> %(browsers)s </menu> <separator /> %(views)s </menu> <menu action='Help'> <menuitem action='OnlineHelp' always-show-image='true'/> <menuitem action='Shortcuts' always-show-image='true'/> <menuitem action='SearchHelp' always-show-image='true'/> <separator/> <menuitem action='CheckUpdates' always-show-image='true'/> <menuitem action='About' always-show-image='true'/> </menu> </menubar> </ui> """ def secondary_browser_menu_items(): items = (_browser_items('Browser') + ["<separator />"] + _browser_items('Browser', True)) return "\n".join(items) def browser_menu_items(): items = (_browser_items('View') + ["<separator />"] + _browser_items('View', True)) return "\n".join(items) def _browser_items(prefix, external=False): return ["<menuitem action='%s%s'/>" % (prefix, kind.__name__) for kind in browsers.browsers if kind.uses_main_library ^ external] DND_URI_LIST, = range(1) class SongListPaned(RVPaned): def __init__(self, song_scroller, qexpander): super().__init__() self.pack1(song_scroller, resize=True, shrink=False) self.pack2(qexpander, resize=True, shrink=False) self.set_relative(config.getfloat("memory", "queue_position", 0.75)) self.connect( 'notify::position', self._changed, "memory", "queue_position") self._handle_position = self.get_relative() qexpander.connect('notify::visible', self._expand_or) qexpander.connect('notify::expanded', self._expand_or) qexpander.connect('draw', self._check_minimize) self.connect("button-press-event", self._on_button_press) self.connect('notify', self._moved_pane_handle) @property def _expander(self): return self.get_child2() def _on_button_press(self, pane, event): # If we start to drag the pane handle while the # queue expander is unexpanded, expand it and move the handle # to the bottom, so we can 'drag' the queue out if event.window != pane.get_handle_window(): return False if not self._expander.get_expanded(): self._expander.set_expanded(True) pane.set_relative(1.0) return False def _expand_or(self, widget, prop): if self._expander.get_property('expanded'): self.set_relative(self._handle_position) def _moved_pane_handle(self, widget, prop): if self._expander.get_property('expanded'): self._handle_position = self.get_relative() def _check_minimize(self, *args): if not self._expander.get_property('expanded'): p_max = self.get_property("max-position") p_cur = self.get_property("position") if p_max != p_cur: self.set_property("position", p_max) def _changed(self, widget, event, section, option): if self._expander.get_expanded() and self.get_property('position-set'): config.set(section, option, str(self.get_relative())) class QuodLibetWindow(Window, PersistentWindowMixin, AppWindow): def __init__(self, library, player, headless=False, restore_cb=None): super().__init__(dialog=False) self.__destroyed = False self.__update_title(player) self.set_default_size(600, 480) main_box = Gtk.VBox() self.add(main_box) self.side_book = qltk.Notebook() # get the playlist up before other stuff self.songlist = MainSongList(library, player) self.songlist.connect("key-press-event", self.__songlist_key_press) self.songlist.connect_after( 'drag-data-received', self.__songlist_drag_data_recv) self.song_scroller = ScrolledWindow() self.song_scroller.set_policy( Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.song_scroller.set_shadow_type(Gtk.ShadowType.IN) self.song_scroller.add(self.songlist) self.qexpander = QueueExpander(library, player) self.qexpander.set_no_show_all(True) self.qexpander.set_visible(config.getboolean("memory", "queue")) def on_queue_visible(qex, param): config.set("memory", "queue", str(qex.get_visible())) self.qexpander.connect("notify::visible", on_queue_visible) self.playlist = PlaylistMux( player, self.qexpander.model, self.songlist.model) self.__player = player # create main menubar, load/restore accelerator groups self.__library = library ui = self.__create_menu(player, library) accel_group = ui.get_accel_group() self.add_accel_group(accel_group) def scroll_and_jump(*args): self.__jump_to_current(True, None, True) keyval, mod = Gtk.accelerator_parse("<Primary><shift>J") accel_group.connect(keyval, mod, 0, scroll_and_jump) # custom accel map accel_fn = os.path.join(quodlibet.get_user_dir(), "accels") Gtk.AccelMap.load(accel_fn) # save right away so we fill the file with example comments of all # accels Gtk.AccelMap.save(accel_fn) menubar = ui.get_widget("/Menu") # Since https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79 # toplevel menu items show an empty 16x16 image. While we don't # need image items there UIManager creates them by default. # Work around by removing the empty GtkImages for child in menubar.get_children(): if isinstance(child, Gtk.ImageMenuItem): child.set_image(None) main_box.pack_start(menubar, False, True, 0) top_bar = TopBar(self, player, library) main_box.pack_start(top_bar, False, True, 0) self.top_bar = top_bar self.__browserbox = Align(top=3, bottom=3) self.__paned = paned = ConfigRHPaned("memory", "sidebar_pos", 0.25) paned.pack1(self.__browserbox, resize=True) # We'll pack2 when necessary (when the first sidebar plugin is set up) main_box.pack_start(paned, True, True, 0) play_order = PlayOrderWidget(self.songlist.model, player) statusbox = StatusBarBox(play_order, self.qexpander) self.order = play_order self.statusbar = statusbox.statusbar align = Align(statusbox, top=1, bottom=4, left=6, right=6) main_box.pack_start(align, False, True, 0) self.songpane = SongListPaned(self.song_scroller, self.qexpander) self.songpane.show_all() try: orders = [] for e in config.getstringlist('memory', 'sortby', []): orders.append((e[1:], int(e[0]))) except ValueError: pass else: self.songlist.set_sort_orders(orders) self.browser = None self.ui = ui main_box.show_all() self._playback_error_dialog = None connect_destroy(player, 'song-started', self.__song_started) connect_destroy(player, 'paused', self.__update_paused, True) connect_destroy(player, 'unpaused', self.__update_paused, False) # make sure we redraw all error indicators before opening # a dialog (blocking the main loop), so connect after default handlers connect_after_destroy(player, 'error', self.__player_error) # connect after to let SongTracker update stats connect_after_destroy(player, "song-ended", self.__song_ended) # set at least the playlist. the song should be restored # after the browser emits the song list player.setup(self.playlist, None, 0) self.__restore_cb = restore_cb self.__first_browser_set = True restore_browser = not headless try: self._select_browser( self, config.get("memory", "browser"), library, player, restore_browser) except: config.set("memory", "browser", browsers.name(browsers.default)) config.save() raise self.songlist.connect('popup-menu', self.__songs_popup_menu) self.songlist.connect('columns-changed', self.__cols_changed) self.songlist.connect('columns-changed', self.__hide_headers) self.songlist.info.connect("changed", self.__set_totals) lib = library.librarian connect_destroy(lib, 'changed', self.__song_changed, player) targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_dest_set( Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) self.connect('drag-data-received', self.__drag_data_received) if not headless: on_first_map(self, self.__configure_scan_dirs, library) if config.getboolean('library', 'refresh_on_start'): self.__rebuild(None, False) self.connect("key-press-event", self.__key_pressed, player) self.connect("destroy", self.__destroy) self.enable_window_tracking("quodlibet") def hide_side_book(self): self.side_book.hide() def add_sidebar(self, box, name): vbox = Gtk.Box(margin=0) vbox.pack_start(box, True, True, 0) vbox.show() if self.side_book_empty: self.add_sidebar_to_layout(self.side_book) self.side_book.append_page(vbox, label=name) self.side_book.set_tab_detachable(vbox, False) self.side_book.show_all() return vbox def remove_sidebar(self, widget): self.side_book.remove_page(self.side_book.page_num(widget)) if self.side_book_empty: print_d("Hiding sidebar") self.__paned.remove(self.__paned.get_children()[1]) def add_sidebar_to_layout(self, widget): print_d("Recreating sidebar") align = Align(widget, top=6, bottom=3) self.__paned.pack2(align, shrink=True) align.show_all() @property def side_book_empty(self): return not self.side_book.get_children() def set_seekbar_widget(self, widget): """Add an alternative seek bar widget. Args: widget (Gtk.Widget): a new widget or None to remove the current one """ self.top_bar.set_seekbar_widget(widget) def set_as_osx_window(self, osx_app): assert osx_app self._dock_menu = DockMenu(app) osx_app.set_dock_menu(self._dock_menu) menu = self.ui.get_widget("/Menu") menu.hide() osx_app.set_menu_bar(menu) # Reparent some items to the "Application" menu item = self.ui.get_widget('/Menu/Help/About') osx_app.insert_app_menu_item(item, 0) osx_app.insert_app_menu_item(Gtk.SeparatorMenuItem(), 1) item = self.ui.get_widget('/Menu/File/Preferences') osx_app.insert_app_menu_item(item, 2) quit_item = self.ui.get_widget('/Menu/File/Quit') quit_item.hide() def get_is_persistent(self): return True def open_file(self, filename): assert isinstance(filename, fsnative) song = self.__library.add_filename(filename, add=False) if song is not None: if self.__player.go_to(song): self.__player.paused = False return True else: return False def enqueue(self, songs, limit=0): """Append `songs` to the queue Ask for confimation if the number of songs exceeds `limit`. """ if len(songs) > limit: dialog = ConfirmEnqueue(self, len(songs)) if dialog.run() != Gtk.ResponseType.YES: return self.playlist.enqueue(songs) def __player_error(self, player, song, player_error): # it's modal, but mmkeys etc. can still trigger new ones if self._playback_error_dialog: self._playback_error_dialog.destroy() dialog = PlaybackErrorDialog(self, player_error) self._playback_error_dialog = dialog dialog.run() self._playback_error_dialog = None def __configure_scan_dirs(self, library): """Get user to configure scan dirs, if none is set up""" if not get_scan_dirs() and not len(library) and \ quodlibet.is_first_session("quodlibet"): print_d("Couldn't find any scan dirs") resp = ConfirmLibDirSetup(self).run() if resp == ConfirmLibDirSetup.RESPONSE_SETUP: prefs = PreferencesWindow(self) prefs.set_page("library") prefs.show() def __keyboard_shortcuts(self, action): show_shortcuts(self) def __edit_bookmarks(self, librarian, player): if player.song: window = EditBookmarks(self, librarian, player) window.show() def __key_pressed(self, widget, event, player): if not player.song: return def seek_relative(seconds): current = player.get_position() current += seconds * 1000 current = min(player.song("~#length") * 1000 - 1, current) current = max(0, current) player.seek(current) if qltk.is_accel(event, "<alt>Right"): seek_relative(10) return True elif qltk.is_accel(event, "<alt>Left"): seek_relative(-10) return True def __destroy(self, *args): self.playlist.destroy() # The tray icon plugin tries to unhide QL because it gets disabled # on Ql exit. The window should stay hidden after destroy. self.show = lambda: None self.present = self.show def __drag_data_received(self, widget, ctx, x, y, sel, tid, etime): assert tid == DND_URI_LIST uris = sel.get_uris() dirs = [] error = False for uri in uris: try: filename = uri2fsn(uri) except ValueError: filename = None if filename is not None: loc = os.path.normpath(filename) if os.path.isdir(loc): dirs.append(loc) else: loc = os.path.realpath(loc) if loc not in self.__library: self.__library.add_filename(loc) elif app.player.can_play_uri(uri): if uri not in self.__library: self.__library.add([RemoteFile(uri)]) else: error = True break Gtk.drag_finish(ctx, not error, False, etime) if error: ErrorMessage( self, _("Unable to add songs"), _("%s uses an unsupported protocol.") % util.bold(uri), escape_desc=False).run() else: if dirs: copool.add( self.__library.scan, dirs, cofuncid="library", funcid="library") def __songlist_key_press(self, songlist, event): return self.browser.key_pressed(event) def __songlist_drag_data_recv(self, view, *args): if self.browser.can_reorder: songs = view.get_songs() self.browser.reordered(songs) self.songlist.clear_sort() def __create_menu(self, player, library): def add_view_items(ag): act = Action(name="Information", label=_('_Information'), icon_name=Icons.DIALOG_INFORMATION) act.connect('activate', self.__current_song_info) ag.add_action(act) act = Action(name="Jump", label=_('_Jump to Playing Song'), icon_name=Icons.GO_JUMP) self.__jump_to_current(True, None, True) act.connect('activate', self.__jump_to_current) ag.add_action_with_accel(act, "<Primary>J") def add_top_level_items(ag): ag.add_action(Action(name="File", label=_("_File"))) ag.add_action(Action(name="Song", label=_("_Song"))) ag.add_action(Action(name="View", label=_('_View'))) ag.add_action(Action(name="Browse", label=_("_Browse"))) ag.add_action(Action(name="Control", label=_('_Control'))) ag.add_action(Action(name="Help", label=_('_Help'))) ag = Gtk.ActionGroup.new('QuodLibetWindowActions') add_top_level_items(ag) add_view_items(ag) act = Action(name="AddFolders", label=_(u'_Add a Folder…'), icon_name=Icons.LIST_ADD) act.connect('activate', self.open_chooser) ag.add_action_with_accel(act, "<Primary>O") act = Action(name="AddFiles", label=_(u'_Add a File…'), icon_name=Icons.LIST_ADD) act.connect('activate', self.open_chooser) ag.add_action(act) act = Action(name="AddLocation", label=_(u'_Add a Location…'), icon_name=Icons.LIST_ADD) act.connect('activate', self.open_location) ag.add_action(act) act = Action(name="BrowseLibrary", label=_('Open _Browser'), icon_name=Icons.EDIT_FIND) ag.add_action(act) act = Action(name="Preferences", label=_('_Preferences'), icon_name=Icons.PREFERENCES_SYSTEM) act.connect('activate', self.__preferences) ag.add_action(act) act = Action(name="Plugins", label=_('_Plugins'), icon_name=Icons.SYSTEM_RUN) act.connect('activate', self.__plugins) ag.add_action(act) act = Action(name="Quit", label=_('_Quit'), icon_name=Icons.APPLICATION_EXIT) act.connect('activate', lambda *x: self.destroy()) ag.add_action_with_accel(act, "<Primary>Q") act = Action(name="EditTags", label=_('Edit _Tags'), icon_name=Icons.DOCUMENT_PROPERTIES) act.connect('activate', self.__current_song_prop) ag.add_action(act) act = Action(name="EditBookmarks", label=_(u"Edit Bookmarks…")) connect_obj(act, 'activate', self.__edit_bookmarks, library.librarian, player) ag.add_action_with_accel(act, "<Primary>B") act = Action(name="Previous", label=_('Pre_vious'), icon_name=Icons.MEDIA_SKIP_BACKWARD) act.connect('activate', self.__previous_song) ag.add_action_with_accel(act, "<Primary>comma") act = Action(name="PlayPause", label=_('_Play'), icon_name=Icons.MEDIA_PLAYBACK_START) act.connect('activate', self.__play_pause) ag.add_action_with_accel(act, "<Primary>space") act = Action(name="Next", label=_('_Next'), icon_name=Icons.MEDIA_SKIP_FORWARD) act.connect('activate', self.__next_song) ag.add_action_with_accel(act, "<Primary>period") act = Action(name="Stop", label=_("Stop"), icon_name=Icons.MEDIA_PLAYBACK_STOP) act.connect('activate', self.__stop) ag.add_action(act) act = ToggleAction(name="StopAfter", label=_("Stop After This Song")) ag.add_action_with_accel(act, "<shift>space") # access point for the tray icon self.stop_after = act act = Action(name="Shortcuts", label=_("_Keyboard Shortcuts")) act.connect('activate', self.__keyboard_shortcuts) ag.add_action_with_accel(act, "<Primary>question") act = Action(name="About", label=_("_About"), icon_name=Icons.HELP_ABOUT) act.connect('activate', self.__show_about) ag.add_action_with_accel(act, None) act = Action(name="OnlineHelp", label=_("Online Help"), icon_name=Icons.HELP_BROWSER) def website_handler(*args): util.website(const.ONLINE_HELP) act.connect('activate', website_handler) ag.add_action_with_accel(act, "F1") act = Action(name="SearchHelp", label=_("Search Help")) def search_help_handler(*args): util.website(const.SEARCH_HELP) act.connect('activate', search_help_handler) ag.add_action_with_accel(act, None) act = Action(name="CheckUpdates", label=_("_Check for Updates…"), icon_name=Icons.NETWORK_SERVER) def check_updates_handler(*args): d = UpdateDialog(self) d.run() d.destroy() act.connect('activate', check_updates_handler) ag.add_action_with_accel(act, None) act = Action( name="RefreshLibrary", label=_("_Scan Library"), icon_name=Icons.VIEW_REFRESH) act.connect('activate', self.__rebuild, False) ag.add_action_with_accel(act, "<Primary>R") current = config.get("memory", "browser") try: browsers.get(current) except ValueError: current = browsers.name(browsers.default) first_action = None for Kind in browsers.browsers: name = browsers.name(Kind) index = browsers.index(name) action_name = "View" + Kind.__name__ act = RadioAction(name=action_name, label=Kind.accelerated_name, value=index) act.join_group(first_action) first_action = first_action or act if name == current: act.set_active(True) ag.add_action_with_accel(act, "<Primary>%d" % ((index + 1) % 10,)) assert first_action self._browser_action = first_action def action_callback(view_action, current_action): current = browsers.name( browsers.get(current_action.get_current_value())) self._select_browser(view_action, current, library, player) first_action.connect("changed", action_callback) for Kind in browsers.browsers: action = "Browser" + Kind.__name__ label = Kind.accelerated_name name = browsers.name(Kind) index = browsers.index(name) act = Action(name=action, label=label) def browser_activate(action, Kind): LibraryBrowser.open(Kind, library, player) act.connect('activate', browser_activate, Kind) ag.add_action_with_accel(act, "<Primary><alt>%d" % ((index + 1) % 10,)) ui = Gtk.UIManager() ui.insert_action_group(ag, -1) menustr = MENU % { "views": browser_menu_items(), "browsers": secondary_browser_menu_items(), "filters_menu": FilterMenu.MENU } ui.add_ui_from_string(menustr) self._filter_menu = FilterMenu(library, player, ui) # Cute. So. UIManager lets you attach tooltips, but when they're # for menu items, they just get ignored. So here I get to actually # attach them. ui.get_widget("/Menu/File/RefreshLibrary").set_tooltip_text( _("Check for changes in your library")) return ui def __show_about(self, *args): about = AboutDialog(self, app) about.run() about.destroy() def select_browser(self, browser_key, library, player): """Given a browser name (see browsers.get()) changes the current browser. Returns True if the passed browser ID is known and the change was initiated. """ try: Browser = browsers.get(browser_key) except ValueError: return False action_name = "View%s" % Browser.__name__ for action in self._browser_action.get_group(): if action.get_name() == action_name: action.set_active(True) return True return False def _select_browser(self, activator, current, library, player, restore=False): Browser = browsers.get(current) window = self.get_window() if window: window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) # Wait for the cursor to update before continuing while Gtk.events_pending(): Gtk.main_iteration() config.set("memory", "browser", current) if self.browser: if not (self.browser.uses_main_library and Browser.uses_main_library): self.songlist.clear() container = self.browser.__container self.browser.unpack(container, self.songpane) if self.browser.accelerators: self.remove_accel_group(self.browser.accelerators) container.destroy() self.browser.destroy() self.browser = Browser(library) self.browser.connect('songs-selected', self.__browser_cb, library, player) self.browser.connect('songs-activated', self.__browser_activate) if restore: self.browser.restore() self.browser.activate() self.browser.finalize(restore) if not restore: self.browser.unfilter() if self.browser.can_reorder: self.songlist.enable_drop() elif self.browser.dropped: self.songlist.enable_drop(False) else: self.songlist.disable_drop() if self.browser.accelerators: self.add_accel_group(self.browser.accelerators) self.set_sortability() container = self.browser.__container = self.browser.pack(self.songpane) # Reset the cursor when done loading the browser if window: GLib.idle_add(window.set_cursor, None) player.replaygain_profiles[1] = self.browser.replaygain_profiles player.reset_replaygain() self.__browserbox.add(container) container.show() self._filter_menu.set_browser(self.browser) self.__hide_headers() def set_sortability(self): self.songlist.sortable = not self.browser.can_reorder def __update_paused(self, player, paused): menu = self.ui.get_widget("/Menu/Control/PlayPause") image = menu.get_image() if paused: label, icon = _("_Play"), Icons.MEDIA_PLAYBACK_START else: label, icon = _("P_ause"), Icons.MEDIA_PLAYBACK_PAUSE menu.set_label(label) image.set_from_icon_name(icon, Gtk.IconSize.MENU) def __song_ended(self, player, song, stopped): # Check if the song should be removed, based on the # active filter of the current browser. active_filter = self.browser.active_filter if song and active_filter and not active_filter(song): iter_ = self.songlist.model.find(song) if iter_: self.songlist.remove_iters([iter_]) if self.stop_after.get_active(): player.paused = True self.stop_after.set_active(False) def __song_changed(self, library, songs, player): if player.info in songs: self.__update_title(player) def __update_title(self, player): song = player.info title = "Quod Libet" if song: tag = config.gettext("settings", "window_title_pattern") if tag: title = song.comma(tag) + " - " + title self.set_title(title) def __song_started(self, player, song): self.__update_title(player) for wid in ["Control/Next", "Control/StopAfter", "Song/EditTags", "Song/Information", "Song/EditBookmarks", "Song/Jump"]: self.ui.get_widget('/Menu/' + wid).set_sensitive(bool(song)) # don't jump on stream changes (player.info != player.song) main_should_jump = (song and player.song is song and not self.songlist._activated and config.getboolean("settings", "jump") and self.songlist.sourced) queue_should_jump = (song and player.song is song and not self.qexpander.queue._activated and config.getboolean("settings", "jump") and self.qexpander.queue.sourced and config.getboolean("memory", "queue_keep_songs")) if main_should_jump: self.__jump_to_current(False, self.songlist) elif queue_should_jump: self.__jump_to_current(False, self.qexpander.queue) def __play_pause(self, *args): app.player.playpause() def __stop(self, *args): app.player.stop() def __jump_to_current(self, explicit, songlist=None, force_scroll=False): """Select/scroll to the current playing song in the playlist. If it can't be found tell the browser to properly fill the playlist with an appropriate selection containing the song. explicit means that the jump request comes from the user and not from an event like song-started. songlist is the songlist to be jumped within. Usually the main song list or the queue. If None, the currently sourced songlist will be used. force_scroll will ask the browser to refill the playlist in any case. """ def idle_jump_to(song, select): ok = songlist.jump_to_song(song, select=select) if ok: songlist.grab_focus() return False if not songlist: if (config.getboolean("memory", "queue_keep_songs") and self.qexpander.queue.sourced): songlist = self.qexpander.queue else: songlist = self.songlist if app.player is None: return song = app.player.song # We are not playing a song if song is None: return if not force_scroll: ok = songlist.jump_to_song(song, select=explicit) else: assert explicit ok = False if ok: songlist.grab_focus() elif explicit: # if we can't find it and the user requested it, try harder self.browser.scroll(song) # We need to wait until the browser has finished # scrolling/filling and the songlist is ready. # Not perfect, but works for now. GLib.idle_add( idle_jump_to, song, explicit, priority=GLib.PRIORITY_LOW) def __next_song(self, *args): app.player.next() def __previous_song(self, *args): app.player.previous() def __rebuild(self, activator, force): scan_library(self.__library, force) # Set up the preferences window. def __preferences(self, activator): window = PreferencesWindow(self) window.show() def __plugins(self, activator): window = PluginWindow(self) window.show() def open_location(self, action): name = GetStringDialog(self, _("Add a Location"), _("Enter the location of an audio file:"), button_label=_("_Add"), button_icon=Icons.LIST_ADD).run() if name: if not uri_is_valid(name): ErrorMessage( self, _("Unable to add location"), _("%s is not a valid location.") % util.bold(name)).run() elif not app.player.can_play_uri(name): ErrorMessage( self, _("Unable to add location"), _("%s uses an unsupported protocol.") % (util.bold(name)), escape_desc=False).run() else: if name not in self.__library: self.__library.add([RemoteFile(name)]) def open_chooser(self, action): if action.get_name() == "AddFolders": fns = choose_folders(self, _("Add Music"), _("_Add Folders")) if fns: # scan them copool.add(self.__library.scan, fns, cofuncid="library", funcid="library") else: patterns = ["*" + path2fsn(k) for k in formats.loaders.keys()] choose_filter = create_chooser_filter(_("Music Files"), patterns) fns = choose_files( self, _("Add Music"), _("_Add Files"), choose_filter) if fns: for filename in fns: self.__library.add_filename(filename) def __songs_popup_menu(self, songlist): path, col = songlist.get_cursor() header = col.header_name menu = self.songlist.Menu(header, self.browser, self.__library) if menu is not None: return self.songlist.popup_menu(menu, 0, Gtk.get_current_event_time()) def __current_song_prop(self, *args): song = app.player.song if song: librarian = self.__library.librarian window = SongProperties(librarian, [song], parent=self) window.show() def __current_song_info(self, *args): song = app.player.song if song: librarian = self.__library.librarian window = Information(librarian, [song], self) window.show() def __browser_activate(self, browser): app.player._reset() def __browser_cb(self, browser, songs, sorted, library, player): if browser.background: bg = background_filter() if bg: songs = list(filter(bg, songs)) self.songlist.set_songs(songs, sorted) # After the first time the browser activates, which should always # happen if we start up and restore, restore the playing song. # Because the browser has send us songs we can be sure it has # registered all its libraries. if self.__first_browser_set: self.__first_browser_set = False song = library.librarian.get(config.get("memory", "song")) seek_pos = config.getfloat("memory", "seek", 0) config.set("memory", "seek", 0) if song is not None: player.setup(self.playlist, song, seek_pos, False) if self.__restore_cb: self.__restore_cb() self.__restore_cb = None def __hide_headers(self, activator=None): for column in self.songlist.get_columns(): if self.browser.headers is None: column.set_visible(True) else: for tag in util.tagsplit(column.header_name): if tag in self.browser.headers: column.set_visible(True) break else: column.set_visible(False) def __cols_changed(self, songlist): headers = [col.header_name for col in songlist.get_columns()] try: headers.remove('~current') except ValueError: pass if len(headers) == len(get_columns()): # Not an addition or removal (handled separately) set_columns(headers) SongList.headers = headers def __make_query(self, query): if self.browser.can_filter_text(): self.browser.filter_text(query.encode('utf-8')) self.browser.activate() def __set_totals(self, info, songs): length = sum(song.get("~#length", 0) for song in songs) t = self.browser.status_text(count=len(songs), time=util.format_time_preferred(length)) self.statusbar.set_default_text(t) class ConfirmEnqueue(qltk.Message): def __init__(self, parent, count): title = ngettext("Are you sure you want to enqueue %d song?", "Are you sure you want to enqueue %d songs?", count) % count description = "" super().__init__( Gtk.MessageType.WARNING, parent, title, description, Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Enqueue"), Icons.LIST_ADD, Gtk.ResponseType.YES) �������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/ratingsmenu.py�������������������������������������������������������0000664�0001750�0001750�00000010670�14037102221�020052� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011-2020 Nick Boultbee # 2005 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. from typing import Optional from gi.repository import Gtk from quodlibet import _ from quodlibet import config from quodlibet import qltk from quodlibet.config import RATINGS from quodlibet.qltk import Icons from quodlibet.qltk import SeparatorMenuItem from quodlibet.util import format_rating class ConfirmRateMultipleDialog(qltk.Message): def __init__(self, parent, count: int, value: Optional[float]): assert count > 1 title = (_("Are you sure you want to change the " "rating of all %d songs?") % count) if value is None: desc = _("The saved ratings will be removed") action_title = _("_Remove Rating") else: desc = (_("The rating of all selected songs will be changed to %s") % format_rating(value)) action_title = _("Change _Rating") super().__init__( Gtk.MessageType.WARNING, parent, title, desc, Gtk.ButtonsType.NONE) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(action_title, Gtk.ResponseType.YES) class RatingsMenuItem(Gtk.ImageMenuItem): def __init__(self, songs, library, label=_("_Rating")): super().__init__(label=label, use_underline=True) self._songs = songs image = Gtk.Image.new_from_icon_name(Icons.FAVORITE, Gtk.IconSize.MENU) image.show() self.set_image(image) submenu = Gtk.Menu() self.set_submenu(submenu) self._rating_menu_items = [] for i in RATINGS.all: text = "%0.2f\t%s" % (i, format_rating(i)) itm = Gtk.CheckMenuItem(label=text) itm.rating = i submenu.append(itm) handler = itm.connect( 'toggled', self._on_rating_change, i, library) self._rating_menu_items.append((itm, handler)) reset = Gtk.MenuItem(label=_("_Remove Rating"), use_underline=True) reset.connect('activate', self._on_rating_remove, library) self._select_ratings() submenu.append(SeparatorMenuItem()) submenu.append(reset) submenu.show_all() def set_songs(self, songs): """Set a new set of songs affected by the rating menu""" self._songs = songs self._select_ratings() def _select_ratings(self): ratings = [song("~#rating") for song in self._songs if song and song.has_rating] song_count = len(self._songs) for (menu_item, handler) in self._rating_menu_items: rating_val = menu_item.rating rated_count = ratings.count(rating_val) menu_item.handler_block(handler) if rated_count == 0: menu_item.set_active(False) elif rated_count == song_count: menu_item.set_active(True) else: menu_item.set_inconsistent(True) menu_item.handler_unblock(handler) def _on_rating_change(self, menuitem, value, library): self.set_rating(value, self._songs, library) def _on_rating_remove(self, menutitem, library): self.remove_rating(self._songs, library) def set_rating(self, value, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): parent = qltk.get_menu_item_top_parent(self) dialog = ConfirmRateMultipleDialog(parent, count, value) if dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value librarian.changed(songs) def remove_rating(self, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): parent = qltk.get_menu_item_top_parent(self) dialog = ConfirmRateMultipleDialog(parent, count, None) if dialog.run() != Gtk.ResponseType.YES: return reset = [] for song in songs: if "~#rating" in song: del song["~#rating"] reset.append(song) librarian.changed(reset) ������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/renamefiles.py�������������������������������������������������������0000644�0001750�0001750�00000044077�14327505043�020031� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import re import unicodedata import glob import shutil from gi.repository import Gtk, Gdk from senf import fsn2text, text2fsn import quodlibet from quodlibet import qltk from quodlibet import util from quodlibet import config from quodlibet import _ from quodlibet.plugins import PluginManager from quodlibet.pattern import FileFromPattern from quodlibet.pattern import ArbitraryExtensionFileFromPattern from quodlibet.qltk._editutils import FilterPluginBox, FilterCheckButton from quodlibet.qltk._editutils import EditingPluginHandler from quodlibet.qltk.views import TreeViewColumn from quodlibet.qltk.cbes import ComboBoxEntrySave from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.qltk.models import ObjectStore from quodlibet.qltk import Icons, Button, Frame from quodlibet.qltk.wlw import WritingWindow from quodlibet.util import connect_obj from quodlibet.util.path import strip_win32_incompat_from_path from quodlibet.util.dprint import print_d, print_e NBP = os.path.join(quodlibet.get_user_dir(), "lists", "renamepatterns") NBP_EXAMPLES = """\ <tracknumber>. <title> <tracknumber|<tracknumber>. ><title> <tracknumber> - <title> <tracknumber> - <artist> - <title> /path/<artist> - <album>/<tracknumber>. <title> ~/<artist>/<album>/<tracknumber> - <title> <albumartist|<albumartist>|<artist>>/(<~year>) <album>\ /<tracknumber|<tracknumber> - ><title>""" class SpacesToUnderscores(FilterCheckButton): _label = _("Replace spaces with _underscores") _section = "rename" _key = "spaces" _order = 1.0 def filter(self, original, filename): return filename.replace(" ", "_") class ReplaceColons(FilterCheckButton): _label = _("Replace [semi]colon delimiting with hyphens") _tooltip = _('e.g. "iv: allegro.flac" → "iv - allegro.flac"') _section = "rename" _key = "colons" _order = 1.05 def __init__(self): super().__init__() # If on Windows, force this to be inactive (and hidden) if os.name == 'nt': self.set_active(False) self.set_sensitive(False) self.set_no_show_all(True) def filter(self, original, filename): regx = re.compile(r'\s*[:;]\s+\b') return regx.sub(" - ", filename) class StripWindowsIncompat(FilterCheckButton): _label = _("Strip _Windows-incompatible characters") _section = "rename" _key = "windows" _order = 1.1 def __init__(self): super().__init__() # If on Windows, force this to be inactive (and hidden) if os.name == 'nt': self.set_active(False) self.set_sensitive(False) self.set_no_show_all(True) def filter(self, original, filename): return strip_win32_incompat_from_path(filename) class StripDiacriticals(FilterCheckButton): _label = _("Strip _diacritical marks") _section = "rename" _key = "diacriticals" _order = 1.2 def filter(self, original, filename): return u"".join(filter(lambda s: not unicodedata.combining(s), unicodedata.normalize('NFKD', filename))) class StripNonASCII(FilterCheckButton): _label = _("Strip non-_ASCII characters") _section = "rename" _key = "ascii" _order = 1.3 def filter(self, original, filename): return u"".join(map(lambda s: (s <= "~" and s) or u"_", filename)) class Lowercase(FilterCheckButton): _label = _("Use only _lowercase characters") _section = "rename" _key = "lowercase" _order = 1.4 def filter(self, original, filename): return filename.lower() class RenameFilesPluginHandler(EditingPluginHandler): from quodlibet.plugins.editing import RenameFilesPlugin Kind = RenameFilesPlugin class Entry: def __init__(self, song): self.song = song new_name = None """new name as unicode or None if not set""" @property def name(self): return fsn2text(self.song("~basename")) class RenameFiles(Gtk.VBox): title = _("Rename Files") FILTERS = [SpacesToUnderscores, ReplaceColons, StripWindowsIncompat, StripDiacriticals, StripNonASCII, Lowercase] handler = RenameFilesPluginHandler() IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'bmp'] @classmethod def init_plugins(cls): PluginManager.instance.register_handler(cls.handler) def __init__(self, parent, library): super().__init__(spacing=6) self.__skip_interactive = False self.set_border_width(12) hbox = Gtk.HBox(spacing=6) cbes_defaults = NBP_EXAMPLES.split("\n") self.combo = ComboBoxEntrySave(NBP, cbes_defaults, title=_("Path Patterns"), edit_title=_(u"Edit saved patterns…")) self.combo.show_all() hbox.pack_start(self.combo, True, True, 0) self.preview = qltk.Button(_("_Preview"), Icons.VIEW_REFRESH) self.preview.show() hbox.pack_start(self.preview, False, True, 0) self.pack_start(hbox, False, True, 0) self.combo.get_child().connect('changed', self._changed) model = ObjectStore() self.view = Gtk.TreeView(model=model) self.view.show() sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(self.view) self.pack_start(sw, True, True, 0) self.pack_start(Gtk.VBox(), False, True, 0) # rename options rename_options = Gtk.HBox() # file name options filter_box = FilterPluginBox(self.handler, self.FILTERS) filter_box.connect("preview", self.__filter_preview) filter_box.connect("changed", self.__filter_changed) self.filter_box = filter_box frame_filename_options = Frame(_("File names"), filter_box) frame_filename_options.show_all() rename_options.pack_start(frame_filename_options, False, True, 0) # album art options albumart_box = Gtk.VBox() # move art moveart_box = Gtk.VBox() self.moveart = ConfigCheckButton( _('_Move album art'), "rename", "move_art", populate=True) self.moveart.set_tooltip_text( _("See '[albumart] filenames' config entry " "for image search strings")) self.moveart.show() moveart_box.pack_start(self.moveart, False, True, 0) self.moveart_overwrite = ConfigCheckButton( _('_Overwrite album art at target'), "rename", "move_art_overwrite", populate=True) self.moveart_overwrite.show() moveart_box.pack_start(self.moveart_overwrite, False, True, 0) albumart_box.pack_start(moveart_box, False, True, 0) # remove empty removeemptydirs_box = Gtk.VBox() self.removeemptydirs = ConfigCheckButton( _('_Remove empty directories'), "rename", "remove_empty_dirs", populate=True) self.removeemptydirs.show() removeemptydirs_box.pack_start(self.removeemptydirs, False, True, 0) albumart_box.pack_start(removeemptydirs_box, False, True, 0) frame_albumart_options = Frame(_("Album art"), albumart_box) frame_albumart_options.show_all() rename_options.pack_start(frame_albumart_options, False, True, 0) self.pack_start(rename_options, False, True, 0) # Save button self.save = Button(_("_Save"), Icons.DOCUMENT_SAVE) self.save.show() bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.pack_start(self.save, True, True, 0) self.pack_start(bbox, False, True, 0) render = Gtk.CellRendererText() column = TreeViewColumn(title=_('File')) column.pack_start(render, True) def cell_data_file(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.name) column.set_cell_data_func(render, cell_data_file) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) self.view.append_column(column) render = Gtk.CellRendererText() render.set_property('editable', True) column = TreeViewColumn(title=_('New Name')) column.pack_start(render, True) def cell_data_new_name(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.new_name or u"") column.set_cell_data_func(render, cell_data_new_name) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) self.view.append_column(column) connect_obj(self.preview, 'clicked', self._preview, None) connect_obj(parent, 'changed', self.__class__._preview, self) connect_obj(self.save, 'clicked', self._rename, library) render.connect('edited', self.__row_edited) for child in self.get_children(): child.show() def __filter_preview(self, *args): Gtk.Button.clicked(self.preview) def __filter_changed(self, *args): self._changed(self.combo.get_child()) def _changed(self, entry): self.save.set_sensitive(False) self.preview.set_sensitive(bool(entry.get_text())) def __row_edited(self, renderer, path, new): path = Gtk.TreePath.new_from_string(path) model = self.view.get_model() entry = model[path][0] if entry.new_name != new: entry.new_name = new self.preview.set_sensitive(True) self.save.set_sensitive(True) model.path_changed(path) def _rename(self, library): model = self.view.get_model() win = WritingWindow(self, len(model)) win.show() was_changed = set() skip_all = self.__skip_interactive self.view.freeze_child_notify() should_move_art = config.getboolean("rename", "move_art") moveart_sets = {} remove_empty_dirs = config.getboolean("rename", "remove_empty_dirs") for entry in model.values(): if entry.new_name is None: continue song = entry.song old_name = entry.name old_pathfile = song['~filename'] new_name = entry.new_name new_pathfile = "" # ensure target is a full path if os.path.abspath(new_name) != \ os.path.abspath(os.path.join(os.getcwd(), new_name)): new_pathfile = new_name else: # must be a relative pattern, so prefix the path new_pathfile = \ os.path.join(os.path.dirname(old_pathfile), new_name) try: library.rename(song, text2fsn(new_name), changed=was_changed) except Exception: util.print_exc() if skip_all: continue RESPONSE_SKIP_ALL = 1 msg = qltk.Message( Gtk.MessageType.ERROR, win, _("Unable to rename file"), _("Renaming %(old-name)s to %(new-name)s failed. " "Possibly the target file already exists, " "or you do not have permission to make the " "new file or remove the old one.") % { "old-name": util.bold(old_name), "new-name": util.bold(new_name), }, buttons=Gtk.ButtonsType.NONE) msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL) msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP, Gtk.ResponseType.CANCEL) msg.add_button(_("_Continue"), Gtk.ResponseType.OK) msg.set_default_response(Gtk.ResponseType.OK) resp = msg.run() skip_all |= (resp == RESPONSE_SKIP_ALL) # Preserve old behavior: shift-click is Ignore All mods = Gdk.Display.get_default().get_pointer()[3] skip_all |= mods & Gdk.ModifierType.SHIFT_MASK library.reload(song, changed=was_changed) if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL: break if should_move_art: self._moveart(moveart_sets, old_pathfile, new_pathfile, song) if remove_empty_dirs: path_old = os.path.dirname(old_pathfile) if not os.listdir(path_old): try: os.rmdir(path_old) print_d("Removed empty directory: %r" % path_old, self) except Exception: util.print_exc() if win.step(): break self.view.thaw_child_notify() win.destroy() library.changed(was_changed) self.save.set_sensitive(False) def _moveart(self, art_sets, pathfile_old, pathfile_new, song): path_old = os.path.dirname(os.path.realpath(pathfile_old)) path_new = os.path.dirname(os.path.realpath(pathfile_new)) if os.path.realpath(path_old) == os.path.realpath(path_new): return if (path_old in art_sets.keys() and not art_sets[path_old]): return # get art set for path images = [] if path_old in art_sets.keys(): images = art_sets[path_old] else: def glob_escape(s): for c in '[*?': s = s.replace(c, '[' + c + ']') return s # generate art set for path art_sets[path_old] = images path_old_escaped = glob_escape(path_old) for suffix in self.IMAGE_EXTENSIONS: images.extend(glob.glob(os.path.join(path_old_escaped, "*." + suffix))) if images: # set not empty yet, (re)process filenames = config.getstringlist("albumart", "search_filenames") moves = [] for fn in filenames: fn = os.path.join(path_old, fn) if "<" in fn: # resolve path fnres = ArbitraryExtensionFileFromPattern(fn).format(song) if fnres in images and fnres not in moves: moves.append(fnres) elif "*" in fn: moves.extend(f for f in glob.glob(fn) if f in images and f not in moves) elif fn in images and fn not in moves: moves.append(fn) if len(moves) > 0: overwrite = config.getboolean("rename", "move_art_overwrite") for fnmove in moves: try: # existing files safeguarded until move successful, # then deleted if overwrite set fnmoveto = os.path.join(path_new, os.path.split(fnmove)[1]) fnmoveto_orig = "" if os.path.exists(fnmoveto): fnmoveto_orig = fnmoveto + ".orig" if not os.path.exists(fnmoveto_orig): os.rename(fnmoveto, fnmoveto_orig) else: suffix = 1 while os.path.exists(fnmoveto_orig + "." + str(suffix)): suffix += 1 fnmoveto_orig = (fnmoveto_orig + "." + str(suffix)) os.rename(fnmoveto, fnmoveto_orig) print_d(f"Renaming image {fnmove!r} to {fnmoveto!r}", self) shutil.move(fnmove, fnmoveto) if overwrite and fnmoveto_orig: os.remove(fnmoveto_orig) images.remove(fnmove) except Exception as e: print_e(f"Couldn't move file ({e})") util.print_exc() def _preview(self, songs): model = self.view.get_model() if songs is None: songs = [e.song for e in model.values()] pattern_text = self.combo.get_child().get_text() try: pattern = FileFromPattern(pattern_text) except ValueError: qltk.ErrorMessage( self, _("Path is not absolute"), _("The pattern\n\t%s\ncontains / but does not start from root. " "To avoid misnamed folders, " "root your pattern by starting it with / or ~/.") % ( util.bold(pattern_text))).run() return else: if pattern: self.combo.prepend_text(pattern_text) self.combo.write(NBP) # native paths orignames = [song["~filename"] for song in songs] newnames = [fsn2text(pattern.format(song)) for song in songs] for f in self.filter_box.filters: if f.active: newnames = f.filter_list(orignames, newnames) model.clear() for song, newname in zip(songs, newnames): entry = Entry(song) entry.new_name = newname model.append(row=[entry]) self.preview.set_sensitive(False) self.save.set_sensitive(bool(pattern_text)) for song in songs: if not song.is_file: self.set_sensitive(False) break else: self.set_sensitive(True) @property def test_mode(self): return self.__skip_interactive @test_mode.setter def test_mode(self, value): self.__skip_interactive = value �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/scanbox.py�����������������������������������������������������������0000644�0001750�0001750�00000015252�14267565021�017172� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2021 Joe Wreschnig, Michael Urman, Iñigo Serna, # Steven Robertson, Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from gi.repository import Pango from quodlibet.qltk.msg import ConfirmationPrompt from senf import fsn2text from quodlibet import _, print_w, print_d, app, ngettext from quodlibet.qltk.chooser import choose_folders, _get_chooser, _run_chooser from quodlibet.qltk.views import RCMHintedTreeView from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.x import MenuItem, Button from quodlibet.qltk import Icons from quodlibet.util.path import unexpand from quodlibet.util.library import get_scan_dirs, set_scan_dirs from quodlibet.util import connect_obj, copool class ScanBox(Gtk.HBox): """A box for editing the Library's scan directories""" def __init__(self): super().__init__(spacing=6) self.model = model = ObjectStore() self.view = view = RCMHintedTreeView(model=model) view.set_fixed_height_mode(True) view.set_headers_visible(False) menu = Gtk.Menu() remove_item = MenuItem(_("_Remove"), Icons.LIST_REMOVE) menu.append(remove_item) menu.show_all() view.connect('popup-menu', self.__popup, menu) connect_obj(remove_item, 'activate', self.__remove, view) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(view) sw.set_size_request(-1, max(sw.size_request().height, 80)) sw.set_tooltip_text(_("Songs in the listed folders will be added " "to the library during a library refresh")) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) def cdf(column, cell, model, iter_, data): path = model.get_value(iter_) cell.set_property('text', fsn2text(unexpand(path))) column = Gtk.TreeViewColumn(None, render) column.set_cell_data_func(render, cdf) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) view.append_column(column) add = Button(_("_Add"), Icons.LIST_ADD) add.set_tooltip_text(_("The new directory will be scanned after adding")) add.connect("clicked", self.__add) remove = Button(_("_Remove"), Icons.LIST_REMOVE) remove.set_tooltip_text(_("All songs in the selected directories " "will also be removed from the library")) move = Button(_("_Move"), Icons.EDIT_REDO) move.connect("clicked", self.__move) move.set_tooltip_text(_("Move a scan root (but not the files), " "migrating metadata for all included tracks.")) selection = view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect("changed", self.__select_changed, remove, move) selection.emit("changed") connect_obj(remove, "clicked", self.__remove, view) vbox = Gtk.VBox(spacing=6) vbox.pack_start(add, False, True, 0) vbox.pack_start(remove, False, True, 0) vbox.pack_start(move, False, True, 0) self.pack_start(sw, True, True, 0) self.pack_start(vbox, False, True, 0) for path in get_scan_dirs(): model.append(row=[path]) for child in self.get_children(): child.show_all() def __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __select_changed(self, selection, remove_button, move_button): remove_button.set_sensitive(selection.count_selected_rows()) move_button.set_sensitive(selection.count_selected_rows() == 1) def __save(self): set_scan_dirs(list(self.model.itervalues())) def __remove(self, view) -> None: selection = self.view.get_selection() model, paths = selection.get_selected_rows() gone_dirs = [model[p][0] for p in paths or []] total = len(gone_dirs) if not total: return msg = (_("Remove {dir!r} and all its tracks?").format(dir=gone_dirs[0]) if total == 1 else _("Remove {n} library paths and their tracks?").format(n=total)) title = ngettext("Remove library path?", "Remove library paths?", total) prompt = ConfirmationPrompt(self, title, msg, _("Remove"), ok_button_icon=Icons.LIST_REMOVE) if prompt.run() == ConfirmationPrompt.RESPONSE_INVOKE: view.remove_selection() self.__save() def __add(self, *args): fns = choose_folders(self, _("Select Directories"), _("_Add Folders")) for fn in fns: self.model.append(row=[fn]) self.__save() def __move(self, widget): selection = self.view.get_selection() model, paths = selection.get_selected_rows() rows = [model[p] for p in paths or []] if len(rows) > 1: print_w("Can't do multiple moves at once") return elif not rows: return base_dir = rows[0][0] chooser = _get_chooser(_("Select This Directory"), _("_Cancel")) chooser.set_title( _("Select Actual / New Directory for {dir!r}").format(dir=base_dir)) chooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER) chooser.set_local_only(True) chooser.set_select_multiple(False) results = _run_chooser(self, chooser) if not results: return new_dir = results[0] desc = (_("This will move QL metadata:\n\n" "{old!r} → {new!r}\n\n" "The audio files themselves are not moved by this.\n" "Nonetheless, a backup is recommended " "(including the Quod Libet 'songs' file).") .format(old=base_dir, new=new_dir)) title = _("Move scan root {dir!r}?").format(dir=base_dir) value = ConfirmationPrompt(self, title=title, description=desc, ok_button_text=_("OK, move it!")).run() if value != ConfirmationPrompt.RESPONSE_INVOKE: print_d("User aborted") return print_d(f"Migrate from {base_dir} -> {new_dir}") copool.add(app.librarian.move_root, base_dir, new_dir) path = paths[0] self.model[path] = [new_dir] self.model.row_changed(path, rows[0].iter) self.__save() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689587289.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/searchbar.py���������������������������������������������������������0000644�0001750�0001750�00000032057�14455207131�017463� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010-2011 Christoph Reiter, Steven Robertson # 2016-2018 Nick Boultbee # 2018-2019 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. import operator import os from functools import reduce from gi.repository import Gtk, GObject, GLib import quodlibet from quodlibet import config from quodlibet import _ from quodlibet.query import Query from quodlibet.qltk.cbes import ComboBoxEntrySave from quodlibet.qltk.ccb import ConfigCheckMenuItem from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.qltk import is_accel from quodlibet.util import limit_songs, DeferredSignal class SearchBarBox(Gtk.Box): """ A search bar widget for inputting queries. signals: query-changed - a parsable query string focus-out - If the widget gets focused while being focused (usually for focusing the songlist) """ __gsignals__ = { 'query-changed': ( GObject.SignalFlags.RUN_LAST, None, (object,)), 'focus-out': (GObject.SignalFlags.RUN_LAST, None, ()), } DEFAULT_TIMEOUT = 400 def __init__(self, filename=None, completion=None, accel_group=None, timeout=DEFAULT_TIMEOUT, validator=Query.validator, star=None): super().__init__(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) if filename is None: filename = os.path.join( quodlibet.get_user_dir(), "lists", "queries") historic_entries_count = config.getint("browsers", "searchbar_historic_entries") combo = ComboBoxEntrySave( filename, count=historic_entries_count, validator=validator, title=_("Saved Searches"), edit_title=_(u"Edit saved searches…")) self.__deferred_changed = DeferredSignal( self._filter_changed, timeout=timeout, owner=self) self.__combo = combo entry = combo.get_child() self._entry = entry if completion: entry.set_completion(completion) self._star = star self._query = None self.__sig = combo.connect('text-changed', self.__text_changed) entry.connect('clear', self._filter_changed) entry.connect('backspace', self.__text_changed) entry.connect('populate-popup', self.__menu) entry.connect('activate', self._filter_changed) entry.connect('activate', self.__save_search) entry.connect('focus-out-event', self.__save_search) entry.connect('key-press-event', self.__key_pressed) entry.set_placeholder_text(_("Search")) entry.set_tooltip_text(_("Search your library, " "using free text or QL queries")) combo.enable_clear_button() self.pack_start(combo, True, True, 0) if accel_group: key, mod = Gtk.accelerator_parse("<Primary>L") accel_group.connect(key, mod, 0, lambda *x: entry.mnemonic_activate(True)) for child in self.get_children(): child.show_all() def set_enabled(self, enabled=True): self._entry.set_sensitive(enabled) def set_text(self, text): """Set the text without firing any signals""" self.__deferred_changed.abort() self._update_query_from(text) # deactivate all signals and change the entry text self.__inhibit() self._entry.set_text(text) self.__uninhibit() def _update_query_from(self, text): # TODO: remove tight coupling to Query self._query = Query(text, star=self._star) def get_text(self): """Get the active text as unicode""" return self._entry.get_text() def get_query(self, star=None): if star and star != self._star: self._star = star self._update_query_from(self.get_text()) return self._query def changed(self): """Triggers a filter-changed signal if the current text is a parsable query """ self._filter_changed() def __inhibit(self): self.__combo.handler_block(self.__sig) def __uninhibit(self): self.__combo.handler_unblock(self.__sig) def __menu(self, entry, menu): sep = SeparatorMenuItem() sep.show() menu.prepend(sep) cb = ConfigCheckMenuItem( _("Search after _typing"), 'settings', 'eager_search', populate=True) cb.set_tooltip_text( _("Show search results after the user stops typing")) cb.show() menu.prepend(cb) def __mnemonic_activate(self, label, group_cycling): widget = label.get_mnemonic_widget() if widget.is_focus(): self.emit('focus-out') return True def __save_search(self, entry, *args): # only save the query on focus-out if eager_search is turned on if (len(args) > 0 and args[0] and not config.getboolean('settings', 'eager_search')): return text = self.get_text().strip() if text and self._query and self._query.is_parsable: # Adding the active text to the model triggers a changed signal # (get_active is no longer -1), so inhibit self.__inhibit() self.__combo.prepend_text(text) self.__combo.write() self.__uninhibit() def __key_pressed(self, entry, event): if (is_accel(event, '<Primary>Return') or is_accel(event, '<Primary>KP_Enter')): # Save query on Primary+Return accel, even though the focus is kept self.__save_search(entry) return False def _filter_changed(self, *args): self.__deferred_changed.abort() text = self.get_text() self._update_query_from(text) if self._query.is_parsable: GLib.idle_add(self.emit, 'query-changed', text) def __text_changed(self, *args): if not self._entry.is_sensitive(): return # the combobox has an active entry selected -> no timeout # todo: we need a timeout when the selection changed because # of keyboard input (up/down arrows) if self.__combo.get_active() != -1: self._filter_changed() return if not config.getboolean('settings', 'eager_search'): return self.__deferred_changed() class LimitSearchBarBox(SearchBarBox): """A version of `SearchBarBox` that allows specifying the limiting and weighting of a search.""" class Limit(Gtk.HBox): __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, ()), } def __init__(self): super().__init__(spacing=3, no_show_all=True) label = Gtk.Label(label=_("_Limit:")) self.pack_start(label, True, True, 0) self.__limit = limit = Gtk.SpinButton() self.__limit.connect("value-changed", self.__changed) limit.set_numeric(True) limit.set_range(0, 9999) limit.set_increments(5, 100) label.set_mnemonic_widget(limit) label.set_use_underline(True) self.pack_start(limit, True, True, 0) self.__weight = Gtk.CheckButton( label=_("_Weight"), use_underline=True) self.__weight.connect("toggled", self.__changed) self.pack_start(self.__weight, True, True, 0) for child in self.get_children(): child.show() def __changed(self, *args): self.emit("changed") @property def value(self): return self.__limit.get_value_as_int() @property def weighted(self): return self.__weight.get_active() def __init__(self, show_limit=False, *args, **kwargs): super().__init__(*args, **kwargs) self.__limit = self.Limit() self.__limit.set_visible(show_limit) self.pack_start(self.__limit, False, True, 0) self.__limit.connect("changed", self.__limit_changed) def __limit_changed(self, *args): self.changed() def limit(self, songs): if self.__limit.get_visible(): return limit_songs(songs, self.__limit.value, self.__limit.weighted) else: return songs def toggle_limit_widgets(self, button): """Toggles the visibility of the limit widget according to `button`""" if button.get_active(): self.__limit.show() else: self.__limit.hide() self.changed() class MultiSearchBarBox(LimitSearchBarBox): """An extension of `LimitSearchBarBox` allowing multiple queries. Note: Instances of this class must have their flow_box attribute packed by their parents or the multiple queries won't work. """ def __init__(self, *args, show_multi=False, multi_filename=None, **kwargs): super().__init__(*args, **kwargs) self.multi_filename = os.path.join( quodlibet.get_user_dir(), "lists", "multiqueries" ) if multi_filename is None else multi_filename self._old_placeholder = self._entry.get_placeholder_text() self._old_tooltip = self._entry.get_tooltip_text() self._add_button = Gtk.Button.new_from_icon_name("list-add", Gtk.IconSize.BUTTON) self._add_button.set_no_show_all(True) self.pack_start(self._add_button, False, True, 0) self._add_button.connect('clicked', self.activated) self._entry.connect('activate', self.activated) self.flow_box = Gtk.FlowBox(no_show_all=True, max_children_per_line=99, selection_mode=Gtk.SelectionMode.NONE) self.toggle_multi_bool(show_multi) def activated(self, _): if self.flow_box.get_visible(): text = self.get_text().strip() if text == "": # disallow empty queries return self.add_query_item(text) self.set_text("") self._filter_changed() def add_query_item(self, text): q = QueryItem(text, self._filter_changed) q.show() self.flow_box.add(q) def load(self): try: with open(self.multi_filename) as f: for row in f: self.add_query_item(row.strip()) except OSError: pass def save(self): if not os.path.isdir(os.path.dirname(self.multi_filename)): os.makedirs(os.path.dirname(self.multi_filename)) with open(self.multi_filename, "w") as f: f.writelines(lq.string + "\n" for lq in self.flow_box.get_children()) def _update_query_from(self, text): if self.flow_box.get_visible(): matches = [lq.query._unpack() for lq in self.flow_box.get_children()] self._query = Query(text, star=self._star) self._query._match = reduce(operator.and_, matches, self._query._match) else: super()._update_query_from(text) def toggle_multi(self, button): """Toggles the multiquery mode according to `button`""" self.toggle_multi_bool(button.get_active()) def toggle_multi_bool(self, multi): """Toggles the multiquery mode to the given bool""" if multi: self._add_button.show() self.flow_box.show() self._old_placeholder = self._entry.get_placeholder_text() self._old_tooltip = self._entry.get_tooltip_text() self._entry.set_placeholder_text(_("Add query")) self._entry.set_tooltip_text(_("Add a QL query or free text " "to be &ed together")) else: self._add_button.hide() self.flow_box.hide() self._entry.set_placeholder_text(self._old_placeholder) self._entry.set_tooltip_text(self._old_tooltip) self.changed() class QueryItem(Gtk.FlowBoxChild): """A FlowBoxChild representing a query""" def __init__(self, string, changed_callback): super().__init__() self.changed_callback = changed_callback self.string = string self.query = Query(string) hbox = Gtk.HBox() hbox.pack_start(Gtk.Label(string, halign=Gtk.Align.START, margin=6), True, True, 0) btn = Gtk.Button.new_from_icon_name("window-close", Gtk.IconSize.BUTTON) btn.set_relief(Gtk.ReliefStyle.NONE) btn.connect('clicked', self.remove) hbox.pack_start(btn, False, True, 0) frame = Gtk.Frame() frame.add(hbox) self.add(frame) self.show_all() def remove(self, _): self.destroy() self.changed_callback() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/seekbutton.py��������������������������������������������������������0000644�0001750�0001750�00000030632�14267565021�017717� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk, GLib from quodlibet import _ from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet.qltk import get_top_parent from quodlibet.qltk.tracker import TimeTracker from quodlibet.qltk import bookmarks from quodlibet.qltk.x import Align from quodlibet.qltk import Icons from quodlibet.qltk.ccb import ConfigCheckMenuItem from quodlibet.qltk.util import window_grab_and_map, window_ungrab_and_unmap, \ position_window_beside_widget from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.util import connect_obj, connect_destroy class TimeLabel(Gtk.Label): """A label for displaying the running time It tries to minimize size changes due to unequal character widths with the same number of characters. e.g. a time display -> 04:20 """ def __init__(self, time_=0): Gtk.Label.__init__(self) self.__widths = {} # num-chars -> (max-min-width, max-natural-width) self._disabled = False self.set_time(time_) def do_get_preferred_width(self): widths = Gtk.Label.do_get_preferred_width(self) # If for same number of characters, the needed width was larger, # use that instead of the current one num_chars = len(self.get_text()) max_widths = self.__widths.get(num_chars, widths) widths = max(widths[0], max_widths[0]), max(widths[1], max_widths[1]) self.__widths[num_chars] = widths return widths def set_time(self, time_): """Set the time in seconds""" self._last_time = time_ if self._disabled: return self.set_text(util.format_time_display(time_)) def set_disabled(self, disabled): """Disable the time display temporarily, means there is no meaningful time to show. Re-enabling will show the previous time value """ self._disabled = disabled if disabled: self.set_text(u"‒\u2236‒‒") else: self.set_time(self._last_time) class HSlider(Gtk.Button): def __init__(self, child=None): super().__init__() if child: self.add(child) self.connect('clicked', self.__clicked) self._disable_slider = False self.__grabbed = [] window = self.__window = Gtk.Window(type=Gtk.WindowType.POPUP) self.__adj = Gtk.Adjustment.new(0, 0, 0, 3, 15, 0) frame = Gtk.Frame() frame.set_border_width(0) frame.set_shadow_type(Gtk.ShadowType.OUT) self.add_events(Gdk.EventMask.SCROLL_MASK) hscale = Gtk.Scale(adjustment=self.__adj) hscale.set_orientation(Gtk.Orientation.HORIZONTAL) window.connect('button-press-event', self.__button) window.connect('key-press-event', self.__key) hscale.set_draw_value(False) self.scale = hscale window.add(frame) self._box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self._box.add(hscale) frame.add(self._box) self.connect('scroll-event', self.__scroll, hscale) self.connect("destroy", self.__destroy) # forward scroll event to the button def foward_scroll(scale, event): self.emit('scroll-event', event.copy()) window.connect('scroll-event', foward_scroll) # ignore scroll events on the scale, the window handles it instead self.scale.connect('scroll-event', lambda *x: True) # handle all unhandled button events on the scale # so only events not on the scale hide the window def handle_all(scale, event): return True self.scale.connect_after('button-press-event', handle_all) self.scale.connect_after('button-release-event', handle_all) # forward release event to the scale def foward_release(scale, event): self.scale.emit('button-release-event', event.copy()) window.connect('button-release-event', foward_release) self.set_slider_length(200) if child: self.get_child().show_all() def __destroy(self, *args): self.__window.destroy() self.__window = None def set_slider_disabled(self, disable): """Hide the slider and don't allow showing it again until it is enabled again """ self._disable_slider = disable if disable: self.__popup_hide() def set_slider_length(self, length): self.scale.set_size_request(length, -1) # force a window resize.. self.__window.resize(1, 1) def set_slider_widget(self, widget): self._box.pack_start( Align(widget, border=6, left=-3), False, True, 0) def __clicked(self, button): if self.__window.get_property('visible'): return if self._disable_slider: return if self.__grabbed: self.__popup_hide() window = self.__window frame = window.get_child() frame.show_all() window.set_transient_for(get_top_parent(self)) # this type hint tells the wayland backend to create a popup window.set_type_hint(Gdk.WindowTypeHint.DROPDOWN_MENU) position_window_beside_widget(window, self) self.__grabbed = window_grab_and_map( window, Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.BUTTON_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.SCROLL_MASK) def __scroll(self, widget, event, hscale): adj = self.__adj v = hscale.get_value() direction = event.direction if direction in [Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.RIGHT]: v -= adj.props.step_increment elif direction in [Gdk.ScrollDirection.UP, Gdk.ScrollDirection.LEFT]: v += adj.props.step_increment else: # newer Gdk.ScrollDirection.SMOOTH return v = min(adj.props.upper, max(adj.props.lower, v)) hscale.set_value(v) def __button(self, widget, ev): self.__popup_hide() def __key(self, hscale, ev): if ev.string in ["\n", "\r", " ", "\x1b"]: # enter, space, escape self.__popup_hide() def __popup_hide(self): window_ungrab_and_unmap(self.__window, self.__grabbed) del self.__grabbed[:] class SeekButton(HSlider): __lock = False __sig = None __seekable = True def __init__(self, player, library): hbox = Gtk.HBox(spacing=3) l = TimeLabel() self._time_label = l hbox.pack_start(l, True, True, 0) arrow = Gtk.Arrow.new(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE) hbox.pack_start(arrow, False, True, 0) super().__init__(hbox) self._slider_label = TimeLabel() self.set_slider_widget(self._slider_label) self._on_seekable_changed(player) connect_destroy(player, "notify::seekable", self._on_seekable_changed) self.scale.connect('button-press-event', self.__seek_lock) self.scale.connect('button-release-event', self.__seek_unlock, player) self.scale.connect('key-press-event', self.__seek_lock) self.scale.connect('key-release-event', self.__seek_unlock, player) self.connect('scroll-event', self.__scroll, player) self.scale.connect('value-changed', self.__update_time, l) m = Gtk.Menu() c = ConfigCheckMenuItem( _("Display remaining time"), "player", "time_remaining") c.set_active(config.getboolean("player", "time_remaining")) connect_obj(c, 'toggled', self.scale.emit, 'value-changed') self.__remaining = c m.append(c) m.append(SeparatorMenuItem()) i = qltk.MenuItem(_(u"_Edit Bookmarks…"), Icons.EDIT) def edit_bookmarks_cb(menu_item): window = bookmarks.EditBookmarks(self, library, player) window.show() i.connect('activate', edit_bookmarks_cb) m.append(i) m.show_all() connect_obj(self, 'button-press-event', self.__check_menu, m, player, c) connect_obj(self, 'popup-menu', self.__popup_menu, m, player) timer = TimeTracker(player) connect_obj(timer, 'tick', self.__check_time, player) connect_destroy( library, "changed", self.__songs_changed, player, m) connect_destroy(player, 'song-started', self.__song_started, m) connect_destroy(player, 'seek', self.__seeked) def _on_seekable_changed(self, player, *args): self._time_label.set_disabled(not player.seekable) self.set_slider_disabled(not player.seekable) def __check_menu(self, menu, event, player, remaining_item): if event.type != Gdk.EventType.BUTTON_PRESS: return if event.button == Gdk.BUTTON_SECONDARY: return self.__popup_menu(menu, player, event) elif event.button == Gdk.BUTTON_MIDDLE: remaining_item.set_active(not remaining_item.get_active()) return True def __popup_menu(self, menu, player, event=None): for child in menu.get_children()[2:-1]: menu.remove(child) child.destroy() try: marks = player.song.bookmarks except AttributeError: # song is None pass else: items = qltk.bookmarks.MenuItems(marks, player, self.__seekable) items.reverse() for i in items: menu.insert(i, 2) if event: qltk.popup_menu_at_widget(menu, self, 3, event.time) else: time = Gtk.get_current_event_time() qltk.popup_menu_under_widget(menu, self, 3, time) return True def __seeked(self, player, song, ms): self.scale.set_value(ms / 1000.) def __scroll(self, widget, event, player): self.__lock = True if self.__sig is not None: GLib.source_remove(self.__sig) self.__sig = GLib.timeout_add(100, self.__scroll_timeout, player) def __scroll_timeout(self, player): self.__lock = False if self.__seekable: player.seek(self.scale.get_value() * 1000) self.__sig = None def __seek_lock(self, scale, event): self.__lock = True def __seek_unlock(self, scale, event, player): self.__lock = False if self.__seekable: player.seek(self.scale.get_value() * 1000) def __check_time(self, player): # When the song is paused GStreamer returns < 1 for position # queries, so if it's paused just ignore it. if not (player.paused or self.__lock): position = player.get_position() / 1000. if (not self.__seekable and position > self.scale.get_adjustment().get_upper()): self.scale.set_range(0, position) self.scale.set_value(position) return True def __update_time(self, scale, timer): value = scale.get_value() max_ = scale.get_adjustment().get_upper() remaining = value - max_ if self.__remaining.get_active(): remaining, value = value, remaining timer.set_time(value) self._slider_label.set_time(remaining) def __songs_changed(self, library, songs, player, menu): song = player.song if song in songs: self.__update_slider(song, menu) def __song_started(self, player, song, menu): self.scale.set_value(0) self.__update_slider(song, menu) def __update_slider(self, song, menu): if song and song("~#length") > 0: self.scale.set_range(0, song("~#length")) slider_width = int(song("~#length") / 1.5) + 80 self.__seekable = True else: self.scale.set_range(0, 1) slider_width = 0 self.__seekable = False slider_width = min(max(slider_width, 170), 400) self.set_slider_length(slider_width) for child in menu.get_children()[2:-1]: menu.remove(child) child.destroy() menu.get_children()[-1].set_sensitive(self.__seekable) self.scale.emit('value-changed') ������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/shortcuts.py���������������������������������������������������������0000775�0001750�0001750�00000006417�14035600052�017566� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet import const from quodlibet import util from quodlibet import _ SHORTCUTS = [ (_("Main Window"), [ ("<Alt>Left", _("Seek backwards by 10 seconds")), ("<Alt>Right", _("Seek forward by 10 seconds")), ("<Primary>L", _("Focus the search entry")), ]), (_("Browsers"), [ ("<Primary><Shift>J", _("Reset filters and jump to the playing song")), ]), (_("Song List"), [ ("<Primary>I", _("Open the information window for the selected songs")), ("<Alt>Return", _("Open the tag editor for the selected songs")), ("<Primary>Return", _("Queue the selected songs")), ("<Primary>Delete", _("Delete the selected songs")), ("<Primary>F", _("Show the inline search entry")), ("<Ctrl>", "+ " + _("Left click on a column header") + ":\n" + _("Add the column to the list of columns to sort by")), ]), (_("Tree View"), [ ("Left <Primary>Left", _("Collapses the element or select the parent element")), ("Right <Primary>Right", _("Expands the element")), ]), (_("Text Entries"), [ ("<Primary>Z", _("Undo the last change")), ("<Primary><Shift>Z", _("Redo the last undone change")), ]), (_("Paned Browser"), [ ("<Primary>Home", _("Select all songs in all panes")), ]), ] def build_shortcut_window(data): """Returns a filled Gtk.ShortcutsWindow""" assert has_shortcut_window() # Note: gtk+ is picky about the order of adding/showing things because # this is usually done through XML. e.g. adding shortcuts after a section # won't make them show up in the search etc.. w = Gtk.ShortcutsWindow() section = Gtk.ShortcutsSection() section.show() for group_title, shortcuts in data: group = Gtk.ShortcutsGroup(title=group_title) group.show() for accel, shortcut_title in shortcuts: short = Gtk.ShortcutsShortcut( title=shortcut_title, accelerator=accel) short.show() group.add(short) section.add(group) w.add(section) return w def has_shortcut_window(): """Returns if the current Gtk+ supports ShortcutsWindow. Gtk+ >= 3.20""" return hasattr(Gtk, "ShortcutsWindow") def show_shortcuts(parent): """Either opens a window showing keyboard shortcuts or a website in the default browser, depending on the Gtk+ version """ if has_shortcut_window(): window = build_shortcut_window(SHORTCUTS) window.set_transient_for(parent) window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) window.set_modal(True) window.show() # XXX: The windows does some weird size changes on start which confuses # window placement. This fixes the jumping around and wrong position # with some WMs and under Windows. window.hide() window.unrealize() window.show() else: util.website(const.SHORTCUTS_HELP) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/showfiles.py���������������������������������������������������������0000664�0001750�0001750�00000012721�14035600052�017523� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2020 Nick Boultbee # 2012,2014,2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Show directories and files in the default system file browser""" import os import subprocess from gi.repository import GLib from gi.repository import Gio from gi.repository import Gtk from senf import fsn2uri, fsnative from quodlibet import print_d from quodlibet.util import is_windows, is_osx def show_files(dirname, entries=[]): """Shows the directory in the default file browser and if passed a list of directory entries will highlight those. Depending on the system/platform this might highlight all files passed, or only one of them, or none at all. Args: dirname (fsnative): Path to the directory entries (List[fsnative]): List of (relative) filenames in the directory entries (List[fsnative]): List of (relative) filenames in the directory Returns: bool: if the action was successful or not """ assert isinstance(dirname, fsnative) assert all(isinstance(e, fsnative) and os.path.basename(e) == e for e in entries) dirname = os.path.abspath(dirname) if is_windows(): implementations = [_show_files_win32] elif is_osx(): implementations = [_show_files_finder] else: implementations = [ _show_files_fdo, _show_files_thunar, _show_files_xdg_open, _show_files_gnome_open, ] for impl in implementations: try: impl(dirname, entries) except BrowseError as e: print_d("Couldn't show files with %s (%s), ignoring." % (impl, e)) continue else: return True return False def show_songs(songs): """Returns False if showing any of them failed""" dirs = {} for s in songs: dirs.setdefault(s("~dirname"), []).append(s("~basename")) for dirname, entries in sorted(dirs.items()): status = show_files(dirname, entries) if not status: return False return True class BrowseError(Exception): pass def _get_startup_id(): from quodlibet import app app_name = type(app.window).__name__ return "%s_TIME%d" % (app_name, Gtk.get_current_event_time()) def _get_dbus_proxy(name, path, iface): bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) return Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, name, path, iface, None) def _show_files_fdo(dirname, entries): # https://www.freedesktop.org/wiki/Specifications/file-manager-interface/ FDO_PATH = "/org/freedesktop/FileManager1" FDO_NAME = "org.freedesktop.FileManager1" FDO_IFACE = "org.freedesktop.FileManager1" try: dbus_proxy = _get_dbus_proxy(FDO_NAME, FDO_PATH, FDO_IFACE) if not entries: dbus_proxy.ShowFolders('(ass)', [fsn2uri(dirname)], _get_startup_id()) else: item_uri = fsn2uri(os.path.join(dirname, entries[0])) dbus_proxy.ShowItems('(ass)', [item_uri], _get_startup_id()) except GLib.Error as e: raise BrowseError(e) def _show_files_thunar(dirname, entries): # https://git.xfce.org/xfce/thunar/tree/thunar/thunar-dbus-service-infos.xml XFCE_PATH = "/org/xfce/FileManager" XFCE_NAME = "org.xfce.FileManager" XFCE_IFACE = "org.xfce.FileManager" try: dbus_proxy = _get_dbus_proxy(XFCE_NAME, XFCE_PATH, XFCE_IFACE) if not entries: dbus_proxy.DisplayFolder('(sss)', fsn2uri(dirname), "", _get_startup_id()) else: dbus_proxy.DisplayFolderAndSelect( '(ssss)', fsn2uri(dirname), entries[0], "", _get_startup_id()) except GLib.Error as e: raise BrowseError(e) def _show_files_gnome_open(dirname, *args): try: if subprocess.call(["gnome-open", dirname]) != 0: raise EnvironmentError("gnome-open error return status") except EnvironmentError as e: raise BrowseError(e) def _show_files_xdg_open(dirname, *args): try: if subprocess.call(["xdg-open", dirname]) != 0: raise EnvironmentError("xdg-open error return status") except EnvironmentError as e: raise BrowseError(e) def _show_files_win32(dirname, entries): if not is_windows(): raise BrowseError("windows only") if not entries: # open_folder_and_select_items will open the parent if no items # are passed, so execute explorer directly for that case try: if subprocess.call(["explorer", dirname]) != 0: raise EnvironmentError("explorer error return status") except EnvironmentError as e: raise BrowseError(e) else: from quodlibet.util.windows import open_folder_and_select_items try: open_folder_and_select_items(dirname, entries) except WindowsError as e: raise BrowseError(e) def _show_files_finder(dirname, *args): if not is_osx(): raise BrowseError("OS X only") try: if subprocess.call(["open", "-R", dirname]) != 0: raise EnvironmentError("open error return status") except EnvironmentError as e: raise BrowseError(e) �����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692708870.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/songlist.py����������������������������������������������������������0000644�0001750�0001750�00000130745�14471130006�017370� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2012 Christoph Reiter # 2014 Jan Path # 2011-2023 Nick Boultbee # 2018 David Morris # # 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 2 of the License, or # (at your option) any later version. from typing import List, Optional, Sequence, Tuple from gi.repository import Gtk, GLib, Gdk, GObject from senf import uri2fsn from quodlibet import app, print_w, print_d from quodlibet import config from quodlibet import const from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.query import Query from quodlibet.pattern import Pattern from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.views import AllTreeView, DragScroll from quodlibet.qltk.ratingsmenu import ConfirmRateMultipleDialog from quodlibet.qltk.songmodel import PlaylistModel from quodlibet.qltk import Icons from quodlibet.qltk.util import GSignals from quodlibet.qltk.delete import trash_songs from quodlibet.formats._audio import TAG_TO_SORT, AudioFile from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.qltk.songlistcolumns import create_songlist_column, SongListColumn from quodlibet.util import connect_destroy DND_QL, DND_URI_LIST = range(2) class SongSelectionInfo(GObject.Object): """ Songs which get included in the status bar summary. The `changed` signal gets fired after any of the songs in the selection or the selection itself has changed. The signal is async. Two selection states: - 0 or 1 selected row: all rows - 2 or more: only the selected rows The signals fires if the state changes. FIXME: `row-changed` for song lists isn't implemented (performance). Since a library change could change the selection it should also trigger this. Since this would happen quite often (song stat changes) and would lead to a complete re-calc in the common case, ignore it for now. """ __gsignals__: GSignals = { # changed(songs:list) 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)) } def __init__(self, songlist): super().__init__() self.__idle = None self.__songlist = songlist self.__selection = sel = songlist.get_selection() self.__count = sel.count_selected_rows() self.__sel_id = songlist.connect('selection-changed', self.__selection_changed) self.__sel_id = songlist.connect('songs-removed', self.__songs_removed) def destroy(self): self.__songlist.disconnect(self.__sel_id) if self.__idle: GLib.source_remove(self.__idle) def refresh(self): songlist = self.__songlist songs = songlist.get_selected_songs() or songlist.get_songs() self.emit('changed', songs) def _update_songs(self, songs): """After making changes (filling the list) call this to skip any queued changes and emit the passed songs instead""" self.__emit_info_selection(songs) self.__count = len(songs) def __idle_emit(self, songs): if songs is None: if self.__count <= 1: songs = self.__songlist.get_songs() else: songs = self.__songlist.get_selected_songs() self.emit('changed', songs) self.__idle = None def __emit_info_selection(self, songs=None): if self.__idle: GLib.source_remove(self.__idle) self.__idle = GLib.idle_add( self.__idle_emit, songs, priority=GLib.PRIORITY_LOW) def __songs_removed(self, songlist, removed): try: self.__emit_info_selection() except Exception as e: print_w(f"Couldn't process removed songs ({e})r") def __selection_changed(self, songlist, selection): count = selection.count_selected_rows() if self.__count == count == 0: return if count <= 1: if self.__count > 1: self.__emit_info_selection() else: self.__emit_info_selection() self.__count = count def get_columns(): """Gets the list of songlist column headings""" columns = config.getstringlist("settings", "columns", const.DEFAULT_COLUMNS) if "~current" in columns: columns.remove("~current") return columns def set_columns(vals): """Persists the settings for songlist headings held in `vals`""" config.setstringlist("settings", "columns", vals) def get_sort_tag(tag): """Returns a tag that can be used for sorting for the given column tag. Returns '' if the default sort key should be used. """ replace_order = { "~#track": "", "~#disc": "", "~#tracks": "", "~#discs": "", "~length": "~#length" } if tag == "~title~version": tag = "title" elif tag == "~album~discsubtitle": tag = "album" if "<" in tag: for key, value in replace_order.items(): if value: value = f"<{value}>" tag = tag.replace(f"<{key}>", value) for key, value in TAG_TO_SORT.items(): tag = tag.replace("<%s>" % key, "<{1}|<{1}>|<{0}>>".format(key, value)) tag = Pattern(tag).format else: tags = util.tagsplit(tag) sort_tags = [] for tag in tags: tag = replace_order.get(tag, tag) tag = TAG_TO_SORT.get(tag, tag) if tag not in sort_tags: sort_tags.append(tag) if len(sort_tags) > 1: tag = "~" + "~".join(sort_tags) return tag def header_tag_split(header): """Split a pattern or a tied tag into separate tags""" if "<" in header: try: return list(Pattern(header).tags) except ValueError: return [] else: return util.tagsplit(header) class SongListDnDMixin(GObject.GObject): """DnD support for the SongList class""" def setup_drop(self, library): self.connect('drag-begin', self.__drag_begin) self.connect('drag-motion', self.__drag_motion) self.connect('drag-leave', self.__drag_leave) self.connect('drag-data-get', self.__drag_data_get) self.connect('drag-data-received', self.__drag_data_received, library) def __drag_begin(self, *args): ok, state = Gtk.get_current_event_state() if ok and state & qltk.get_primary_accel_mod(): self.__force_copy = True else: self.__force_copy = False def enable_drop(self, by_row=True): targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY | Gdk.DragAction.MOVE) self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY | Gdk.DragAction.MOVE) self.__drop_by_row = by_row self.__force_copy = False def disable_drop(self): targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) self.drag_dest_unset() def __drag_motion(self, view, ctx, x, y, time): if self.__drop_by_row: self.set_drag_dest(x, y) self.scroll_motion(x, y) if Gtk.drag_get_source_widget(ctx) == self and \ not self.__force_copy: kind = Gdk.DragAction.MOVE else: kind = Gdk.DragAction.COPY Gdk.drag_status(ctx, kind, time) return True else: self.get_parent().drag_highlight() Gdk.drag_status(ctx, Gdk.DragAction.COPY, time) return True def __drag_leave(self, widget, ctx, time): widget.get_parent().drag_unhighlight() self.scroll_disable() def __drag_data_get(self, view, ctx, sel, tid, etime): model, paths = self.get_selection().get_selected_rows() if tid == DND_QL: songs = [model[path][0] for path in paths if model[path][0].can_add] if len(songs) != len(paths): qltk.ErrorMessage( qltk.get_top_parent(self), _("Unable to copy songs"), _("The files selected cannot be copied to other " "song lists or the queue.")).run() Gdk.drag_abort(ctx, etime) return qltk.selection_set_songs(sel, songs) # DEM 2018/05/25: The below check is a deliberate repetition of # code in the drag-motion signal handler. In MacOS/Quartz, the # context action is not propogated between event handlers for # drag-motion and drag-data-get using "ctx.get_actions()". It is # unclear if this is a bug or expected behavior. Regardless, the # context widget information is the same so identical behavior can # be achieved by simply using the same widget check as in the move # action. if Gtk.drag_get_source_widget(ctx) == self and \ not self.__force_copy: self.__drag_iters = list(map(model.get_iter, paths)) else: self.__drag_iters = [] else: uris = [model[path][0]("~uri") for path in paths] sel.set_uris(uris) self.__drag_iters = [] def __drag_data_received(self, view, ctx, x, y, sel, info, etime, library): model = view.get_model() if info == DND_QL: filenames = qltk.selection_get_filenames(sel) move = bool(ctx.get_selected_action() & Gdk.DragAction.MOVE) elif info == DND_URI_LIST: def to_filename(s): try: return uri2fsn(s) except ValueError: return None filenames = list(filter(None, map( to_filename, sel.get_uris()))) move = False else: Gtk.drag_finish(ctx, False, False, etime) return # Should always have one here, but you never know (also: types) librarian = library.librarian or library to_add = [] for filename in filenames: if filename not in librarian: library.add_filename(filename) elif filename not in library: to_add.append(librarian[filename]) library.add(to_add) songs: List = list(filter(None, map(library.get, filenames))) if not songs: Gtk.drag_finish(ctx, bool(not filenames), False, etime) return if not self.__drop_by_row: success = self.__drag_data_browser_dropped(songs) Gtk.drag_finish(ctx, success, False, etime) return try: path, position = view.get_dest_row_at_pos(x, y) except TypeError: path = max(0, len(model) - 1) position = Gtk.TreeViewDropPosition.AFTER if move and Gtk.drag_get_source_widget(ctx) == view: iter = model.get_iter(path) # model can't be empty, we're moving if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): while self.__drag_iters: model.move_before(self.__drag_iters.pop(0), iter) else: while self.__drag_iters: model.move_after(self.__drag_iters.pop(), iter) Gtk.drag_finish(ctx, True, False, etime) else: song = songs.pop(0) try: iter = model.get_iter(path) except ValueError: iter = model.append(row=[song]) # empty model else: if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): iter = model.insert_before(iter, [song]) else: iter = model.insert_after(iter, [song]) for song in songs: iter = model.insert_after(iter, [song]) Gtk.drag_finish(ctx, True, move, etime) def __drag_data_browser_dropped(self, songs): window = qltk.get_top_parent(self) return window.browser.dropped(songs) class SongList(AllTreeView, SongListDnDMixin, DragScroll, util.InstanceTracker): """A TreeView containing a list of songs.""" __gsignals__: GSignals = { 'songs-removed': (GObject.SignalFlags.RUN_LAST, None, (object,)), 'orders-changed': (GObject.SignalFlags.RUN_LAST, None, []) } headers: List[str] = [] """The list of current headers.""" star = list(Query.STAR) def Menu(self, header, browser, library): songs = self.get_selected_songs() if not songs: return def Filter(t): # Translators: The substituted string is the name of the # selected column (a translated tag name). b = qltk.MenuItem( _("_Filter on %s") % util.tag(t, True), Icons.EDIT_FIND) b.connect('activate', self.__filter_on, t, songs, browser) return b header = header_tag_split(header)[0] can_filter = browser.can_filter menu_items = [] if header not in ["artist", "album"] and can_filter(header): menu_items.append(Filter(header)) if can_filter("artist"): menu_items.append(Filter("artist")) if can_filter("album"): menu_items.append(Filter("album")) menu = browser.Menu(songs, library, items=[menu_items]) menu.show_all() return menu def __init__(self, library, player=None, update=False, model_cls=PlaylistModel, sortable: bool = True): super().__init__() self._sortable = sortable self._register_instance(SongList) self.set_model(model_cls()) self.info = SongSelectionInfo(self) self.set_size_request(200, 150) self.set_rules_hint(True) self.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.set_fixed_height_mode(True) self.__csig = self.connect('columns-changed', self.__columns_changed) self._first_column = None # A priority list of how to apply the sort keys. # might contain column header names not present... self._sort_sequence: List[str] = [] self.set_column_headers(self.headers) librarian = library.librarian or library connect_destroy(librarian, 'changed', self.__song_updated) connect_destroy(librarian, 'removed', self.__song_removed, player) if update: connect_destroy(librarian, 'added', self.__song_added) if player: connect_destroy(player, 'paused', lambda *x: self.__redraw_current()) connect_destroy(player, 'unpaused', lambda *x: self.__redraw_current()) connect_destroy(player, 'error', lambda *x: self.__redraw_current()) self.connect('button-press-event', self.__button_press, library) self.connect('key-press-event', self.__key_press, library, player) self.setup_drop(library) self.disable_drop() self.set_search_equal_func(self.__search_func, None) self.connect('destroy', self.__destroy) @property def sortable(self) -> bool: """Whether the columns clicked to enable sorting of songs""" return self._sortable @sortable.setter def sortable(self, value: bool): # It's either sortable or clickable columns, both ends in a buggy UI (see #4099) always_sortable = config.getboolean("song_list", "always_allow_sorting") self._sortable = value or always_sortable self.set_headers_clickable(value) @property def model(self) -> Gtk.TreeModel: return self.get_model() @property def sourced(self): return self.model.sourced def toggle_column_sort(self, column, replace=True, refresh=True): """Toggles the sort order of a column. If not sorted, defaults to Gtk.SortType.ASCENDING If replace is False, the column will be appended to existing sorted columns. If it replaces a sort sequence where it was part of before it will not toggle itself, only remove the other ones. If refresh is True, the song list will be resorted. """ if not self.sortable: return # update the sort priority list if replace: del self._sort_sequence[:] else: try: self._sort_sequence.remove(column.header_name) except ValueError: pass self._sort_sequence.append(column.header_name) # in case we replace a multi sort with one sort that was part before # don't toggle, because it usually means we want to get rid of # the other one dont_reverse = False if replace and column.get_sort_indicator(): for c in self.get_columns(): if c is not column and c.get_sort_indicator(): dont_reverse = True break # set the indicators default_order = Gtk.SortType.ASCENDING for c in self.get_columns(): if c is column: if c.get_sort_indicator(): if dont_reverse: order = c.get_sort_order() else: order = not c.get_sort_order() else: order = default_order c.set_sort_order(order) c.set_sort_indicator(True) if not replace: break elif replace: c.set_sort_indicator(False) if refresh: songs = self.get_songs() song_order = self._get_song_order(songs) self.model.reorder(song_order) selection = self.get_selection() _, paths = selection.get_selected_rows() if paths: self.scroll_to_cell(paths[0], use_align=True, row_align=0.5) self.emit("orders-changed") def find_default_sort_column(self): """Returns a column that will sort using only the default sort key or None if none can't be found """ for c in self.get_columns(): # get_sort_tag == "" if the default sort key should be used if not get_sort_tag(c.header_name): return c def is_sorted(self): """If any of the columns has a sort indicator. This does not mean that the list content is sorted. """ for c in self.get_columns(): if c.get_sort_indicator(): return True return False def clear_sort(self): """Remove all column sort indicators""" for h in self.get_columns(): h.set_sort_indicator(False) del self._sort_sequence[:] self.emit("orders-changed") def get_sort_orders(self): """Returns a list of tuples (header_name, descending)""" sorted_ = [c for c in self.get_columns() if c.get_sort_indicator()] # if someone adds columns and sorts them using the TV API directly.. # better not crash I guess for c in sorted_: if c.header_name not in self._sort_sequence: self._sort_sequence.append(c.header_name) sorted_.sort(key=lambda c: self._sort_sequence.index(c.header_name)) return [(c.header_name, bool(c.get_sort_order())) for c in sorted_] def set_sort_orders(self, orders): """Pass a value returned by get_sort_orders() to restore the state""" if not self.sortable: return self._sort_sequence = [tag for tag, o in orders] orders = dict(orders) for c in self.get_columns(): if c.header_name in orders: c.set_sort_indicator(True) c.set_sort_order(orders[c.header_name]) else: c.set_sort_indicator(False) self.emit("orders-changed") def __destroy(self, *args): self.info.destroy() self.info = None self.handler_block(self.__csig) for column in self.get_columns(): self.remove_column(column) self.handler_unblock(self.__csig) def __search_func(self, model, column, key, iter, *args): for column in self.get_columns(): value = model.get_value(iter)(column.header_name) if not isinstance(value, str): continue elif key in value.lower() or key in value: return False else: return True def __filter_on(self, widget, header, songs, browser): if not browser: return # Fall back to the playing song if songs is None: if app.player.song: songs = [app.player.song] else: return browser.filter_on(songs, header) def __button_press(self, view, event, librarian): if event.button != Gdk.BUTTON_PRIMARY: return x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: return True if event.window != self.get_bin_window(): return False if col.header_name == "~rating": if not config.getboolean("browsers", "rating_click"): return song = view.get_model()[path][0] l = Gtk.Label() l.show() l.set_text(config.RATINGS.full_symbol) width = l.get_preferred_size()[1].width l.destroy() if not width: return False precision = config.RATINGS.precision count = int(float(cellx - 5) / width) + 1 rating = max(0.0, min(1.0, count * precision)) if rating <= precision and song("~#rating") == precision: rating = 0.0 self.__set_rating(rating, [song], librarian) def __set_rating(self, value, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): dialog = ConfirmRateMultipleDialog(self, count, value) if dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value librarian.changed(songs) def __key_press(self, songlist, event, librarian, player): if qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): self.__enqueue(self.get_selected_songs()) return True elif qltk.is_accel(event, "<Primary>F"): self.emit('start-interactive-search') return True elif qltk.is_accel(event, "<Primary>Delete"): songs = self.get_selected_songs() if songs: trash_songs(self, songs, librarian) return True elif qltk.is_accel(event, "<alt>Return"): songs = self.get_selected_songs() if songs: window = SongProperties(librarian, songs, parent=self) window.show() return True elif qltk.is_accel(event, "<Primary>I"): songs = self.get_selected_songs() if songs: window = Information(librarian, songs, self) window.show() return True elif qltk.is_accel(event, "space", "KP_Space") and player is not None: player.paused = not player.paused return True elif qltk.is_accel(event, "F2"): songs = self.get_selected_songs() if len(songs) > 1: print_d("Can't edit more than one") elif songs: path, col = songlist.get_cursor() song = self.get_first_selected_song() cls = type(col).__name__ if col.can_edit: print_d(f"Let's edit this: {song} ({cls} can be edited)") renderers = col.get_cells() renderers[0].props.editable = True self.set_cursor(path, col, start_editing=True) else: print_d(f"Can't edit {cls}. Maybe it's synthetic / numeric?") return False def __enqueue(self, songs): songs = [s for s in songs if s.can_add] if songs: from quodlibet import app app.window.playlist.enqueue(songs) def __redraw_current(self): model = self.get_model() iter_ = model.current_iter if iter_: path = model.get_path(iter_) model.row_changed(path, iter_) def __columns_changed(self, *args): headers = [h.header_name for h in self.get_columns()] SongList.set_all_column_headers(headers) SongList.headers = headers def __column_width_changed(self, *args): # make sure non-resizable columns stay non-expanding. # gtk likes to change them sometimes for c in self.get_columns(): if not c.get_resizable() and c.get_expand(): c.set_expand(False) widths = [] expands = [] for c in self.get_columns(): if not c.get_resizable(): continue widths.extend((c.header_name, str(c.get_fixed_width()))) expands.extend((c.header_name, str(int(c.get_expand())))) config.setstringlist("memory", "column_widths", widths) config.setstringlist("memory", "column_expands", expands) @classmethod def set_all_column_headers(cls, headers): set_columns(headers) try: headers.remove("~current") except ValueError: pass cls.headers = headers for listview in cls.instances(): listview.set_column_headers(headers) star = list(Query.STAR) for header in headers: for tag in header_tag_split(header): if not tag.startswith("~#") and tag not in star: star.append(tag) for tag in config.getlist("settings", "search_tags"): if tag and tag not in star: star.append(tag) SongList.star = star def set_model(self, model): super().set_model(model) self.set_search_column(0) def clear(self): """Remove all songs""" model = self.get_model() if model: model.clear() def get_songs(self): """Get all songs currently in the song list""" model = self.get_model() if not model: return [] return model.get() def _get_song_order(self, songs: List[AudioFile]) -> Optional[Sequence[int]]: """Returns mapping from new position to position in given list of songs when sorted based on the column sort orders""" orders = self.get_sort_orders() if orders: song_order = list(range(len(songs))) for key, reverse in self.__get_song_sort_key_func(orders): song_order.sort(key=lambda i: key(songs[i]), reverse=reverse) return song_order else: return None def __get_song_sort_key_func(self, order): last_tag = None last_order = None first = True key_func = [] for tag, reverse in order: tag = get_sort_tag(tag) # always sort using the default sort key first if first: first = False key_func.append((lambda s: s.sort_key, reverse)) last_order = reverse last_tag = "" # no need to sort twice in a row with the same key/order if tag == last_tag and last_order == reverse: continue last_order = reverse last_tag = tag if tag == "": key_func.append((lambda s: s.sort_key, reverse)) else: sort_func = AudioFile.sort_by_func(tag) key_func.append((sort_func, reverse)) return key_func def add_songs(self, songs): """Add songs to the list in the right order and position""" if not songs: return model = self.get_model() if not len(model): self.set_songs(songs, scroll=False) return if not self.is_sorted(): model.append_many(songs) return for song in songs: insert_iter = self.__find_song_position(song) model.insert_before(insert_iter, row=[song]) def set_songs(self, songs: List[AudioFile], sorted: bool = False, scroll: bool = True, scroll_select: bool = False): """Fill the song list. If sorted is True, the passed songs will not be sorted and all sort indicators will be removed. If scroll is True the list will scroll to the current song. If scroll_select is True restore the selection of the first selected song and scroll to. Falls back to the current song. """ model = self.get_model() assert model is not None song_order = None if not sorted: # make sure some sorting is set and visible if not self.is_sorted(): default = self.find_default_sort_column() if default: self.toggle_column_sort(default, refresh=False) song_order = self._get_song_order(songs) else: self.clear_sort() restore_song = None if scroll_select: restore_song = self.get_first_selected_song() with self.without_model() as model: model.set(songs) if song_order: model.reorder(song_order) # scroll to the first selected or current song and restore # selection for the first selected item if there was one if scroll or scroll_select: if restore_song is not None and restore_song is not model.current: try: index = songs.index(restore_song) except ValueError: path = model.current_path else: path = Gtk.TreePath.new() path.append_index(index) else: path = model.current_path if path is not None: if restore_song is not None: self.set_cursor(path) self.scroll_to_cell(path, use_align=True, row_align=0.5) # the song selection has queued a change now, cancel that and # pass the songs manually self.info._update_songs(songs) def jump_to_song(self, song, select=False): """Scrolls to and selects the given song if in the list. Returns True if the song was found. """ model = self.get_model() if not model: return False # fast path if song == model.current: path = model.current_path else: iter_ = model.find(song) if iter_ is None: return False path = model.get_path(iter_) if select: self.set_cursor(path) self.scroll_to_cell(path, use_align=True, row_align=0.5) return True def get_first_selected_song(self): """The first selected song in the list or None""" selection = self.get_selection() model, paths = selection.get_selected_rows() if paths: return model.get_value(model.get_iter(paths[0])) def get_selected_songs(self): """Returns a list of selected songs""" songs = [] def func(model, path, iter_, user_data): songs.append(model.get_value(iter_)) selection = self.get_selection() selection.selected_foreach(func, None) return songs def __find_song_position(self, song): """Finds the appropriate position of a song in a sorted song list. Returns iter of the song after the given song according to the current sort order. Returns None if the correct position is at the end of the song list. """ model = self.get_model() order = self.get_sort_orders() sort_key_func = list(enumerate(reversed( self.__get_song_sort_key_func(order)))) song_sort_keys = [key(song) for i, (key, r) in sort_key_func] i = 0 j = len(model) while i < j: mid = (i + j) // 2 other_song_iter = model.iter_nth_child(None, mid) other_song = model.get_value(other_song_iter) song_is_lower = False for i, (key, reverse) in sort_key_func: other_key = key(other_song) is_lower = song_sort_keys[i] < other_key is_greater = song_sort_keys[i] > other_key if not reverse and is_lower or reverse and is_greater: song_is_lower = True break if not reverse and is_greater or reverse and is_lower: break if song_is_lower: j = mid else: i = mid + 1 if i < len(model): return model.iter_nth_child(None, i) return None def __find_iters_in_selection(self, songs) -> Tuple[List, List, bool]: model, rows = self.get_selection().get_selected_rows() rows = rows or [] iters = [] removed_songs = [] for r in rows: if model[r][0] in songs: iters.append(model[r].iter) removed_songs.append(model[r][0]) complete = len(iters) == len(songs) return iters, removed_songs, complete def __song_updated(self, librarian, songs): """Only update rows that are currently displayed. Warning: This makes the row-changed signal useless. """ model = self.get_model() if config.getboolean("song_list", "auto_sort") and self.is_sorted(): iters, _, complete = self.__find_iters_in_selection(songs) if not complete: iters = model.find_all(songs) rows = [Gtk.TreeRowReference.new(model, model.get_path(i)) for i in iters] for row in rows: iter = model.get_iter(row.get_path()) song = model.get_value(iter) insert_iter = self.__find_song_position(song) model.move_before(iter, insert_iter) vrange = self.get_visible_range() if vrange is None: return (start,), (end,) = vrange for path in range(start, end + 1): row = model[path] if row[0] in songs: model.row_changed(row.path, row.iter) def __song_added(self, librarian, songs): window = qltk.get_top_parent(self) filter_ = window.browser.active_filter if callable(filter_): self.add_songs(list(filter(filter_, songs))) def __song_removed(self, librarian, songs, player): try: # The player needs to be called first so it can ge the next song # in case the current one gets deleted and the order gets reset. if player: for song in songs: player.remove(song) model = self.get_model() # The selected songs are removed from the library and should # be removed from the view. if not len(model): return songs = set(songs) # search in the selection first # speeds up common case: select songs and remove them iters, removed_songs, complete = self.__find_iters_in_selection(songs) # if not all songs were in the selection, search the whole view if not complete: removed_songs = [] for iter_, value in self.model.iterrows(): if value in songs: iters.append(iter_) removed_songs.append(value) if removed_songs: self.emit('songs-removed', set(removed_songs)) self.remove_iters(iters) except Exception as e: print_w(f"Couldn't process removed songs: {e}", self) def set_first_column_type(self, column_type): """Set a column that will be included at the beginning""" self._first_column = column_type # refresh self.set_column_headers(self.headers) # Build a new filter around our list model, set the headers to their # new values. def set_column_headers(self, headers): if len(headers) == 0: return self.handler_block(self.__csig) old_sort = self.get_sort_orders() for column in self.get_columns(): self.remove_column(column) if self._first_column: column = self._first_column() self.append_column(column) cws = config.getstringlist("memory", "column_widths") column_widths = {} for i in range(0, len(cws), 2): column_widths[cws[i]] = int(cws[i + 1]) ce = config.getstringlist("memory", "column_expands") column_expands = {} for i in range(0, len(ce), 2): column_expands[ce[i]] = int(ce[i + 1]) for t in headers: column = create_songlist_column(self.model, t) if column.get_resizable(): if t in column_widths: column.set_fixed_width(column_widths[t]) if t in column_expands: column.set_expand(column_expands[t]) else: column.set_expand(True) def column_clicked(column, *args): # if ctrl is held during the sort click, append a sort key # or change order if already sorted ctrl_held = False event = Gtk.get_current_event() if event: ok, state = event.get_state() if ok and state & qltk.get_primary_accel_mod(): ctrl_held = True self.toggle_column_sort(column, replace=not ctrl_held) column.connect('clicked', column_clicked) column.connect('button-press-event', self.__showmenu) column.connect('popup-menu', self.__showmenu) column.connect('notify::width', self.__column_width_changed) column.set_reorderable(True) self.append_column(column) self.set_sort_orders(old_sort) self.columns_autosize() self.handler_unblock(self.__csig) def _menu(self, column: SongListColumn) -> Gtk.Menu: menu = Gtk.Menu() def selection_done_cb(menu): menu.destroy() menu.connect('selection-done', selection_done_cb) current_set = set(SongList.headers) def tag_title(tag: str): if "<" in tag: return util.pattern(tag) return util.tag(tag) current = [(tag_title(c), c) for c in SongList.headers] def add_header_toggle(menu: Gtk.Menu, pair: Tuple[str, str], active: bool, column: SongListColumn = column): header, tag = pair item = Gtk.CheckMenuItem(label=header) item.tag = tag item.set_active(active) item.connect('activate', self.__toggle_header_item, column) item.show() item.set_tooltip_text(tag) menu.append(item) for header in current: add_header_toggle(menu, header, True) sep = SeparatorMenuItem() sep.show() menu.append(sep) trackinfo = """title genre comment ~title~version ~#track ~#playcount ~#skipcount ~rating ~#length ~playlists bpm initialkey""".split() peopleinfo = """artist ~people performer arranger author composer conductor lyricist originalartist""".split() albuminfo = """album ~album~discsubtitle labelid ~#disc ~#discs ~#tracks albumartist""".split() dateinfo = """date originaldate recordingdate ~year ~originalyear ~#laststarted ~#lastplayed ~#added ~#mtime""".split() fileinfo = """~format ~#bitdepth ~#bitrate ~#filesize ~filename ~basename ~dirname ~uri ~codec ~encoding ~#channels ~#samplerate""".split() copyinfo = """copyright organization location isrc contact website""".split() all_headers: List[str] = sum( [trackinfo, peopleinfo, albuminfo, dateinfo, fileinfo, copyinfo], []) for name, group in [ (_("All _Headers"), all_headers), (_("_Track Headers"), trackinfo), (_("_Album Headers"), albuminfo), (_("_People Headers"), peopleinfo), (_("_Date Headers"), dateinfo), (_("_File Headers"), fileinfo), (_("_Production Headers"), copyinfo), ]: item = Gtk.MenuItem(label=name, use_underline=True) item.show() menu.append(item) submenu = Gtk.Menu() item.set_submenu(submenu) for header in sorted(zip(map(util.tag, group), group)): add_header_toggle(submenu, header, header[1] in current_set) sep = SeparatorMenuItem() sep.show() menu.append(sep) custom = Gtk.MenuItem( label=_(u"_Customize Headers…"), use_underline=True) custom.show() custom.connect('activate', self.__add_custom_column) menu.append(custom) item = Gtk.CheckMenuItem(label=_("_Expand Column"), use_underline=True) item.set_active(column.get_expand()) item.set_sensitive(column.get_resizable()) def set_expand_cb(item, column): do_expand = item.get_active() if not do_expand: # in case we unexpand, get the current width and set it # so the column doesn't give up all its space # to the left over expanded columns column.set_fixed_width(column.get_width()) else: # in case we expand this seems to trigger a re-distribution # between all expanded columns column.set_fixed_width(-1) column.set_expand(do_expand) self.columns_autosize() sep = SeparatorMenuItem() sep.show() menu.append(sep) item.connect('activate', set_expand_cb, column) item.show() menu.append(item) return menu def __toggle_header_item(self, item, column): headers = SongList.headers[:] if item.get_active(): try: headers.insert(self.get_columns().index(column), item.tag) except ValueError: headers.append(item.tag) else: try: headers.remove(item.tag) except ValueError: pass SongList.set_all_column_headers(headers) SongList.headers = headers def __add_custom_column(self, item): # Prefs has to import SongList, so do this here to avoid # a circular import. from quodlibet.qltk.prefs import PreferencesWindow window = PreferencesWindow(self) window.show() window.set_page("songlist") def __showmenu(self, column, event=None): time = event.time if event else Gtk.get_current_event_time() if event is not None and event.button != Gdk.BUTTON_SECONDARY: return False menu = self._menu(column) menu.attach_to_widget(self, None) if event: menu.popup(None, None, None, None, event.button, time) return True widget = column.get_widget() qltk.popup_menu_under_widget(menu, widget, 3, time) return True @config.register_upgrade_function def _migrate_rating_column(config, old, new): if old < 0: # https://github.com/quodlibet/quodlibet/issues/1381 columns = get_columns()[:] for i, c in enumerate(columns): if c == "~#rating": columns[i] = "~rating" set_columns(columns) ���������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/songlistcolumns.py���������������������������������������������������0000644�0001750�0001750�00000040445�14327505043�020775� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2012 Christoph Reiter # 2011-2022 Nick Boultbee # 2014 Jan Path # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Pango, GLib, Gio from senf import fsnative, fsn2text from quodlibet.util.string.date import format_date from quodlibet import _, print_d from quodlibet import util from quodlibet import config from quodlibet import app from quodlibet.pattern import Pattern from quodlibet.qltk.views import TreeViewColumnButton from quodlibet.qltk import add_css from quodlibet.util.path import unexpand from quodlibet.formats._audio import FILESYSTEM_TAGS from quodlibet.qltk.x import CellRendererPixbuf def create_songlist_column(model: Gtk.TreeModel, t): """Returns a SongListColumn instance for the given tag""" if t in ["~#added", "~#mtime", "~#lastplayed", "~#laststarted"]: return DateColumn(t) elif t in ["~length", "~#length"]: return LengthColumn() elif t == "~#filesize": return FilesizeColumn() elif t in ["~rating"]: return RatingColumn() elif t.startswith("~#"): return NumericColumn(t) elif t in FILESYSTEM_TAGS: return FSColumn(t) elif "<" in t: return PatternColumn(t) elif "~" not in t and t != "title": return NonSynthTextColumn(model, t) else: return WideTextColumn(t) def _highlight_current_cell(cr, background_area, cell_area, flags): """Draws a 'highlighting' background for the cell. Look depends on the active theme. """ # Use drawing code/CSS for Entry (reason being that it looks best here) dummy_widget = Gtk.Entry() style_context = dummy_widget.get_style_context() style_context.save() # Make it less prominent state = Gtk.StateFlags.INSENSITIVE | Gtk.StateFlags.BACKDROP style_context.set_state(state) color = style_context.get_border_color(state) add_css(dummy_widget, "* { border-color: rgba(%d, %d, %d, 0.3); }" % ( color.red * 255, color.green * 255, color.blue * 255)) ba = background_area ca = cell_area # Draw over the left and right border so we don't see the rounded corners # and borders. Use height for the overshoot as rounded corners + border # should never be larger than the height.. # Ideally we would draw over the whole background but the cell area only # redraws the cell_area so we get leftover artifacts if we draw # above/below. draw_area = (ba.x - ca.height, ca.y, ba.width + ca.height * 2, ca.height) cr.save() cr.new_path() cr.rectangle(ba.x, ca.y, ba.width, ca.height) cr.clip() Gtk.render_background(style_context, cr, *draw_area) Gtk.render_frame(style_context, cr, *draw_area) cr.restore() style_context.restore() class SongListCellAreaBox(Gtk.CellAreaBox): highlight = False def do_render(self, context, widget, cr, background_area, cell_area, flags, paint_focus): if self.highlight and not flags & Gtk.CellRendererState.SELECTED: _highlight_current_cell(cr, background_area, cell_area, flags) return Gtk.CellAreaBox.do_render( self, context, widget, cr, background_area, cell_area, flags, paint_focus) def do_apply_attributes(self, tree_model, iter_, is_expander, is_expanded): self.highlight = tree_model.get_path(iter_) == tree_model.current_path return Gtk.CellAreaBox.do_apply_attributes( self, tree_model, iter_, is_expander, is_expanded) class SongListColumn(TreeViewColumnButton): can_edit = False """Whether this column can support editing""" def __init__(self, tag): """tag e.g. 'artist'""" title = self._format_title(tag) super().__init__( title=title, cell_area=SongListCellAreaBox()) self.set_tooltip_text(title) self.header_name = tag self.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.set_visible(True) self.set_sort_indicator(False) self._last_rendered = None def _format_title(self, tag): """Format the column title based on the tag""" return util.tag(tag) def _needs_update(self, value): """Call to check if the last passed value was the same. This is used to reduce formatting if the input is the same either because of redraws or all columns have the same value """ if self._last_rendered == value: return False self._last_rendered = value return True class TextColumn(SongListColumn): """Base text column""" def __init__(self, tag): super().__init__(tag) self._render = Gtk.CellRendererText() self.pack_start(self._render, True) self.set_cell_data_func(self._render, self._cdf) self.set_clickable(True) # We check once in a while if the font size has changed. If it has # we reset the min/fixed width and force at least one cell to update # (which might trigger other column size changes..) self._last_width = None self._force_update = False self._deferred_width_check = util.DeferredSignal( self._check_width_update, timeout=500) def on_tv_changed(column, old, new): if new is None: self._deferred_width_check.abort() else: self._deferred_width_check.call() self.connect("tree-view-changed", on_tv_changed) def _get_min_width(self): return -1 def _cell_width(self, text): """Returns the column width needed for the passed text""" widget = self.get_tree_view() assert widget is not None layout = widget.create_pango_layout(text) text_width = layout.get_pixel_size()[0] cell_pad = self._render.get_property('xpad') return text_width + 8 + cell_pad def _check_width_update(self): width = self._cell_width(u"abc 123") if self._last_width == width: self._force_update = False return self._last_width = width self._force_update = True self.queue_resize() def _needs_update(self, value): return self._force_update or \ super()._needs_update(value) def _cdf(self, column, cell, model, iter_, user_data): self._deferred_width_check() if self._force_update: min_width = self._get_min_width() self.set_min_width(min_width) if not self.get_resizable(): self.set_fixed_width(min_width) # calling it in the cell_data_func leads to broken drawing.. GLib.idle_add(self.queue_resize) value = self._fetch_value(model, iter_) if not self._needs_update(value): return self._apply_value(model, iter_, cell, value) def _fetch_value(self, model, iter_): """Should return everything needed for formatting the final value""" raise NotImplementedError def _apply_value(self, model, iter_, cell, value): """Should format the value and set it on the cell renderer""" raise NotImplementedError class RatingColumn(TextColumn): """Render ~rating directly (simplifies filtering, saves a function call). """ def __init__(self, *args, **kwargs): super().__init__("~rating", *args, **kwargs) self.set_expand(False) self.set_resizable(False) def _get_min_width(self): return self._cell_width(util.format_rating(1.0)) def _fetch_value(self, model, iter_): song = model.get_value(iter_) rating = song.get("~#rating") default = config.RATINGS.default return (rating, default) def _apply_value(self, model, iter_, cell, value): rating, default = value cell.set_sensitive(rating is not None) value = rating if rating is not None else default cell.set_property('text', util.format_rating(value)) class WideTextColumn(TextColumn): """Resizable and ellipsized at the end. Used for any key with a '~' in it, and 'title'. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._render.set_property('ellipsize', Pango.EllipsizeMode.END) self.set_resizable(True) def _get_min_width(self): return self._cell_width("000") def _fetch_value(self, model, iter_): return model.get_value(iter_).comma(self.header_name) def _apply_value(self, model, iter_, cell, value): cell.set_property('text', value) class DateColumn(WideTextColumn): """The '~#' keys that are dates.""" def _fetch_value(self, model, iter_): return model.get_value(iter_)(self.header_name) def _apply_value(self, model, iter_, cell, stamp): if not stamp: cell.set_property('text', _("Never")) else: fmt = config.gettext("settings", "datecolumn_timestamp_format") text = format_date(stamp, fmt) cell.set_property('text', text) class NonSynthTextColumn(WideTextColumn): """Optimize for non-synthesized keys by grabbing them directly. Used for any tag without a '~' except 'title'. """ can_edit = True def __row_edited(self, render, path, new: str, model: Gtk.TreeModel) -> None: print_d(f"Trying to edit {self.header_name} to {new!r}") model[path][0][self.header_name] = new model.path_changed(path) def __init__(self, model, tag): super().__init__(tag) self._render.connect("edited", self.__row_edited, model) def _fetch_value(self, model, iter_): return model.get_value(iter_).get(self.header_name, "") def _apply_value(self, model, iter_, cell, value): cell.set_property('text', value.replace("\n", ", ")) class FSColumn(WideTextColumn): """Contains text in the filesystem encoding, so needs to be decoded safely (and also more slowly). """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._render.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE) def _fetch_value(self, model, iter_): values = model.get_value(iter_).list(self.header_name) return values[0] if values else fsnative(u"") def _apply_value(self, model, iter_, cell, value): cell.set_property('text', fsn2text(unexpand(value))) class PatternColumn(WideTextColumn): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) try: self._pattern = Pattern(self.header_name) except ValueError: self._pattern = None def _format_title(self, tag): return util.pattern(tag) def _fetch_value(self, model, iter_): song = model.get_value(iter_) if self._pattern is not None: return self._pattern % song return u"" def _apply_value(self, model, iter_, cell, value): cell.set_property('text', value) class NumericColumn(TextColumn): """Any '~#' keys except dates.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._render.set_property('xalign', 1.0) self.set_alignment(1.0) self.set_expand(False) self.set_resizable(False) self._texts = {} self._timeout = None def on_tv_changed(column, old, new): if new is None and self._timeout is not None: GLib.source_remove(self._timeout) self._timeout = None self.connect("tree-view-changed", on_tv_changed) def _get_min_width(self): """Give the initial and minimum width. override if needed""" # Best efforts for the general minimum width case # Allows well for >=1000 Kbps, -12.34 dB RG values, "Length" etc return self._cell_width("-22.22") def _fetch_value(self, model, iter_): return model.get_value(iter_).comma(self.header_name) def _apply_value(self, model, iter_, cell, value): if isinstance(value, float): text = u"%.2f" % round(value, 2) else: text = str(value) cell.set_property('text', text) self._recalc_width(model.get_path(iter_), text) def _delayed_recalc(self): self._timeout = None tv = self.get_tree_view() assert tv is not None range_ = tv.get_visible_range() if not range_: return start, end = range_ start = start[0] end = end[0] # compute the cell width for all drawn cells in range +/- 3 for key, value in list(self._texts.items()): if not (start - 3) <= key <= (end + 3): del self._texts[key] elif isinstance(value, str): self._texts[key] = self._cell_width(value) # resize if too small or way too big and above the minimum width = self.get_width() needed_width = max( [self._get_min_width()] + list(self._texts.values())) if width < needed_width: self._resize(needed_width) elif width - needed_width >= self._cell_width("0"): self._resize(needed_width) def _resize(self, width): # In case the treeview has no other expanding columns, setting the # width will have no effect on the actual width. Calling queue_resize() # in that case would result in an endless recalc loop. So stop here. if width == self.get_fixed_width() and width == self.get_max_width(): return self.set_fixed_width(width) self.set_max_width(width) self.queue_resize() def _recalc_width(self, path, text): self._texts[path[0]] = text if self._timeout is not None: GLib.source_remove(self._timeout) self._timeout = None self._timeout = GLib.idle_add(self._delayed_recalc, priority=GLib.PRIORITY_LOW) class LengthColumn(NumericColumn): def __init__(self): super().__init__("~#length") def _get_min_width(self): # 1:22:22, allows entire albums as files (< 75mins) return self._cell_width(util.format_time_display(60 * 82 + 22)) def _fetch_value(self, model, iter_): return model.get_value(iter_).get("~#length", 0) def _apply_value(self, model, iter_, cell, value): text = util.format_time_display(value) cell.set_property('text', text) self._recalc_width(model.get_path(iter_), text) class FilesizeColumn(NumericColumn): def __init__(self): super().__init__("~#filesize") def _get_min_width(self): # e.g "2.22 MB" return self._cell_width(util.format_size(2.22 * (1024 ** 2))) def _fetch_value(self, model, iter_): return model.get_value(iter_).get("~#filesize", 0) def _apply_value(self, model, iter_, cell, value): text = util.format_size(value) cell.set_property('text', text) self._recalc_width(model.get_path(iter_), text) class CurrentColumn(SongListColumn): """Displays the current song indicator, either a play or pause icon.""" def __init__(self): super().__init__("~current") self._render = CellRendererPixbuf() self.pack_start(self._render, True) self._render.set_property('xalign', 0.5) self.set_fixed_width(24) self.set_expand(False) self.set_cell_data_func(self._render, self._cdf) def _format_title(self, tag): return u"" def _cdf(self, column, cell, model, iter_, user_data): PLAY = "media-playback-start" PAUSE = "media-playback-pause" STOP = "media-playback-stop" ERROR = "dialog-error" row = model[iter_] if row.path == model.current_path: player = app.player if player.error: name = ERROR elif model.sourced: name = [PLAY, PAUSE][player.paused] else: name = STOP else: name = None if not self._needs_update(name): return if name is not None: gicon = Gio.ThemedIcon.new_from_names( [name + "-symbolic", name]) else: gicon = None cell.set_property('gicon', gicon) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1675520037.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/songmodel.py���������������������������������������������������������0000644�0001750�0001750�00000023135�14367464045�017530� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2016 Nick Boultbee # 2018-2019 Fredrik Strupe # # 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 2 of the License, or # (at your option) any later version. from typing import Any, Iterable, List, Optional, Sequence, Type from gi.repository import Gtk from quodlibet.order import Order from quodlibet.qltk.playorder import OrderInOrder from quodlibet.qltk.models import ObjectStore from quodlibet.util import print_d from quodlibet import config class PlaylistMux: """Provides the PlaylistModel interface combining the song list model and the queue one. If no longer needed, call destroy(). """ def __init__(self, player, q, pl): self.q = q self.pl = pl self._id = player.connect('song-started', self.__song_started) self._player = player def destroy(self): self._player.disconnect(self._id) def __song_started(self, player, song): if song is not None and self.q.sourced: iter = self.q.find(song) keep_song = config.getboolean("memory", "queue_keep_songs", False) if iter and not keep_song: self.q.remove(iter) # we don't call _check_sourced here since we want the queue # to stay sourced even if no current song is left @property def current(self): """The current song or None""" if self.q.current is not None: return self.q.current else: return self.pl.current def _check_sourced(self): if self.q.current is not None: self.q.sourced = True self.pl.sourced = False else: self.q.sourced = False self.pl.sourced = True def next(self): """Switch to the next song""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_disable = config.getboolean("memory", "queue_disable", False) if (self.q.is_empty() or q_disable or (keep_songs and not self.q.sourced)): self.pl.next() if q_disable and self.q.sourced: # The go_to is to make sure the playlist begins playing # when the queue is disabled while being sourced self.go_to(self.pl.current) else: self.q.next() self._check_sourced() def next_ended(self): """Switch to the next song (action comes from the user)""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_disable = config.getboolean("memory", "queue_disable", False) if (self.q.is_empty() or q_disable or (keep_songs and not self.q.sourced)): self.pl.next_ended() if q_disable and self.q.sourced: self.go_to(self.pl.current) else: self.q.next_ended() self._check_sourced() def previous(self): """Go to the previous song""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_disable = config.getboolean("memory", "queue_disable", False) if q_disable or self.pl.sourced or not keep_songs: self.pl.previous() if q_disable and self.q.sourced: self.go_to(self.pl.current) else: self.q.previous() self._check_sourced() def go_to(self, song, explicit=False, source=None): """Switch the current active song to song. song can be an Gtk.TreeIter or AudioFile. explicit should be True of the action comes from the user. source should be the right PlaylistModel in case song is an iter. """ print_d("Told to go to %r" % getattr(song, "key", song)) main, other = self.pl, self.q if source is not None: assert source in (self.pl, self.q) if source is self.q: main, other = other, main res = main.go_to(song, explicit) if res is not None or not explicit: other.go_to(None) self._check_sourced() return res def reset(self): """Switch to the first song""" self.q.go_to(None) self.pl.reset() self._check_sourced() def enqueue(self, songs): """Append the songs to the queue model""" self.q.append_many(songs) def unqueue(self, songs): """Remove all occurrences of all passed songs in the queue""" q = self.q for iter_ in q.find_all(songs): q.remove(iter_) class TrackCurrentModel(ObjectStore): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__iter = None last_current: Optional[Any] = None """The last valid current song""" def set(self, songs: Sequence[Any]): """Clear the model and add the passed songs""" print_d("Filling view model with %d songs." % len(songs)) self.clear() self.__iter = None oldsong = self.last_current for iter_, song in zip(self.iter_append_many(songs), songs): if song is oldsong: self.__iter = iter_ def get(self) -> List[Any]: """A list of all contained songs""" return list(self.itervalues()) @property def current(self) -> Optional[Any]: """The current song or None""" return self.__iter and self.get_value(self.__iter, 0) @property def current_path(self): """The Gtk.TreePath of the current song or None""" return self.__iter and self.get_path(self.__iter) @property def current_iter(self): """The Gtk.TreeIter of the current song or None""" return self.__iter @current_iter.setter def current_iter(self, iter_): if iter_ == self.__iter: return # emit a row-changed for the previous and the new iter after it is set # so that the currentcolumn icon gets updated on song changes for it in filter(None, (self.__iter, iter_)): self.row_changed(self.get_path(it), it) self.__iter = iter_ self.last_current = self.current def find(self, song: Any): """Returns the iter to the first occurrence of song in the model or None if it wasn't found. """ # fast path if self.current == song: return self.current_iter # search the rest for iter_, value in self.iterrows(): if value == song: return iter_ return def find_all(self, songs: Iterable[Any]): """Returns a list of iters for all occurrences of all songs. (since a song can be in the model multiple times) """ songs = set(songs) return [iter_ for iter_, value in self.iterrows() if value in songs] def remove(self, iter_): if self.__iter and self[iter_].path == self[self.__iter].path: self.__iter = None super().remove(iter_) def clear(self): self.__iter = None super().clear() def __contains__(self, song): return bool(self.find(song)) class PlaylistModel(TrackCurrentModel): """A play list model for song lists""" order: Order """The active play order""" sourced = False """True in case this model is the source of the currently playing song""" def __init__(self, order_cls: Type[Order] = OrderInOrder): super().__init__(object) self.order = order_cls() def next(self): """Switch to the next song""" iter_ = self.current_iter print_d("Using %s.next_explicit() to get next song" % self.order) self.current_iter = self.order.next_explicit(self, iter_) def next_ended(self): """Switch to the next song (action comes from the user)""" iter_ = self.current_iter print_d("Using %s.next_implicit() to get next song" % self.order) self.current_iter = self.order.next_implicit(self, iter_) def previous(self): """Go to the previous song""" iter_ = self.current_iter self.current_iter = self.order.previous_explicit(self, iter_) def go_to(self, song_or_iter, explicit=False, source=None): """Switch the current active song to song. song can be an Gtk.TreeIter or AudioFile. explicit should be True of the action comes from the user. source should be this model or None. """ assert source is None or source is self print_d("Told to go to %r" % getattr(song_or_iter, "key", song_or_iter)) iter_ = None if isinstance(song_or_iter, Gtk.TreeIter): iter_ = song_or_iter elif song_or_iter is not None: # We were told to go to a song that was valid but couldn't find it. # Set it as last current so it gets set current when we find it in # the future. self.last_current = song_or_iter iter_ = self.find(song_or_iter) if explicit: self.current_iter = self.order.set_explicit(self, iter_) else: self.current_iter = self.order.set_implicit(self, iter_) return self.current_iter def set(self, songs: Sequence[Any]): """Clear the model and add the passed songs""" self.order.reset(self) super().set(songs) def reset(self): """Switch to the first song""" self.go_to(None) self.order.reset(self) if not self.is_empty(): self.next() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/songsmenu.py���������������������������������������������������������0000644�0001750�0001750�00000043302�14327505043�017543� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2013-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.formats import AudioFile from quodlibet.plugins.gui import MenuItemPlugin from quodlibet.plugins.songshelpers import is_a_file from quodlibet.qltk.chooser import choose_folders from quodlibet.qltk.download import DownloadProgress from quodlibet.qltk.pluginwin import PluginWindow from quodlibet import ngettext, _, print_d, app, util from quodlibet import qltk from quodlibet.errorreport import errorhook from quodlibet.qltk.showfiles import show_songs from quodlibet.util import print_e, print_w, copool from quodlibet.qltk.msg import ConfirmationPrompt, ErrorMessage, Message from quodlibet.qltk.delete import TrashMenuItem, trash_songs from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.x import SeparatorMenuItem from quodlibet.qltk.ratingsmenu import RatingsMenuItem from quodlibet.qltk import get_top_parent, get_menu_item_top_parent, Icons from quodlibet.plugins import PluginManager, PluginHandler from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.util.songwrapper import ListWrapper, check_wrapper_changed def confirm_song_removal_invoke(parent, songs): songs = set(songs) if not songs: return True count = len(songs) song = next(iter(songs)) if count == 1: title = _("Remove track: \"%(title)s\" from the library?") % { 'title': song('title') or song('~basename')} else: title = _("Remove %(count)d tracks from the library?") % { 'count': count} prompt = ConfirmationPrompt(parent, title, "", _("Remove from Library"), ok_button_icon=Icons.LIST_REMOVE) return prompt.run() == ConfirmationPrompt.RESPONSE_INVOKE def confirm_multi_song_invoke(parent, plugin_name, count): """Dialog to confirm invoking a plugin with X songs in case X is high""" title = ngettext("Run the plugin \"%(name)s\" on %(count)d song?", "Run the plugin \"%(name)s\" on %(count)d songs?", count) % {"name": plugin_name, "count": count} description = "" ok_text = _("_Run Plugin") prompt = ConfirmationPrompt(parent, title, description, ok_text).run() return prompt == ConfirmationPrompt.RESPONSE_INVOKE def confirm_multi_album_invoke(parent, plugin_name, count): """Dialog to confirm invoking a plugin with X albums in case X is high""" title = ngettext("Run the plugin \"%(name)s\" on %(count)d album?", "Run the plugin \"%(name)s\" on %(count)d albums?", count) % {"name": plugin_name, "count": count} description = "" ok_text = _("_Run Plugin") prompt = ConfirmationPrompt(parent, title, description, ok_text).run() return prompt == ConfirmationPrompt.RESPONSE_INVOKE class SongsMenuPluginHandler(PluginHandler): def __init__(self, song_confirmer=None, album_confirmer=None): """custom confirmers for testing""" self.__plugins = [] self._confirm_multiple_songs = confirm_multi_song_invoke if song_confirmer is not None: self._confirm_multiple_songs = song_confirmer self._confirm_multiple_albums = confirm_multi_album_invoke if album_confirmer is not None: self._confirm_multiple_albums = album_confirmer def Menu(self, library, songs): songs = ListWrapper(songs) attrs = ['plugin_song', 'plugin_songs', 'plugin_album', 'plugin_albums'] if len(songs) == 1: attrs.append('plugin_single_song') last = (songs and songs[-1]) or None for song in songs: if song.album_key != last.album_key: break last = song else: attrs.append('plugin_single_album') items = [] kinds = self.__plugins kinds.sort(key=lambda plugin: plugin.PLUGIN_ID) for Kind in kinds: usable = any(callable(getattr(Kind, s)) for s in attrs) if usable: try: items.append(Kind(songs, library)) except: print_e("Couldn't initialise song plugin %s. Stack trace:" % Kind) errorhook() items = [i for i in items if i.initialized] if items: menu = Gtk.Menu() for item in items: try: menu.append(item) args = (library, songs) if item.get_submenu(): for subitem in item.get_submenu().get_children(): subitem.connect( 'activate', self.__on_activate, item, *args) else: item.connect( 'activate', self.__on_activate, item, *args) except: errorhook() item.destroy() menu.append(SeparatorMenuItem()) prefs = Gtk.MenuItem(label=_("Configure Plugins…")) prefs.connect("activate", lambda _: PluginWindow().show()) menu.append(prefs) else: menu = None return menu def __get_albums(self, songs): albums = {} for song in songs: key = song.album_key if key not in albums: albums[key] = [] albums[key].append(song) albums = list(albums.values()) for album in albums: album.sort() return albums def handle(self, plugin_id, library, parent, songs): """Start a song menu plugin directly without a menu""" parent = get_top_parent(parent) for plugin in self.__plugins: if plugin.PLUGIN_ID == plugin_id: songs = ListWrapper(songs) try: plugin = plugin(songs, library) except Exception: errorhook() else: self.__handle(plugin, plugin, library, songs, parent) return def __on_activate(self, item, plugin, library, songs): parent = get_menu_item_top_parent(item) self.__handle(item, plugin, library, songs, parent) def __handle(self, item, plugin, library, songs, parent): if len(songs) == 0: return try: if len(songs) == 1 and callable(plugin.plugin_single_song): try: ret = plugin.plugin_single_song(songs[0]) except Exception: errorhook() else: if ret: return if callable(plugin.plugin_song): total = len(songs) if total > plugin.MAX_INVOCATIONS: if not self._confirm_multiple_songs( parent, plugin.PLUGIN_NAME, total): return try: ret = map(plugin.plugin_song, songs) except Exception: errorhook() else: if any(ret): return if callable(plugin.plugin_songs): try: ret = plugin.plugin_songs(songs) except Exception: errorhook() else: if ret: return if plugin.handles_albums: albums = self.__get_albums(songs) total = len(albums) if total > plugin.MAX_INVOCATIONS: if not self._confirm_multiple_albums( parent, plugin.PLUGIN_NAME, total): return if callable(plugin.plugin_single_album) and len(albums) == 1: try: ret = plugin.plugin_single_album(albums[0]) except Exception: errorhook() else: if ret: return if callable(plugin.plugin_album): try: ret = map(plugin.plugin_album, albums) except Exception: errorhook() else: if any(ret): return if callable(plugin.plugin_albums): try: ret = plugin.plugin_albums(albums) except Exception: errorhook() else: if ret: return finally: check_wrapper_changed(library, filter(None, songs)) def plugin_handle(self, plugin): return issubclass(plugin.cls, SongsMenuPlugin) def plugin_enable(self, plugin): self.__plugins.append(plugin.cls) def plugin_disable(self, plugin): self.__plugins.remove(plugin.cls) class SongsMenu(Gtk.Menu): plugins = SongsMenuPluginHandler() @classmethod def init_plugins(cls): PluginManager.instance.register_handler(cls.plugins) def __init__(self, library, songs, plugins=True, playlists=True, queue=True, remove=True, delete=False, edit=True, info=True, ratings=True, show_files=True, download=False, items=None, accels=True, removal_confirmer=None, folder_chooser=None): super().__init__() # The library may actually be a librarian; if it is, use it, # otherwise find the real librarian. librarian = getattr(library, 'librarian', library) if ratings: ratings_item = RatingsMenuItem(songs, librarian) ratings_item.set_sensitive(bool(songs)) self.append(ratings_item) self.separate() # external item groups for subitems in reversed(items or []): self.separate() for item in subitems: self.append(item) self.separate() if plugins: submenu = self.plugins.Menu(librarian, songs) if submenu is not None: b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN) b.set_sensitive(bool(songs)) self.append(b) b.set_submenu(submenu) self.append(SeparatorMenuItem()) in_lib = True can_add = True is_file = True for song in songs: if song not in library: in_lib = False if not song.can_add: can_add = False if not song.is_file: is_file = False if playlists: try: from quodlibet.browsers.playlists.menu import PlaylistMenu submenu = PlaylistMenu(songs, library.playlists) except AttributeError as e: print_w("Couldn't get Playlists menu: %s" % e) else: b = qltk.MenuItem(_("Play_lists"), Icons.FOLDER_DRAG_ACCEPT) b.set_sensitive(can_add and bool(songs)) b.set_submenu(submenu) self.append(b) if queue: b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD) def enqueue_cb(item, songs): songs = [s for s in songs if s.can_add] if songs: from quodlibet import app app.window.playlist.enqueue(songs) b.connect('activate', enqueue_cb, songs) if accels: qltk.add_fake_accel(b, "<Primary>Return") self.append(b) b.set_sensitive(can_add and bool(songs)) if remove or delete: self.separate() if remove: self._confirm_song_removal = (removal_confirmer or confirm_song_removal_invoke) b = qltk.MenuItem(_("_Remove from Library…"), Icons.LIST_REMOVE) if callable(remove): b.connect('activate', lambda item: remove(songs)) else: def remove_cb(item, songs, library): parent = get_menu_item_top_parent(item) if self._confirm_song_removal(parent, songs): library.remove(songs) b.connect('activate', remove_cb, songs, library) b.set_sensitive(in_lib and bool(songs)) self.append(b) if delete: if callable(delete): b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE) b.connect('activate', lambda item: delete(songs)) if accels: qltk.add_fake_accel(b, "<Primary>Delete") else: b = TrashMenuItem() if accels: qltk.add_fake_accel(b, "<Primary>Delete") def trash_cb(item): parent = get_menu_item_top_parent(item) trash_songs(parent, songs, librarian) b.connect('activate', trash_cb) b.set_sensitive(is_file and bool(songs)) self.append(b) if edit: self.separate() b = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT) b.set_sensitive(bool(songs)) if accels: qltk.add_fake_accel(b, "<alt>Return") def song_properties_cb(menu_item): parent = get_menu_item_top_parent(menu_item) window = SongProperties(librarian, songs, parent) window.show() b.connect('activate', song_properties_cb) self.append(b) if info: b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION) b.set_sensitive(bool(songs)) if accels: qltk.add_fake_accel(b, "<Primary>I") def information_cb(menu_item): parent = get_menu_item_top_parent(menu_item) window = Information(librarian, songs, parent) window.show() b.connect('activate', information_cb) self.append(b) if show_files and any(is_a_file(s) for s in songs): def show_files_cb(menu_item): print_d("Trying to show files...") if not show_songs(songs): parent = get_menu_item_top_parent(menu_item) msg = ErrorMessage(parent, _("Unable to show files"), _("Error showing files, " "or no program available to show them.")) msg.run() self.separate() total = len([s for s in songs if is_a_file(s)]) text = ngettext( "_Show in File Manager", "_Show %(total)d Files in File Manager", total) % {"total": total} b = qltk.MenuItem(text, Icons.DOCUMENT_OPEN) b.set_sensitive(bool(songs) and len(songs) < MenuItemPlugin.MAX_INVOCATIONS) b.connect('activate', show_files_cb) self.append(b) if download: def is_downloadable(song: AudioFile): return bool(not song.is_file and song.get("~uri", False)) self.separate() relevant = [s for s in songs if is_downloadable(s)] total = len(relevant) text = ngettext( "_Download file…", "_Download %(total)d files…", total) % {"total": total} b = qltk.MenuItem(text, Icons.EMBLEM_DOWNLOADS) b.set_sensitive(relevant and len(relevant) < MenuItemPlugin.MAX_INVOCATIONS) def _finished(p, successes, failures): msg = (f"{util.bold(successes)} " + _("successful") + f"\n{util.bold(failures)} " + _("failed")) print_d(msg.replace("\n", "; ")) warning = Message(Gtk.MessageType.INFO, app.window, _("Downloads complete"), msg, escape_desc=False) warning.run() def download_cb(menu_item): songs = relevant total = len(songs) msg = ngettext("Download {name!r} to", "Download {total} files to", total) msg = msg.format(name=next(iter(songs))("title")[:99] if total else "?", total=total) chooser = folder_chooser or choose_folders paths = chooser(None, msg, _("Download here"), allow_multiple=False) if not paths: print_d("Cancelling download") return path = paths[0] progress = DownloadProgress(songs) progress.connect('finished', _finished) copool.add(progress.download_songs, path) b.connect('activate', download_cb) self.append(b) def selection_done_cb(menu): menu.destroy() self.connect('selection-done', selection_done_cb) def separate(self): if not self.get_children(): return elif not isinstance(self.get_children()[-1], Gtk.SeparatorMenuItem): self.append(SeparatorMenuItem()) def preseparate(self): if not self.get_children(): return elif not isinstance(self.get_children()[0], Gtk.SeparatorMenuItem): self.prepend(SeparatorMenuItem()) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/tagscombobox.py������������������������������������������������������0000664�0001750�0001750�00000004725�14035600052�020214� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2015 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.util import tag from quodlibet.util.tags import USER_TAGS class _TagsCombo: __tags = sorted(USER_TAGS) def _fill_model(self, can_change): self.clear() render = Gtk.CellRendererText() self.pack_start(render, True) self.add_attribute(render, 'text', 1) if can_change is None: can_change = self.__tags can_change = sorted(can_change) model = self.get_model() for t in can_change: model.append(row=[t, "%s (%s)" % (tag(t), t)]) self.set_model(model) if len(model) == 0: raise ValueError("TagsCombo boxes require at least one tag name") @property def tag(self): return self._tag() class TagsComboBox(Gtk.ComboBox, _TagsCombo): """A ComboBox containing a list of tags for the user to choose from. The tag names are presented both translated and untranslated. The 'tag' attribute is the currently chosen tag.""" def __init__(self, can_change=None): super().__init__(model=Gtk.ListStore(str, str)) self._fill_model(can_change) self.set_active(0) def _tag(self): iter = self.get_active_iter() return self.get_model()[iter][0] class TagsComboBoxEntry(Gtk.ComboBox, _TagsCombo): """A ComboBoxEntry containing a list of tags for the user to choose from. The tag names are presented both translated and untranslated in the menu, but always untranslated when editing. The 'tag' attribute is the currently chosen tag.""" def __init__(self, can_change=None, tooltip_markup=None): super().__init__( model=Gtk.ListStore(str, str), entry_text_column=0, has_entry=True) self._fill_model(can_change) if tooltip_markup: self.get_child().set_tooltip_markup(tooltip_markup) def _fill_model(self, can_change): super()._fill_model(can_change) comp = Gtk.EntryCompletion() comp.set_model(self.get_model()) comp.set_text_column(0) self.get_child().set_completion(comp) def _tag(self): return self.get_child().get_text() �������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/tagsfrompath.py������������������������������������������������������0000644�0001750�0001750�00000026152�14327505043�020230� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. import re import os from gi.repository import Gtk from senf import fsn2text import quodlibet from quodlibet import _, ngettext from quodlibet import config from quodlibet import qltk from quodlibet import util from quodlibet.formats import AudioFileError from quodlibet.plugins import PluginManager from quodlibet.qltk._editutils import FilterPluginBox, FilterCheckButton from quodlibet.qltk._editutils import EditingPluginHandler, OverwriteWarning from quodlibet.qltk._editutils import WriteFailedError from quodlibet.qltk.wlw import WritingWindow from quodlibet.qltk.views import TreeViewColumn from quodlibet.qltk.cbes import ComboBoxEntrySave from quodlibet.qltk.models import ObjectStore from quodlibet.qltk import Icons from quodlibet.util.tagsfrompath import TagsFromPattern from quodlibet.util.string.splitters import split_value from quodlibet.util import connect_obj from quodlibet.plugins.editing import TagsFromPathPlugin TBP = os.path.join(quodlibet.get_user_dir(), "lists", "tagpatterns") TBP_EXAMPLES = """\ <tracknumber>. <title> <tracknumber> - <title> <tracknumber> - <artist> - <title> <artist> - <album>/<tracknumber>. <title> <artist>/<album>/<tracknumber> - <title>""" class UnderscoresToSpaces(FilterCheckButton): _label = _("Replace _underscores with spaces") _section = "tagsfrompath" _key = "underscores" _order = 1.0 def filter(self, tag, value): return value.replace("_", " ") class TitleCase(FilterCheckButton): _label = _("_Title-case tags") _section = "tagsfrompath" _key = "titlecase" _order = 1.1 def filter(self, tag, value): return util.title(value) class SplitTag(FilterCheckButton): _label = _("Split into multiple _values") _section = "tagsfrompath" _key = "split" _order = 1.2 def filter(self, tag, value): spls = config.gettext("editing", "split_on") spls = spls.split() return "\n".join(split_value(value, spls)) class TagsFromPathPluginHandler(EditingPluginHandler): Kind = TagsFromPathPlugin class ListEntry: def __init__(self, song): self.song = song self.matches = {} def get_match(self, key): return self.matches.get(key, u"") def replace_match(self, key, value): self.matches[key] = value @property def name(self): return fsn2text(self.song("~basename")) class TagsFromPath(Gtk.VBox): title = _("Tags From Path") FILTERS = [UnderscoresToSpaces, TitleCase, SplitTag] handler = TagsFromPathPluginHandler() @classmethod def init_plugins(cls): PluginManager.instance.register_handler(cls.handler) def __init__(self, parent, library): super().__init__(spacing=6) self.set_border_width(12) hbox = Gtk.HBox(spacing=6) cbes_defaults = TBP_EXAMPLES.split("\n") self.combo = ComboBoxEntrySave(TBP, cbes_defaults, title=_("Path Patterns"), edit_title=_(u"Edit saved patterns…")) self.combo.show_all() hbox.pack_start(self.combo, True, True, 0) self.preview = qltk.Button(_("_Preview"), Icons.VIEW_REFRESH) self.preview.show() hbox.pack_start(self.preview, False, True, 0) self.pack_start(hbox, False, True, 0) self.combo.get_child().connect('changed', self._changed) model = ObjectStore() self.view = Gtk.TreeView(model=model) self.view.show() sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(self.view) self.pack_start(sw, True, True, 0) vbox = Gtk.VBox() addreplace = Gtk.ComboBoxText() addreplace.append_text(_("Tags replace existing ones")) addreplace.append_text(_("Tags are added to existing ones")) addreplace.set_active(config.getboolean("tagsfrompath", "add")) addreplace.connect('changed', self.__add_changed) vbox.pack_start(addreplace, True, True, 0) addreplace.show() self.pack_start(vbox, False, True, 0) filter_box = FilterPluginBox(self.handler, self.FILTERS) filter_box.connect("preview", self.__filter_preview) filter_box.connect("changed", self.__filter_changed) self.filter_box = filter_box self.pack_start(filter_box, False, True, 0) # Save button self.save = qltk.Button(_("_Save"), Icons.DOCUMENT_SAVE) self.save.show() bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.pack_start(self.save, True, True, 0) self.pack_start(bbox, False, True, 0) connect_obj(self.preview, 'clicked', self.__preview, None) connect_obj(parent, 'changed', self.__class__.__preview, self) # Save changes connect_obj(self.save, 'clicked', self.__save, addreplace, library) for child in self.get_children(): child.show() def __filter_preview(self, *args): Gtk.Button.clicked(self.preview) def __filter_changed(self, *args): self._changed(self.combo.get_child()) def _changed(self, entry): self.save.set_sensitive(False) self.preview.set_sensitive(bool(entry.get_text())) def __add_changed(self, combo): config.set("tagsfrompath", "add", str(bool(combo.get_active()))) def __preview(self, songs): if songs is None: songs = [row[0].song for row in (self.view.get_model() or [])] if songs: pattern_text = self.combo.get_child().get_text() else: pattern_text = "" try: pattern = TagsFromPattern(pattern_text) except re.error: qltk.ErrorMessage( self, _("Invalid pattern"), _("The pattern\n\t%s\nis invalid. " "Possibly it contains the same tag twice or " "it has unbalanced brackets (< / >).") % ( util.bold(pattern_text)), escape_desc=False).run() return else: if pattern_text: self.combo.prepend_text(pattern_text) self.combo.write(TBP) invalid = [] for header in pattern.headers: if not min([song.can_change(header) for song in songs]): invalid.append(header) total = len(invalid) if total and songs: title = ngettext("Invalid tag", "Invalid tags", total) msg = ngettext("Invalid tag %s\n\nThe files currently " "selected do not support editing this tag.", "Invalid tags %s\n\nThe files currently " "selected do not support editing these tags.", total) tags_str = util.bold(", ".join(invalid)) qltk.ErrorMessage(self, title, msg % tags_str, escape_desc=False).run() pattern = TagsFromPattern("") self.view.set_model(None) model = ObjectStore() for col in self.view.get_columns(): self.view.remove_column(col) render = Gtk.CellRendererText() col = TreeViewColumn(title=_('File')) col.pack_start(render, True) col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) def cell_data_file(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.name) col.set_cell_data_func(render, cell_data_file) def cell_data_header(column, cell, model, iter_, header): entry = model.get_value(iter_) cell.set_property("text", entry.get_match(header)) self.view.append_column(col) for i, header in enumerate(pattern.headers): render = Gtk.CellRendererText() render.set_property('editable', True) render.connect('edited', self.__row_edited, model, header) escaped_title = header.replace("_", "__") col = Gtk.TreeViewColumn(escaped_title, render) col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) col.set_cell_data_func(render, cell_data_header, header) self.view.append_column(col) for song in songs: entry = ListEntry(song) match = pattern.match(song) for h in pattern.headers: text = match.get(h, '') for f in self.filter_box.filters: if f.active: text = f.filter(h, text) if not song.can_multiple_values(h): text = u", ".join(text.split("\n")) entry.matches[h] = text model.append([entry]) # save for last to potentially save time if songs: self.view.set_model(model) self.preview.set_sensitive(False) self.save.set_sensitive(len(pattern.headers) > 0) def __save(self, addreplace, library): pattern_text = self.combo.get_child().get_text() pattern = TagsFromPattern(pattern_text) model = self.view.get_model() add = bool(addreplace.get_active()) win = WritingWindow(self, len(model)) win.show() was_changed = set() all_done = False for entry in ((model and model.values()) or []): song = entry.song changed = False if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break for i, h in enumerate(pattern.headers): text = entry.get_match(h) if text: can_multiple = song.can_multiple_values(h) if not add or h not in song or not can_multiple: song[h] = text changed = True else: for val in text.split("\n"): if val not in song.list(h): song.add(h, val) changed = True if changed: try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True win.destroy() library.changed(was_changed) self.save.set_sensitive(not all_done) def __row_edited(self, renderer, path, new, model, header): entry = model[path][0] if entry.get_match(header) != new: entry.replace_match(header, new) self.preview.set_sensitive(True) self.save.set_sensitive(True) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658776081.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/textedit.py����������������������������������������������������������0000644�0001750�0001750�00000014074�14267565021�017370� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib, Pango from senf import fsnative from quodlibet import _ from quodlibet import qltk from quodlibet import util from quodlibet.qltk import Button, Icons from quodlibet.formats import AudioFile from quodlibet.pattern import XMLFromPattern, XMLFromMarkupPattern, \ error as PatternError from quodlibet.util import connect_obj try: import gi gi.require_version("GtkSource", "3.0") from gi.repository import GtkSource except (ValueError, ImportError): TextView = Gtk.TextView TextBuffer = Gtk.TextBuffer else: TextView = GtkSource.View class TextBuffer(GtkSource.Buffer): # type: ignore def __init__(self, *args): super().__init__(*args) self.set_highlight_matching_brackets(False) self.set_highlight_syntax(False) def set_text(self, *args): self.begin_not_undoable_action() super().set_text(*args) self.end_not_undoable_action() class TextEditBox(Gtk.HBox): """A simple text editing area with a default value, a revert button, and an apply button. The 'buffer' attribute is the text buffer, the 'apply' attribute is the apply button. FIXME: Button text should changeable (without poking the buttons directly). """ def __init__(self, default=""): super().__init__(spacing=6) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(TextView(buffer=TextBuffer())) self.pack_start(sw, True, True, 0) self.buffer = sw.get_child().get_buffer() box = Gtk.VBox(spacing=6) rev = Button(_("_Revert"), Icons.DOCUMENT_REVERT) app = Button(_("_Apply")) box.pack_start(rev, False, True, 0) box.pack_start(app, False, True, 0) self.pack_start(box, False, True, 0) connect_obj(rev, 'clicked', self.buffer.set_text, default) self.revert = rev self.apply = app @property def text(self): start, end = self.buffer.get_bounds() return self.buffer.get_text(start, end, True) @text.setter def text(self, value): self.buffer.set_text(value, -1) def validate_markup_pattern(text, alternative_markup=True, links=False): """Check whether a passed pattern results in a valid pango markup. Args: text (unicode): the pattern alternative_markup (bool): if "[b]" gets mapped to "\\<b\\>" links (bool): if link tags are allowed (for Gtk.Label only) Raises: ValueError: In case the pattern isn't valid """ assert isinstance(text, str) f = AudioFile({"~filename": fsnative(u"dummy")}) try: if alternative_markup: pattern = XMLFromMarkupPattern(text) else: pattern = XMLFromPattern(text) text = pattern % f except PatternError as e: return ValueError(e) try: Pango.parse_markup(text, -1, u"\u0000") except GLib.GError as e: if not links: raise ValueError(e) # Gtk.Label supports links on top of pango markup but doesn't # provide a way to verify them. We can check if the markup # was accepted by seeing if get_text() returns something. l = Gtk.Label() # add a character in case text is empty. # this might print a warning to stderr.. no idea how to prevent that.. l.set_markup(text + " ") if not l.get_text(): raise ValueError(e) class PatternEditBox(TextEditBox): """A TextEditBox that stops the apply button's clicked signal if the pattern is invalid. You need to use connect_after to connect to it, to get this feature.""" def __init__(self, default="", alternative_markup=True, links=False): super().__init__(default) self._alternative_markup = alternative_markup self._links = links self.apply.connect('clicked', self.__check_markup) def __check_markup(self, apply): try: validate_markup_pattern( self.text, self._alternative_markup, self._links) except ValueError as e: qltk.ErrorMessage( self, _("Invalid pattern"), _("The pattern you entered was invalid. Make sure you enter " "< and > as \\< and \\> and that your tags are " "balanced.\n\n%s") % util.escape(str(e))).run() apply.stop_emission('clicked') return False class TextEdit(qltk.UniqueWindow): """A window with a text editing box in it.""" Box = TextEditBox def __init__(self, parent, default="", **kwargs): if self.is_not_unique(): return super().__init__() self.set_title(_("Edit Display")) self.set_transient_for(qltk.get_top_parent(parent)) self.set_border_width(12) self.set_default_size(420, 190) vbox = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) self.box = box = self.Box(default, **kwargs) vbox.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): vbox.pack_start(b, False, True, 0) self.add(vbox) self.apply = box.apply self.revert = box.revert close.grab_focus() self.get_child().show_all() @property def text(self): return self.box.text @text.setter def text(self, value): self.box.text = value class PatternEdit(TextEdit): """A window with a pattern editing box in it.""" Box = PatternEditBox ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/tracker.py�����������������������������������������������������������0000664�0001750�0001750�00000015714�14231604332�017163� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2013 Christoph Reiter # 2020-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import time from typing import Collection from gi.repository import GObject, GLib from quodlibet import config, print_d from quodlibet.formats import AudioFile from quodlibet.library.base import Library class TimeTracker(GObject.GObject): """Emits tick every second (with up to one second jitter) as long as the player is actively playing. Uses timeout_add_seconds, so multiple instances of this should sync and not produce more wakeups. """ __gsignals__ = { 'tick': (GObject.SignalFlags.RUN_LAST, None, ()), } def __init__(self, player): super().__init__() self.__interval = 1000 self.__player = player self.__id = None self.__stop = False self.__reset = False self.__sigs = [ player.connect("paused", self.__paused, True), player.connect("unpaused", self.__paused, False), ] self.__paused(player, player.paused) def set_interval(self, interval): """Update the resolution in milliseconds""" self.__interval = interval self.__reset = True def tick(self): """Emit a tick event""" self.emit("tick") def destroy(self): for signal_id in self.__sigs: self.__player.disconnect(signal_id) self.__source_remove() def __source_remove(self): if self.__id is not None: GLib.source_remove(self.__id) self.__id = None def __update(self): if self.__stop: self.__source_remove() return False if self.__reset: self.__reset = False self.__source_remove() self.__paused(self.__player, self.__player.paused) self.tick() return True def __paused(self, player, paused): if paused: # By removing the timeout only in the callback we are safe from # huge deviation caused by lots of pause/unpause actions. self.__stop = True else: self.__stop = False if self.__id is None: # The application is already woke up every seconds # so synchronize to it by calling timeout_add_seconds(...) # if the requested tracker interval is exactly 1 second. self.__id = GLib.timeout_add_seconds(1, self.__update) \ if self.__interval == 1000 \ else GLib.timeout_add(self.__interval, self.__update) class SongTracker: def __init__(self, librarian, player, pl): self.__player_ids = [ player.connect('song-ended', self.__end, librarian, pl), player.connect('song-started', self.__start, librarian), ] self.__player = player timer = TimeTracker(player) timer.connect("tick", self.__timer) self.elapsed = 0 self.__to_change = set() self.__change_id = None def destroy(self): for id_ in self.__player_ids: self.__player.disconnect(id_) self.__player = None if self.__change_id: GLib.source_remove(self.__change_id) self.__change_id = None def __changed(self, librarian, song): # try to combine changed events and process them if QL is idle self.__to_change.add(song) if self.__change_id is not None: GLib.source_remove(self.__change_id) self.__change_id = None def idle_change(): librarian.changed(list(self.__to_change)) self.__to_change.clear() self.__change_id = None self.__change_id = GLib.idle_add(idle_change, priority=GLib.PRIORITY_LOW) def __start(self, player, song, librarian): self.elapsed = 0 if song is not None: if song.multisong: song["~#lastplayed"] = int(time.time()) song["~#playcount"] = song.get("~#playcount", 0) + 1 else: config.set("memory", "song", song["~filename"]) song["~#laststarted"] = int(time.time()) self.__changed(librarian, song) else: config.set("memory", "song", "") def __end(self, player, song, ended, librarian, pl): if song is not None and not song.multisong: if ended: config.set("memory", "seek", player.get_position()) else: config.set("memory", "seek", 0) playcount_minimum_length = config.getfloat( "player", "playcount_minimum_length_proportion") * int(song.get( "~#length", 1)) if self.elapsed >= playcount_minimum_length: song["~#lastplayed"] = int(time.time()) song["~#playcount"] = song.get("~#playcount", 0) + 1 self.__changed(librarian, song) elif pl.current is not song: if not player.error: song["~#skipcount"] = song.get("~#skipcount", 0) + 1 self.__changed(librarian, song) else: config.set("memory", "seek", 0) def __timer(self, timer): self.elapsed += 1 class FSInterface: """Provides a file in ~/.quodlibet to indicate what song is playing.""" def __init__(self, path, player, library: Library): self.path = path self._player = player self._pids = [ player.connect('song-started', self.__started), player.connect('song-ended', self.__ended), ] self._lids = [library.connect('changed', self.__changed)] self._library = library def destroy(self): for id_ in self._pids: self._player.disconnect(id_) for id_ in self._lids: print_d(f"Disconnecting signal {id_} from {self._library}") self._library.disconnect(id_) try: os.unlink(self.path) except EnvironmentError: pass def __started(self, player, song): if song: song = player.with_elapsed_info(song) try: with open(self.path, "wb") as f: f.write(song.to_dump()) except EnvironmentError: pass def __ended(self, player, song, stopped): try: os.unlink(self.path) except EnvironmentError: pass def __changed(self, _lib: Library, songs: Collection[AudioFile]): current = self._player.song if current and current in songs: print_d("Current song changed, updating current file") self.__started(self._player, current) ����������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/tracknumbers.py������������������������������������������������������0000664�0001750�0001750�00000017305�14035600052�020223� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from senf import fsn2text from quodlibet import qltk from quodlibet import util from quodlibet import _ from quodlibet.formats import AudioFileError from quodlibet.qltk._editutils import OverwriteWarning, WriteFailedError from quodlibet.qltk.views import HintedTreeView, TreeViewColumn from quodlibet.qltk.wlw import WritingWindow from quodlibet.qltk.x import Button, Align from quodlibet.qltk.models import ObjectStore from quodlibet.qltk import Icons from quodlibet.util import connect_obj class Entry: def __init__(self, song): self.song = song self.tracknumber = song("tracknumber") @property def name(self): return fsn2text(self.song("~basename")) class TrackNumbers(Gtk.VBox): def __init__(self, prop, library): super().__init__(spacing=6) self.title = _("Track Numbers") self.set_border_width(12) label_start = Gtk.Label(label=_("Start fro_m:"), halign=Gtk.Align.END) label_start.set_use_underline(True) spin_start = Gtk.SpinButton() spin_start.set_range(0, 999) spin_start.set_increments(1, 10) spin_start.set_value(1) label_start.set_mnemonic_widget(spin_start) label_total = Gtk.Label( label=_("_Total tracks:"), halign=Gtk.Align.END) label_total.set_use_underline(True) spin_total = Gtk.SpinButton() spin_total.set_range(0, 999) spin_total.set_increments(1, 10) label_total.set_mnemonic_widget(spin_total) preview = qltk.Button(_("_Preview"), Icons.VIEW_REFRESH) grid = Gtk.Grid(row_spacing=4, column_spacing=4) grid.add(label_start) grid.attach_next_to( spin_start, label_start, Gtk.PositionType.RIGHT, 1, 1) grid.attach_next_to( label_total, label_start, Gtk.PositionType.BOTTOM, 1, 1) grid.attach_next_to( spin_total, label_total, Gtk.PositionType.RIGHT, 1, 1) grid.attach_next_to( Align(preview, halign=Gtk.Align.END), spin_start, Gtk.PositionType.RIGHT, 1, 1) preview.props.hexpand = True model = ObjectStore() view = HintedTreeView(model=model) self.pack_start(grid, False, True, 0) render = Gtk.CellRendererText() column = TreeViewColumn(title=_('File')) column.pack_start(render, True) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) def cell_data_file(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.name) column.set_cell_data_func(render, cell_data_file) view.append_column(column) render = Gtk.CellRendererText() render.set_property('editable', True) column = TreeViewColumn(title=_('Track')) column.pack_start(render, True) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) def cell_data_track(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.tracknumber) column.set_cell_data_func(render, cell_data_track) view.append_column(column) view.set_reorderable(True) w = Gtk.ScrolledWindow() w.set_shadow_type(Gtk.ShadowType.IN) w.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) w.add(view) self.pack_start(w, True, True, 0) bbox = Gtk.HButtonBox() bbox.set_spacing(6) bbox.set_layout(Gtk.ButtonBoxStyle.END) save = Button(_("_Save"), Icons.DOCUMENT_SAVE) self.save = save connect_obj(save, 'clicked', self.__save_files, prop, model, library) revert = Button(_("_Revert"), Icons.DOCUMENT_REVERT) self.revert = revert bbox.pack_start(revert, True, True, 0) bbox.pack_start(save, True, True, 0) self.pack_start(bbox, False, True, 0) preview_args = [spin_start, spin_total, model, save, revert] preview.connect('clicked', self.__preview_tracks, *preview_args) connect_obj(revert, 'clicked', self.__update, None, *preview_args[1:]) spin_total.connect( 'value-changed', self.__preview_tracks, *preview_args) spin_start.connect( 'value-changed', self.__preview_tracks, *preview_args) connect_obj(view, 'drag-end', self.__class__.__preview_tracks, self, *preview_args) render.connect('edited', self.__row_edited, model, preview, save) connect_obj(prop, 'changed', self.__class__.__update, self, spin_total, model, save, revert) for child in self.get_children(): child.show_all() def __row_edited(self, render, path, new, model, preview, save): path = Gtk.TreePath.new_from_string(path) row = model[path] entry = row[0] if entry.tracknumber != new: entry.tracknumber = new preview.set_sensitive(True) save.set_sensitive(True) model.path_changed(path) def __save_files(self, parent, model, library): win = WritingWindow(parent, len(model)) was_changed = set() all_done = False for entry in model.values(): song, track = entry.song, entry.tracknumber if song.get("tracknumber") == track: win.step() continue if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break song["tracknumber"] = track try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True library.changed(was_changed) win.destroy() self.save.set_sensitive(not all_done) self.revert.set_sensitive(not all_done) def __preview_tracks(self, ctx, start, total, model, save, revert): start = start.get_value_as_int() total = total.get_value_as_int() for row in model: if total: s = u"%d/%d" % (row.path.get_indices()[0] + start, total) else: s = str(row.path.get_indices()[0] + start) entry = row[0] entry.tracknumber = s model.row_changed(row.path, row.iter) save.set_sensitive(True) revert.set_sensitive(True) def __update(self, songs, total, model, save, revert): if songs is None: songs = [e.song for e in model.values()] else: songs = list(songs) def sort_key(song): return song("~#track", 0), song("~basename"), song songs.sort(key=sort_key) model.clear() total.set_value(len(songs)) for song in songs: if not song.can_change("tracknumber"): self.set_sensitive(False) break else: self.set_sensitive(True) for song in songs: model.append([Entry(song)]) save.set_sensitive(False) revert.set_sensitive(False) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/unity.py�������������������������������������������������������������0000664�0001750�0001750�00000004271�14035600052�016671� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Everything related to Ubuntu Unity integration (quicklist..) See the MPRIS plugin for sound menu integration. """ import gi from quodlibet import _ from quodlibet.util import gi_require_versions is_unity = True try: gi.require_version("Dbusmenu", "0.4") from gi.repository import Dbusmenu except (ValueError, ImportError): is_unity = False try: gi_require_versions("Unity", ["7.0", "6.0", "5.0"]) from gi.repository import Unity except (ValueError, ImportError): is_unity = False def init(desktop_id, player): """Set up unity integration. * desktop_id: e.g. 'quodlibet.desktop' * player: BasePlayer() http://developer.ubuntu.com/api/devel/ubuntu-12.04/c/Unity-5.0.html http://developer.ubuntu.com/api/devel/ubuntu-13.10/c/Unity-7.0.html """ if not is_unity: return launcher = Unity.LauncherEntry.get_for_desktop_id(desktop_id) main = Dbusmenu.Menuitem() play_pause = Dbusmenu.Menuitem() play_pause.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Play/Pause")) play_pause.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True) main.child_append(play_pause) def play_pause_cb(item, timestamp): player.playpause() play_pause.connect("item-activated", play_pause_cb) next_ = Dbusmenu.Menuitem() next_.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Next")) next_.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True) main.child_append(next_) def next_cb(item, timestamp): player.next() next_.connect("item-activated", next_cb) prev = Dbusmenu.Menuitem() prev.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Previous")) prev.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True) main.child_append(prev) def prev_cb(item, timestamp): player.previous() prev.connect("item-activated", prev_cb) launcher.set_property("quicklist", main) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/util.py��������������������������������������������������������������0000664�0001750�0001750�00000006441�14035600052�016477� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from typing import Tuple, Dict, Union, Type, Optional, Sequence from gi.repository import Gtk, Gdk, GObject from quodlibet.qltk import is_wayland GSignals = Dict[ str, Union[Tuple[GObject.SignalFlags, Optional[Type], Sequence[Type]], str]] def window_grab_and_map(window, mask): """Returns a list of devices that have a grab or an empty list if something failed. If somethings failed the window will be hidden. """ device = Gtk.get_current_event_device() event_time = Gtk.get_current_event_time() if not device: return [] # On wayland we need to grab before mapping and on X11 and everywhere else # we can grab after we are mapped if not is_wayland(): window.show() else: window.realize() Gtk.device_grab_add(window, device, True) status = device.grab( window.get_window(), Gdk.GrabOwnership.WINDOW, True, mask, None, event_time) if status != Gdk.GrabStatus.SUCCESS: Gtk.device_grab_remove(window, device) window.hide() return [] associated_device = device.get_associated_device() if associated_device is None: if is_wayland(): window.show() return [device] Gtk.device_grab_add(window, associated_device, True) status = associated_device.grab( window.get_window(), Gdk.GrabOwnership.WINDOW, True, mask, None, event_time) if status != Gdk.GrabStatus.SUCCESS: Gtk.device_grab_remove(window, associated_device) Gtk.device_grab_remove(window, device) device.ungrab(event_time) window.hide() return [] if is_wayland(): window.show() return [device, associated_device] def window_ungrab_and_unmap(window, devices): """Takes the result of window_grab_and_map() and removes the grabs""" event_time = Gtk.get_current_event_time() for device in devices: Gtk.device_grab_remove(window, device) device.ungrab(event_time) window.hide() #gtk3.8 bug: https://bugzilla.gnome.org/show_bug.cgi?id=700185 window.unrealize() def position_window_beside_widget(window, widget, end=True, pad=3): """Positions `window` left or right beside `widget` on the screen. `padding` is the space between the widget and the window. If `end` is True the window will be placed on the right side in LTR mode or on the left side in RTL mode. """ if Gtk.Widget.get_default_direction() != Gtk.TextDirection.LTR: right = not end else: right = end assert widget.get_realized() toplevel = widget.get_toplevel() dx, dy = widget.translate_coordinates(toplevel, 0, 0) x, y = toplevel.get_window().get_origin()[1:] x += dx y += dy widget_alloc = widget.get_allocation() w, h = widget_alloc.width, widget_alloc.height window.size_request() ww, wh = window.get_size() if right: sx, sy = ((x + w + pad), (y + (h - wh) // 2)) else: sx, sy = ((x - (ww + pad)), (y + (h - wh) // 2)) window.move(sx, sy) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/views.py�������������������������������������������������������������0000644�0001750�0001750�00000134542�14327505043�016671� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2012, 2013 Christoph Reiter # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import contextlib import sys import os from gi.repository import Gtk, Gdk, GObject, Pango, GLib import cairo from quodlibet import _, print_e, util from quodlibet import config from quodlibet.qltk import get_top_parent, is_accel, is_wayland, gtk_version, \ menu_popup, get_primary_accel_mod from quodlibet.qltk.image import get_surface_extents from .util import GSignals class TreeViewHints(Gtk.Window): """Handle 'hints' for treeviews. This includes expansions of truncated columns, and in the future, tooltips.""" class _MinLabel(Gtk.Label): def do_get_preferred_width(*args): return (0, Gtk.Label.do_get_preferred_width(*args)[0]) # input_shape_combine_region does not work under Windows, we have # to pass all events to the treeview. In case it does work, this handlers # will never be called. __gsignals__: GSignals = dict.fromkeys( ['button-press-event', 'button-release-event', 'motion-notify-event', 'scroll-event', 'enter-notify-event', 'leave-notify-event'], 'override') __empty_region = cairo.Region(cairo.RectangleInt()) def __init__(self): try: # gtk+ 3.20 TreeViewHints.set_css_name("tooltip") except AttributeError: pass super().__init__(type=Gtk.WindowType.POPUP) # set the type hint so the wayland backend maps it as a subsurface # which supports relative positioning self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) self.__clabel = Gtk.Label() self.__clabel.show() self.__clabel.set_alignment(0, 0.5) self.__clabel.set_ellipsize(Pango.EllipsizeMode.NONE) screen = self.get_screen() rgba = screen.get_rgba_visual() if rgba is not None: self.set_visual(rgba) self.__label = label = self._MinLabel() label.set_alignment(0, 0.5) label.set_ellipsize(Pango.EllipsizeMode.NONE) label.show() self.add(label) self.add_events( Gdk.EventMask.BUTTON_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.POINTER_MOTION_MASK) context = self.get_style_context() context.add_class("tooltip") context.add_class("ql-tooltip") self.set_accept_focus(False) self.set_resizable(False) self.set_name("gtk-tooltip") if gtk_version < (3, 13): self.set_border_width(1) self.connect('leave-notify-event', self.__undisplay) self.__handlers = {} self.__current_path = self.__current_col = None self.__current_renderer = None self.__view = None self.__hide_id = None def connect_view(self, view): # don't depend on padding set by theme, we need the text coordinates # to match in all cases self._style_provider = style_provider = Gtk.CssProvider() style_provider.load_from_data(b""" .ql-tooltip * { border-width: 0px; padding: 0px; } .ql-tooltip { padding: 0px; } """) # somehow this doesn't apply if we set it on the window, only # if set for the screen. gets reverted again in disconnect_view() Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) self.__handlers[view] = [ view.connect('motion-notify-event', self.__motion), view.connect('leave-notify-event', self.__motion), view.connect('scroll-event', self.__undisplay), view.connect('key-press-event', self.__undisplay), view.connect('unmap', self.__undisplay), view.connect('destroy', self.disconnect_view), ] def disconnect_view(self, view): try: for handler in self.__handlers[view]: view.disconnect(handler) del self.__handlers[view] except KeyError: pass # Hide if the active treeview is going away if view is self.__view: self.__undisplay() self.set_transient_for(None) if self.__hide_id: GLib.source_remove(self.__hide_id) self.__hide_id = None self.hide() Gtk.StyleContext.remove_provider_for_screen( Gdk.Screen.get_default(), self._style_provider) def __motion(self, view, event): label = self.__label clabel = self.__clabel # trigger over row area, not column headers if event.window is not view.get_bin_window(): self.__undisplay() return False x, y = map(int, [event.x, event.y]) # For gtk3.16 overlay scrollbars: if our event x coordinate # is contained in the scrollbar, hide the tooltip. Unlike other # hiding events we don't want to send a leave event to the scrolled # window so the overlay scrollbar doesn't hide and can be interacted # with. parent = view.get_parent() # We only need to check if the tooltip is there since events # on the scrollbars don't get forwarded to us anyway. if self.__view and parent and isinstance(parent, Gtk.ScrolledWindow): vscrollbar = parent.get_vscrollbar() res = vscrollbar.translate_coordinates(view, 0, 0) if res is not None: x_offset = res[0] vbar_width = vscrollbar.get_allocation().width if x_offset <= x <= x_offset + vbar_width: self.__undisplay(send_leave=False) return False # hide if any modifier is active. mask = Gtk.accelerator_get_default_mod_mask() mask = Gdk.Keymap.get_default().map_virtual_modifiers(mask)[1] if event.get_state() & mask: self.__undisplay() return False # get the cell at the mouse position try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: # no hints where no rows exist self.__undisplay() return False col_area = view.get_cell_area(path, col) # make sure we are on the same level if x < col_area.x: self.__undisplay() return False # hide for partial hidden rows at the bottom if y > view.get_visible_rect().height: self.__undisplay() return False # get the renderer at the mouse position and get the xpos/width renderers = col.get_cells() pos = sorted(zip(map(col.cell_get_position, renderers), renderers)) pos = [p for p in pos if p[0][0] < cellx] if not pos: self.__undisplay() return False (render_offset, render_width), renderer = pos[-1] if self.__current_renderer == renderer and self.__current_path == path: return False # only ellipsized text renderers if not isinstance(renderer, Gtk.CellRendererText): self.__undisplay() return False ellipsize = renderer.get_property('ellipsize') if ellipsize == Pango.EllipsizeMode.END: expand_left = False elif ellipsize == Pango.EllipsizeMode.MIDDLE: # depending on where the cursor is expand_left = x > col_area.x + render_offset + render_width / 2 elif ellipsize == Pango.EllipsizeMode.START: expand_left = True else: self.__undisplay() return False # don't display if the renderer is in editing mode if renderer.props.editing: self.__undisplay() return False # set the cell renderer attributes for the active cell model = view.get_model() col.cell_set_cell_data(model, model.get_iter(path), False, False) # the markup attribute is write only, so the markup text needs # to be saved on the python side, so we can copy it to the label markup = getattr(renderer, "markup", None) if markup is None: text = renderer.get_property('text') set_text = lambda l: l.set_text(text) else: # markup can also be column index if isinstance(markup, int): markup = model[path][markup] set_text = lambda l: l.set_markup(markup) # Use the renderer padding as label padding so the text offset matches render_xpad = renderer.get_property("xpad") # the renderer xpad is not enough for the tooltip, especially with # rounded corners the label gets nearly clipped. MIN_HINT_X_PAD = 4 if render_xpad < MIN_HINT_X_PAD: extra_xpad = MIN_HINT_X_PAD - render_xpad else: extra_xpad = 0 label.set_padding(render_xpad + extra_xpad, 0) set_text(clabel) clabel.set_padding(render_xpad, 0) label_width = clabel.get_layout().get_pixel_size()[0] label_width += clabel.get_layout_offsets()[0] or 0 # layout offset includes the left padding, so add one more label_width += render_xpad # CellRenderer width is too large if it's the last one in a column. # Use cell_area width as a maximum and limit render_width. max_width = col_area.width if render_width + render_offset > max_width: render_width = max_width - render_offset # don't display if it doesn't need expansion if label_width < render_width: self.__undisplay() return False dummy, ox, oy = view.get_window().get_origin() bg_area = view.get_background_area(path, None) # save for adjusting passthrough events self.__dx, self.__dy = col_area.x + render_offset, bg_area.y self.__dx -= extra_xpad if expand_left: # shift to the left # FIXME: ellipsize start produces a space at the end depending # on the text. I don't know how to compute it.. self.__dx -= (label_width - render_width) # final window coordinates/size x = ox + self.__dx y = oy + self.__dy x, y = view.convert_bin_window_to_widget_coords(x, y) w = label_width + extra_xpad * 2 h = bg_area.height if not is_wayland(): # clip if it's bigger than the monitor mon_border = 5 # leave some space screen = Gdk.Screen.get_default() if not expand_left: monitor_idx = screen.get_monitor_at_point(x, y) mon = screen.get_monitor_geometry(monitor_idx) space_right = mon.x + mon.width - x - w - mon_border if space_right < 0: w += space_right label.set_ellipsize(Pango.EllipsizeMode.END) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: monitor_idx = screen.get_monitor_at_point(x + w, y) mon = screen.get_monitor_geometry(monitor_idx) space_left = x - mon.x - mon_border if space_left < 0: x -= space_left self.__dx -= space_left w += space_left label.set_ellipsize(Pango.EllipsizeMode.START) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) # Don't show if the resulting tooltip would be smaller # than the visible area (if not all is on the display) if w < render_width: self.__undisplay() return False self.__view = view self.__current_renderer = renderer self.__edit_id = renderer.connect('editing-started', self.__undisplay) self.__current_path = path self.__current_col = col if self.__hide_id: GLib.source_remove(self.__hide_id) self.__hide_id = None self.set_transient_for(get_top_parent(view)) set_text(label) self.set_size_request(w, h) # Set region on this window for which to receive mouse events to the # empty region. Mouse events will be passed to the window below the # tooltip. The Gdk implementation for win32 does not support this, which # leads to events not being received in either window. if sys.platform != "win32": self.input_shape_combine_region(self.__empty_region) window = self.get_window() if self.get_visible() and window: window.move_resize(x, y, w, h) else: self.move(x, y) self.resize(w, h) self.show() return False def __undisplay(self, *args, **kwargs): if not self.__view: return send_leave = kwargs.pop("send_leave", True) # XXXXXXXX!: for overlay scrollbars the parent scrolled window # listens to notify-leave events to hide them. In case we show # the tooltip and leave the SW through the tooltip the SW will never # get an event and the scrollbar stays visible forever. # This creates a half broken leave event which is just enough # to make this work. parent = self.__view.get_parent() fake_event = None if parent and isinstance(parent, Gtk.ScrolledWindow) and send_leave: fake_event = Gdk.Event.new(Gdk.EventType.LEAVE_NOTIFY) fake_event.any.window = parent.get_window() struct = fake_event.crossing struct.time = Gtk.get_current_event_time() ok, state = Gtk.get_current_event_state() if ok: struct.state = state device = Gtk.get_current_event_device() if device is not None: struct.set_device(device) if self.__current_renderer and self.__edit_id: self.__current_renderer.disconnect(self.__edit_id) self.__current_renderer = self.__edit_id = None self.__current_path = self.__current_col = None self.__view = None def hide(fake_event): if fake_event is not None: Gtk.main_do_event(fake_event) self.__hide_id = None self.hide() return False if gtk_version < (3, 13): # https://bugzilla.gnome.org/show_bug.cgi?id=731055 # Work around Gnome Shell redraw bugs: it doesn't like # multiple hide()/show(), so we try to reduce calls to hide # by aborting it if the pointer is on a new cell shortly after. self.__hide_id = GLib.timeout_add(20, hide, fake_event) else: # mutter3.12 and gtk3.14 are a bit broken together, so it's safe # to assume we have a fixed mutter release.. hide(fake_event) def __event(self, event): if not self.__view: return True # hack: present the main window on key press if event.type == Gdk.EventType.BUTTON_PRESS: # hack: present is overridden to present all windows. # bypass to only select one Gtk.Window.present(get_top_parent(self.__view)) def translate_enter_leave_event(event): # enter/leave events have different x/y values as motion events # so it makes sense to push them to the underlying view as # additional motion events. # Warning: this may result in motion events outside of the # view window.. ? new_event = Gdk.Event.new(Gdk.EventType.MOTION_NOTIFY) struct = new_event.motion for attr in ["x", "y", "x_root", "y_root", "time", "window", "state", "send_event"]: setattr(struct, attr, getattr(event.crossing, attr)) device = Gtk.get_current_event_device() if device is not None: struct.set_device(device) return new_event # FIXME: We should translate motion events on the tooltip # to crossing events for the underlying view. # (I think, no tested) Currently the hover scrollbar stays visible # if the mouse leaves the view through the tooltip without the # knowledge of the view. type_ = event.type real_event = None if type_ == Gdk.EventType.BUTTON_PRESS: real_event = event.button elif type_ == Gdk.EventType.BUTTON_RELEASE: real_event = event.button elif type_ == Gdk.EventType.MOTION_NOTIFY: real_event = event.motion elif type_ == Gdk.EventType.ENTER_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion elif type_ == Gdk.EventType.LEAVE_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion if real_event: real_event.x += self.__dx real_event.y += self.__dy # modifying event.window is a necessary evil, made okay because # nobody else should tie to any TreeViewHints events ever. event.any.window = self.__view.get_bin_window() Gtk.main_do_event(event) return True def do_button_press_event(self, event): return self.__event(event) def do_button_release_event(self, event): return self.__event(event) def do_motion_notify_event(self, event): return self.__event(event) def do_enter_notify_event(self, event): return self.__event(event) def do_leave_notify_event(self, event): return self.__event(event) def do_scroll_event(self, event): return self.__event(event) class DragScroll: """A treeview mixin for smooth drag and scroll (needs BaseView). Call scroll_motion in the 'drag-motion' handler and scroll_disable in the 'drag-leave' handler. """ __scroll_delay = None __scroll_periodic = None __scroll_args = (0, 0, 0, 0) __scroll_length = 0 __scroll_last = None def __enable_scroll(self): """Start scrolling if it hasn't already""" if self.__scroll_periodic is not None or \ self.__scroll_delay is not None: return def periodic_scroll(): """Get the tree coords for 0,0 and scroll from there""" wx, wy, dist, ref = self.__scroll_args x, y = self.convert_widget_to_tree_coords(0, 0) x, y = self.convert_bin_window_to_widget_coords(x, y) # We reached an end, stop if self.__scroll_last == y: self.scroll_disable() return self.__scroll_last = y # If we went full speed for a while.. speed up # .. every number is made up here if self.__scroll_length >= 50 * ref: dist *= self.__scroll_length / (ref * 10) if self.__scroll_length < 2000 * ref: self.__scroll_length += abs(dist) try: self.scroll_to_point(-1, y + dist) except OverflowError: pass self.set_drag_dest(wx, wy) # we have to re-add the timeout.. otherwise they could add up # because scroll can last longer than 50ms GLib.source_remove(self.__scroll_periodic) self.__scroll_periodic = None enable_periodic_scroll() def enable_periodic_scroll(): self.__scroll_periodic = GLib.timeout_add(50, periodic_scroll) self.__scroll_delay = None self.__scroll_delay = GLib.timeout_add(350, enable_periodic_scroll) def scroll_disable(self): """Disable all scrolling""" if self.__scroll_periodic is not None: GLib.source_remove(self.__scroll_periodic) self.__scroll_periodic = None if self.__scroll_delay is not None: GLib.source_remove(self.__scroll_delay) self.__scroll_delay = None self.__scroll_length = 0 self.__scroll_last = None def scroll_motion(self, x, y): """Call with current widget coords during a dnd action to update scrolling speed""" visible_rect = self.get_visible_rect() if visible_rect is None: self.scroll_disable() return # I guess the bin to visible_rect difference is the header height # but this could be wrong start = self.convert_bin_window_to_widget_coords(0, 0)[1] end = visible_rect.height + start # Get the font height as size reference reference = max(self.create_pango_layout("").get_pixel_size()[1], 1) # If the drag is in the scroll area, adjust the speed scroll_offset = int(reference * 3) in_upper_scroll = (start < y < start + scroll_offset) in_lower_scroll = (y > end - scroll_offset) # thanks TI200 def accel(x): try: return int(1.1 ** (x * 12 / reference)) - (x / reference) except ValueError: return 0 if in_lower_scroll: diff = accel(y - end + scroll_offset) elif in_upper_scroll: diff = - accel(start + scroll_offset - y) else: self.scroll_disable() return # The area where we can go to full speed full_offset = int(reference * 0.8) in_upper_full = (start < y < start + full_offset) in_lower_full = (y > end - full_offset) if not in_upper_full and not in_lower_full: self.__scroll_length = 0 # For the periodic scroll function self.__scroll_args = (x, y, diff, reference) # The area to trigger a scroll is a bit smaller trigger_offset = int(reference * 2.5) in_upper_trigger = (start < y < start + trigger_offset) in_lower_trigger = (y > end - trigger_offset) if in_upper_trigger or in_lower_trigger: self.__enable_scroll() class BaseView(Gtk.TreeView): __gsignals__: GSignals = { # like the tree selection changed signal but doesn't emit twice in case # a row is activated 'selection-changed': (GObject.SignalFlags.RUN_LAST, None, (object, )), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.connect("key-press-event", self.__key_pressed) self._setup_selection_signal() def _setup_selection_signal(self): # Forwards selection changed events except in case row-activated # just happened and the selection changed event is a result of the # button release after the row-activated event. # This makes the selection change only once in case of double clicking # a row. self._sel_ignore_next = False self._sel_ignore_time = -1 def on_selection_changed(selection): if self._sel_ignore_time != Gtk.get_current_event_time(): self.emit("selection-changed", selection) self._sel_ignore_time = -1 id_ = self.get_selection().connect('changed', on_selection_changed) def on_destroy(self): self.get_selection().disconnect(id_) self.connect('destroy', on_destroy) def on_row_activated(*args): self._sel_ignore_next = True self.connect_after("row-activated", on_row_activated) def on_button_release_event(self, event): if self._sel_ignore_next: self._sel_ignore_time = Gtk.get_current_event_time() self._sel_ignore_next = False self.connect("button-release-event", on_button_release_event) def do_key_press_event(self, event): if is_accel(event, "space", "KP_Space"): return False return Gtk.TreeView.do_key_press_event(self, event) def __key_pressed(self, view, event): def get_first_selected(): selection = self.get_selection() model, paths = selection.get_selected_rows() return paths and paths[0] or None if is_accel(event, "Right") or is_accel(event, "<Primary>Right"): first = get_first_selected() if first: self.expand_row(first, False) elif is_accel(event, "Left") or is_accel(event, "<Primary>Left"): first = get_first_selected() if first: if self.row_expanded(first): self.collapse_row(first) else: # if we can't collapse, move the selection to the parent, # so that a second attempt collapses the parent model = self.get_model() parent = model.iter_parent(model.get_iter(first)) if parent: self.set_cursor(model.get_path(parent)) def remove_paths(self, paths): """Remove rows and restore the selection if it got removed""" model = self.get_model() self.remove_iters([model.get_iter(p) for p in paths]) def remove_iters(self, iters): """Remove rows and restore the selection if it got removed""" self.__remove_iters(iters) def remove_selection(self): """Remove all currently selected rows and select the position of the first removed one.""" selection = self.get_selection() mode = selection.get_mode() if mode in (Gtk.SelectionMode.SINGLE, Gtk.SelectionMode.BROWSE): model, iter_ = selection.get_selected() if iter_: self.__remove_iters([iter_], force_restore=True) elif mode == Gtk.SelectionMode.MULTIPLE: model, paths = selection.get_selected_rows() iters = list(map(model.get_iter, paths or [])) self.__remove_iters(iters, force_restore=True) def select_by_func(self, func, scroll=True, one=False): """Calls func with every Gtk.TreeModelRow in the model and selects it if func returns True. In case func never returned True, the selection will not be changed. Returns True if the selection was changed.""" model = self.get_model() if not model: return False selection = self.get_selection() first = True for row in model: if func(row): if not first: selection.select_path(row.path) continue self.set_cursor(row.path) if scroll: self.scroll_to_cell(row.path, use_align=True, row_align=0.5) first = False if one: break return not first def iter_select_by_func(self, func, scroll=True): """Selects the next row after the current selection for which func returns True, removing the selection of all other rows. func gets passed Gtk.TreeModelRow and should return True if the row should be selected. If scroll=True then scroll to the selected row if the selection changes. Returns True if the selection was changed. """ model = self.get_model() if not model: return False if not model.get_iter_first(): # empty model return False selection = self.get_selection() model, paths = selection.get_selected_rows() # get the last iter we shouldn't be looking at if not paths: last_iter = model[-1].iter else: last_iter = model.get_iter(paths[-1]) # get the first iter we should be looking at start_iter = model.iter_next(last_iter) if start_iter is None: start_iter = model.get_iter_first() row_iter = Gtk.TreeModelRowIter(model, start_iter) for row in row_iter: if not func(row): continue self.set_cursor(row.path) if scroll: self.scroll_to_cell(row.path, use_align=True, row_align=0.5) return True last_path = model.get_path(last_iter) for row in model: if row.path.compare(last_path) == 0: return False if not func(row): continue self.set_cursor(row.path) if scroll: self.scroll_to_cell(row.path, use_align=True, row_align=0.5) return True return False def set_drag_dest(self, x, y, into_only=False): """Sets a drag destination for widget coords into_only will only highlight rows or the whole widget and no lines between rows. """ dest_row = self.get_dest_row_at_pos(x, y) if dest_row is None: rows = len(self.get_model()) if not rows: (self.get_parent() or self).drag_highlight() else: self.set_drag_dest_row(Gtk.TreePath(rows - 1), Gtk.TreeViewDropPosition.AFTER) else: path, pos = dest_row if into_only: if pos == Gtk.TreeViewDropPosition.BEFORE: pos = Gtk.TreeViewDropPosition.INTO_OR_BEFORE elif pos == Gtk.TreeViewDropPosition.AFTER: pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER self.set_drag_dest_row(path, pos) def __remove_iters(self, iters, force_restore=False): if not iters: return selection = self.get_selection() model = self.get_model() if force_restore: for iter_ in iters: model.remove(iter_) else: old_count = selection.count_selected_rows() for iter_ in iters: model.remove(iter_) # only restore a selection if all selected rows are gone afterwards if not old_count or selection.count_selected_rows(): return # model.remove makes the removed iter point to the next row if possible # so check if the last iter is a valid one and select it or # simply select the last row if model.iter_is_valid(iters[-1]): selection.select_iter(iters[-1]) elif len(model): selection.select_path(model[-1].path) @contextlib.contextmanager def without_model(self): """Context manager which removes the model from the view and adds it back afterwards. Tries to preserve all state that gets reset on a model change. """ old_model = self.get_model() search_column = self.get_search_column() sorts = [column.get_sort_indicator() for column in self.get_columns()] self.set_model(None) yield old_model self.set_model(old_model) self.set_search_column(search_column) for column, value in zip(self.get_columns(), sorts): column.set_sort_indicator(value) class DragIconTreeView(BaseView): """TreeView that sets the selected rows as drag icons - Drag icons include 3 rows/2 plus a "and more" count """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.connect('drag-begin', self.__begin) def __begin(self, view, drag_ctx): model, paths = view.get_selection().get_selected_rows() surface = self.create_multi_row_drag_icon(paths, max_rows=3) if surface is not None: Gtk.drag_set_icon_surface(drag_ctx, surface) def create_multi_row_drag_icon(self, paths, max_rows): """Similar to create_row_drag_icon() but creates a drag icon for multiple paths or None. The resulting surface will draw max_rows rows and point out if there are more rows selected. """ if not paths: return if len(paths) == 1: return self.create_row_drag_icon(paths[0]) # create_row_drag_icon can return None icons = [self.create_row_drag_icon(p) for p in paths[:max_rows]] icons = [i for i in icons if i is not None] if not icons: return sizes = [get_surface_extents(s) for s in icons] if None in sizes: return width = max([s[2] for s in sizes]) height = sum([s[3] for s in sizes]) # this is the border width we see in the gtk provided surface, not # much we can do besides hardcoding it here bw = 1 layout = None if len(paths) > max_rows: more = _(u"and %d more…") % (len(paths) - max_rows) more = util.italic(more) layout = self.create_pango_layout("") layout.set_markup(more) layout.set_alignment(Pango.Alignment.CENTER) layout.set_width(Pango.SCALE * (width - 2 * bw)) lw, lh = layout.get_pixel_size() height += lh height += 6 # padding surface = icons[0].create_similar( cairo.CONTENT_COLOR_ALPHA, width, height) ctx = cairo.Context(surface) # render background style_ctx = self.get_style_context() Gtk.render_background(style_ctx, ctx, 0, 0, width, height) # render rows count_y = 0 for icon, (x, y, icon_width, icon_height) in zip(icons, sizes): ctx.save() ctx.set_source_surface(icon, -x, count_y + -y) ctx.rectangle(bw, count_y + bw, icon_width - 2 * bw, icon_height - 2 * bw) ctx.clip() ctx.paint() ctx.restore() count_y += icon_height if layout: Gtk.render_layout(style_ctx, ctx, bw, count_y, layout) # render border Gtk.render_line(style_ctx, ctx, 0, 0, 0, height - 1) Gtk.render_line(style_ctx, ctx, 0, height - 1, width - 1, height - 1) Gtk.render_line(style_ctx, ctx, width - 1, height - 1, width - 1, 0) Gtk.render_line(style_ctx, ctx, width - 1, 0, 0, 0) return surface class MultiDragTreeView(BaseView): """TreeView with multirow drag support. Button press events which would result in a row getting unselected get delayed until the next button release event. This makes it possible to drag one or more selected rows without changing the selection. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.connect('button-press-event', self.__button_press) self.connect('button-release-event', self.__button_release) self.__pending_action = None def __button_press(self, view, event): if event.button == Gdk.BUTTON_PRIMARY: return self.__block_selection(event) def __block_selection(self, event): x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = self.get_path_at_pos(x, y) except TypeError: return True selection = self.get_selection() is_selected = selection.path_is_selected(path) mod_active = event.get_state() & ( get_primary_accel_mod() | Gdk.ModifierType.SHIFT_MASK) if is_selected: self.__pending_action = (path, col, mod_active) selection.set_select_function(lambda *args: False, None) else: self.__pending_action = None selection.set_select_function(lambda *args: True, None) def __button_release(self, view, event): if self.__pending_action: path, col, single_unselect = self.__pending_action selection = self.get_selection() selection.set_select_function(lambda *args: True, None) if single_unselect: selection.unselect_path(path) else: self.set_cursor(path, col, 0) self.__pending_action = None class RCMTreeView(BaseView): """Emits popup-menu when a row is right-clicked on.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.connect('button-press-event', self.__button_press) def __button_press(self, view, event): if event.button == Gdk.BUTTON_SECONDARY: return self.__check_popup(event) def __check_popup(self, event): x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = self.get_path_at_pos(x, y) except TypeError: return True self.grab_focus() selection = self.get_selection() if not selection.path_is_selected(path): self.set_cursor(path, col, 0) else: col.focus_cell(col.get_cells()[0]) self.__position_at_mouse = True self.emit('popup-menu') return True def ensure_popup_selection(self): try: self.__position_at_mouse except AttributeError: path, col = self.get_cursor() if path is None: return False self.scroll_to_cell(path, col) # ensure current cursor path is selected, just like right-click selection = self.get_selection() if not selection.path_is_selected(path): selection.unselect_all() selection.select_path(path) return True def popup_menu(self, menu, button, time): try: del self.__position_at_mouse except AttributeError: # suppress menu if the cursor isn't on a real path if not self.ensure_popup_selection(): return False pos_func = self.__popup_position else: pos_func = None # force attach the menu to the view attached_widget = menu.get_attach_widget() if attached_widget != self: if attached_widget is not None: menu.detach() menu.attach_to_widget(self, None) menu_popup(menu, None, None, pos_func, None, button, time) return True def __popup_position(self, menu, *args): path, col = self.get_cursor() # get a rectangle describing the cell render area (assume 3 px pad) rect = self.get_cell_area(path, col) padding = 3 rect.x += padding rect.width = max(rect.width - padding * 2, 0) rect.y += padding rect.height = max(rect.height - padding * 2, 0) x, y = self.get_window().get_origin()[1:] x, y = self.convert_bin_window_to_widget_coords(x + rect.x, y + rect.y) menu.realize() ma = menu.get_allocation() menu_y = rect.height + y if self.get_direction() == Gtk.TextDirection.LTR: menu_x = x else: menu_x = x - ma.width + rect.width # on X11/win32 we can use the screen size if not is_wayland(): # fit menu to screen, aligned per text direction screen = self.get_screen() screen_width = screen.get_width() screen_height = screen.get_height() # show above row if no space below and enough above if menu_y + ma.height > screen_height and y - ma.height > 0: menu_y = y - ma.height # make sure it's not outside of the screen if self.get_direction() == Gtk.TextDirection.LTR: menu_x = max(0, min(menu_x, screen_width - ma.width)) else: menu_x = min(max(0, menu_x), screen_width) return (menu_x, menu_y, True) # x, y, move_within_screen class HintedTreeView(BaseView): """A TreeView that pops up a tooltip when you hover over a cell that contains ellipsized text.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.supports_hints(): try: tvh = HintedTreeView.hints except AttributeError: tvh = HintedTreeView.hints = TreeViewHints() tvh.connect_view(self) def set_tooltip_text(self, *args, **kwargs): print_e("Setting a tooltip on the view breaks tv hints. Set it" " on the parent scrolled window instead") return super().set_tooltip_text(*args, **kwargs) def supports_hints(self): """If the treeview hints support is enabled. Can be used to display scroll bars instead for example. """ if "QUODLIBET_NO_HINTS" in os.environ: return False return not config.state('disable_hints') class _TreeViewColumnLabel(Gtk.Label): """A label which fades into the background at the end; for use only in TreeViewColumns. The hackery with using the parent's allocation is needed because the label always gets the allocation it has requested, ignoring the actual width of the column header. """ def do_draw(self, ctx): alloc = self.get_allocation() # in case there are no parents use the same alloc which should # result in no custom drawing. p1 = self.get_parent() or self p2 = p1.get_parent() or p1 p3 = p2.get_parent() or p2 p2_alloc = p2.get_allocation() p3_alloc = p3.get_allocation() # remove the space needed by the arrow and add the space # added by the padding so we only start drawing when we clip # the text directly available_width = p2_alloc.width - \ abs(p2_alloc.x - alloc.x) + (p2_alloc.x - p3_alloc.x) if alloc.width <= available_width: return Gtk.Label.do_draw(self, ctx) req_height = self.get_requisition().height w, h = alloc.width, alloc.height aw = available_width # possible when adding new columns.... create_similar will fail # in this case below, so just skip. if min(w, h) < 0: return Gtk.Label.do_draw(self, ctx) surface = ctx.get_target() # draw label to image surface label_surface = surface.create_similar(cairo.CONTENT_COLOR_ALPHA, w, h) label_ctx = cairo.Context(label_surface) res = Gtk.Label.do_draw(self, label_ctx) # create a gradient. # make the gradient width depend roughly on the font size gradient_width = min(req_height * 0.8, aw) if self.get_direction() == Gtk.TextDirection.RTL: start = (w - aw) end = start + gradient_width else: end = (aw - gradient_width) start = end + gradient_width pat = cairo.LinearGradient(start, 0, end, 0) pat.add_color_stop_rgba(0, 0, 0, 0, 0) pat.add_color_stop_rgba(gradient_width, 1, 1, 1, 1) # gradient surface grad_surface = surface.create_similar(cairo.CONTENT_COLOR_ALPHA, w, h) imgctx = cairo.Context(grad_surface) imgctx.set_source(pat) imgctx.paint() # draw label using the gradient as the alpha channel mask ctx.save() ctx.set_source_surface(label_surface) ctx.mask_surface(grad_surface) ctx.restore() return res class TreeViewColumn(Gtk.TreeViewColumn): __gsignals__: GSignals = { # tree-view-changed(old_tree_view, new_tree_view) # Triggers when the columns gets added/removed from a tree view. # The passed values are either a TreeView or None 'tree-view-changed': ( GObject.SignalFlags.RUN_LAST, None, (object, object)), } def __init__(self, **kwargs): title = kwargs.pop("title", u"") # skip overrides which don't allow to set properties GObject.Object.__init__(self, **kwargs) label = _TreeViewColumnLabel(label=title) label.set_padding(1, 1) label.show() self.set_widget(label) # the button gets created once the widget gets realized self._button = None self._tooltip_text = None label.__realize = label.connect('realize', self.__realized) def __realized(self, widget): widget.disconnect(widget.__realize) self._button = widget.get_ancestor(Gtk.Button) self.set_tooltip_text(self._tooltip_text) def on_parent_set(button, old_parent): new_parent = button.get_parent() assert new_parent is None or isinstance(new_parent, Gtk.TreeView) self.emit("tree-view-changed", old_parent, new_parent) # parent already set, emit manually on_parent_set(self._button, None) self._button.connect("parent-set", on_parent_set) def set_tooltip_text(self, text): if self._button: self._button.props.tooltip_text = text else: self._tooltip_text = text def set_use_markup(self, value): widget = self.get_widget() if isinstance(widget, Gtk.Label): widget.set_use_markup(value) class TreeViewColumnButton(TreeViewColumn): """A TreeViewColumn that forwards its header events: button-press-event and popup-menu""" __gsignals__: GSignals = { 'button-press-event': (GObject.SignalFlags.RUN_LAST, bool, (object,)), 'popup-menu': (GObject.SignalFlags.RUN_LAST, bool, tuple()), } def __init__(self, **kwargs): super().__init__(**kwargs) label = self.get_widget() label.__realize = label.connect('realize', self.__connect_menu_event) def __connect_menu_event(self, widget): widget.disconnect(widget.__realize) del widget.__realize button = widget.get_ancestor(Gtk.Button) if button: button.connect('button-press-event', self.button_press_event) button.connect('popup-menu', self.popup_menu) def button_press_event(self, widget, event): return self.emit('button-press-event', event) def popup_menu(self, widget): return self.emit('popup-menu') class RCMHintedTreeView(HintedTreeView, RCMTreeView, DragIconTreeView): """A TreeView that has hints and a context menu.""" pass class AllTreeView(HintedTreeView, RCMTreeView, DragIconTreeView, MultiDragTreeView): """A TreeView that has hints, a context menu, and multi-selection dragging support.""" pass ��������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1625496978.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/window.py������������������������������������������������������������0000664�0001750�0001750�00000035171�14070616622�017044� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2014 Christoph Reiter # 2014,2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys import os from typing import List from gi.repository import Gtk, Gdk from quodlibet import config from quodlibet.qltk import get_top_parent, is_wayland, gtk_version, is_accel from quodlibet.qltk.x import Button from quodlibet.util import DeferredSignal, print_d, print_w from quodlibet.util import connect_obj, connect_destroy def on_first_map(window, callback, *args, **kwargs): """Calls callback when the passed Gtk.Window is first visible on screen or it already is. """ assert isinstance(window, Gtk.Window) if window.get_mapped(): callback(*args, **kwargs) return False id_ = [0] def on_map(*otherargs): window.disconnect(id_[0]) callback(*args, **kwargs) id_[0] = window.connect("map", on_map) return False def should_use_header_bar(): settings = Gtk.Settings.get_default() if not settings: return False if not hasattr(settings.props, "gtk_dialogs_use_header"): return False return settings.get_property("gtk-dialogs-use-header") def fix_default_size(width, height): # https://bugzilla.gnome.org/show_bug.cgi?id=740922 if gtk_version < (3, 19): # fixed with 3.20: # https://bugzilla.gnome.org/show_bug.cgi?id=756618 if width != -1: width += min((width - 174), 56) if height != -1: height += 84 return (width, height) class Dialog(Gtk.Dialog): """A Gtk.Dialog subclass which supports the use_header_bar property for all Gtk versions and will ignore it if header bars shouldn't be used according to GtkSettings. """ def __init__(self, *args, **kwargs): if not should_use_header_bar(): kwargs.pop("use_header_bar", None) super().__init__(*args, **kwargs) def get_titlebar(self): try: # gtk+ >=3.16 return super().get_titlebar() except AttributeError: return None def set_default_size(self, width, height): if self.get_titlebar(): width, height = fix_default_size(width, height) else: # In case we don't use a headerbar we have to add an additional # row of buttons in the content box. To get roughly the same # content height make the window a bit taller. if height != -1: height += 20 super().set_default_size(width, height) def add_icon_button(self, label, icon_name, response_id): """Like add_button() but allows to pass an icon name""" button = Button(label, icon_name) # file chooser uses grab_default() on this button.set_can_default(True) button.show() self.add_action_widget(button, response_id) return button class Window(Gtk.Window): """Base window class the keeps track of all window instances. All active instances can be accessed through Window.windows. By defining dialog=True as a kwarg binds Escape to close, otherwise ^W will close the window. """ windows: List[Gtk.Window] = [] _preven_inital_show = False def __init__(self, *args, **kwargs): self._header_bar = None dialog = kwargs.pop("dialog", True) super().__init__(*args, **kwargs) type(self).windows.append(self) if dialog: # Modal is the only way to center the window on the parent # with wayland atm if is_wayland(): self.set_modal(True) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.set_destroy_with_parent(True) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) connect_obj(self, 'destroy', type(self).windows.remove, self) self.connect('key-press-event', self._on_key_press) def _on_key_press(self, widget, event): is_dialog = (self.get_type_hint() == Gdk.WindowTypeHint.DIALOG) if (is_dialog and is_accel(event, "Escape")) or ( not is_dialog and is_accel(event, "<Primary>w")): # Do not close the window if we edit a Gtk.CellRendererText. # Focus the treeview instead. if isinstance(self.get_focus(), Gtk.Entry) and \ isinstance(self.get_focus().get_parent(), Gtk.TreeView): self.get_focus().get_parent().grab_focus() return Gdk.EVENT_PROPAGATE self.close() return Gdk.EVENT_STOP if not is_dialog and is_accel(event, "F11"): self.toggle_fullscreen() return Gdk.EVENT_STOP return Gdk.EVENT_PROPAGATE def toggle_fullscreen(self): """Toggle the fullscreen mode of the window depending on its current state. If the windows isn't realized it will switch to fullscreen when it does. """ window = self.get_window() if not window: is_fullscreen = False else: is_fullscreen = window.get_state() & Gdk.WindowState.FULLSCREEN if is_fullscreen: self.unfullscreen() else: self.fullscreen() def set_default_size(self, width, height): if self._header_bar: width, height = fix_default_size(width, height) super().set_default_size(width, height) def use_header_bar(self): """Try to use a headerbar, returns the widget or None in case GTK+ is too old or headerbars are disabled (under xfce for example) """ assert not self._header_bar if not should_use_header_bar(): return False header_bar = Gtk.HeaderBar() header_bar.set_show_close_button(True) header_bar.show() old_title = self.get_title() self.set_titlebar(header_bar) if old_title is not None: self.set_title(old_title) self._header_bar = header_bar self.set_default_size(*self.get_default_size()) return header_bar def has_close_button(self): """Returns True in case we are sure that the window decorations include a close button. """ if self.get_type_hint() == Gdk.WindowTypeHint.NORMAL: return True if os.name == "nt": return True if sys.platform == "darwin": return True if self._header_bar is not None: return self._header_bar.get_show_close_button() screen = Gdk.Screen.get_default() if hasattr(screen, "get_window_manager_name"): # X11 only wm_name = screen.get_window_manager_name() # Older Gnome Shell didn't show close buttons. # We can't get the version but the GTK+ version is a good guess, # I guess.. if wm_name == "GNOME Shell" and gtk_version < (3, 18): return False return True def present(self): """A version of present that also works if not called from an event handler (there is no active input event). See https://bugzilla.gnome.org/show_bug.cgi?id=688830 """ try: from gi.repository import GdkX11 except ImportError: super().present() else: window = self.get_window() if window and isinstance(window, GdkX11.X11Window): timestamp = GdkX11.x11_get_server_time(window) self.present_with_time(timestamp) else: super().present() def set_transient_for(self, parent): """Set a parent for the window. In case parent=None, fall back to the main window. """ is_toplevel = parent and parent.props.type == Gtk.WindowType.TOPLEVEL if parent is None or not is_toplevel: if parent: print_w("Not a toplevel window set for: %r" % self) from quodlibet import app parent = app.window super().set_transient_for(parent) @classmethod def prevent_inital_show(cls, value): cls._preven_inital_show = bool(value) def show_maybe(self): """Show the window, except if prevent_inital_show() was called and this is the first time. Returns whether the window was shown. """ if not self._preven_inital_show: self.show() return not self._preven_inital_show class PersistentWindowMixin: """A mixin for saving/restoring window size/position/maximized state""" def enable_window_tracking(self, config_prefix, size_suffix=""): """Enable tracking/saving of changes and restore size/pos/maximized. Make sure to call set_transient_for() before since position is restored relative to the parent in this case. config_prefix -- prefix for the config key (prefix_size, prefix_position, prefix_maximized) size_suffix -- optional suffix for saving the size. For cases where the window has multiple states with different content sizes. (example: edit tags with one song or multiple) """ self.__state = 0 self.__name = config_prefix self.__size_suffix = size_suffix self.__save_size_pos_deferred = DeferredSignal( self.__do_save_size_pos, timeout=50, owner=self) self.connect('configure-event', self.__configure_event) self.connect('window-state-event', self.__window_state_changed) self.connect('notify::visible', self.__visible_changed) parent = self.get_transient_for() if parent: connect_destroy( parent, 'configure-event', self.__parent_configure_event) self.__restore_window_state() def __visible_changed(self, *args): if not self.get_visible(): # https://bugzilla.gnome.org/show_bug.cgi?id=731287 # if we restore after hide, mutter will remember for the next show # hurray! self.__restore_window_state() def __restore_window_state(self): if not is_wayland(): self.__restore_state() self.__restore_position() self.__restore_size() def __conf(self, name): if name == "size": name += "_" + self.__size_suffix return "%s_%s" % (self.__name, name) def __restore_state(self): print_d("Restore state") if config.getint("memory", self.__conf("maximized"), 0): self.maximize() else: self.unmaximize() def __restore_position(self): print_d("Restore position") pos = config.get('memory', self.__conf("position"), "") if not pos: return try: x, y = map(int, pos.split()) except ValueError: return parent = self.get_transient_for() if parent: px, py = parent.get_position() x += px y += py self.move(x, y) def __restore_size(self): print_d("Restore size") value = config.get('memory', self.__conf("size"), "") if not value: return try: x, y = map(int, value.split()) except ValueError: return screen = self.get_screen() x = min(x, screen.get_width()) y = min(y, screen.get_height()) if x >= 1 and y >= 1: self.resize(x, y) def __parent_configure_event(self, window, event): # since our position is relative to the parent if we have one, # we also need to save our position if the parent position changes self.__do_save_pos() return False def __configure_event(self, window, event): # xfwm4 resized the window before it maximizes it, which leads # to QL remembering the wrong size. Work around that by waiting # until configure-event settles down, at which point the maximized # state should be set self.__save_size_pos_deferred() return False def _should_ignore_state(self): if self.__state & Gdk.WindowState.MAXIMIZED: return True elif self.__state & Gdk.WindowState.FULLSCREEN: return True elif not self.get_visible(): return True return False def __do_save_size_pos(self): if self._should_ignore_state(): return width, height = self.get_size() value = "%d %d" % (width, height) config.set("memory", self.__conf("size"), value) self.__do_save_pos() def __do_save_pos(self): if self._should_ignore_state(): return x, y = self.get_position() parent = self.get_transient_for() if parent: px, py = parent.get_position() x -= px y -= py pos_value = '%s %s' % (x, y) config.set('memory', self.__conf("position"), pos_value) def __window_state_changed(self, window, event): self.__state = event.new_window_state if self.__state & Gdk.WindowState.WITHDRAWN: return maximized = int(self.__state & Gdk.WindowState.MAXIMIZED) config.set("memory", self.__conf("maximized"), maximized) class _Unique: """A mixin for window-like classes to ensure one instance per class. """ __window = None def __new__(klass, *args, **kwargs): window = klass.__window if window is None: return super(_Unique, klass).__new__(klass, *args, **kwargs) # Look for widgets in the args, if there is one and it has # a new top level window, re-parent and reposition the window. widgets = [w for w in args if isinstance(w, Gtk.Widget)] if widgets: parent = window.get_transient_for() new_parent = get_top_parent(widgets[0]) if parent and new_parent and parent is not new_parent: window.set_transient_for(new_parent) window.hide() window.show() window.present() return window @classmethod def is_not_unique(klass): """Returns True if a window instance already exists.""" return bool(klass.__window) def __init__(self, *args, **kwargs): if type(self).__window: return else: type(self).__window = self super().__init__(*args, **kwargs) connect_obj(self, 'destroy', self.__destroy, self) def __destroy(self, *args): type(self).__window = None class UniqueWindow(_Unique, Window): pass �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/wlw.py���������������������������������������������������������������0000644�0001750�0001750�00000020643�14324322342�016335� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import math import time from gi.repository import Gtk, Pango, Gdk from quodlibet import _ from quodlibet.qltk import get_top_parent, Icons, Button, ToggleButton from quodlibet.util import format_int_locale, format_time_display class WaitLoadBase: """Abstract class providing a label, a progressbar, pause/stop buttons, and the stepping logic.""" def __init__(self, count=0, text="", initial={}, limit=3): """count: the total amount of items expected, 0 for unknown/indefinite text: text to display in the label; may contain % formats initial: initial values for % formats (text % initial) limit: count must be greater than limit (or 0) for pause/stop to appear The current iteration of the counter can be gotten as self.current. count can be gotten as self.count. """ super().__init__() self._label = Gtk.Label() self._label.set_use_markup(True) self._progress = Gtk.ProgressBar() self._progress.set_pulse_step(0.08) self.pulse = self._progress.pulse self.set_fraction = self._progress.set_fraction self.set_text = self._label.set_markup self.setup(count, text, initial) if self.count > limit or self.count == 0: # Add stop/pause buttons. count = 0 means an indefinite # number of steps. self._cancel_button = Button(_("_Stop"), Icons.PROCESS_STOP) self._pause_button = ToggleButton(_("P_ause"), Icons.MEDIA_PLAYBACK_PAUSE) self._cancel_button.connect('clicked', self.__cancel_clicked) self._pause_button.connect('clicked', self.__pause_clicked) else: self._cancel_button = None self._pause_button = None def setup(self, count=0, text="", initial=None): self.current = 0 self.count = count self._text = text self.paused = False self.quit = False self._start_time = time.time() initial = initial or {} initial.setdefault("total", self.count) initial.setdefault("current", self.current) initial.setdefault("remaining", _("Unknown")) def localeify(k, v): foo = '%(' + k + ')d' if foo in self._text: self._text = self._text.replace(foo, '%(' + k + ')s') return k, format_int_locale(int(v)) return k, v localed = dict(localeify(k, v) for k, v in initial.items()) self._label.set_markup(self._text % localed) self._progress.set_fraction(0.0) def __pause_clicked(self, button): self.paused = button.get_active() def __cancel_clicked(self, button): self.quit = True def step(self, **values): """Advance the counter by one. Arguments are applied to the originally-supplied text as a format string. This function doesn't return if the dialog is paused (though the GTK main loop will still run), and returns True if stop was pressed. """ if self.count: self.current += 1 self._progress.set_fraction( max(0, min(1, self.current / float(self.count)))) else: self._progress.pulse() values.setdefault("total", format_int_locale(self.count)) values.setdefault("current", format_int_locale(self.current)) if self.count: t = (time.time() - self._start_time) / self.current remaining = math.ceil((self.count - self.current) * t) values.setdefault("remaining", format_time_display(remaining)) self._label.set_markup(self._text % values) while not self.quit and (self.paused or Gtk.events_pending()): Gtk.main_iteration() return self.quit class WaitLoadWindow(WaitLoadBase, Gtk.Window): """A window with a progress bar and some nice updating text, as well as pause/stop buttons. Example: w = WaitLoadWindow(None, 5, "%(current)d/%(total)d") for i in range(1, 6): w.step() w.destroy() """ def __init__(self, parent, *args): """parent: the parent window, or None""" Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL) self.set_decorated(False) WaitLoadBase.__init__(self) self.setup(*args) parent = get_top_parent(parent) if parent: sig = parent.connect('configure-event', self.__recenter) self.connect('destroy', self.__reset_cursor, parent) self.connect('destroy', self.__disconnect, sig, parent) sig_vis = parent.connect( 'visibility-notify-event', self.__update_visible) self.connect('destroy', self.__disconnect, sig_vis, parent) self.set_transient_for(parent) window = parent.get_window() if window: window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) # Note that this should not be modal as popups occuring during # progress will not be clickable self.add(Gtk.Frame()) self.get_child().set_shadow_type(Gtk.ShadowType.OUT) vbox = Gtk.VBox(spacing=12) vbox.set_border_width(12) self._label.set_size_request(170, -1) self._label.set_line_wrap(True) self._label.set_justify(Gtk.Justification.CENTER) vbox.pack_start(self._label, True, True, 0) vbox.pack_start(self._progress, True, True, 0) if self._cancel_button and self._pause_button: # Display a stop/pause box. count = 0 means an indefinite # number of steps. hbox = Gtk.HBox(spacing=6, homogeneous=True) hbox.pack_start(self._cancel_button, True, True, 0) hbox.pack_start(self._pause_button, True, True, 0) vbox.pack_start(hbox, True, True, 0) self.get_child().add(vbox) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.get_child().show_all() while Gtk.events_pending(): Gtk.main_iteration() def __update_visible(self, parent, event): if event.state == Gdk.VisibilityState.FULLY_OBSCURED: self.hide() else: self.show() def __recenter(self, parent, event): x, y = parent.get_position() dx, dy = parent.get_size() dx2, dy2 = self.get_size() self.move(x + dx // 2 - dx2 // 2, y + dy // 2 - dy2 // 2) def __disconnect(self, widget, sig, parent): parent.disconnect(sig) def __reset_cursor(self, widget, parent): if parent.get_window(): parent.get_window().set_cursor(None) class WritingWindow(WaitLoadWindow): """A WaitLoadWindow that defaults to text suitable for saving files.""" def __init__(self, parent, count): super().__init__( parent, count, (_("Saving the songs you changed.") + "\n\n" + _("%(current)d/%(total)d songs saved\n(%(remaining)s remaining)") )) def step(self): return super().step() class WaitLoadBar(WaitLoadBase, Gtk.HBox): def __init__(self): super().__init__() self._label.set_alignment(0.0, 0.5) self._label.set_ellipsize(Pango.EllipsizeMode.END) self._cancel_button.remove(self._cancel_button.get_child()) self._cancel_button.add(Gtk.Image.new_from_icon_name( Icons.PROCESS_STOP, Gtk.IconSize.MENU)) self._pause_button.remove(self._pause_button.get_child()) self._pause_button.add(Gtk.Image.new_from_icon_name( Icons.MEDIA_PLAYBACK_PAUSE, Gtk.IconSize.MENU)) self.pack_start(self._label, True, True, 0) self.pack_start(self._progress, False, True, 6) self.pack_start(self._pause_button, False, True, 0) self.pack_start(self._cancel_button, False, True, 0) for child in self.get_children(): child.show_all() def step(self, **values): ret = super().step(**values) params = {"current": format_int_locale(self.current), "all": format_int_locale(self.count)} self._progress.set_text(_("%(current)s of %(all)s") % params) return ret ���������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/qltk/x.py�����������������������������������������������������������������0000644�0001750�0001750�00000042633�14327505043�016002� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2020-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. """ Things that are more or less direct wrappers around GTK widgets to ease constructors. """ from typing import Optional from urllib.request import urlopen from gi.repository import Gtk, GObject, GLib, Gio, GdkPixbuf, Gdk from quodlibet.util.dprint import print_d from quodlibet import util from quodlibet.util import print_w from quodlibet.util.thread import call_async, Cancellable from quodlibet.qltk import add_css, is_accel, gtk_version from .paned import Paned, RPaned, RHPaned, RVPaned, ConfigRPaned, \ ConfigRHPaned, ConfigRVPaned Paned, RPaned, RHPaned, RVPaned, ConfigRPaned, ConfigRHPaned, ConfigRVPaned class ScrolledWindow(Gtk.ScrolledWindow): """Draws a border around all edges that don't touch the parent window""" def do_size_allocate(self, alloc): if self.get_shadow_type() == Gtk.ShadowType.NONE: return Gtk.ScrolledWindow.do_size_allocate(self, alloc) toplevel = self.get_toplevel() # try to get the child so we ignore the CSD toplevel = toplevel.get_child() or toplevel try: dx, dy = self.translate_coordinates(toplevel, 0, 0) except TypeError: GLib.idle_add(self.queue_resize) return Gtk.ScrolledWindow.do_size_allocate(self, alloc) ctx = self.get_style_context() border = ctx.get_border(ctx.get_state()) # https://bugzilla.gnome.org/show_bug.cgi?id=694844 border.left = border.top = border.right = border.bottom = 1 # XXX: ugly, ugly hack # Pretend the main window toolbar is the top of the window. # This removes the top border in case the ScrolledWindow # is drawn right below the toolbar. try: top_bar = toplevel.top_bar if not isinstance(top_bar, Gtk.Widget): raise TypeError except (AttributeError, TypeError): pass else: top_ctx = top_bar.get_style_context() b = top_ctx.get_border(top_ctx.get_state()) if b.bottom: dy_bar = self.translate_coordinates(top_bar, 0, 0)[1] dy_bar -= top_bar.get_allocation().height dy = min(dy, dy_bar) # since 3.15 the gdkwindow moves to dx==-1 with the allocation # so ignore anything < 0 (I guess something passes the adjusted alloc # to us a second time) # https://git.gnome.org/browse/gtk+/commit/?id=fdf367e8689cb dx = max(0, dx) dy = max(0, dy) # Don't remove the border if the border is drawn inside # and the scrollbar on that edge is visible bottom = left = right = top = False if gtk_version < (3, 19): value = GObject.Value() value.init(GObject.TYPE_BOOLEAN) # default to True: # https://bugzilla.gnome.org/show_bug.cgi?id=701058 value.set_boolean(True) ctx.get_style_property("scrollbars-within-bevel", value) scroll_within = value.get_boolean() value.unset() else: # was deprecated in gtk 3.20 # https://git.gnome.org/browse/gtk+/commit/?id= # 7c0f0e882ae60911e39aaf7b42fb2d94108f3474 scroll_within = True if not scroll_within: h, v = self.get_hscrollbar(), self.get_vscrollbar() hscroll = vscroll = False if h.get_visible(): req = h.size_request() hscroll = bool(req.width + req.height) if v.get_visible(): req = v.size_request() vscroll = bool(req.width + req.height) placement = self.get_placement() if placement == Gtk.CornerType.TOP_LEFT: bottom = hscroll right = vscroll elif placement == Gtk.CornerType.BOTTOM_LEFT: right = vscroll top = hscroll elif placement == Gtk.CornerType.TOP_RIGHT: bottom = hscroll left = vscroll elif placement == Gtk.CornerType.BOTTOM_RIGHT: left = vscroll top = hscroll top_alloc = toplevel.get_allocation() width, height = top_alloc.width, top_alloc.height if alloc.height + dy == height and not bottom: alloc.height += border.bottom if alloc.width + dx == width and not right: alloc.width += border.right if dy == 0 and not top: alloc.y -= border.top alloc.height += border.top if dx == 0 and not left: alloc.x -= border.left alloc.width += border.left return Gtk.ScrolledWindow.do_size_allocate(self, alloc) MT = Gdk.ModifierType class Notebook(Gtk.Notebook): """A regular gtk.Notebook, except when appending a page, if no label is given, the page's 'title' attribute (either a string or a widget) is used.""" _KEY_MODS = (MT.SHIFT_MASK | MT.CONTROL_MASK | MT.MOD1_MASK | MT.MOD2_MASK) """Keyboard modifiers of interest""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.connect("key-press-event", self.__key_pressed) def __key_pressed(self, _widget: Gtk.Widget, event: Gdk.Event): # alt+X switches to page X for i in range(self.get_n_pages()): if is_accel(event, "<alt>%d" % (i + 1)): self.set_current_page(i) return Gdk.EVENT_STOP state = event.state & self._KEY_MODS # Use hardware, as Gtk+ seems to special-case tab for itself if event.hardware_keycode == 23: total = self.get_n_pages() current = self.get_current_page() if state == (MT.SHIFT_MASK | MT.CONTROL_MASK | MT.MOD2_MASK): self.set_current_page((current + total - 1) % total) return Gdk.EVENT_STOP elif state == (MT.CONTROL_MASK | MT.MOD2_MASK): self.set_current_page((current + 1) % total) return Gdk.EVENT_STOP else: print_d(f"Unhandled tab key combo: {event.state}") return Gdk.EVENT_PROPAGATE def do_size_allocate(self, alloc): ctx = self.get_style_context() border = ctx.get_border(ctx.get_state()) toplevel = self.get_toplevel() # try to get the child so we ignore the CSD toplevel = toplevel.get_child() or toplevel try: dx, dy = self.translate_coordinates(toplevel, 0, 0) except TypeError: GLib.idle_add(self.queue_resize) return Gtk.Notebook.do_size_allocate(self, alloc) dx = max(0, dx) dy = max(0, dy) # all 0 since gtk+ 3.12.. border.left = border.top = border.right = border.bottom = 1 top_alloc = toplevel.get_allocation() width, height = top_alloc.width, top_alloc.height if alloc.height + dy == height: alloc.height += border.bottom if alloc.width + dx == width: alloc.width += border.right if dy == 0: alloc.y -= border.top alloc.height += border.top if dx == 0: alloc.x -= border.left alloc.width += border.left return Gtk.Notebook.do_size_allocate(self, alloc) def append_page(self, page, label=None): if label is None: try: label = page.title except AttributeError: raise TypeError("no page.title and no label given") if not isinstance(label, Gtk.Widget): label = Gtk.Label(label=label) super().append_page(page, label) def Frame(label, child=None): """A Gtk.Frame with no shadow, 12px left padding, and 6px top padding.""" frame = Gtk.Frame() label_w = Gtk.Label() label_w.set_markup(util.bold(label)) align = Align(left=12, top=6) frame.add(align) frame.set_shadow_type(Gtk.ShadowType.NONE) frame.set_label_widget(label_w) if child: align.add(child) label_w.set_mnemonic_widget(child) label_w.set_use_underline(True) return frame class Align(Gtk.Alignment): """Note: With gtk3.12+ we could replace this with a Gtk.Bin + margin properties. """ def __init__(self, child=None, top=0, right=0, bottom=0, left=0, border=0, halign=Gtk.Align.FILL, valign=Gtk.Align.FILL): def align_to_xy(a): """(xyalign, xyscale)""" if a == Gtk.Align.FILL: return 0.0, 1.0 elif a == Gtk.Align.START: return 0.0, 0.0 elif a == Gtk.Align.END: return 1.0, 0.0 elif a == Gtk.Align.CENTER: return 0.5, 0.0 else: return 0.5, 1.0 xalign, xscale = align_to_xy(halign) yalign, yscale = align_to_xy(valign) bottom_padding = border + bottom top_padding = border + top left_padding = border + left right_padding = border + right super().__init__(xalign=xalign, xscale=xscale, yalign=yalign, yscale=yscale, bottom_padding=bottom_padding, top_padding=top_padding, left_padding=left_padding, right_padding=right_padding) if child is not None: self.add(child) def get_margin_top(self): return self.props.top_padding def get_margin_bottom(self): return self.props.bottom_padding def get_margin_left(self): return self.props.left_padding def get_margin_right(self): return self.props.right_padding def MenuItem(label, icon_name: Optional[str] = None, tooltip: Optional[str] = None): """An ImageMenuItem with a custom label and stock image.""" if icon_name is None: return Gtk.MenuItem.new_with_mnemonic(label) item = Gtk.ImageMenuItem.new_with_mnemonic(label) if tooltip: item.set_tooltip_text(tooltip) item.set_always_show_image(True) image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU) image.show() item.set_image(image) return item def _Button(type_, label, icon_name, size): if icon_name is None: return type_.new_with_mnemonic(label) align = Align(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER) hbox = Gtk.HBox(spacing=6) image = Gtk.Image.new_from_icon_name(icon_name, size) hbox.pack_start(image, True, True, 0) label = Gtk.Label(label=label) label.set_use_underline(True) hbox.pack_start(label, True, True, 0) align.add(hbox) align.show_all() button = type_() button.add(align) return button def Button(label, icon_name=None, size=Gtk.IconSize.BUTTON): """A Button with a custom label and stock image. It should pack exactly like a stock button. """ return _Button(Gtk.Button, label, icon_name, size) def ToggleButton(label, icon_name=None, size=Gtk.IconSize.BUTTON): """A ToggleButton with a custom label and stock image. It should pack exactly like a stock button. """ return _Button(Gtk.ToggleButton, label, icon_name, size) class _SmallImageButton: """A button for images with less padding""" def __init__(self, **kwargs): super().__init__(**kwargs) self.set_size_request(26, 26) add_css(self, """ * { padding: 0px; } """) class SmallImageButton(_SmallImageButton, Gtk.Button): pass class SmallImageToggleButton(_SmallImageButton, Gtk.ToggleButton): pass def EntryCompletion(words): """Simple string completion.""" model = Gtk.ListStore(str) for word in sorted(words): model.append(row=[word]) comp = Gtk.EntryCompletion() comp.set_model(model) comp.set_text_column(0) return comp def RadioMenuItem(*args, **kwargs): """RadioMenuItem that allows None for group""" if kwargs.get("group", None) is None: kwargs.pop("group", None) return Gtk.RadioMenuItem(*args, **kwargs) def SeparatorMenuItem(*args, **kwargs): # https://bugzilla.gnome.org/show_bug.cgi?id=670575 # PyGObject 3.2 always sets a label in __init__ if not args and not kwargs: return Gtk.SeparatorMenuItem.new() return Gtk.SeparatorMenuItem(*args, **kwargs) def SymbolicIconImage(name, size, fallbacks=None): """Gtk.Image that displays a symbolic version of 'name' and falls back to the non-symbolic one. """ symbolic_name = name + "-symbolic" gicon = Gio.ThemedIcon.new_from_names([symbolic_name, name]) return Gtk.Image.new_from_gicon(gicon, size) class CellRendererPixbuf(Gtk.CellRendererPixbuf): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if gtk_version < (3, 16): # was deprecated in 3.16 and defaults to True now. Since it was # False before force it here so we have the same behavior in all # cases self.set_property("follow-state", True) class Action(Gtk.Action): def __init__(self, *args, **kargs): # Older pygobject didn't pass through kwargs to GObject.Object # so skip the override __init__ GObject.Object.__init__(self, *args, **kargs) class ToggleAction(Gtk.ToggleAction): def __init__(self, *args, **kargs): GObject.Object.__init__(self, *args, **kargs) class RadioAction(Gtk.RadioAction): def __init__(self, *args, **kargs): GObject.Object.__init__(self, *args, **kargs) class WebImage(Gtk.Image): """A Gtk.Image which loads the image over HTTP in the background and displays it when available. """ def __init__(self, url, width=-1, height=-1): """ Args: url (str): an HTTP URL width (int): a width to reserve for the image or -1 height (int): a height to reserve for the image or -1 """ super().__init__() self._cancel = Cancellable() call_async(self._fetch_image, self._cancel, self._finished, (url,)) self.connect("destroy", self._on_destroy) self.set_size_request(width, height) self.set_from_icon_name("image-loading", Gtk.IconSize.BUTTON) def _on_destroy(self, *args): self._cancel.cancel() def _fetch_image(self, url): try: data = urlopen(url).read() except Exception as e: print_w("Couldn't read web image from %s (%s)" % (url, e)) return None try: loader = GdkPixbuf.PixbufLoader() except GLib.GError as e: print_w("Couldn't create GdkPixbuf (%s)" % e) else: loader.write(data) loader.close() print_d("Got web image from %s" % url) return loader.get_pixbuf() def _finished(self, pixbuf): if pixbuf is None: self.set_from_icon_name("image-missing", Gtk.IconSize.BUTTON) else: self.set_from_pixbuf(pixbuf) class HighlightToggleButton(Gtk.ToggleButton): """A ToggleButton which changes the foreground color when active""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._provider = None self._color = "" self._dummy = Gtk.ToggleButton() def _update_provider(self): # not active, reset everything if not self.get_active(): if self._provider is not None: style_context = self.get_style_context() style_context.remove_provider(self._provider) self._provider = None self._color = "" return # in case the foreground changes between normal and checked # state assume that the theme does some highlighting and stop. style_context = self._dummy.get_style_context() style_context.save() style_context.set_state(Gtk.StateFlags.NORMAL) a = style_context.get_color(style_context.get_state()) style_context.set_state(Gtk.StateFlags.CHECKED) b = style_context.get_color(style_context.get_state()) same_color = (a.to_string() == b.to_string()) style_context.restore() if not same_color: style_context = self.get_style_context() if self._provider is not None: style_context.remove_provider(self._provider) self._provider = None self._color = "" return # force a color style_context = self.get_style_context() style_context.save() style_context.set_state(Gtk.StateFlags.VISITED) color = style_context.get_color(style_context.get_state()) style_context.restore() if self._color != color.to_string(): self._color = color.to_string() style_context = self.get_style_context() if self._provider is not None: style_context.remove_provider(self._provider) provider = Gtk.CssProvider() provider.load_from_data( (u"* {color: %s}" % self._color).encode("ascii")) style_context.add_provider( provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) self._provider = provider def do_draw(self, context): self._update_provider() return Gtk.ToggleButton.do_draw(self, context) �����������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735242.0109358 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/query/��������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015337� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/query/__init__.py���������������������������������������������������������0000664�0001750�0001750�00000000461�14035600052�017447� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from ._query import Query, QueryType Query, QueryType ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692647462.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/query/_match.py�����������������������������������������������������������0000644�0001750�0001750�00000042045�14470740046�017160� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2011 Christoph Reiter # 2016 Ryan Dellenbaugh # 2016-22 Nick Boultbee # 2018 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. from __future__ import annotations import operator import time from enum import auto, Enum from numbers import Real from typing import TypeVar, List, Iterable, Optional from quodlibet.formats import FILESYSTEM_TAGS, TIME_TAGS from quodlibet.formats._audio import SIZE_TAGS, DURATION_TAGS from quodlibet.unisearch import compile from quodlibet.util import parse_date from senf import fsn2text, fsnative T = TypeVar("T") class Error(ValueError): pass class ParseError(Error): pass class Node: def search(self, data: T) -> bool: raise NotImplementedError def filter(self, sequence: Iterable[T]) -> List[T]: return [s for s in sequence if self.search(s)] def _unpack(self) -> Node: return self def __or__(self, other: Node) -> Node: return NotImplemented def __and__(self, other: Node) -> Node: return NotImplemented def __neg__(self) -> Node: return Neg(self._unpack()) @property def valid(self) -> bool: return True class Regex(Node): def __init__(self, pattern: str, mod_string: str): self.pattern = str(pattern) self.mod_string = str(mod_string) ignore_case = "c" not in self.mod_string or "i" in self.mod_string dot_all = "s" in self.mod_string asym = "d" in self.mod_string try: re = compile(self.pattern, ignore_case, dot_all, asym) self.search = re # type: ignore except ValueError: raise ParseError( "The regular expression /%s/ is invalid." % self.pattern) def __repr__(self): return "<Regex pattern=%s mod=%s>" % (self.pattern, self.mod_string) class True_(Node): """Always True""" def search(self, data): return True def filter(self, sequence): return list(sequence) def __repr__(self): return "<True>" def __or__(self, other): return self def __and__(self, other): other = other._unpack() return other class False_(Node): """Always False""" def search(self, data): return False def filter(self, sequence): return [] def __repr__(self): return "<False>" def __or__(self, other): other = other._unpack() return other def __and__(self, other): return self class Union(Node): """True if the object matches any of its REs.""" def __init__(self, res: List[Node]): self.res = res def search(self, data): for re in self.res: if re.search(data): return True return False def __repr__(self): return "<Union %r>" % self.res def __or__(self, other): other = other._unpack() if isinstance(other, Union): return Union(self.res + list(other.res)) elif isinstance(other, True_): return other.__or__(self) return Union(self.res + [other]) def __and__(self, other): other = other._unpack() if isinstance(other, (Inter, True_)): return other.__and__(self) return Inter([self, other]) class Inter(Node): """True if the object matches all of its REs.""" def __init__(self, res): self.res = res def search(self, data): for re in self.res: if not re.search(data): return False return True def filter(self, sequence): current = sequence for re in self.res: current = filter(re.search, current) if not isinstance(current, list): current = list(current) return current def __repr__(self): return "<Inter %r>" % self.res def __and__(self, other): other = other._unpack() if isinstance(other, Inter): return Inter(self.res + other.res) if isinstance(other, True_): return other.__and__(self) return Inter(self.res + [other]) def __or__(self, other): other = other._unpack() if isinstance(other, (Union, True_)): return other.__or__(self) return Union([self, other]) class Neg(Node): """True if the object doesn't match its RE.""" def __init__(self, res): self.res = res def search(self, data): return not self.res.search(data) def __repr__(self): return "<Neg %r>" % self.res def __and__(self, other): other = other._unpack() if isinstance(other, True_): return other.__and__(self) return Inter([self, other]) def __or__(self, other): other = other._unpack() if isinstance(other, True_): return other.__or__(self) return Union([self, other]) def __neg__(self): return self.res class Numcmp(Node): """Numeric comparisons""" operators = { "<": operator.lt, "<=": operator.le, ">": operator.gt, ">=": operator.ge, "=": operator.eq, "==": operator.eq, "!=": operator.ne, } def __init__(self, expr: Numexpr, op: str, expr2: Numexpr): self._expr = expr self._op = self.operators[op] self._expr2 = expr2 units = expr2.units() if units and not expr.valid_for_units(units): raise ParseError(f"Wrong units for {expr}") def search(self, data): time_ = time.time() use_date = self._expr.use_date() or self._expr2.use_date() val = self._expr.evaluate(data, time_, use_date) val2 = self._expr2.evaluate(data, time_, use_date) if val is not None and val2 is not None: return self._op(val, val2) return False def __repr__(self): return "<Numcmp expr=%r, op=%r, expr2=%r>" % ( self._expr, self._op.__name__, self._expr2) def __and__(self, other): other = other._unpack() if isinstance(other, True_): return other.__and__(self) return Inter([self, other]) def __or__(self, other): other = other._unpack() if isinstance(other, True_): return other.__or__(self) return Union([self, other]) class Numexpr: """Expression in numeric comparison""" def evaluate(self, data: T, time: float, use_date: bool): """Evaluate the expression to a number. :param data: is the audiofile to evaluate for :param time: is the current time :param use_date: whether to evaluate as a date (used to handle expressions like 2015-02-11 that look like dates and subtraction) """ raise NotImplementedError def use_date(self) -> bool: """Returns whether to force the final comparison to compare the date values instead of the number values.""" return False def units(self) -> Optional[Units]: """Returns optional (converted) units for this number""" return None def valid_for_units(self, units: Units) -> bool: """Returns true if the given unit is valid for this expression""" return True class NumexprTag(Numexpr): """Numeric tag""" def __init__(self, tag: str): self._tag = tag self._ftag = "~#" + self._tag # Strip aggregate function from tag self._base_ftag = (self._ftag or "").split(":")[0] def valid_for_units(self, units: Units) -> bool: return self._base_ftag in UNITS_TO_TAGS[units] def evaluate(self, data, time, use_date): if self._tag == 'date': date = data('date') if not date: return None try: num = parse_date(date) except ValueError: return None else: num = data(self._ftag, None) if num is not None: if self._base_ftag in TIME_TAGS: num = time - num return round(num, 2) return None def __repr__(self): return "<NumexprTag tag=%r>" % self._tag def use_date(self): return self._tag == 'date' class NumexprUnary(Numexpr): """Unary numeric operation (like -)""" operators = { '-': operator.neg } def __init__(self, op: str, expr: Numexpr): self.__op = self.operators[op] self.__expr = expr def evaluate(self, data, time, use_date): val = self.__expr.evaluate(data, time, use_date) if val is not None: return self.__op(val) return None def __repr__(self): return "<NumexprUnary op=%r expr=%r>" % (self.__op, self.__expr) def use_date(self): return self.__expr.use_date() class NumexprBinary(Numexpr): """Binary numeric operation (like + or *)""" operators = { '-': operator.sub, '+': operator.add, '*': operator.mul, '/': operator.floordiv, } precedence = { operator.sub: 1, operator.add: 1, operator.mul: 2, operator.floordiv: 2, } def __init__(self, op: str, expr: Numexpr, expr2: Numexpr): self.__op = self.operators[op] self.__expr = expr self.__expr2 = expr2 # Rearrange expressions for operator precedence if (isinstance(expr, NumexprBinary) and self.precedence[expr.__op] < self.precedence[self.__op]): self.__expr = expr.__expr self.__op = expr.__op expr.__expr = expr.__expr2 expr.__op = self.operators[op] expr.__expr2 = expr2 self.__expr2 = expr def evaluate(self, data, time, use_date): val = self.__expr.evaluate(data, time, use_date) val2 = self.__expr2.evaluate(data, time, use_date) if val is not None and val2 is not None: try: return self.__op(val, val2) except ZeroDivisionError: return val * float('inf') return None def __repr__(self): return "<NumexprBinary op=%r expr=%r expr2=%r>" % ( self.__op, self.__expr, self.__expr2) def use_date(self): return self.__expr.use_date() or self.__expr2.use_date() class NumexprGroup(Numexpr): """Parenthesized group in numeric expression""" def __init__(self, expr: Numexpr): self.__expr = expr def evaluate(self, data, time, use_date): return self.__expr.evaluate(data, time, use_date) def __repr__(self): return "<NumexprGroup expr=%r>" % (self.__expr) def use_date(self): return self.__expr.use_date() class NumexprNumber(Numexpr): """Number in numeric expression""" def __init__(self, value: Real, units: Optional[Units] = None): self._value = float(value) self._units = units def evaluate(self, data, time, use_date): return self._value def units(self) -> Optional[Units]: return self._units def __repr__(self): return "<NumexprNumber value=%.2f>" % (self._value) class NumexprNow(Numexpr): """Current time, with optional offset""" def __init__(self, offset=0): self.__offset = offset def evaluate(self, data, time, use_date): return time - self.__offset def __repr__(self): return "<NumexprNow offset=%r>" % (self.__offset) class NumexprNumberOrDate(Numexpr): """An ambiguous value like 2015-09-25 than can be interpreted as either a number or a date.""" def __init__(self, date): self.date = parse_date(date) parts = date.split('-') self.number = int(parts[0]) if len(parts) > 1: self.number -= int(parts[1]) if len(parts) > 2: self.number -= int(parts[2]) def evaluate(self, data, time, use_date): if use_date: return self.date else: return self.number def __repr__(self): return ('<NumexprNumberOrDate number=%r date=%r>' % (self.number, self.date)) class Units(Enum): SECONDS = auto() BYTES = auto() UNITS_TO_TAGS = {Units.SECONDS: TIME_TAGS | DURATION_TAGS, Units.BYTES: SIZE_TAGS} def numexprUnit(value, unit): """Process numeric units and return NumexprNumber""" unit = unit.lower().strip() converted = Units.SECONDS # Time units if unit.startswith("second"): value = value elif unit.startswith("minute"): value *= 60 elif unit.startswith("hour"): value *= 60 * 60 elif unit.startswith("day"): value *= 24 * 60 * 60 elif unit.startswith("week"): value *= 7 * 24 * 60 * 60 elif unit.startswith("month"): value *= 30 * 24 * 60 * 60 elif unit.startswith("year"): value *= 365 * 24 * 60 * 60 # Size units elif unit.startswith("g"): value *= 1024 ** 3 converted = Units.BYTES elif unit.startswith("m"): value *= 1024 ** 2 converted = Units.BYTES elif unit.startswith("k"): value *= 1024 converted = Units.BYTES elif unit.startswith("b"): converted = Units.SECONDS elif unit: raise ParseError("No such unit: %r" % unit) return NumexprNumber(value, converted) def numexprTagOrSpecial(tag): """Handle special values that look like tags""" if tag == "now": return NumexprNow() if tag == "today": return NumexprNow(offset=24 * 60 * 60) else: return NumexprTag(tag) class Tag(Node): """See if a property of the object matches its RE.""" # Shorthand for common tags. ABBRS = {"a": "artist", "b": "album", "v": "version", "t": "title", "n": "tracknumber", "d": "date", } def __init__(self, names, res): self.res = res self._names = [] self.__intern = [] self.__fs = [] names = [Tag.ABBRS.get(n.lower(), n.lower()) for n in names] for name in names: if name[:1] == "~": if name.startswith("~#"): raise ValueError("numeric tags not supported") if name in FILESYSTEM_TAGS: self.__fs.append(name) else: self.__intern.append(name) else: self._names.append(name) def search(self, data): search = self.res.search fs_default = fsnative() for name in self._names: val = data.get(name) if val is None: if name in ("filename", "mountpoint"): val = fsn2text(data.get("~" + name, fs_default)) else: val = data.get("~" + name, u"") if search(val): return True for name in self.__intern: if search(data(name)): return True for name in self.__fs: if search(fsn2text(data(name, fs_default))): return True return False def __repr__(self): names = self._names + self.__intern return ("<Tag names=%r, res=%r>" % (names, self.res)) def __and__(self, other): other = other._unpack() if isinstance(other, True_): return other.__and__(self) return Inter([self, other]) def __or__(self, other): other = other._unpack() if isinstance(other, True_): return other.__or__(self) return Union([self, other]) class Extension(Node): """Plugin-defined query extension Syntax is @(plugin_name) or @(plugin_name: body) Raises a ParseError if no plugin is loaded for the name, or if the plugin fails to parse the body""" def __init__(self, name, body): # pulls in gtk+ from quodlibet.plugins.query import QUERY_HANDLER, QueryPluginError self.__name = name self.__valid = True self.__body = body try: self.__plugin = QUERY_HANDLER.get_plugin(name) except KeyError: self.__valid = False return try: self.__body = self.__plugin.parse_body(body) except QueryPluginError: self.__valid = False return def search(self, data): return self.__valid and self.__plugin.search(data, self.__body) @property def valid(self) -> bool: return self.__valid def __repr__(self): return ('<Extension name=%r valid=%r body=%r>' % (self.__name, self.__valid, self.__body)) def __and__(self, other): other = other._unpack() if isinstance(other, (Inter, True_)): return other.__and__(self) return Inter([self] + [other]) def __or__(self, other): other = other._unpack() if isinstance(other, (Union, True_)): return other.__or__(self) return Union([self, other]) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/query/_parser.py����������������������������������������������������������0000644�0001750�0001750�00000025016�14324322342�017350� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2016 Ryan Dellenbaugh # 2017-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import codecs import re from . import _match as match from ._match import ParseError, Units from quodlibet.util import re_escape # Precompiled regexes TAG = re.compile(r'[~\w\s:]+') UNARY_OPERATOR = re.compile(r'-') BINARY_OPERATOR = re.compile(r'[+\-\*/]') RELATIONAL_OPERATOR = re.compile(r'>=|<=|==|!=|>|<|=') DIGITS = re.compile(r'\d+(\.\d+)?') WORD = re.compile(r'[ \w]+') REGEXP = re.compile(r'([^/\\]|\\.)*') SINGLE_STRING = re.compile(r"([^'\\]|\\.)*") DOUBLE_STRING = re.compile(r'([^"\\]|\\.)*') MODIFIERS = re.compile(r'[cisld]*') TEXT = re.compile(r'[^,)]+') DATE = re.compile(r'\d{4}(?!\d)(-\d{1,2}(-\d{1,2})?)?') class QueryParser: """Parse the input. One lookahead token, start symbol is Query.""" def __init__(self, tokens, star=[]): self.tokens = tokens self.index = 0 self.last_match = None self.star = star def space(self): """Advance to the first non-space token""" while not self.eof() and self.tokens[self.index] == ' ': self.index += 1 def accept(self, token): """Return whether the next token is the same as the provided token, and if so advance past it.""" self.space() if self.eof(): return False if self.tokens[self.index] == token: self.index += 1 return True else: return False def accept_re(self, regexp): """Same as accept, but with a regexp instead of a single token. Sets self.last_match to the match text upon success""" self.space() re_match = regexp.match(self.tokens, self.index) if re_match: self.index = re_match.end() re_match = re_match.group() self.last_match = re_match return re_match def expect(self, token): """Raise an error if the next token doesn't match the provided token""" if not self.accept(token): raise ParseError("'{0}' expected at index {1}, but not found" .format(token, self.index)) def expect_re(self, regexp): """Same as expect, but with a regexp instead of a single token""" if self.accept_re(regexp) is None: raise ParseError("RE match expected at index {0}, but not found" .format(self.index)) return self.last_match def eof(self): """Return whether last token has been consumed""" return self.index >= len(self.tokens) def match_list(self, rule): """Match a comma-separated list of rules""" m = [rule()] while self.accept(','): m.append(rule()) return m def StartQuery(self): """Match a query that extends until the end of the input""" s = self.Query(outer=True) if not self.eof(): raise ParseError('Query ended before end of input') return s def Query(self, outer=False): """Rule for a query or subquery. Determines type of query based on first token""" self.space() if self.eof(): return match.True_() elif self.accept('!'): return self.Negation(self.Query) elif self.accept('&'): return self.Intersection(self.Query) elif self.accept('|'): return self.Union(self.Query) elif self.accept('#'): return self.Intersection(self.Numcmp) elif self.accept('@'): return self.Extension() index = self.index try: # Equals, NotEquals and Star can begin the same, # so try in order, backtracking on failure (with Star last) return self.Equals() except ParseError: self.index = index try: return self.NotEquals() except ParseError: self.index = index return self.Star(outer=outer) def Negation(self, rule): """Rule for '!query'. '!' token is consumed in Query""" return match.Neg(rule()) def Intersection(self, rule): """Rule for '&(query, query)'. '&' token is consumed in Query""" self.expect('(') inter = match.Inter(self.match_list(rule)) self.expect(')') return inter def Union(self, rule): """Rule for '|(query, query)'. '|' token is consumed in Query""" self.expect('(') union = match.Union(self.match_list(rule)) self.expect(')') return union def Numcmp(self): """Rule for numerical comparison like 'length > 3:30'""" cmps = [] expr2 = self.Numexpr(allow_date=True) while self.accept_re(RELATIONAL_OPERATOR): expr = expr2 relop = self.last_match expr2 = self.Numexpr(allow_date=True) cmps.append(match.Numcmp(expr, relop, expr2)) if not cmps: raise ParseError('No relational operator in numerical comparison') if len(cmps) > 1: return match.Inter(cmps) else: return cmps[0] def Numexpr(self, allow_date=False): """Rule for numerical expression like 'playcount + 4'""" if self.accept('('): expr = match.NumexprGroup(self.Numexpr(allow_date=True)) self.expect(')') elif self.accept_re(UNARY_OPERATOR): expr = match.NumexprUnary(self.last_match, self.Numexpr()) elif allow_date and self.accept_re(DATE): # Parse sequences of numbers that looks like dates as either dates # or numbers try: expr = match.NumexprNumberOrDate(self.last_match) except ValueError: # If the date can't be parsed then backtrack and try again # without allowing dates self.index -= len(self.last_match) expr = self.Numexpr(allow_date=False) elif self.accept_re(DIGITS): number = float(self.last_match) if self.accept(':'): # time like 4:15 number2 = float(self.expect_re(DIGITS)) expr = match.NumexprNumber(60 * number + number2, units=Units.SECONDS) elif self.accept_re(WORD): # Number with units like 7 minutes expr = match.numexprUnit(number, self.last_match) else: expr = match.NumexprNumber(number) else: # Either tag name or special name like "today" expr = match.numexprTagOrSpecial(self.expect_re(TAG).strip()) if self.accept_re(BINARY_OPERATOR): # Try matching a binary operator then the second argument binop = self.last_match expr2 = self.Numexpr() return match.NumexprBinary(binop, expr, expr2) else: return expr def Extension(self): """Rule for plugin use like @(plugin: arguments)""" self.expect('(') name = self.expect_re(WORD) if self.accept(':'): body = self.ExtBody() else: body = None self.expect(')') return match.Extension(name, body) def ExtBody(self): """Body of plugin expression. Matches balanced parentheses""" depth = 0 index = self.index try: while True: current = self.tokens[index] if current == '(': depth += 1 elif current == ')': if depth == 0: break depth -= 1 elif current == '\\': index += 1 index += 1 except IndexError: if depth != 0: raise ParseError('Unexpected end of string while parsing ' 'extension body') result = self.tokens[self.index:index] self.index = index return result def Equals(self): """Rule for 'tag=value' queries""" tags = self.match_list(lambda: self.expect_re(TAG)) tags = [tag.strip() for tag in tags] self.expect('=') value = self.Value() return match.Tag(tags, value) def NotEquals(self): """Rule for 'tag!=value' queries""" tags = self.match_list(lambda: self.expect_re(TAG)) tags = [tag.strip() for tag in tags] self.expect('!') self.expect('=') value = self.Value() return match.Neg(match.Tag(tags, value)) def Value(self, outer=False): """Rule for value. Either a regexp, quoted string, boolean combination of values, or free text string""" if self.accept('/'): regex = self.expect_re(REGEXP) self.expect('/') return self.RegexpMods(regex) elif self.accept('"'): regex = self.str_to_re(self.expect_re(DOUBLE_STRING)) self.expect('"') return self.RegexpMods(regex) elif self.accept("'"): regex = self.str_to_re(self.expect_re(SINGLE_STRING)) self.expect("'") return self.RegexpMods(regex) elif self.accept('!'): return self.Negation(self.Value) elif self.accept('|'): return self.Union(self.Value) elif self.accept('&'): return self.Intersection(self.Value) else: if outer: # Hack to force plain text parsing for top level free text raise ParseError('Free text not allowed at top level of query') return match.Regex(re_escape(self.expect_re(TEXT)), u"d") def RegexpMods(self, regex): """Consume regexp modifiers from tokens and compile provided regexp with them. """ mod_string = self.expect_re(MODIFIERS) return match.Regex(regex, mod_string) def Star(self, outer=False): """Rule for value that matches all visible tags""" return match.Tag(self.star, self.Value(outer=outer)) def str_to_re(self, string): """Convert plain string to escaped regexp that can be compiled""" if isinstance(string, str): string = string.encode('utf-8') string = codecs.escape_decode(string)[0] string = string.decode('utf-8') return "^%s$" % re_escape(string) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692647423.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/query/_query.py�����������������������������������������������������������0000644�0001750�0001750�00000012443�14470737777�017251� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2015-2020 Nick Boultbee, # 2016 Ryan Dellenbaugh, # 2019 Peter Strulo # # 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 2 of the License, or # (at your option) any later version. from __future__ import annotations from enum import Enum, auto from typing import Optional, Type, Iterable, TypeVar from quodlibet import print_d, config from quodlibet.util import re_escape, cached_property from . import _match as match from ._match import Error, Node, False_ from ._parser import QueryParser T = TypeVar("T") class QueryType(Enum): TEXT = auto() VALID = auto() INVALID = auto() def __repr__(self): # Compact representation return self._name_ def __str__(self): return self._name_ class Query(Node): STAR: Iterable[str] = ["artist", "album", "title"] """Default tags to search in, use/extend and pass to Query()""" Error: Type[Exception] = Error """Base error type""" type: Optional[QueryType] = None """The QueryType value: VALID or TEXT""" string: Optional[str] = None """The original string which was used to create this query""" def __init__(self, string: str, star: Optional[Iterable[str]] = None): """Parses the query string and returns a match object. :param string: The text to parse :param star: Tags to look in, if none are specified in the query. Defaults to those specified in `STAR`. This parses the query language as well as some tagless shortcuts: "foo bar" -> &(star1,star2=foo,star1,star2=bar) "!foo" -> !star1,star2=foo "&(foo, bar)" -> &(star1,star2=foo, star1,star2=bar) "&(foo, !bar)" -> &(star1,star2=foo, !star1,star2=bar) "|(foo, bar)" -> |(star1,star2=foo, star1,star2=bar) "!&(foo, bar)" -> !&(star1,star2=foo, star1,star2=bar) "!(foo, bar)" -> !star1,star2=(foo, bar) etc... """ print_d(f"Creating query {string!r}") if star is None: star = self.STAR assert isinstance(string, str) self.star = list(star) self.string = string self.type = QueryType.VALID try: self._match = QueryParser(string, star=star).StartQuery() if not self._match.valid: self.type = QueryType.INVALID return except self.Error: pass if not set("#=").intersection(string): for c in config.get("browsers", "ignored_characters"): string = string.replace(c, "") parts = ["/%s/d" % re_escape(s) for s in string.split()] string = "&(" + ",".join(parts) + ")" self.string = string try: self.type = QueryType.TEXT self._match = QueryParser(string, star=star).StartQuery() return except self.Error: pass print_d("Query '%s' is invalid" % string) self.type = QueryType.INVALID self._match = False_() @classmethod def StrictQueryMatcher(cls, string): """Returns a Matcher for a strict, valid (non-freetext) Query, or `None` if this fails. """ try: return QueryParser(string).StartQuery() except Error: return None def __repr__(self) -> str: return "<Query string=%r type=%r star=%r>" % ( self.string, self.type, self.star) @cached_property def search(self): return self._match.search @cached_property def filter(self): return self._match.filter @property def valid(self) -> bool: """Whether a query is a valid full (not free-text) query""" return self.type == QueryType.VALID @property def matches_all(self) -> bool: """Whether the resulting query will not filter anything""" return isinstance(self._match, match.True_) @property def is_parsable(self) -> bool: """Whether the text can be parsed at all""" return self.type is not QueryType.INVALID def _unpack(self) -> Node: # so that other classes can see the wrapped one and optimize # the result using the type information return self._match def __or__(self, other: Node) -> Node: return self._match.__or__(other) def __and__(self, other: Node) -> Node: return self._match.__and__(other) def __neg__(self) -> Node: return self._match.__neg__() def __eq__(self, other) -> bool: return (self.string == other.string and self.star == other.star and self.type == other.type) @classmethod def validator(cls, string: str) -> Optional[bool]: """Returns True/False for a query, None for a text only query""" query = cls(string) type_ = query.type if type_ == QueryType.VALID: # in case of an empty but valid query we say it's "text" if query.matches_all: return None return True elif type_ == QueryType.INVALID: return False return None �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/remote.py�����������������������������������������������������������������0000644�0001750�0001750�00000010306�14310167056�016043� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from typing import Type from senf import path2fsn, fsn2bytes, bytes2fsn, fsnative from quodlibet.util import fifo, print_w from quodlibet import get_user_dir try: from quodlibet.util import winpipe except ImportError: winpipe = None # type: ignore class RemoteError(Exception): pass class RemoteBase: """A thing for communicating with existing instances of ourself.""" def __init__(self, app, cmd_registry): """ Args: app (Application) cmd_registry (CommandRegistry) """ raise NotImplementedError @classmethod def remote_exists(cls): """See if another instance exists Returns: bool """ raise NotImplementedError @classmethod def send_message(cls, message): """Send data to the existing instance if possible and returns a response. Args: message (fsnative) Returns: fsnative or None Raises: RemoteError: in case the message couldn't be send or there was no response. """ raise NotImplementedError def start(self): """Start the listener for other instances. Raises: RemoteError: in case another instance is already listening. """ raise NotImplementedError def stop(self): """Stop the listener for other instances""" raise NotImplementedError class QuodLibetWinRemote(RemoteBase): _NAME = "quodlibet" def __init__(self, app, cmd_registry): self._app = app self._cmd_registry = cmd_registry self._server = winpipe.NamedPipeServer(self._NAME, self._callback) @classmethod def remote_exists(cls): return winpipe.pipe_exists(cls._NAME) @classmethod def send_message(cls, message): data = fsn2bytes(path2fsn(message), "utf-8") try: winpipe.write_pipe(cls._NAME, data) except EnvironmentError as e: raise RemoteError(e) def start(self): try: self._server.start() except winpipe.NamedPipeServerError as e: raise RemoteError(e) def stop(self): self._server.stop() def _callback(self, data): message = bytes2fsn(data, "utf-8") self._cmd_registry.handle_line(self._app, message) class QuodLibetUnixRemote(RemoteBase): _FIFO_NAME = "control" _PATH = os.path.join(get_user_dir(), _FIFO_NAME) def __init__(self, app, cmd_registry): self._app = app self._cmd_registry = cmd_registry self._fifo = fifo.FIFO(self._PATH, self._callback) @classmethod def remote_exists(cls): return fifo.fifo_exists(cls._PATH) @classmethod def send_message(cls, message): assert isinstance(message, fsnative) try: return fifo.write_fifo(cls._PATH, fsn2bytes(message, None)) except fifo.FIFOError as e: raise RemoteError(e) def start(self): try: self._fifo.open() except fifo.FIFOError as e: raise RemoteError(e) def stop(self): self._fifo.destroy() def _callback(self, data): try: messages = list(fifo.split_message(data)) except ValueError: print_w("invalid message: %r" % data) return for command, path in messages: command = bytes2fsn(command, None) response = self._cmd_registry.handle_line(self._app, command) if path is not None: path = bytes2fsn(path, None) with open(path, "wb") as h: if response is not None: assert isinstance(response, fsnative) h.write(fsn2bytes(response, None)) Remote: Type[RemoteBase] if os.name == "nt": Remote = QuodLibetWinRemote else: Remote = QuodLibetUnixRemote ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735242.0109358 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015655� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/__init__.py�������������������������������������������������������0000664�0001750�0001750�00000002051�14035600052�017762� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet import print_d from quodlibet.util import is_linux from ._base import SessionClient, SessionError def iter_backends(): if is_linux(): from .gnome import GnomeSessionClient yield GnomeSessionClient from .xfce import XfceSessionClient yield XfceSessionClient from .xsmp import XSMPSessionClient yield XSMPSessionClient # dummy one last yield SessionClient def init(app): """Returns an active SessionClient instance or None""" for backend in iter_backends(): print_d("Trying %s" % backend.__name__) client = backend() try: client.open(app) except SessionError as e: print_d(str(e)) else: return client assert False ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/_base.py����������������������������������������������������������0000664�0001750�0001750�00000001005�14035600052�017272� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. class SessionError(Exception): pass class SessionClient: def open(self, app): """Raises SessionError""" pass def close(self): """Doesn't raise, can be called multiple times""" pass ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/_xsmp.py����������������������������������������������������������0000664�0001750�0001750�00000021645�14035600052�017363� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import enum import ctypes from gi.repository import GLib, GObject try: h = ctypes.cdll.LoadLibrary("libSM.so.6") except OSError as e: raise ImportError(e) @ctypes.POINTER class SmcConn(ctypes.Structure): pass SmPointer = ctypes.c_void_p Bool = ctypes.c_int SmcSaveYourselfProc = ctypes.CFUNCTYPE( None, SmcConn, SmPointer, ctypes.c_int, Bool, ctypes.c_int, Bool) SmcDieProc = ctypes.CFUNCTYPE(None, SmcConn, SmPointer) SmcSaveCompleteProc = ctypes.CFUNCTYPE(None, SmcConn, SmPointer) SmcShutdownCancelledProc = ctypes.CFUNCTYPE(None, SmcConn, SmPointer) class save_yourself(ctypes.Structure): _fields_ = [ ("callback", SmcSaveYourselfProc), ("client_data", SmPointer), ] class die(ctypes.Structure): _fields_ = [ ("callback", SmcDieProc), ("client_data", SmPointer), ] class save_complete(ctypes.Structure): _fields_ = [ ("callback", SmcSaveCompleteProc), ("client_data", SmPointer), ] class shutdown_cancelled(ctypes.Structure): _fields_ = [ ("callback", SmcShutdownCancelledProc), ("client_data", SmPointer), ] class SmcCallbacks(ctypes.Structure): _fields_ = [ ("save_yourself", save_yourself), ("die", die), ("save_complete", save_complete), ("shutdown_cancelled", shutdown_cancelled), ] SmProtoMajor = 1 SmProtoMinor = 0 SmcSaveYourselfProcMask = 1 << 0 SmcDieProcMask = 1 << 1 SmcSaveCompleteProcMask = 1 << 2 SmcShutdownCancelledProcMask = 1 << 3 SmcCloseStatus = ctypes.c_int SmcClosedNow = 0 SmcClosedASAP = 1 SmcConnectionInUse = 2 SmcOpenConnection = h.SmcOpenConnection SmcOpenConnection.argtypes = [ ctypes.c_char_p, SmPointer, ctypes.c_int, ctypes.c_int, ctypes.c_ulong, ctypes.POINTER(SmcCallbacks), ctypes.c_char_p, ctypes.POINTER(ctypes.c_char_p), ctypes.c_int, ctypes.c_char_p] SmcOpenConnection.restype = SmcConn SmcCloseConnection = h.SmcCloseConnection SmcCloseConnection.argtypes = [ SmcConn, ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] SmcCloseConnection.restype = SmcCloseStatus SmcSaveYourselfDone = h.SmcSaveYourselfDone SmcSaveYourselfDone.argtypes = [SmcConn, Bool] SmcSaveYourselfDone.restype = None @ctypes.POINTER class IceConn(ctypes.Structure): pass IcePointer = ctypes.c_void_p IceWatchProc = ctypes.CFUNCTYPE( None, IceConn, IcePointer, Bool, ctypes.POINTER(IcePointer)) Status = ctypes.c_int IceAddConnectionWatch = h.IceAddConnectionWatch IceAddConnectionWatch.argtypes = [IceWatchProc, IcePointer] IceAddConnectionWatch.restype = Status IceRemoveConnectionWatch = h.IceRemoveConnectionWatch IceRemoveConnectionWatch.argtypes = [IceWatchProc, IcePointer] IceRemoveConnectionWatch.restype = None IceConnectionNumber = h.IceConnectionNumber IceConnectionNumber.argtypes = [IceConn] IceConnectionNumber.restype = ctypes.c_int IceProcessMessagesStatus = ctypes.c_int IceProcessMessagesSuccess = 0 IceProcessMessagesIOError = 1 IceProcessMessagesConnectionClosed = 2 @ctypes.POINTER class FIXMEPtr(ctypes.Structure): pass IceProcessMessages = h.IceProcessMessages IceProcessMessages.argtypes = [IceConn, FIXMEPtr, FIXMEPtr] IceProcessMessages.restype = IceProcessMessagesStatus IceSetShutdownNegotiation = h.IceSetShutdownNegotiation IceSetShutdownNegotiation.argtypes = [IceConn, Bool] IceSetShutdownNegotiation.restype = None IceCloseStatus = ctypes.c_int IceCloseConnection = h.IceCloseConnection IceCloseConnection.argtypes = [IceConn] IceCloseConnection.restype = IceCloseStatus class SaveType(enum.IntEnum): GLOBAL = 0 LOCAL = 1 BOTH = 2 class InteractStyle(enum.IntEnum): NONE = 0 ERRORS = 1 ANY = 2 class XSMPError(Exception): pass class XSMPSource: """Dispatches SM messages in the glib mainloop""" def __init__(self): self._watch_id = None self._watch_proc = None def open(self): if self._watch_proc is not None: raise XSMPError("already open") @IceWatchProc def watch_proc(conn, client_data, opening, watch_data): if opening: fd = IceConnectionNumber(conn) channel = GLib.IOChannel.unix_new(fd) self._watch_id = GLib.io_add_watch( channel, GLib.PRIORITY_DEFAULT, (GLib.IOCondition.ERR | GLib.IOCondition.HUP | GLib.IOCondition.IN), self._process_func, conn) else: if self._watch_id is not None: GObject.source_remove(self._watch_id) self._watch_id = None self._watch_proc = watch_proc status = IceAddConnectionWatch(watch_proc, None) if status == 0: raise XSMPError( "IceAddConnectionWatch failed with %d" % status) def close(self): if self._watch_proc is not None: IceRemoveConnectionWatch(self._watch_proc, None) self._watch_proc = None if self._watch_id is not None: GObject.source_remove(self._watch_id) self._watch_id = None def _process_func(self, channel, condition, conn): status = IceProcessMessages(conn, None, None) if status != IceProcessMessagesSuccess: if status != IceProcessMessagesConnectionClosed: IceCloseConnection(conn) self._watch_id = None return False return True class XSMPClient(GObject.Object): __gsignals__ = { "save-yourself": (GObject.SignalFlags.RUN_LAST, None, (object, object, object, object)), "die": (GObject.SignalFlags.RUN_LAST, None, tuple()), "save-complete": (GObject.SignalFlags.RUN_LAST, None, tuple()), "shutdown-cancelled": (GObject.SignalFlags.RUN_LAST, None, tuple()), } def __init__(self): super().__init__() self._source = None self._callbacks = SmcCallbacks() self._conn = None self._id = None def wrap_cb(func_type, cb): def c_callback(*args): return cb(self, func_type, *args[2:]) return func_type(c_callback) self._callbacks.save_yourself.callback = wrap_cb( SmcSaveYourselfProc, self._on_save_yourself) self._callbacks.die.callback = wrap_cb(SmcDieProc, self._on_die) self._callbacks.save_complete.callback = wrap_cb( SmcSaveCompleteProc, self._on_save_complete) self._callbacks.shutdown_cancelled.callback = wrap_cb( SmcShutdownCancelledProc, self._on_shutdown_cancelled) def _on_save_yourself(self, conn, client_data, save_type, shutdown, interact_style, fast): self.emit( "save-yourself", SaveType(save_type), bool(shutdown), InteractStyle(interact_style), bool(fast)) def _on_die(self, conn, client_data): self.emit("die") def _on_save_complete(self, conn, client_data): self.emit("save-complete") def _on_shutdown_cancelled(self, conn, client_data): self.emit("shutdown-cancelled") @property def client_id(self): if self._conn is None: raise XSMPError("connection closed") return self._id def open(self): if self._conn is not None: raise XSMPError("connection already open") self._source = XSMPSource() self._source.open() error_string = ctypes.create_string_buffer(250) id_ = ctypes.c_char_p() self._conn = SmcOpenConnection( None, None, SmProtoMajor, SmProtoMinor, (SmcDieProcMask | SmcSaveCompleteProcMask | SmcSaveYourselfProcMask | SmcShutdownCancelledProcMask), ctypes.byref(self._callbacks), None, ctypes.byref(id_), len(error_string), error_string) # null ptr still returns an object, but its falsy if not self._conn: self._conn = None if self._conn is None: self._conn = None self._source.close() self._source = None raise XSMPError("open failed: %r" % error_string.value.decode("utf-8")) # FIXME: id_ should be freed with free() self._id = id_.value.decode("utf-8") def save_yourself_done(self, success): if self._conn is None: raise XSMPError("connection closed") SmcSaveYourselfDone(self._conn, success) def close(self): if self._conn is not None: SmcCloseConnection(self._conn, 0, None) self._conn = None if self._source is not None: self._source.close() self._source = None def __del__(self): self.close() self._callbacks = None �������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/gnome.py����������������������������������������������������������0000664�0001750�0001750�00000006416�14035600052�017341� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gio, GLib from quodlibet import print_d, print_w from ._base import SessionClient, SessionError class GnomeSessionClient(SessionClient): DBUS_NAME = 'org.gnome.SessionManager' DBUS_OBJECT_PATH = '/org/gnome/SessionManager' DBUS_MAIN_INTERFACE = 'org.gnome.SessionManager' DBUS_CLIENT_INTERFACE = 'org.gnome.SessionManager.ClientPrivate' def __init__(self): super().__init__() self._client_priv = None self._client_path = None self._sig_id = None def open(self, app): print_d("Connecting with gnome session manager") try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) session_mgr = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_OBJECT_PATH, self.DBUS_MAIN_INTERFACE, None) if session_mgr.get_name_owner() is None: raise SessionError("%s unowned" % self.DBUS_NAME) client_path = session_mgr.RegisterClient('(ss)', app.id, "") if client_path is None: # https://github.com/quodlibet/quodlibet/issues/2435 raise SessionError( "Broken session manager implementation, likely LXDE") client_priv = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, client_path, self.DBUS_CLIENT_INTERFACE, None) def g_signal_cb(proxy, sender, signal, args): if signal == 'EndSession': print_d("GSM sent EndSession: going down") proxy.EndSessionResponse('(bs)', True, "") app.quit() elif signal == 'Stop': print_d("GSM sent Stop: going down") app.quit() elif signal == 'QueryEndSession': print_d("GSM sent QueryEndSession") proxy.EndSessionResponse('(bs)', True, "") self._sig_id = client_priv.connect('g-signal', g_signal_cb) self._client_priv = client_priv self._client_path = client_path print_d("Connected with gnome session manager: %s" % client_path) except GLib.Error as e: raise SessionError(e) def close(self): if self._client_priv is None: return self._client_priv.disconnect(self._sig_id) self._sig_id = None try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) session_mgr = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, self.DBUS_NAME, self.DBUS_OBJECT_PATH, self.DBUS_MAIN_INTERFACE, None) session_mgr.UnregisterClient('(o)', self._client_path) except GLib.Error as e: print_w(str(e)) print_d("Disconnected from gnome session manager: %s" % self._client_path) self._client_path = None ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/xfce.py�����������������������������������������������������������0000664�0001750�0001750�00000001072�14035600052�017152� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .gnome import GnomeSessionClient class XfceSessionClient(GnomeSessionClient): DBUS_NAME = 'org.xfce.SessionManager' DBUS_OBJECT_PATH = '/org/xfce/SessionManager' DBUS_MAIN_INTERFACE = 'org.xfce.Session.Manager' DBUS_CLIENT_INTERFACE = 'org.xfce.Session.Client' ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/session/xsmp.py�����������������������������������������������������������0000664�0001750�0001750�00000003522�14035600052�017216� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet import print_d from ._base import SessionClient, SessionError class XSMPSessionClient(SessionClient): def __init__(self): super().__init__() self._client = None def open(self, app): try: from ._xsmp import XSMPClient, XSMPError except ImportError as e: raise SessionError(e) print_d("Connecting with XSMP") client = XSMPClient() try: client.open() except XSMPError as e: raise SessionError(e) try: from gi.repository import GdkX11 except ImportError: pass else: GdkX11.x11_set_sm_client_id(client.client_id) print_d("Connected. Client ID: %s" % client.client_id) def save_yourself(client, *args): print_d("xsmp: save_yourself %r" % (args,)) client.save_yourself_done(True) def die(client, *args): print_d("xsmp: die") app.quit() def save_complete(client): print_d("xsmp: save_complete") def shutdown_cancelled(client): print_d("xsmp: shutdown_cancelled") client.connect("save-yourself", save_yourself) client.connect("die", die) client.connect("save-complete", save_complete) client.connect("shutdown-cancelled", shutdown_cancelled) self._client = client def close(self): if self._client is None: return print_d("Disconnecting from XSMP") self._client.close() self._client = None ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735242.0109358 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/unisearch/����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016153� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/unisearch/__init__.py�����������������������������������������������������0000644�0001750�0001750�00000001420�14310167056�020265� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """ Functions for adjusting regular expressions so that ASCII characters in them match similar looking unicode characters. re_add_variants(u"Mum") => u"[MḾṀṂ][uùúûüũūŭůűųưǔǖǘǚǜȕȗṳṵṷṹṻụủứừửữự][mḿṁṃ]" This is similar to Asymmetric Search: http://unicode.org/reports/tr10/#Asymmetric_Search The goal is to make searching easy using an English keyboard without any knowledge of other languages. """ from .parser import compile compile ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/unisearch/db.py�����������������������������������������������������������0000664�0001750�0001750�00000033722�14035600052�017117� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from typing import Dict, Set, List import unicodedata import sys from urllib.request import urlopen from quodlibet.util import cached_func _DIACRITIC_CACHE = { u'\u0300': (u'AEINOUWYaeinouwy\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9' u'\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0415\u0418' u'\u0435\u0438'), u'\u0300\u0345': u'\u03b1\u03b7\u03c9', u'\u0301': (u'ACEGIKLMNOPRSUWYZacegiklmnoprsuwyz\xc6\xd8\xe6\xf8\u0391' u'\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7' u'\u03b9\u03bf\u03c5\u03c9\u0413\u041a\u0433\u043a'), u'\u0301\u0307': u'Ss', u'\u0301\u0345': u'\u03b1\u03b7\u03c9', u'\u0302': u'ACEGHIJOSUWYZaceghijosuwyz', u'\u0302\u0300': u'AEOaeo', u'\u0302\u0301': u'AEOaeo', u'\u0302\u0303': u'AEOaeo', u'\u0302\u0309': u'AEOaeo', u'\u0303': u'AEINOUVYaeinouvy', u'\u0303\u0301': u'OUou', u'\u0303\u0304': u'Oo', u'\u0303\u0308': u'Oo', u'\u0304': (u'AEGIOUYaegiouy\xc6\xe6\u0391\u0399\u03a5\u03b1\u03b9' u'\u03c5\u0418\u0423\u0438\u0443'), u'\u0304\u0300': u'EOeo', u'\u0304\u0301': u'EOeo', u'\u0304\u0308': u'Uu', u'\u0306': (u'AEGIOUaegiou\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410' u'\u0415\u0416\u0418\u0423\u0430\u0435\u0436\u0438\u0443'), u'\u0306\u0300': u'Aa', u'\u0306\u0301': u'Aa', u'\u0306\u0303': u'Aa', u'\u0306\u0309': u'Aa', u'\u0307': u'ABCDEFGHIMNOPRSTWXYZabcdefghmnoprstwxyz', u'\u0307\u0304': u'AOao', u'\u0308': (u'AEHIOUWXYaehiotuwxy\u0399\u03a5\u03b9\u03c5\u0406\u0410' u'\u0415\u0416\u0417\u0418\u041e\u0423\u0427\u042b\u042d' u'\u0430\u0435\u0436\u0437\u0438\u043e\u0443\u0447\u044b' u'\u044d\u0456\u04d8\u04d9\u04e8\u04e9'), u'\u0308\u0300': u'Uu\u03b9\u03c5', u'\u0308\u0301': u'IUiu\u03b9\u03c5', u'\u0308\u0304': u'AOUaou', u'\u0308\u030c': u'Uu', u'\u0308\u0342': u'\u03b9\u03c5', u'\u0309': u'AEIOUYaeiouy', u'\u030a': u'AUauwy', u'\u030a\u0301': u'Aa', u'\u030b': u'OUou\u0423\u0443', u'\u030c': u'ACDEGHIKLNORSTUZacdeghijklnorstuz\u01b7\u0292', u'\u030c\u0307': u'Ss', u'\u030f': u'AEIORUaeioru\u0474\u0475', u'\u0311': u'AEIORUaeioru', u'\u0313': (u'\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7' u'\u03b9\u03bf\u03c1\u03c5\u03c9'), u'\u0313\u0300': (u'\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5' u'\u03b7\u03b9\u03bf\u03c5\u03c9'), u'\u0313\u0300\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0313\u0301': (u'\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5' u'\u03b7\u03b9\u03bf\u03c5\u03c9'), u'\u0313\u0301\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0313\u0342': u'\u0391\u0397\u0399\u03a9\u03b1\u03b7\u03b9\u03c5\u03c9', u'\u0313\u0342\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0313\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0314': (u'\u0391\u0395\u0397\u0399\u039f\u03a1\u03a5\u03a9\u03b1' u'\u03b5\u03b7\u03b9\u03bf\u03c1\u03c5\u03c9'), u'\u0314\u0300': (u'\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1' u'\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9'), u'\u0314\u0300\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0314\u0301': (u'\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1' u'\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9'), u'\u0314\u0301\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0314\u0342': (u'\u0391\u0397\u0399\u03a5\u03a9\u03b1\u03b7\u03b9' u'\u03c5\u03c9'), u'\u0314\u0342\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u0314\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9', u'\u031b': u'OUou', u'\u031b\u0300': u'OUou', u'\u031b\u0301': u'OUou', u'\u031b\u0303': u'OUou', u'\u031b\u0309': u'OUou', u'\u031b\u0323': u'OUou', u'\u0323': u'ABDEHIKLMNORSTUVWYZabdehiklmnorstuvwyz', u'\u0323\u0302': u'AEOaeo', u'\u0323\u0304': u'LRlr', u'\u0323\u0306': u'Aa', u'\u0323\u0307': u'Ss', u'\u0324': u'Uu', u'\u0325': u'Aa', u'\u0326': u'STst', u'\u0327': u'CDEGHKLNRSTcdeghklnrst', u'\u0327\u0301': u'Cc', u'\u0327\u0306': u'Ee', u'\u0328': u'AEIOUaeiou', u'\u0328\u0304': u'Oo', u'\u032d': u'DELNTUdelntu', u'\u032e': u'Hh', u'\u0330': u'EIUeiu', u'\u0331': u'BDKLNRTZbdhklnrtz', u'\u0342': u'\u03b1\u03b7\u03b9\u03c5\u03c9', u'\u0342\u0345': u'\u03b1\u03b7\u03c9', u'\u0345': u'\u0391\u0397\u03a9\u03b1\u03b7\u03c9' } # See misc/uca_decomps.py _UCA_DECOMPS_CACHE = { u'AA': u'\ua732', u'AE': u'\xc6\u01e2\u01fc', u'AO': u'\ua734', u'AU': u'\ua736', u'AV': u'\ua738\ua73a', u'AY': u'\ua73c', u'D': u'\xd0\u0110\ua779', u'DZ': u'\u01c4\u01f1', u'Dz': u'\u01c5\u01f2', u'F': u'\ua77b', u'G': u'\ua77d', u'H': u'\u0126', u'IJ': u'\u0132', u'L': u'\u0141', u'LJ': u'\u01c7', u'LL': u'\u1efa', u'Lj': u'\u01c8', u'NJ': u'\u01ca', u'Nj': u'\u01cb', u'O': u'\xd8\u01fe', u'OE': u'\u0152', u'OO': u'\ua74e', u'R': u'\ua782', u'S': u'\ua784', u'SS': u'\u1e9e', u'T': u'\ua786', u'Tz': u'\ua728', u'VY': u'\ua760', u'aa': u'\ua733', u'ae': u'\xe6\u01e3\u01fd', u'ao': u'\ua735', u'au': u'\ua737', u'av': u'\ua739\ua73b', u'ay': u'\ua73d', u'd': u'\xf0\u0111\ua77a', u'db': u'\u0238', u'dz': u'\u01c6\u01f3\u02a3', u'd\u0291': u'\u02a5', u'd\u0292': u'\u02a4', u'f': u'\ua77c', u'ff': u'\ufb00', u'ffi': u'\ufb03', u'ffl': u'\ufb04', u'fi': u'\ufb01', u'fl': u'\ufb02', u'f\u014b': u'\u02a9', u'g': u'\u1d79', u'h': u'\u0127\u210f', u'ij': u'\u0133', u'l': u'\u0142', u'lj': u'\u01c9', u'll': u'\u1efb', u'ls': u'\u02aa', u'lz': u'\u02ab', u'n': u'\u0149', u'nj': u'\u01cc', u'o': u'\xf8\u01ff', u'oe': u'\u0153', u'oo': u'\ua74f', u'qp': u'\u0239', u'r': u'\ua783', u's': u'\ua785', u'ss': u'\xdf', u'st': u'\ufb05\ufb06', u't': u'\ua787', u'th': u'\u1d7a', u'ts': u'\u01be\u02a6', u'tz': u'\ua729', u't\u0255': u'\u02a8', u't\u0283': u'\u02a7', u'vy': u'\ua761', u'zw': u'\u018d', u'\u039a\u03b1\u03b9': u'\u03cf', u'\u03ba\u03b1\u03b9': u'\u03d7', u'\u03c3': u'\u03c2\u03f2\U0001d6d3\U0001d70d' u'\U0001d747\U0001d781\U0001d7bb', u'\u0413': u'\u0490', u'\u041e': u'\ua668\ua66a\ua66c', u'\u0433': u'\u0491', u'\u043e': u'\ua669\ua66b\ua66d', u'\u0565\u0582': u'\u0587', u'\u0574\u0565': u'\ufb14', u'\u0574\u056b': u'\ufb15', u'\u0574\u056d': u'\ufb17', u'\u0574\u0576': u'\ufb13', u'\u057e\u0576': u'\ufb16', u'\u2c95\u2c81\u2c93': u'\u2ce4', } _PUNCT_CONFUSABLES_CACHE = { u'!': u'\uff01\u01c3\u2d51', u'!!': u'\u203c', u'!?': u'\u2049', u'"': (u'\u1cd3\uff02\u201c\u201d\u201f\u2033\u2036\u3003\u05f4\u02dd' u'\u02ba\u02f6\u02ee\u05f2'), u'&': u'\ua778', u"'": (u'\u055d\uff07\u2018\u2019\u201b\u2032\u2035\u055a\u05f3`\u1fef' u'\uff40\xb4\u0384\u1ffd\u1fbd\u1fbf\u1ffe\u02b9\u0374\u02c8\u02ca' u'\u02cb\u02f4\u02bb\u02bd\u02bc\u02be\ua78c\u05d9\u07f4\u07f5' u'\u144a\u16cc'), u"''": (u'\u1cd3"\uff02\u201c\u201d\u201f\u2033\u2036\u3003\u05f4\u02dd' u'\u02ba\u02f6\u02ee\u05f2'), u"'''": u'\u2034\u2037', u"''''": u'\u2057', u'(': u'\uff3b\u2768\u2772\u3014\ufd3e', u'((': u'\u2e28', u')': u'\uff3d\u2769\u2773\u3015\ufd3f', u'))': u'\u2e29', u'*': u'\u204e\u066d\u2217\U0001031f', u',': u'\u060d\u066b\u201a\xb8\ua4f9', u'-': (u'\u2010\u2011\u2012\u2013\ufe58\u06d4\u2043\u02d7\u2212\u2796' u'\u2cba'), u'-.': u'\ua4fe', u'.': u'\U0001d16d\u2024\u0701\u0702\ua60e\U00010a50\u0660\u06f0\ua4f8', u'.,': u'\ua4fb', u'..': u'\u2025\ua4fa', u'...': u'\u2026', u'/': (u'\u1735\u2041\u2215\u2044\u2571\u27cb\u29f8\U0001d23a\u31d3\u3033' u'\u2cc6\u30ce\u4e3f\u2f03'), u'//': u'\u2afd', u'///': u'\u2afb', u':': (u'\u0903\u0a83\uff1a\u0589\u0703\u0704\u16ec\ufe30\u1803\u1809' u'\u205a\u05c3\u02f8\ua789\u2236\u02d0\ua4fd'), u';': u'\u037e', u'?': u'\u0294\u0241\u097d\u13ae\ua6eb', u'?!': u'\u2048', u'??': u'\u2047', u'\\': (u'\uff3c\ufe68\u2216\u27cd\u29f5\u29f9\U0001d20f\U0001d23b\u31d4' u'\u4e36\u2f02'), u'\\\\': u'\u2cf9\u244a', u'_': u'\u07fa\ufe4d\ufe4e\ufe4f', u'{': u'\u2774\U0001d114', u'}': u'\u2775', } def get_decomps_mapping(regenerate=False) -> Dict[str, str]: """This takes the decomps.txt file of the Unicode UCA and gives us a cases where a letter can be decomposed for collation and that mapping isn't in NFKD. """ if not regenerate: return _UCA_DECOMPS_CACHE mapping: Dict[str, str] = {} h = urlopen("http://unicode.org/Public/UCA/8.0.0/decomps.txt") for line in h.read().splitlines(): if line.startswith("#"): continue to_uni = lambda x: chr(int(x, 16)) is_letter = lambda x: unicodedata.category(x) in ("Lu", "Ll", "Lt") cp, line = line.split(";", 1) tag, line = line.split(";", 1) decomp, line = line.split("#", 1) decomp = map(to_uni, decomp.strip().split()) cp = to_uni(cp) if not is_letter(cp): continue decomp = filter(is_letter, decomp) simple = "".join(decomp) if not simple: continue # skip anything we get from normalization if unicodedata.normalize("NFKD", cp)[0] == simple: continue mapping[simple] = mapping.get(simple, "") + cp return mapping def get_punctuation_mapping(regenerate=False) -> Dict[str, str]: """This takes the unicode confusables set and extracts punctuation which looks similar to one or more ASCII punctuation. e.g. ' --> ' """ if not regenerate: return _PUNCT_CONFUSABLES_CACHE h = urlopen("http://www.unicode.org/Public/security/9.0.0/confusables.txt") data = h.read() mapping: Dict[str, str] = {} for line in data.decode("utf-8-sig").splitlines(): line = line.strip() if not line: continue if line.startswith(u"#"): continue char, repls = line.split(";", 2)[:2] char = char.strip() repls = repls.split() to_uni = lambda x: chr(int(x, 16)) char = to_uni(char) repls = [to_uni(r) for r in repls] def is_ascii(char): try: char.encode("ascii") except UnicodeEncodeError: return False return True def is_punct(char): return unicodedata.category(char).startswith("P") if all(is_ascii(c) and is_punct(c) for c in repls) and char: repls_joined = u"".join(repls) mapping[repls_joined] = mapping.get(repls_joined, u"") + char # if any of the equal chars is also ascii + punct we can replace # it as well for ascii_, uni in mapping.items(): also_ascii = [c for c in uni if is_ascii(c) and is_punct(c)] for c in also_ascii: mapping[c] = uni.replace(c, u"") return mapping def diacritic_for_letters(regenerate=False) -> Dict[str, str]: """Returns a mapping for combining diacritic mark to ascii characters for which they can be used to combine to a single unicode char. (actually not ascii, but unicode from the Lu/Ll/Lt categories, but mainly ascii) Since this is quite expensive to compute, the result is a cached version unless regenerate != True. regenerate = True is used for unittests to validate the cache. """ if not regenerate: return _DIACRITIC_CACHE d: Dict[str, Set[str]] = {} for i in range(sys.maxunicode): u = chr(i) n = unicodedata.normalize("NFKD", u) if len(n) <= 1: continue if unicodedata.category(u) not in ("Lu", "Ll", "Lt"): continue if not all(map(unicodedata.combining, n[1:])): continue d.setdefault(n[1:], set()).add(n[0]) d2: Dict[str, str] = {} for k, v in d.items(): d2[k] = u"".join(sorted(v)) return d2 def generate_re_mapping(_diacritic_for_letters: Dict[str, str]) -> Dict[str, str]: letter_to_variants: Dict[str, List[str]] = {} # combine combining characters with the ascii chars for dia, letters in _diacritic_for_letters.items(): for c in letters: unichar = unicodedata.normalize("NFKC", c + dia) letter_to_variants.setdefault(c, []).append(unichar) letter_to_variants_joined: Dict[str, str] = {} # create strings to replace ascii with for k, v in letter_to_variants.items(): letter_to_variants_joined[k] = u"".join(sorted(v)) return letter_to_variants_joined @cached_func def get_replacement_mapping() -> Dict[str, List[str]]: """Returns a dict mapping a sequence of characters to another sequence of characters. If a key occurs in a text, it should also match any of the characters in in the value. """ mapping: Dict[str, List[str]] = {} # use _DIACRITIC_CACHE and create a lookup table for cp, repl in generate_re_mapping( diacritic_for_letters(regenerate=False)).items(): mapping.setdefault(cp, []).extend(repl) # add more from the UCA decomp dataset for cp, repl in get_decomps_mapping(regenerate=False).items(): mapping.setdefault(cp, []).extend(repl) # and some punctuation for cp, repl in get_punctuation_mapping(regenerate=False).items(): mapping.setdefault(cp, []).extend(repl) return mapping ����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/unisearch/parser.py�������������������������������������������������������0000664�0001750�0001750�00000022672�14037102221�020025� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from typing import List, Dict, Callable import re import sre_parse import sre_constants import unicodedata from quodlibet import print_d from quodlibet.util import re_escape from .db import get_replacement_mapping def _fixup_literal(literal, in_seq, mapping): u = chr(literal) if u in mapping: u = u + u"".join(mapping[u]) need_seq = len(u) > 1 u = re_escape(u) if need_seq and not in_seq: u = u"[%s]" % u return u def _fixup_literal_list(literals, mapping): u = u"".join(map(chr, literals)) # longest matches first, we will handle contained ones in the replacement # function reg = u"(%s)" % u"|".join( map(re_escape, sorted(mapping.keys(), key=len, reverse=True))) def replace_func(match): text = match.group(1) all_ = u"" for c in text: all_ += _fixup_literal(ord(c), False, mapping) if len(text) > 1: multi = u"".join(mapping[text]) if len(multi) > 1: multi = "[%s]" % re_escape(multi) else: multi = re_escape(multi) return "(?:%s|%s)" % (all_, multi) return all_ new = u"" pos = 0 for match in re.finditer(reg, u): new += re_escape(u[pos:match.start()]) new += replace_func(match) pos = match.end() new += re_escape(u[pos:]) return new def _fixup_not_literal(literal, mapping): u = chr(literal) return u"[^%s]" % u"".join(re_escape(u + u"".join(mapping.get(u, [])))) def _fixup_range(start, end, mapping): extra = [] for i in range(start, end + 1): u = chr(i) if u in mapping: extra.append(re_escape(u"".join(mapping[u]))) start = re_escape(chr(start)) end = re_escape(chr(end)) return u"%s%s-%s" % ("".join(extra), start, end) def _merge_literals(pattern): done = [] current = [] for op, av in pattern: op = str(op).lower() if op == "literal": current.append(av) else: if current: done.append(("literals", tuple(current))) current = [] done.append((op, av)) if current: done.append(("literals", tuple(current))) return done def _construct_in(pattern, mapping): negate = False parts = [] for op, av in _merge_literals(pattern): op = str(op).lower() if op == "range": start, end = av parts.append(_fixup_range(start, end, mapping)) elif op == "literals": expanded = [] for c in av: v = _fixup_literal(c, True, mapping) if v not in expanded: expanded.append(v) parts.extend(expanded) elif op == "negate": negate = True elif op == "category": av = str(av).lower() cats = { "category_word": u"\\w", "category_not_word": u"\\W", "category_digit": u"\\d", "category_not_digit": u"\\D", "category_space": u"\\s", "category_not_space": u"\\S", } try: parts.append(cats[av]) except KeyError: raise NotImplementedError(av) else: raise NotImplementedError(op) return "[%s%s]" % ("^" if negate else "", u"".join(parts)) def _construct_regexp( pattern: sre_parse.SubPattern, mapping: Dict[str, List[str]], parent="") -> str: """Raises NotImplementedError""" parts = [] for op, av in _merge_literals(pattern): op = str(op).lower() assert op != "literal" if op == "not_literal": parts.append(_fixup_not_literal(av, mapping)) elif op == "literals": parts.append(_fixup_literal_list(av, mapping)) elif op == "category": av = str(av).lower() cats = { "category_word": u"\\w", "category_not_word": u"\\W", "category_digit": u"\\d", "category_not_digit": u"\\D", "category_space": u"\\s", "category_not_space": u"\\S", } try: parts.append(cats[av]) except KeyError: raise NotImplementedError(av) elif op == "any": parts.append(u".") elif op == "in": parts.append(_construct_in(av, mapping)) elif op == "max_repeat" or op == "min_repeat": min_, max_, pad = av pad = _construct_regexp(pad, mapping) if min_ == 1 and max_ == sre_constants.MAXREPEAT: parts.append(u"%s+" % pad) elif min_ == 0 and max_ == sre_constants.MAXREPEAT: parts.append(u"%s*" % pad) elif min_ == 0 and max_ == 1: parts.append(u"%s?" % pad) else: parts.append(u"%s{%d,%d}" % (pad, min_, max_)) if op == "min_repeat": parts[-1] = parts[-1] + u"?" elif op == "at": av = str(av).lower() ats = { "at_beginning": u"^", "at_end": u"$", "at_beginning_string": u"\\A", "at_boundary": u"\\b", "at_non_boundary": u"\\B", "at_end_string": u"\\Z", } try: parts.append(ats[av]) except KeyError: raise NotImplementedError(av) elif op == "subpattern": # Python 3.6 extended this # https://bugs.python.org/issue433028 if len(av) == 4: if av[1:3] == (0, 0): av = [av[0], av[-1]] else: raise NotImplementedError(op, av) group, pad = av pad = _construct_regexp(pad, mapping, parent=op) if group is None: parts.append(u"(?:%s)" % pad) else: parts.append(u"(%s)" % pad) elif op == "assert": direction, pad = av pad = _construct_regexp(pad, mapping) if direction == 1: parts.append(u"(?=%s)" % pad) elif direction == -1: parts.append(u"(?<=%s)" % pad) else: raise NotImplementedError(direction) elif op == "assert_not": direction, pad = av pad = _construct_regexp(pad, mapping) if direction == 1: parts.append(u"(?!%s)" % pad) elif direction == -1: parts.append(u"(?<!%s)" % pad) else: raise NotImplementedError(direction) elif op == "branch": dummy, branches = av branches = map(lambda b: _construct_regexp(b, mapping), branches) pad = u"|".join(branches) if parent != "subpattern": parts.append("(?:%s)" % pad) else: parts.append(pad) else: raise NotImplementedError(op) return u"".join(parts) def re_replace_literals(text: str, mapping: Dict[str, List[str]]) -> str: """Raises NotImplementedError or re.error""" assert isinstance(text, str) pattern = sre_parse.parse(text) return _construct_regexp(pattern, mapping) def re_add_variants(text: str) -> str: """Will replace all occurrences of ascii chars by a bracket expression containing the character and all its variants with a diacritic mark. "föhn" -> "[fḟ]ö[hĥȟḣḥḧḩḫẖ][nñńņňǹṅṇṉṋ]" In case the passed in regex is invalid raises re.error. Supports all regexp except ones with group references. In case something is not supported NotImplementedError gets raised. """ assert isinstance(text, str) text = unicodedata.normalize("NFC", text) return re_replace_literals(text, get_replacement_mapping()) def compile(pattern: str, ignore_case: bool = True, dot_all: bool = False, asym: bool = False) -> Callable[[str], bool]: """ Args: pattern (str): a unicode regex ignore_case (bool): if case shouuld be ignored when matching dot_all (bool): if "." should match newlines asym (bool): if ascii should match similar looking unicode chars Returns: A callable which will return True if the pattern is contained in the passed text. Raises: ValueError: In case the regex is invalid """ assert isinstance(pattern, str) pattern = unicodedata.normalize("NFC", pattern) if asym: try: pattern = re_add_variants(pattern) except NotImplementedError: # too complex, just skip this step print_d("regex not supported: %s" % pattern) except re.error as e: raise ValueError(e) mods = re.MULTILINE | re.UNICODE if ignore_case: mods |= re.IGNORECASE if dot_all: mods |= re.DOTALL try: reg = re.compile(pattern, mods) except re.error as e: raise ValueError(e) normalize = unicodedata.normalize def search(text: str): return bool(reg.search(normalize("NFC", text))) return search ����������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/update.py�����������������������������������������������������������������0000644�0001750�0001750�00000011527�14327505043�016040� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Check for new versions of the application For each "build type" (basically each bundle/installer) we host an (sparkle appcast) rss feed on quodlibet.github.io. We download it and compare versions... Since there can be multiple builds per release for the same release type (e.g. the installer was broken and had to be redone) the build version is used and not the release version. """ from urllib.request import urlopen from gi.repository import Gtk import feedparser import quodlibet from quodlibet import _, util from quodlibet.build import BUILD_TYPE from quodlibet.qltk.window import Dialog from quodlibet.util.dprint import print_exc from quodlibet.util import escape from quodlibet.util.thread import call_async, Cancellable class UpdateError(Exception): pass def parse_version(version_string): """Might raise ValueError""" return tuple(map(int, version_string.split("."))) def format_version(version_tuple): return u".".join(map(str, version_tuple)) def fetch_versions(build_type, timeout=5.0): """Fetches the list of available releases and returns a list of version tuples. Sorted and oldest version first. The list might be empty. Also returns an URL to the download page. Args: build_type (text): the build type. e.g. "default" or "windows" timeout (float): timeout in seconds Thread safe. Raises UpdateError """ try: content = urlopen( u"https://quodlibet.github.io/appcast/%s.rss" % build_type, timeout=timeout).read() except Exception as error: raise UpdateError(error) d = feedparser.parse(content) if d.bozo: raise UpdateError(d.bozo_exception) try: link = d.feed.link enclosures = [e for entry in d.entries for e in entry.enclosures] except AttributeError as error: raise UpdateError(error) try: versions = [parse_version(en.version) for en in enclosures] except ValueError as error: raise UpdateError(error) return sorted(versions), link class UpdateDialog(Dialog): def __init__(self, parent): super().__init__( title=_("Checking for Updates"), use_header_bar=True, modal=True) self.set_default_size(380, 110) self.set_transient_for(parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.set_default_response(Gtk.ResponseType.CANCEL) content = self.get_content_area() self._stack = Gtk.Stack(border_width=10) self._stack.set_transition_duration(500) self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE) content.pack_start(self._stack, True, True, 0) content.show_all() spinner = Gtk.Spinner() spinner.start() self._set_widget(spinner) def run(self): def do_fetch_versions(): try: return fetch_versions(BUILD_TYPE) except UpdateError: print_exc() return None cancel = Cancellable() self.connect("response", self._on_response, cancel) call_async(do_fetch_versions, cancel, self._on_result) return super().run() def _on_result(self, args): if args is None or not args[0]: text = _("Connection failed") else: versions, url = args version = quodlibet.get_build_version() def f(v): return util.bold(format_version(v)) if version >= versions[-1]: text = (_("You are already using the newest version " "%(version)s") % {"version": f(version)}) else: text = (_("A new version %(new-version)s is available\n\n" "You are currently using version %(old-version)s\n\n" "Visit the <a href='%(url)s'>website</a>") % { "new-version": f(versions[-1]), "old-version": f(version), "url": escape(url)}) self._set_widget( Gtk.Label(label=text, use_markup=True, wrap=True, justify=Gtk.Justification.CENTER)) button = self.get_widget_for_response(Gtk.ResponseType.CANCEL) button.set_label(_("_Close")) def _set_widget(self, widget): old = self._stack.get_visible_child() self._stack.add(widget) widget.show() self._stack.set_visible_child(widget) if old: old.destroy() def _on_response(self, dialog, response_id, cancel): cancel.cancel() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.014269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/���������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015147� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1675520038.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/__init__.py����������������������������������������������������������0000644�0001750�0001750�00000103505�14367464046�017303� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import random import re import ctypes import ctypes.util import sys import unicodedata import threading import locale from typing import Dict, List, Callable from functools import reduce # Windows doesn't have fcntl, just don't lock for now try: import fcntl fcntl except ImportError: fcntl = None # type: ignore from senf import fsnative from quodlibet.util.string.titlecase import title from quodlibet.const import SUPPORT_EMAIL, COPYRIGHT from quodlibet.util.dprint import print_d, print_, print_e, print_w, print_exc from .misc import cached_func, get_module_dir, get_ca_file, \ NamedTemporaryFile, cmp from .environment import is_plasma, is_unity, is_enlightenment, \ is_linux, is_windows, is_wine, is_osx, is_flatpak, matches_flatpak_runtime from .enum import enum from .i18n import _, ngettext, C_ # flake8 cached_func, enum, print_w, print_exc, is_plasma, is_unity, is_enlightenment, is_linux, is_windows, is_wine, is_osx, get_module_dir, get_ca_file, NamedTemporaryFile, is_flatpak, cmp, matches_flatpak_runtime class InstanceTracker: """A mixin for GObjects to return a list of all alive objects of a given type. Note that it must be used with a GObject or something with a connect method and destroy signal.""" __kinds: Dict[type, List[object]] = {} def _register_instance(self, klass=None): """Register this object to be returned in the active instance list.""" if klass is None: klass = type(self) self.__kinds.setdefault(klass, []).append(self) self.connect('destroy', self.__kinds[klass].remove) @classmethod def instances(klass): return klass.__kinds.get(klass, []) class OptionParser: def __init__(self, name, version, description=None, usage=None): self.__name = name self.__version = version self.__args = {} self.__translate_short = {} self.__translate_long = {} self.__help = {} self.__usage = usage self.__description = description self.add( "help", shorts="h", help=_("Display brief usage information")) self.add( "version", shorts="v", help=_("Display version and copyright")) self.add("debug", shorts="d", help=_("Print debugging information")) def add(self, canon, help=None, arg="", shorts="", longs=[]): self.__args[canon] = arg for s in shorts: self.__translate_short[s] = canon for l in longs: self.__translate_long[l] = canon if help: self.__help[canon] = help def __shorts(self): shorts = "" for short, canon in self.__translate_short.items(): shorts += short + (self.__args[canon] and "=" or "") return shorts def __longs(self): longs = [] for long_, arg in self.__args.items(): longs.append(long_ + (arg and "=" or "")) for long_, canon in self.__translate_long.items(): longs.append(long_ + (self.__args[canon] and "=" or "")) return longs def __format_help(self, opt, space): if opt in self.__help: help = self.__help[opt] if self.__args[opt]: opt = "%s=%s" % (opt, self.__args[opt]) return " --%s %s\n" % (opt.ljust(space), help) else: return "" def help(self): l = 0 for k in self.__help.keys(): l = max(l, len(k) + len(self.__args.get(k, "")) + 4) s = _("Usage: %(program)s %(usage)s") % { "program": sys.argv[0], "usage": self.__usage if self.__usage else _("[options]"), } s += "\n" if self.__description: s += "%s - %s\n" % (self.__name, self.__description) s += "\n" keys = sorted(self.__help.keys()) try: keys.remove("help") except ValueError: pass try: keys.remove("version") except ValueError: pass for h in keys: s += self.__format_help(h, l) if keys: s += "\n" s += self.__format_help("help", l) s += self.__format_help("version", l) return s def set_help(self, newhelp): self.__help = newhelp def version(self): return ("""\ {title} {version} <{email}> {copyright}\ """).format(title=self.__name, version=self.__version, email=SUPPORT_EMAIL, copyright=COPYRIGHT) def parse(self, args=None): if args is None: args = sys.argv[1:] from getopt import getopt, GetoptError try: opts, args = getopt(args, self.__shorts(), self.__longs()) except GetoptError as s: s = str(s) text = [] if "not recognized" in s: text.append( _("Option %r not recognized.") % s.split()[1]) elif "requires argument" in s: text.append( _("Option %r requires an argument.") % s.split()[1]) elif "unique prefix" in s: text.append( _("%r is not a unique prefix.") % s.split()[1]) if "help" in self.__args: text.append(_("Try %s --help.") % sys.argv[0]) print_e("\n".join(text)) raise SystemExit(True) else: transopts = {} for o, a in opts: if o.startswith("--"): o = self.__translate_long.get(o[2:], o[2:]) elif o.startswith("-"): o = self.__translate_short.get(o[1:], o[1:]) if o == "help": print_(self.help()) raise SystemExit elif o == "version": print_(self.version()) raise SystemExit elif o == "debug": from quodlibet import const const.DEBUG = True if self.__args[o]: transopts[o] = a else: transopts[o] = True return transopts, args def escape(string: str) -> str: """Escape a string in a manner suitable for XML/Pango.""" return string.replace("&", "&").replace("<", "<").replace(">", ">") def unescape(string: str) -> str: """Unescape a string in a manner suitable for XML/Pango.""" return string.replace("<", "<").replace(">", ">").replace("&", "&") def bold(string: str, escaper: Callable[[str], str] = escape) -> str: return "<b>%s</b>" % escaper(string) def monospace(string: str, escaper: Callable[[str], str] = escape) -> str: return "<tt>%s</tt>" % escaper(string) def italic(string: str, escaper: Callable[[str], str] = escape) -> str: return "<i>%s</i>" % escaper(string) def bold_italic(string: str, escaper: Callable[[str], str] = escape) -> str: return "<b><i>%s</i></b>" % escaper(string) def parse_time(timestr, err=object()): """Parse a time string in hh:mm:ss, mm:ss, or ss format.""" if timestr[0:1] == "-": m = -1 timestr = timestr[1:] else: m = 1 try: return m * reduce(lambda s, a: s * 60 + int(a), re.split(r":|\.", timestr), 0) except (ValueError, re.error): if err is None: raise return 0 def validate_query_date(datestr): """Validates a user provided date that can be compared using date_key(). Returns True id the date is valid. """ parts = datestr.split("-") if len(parts) > 3: return False if len(parts) > 2: try: v = int(parts[2]) except ValueError: return False else: if not 1 <= v <= 31: return False if len(parts) > 1: try: v = int(parts[1]) except ValueError: return False else: if not 1 <= v <= 12: return False try: int(parts[0]) except ValueError: return False return True def date_key(datestr): """Parse a date format y-m-d and returns an undefined integer that can only be used to compare dates. In case the date string is invalid the returned value is undefined. """ # this basically does "2001-02-03" -> 20010203 default = [0, 1, 1] parts = datestr.split("-") parts += default[len(parts):] value = 0 for d, p, m in zip(default, parts, (10000, 100, 1)): try: value += int(p) * m except ValueError: # so that "2003-01-" is equal to "2003-01" .. value += d * m return value def parse_date(datestr): """Parses yyyy-mm-dd date format and returns unix time. Raises ValueError in case the input couldn't be parsed. """ import time try: frmt = ["%Y", "%Y-%m", "%Y-%m-%d"][datestr.count("-")] except IndexError: raise ValueError try: return time.mktime(time.strptime(datestr, frmt)) except OverflowError as e: raise ValueError(e) def format_int_locale(value): """Turn an integer into a grouped, locale-dependent string e.g. 12345 -> "12,345" or "12.345" etc """ return locale.format_string("%d", value, grouping=True) def format_float_locale(value, format="%.2f"): """Turn a float into a grouped, locale-dependent string e.g. 12345.67 -> "12,345.67" or "12.345,67" etc """ return locale.format_string(format, value, grouping=True) def format_rating(value, blank=True): """Turn a number into a sequence of rating symbols.""" from quodlibet import config prefs = config.RATINGS steps = prefs.number value = max(min(value, 1.0), 0) ons = int(round(steps * value)) offs = (steps - ons) if blank else 0 return prefs.full_symbol * ons + prefs.blank_symbol * offs def format_bitrate(value): return _("%d kbps") % int(value) def format_size(size): """Turn an integer size value into something human-readable. Args: size (int): size in bytes Returns: str """ # TODO: Better i18n of this (eg use O/KO/MO/GO in French) if size >= 1024 ** 3: return u"%.1f GB" % (float(size) / (1024 ** 3)) elif size >= 1024 ** 2 * 100: return u"%.0f MB" % (float(size) / (1024 ** 2)) elif size >= 1024 ** 2 * 10: return u"%.1f MB" % (float(size) / (1024 ** 2)) elif size >= 1024 ** 2: return u"%.2f MB" % (float(size) / (1024 ** 2)) elif size >= 1024 * 10: return u"%d KB" % int(size / 1024) elif size >= 1024: return u"%.2f KB" % (float(size) / 1024) else: return u"%d B" % size def format_time(time): """Turn a time value in seconds into hh:mm:ss or mm:ss.""" if time < 0: time = abs(time) prefix = "-" else: prefix = "" if time >= 3600: # 1 hour # time, in hours:minutes:seconds return "%s%d:%02d:%02d" % (prefix, time // 3600, (time % 3600) // 60, time % 60) else: # time, in minutes:seconds return "%s%d:%02d" % (prefix, time // 60, time % 60) def format_time_display(time): """Like format_time, but will use RATIO instead of a colon to separate""" return format_time(time).replace(":", u"\u2236") def format_time_seconds(time): from quodlibet import ngettext time_str = format_int_locale(time) return ngettext("%s second", "%s seconds", time) % time_str def format_time_long(time, limit=2): """Turn a time value in seconds into x hours, x minutes, etc. `limit` limits the count of units used, so the result will be <= time. 0 means no limit. """ from quodlibet import ngettext if time < 1: return _("No time information") cutoffs = [ (60, lambda n: ngettext("%d second", "%d seconds", n)), (60, lambda n: ngettext("%d minute", "%d minutes", n)), (24, lambda n: ngettext("%d hour", "%d hours", n)), (365, lambda n: ngettext("%d day", "%d days", n)), (None, lambda n: ngettext("%d year", "%d years", n)), ] time_str = [] for divisor, gettext_partial in cutoffs: if time < 1: break if divisor is None: time, unit = 0, time else: time, unit = divmod(time, divisor) if unit: time_str.append(gettext_partial(unit) % unit) time_str.reverse() if limit: time_str = time_str[:limit] return ", ".join(time_str) def format_time_preferred(t, fmt=None): """Returns duration formatted to user's preference""" from quodlibet.config import DurationFormat, DURATION fmt = fmt or DURATION.format if fmt == DurationFormat.STANDARD: return format_time_long(t, 2) elif fmt == DurationFormat.NUMERIC: return format_time_display(t) elif fmt == DurationFormat.FULL: return format_time_long(t, 5) else: return format_time_seconds(t) def capitalize(str): """Capitalize a string, not affecting any character after the first.""" return str[:1].upper() + str[1:] def _split_numeric_sortkey(s, limit=10, reg=re.compile(r"[0-9][0-9]*\.?[0-9]*").search, join=u" ".join): """Separate numeric values from the string and convert to float, so it can be used for human sorting. Also removes all extra whitespace.""" result = reg(s) if not result or not limit: text = join(s.split()) return (text,) if text else tuple() else: start, end = result.span() return ( join(s[:start].split()), float(result.group()), _split_numeric_sortkey(s[end:], limit - 1)) def human_sort_key(s, normalize=unicodedata.normalize): if not s: return () if not isinstance(s, str): s = s.decode("utf-8") s = normalize("NFD", s.lower()) return _split_numeric_sortkey(s) def website(site): """Open the given URL in the user's default browser""" from gi.repository import Gtk, Gdk, GLib try: Gtk.show_uri(None, site, Gdk.CURRENT_TIME) except GLib.Error: print_exc() def tag(name, cap=True): # Return a 'natural' version of the tag for human-readable bits. # Strips ~ and ~# from the start and runs it through a map (which # the user can configure). if not name: return ngettext("Invalid tag", "Invalid tags", 1) else: from quodlibet.util.tags import readable parts = map(readable, tagsplit(name)) if cap: # Translators: If tag names, when capitalized, should not # be title-cased ("Looks Like This"), but rather only have # the first letter capitalized, translate this string as # something non-empty other than "titlecase?". if C_("check", "titlecase?") == "titlecase?": parts = map(title, parts) else: parts = map(capitalize, parts) return " / ".join(parts) def tagsplit(tag): """Split a (potentially) tied tag into a list of atomic tags. Two ~~s make the next tag prefixed with a ~, so ~foo~~bar => [foo, ~bar].""" if "~" in tag[1:]: if tag.startswith("~") and not tag.startswith("~#"): tag = tag[1:] tags = [] front = "" for part in tag.split("~"): if part: tags.append(front + part) front = "" else: front = "~" return tags else: return [tag] def pattern(pat, cap=True, esc=False, markup=False): """Return a 'natural' version of the pattern string for human-readable bits. Assumes all tags in the pattern are present. """ from quodlibet.pattern import Pattern, XMLFromPattern, XMLFromMarkupPattern from quodlibet.formats import FILESYSTEM_TAGS class Fakesong(dict): cap = False def comma(self, key): return " - ".join(self.list(key)) def list(self, key): return [tag(k, self.cap) for k in tagsplit(key)] list_separate = list def __call__(self, tag, *args): if tag in FILESYSTEM_TAGS: return fsnative(str(tag)) return 0 if '~#' in tag[:2] else self.comma(tag) fakesong = Fakesong({'filename': tag('filename', cap)}) fakesong.cap = cap try: if markup: p = XMLFromMarkupPattern(pat) elif esc: p = XMLFromPattern(pat) else: p = Pattern(pat) except ValueError: return _("Invalid pattern") return p.format(fakesong) def spawn(argv, stdout=False): """Asynchronously run a program. argv[0] is the executable name, which must be fully qualified or in the path. If stdout is True, return a file object corresponding to the child's standard output; otherwise, return the child's process ID. argv must be strictly str objects to avoid encoding confusion. """ from gi.repository import GLib print_d("Running %r" % argv) args = GLib.spawn_async(argv=argv, flags=GLib.SpawnFlags.SEARCH_PATH, standard_output=stdout) if stdout: return os.fdopen(args[2]) else: return args[0] def fver(tup): return ".".join(map(str, tup)) def make_case_insensitive(filename): return "".join(["[%s%s]" % (c.lower(), c.upper()) for c in filename]) class DeferredSignal: """A wrapper for connecting functions to signals. Some signals may fire hundreds of times, but only require processing once per group. This class pushes the call to the mainloop at idle priority and prevents multiple calls from being inserted in the mainloop at a time, greatly improving responsiveness in some places. When the target function is finally called, the arguments passed are the last arguments passed to DeferredSignal. `priority` defaults to GLib.PRIORITY_DEFAULT If `owner` is given, it will not call the target after the owner is destroyed. Example usage: def func(widget, user_arg): pass widget.connect('signal', DeferredSignal(func, owner=widget), user_arg) """ def __init__(self, func, timeout=None, owner=None, priority=None): """timeout in milliseconds""" self.func = func self.dirty = False self.args = None if owner: def destroy_cb(owner): self.abort() owner.connect("destroy", destroy_cb) from gi.repository import GLib if priority is None: priority = GLib.PRIORITY_DEFAULT if timeout is None: self.do_idle_add = lambda f: GLib.idle_add(f, priority=priority) else: self.do_idle_add = lambda f: GLib.timeout_add( timeout, f, priority=priority) @property def __self__(self): return self.func.__self__ @property def __code__(self): return self.func.__code__ @property def __closure__(self): return self.func.__closure__ def call(self, *args): """Force a call""" self.abort() self.args = args self._wrap() def abort(self): """Abort any queued up calls. Can still be reused afterwards. """ if self.dirty: from gi.repository import GLib GLib.source_remove(self._id) self.dirty = False self.args = None def __call__(self, *args): self.args = args if not self.dirty: self.dirty = True self._id = self.do_idle_add(self._wrap) def _wrap(self): self.func(*self.args) self.dirty = False self.args = None return False def connect_obj(this, detailed_signal, handler, that, *args, **kwargs): """A wrapper for connect() that has the same interface as connect_object(). Used as a temp solution to get rid of connect_object() calls which may be changed to match the C version more closely in the future. https://git.gnome.org/browse/pygobject/commit/?id=86fb12b3e9b75 While it's not clear if switching to weak references will break anything, we mainly used this for adjusting the callback signature. So using connect() behind the scenes will keep things working as they are now. """ def wrap(this, *args): return handler(that, *args) return this.connect(detailed_signal, wrap, *args, **kwargs) def _connect_destroy(sender, func, detailed_signal, handler, *args, **kwargs): """Connect a bound method to a foreign object signal and disconnect if the object the method is bound to emits destroy (Gtk.Widget subclass). Also works if the handler is a nested function in a method and references the method's bound object. This solves the problem that the sender holds a strong reference to the bound method and the bound to object doesn't get GCed. """ if hasattr(handler, "__self__"): obj = handler.__self__ else: # XXX: get the "self" var of the enclosing scope. # Used for nested functions which ref the object but aren't methods. # In case they don't ref "self" normal connect() should be used anyway. index = handler.__code__.co_freevars.index("self") obj = handler.__closure__[index].cell_contents assert obj is not sender handler_id = func(detailed_signal, handler, *args, **kwargs) def disconnect_cb(*args): sender.disconnect(handler_id) obj.connect('destroy', disconnect_cb) return handler_id def connect_destroy(sender, *args, **kwargs): return _connect_destroy(sender, sender.connect, *args, **kwargs) def connect_after_destroy(sender, *args, **kwargs): return _connect_destroy(sender, sender.connect_after, *args, **kwargs) class cached_property: """A read-only @property that is only evaluated once. TODO: work out some typing for this, see test_query.py""" def __init__(self, fget, doc=None): self.fget = fget self.__doc__ = doc or fget.__doc__ self.__name__ = name = fget.__name__ # these get name mangled, so caching won't work unless # we mangle too assert not (name.startswith("__") and not name.endswith("__")), \ "can't cache a dunder method" def __get__(self, obj, cls): if obj is None: return self obj.__dict__[self.__name__] = result = self.fget(obj) return result def sanitize_tags(tags, stream=False): """Returns a new sanitized tag dict. stream defines if the tags of a main/base song should be changed or of a stream song. e.g. title will be removed for the base song but not for the stream one. """ san = {} for key, value in tags.items(): key = key.lower() key = {"location": "website"}.get(key, key) if isinstance(value, str): lower = value.lower().strip() if key == "channel-mode": if "stereo" in lower or "dual" in lower: value = u"stereo" elif key == "audio-codec": if "mp3" in lower: value = u"MP3" elif "aac" in lower or "advanced" in lower: value = u"MPEG-4 AAC" elif "vorbis" in lower: value = u"Ogg Vorbis" if lower in ("http://www.shoutcast.com", "http://localhost/", "default genre", "none", "http://", "unnamed server", "unspecified", "n/a"): continue if key == "duration": try: value = int(int(value) / 1000) except ValueError: pass else: if not stream: continue key = "~#length" elif key == "bitrate": try: value = int(value) / 1000 except ValueError: pass else: if not stream: continue key = "~#bitrate" elif key == "nominal-bitrate": try: value = int(value) / 1000 except ValueError: pass else: if stream: continue key = "~#bitrate" if key in ("emphasis", "mode", "layer", "maximum-bitrate", "minimum-bitrate", "has-crc", "homepage"): continue if not stream and key in ("title", "album", "artist", "date"): continue if isinstance(value, (int, float)): if not key.startswith("~#"): key = "~#" + key san[key] = value else: if key.startswith("~#"): key = key[2:] if not isinstance(value, str): continue value = value.strip() if key in san: if value not in san[key].split("\n"): san[key] += "\n" + value else: san[key] = value return san def build_filter_query(key, values): """Create a text query that matches a union of all values for a key build_filter_query("foo", ["x", "y"]) => foo = |("x"c, "y"c) build_filter_query("~#foo", ["1"]) => #(foo = 1) """ if not values: return u"" if key.startswith("~#"): nheader = key[2:] queries = ["#(%s = %s)" % (nheader, i) for i in values] if len(queries) > 1: return u"|(%s)" % ", ".join(queries) else: return queries[0] else: text = ", ".join( ["'%s'c" % v.replace("\\", "\\\\").replace("'", "\\'") for v in values]) if len(values) == 1: return u"%s = %s" % (key, text) else: return u"%s = |(%s)" % (key, text) def limit_songs(songs, max, weight_by_ratings=False): """Choose at most `max` songs from `songs`, optionally giving weighting to ~#rating""" if not max or len(songs) < max: return songs else: if weight_by_ratings: def rating_weighted_random(song): # Apply even (random : higher rating) weighting return (1 - song("~#rating")) * (1 + random.random()) songs.sort(key=rating_weighted_random) else: random.shuffle(songs) return songs[:max] def gi_require_versions(name, versions): """Like gi.require_version, but will take a list of versions. Returns the required version or raises ValueError. """ assert versions import gi error = None for version in versions: try: gi.require_version(name, version) except ValueError as e: error = e else: return version else: raise error def load_library(names, shared=True): """Load a ctypes library with a range of names to try. Handles direct .so names and library names ["libgpod.so", "gpod"]. If shared is True can return a shared instance. Raises OSError if not found. Returns (library, name) """ if not names: raise ValueError if shared: load_func = lambda n: getattr(ctypes.cdll, n) else: load_func = ctypes.cdll.LoadLibrary errors = [] for name in names: dlopen_name = name if ".so" not in name and ".dll" not in name and \ ".dylib" not in name: dlopen_name = ctypes.util.find_library(name) or name if is_osx() and not os.path.isabs(dlopen_name): dlopen_name = os.path.join(sys.prefix, "lib", dlopen_name) try: return load_func(dlopen_name), name except OSError as e: errors.append(str(e)) raise OSError("\n".join(errors)) def is_main_thread(): """If the calling thread is the main one""" return threading.current_thread().name == "MainThread" class MainRunnerError(Exception): pass class MainRunnerAbortedError(MainRunnerError): pass class MainRunnerTimeoutError(MainRunnerError): pass class MainRunner: """Schedule a function call in the main loop from a worker thread and wait for the result. Make sure to call abort() before the main loop gets destroyed, otherwise the worker thread may block forever in call(). """ def __init__(self): self._source_id = None self._call_id = None self._lock = threading.Lock() self._cond = threading.Condition(self._lock) self._return = None self._error = None self._aborted = False def _run(self, func, *args, **kwargs): try: self._return = func(*args, **kwargs) except Exception as e: self._error = MainRunnerError(e) def _idle_run(self, call_id, call_event, func, *args, **kwargs): call_event.set() with self._lock: # In case a timeout happened but this got still # scheduled, this could be called after call() returns; # Compare to the current call id and do nothing if it isn't ours if call_id is not self._call_id: return False try: self._run(func, *args, **kwargs) finally: self._source_id = None self._cond.notify() return False def abort(self): """After this call returns no function will be executed anymore and a currently blocking call will fail with MainRunnerAbortedError. Can be called multiple times and can not fail. call() will always fail after this was called. """ from gi.repository import GLib with self._lock: if self._aborted: return if self._source_id is not None: GLib.source_remove(self._source_id) self._source_id = None self._aborted = True self._call_id = None self._error = MainRunnerAbortedError("aborted") self._cond.notify() def call(self, func, *args, **kwargs): """Runs the function in the main loop and blocks until it is finished or abort() was called. In case this is called from the main loop the function gets executed immediately. The priority kwargs defines the event source priority and will not be passed to func. In case a timeout kwarg is given the call will raise MainRunnerTimeoutError in case the function hasn't been scheduled (doesn't mean returned) until that time. timeout is a float in seconds. Can raise MainRunnerError in case the function raises an exception. Raises MainRunnerAbortedError in case the runner was aborted. Raises MainRunnerTimeoutError in case the timeout was reached. """ from gi.repository import GLib with self._lock: if self._aborted: raise self._error self._error = None # XXX: ideally this should be GLib.MainContext.default().is_owner() # but that's not available in older pygobject if is_main_thread(): kwargs.pop("priority", None) self._run(func, *args, **kwargs) else: assert self._source_id is None assert self._call_id is None timeout = kwargs.pop("timeout", None) call_event = threading.Event() self._call_id = object() self._source_id = GLib.idle_add( self._idle_run, self._call_id, call_event, func, *args, **kwargs) # only wait for the result if we are sure it got scheduled if call_event.wait(timeout): self._cond.wait() self._call_id = None if self._source_id is not None: GLib.source_remove(self._source_id) self._source_id = None raise MainRunnerTimeoutError("timeout: %r" % timeout) if self._error is not None: raise self._error return self._return def re_escape(string, BAD="/.^$*+-?{,\\[]|()<>#=!:"): """A `re.escape` which also works with unicode""" needs_escape = lambda c: (c in BAD and "\\" + c) or c return type(string)().join(map(needs_escape, string)) def set_process_title(title): """Sets process name as visible in ps or top. Requires ctypes libc and is almost certainly *nix-only. See issue 736 """ if os.name == "nt": return try: libc = load_library(["libc.so.6", "c"])[0] prctl = libc.prctl except (OSError, AttributeError): print_d("Couldn't find module libc.so.6 (ctypes). " "Not setting process title.") else: prctl.argtypes = [ ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ] prctl.restype = ctypes.c_int PR_SET_NAME = 15 data = ctypes.create_string_buffer(title.encode("utf-8")) res = prctl(PR_SET_NAME, ctypes.addressof(data), 0, 0, 0) if res != 0: print_w("Setting the process title failed") def list_unique(sequence): """Takes any sequence and returns a list with all duplicate entries removed while preserving the order. """ l = [] seen = set() append = l.append add = seen.add for v in sequence: if v not in seen: append(v) add(v) return l def reraise(tp, value, tb=None): """Reraise an exception with a new exception type and the original stack trace """ if tb is None: tb = sys.exc_info()[2] raise tp(value).with_traceback(tb) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/atomic.py������������������������������������������������������������0000644�0001750�0001750�00000005344�14310167056�017007� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013,2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Helpers for atomic file operations on Linux/OSX/Windows""" import os import contextlib from senf import fsnative if os.name == "nt": from . import winapi else: import fcntl from .misc import NamedTemporaryFile def _windows_rename(source, dest): """Replaces dest with source. Raises OSError in case of an error. """ assert os.name == "nt" # not atomic, but better than removing the original first... status = winapi.MoveFileExW( source, dest, winapi.MOVEFILE_WRITE_THROUGH | winapi.MOVEFILE_REPLACE_EXISTING) if status == 0: raise winapi.WinError() @contextlib.contextmanager def atomic_save(filename, mode): """Try to replace the content of a file in the safest way possible. A temporary file will be created in the same directory where the replacement data can be written into. After writing is done the data will be flushed to disk and the original file replaced atomically. In case of an error this raises IOError and OSError and the original file will be untouched. In case the computer crashes or any other non-recoverable error happens the temporary file will be left behind and has to be deleted manually. with atomic_save("config.cfg", "wb") as f: f.write(data) """ assert isinstance(filename, fsnative) dir_ = os.path.dirname(filename) basename = os.path.basename(filename) fileobj = NamedTemporaryFile( mode=mode, dir=dir_, prefix=basename + fsnative(u"_"), suffix=fsnative(u".tmp"), delete=False) try: yield fileobj fileobj.flush() fileno = fileobj.fileno() if os.name != "nt" and hasattr(fcntl, "F_FULLFSYNC"): # on OSX fsync doesn't sync all the way.. # https://lists.apple.com/archives/darwin-dev/2005/Feb/msg00072.html # https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fsync.2.html fcntl.fcntl(fileno, fcntl.F_FULLFSYNC) else: # on linux fsync goes all the way by default # http://linux.die.net/man/2/fsync os.fsync(fileno) fileobj.close() if os.name == "nt": _windows_rename(fileobj.name, filename) else: os.rename(fileobj.name, filename) except: try: os.unlink(fileobj.name) except OSError: pass raise finally: fileobj.close() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666907943.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/collection.py��������������������������������������������������������0000644�0001750�0001750�00000071745�14326577447�017716� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2013 Joe Wreschnig, Michael Urman, Iñigo Serna, # Christoph Reiter, Steven Robertson # 2011-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import from __future__ import annotations import os import random from typing import Any from urllib.parse import quote from senf import fsnative, fsn2bytes, bytes2fsn, path2fsn, _fsnative, uri2fsn, fsn2uri from quodlibet import ngettext, _ from quodlibet import util from quodlibet import config from quodlibet.formats._audio import (TAG_TO_SORT, NUMERIC_ZERO_DEFAULT, AudioFile, HasKey) from quodlibet.formats._audio import PEOPLE as _PEOPLE from quodlibet.pattern import Pattern from quodlibet.const import QL_NAMESPACE try: from collections import abc except ImportError: import collections as abc # type: ignore from quodlibet.util import is_windows from quodlibet.util.path import escape_filename, unescape_filename, limit_path from quodlibet.util.dprint import print_d, print_w from quodlibet.util.misc import total_ordering, hashable from .collections import HashedList from datetime import datetime from os.path import splitext, basename, dirname, exists from xml.etree import ElementTree as ET from xml.etree.ElementTree import ElementTree, Element XSPF_NS = "http://xspf.org/ns/0/" PEOPLE = list(_PEOPLE) # Collections value albumartist more than song artist (Issue 1034) PEOPLE.remove("albumartist") PEOPLE.insert(0, "albumartist") ELPOEP = list(reversed(PEOPLE)) PEOPLE_SCORE = [100 ** i for i in range(len(PEOPLE))] def avg(nums): """Returns the average (arithmetic mean) of a list of numbers""" return float(sum(nums)) / len(nums) def bayesian_average(nums, c=None, m=None): """Returns the Bayesian average of an iterable of numbers, with parameters defaulting to config specific to ~#rating.""" m = m or config.RATINGS.default c = c or config.getfloat("settings", "bayesian_rating_factor", 0.0) ret = float(m * c + sum(nums)) / (c + len(nums)) return ret NUM_DEFAULT_FUNCS = { "length": "sum", "playcount": "sum", "added": "max", "lastplayed": "max", "laststarted": "max", "mtime": "max", "rating": "bav", "skipcount": "sum", "year": "min", "originalyear": "min", "filesize": "sum" } NUM_FUNCS = { "max": max, "min": min, "sum": sum, "avg": avg, "bav": bayesian_average } class Collection: """A collection of songs which implements some methods similar to the AudioFile class. The content of the collection can be changed by changing the content of the songs attribute. """ _cache_size = 6 songs = () def __init__(self): """Cache in _cache, LRU key order in _used, keys that return default are in _default""" self.__cache = {} self.__default = set() self.__used = [] def finalize(self): """Finalize the collection. Call this after songs get added or removed""" self.__cache.clear() self.__default.clear() self.__used = [] def get(self, key, default=u"", connector=u" - "): if not self.songs: return default if key[:1] == "~" and "~" in key[1:]: if not isinstance(default, str): return default keys = util.tagsplit(key) v = map(self.__get_cached_value, keys) def default_funct(x): if x is None: return default return x v = map(default_funct, v) v = map(lambda x: (isinstance(x, float) and "%.2f" % x) or x, v) v = map( lambda x: isinstance(x, str) and x or str(x), v) return connector.join(filter(None, v)) or default else: value = self.__get_cached_value(key) if value is None: return default return value __call__ = get def comma(self, key): value = self.get(key) return (value if isinstance(value, (int, float)) else value.replace("\n", ", ")) def list(self, key): v = self.get(key, connector=u"\n") if "~" in key[1:] else self.get(key) if isinstance(v, float): # Ignore insignificant differences in numeric tags caused # by floating point imprecision when converting them to strings v = round(v, 8) return [] if v == "" else str(v).split("\n") def __get_cached_value(self, key): if key in self.__cache: self.__used.remove(key) self.__used.insert(0, key) return self.__cache[key] elif key in self.__default: return None else: val = self.__get_value(key) if val is None: self.__default.add(key) else: self.__used.insert(0, key) self.__cache[key] = val # Remove the oldest if the cache is full if len(self.__used) > self._cache_size: self.__cache.pop(self.__used.pop(-1)) return val def __get_value(self, key): """This is similar to __call__ in the AudioFile class. All internal tags are changed to represent a collection of songs. """ # Using key:<func> runs the resulting list of values # through the function before returning it. # Numeric keys without a func will default to a reasonable function if key.startswith("~#"): key = key[2:] if key[-4:-3] == ":": func = key[-3:] key = key[:-4] elif key == "tracks": return len(self.songs) elif key == "discs": return len({song("~#disc", 1) for song in self.songs}) elif key == "bitrate": length = self.__get_value("~#length") if not length: return 0 w = lambda s: s("~#bitrate", 0) * s("~#length", 0) return sum(w(song) for song in self.songs) / length else: # Standard or unknown numeric key. # AudioFile will try to cast the values to int, # default to avg func = NUM_DEFAULT_FUNCS.get(key, "avg") key = "~#" + key func = NUM_FUNCS.get(func) if func: # If none of the songs can return a numeric key, # the album returns default values = (song(key) for song in self.songs) values = [v for v in values if v != ""] return func(values) if values else None elif key in NUMERIC_ZERO_DEFAULT: return 0 return None elif key[:1] == "~": key = key[1:] numkey = key.split(":")[0] keys = {"people": {}, "peoplesort": {}} if key in keys: people = keys["people"] peoplesort = keys["peoplesort"] for song in self.songs: # Rank people by "relevance" -- artists before composers # before performers, then by number of appearances. for w, k in enumerate(ELPOEP): persons = song.list(k) for person in persons: people[person] = (people.get(person, 0) - PEOPLE_SCORE[w]) if k in TAG_TO_SORT: persons = song.list(TAG_TO_SORT[k]) or persons for person in persons: peoplesort[person] = (peoplesort.get(person, 0) - PEOPLE_SCORE[w]) # It's cheaper to get people and peoplesort in one go keys["people"] = sorted(people.keys(), key=people.__getitem__)[:100] keys["peoplesort"] = sorted(peoplesort.keys(), key=peoplesort.__getitem__)[:100] ret = keys.pop(key) ret = (ret and "\n".join(ret)) or None other, values = keys.popitem() other = "~" + other if not values: self.__default.add(other) else: if other in self.__used: self.__used.remove(other) self.__used.append(other) self.__cache[other] = "\n".join(values) return ret elif numkey == "length": length = self.__get_value("~#" + key) return None if length is None else util.format_time(length) elif numkey == "long-length": length = self.__get_value("~#" + key[5:]) return (None if length is None else util.format_time_long(length)) elif numkey == "tracks": tracks = self.__get_value("~#" + key) return (None if tracks is None else ngettext("%d track", "%d tracks", tracks) % tracks) elif numkey == "discs": discs = self.__get_value("~#" + key) if discs > 1: return ngettext("%d disc", "%d discs", discs) % discs else: # TODO: check this is correct for discs == 1 return None elif numkey == "rating": rating = self.__get_value("~#" + key) if rating is None: return None return util.format_rating(rating) elif numkey == "filesize": size = self.__get_value("~#" + key) return None if size is None else util.format_size(size) key = "~" + key # Nothing special was found, so just take all values of the songs # and sort them by their number of appearance result = {} for song in self.songs: for value in song.list(key): result[value] = result.get(value, 0) - 1 values = list(map(lambda x: x[0], sorted(result.items(), key=lambda x: (x[1], x[0])))) return "\n".join(values) if values else None class Album(Collection, HasKey): """Like a `Collection` but adds cover scanning, some attributes for sorting and uses a set for the songs.""" @util.cached_property def peoplesort(self): return util.human_sort_key(self.get("~peoplesort").split("\n")[0]) @util.cached_property def genre(self): return util.human_sort_key(self.get("genre").split("\n")[0]) @property def date(self): return self.get("date") @property def title(self): return self.get("album") def __init__(self, song): super().__init__() self.songs = set() # albumsort is part of the album_key, so every song has the same self.sort = util.human_sort_key(song("albumsort")) self.key = song.album_key @property def str_key(self): return str(self.key) def finalize(self): """Finalize this album. Call after songs get added or removed""" super().finalize() self.__dict__.pop("peoplesort", None) self.__dict__.pop("genre", None) def __repr__(self): return "Album(%s)" % repr(self.key) @hashable @total_ordering class Playlist(Collection, abc.Iterable, HasKey): """A Playlist is a `Collection` that has list-like features Songs can appear more than once. """ @staticmethod def suggested_name_for(songs): if len(songs) == 0: return _("Empty Playlist") elif len(songs) == 1: return songs[0].comma("title") else: return ngettext( "%(title)s and %(count)d more", "%(title)s and %(count)d more", len(songs) - 1) % ({"title": songs[0].comma("title"), "count": len(songs) - 1}) def __init__(self, name: str, songs_lib=None, pl_lib=None): super().__init__() self._list: HashedList = HashedList() # we require a file library here with masking assert songs_lib is None or hasattr(songs_lib, "masked") self.songs_lib = songs_lib name = str(name) if not name: raise ValueError("Playlists must have a name") self.name = name self.pl_lib = pl_lib # Libraries are dict-like so falsey if empty if self.pl_lib is None: print_d(f"Playlist {name!r} initialised without library") else: self.pl_lib.add([self]) self.__inhibit_library_signals = False @property def key(self) -> str: # type: ignore # (Note: we want no setter) return self.name def get(self, key, default=u"", connector=u" - "): if key == "~name": return self.name return super().get(key, default, connector) __call__ = get # List-like methods, for compatibility with original Playlist class. def extend(self, songs: abc.Iterable[AudioFile]): self._list.extend(songs) self.finalize() self._emit_changed(songs, msg="extend") def append(self, song): ret = self._list.append(song) self._emit_changed([song], msg="append") self.finalize() return ret def clear(self): self._emit_changed(self._list, msg="clear") del self._list[:] self.finalize() def __iter__(self): return iter(self._list) def __len__(self): return len(self._list) def __getitem__(self, index): return self._list[index] def index(self, value): return self._list.index(value) def __setitem__(self, key, value): self._list[key] = value if isinstance(key, slice): # TODO: more reliable slice support self._emit_changed(value, msg="direct slice set") else: self._emit_changed([value], msg="direct set") self.finalize() @property def songs(self): return [s for s in self._list if not isinstance(s, str)] def rename(self, new_name): """Changes this playlist's name and re-saves, or raises an `ValueError` if the name is not allowed""" if new_name == self.name: return self.name = self._validated_name(new_name) self.write() def _validated_name(self, new_name): """Returns a transformed (or not) name, or raises a `ValueError` if the name is not allowed """ new_name = str(new_name) if not new_name: raise ValueError(_("Playlists must have a name")) return new_name def add_songs(self, filenames, library): # TODO: use Set here to avoid duplicate signals changed = [] for i in range(len(self)): if isinstance(self[i], str) and self._list[i] in filenames: song = library[self._list[i]] self._list[i] = song changed.append(song) if changed: self._emit_changed(changed, msg="add") return bool(changed) def remove_songs(self, songs: abc.Iterable[AudioFile], leave_dupes: bool = False) -> bool: """Removes `songs` from this playlist if they are there, removing only the first reference if `leave_dupes` is True :returns True if anything was removed """ changed = False for song in songs: # TODO: document the "library.masked" business if self.songs_lib is not None and self.songs_lib.masked(song): while True: try: self._list[self.index(song)] = song("~filename") except ValueError: break else: changed = True else: while song in self._list: self._list.remove(song) changed = True if leave_dupes: break def songs_gone(): return set(songs) - set(self._list) if changed: self.finalize() # Short-circuit logic will avoid the calculation if not leave_dupes or songs_gone(): self._emit_changed(songs, "remove_songs") return changed @property def inhibit(self): return self.__inhibit_library_signals @inhibit.setter def inhibit(self, value): self.__inhibit_library_signals = value def _emit_changed(self, songs, msg=""): if self.pl_lib is not None and not self.inhibit: print_d(f"Changed playlist {self!r} ({msg})") self.inhibit = True # Awkward, but we don't want to make Collection a GObject really self.pl_lib.emit('changed', [self]) self.inhibit = False if self.songs_lib and not self.inhibit and songs: # See above re: emitting self.songs_lib.emit('changed', songs) def has_songs(self, songs): # TODO(rm): consider the "library.masked" business some, all = False, True for song in songs: found = song in self._list some = some or found all = all and found if some and not all: break return some, all def delete(self): if self.pl_lib is not None and not self.inhibit: self.pl_lib.remove([self]) def write(self): pass @property def has_duplicates(self): """Returns True if there are any duplicated files in this playlist""" return self._list.has_duplicates() def shuffle(self): """Randomly shuffles this playlist, without weighting""" random.shuffle(self._list) if self.pl_lib is not None: self.pl_lib.changed([self]) self.write() def __eq__(self, other): try: return self.name == other.name except AttributeError: return False def __lt__(self, other): try: return self.name < other.name except AttributeError: return False def __hash__(self): return id(self) def __str__(self): songs_text = (ngettext("%d song", "%d songs", len(self.songs)) % len(self.songs)) return u"\"%s\" (%s)" % (self.name, songs_text) class FileBackedPlaylist(Playlist): """A `Playlist` that is stored as a UTF-8 text file of paths""" def __init__(self, dir_: _fsnative, filename: _fsnative, songs_lib=None, pl_lib=None, validate: bool = False): assert isinstance(dir_, fsnative) self.dir = dir_ name = self.name_for(filename) super().__init__(name, songs_lib=songs_lib, pl_lib=pl_lib) if validate: self.name = self._validated_name(name) # Store the actual filename used, not sanitised and validated name # This means we can delete imported things properly, etc... self._last_fn = os.path.join(dir_, filename) try: self._populate_from_file() except IOError: if self.name: print_d("Playlist '%s' not found, creating new." % self.name) self.write() @classmethod def name_for(cls, filename: _fsnative) -> str: return unescape_filename(filename) @classmethod def filename_for(cls, filename: str): return escape_filename(filename) def _populate_from_file(self): """Populates, or raises IOError if no file found""" library = self.songs_lib with open(self.path, "rb") as h: for line in h: assert library is not None try: line = bytes2fsn(line.rstrip(), "utf-8") except ValueError: # decoding failed continue if line in library: self._list.append(library[line]) elif library and library.masked(line): self._list.append(line) @classmethod def new(cls, dir_, base=_("New Playlist"), songs_lib=None, pl_lib=None): assert isinstance(dir_, fsnative) if not (dir_ and os.path.realpath(dir_)): raise ValueError("Invalid playlist directory %r" % (dir_,)) last_error = None for i in range(1000): name = "%s %d" % (base, i) if i else base fn = cls.filename_for(name) try: return cls(dir_, fn, songs_lib=songs_lib, pl_lib=pl_lib, validate=True) except ValueError as e: last_error = e raise ValueError("Couldn't create playlist of name '%s' (e.g. %s)" % (base, last_error)) @classmethod def from_songs(cls, dir_, songs, title=None, songs_lib=None, pl_lib=None): assert isinstance(dir_, fsnative) title = title or cls.suggested_name_for(songs) playlist = cls.new(dir_, title, songs_lib=songs_lib, pl_lib=pl_lib) playlist.extend(songs) return playlist @property def path(self): return os.path.join(self.dir, self.filename_for(self.name)) @property def key(self) -> str: # type: ignore # (Note: we want no setter) return self.name def _validated_name(self, new_name: str) -> str: new_name = super()._validated_name(new_name) path = os.path.join(self.dir, self.filename_for(new_name)) if os.path.exists(path): raise ValueError( _("A playlist named %(name)s already exists at %(path)s") % {"name": new_name, "path": path}) return new_name def delete(self): self._delete_file(self._last_fn) super().delete() @classmethod def _delete_file(cls, fn): print_d(f"Deleting playlist file: {fn!r}") try: os.unlink(fn) except OSError as e: print_w(f"Couldn't delete {fn!r} ({e})") def write(self): fn = self.path with open(fn, "wb") as f: for song in self._list: if isinstance(song, str): f.write(fsn2bytes(song, "utf-8") + b"\n") else: f.write(fsn2bytes(song("~filename"), "utf-8") + b"\n") if self._last_fn != fn: self._delete_file(self._last_fn) self._last_fn = fn def __str__(self): return f"<{type(self).__name__} at {self.path!r}>" class XSPFBackedPlaylist(FileBackedPlaylist): _VERSION: int = 2 """Persistence version""" EXT = "xspf" CREATOR_PATTERN = Pattern("<artist|<artist>|<~people>>") _SAFER = {c: quote(c, safe="") for c in ("\\/:*?\"<>|" if is_windows() else "\0/")} @classmethod def from_playlist(cls, old_pl: FileBackedPlaylist, songs_lib, pl_lib): """Migrate from an existing file-based playlist""" def backup_for(path: str) -> str: base = os.path.join(dirname(path), ".backup") if not exists(base): print_d("Creating playlist backup directory %s" % base) os.mkdir(base) return os.path.join(base, basename(path)) name = old_pl.name new = XSPFBackedPlaylist.new(old_pl.dir, name, songs_lib=songs_lib, pl_lib=pl_lib) new.extend(old_pl) new.write() os.rename(old_pl.path, backup_for(old_pl.path)) old_pl.delete() return new def _populate_from_file(self): library = self.songs_lib try: tree = ET.parse(self.path) # TODO: validate some top-level tag data root = tree.getroot() if root.tag == "playlist": ns_mapping = None print_w(f"Using legacy namespace for import of {self.path}") elif root.tag == "{" + XSPF_NS + "}playlist": # Try correct format first ns_mapping = {"": XSPF_NS} else: raise ValueError(f"Unknown playlist root of {root.tag}") node = root.find("title", namespaces=ns_mapping) if node is None: print_w(f"No <title> found in {self.path} " f"(Got nodes: {[el.tag for el in root.iter()]})") elif self.name != node.text: print_w(f"Playlist was named {node.text!r} in XML " f"instead of {self.name!r} at {self.path!r}") for node in tree.iterfind(".//track", namespaces=ns_mapping): location = node.findtext("location", namespaces=ns_mapping).strip() path = location.replace("\n", "").replace("\r", "") try: # TODO: process relative URIs too? path = uri2fsn(path) except ValueError: pass if path in library: self._list.append(library[path]) elif library and library.masked(path): self._list.append(path) else: # TODO: handle missing playlist items (#3105, #729, #3131) node_dump = ET.tostring(node, method="xml").decode("utf-8") print_w("Couldn't find %r in playlist at %r. " "Perhaps its metadata will help: %r" % (path, self.path, node_dump)) self._list.append(path) library.mask(path) except (ET.ParseError, ValueError) as e: print_w("Couldn't load %r (%s)" % (self.path, e)) @classmethod def filename_for(cls, name: str): # Manually do *minimal* escaping, to allow near-readable filenames for bad, good in cls._SAFER.items(): name = name.replace(bad, good) return path2fsn("%s.%s" % (limit_path(name), cls.EXT)) @classmethod def name_for(cls, file_path: _fsnative) -> str: filename, ext = splitext(unescape_filename(file_path)) if not ext or ext.lower() != f".{cls.EXT}": raise TypeError(f"XSPFs should end in '{cls.EXT}', not {ext}") return filename def write(self): track_list = Element("trackList") # TODO: ditch for proper indent, once we have Python 3.9 track_list.text = "\n" for song in self._list: if isinstance(song, str): track = {"location": fsn2uri(song)} else: creator = self.CREATOR_PATTERN.format(song) mbid = song("musicbrainz_trackid") track = { "location": song("~uri"), "identifier": (f"https://musicbrainz.org/recording/{mbid}" if mbid else None), "title": song("title"), "creator": creator, "album": song("album"), "trackNum": song("~#track"), "duration": int(song("~#length") * 1000.) } track_list.append(self._element_from("track", track, True)) playlist = Element("playlist", attrib={"version": "1", "xmlns": XSPF_NS}) # Be kind to cat, git, editors etc. by leaving a final newline playlist.tail = "\n" playlist.append(self._version_tag()) playlist.append(self._text_element("title", self.name)) playlist.append(self._text_element("date", datetime.now().isoformat())) playlist.append(track_list) tree = ElementTree(playlist) ET.register_namespace("", XSPF_NS) path = self.path print_d(f"Writing {path !r}") tree.write(path, encoding="utf-8", xml_declaration=True) if self._last_fn != path: self._delete_file(self._last_fn) self._last_fn = path @classmethod def _version_tag(cls): """Currently this isn't needed (version 2 is detected), but it probably will be and easier to know than to guess""" meta = Element("meta", attrib={"rel": f"{QL_NAMESPACE}/playlists/version"}) meta.text = str(cls._VERSION) return meta @classmethod def _text_element(cls, name: str, value: Any) -> Element: el = Element(name) el.text = str(value) return el @classmethod def _element_from(cls, name: str, d: dict, with_newline: bool = False) -> Element: """Converts a dict to XML etree. Removes falsey nodes""" out = Element(name) for k, v in d.items(): if k and v: element = (cls._element_from(k, v) if isinstance(v, dict) else cls._text_element(k, v)) out.append(element) if with_newline: out.tail = "\n" return out ���������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/collections.py�������������������������������������������������������0000664�0001750�0001750�00000012545�14231604332�020047� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2013 Christoph Reiter # 2016-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import try: from collections import abc except ImportError: import collections as abc # type: ignore from collections import defaultdict from typing import Any from .misc import total_ordering @total_ordering class DictMixin: """Implement the dict API using keys() and __*item__ methods. Similar to UserDict.DictMixin, this takes a class that defines __getitem__, __setitem__, __delitem__, and keys(), and turns it into a full dict-like object. UserDict.DictMixin is not suitable for this purpose because it's an old-style class. This class is not optimized for very large dictionaries; many functions have linear memory requirements. I recommend you override some of these functions if speed is required. """ def __getitem__(self, key): raise NotImplementedError() def __iter__(self): return iter(self.keys()) def has_key(self, key: Any) -> bool: try: self[key] except KeyError: return False else: return True __contains__ = has_key def iterkeys(self): return iter(self.keys()) def values(self): return [self[k] for k in self.keys()] def itervalues(self): return iter(self.values()) def items(self): return list(zip(self.keys(), self.values())) def iteritems(self): return iter(self.items()) def clear(self): for key in list(self.keys()): del self[key] def pop(self, key, *args): if len(args) > 1: raise TypeError("pop takes at most two arguments") try: value = self[key] except KeyError: if args: return args[0] else: raise del(self[key]) return value def popitem(self): try: key = list(self.keys())[0] return key, self.pop(key) except IndexError: raise KeyError("dictionary is empty") def update(self, other=None, **kwargs): if other is None: self.update(kwargs) other = {} try: for key, value in other.items(): self[key] = value except AttributeError: for key, value in other: self[key] = value def setdefault(self, key, default=None): try: return self[key] except KeyError: self[key] = default return default def get(self, key, default=None): try: return self[key] except KeyError: return default def __repr__(self): return repr(dict(self.items())) def __eq__(self, other): return dict(self.items()) == other def __lt__(self, other): return dict(self.items()) < other __hash__ = object.__hash__ def __len__(self): return len(self.keys()) class DictProxy(DictMixin): def __init__(self, *args, **kwargs): self.__dict = {} super().__init__(*args, **kwargs) def __getitem__(self, key): return self.__dict[key] def __setitem__(self, key, value): self.__dict[key] = value def __delitem__(self, key): del(self.__dict[key]) def keys(self): return self.__dict.keys() class HashedList(abc.MutableSequence): """A list-like collection that can only take hashable items and provides fast membership tests. Can handle duplicate entries. """ def __init__(self, arg=None): self._map = defaultdict(int) if arg is None: self._data = [] return self._data = list(arg) for item in arg: self._map[item] += 1 def __setitem__(self, index, item): old_items = self._data[index] if not isinstance(index, slice): old_items = [old_items] for old in old_items: self._map[old] -= 1 if not self._map[old]: del self._map[old] self._data[index] = item items = item if not isinstance(index, slice): items = [items] for item in items: self._map[item] += 1 def __getitem__(self, index): return self._data[index] def __delitem__(self, index): items = self._data[index] if not isinstance(index, slice): items = [items] for item in items: self._map[item] -= 1 if not self._map[item]: del self._map[item] del self._data[index] def __len__(self): return len(self._data) def insert(self, index, item): self._data.insert(index, item) self._map[item] += 1 def __contains__(self, item): return item in self._map def __iter__(self): for item in self._data: yield item def has_duplicates(self): """Returns True if any item is contained more than once""" return len(self._map) != len(self) def __repr__(self): return repr(self._data) �����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/config.py������������������������������������������������������������0000664�0001750�0001750�00000035117�14035600052�016773� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2008 Joe Wreschnig # 2009-2020 Nick Boultbee # 2011-2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Simple proxy to a Python ConfigParser ConfigParser uses "str" on both Python 2/3, on Python 2 we simply encode text/windows paths using utf-8 and save bytes as is. On Python 3 we save text as is, convert paths to bytes/utf-8 and convert bytes to unicode with utf-8/surrogateescape. The final representation on disk should then in both cases be the same. """ from __future__ import absolute_import import os import csv import collections from io import StringIO from configparser import RawConfigParser as ConfigParser, Error, NoSectionError from senf import fsnative from quodlibet.util import list_unique, print_d from quodlibet.util.atomic import atomic_save from quodlibet.util.string import join_escape, split_escape from quodlibet.util.path import mkdir # In newer RawConfigParser it is possible to replace the internal dict. The # implementation only uses items() for writing, so replace with a dict that # returns them sorted. This makes it easier to look up entries in the file. class _sorted_dict(collections.OrderedDict): def items(self): return sorted(super().items()) _DEFAULT = object() class Config: """A wrapper around RawConfigParser. Provides a ``defaults`` attribute of the same type which can be used to set default values. """ def __init__(self, version=None, _defaults=True): """Use read() to read in an existing config file. version should be an int starting with 0 that gets incremented if you want to register a new upgrade function. If None, upgrade is disabled. """ self._config = ConfigParser(dict_type=_sorted_dict) self.defaults = None if _defaults: self.defaults = Config(_defaults=False) self._version = version self._loaded_version = None self._upgrade_funcs = [] def _do_upgrade(self, func): assert self._loaded_version is not None assert self._version is not None old_version = self._loaded_version new_version = self._version if old_version != new_version: print_d("Config upgrade: %d->%d (%r)" % ( old_version, new_version, func)) func(self, old_version, new_version) def get_version(self): """Get the version of the loaded config file (for testing only) Raises Error if no file was loaded or versioning is disabled. """ if self._version is None: raise Error("Versioning disabled") if self._loaded_version is None: raise Error("No file loaded") return self._loaded_version def register_upgrade_function(self, function): """Register an upgrade function that gets called at each read() if the current config version and the loaded version don't match. Can also be registered after read was called. function(config, old_version: int, new_version: int) -> None """ if self._version is None: raise Error("Versioning disabled") self._upgrade_funcs.append(function) # after read(), so upgrade now if self._loaded_version is not None: self._do_upgrade(function) return function def reset(self, section, option): """Reset the value to the default state""" assert self.defaults is not None try: self._config.remove_option(section, option) except NoSectionError: pass def options(self, section): """Returns a list of options available in the specified section.""" try: options = self._config.options(section) except NoSectionError: if self.defaults: return self.defaults.options(section) raise else: if self.defaults: try: options.extend(self.defaults.options(section)) options = list_unique(options) except NoSectionError: pass return options def get(self, section, option, default=_DEFAULT): """get(section, option[, default]) -> str If default is not given or set, raises Error in case of an error """ try: return self._config.get(section, option) except Error: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.get(section, option) except Error: pass raise return default def gettext(self, *args, **kwargs): value = self.get(*args, **kwargs) # make sure there are no surrogates value.encode("utf-8") return value def getbytes(self, section, option, default=_DEFAULT): try: value = self._config.get(section, option) value = value.encode("utf-8", "surrogateescape") return value except (Error, ValueError) as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getbytes(section, option) except Error: pass raise Error(e) return default def getboolean(self, section, option, default=_DEFAULT): """getboolean(section, option[, default]) -> bool If default is not given or set, raises Error in case of an error """ try: return self._config.getboolean(section, option) except (Error, ValueError) as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getboolean(section, option) except Error: pass raise Error(e) return default def getint(self, section, option, default=_DEFAULT): """getint(section, option[, default]) -> int If default is not give or set, raises Error in case of an error """ try: return int(self._config.getfloat(section, option)) except (Error, ValueError) as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getint(section, option) except Error: pass raise Error(e) return default def getfloat(self, section, option, default=_DEFAULT): """getfloat(section, option[, default]) -> float If default is not give or set, raises Error in case of an error """ try: return self._config.getfloat(section, option) except (Error, ValueError) as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getfloat(section, option) except Error: pass raise Error(e) return default def getstringlist(self, section, option, default=_DEFAULT): """getstringlist(section, option[, default]) -> list If default is not given or set, raises Error in case of an error. Gets a list of strings, using CSV to parse and delimit. """ try: value = self._config.get(section, option) parser = csv.reader( [value], lineterminator='\n', quoting=csv.QUOTE_MINIMAL) try: vals = next(parser) except (csv.Error, ValueError) as e: raise Error(e) return vals except Error as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getstringlist(section, option) except Error: pass raise Error(e) return default def setstringlist(self, section, option, values): """Saves a list of unicode strings using the csv module""" sw = StringIO() values = [str(v) for v in values] writer = csv.writer(sw, lineterminator='\n', quoting=csv.QUOTE_MINIMAL) writer.writerow(values) self.set(section, option, sw.getvalue()) def setlist(self, section, option, values, sep=","): """Saves a list of str using ',' as a separator and \\ for escaping""" values = [str(v) for v in values] joined = join_escape(values, sep) self.set(section, option, joined) def getlist(self, section, option, default=_DEFAULT, sep=","): """Returns a str list saved with setlist()""" try: value = self._config.get(section, option) return split_escape(value, sep) except (Error, ValueError) as e: if default is _DEFAULT: if self.defaults is not None: try: return self.defaults.getlist(section, option, sep=sep) except Error: pass raise Error(e) return default def set(self, section, option, value): """Saves the string representation for the passed value Don't pass unicode, encode first. """ if isinstance(value, bytes): raise TypeError("use setbytes") # RawConfigParser only allows string values but doesn't # scream if they are not (and it only fails before the # first config save..) if not isinstance(value, str): value = str(value) try: self._config.set(section, option, value) except NoSectionError: if self.defaults and self.defaults.has_section(section): self._config.add_section(section) self._config.set(section, option, value) else: raise def settext(self, section, option, value): value = str(value) # make sure there are no surrogates value.encode("utf-8") self.set(section, option, value) def setbytes(self, section, option, value): assert isinstance(value, bytes) value = value.decode("utf-8", "surrogateescape") self.set(section, option, value) def write(self, filename): """Write config to filename. Can raise EnvironmentError """ assert isinstance(filename, fsnative) mkdir(os.path.dirname(filename)) # temporary set the new version for saving if self._version is not None: self.add_section("__config__") self.set("__config__", "version", self._version) try: with atomic_save(filename, "wb") as fileobj: temp = StringIO() self._config.write(temp) data = temp.getvalue().encode("utf-8", "surrogateescape") fileobj.write(data) finally: if self._loaded_version is not None: self.set("__config__", "version", self._loaded_version) def clear(self): """Remove all sections.""" for section in self._config.sections(): self._config.remove_section(section) def is_empty(self): """Whether the config has any sections""" return not self._config.sections() def read(self, filename): """Reads the config from `filename` if the file exists, otherwise does nothing Can raise EnvironmentError, Error. """ try: with open(filename, "rb") as fileobj: fileobj = StringIO( fileobj.read().decode("utf-8", "surrogateescape")) self._config.readfp(fileobj, filename) except (IOError, OSError): return # don't upgrade if we just created a new config if self._version is not None: self._loaded_version = self.getint("__config__", "version", -1) for func in self._upgrade_funcs: self._do_upgrade(func) def has_option(self, section, option): """If the given section exists, and contains the given option""" return self._config.has_option(section, option) or ( self.defaults and self.defaults.has_option(section, option)) def has_section(self, section): """If the given section exists""" return self._config.has_section(section) or ( self.defaults and self.defaults.has_section(section)) def remove_option(self, section, option): """Remove the specified option from the specified section Can raise Error. """ return self._config.remove_option(section, option) def add_section(self, section): """Add a section named section to the instance if it not already exists.""" if not self._config.has_section(section): self._config.add_section(section) class ConfigProxy: """Provides a Config object with a fixed section and a possibility to prefix option names in that section. e.g. it can create a view of the "plugin" section and prefix all options with a plugin name. """ def __init__(self, real_config, section_name, _defaults=True): self._real_config = real_config self._section_name = section_name self.defaults = None if _defaults: self.defaults = self._new_defaults(real_config.defaults) def _new_defaults(self, real_default_config): return ConfigProxy(real_default_config, self._section_name, False) def _option(self, name): """Override if you want to change option names. e.g. prefix them""" return name @classmethod def _init_wrappers(cls): def get_func(name): def method(self, option, *args, **kwargs): config_getter = getattr(self._real_config, name) return config_getter( self._section_name, self._option(option), *args, **kwargs) return method # methods starting with a section arg for name in ["get", "set", "getboolean", "getint", "getfloat", "reset", "settext", "gettext", "getbytes", "setbytes"]: setattr(cls, name, get_func(name)) ConfigProxy._init_wrappers() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1654550871.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/copool.py������������������������������������������������������������0000664�0001750�0001750�00000010234�14247470527�017033� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig, Alexandre Passos # 2014 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. """Manage a pool of routines using Python iterators.""" from gi.repository import GLib class _Routine: def __init__(self, pool, func, funcid, priority, timeout, args, kwargs): self.priority = priority self.timeout = timeout self._source_id = None def wrap(func, funcid, args, kwargs): for value in func(*args, **kwargs): yield True pool.remove(funcid) yield False f = wrap(func, funcid, args, kwargs) self.source_func = f.__next__ @property def paused(self): """If the routine is currently running""" return self._source_id is None def step(self): """Raises StopIteration if the routine has nothing more to do""" return self.source_func() def resume(self): """Resume, if already running do nothing""" if not self.paused: return if self.timeout: self._source_id = GLib.timeout_add( self.timeout, self.source_func, priority=self.priority) else: self._source_id = GLib.idle_add( self.source_func, priority=self.priority) def pause(self): """Pause, if already paused, do nothing""" if self.paused: return GLib.source_remove(self._source_id) self._source_id = None class CoPool: def __init__(self): self.__routines = {} def add(self, func, *args, **kwargs): """Register a routine to run in GLib main loop. func should be a function that returns a Python iterator (e.g. generator) that provides values until it should stop being called. Optional Keyword Arguments: priority -- priority to run at (default GLib.PRIORITY_LOW) funcid -- mutex/removal identifier for this function timeout -- use timeout_add (with given timeout) instead of idle_add (in milliseconds) Only one function with the same funcid can be running at once. Starting a new function with the same ID will stop the old one. If no funcid is given, the function itself is used. The funcid must be usable as a hash key. """ funcid = kwargs.pop("funcid", func) if funcid in self.__routines: remove(funcid) priority = kwargs.pop("priority", GLib.PRIORITY_LOW) timeout = kwargs.pop("timeout", None) routine = _Routine(self, func, funcid, priority, timeout, args, kwargs) self.__routines[funcid] = routine routine.resume() def _get(self, funcid): if funcid in self.__routines: return self.__routines[funcid] raise ValueError("no pooled routine %r" % funcid) def remove(self, funcid): """Stop a registered routine.""" routine = self._get(funcid) routine.pause() del self.__routines[funcid] def remove_all(self): """Stop all running routines.""" for funcid in list(self.__routines.keys()): self.remove(funcid) def pause(self, funcid): """Temporarily pause a registered routine.""" routine = self._get(funcid) routine.pause() def pause_all(self): """Temporarily pause all registered routines.""" for funcid in self.__routines.keys(): self.pause(funcid) def resume(self, funcid): """Resume a paused routine.""" routine = self._get(funcid) routine.resume() def step(self, funcid): """Force this function to iterate once.""" routine = self._get(funcid) return routine.step() # global instance _copool = CoPool() add = _copool.add pause = _copool.pause pause_all = _copool.pause_all remove = _copool.remove remove_all = _copool.remove_all resume = _copool.resume step = _copool.step ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.014269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/cover/���������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016265� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/cover/__init__.py����������������������������������������������������0000664�0001750�0001750�00000000451�14035600052�020374� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from .manager import CoverManager CoverManager �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684322551.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/cover/built_in.py����������������������������������������������������0000644�0001750�0001750�00000016016�14431134367�020457� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2015-2020 Nick Boultbee # 2019 Joschua Gandert # # 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 2 of the License, or # (at your option) any later version. import glob import os.path import re import sre_constants from typing import Text from senf import fsn2text from quodlibet import _ from quodlibet.plugins.cover import CoverSourcePlugin from quodlibet.util.dprint import print_w from quodlibet import config def get_ext(s): return os.path.splitext(s)[1].lstrip('.') def prefer_embedded(): return config.getboolean("albumart", "prefer_embedded", False) def word_regex(s: Text) -> re.Pattern: return re.compile(r'(\b|_)' + s + r'(\b|_)') class EmbeddedCover(CoverSourcePlugin): PLUGIN_ID = "embed-cover" PLUGIN_NAME = _("Embedded album covers") PLUGIN_DESC = _("Uses covers embedded into audio files.") embedded = True @classmethod def group_by(cls, song): # one group per song return song.key @staticmethod def priority(): return 0.85 if prefer_embedded() else 0.7 @property def cover(self): if self.song.has_images: image = self.song.get_primary_image() return image.file if image else None class FilesystemCover(CoverSourcePlugin): PLUGIN_ID = "filesystem-cover" PLUGIN_NAME = _("Filesystem cover") PLUGIN_DESC = _("Uses commonly named images found in common directories " + "alongside the song.") DEBUG = False cover_subdirs = {"scan", "scans", "images", "covers", "artwork"} cover_exts = {"jpg", "jpeg", "png", "gif"} cover_name_regexes = {word_regex(s) for s in ("^folder$", "^cover$", "^front$")} cover_positive_regexes = {word_regex(s) for s in [".+front", "frontcover", "jacket", "albumart", "edited", ".+cover"]} cover_negative_regexes = {word_regex(s) for s in ["back", "inlay", "inset", "inside"]} @classmethod def group_by(cls, song): # in the common case this means we only search once per album return song('~dirname'), song.album_key @property def name(self): return "Filesystem" def __str__(self): return "Filesystem in %s" % (self.group_by(self.song)[0]) @staticmethod def priority(): return 0.80 @property def cover(self): # TODO: Deserves some refactoring if not self.song.is_file: return None base = self.song('~dirname') images = [] def safe_glob(*args, **kwargs): try: return glob.glob(*args, **kwargs) except sre_constants.error: # https://github.com/python/cpython/issues/89973 # old glob would fail with invalid ranges, newer one # handles it correctly. return [] if config.getboolean("albumart", "force_filename"): score = 100 for filename in config.get("albumart", "filename").split(","): # Remove white space to avoid confusion (e.g. "name, name2") filename = filename.strip() escaped_path = os.path.join(glob.escape(base), filename) for path in safe_glob(escaped_path): images.append((score, path)) # So names and patterns at the start are preferred score -= 1 if not images: entries = [] try: entries = os.listdir(base) except EnvironmentError: print_w("Can't list album art directory %s" % base) fns = [] for entry in entries: lentry = entry.lower() if get_ext(lentry) in self.cover_exts: fns.append((None, entry)) if lentry in self.cover_subdirs: subdir = os.path.join(base, entry) sub_entries = [] try: sub_entries = os.listdir(subdir) except EnvironmentError: pass for sub_entry in sub_entries: lsub_entry = sub_entry.lower() if get_ext(lsub_entry) in self.cover_exts: fns.append((entry, sub_entry)) for sub, fn in fns: dec_lfn = os.path.splitext(fsn2text(fn))[0].lower() score = 0 # check for the album label number labelid = self.song.get("labelid", "").lower() if labelid and labelid in dec_lfn: score += 20 # Track-related keywords values = set(self.song.list("~people")) | {self.song("album")} lowers = [value.lower().strip() for value in values if len(value) > 1] total_terms = sum(len(s.split()) for s in lowers) total_words = len([word for word in dec_lfn.split() if len(word) > 1]) # Penalise for many extra words in filename (wrong file?) length_penalty = (- int((total_words - 1) / total_terms) if total_terms else 0) # Matching tag values are very good score += 3 * sum([value in dec_lfn for value in lowers]) # Well known names matching exactly (folder.jpg) score += 4 * sum(r.search(dec_lfn) is not None for r in self.cover_name_regexes) # Generic keywords score += 2 * sum(r.search(dec_lfn) is not None for r in self.cover_positive_regexes) score -= 3 * sum(r.search(dec_lfn) is not None for r in self.cover_negative_regexes) sub_text = f" (in {sub!r})" if sub else "" if self.DEBUG: print(f"[{self.song('~~people~title')}]: " f"Album art {fn!r}{sub_text} " f"scores {score} ({length_penalty})") score += length_penalty # Let's only match if we're quite sure. # This allows other sources to kick in if score > 2: if sub is not None: fn = os.path.join(sub, fn) images.append((score, os.path.join(base, fn))) images.sort(reverse=True) for score, path in images: # could be a directory if not os.path.isfile(path): continue try: return open(path, "rb") except IOError: print_w("Failed reading album art \"%s\"" % path) return None ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/cover/http.py��������������������������������������������������������0000644�0001750�0001750�00000010154�14455205526�017630� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2016-2023 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gio, GLib, Soup from quodlibet.plugins.cover import CoverSourcePlugin from quodlibet.util.http import HTTPRequest, download_json from quodlibet.util import print_w class HTTPDownloadMixin: def download(self, message): request = HTTPRequest(message, self.cancellable) request.connect('sent', self._download_sent) request.connect('received', self._download_received) request.connect('failure', self._download_failure) request.send() def _download_sent(self, request, message): status = message.get_property('status-code') if not 200 <= status < 400: request.cancel() return self.fail('Bad HTTP code {0}'.format(status)) target = Gio.file_new_for_path(self.cover_path) flags = Gio.FileCreateFlags.NONE def replaced(cover_file, task, data): try: ostr = cover_file.replace_finish(task) request.provide_target(ostr) request.connect('receive-failure', self._receive_fail, target) request.receive() except GLib.GError: request.cancel() return self.fail('Cannot open cover file') target.replace_async(None, True, flags, GLib.PRIORITY_DEFAULT, self.cancellable, replaced, None) def _download_received(self, request, ostream): try: ostream.close(None) except GLib.GError as e: print_w(f"Got {e!r} trying to close handle after download") self.emit('fetch-success', self.cover) def _receive_fail(self, request, exception, gfile): def deleted(gfile, task, data): try: gfile.delete_finish(task) except GLib.GError: print_w('Could not clean up cover which failed to download') try: request.ostream.close(None) except GLib.GError as e: print_w(f"Got {e!r} trying to close handle during failure") gfile.delete_async(GLib.PRIORITY_DEFAULT, None, deleted, None) def _download_failure(self, request, exception): try: self.fail(exception.message or ' '.join(exception.args)) except AttributeError: self.fail("Download error (%s)" % exception) class ApiCoverSourcePlugin(CoverSourcePlugin, HTTPDownloadMixin): MIN_DIMENSION = 300 """Minimum width / height in pixels for an image to be used""" @property def url(self): """The URL to the image, if remote""" return None def search(self): if not self.url: return self.emit('search-complete', []) msg = Soup.Message.new('GET', self.url) download_json(msg, self.cancellable, self._handle_search_response, None) def _handle_search_response(self, message, json_dict, data=None): self.emit('search-complete', []) def fetch_cover(self): if not self.url: return self.fail(f"Not enough data to get cover from {type(self).__name__}") def search_complete(self, res): self.disconnect(sci) if res: self.download(Soup.Message.new('GET', res[0]['cover'])) else: return self.fail('No cover was found') sci = self.connect('search-complete', search_complete) self.search() def _album_artists_for(self, song): """Returns a comma-separated list of artists indicating the "main" artists from the song's album""" people = [song.comma(key) for key in ['albumartist', 'artist', 'composer', 'conductor', 'performer']] people = list(filter(None, people)) return people[0] if people else None def escape_query_value(s): return GLib.Uri.escape_string(s, None, True) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/cover/manager.py�����������������������������������������������������0000644�0001750�0001750�00000026055�14310167056�020265� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2014-2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from itertools import chain from gi.repository import GObject from quodlibet import _ from quodlibet.formats import AudioFile from quodlibet.plugins import PluginManager, PluginHandler from quodlibet.qltk.notif import Task from quodlibet.util.cover import built_in from quodlibet.util import print_d from quodlibet.util.thread import call_async from quodlibet.util.thumbnails import get_thumbnail_from_file from quodlibet.plugins.cover import CoverSourcePlugin class CoverPluginHandler(PluginHandler): """A plugin handler for CoverSourcePlugin implementation""" def __init__(self, use_built_in=True): self.providers = set() if use_built_in: self.built_in = {built_in.EmbeddedCover, built_in.FilesystemCover} else: self.built_in = set() def plugin_handle(self, plugin): return issubclass(plugin.cls, CoverSourcePlugin) def plugin_enable(self, plugin): self.providers.add(plugin) print_d(f"Registered {plugin.cls.__name__} cover source") def plugin_disable(self, plugin): self.providers.remove(plugin) print_d(f"Unregistered {plugin.cls.__name__} cover source") @property def sources(self): """Yields all active CoverSourcePlugin classes sorted by priority""" sources = chain((p.cls for p in self.providers), self.built_in) for p in sorted(sources, reverse=True, key=lambda x: x.priority()): yield p class CoverManager(GObject.Object): __gsignals__ = { # ([AudioFile]), emitted if the cover for any songs might have changed 'cover-changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), # Covers were found for the songs 'covers-found': (GObject.SignalFlags.RUN_LAST, None, (object, object)), # All searches were submitted, and success by provider is sent 'searches-complete': (GObject.SignalFlags.RUN_LAST, None, (object,)) } plugin_handler = None def __init__(self, use_built_in=True): super().__init__() self.plugin_handler = CoverPluginHandler(use_built_in) def init_plugins(self): """Register the cover sources plugin handler with the global plugin manager. """ PluginManager.instance.register_handler(self.plugin_handler) @property def sources(self): return self.plugin_handler.sources def cover_changed(self, songs): """Notify the world that the artwork for some songs or collections containing that songs might have changed (For example a new image was added to the folder or a new embedded image was added) This will invalidate all caches and will notify others that they have to re-fetch the cover and do a display update. """ self.emit("cover-changed", songs) def acquire_cover(self, callback, cancellable, song): """ Try to get covers from all cover sources until a cover is found. * callback(found, result) is the function which will be called when this method completes its job. * cancellable – Gio.Cancellable which will interrupt the search. The callback won't be called when the operation is cancelled. """ sources = self.sources def success(source, result): name = source.__class__.__name__ print_d(f"Successfully got cover from {name}") source.disconnect_by_func(success) source.disconnect_by_func(failure) if not cancellable or not cancellable.is_cancelled(): callback(True, result) def failure(source, msg): name = source.__class__.__name__ print_d(f"Didn't get cover from {name}: {msg}") source.disconnect_by_func(success) source.disconnect_by_func(failure) if not cancellable or not cancellable.is_cancelled(): run() def run(): try: provider = next(sources)(song, cancellable) except StopIteration: return callback(False, None) # No cover found cover = provider.cover if cover: name = provider.__class__.__name__ print_d(f"Found local cover from {name}: {cover}") callback(True, cover) else: provider.connect('fetch-success', success) provider.connect('fetch-failure', failure) provider.fetch_cover() if not cancellable or not cancellable.is_cancelled(): run() def acquire_cover_sync(self, song, embedded=True, external=True): """Gets *cached* cover synchronously. As CoverSource fetching functionality is asynchronous it is only possible to check for already fetched cover. """ return self.acquire_cover_sync_many([song], embedded, external) def acquire_cover_sync_many(self, songs, embedded=True, external=True): """Same as acquire_cover_sync but returns a cover for multiple images""" for plugin in self.sources: if not embedded and plugin.embedded: continue if not external and not plugin.embedded: continue groups = {} for song in songs: group = plugin.group_by(song) or '' groups.setdefault(group, []).append(song) # sort both groups and songs by key, so we always get # the same result for the same set of songs for key, group in sorted(groups.items()): song = sorted(group, key=lambda s: s.key)[0] cover = plugin(song).cover if cover: return cover def get_cover(self, song): """Returns a cover file object for one song or None. Compared to acquire_cover_sync() this respects the prefer_embedded setting. """ return self.get_cover_many([song]) def get_cover_many(self, songs): """Returns a cover file object for many songs or None. Returns the first found image for a group of songs. It tries to return the same cover for the same set of songs. """ return self.acquire_cover_sync_many(songs) def get_pixbuf_many(self, songs, width, height): """Returns a Pixbuf which fits into the boundary defined by width and height or None. Uses the thumbnail cache if possible. """ fileobj = self.get_cover_many(songs) if fileobj is None: return return get_thumbnail_from_file(fileobj, (width, height)) def get_pixbuf(self, song, width, height): """see get_pixbuf_many()""" return self.get_pixbuf_many([song], width, height) def get_pixbuf_many_async(self, songs, width, height, cancel, callback): """Async variant; callback gets called with a pixbuf or not called in case of an error. cancel is a Gio.Cancellable. The callback will be called in the main loop. """ fileobj = self.get_cover_many(songs) if fileobj is None: return call_async(get_thumbnail_from_file, cancel, callback, args=(fileobj, (width, height))) def search_cover(self, cancellable, songs): """Search for all the covers applicable to `songs` across all providers Every successful image result emits a 'covers-found' signal (unless cancelled).""" sources = [source for source in self.sources if not source.embedded] processed = {} all_groups = {} task = Task(_("Cover Art"), _("Querying album art providers"), stop=cancellable.cancel) def finished(provider, success): processed[provider] = success total = self._total_groupings(all_groups) frac = len(processed) / total print_d(f"Got result for {provider} ({len(processed)} / {total} group(s))") task.update(frac) if frac >= 1: task.finish() self.emit('searches-complete', processed) def search_complete(provider, results): name = provider.name if not results: print_d(f"No covers from {name}") finished(provider, False) return finished(provider, True) if not (cancellable and cancellable.is_cancelled()): covers = {CoverData(url=res['cover'], source=name, dimensions=res.get('dimensions', None)) for res in results} self.emit('covers-found', provider, covers) provider.disconnect_by_func(search_complete) def failure(provider, result): finished(provider, False) name = provider.__class__.__name__ print_d(f"Failed to get cover from {name!r} ({result})") provider.disconnect_by_func(failure) def song_groups(songs, sources): all_groups = {} for plugin in sources: groups = {} for song in songs: group = plugin.group_by(song) or '' groups.setdefault(group, []).append(song) all_groups[plugin] = groups return all_groups all_groups = song_groups(songs, sources) print_d(f"Got {self._total_groupings(all_groups)} plugin groupings") for plugin_cls, groups in all_groups.items(): for key, group in sorted(groups.items()): song = sorted(group, key=lambda s: s.key)[0] artists = {s.comma('artist') for s in group} if len(artists) > 1: print_d(f"{len(artists)} artist groups in {key} " "- probably a compilation. " "Using provider to search for compilation") song = AudioFile(song) try: del song['artist'] except KeyError: # Artist(s) from other grouped songs, never mind. pass provider = plugin_cls(song) provider.connect('search-complete', search_complete) provider.connect('fetch-failure', failure) provider.search() return all_groups def _total_groupings(self, groups): return sum(len(g) for g in groups.values()) class CoverData(GObject.GObject): """Structured data for results from cover searching""" def __init__(self, url, source=None, dimensions=None): super().__init__() self.url = url self.dimensions = dimensions self.source = source def __repr__(self): return f"CoverData<url={self.url} @ {self.dimensions}>" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/dbusutils.py���������������������������������������������������������0000664�0001750�0001750�00000025371�14231604332�017550� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012, 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import xml.etree.ElementTree as ET import dbus import dbus.service def dbus_unicode_validate(text): """Takes a unicode string and replaces all invalid codepoints that would lead to errors if passed to dbus""" if isinstance(text, bytes): text = text.decode("utf-8") # https://bugs.freedesktop.org/show_bug.cgi?id=40817 def valid(c): return (c < 0x110000 and (c & 0xFFFFF800) != 0xD800 and (c < 0xFDD0 or c > 0xFDEF) and (c & 0xFFFE) != 0xFFFE) cps = [] for c in map(ord, text): if valid(c): cps.append(c) else: cps.append(0xFFFD) return u"".join(map(chr, cps)) def list_spec_properties(spec): """Parse a property spec and return a dict: {'Metadata': {'access': 'read', 'type': 'a{sv}', 'emit': 'true'} 'access' can be: read/write/readwrite 'type' is the dbus data type (dbus.Signature instance) 'emit' can be true/false/invalidates (see dbus spec) """ assert isinstance(spec, str) ANNOTATION_EMITS = "org.freedesktop.DBus.Property.EmitsChangedSignal" def get_emit(element, fallback): for anno in element.findall("annotation"): if anno.attrib["name"] == ANNOTATION_EMITS: emit = anno.attrib["value"] break else: emit = fallback return emit root = ET.fromstring( b'<?xml version="1.0" encoding="UTF-8"?><props>' + spec.encode("utf-8") + b'</props>') props = {} root_emit = get_emit(root, "true") for element in root: if element.tag != "property": continue attrs = element.attrib attrs["emit"] = get_emit(element, root_emit) attrs["type"] = dbus.Signature(attrs["type"]) props[attrs.pop("name")] = attrs return props def filter_property_spec(spec, wl=None, bl=None): """Remove properties based on a white list or black list.""" assert isinstance(spec, str) if wl and bl: raise ValueError if not wl and not bl: return spec root = ET.fromstring( b'<?xml version="1.0" encoding="UTF-8"?><props>' + spec.encode("utf-8") + b'</props>') if wl: to_rm = lambda e: e.attrib["name"] not in wl elif bl: to_rm = lambda e: e.attrib["name"] in bl strs = [] for element in root: if element.tag != "property" or not to_rm(element): strs.append(ET.tostring(element, encoding="unicode").strip()) return "\n".join(strs) TYPE_MAP = { "b": dbus.Boolean, "n": dbus.Int16, "i": dbus.Int32, "x": dbus.Int64, "q": dbus.UInt16, "u": dbus.UInt32, "t": dbus.UInt64, "d": dbus.Double, "o": dbus.ObjectPath, "g": dbus.Signature, "v": lambda x: x, } def apply_signature(value, sig, utf8_strings=False): """Casts basic types to the right dbus types and packs them into containers with the right signature, so they get validated on sending.""" # dbus properties are variant, but have a signature defined, so # we have to convert manually here. if sig in TYPE_MAP: return TYPE_MAP[sig](value) elif sig.startswith("a{"): return dbus.Dictionary(value, signature=sig[2:-1]) elif sig.startswith("a("): return dbus.Struct(value, signature=sig[2:-1]) elif sig.startswith("a"): return dbus.Array(value, signature=sig[1:]) elif sig == "s": if isinstance(value, bytes): value = value.decode("utf-8") return dbus.String(value) else: return TYPE_MAP[sig](value) # Unknown type, just return as is return value class DBusIntrospectable: """Simply collects all introspection data from other mixins and provides the Introspect DBus method returning all combined. All classes need to call set_introspection with their interface and provided signals, properties, methods in the introspection xml format. The dbus bindings already provide a Introspect method, but it doesn't understand properties, also having them in text format in the class is a nice documentation. """ IFACE = "org.freedesktop.DBus.Introspectable" ISPEC = """ <method name="Introspect"> <arg type="s" name="xml_data" direction="out"/> </method> """ def __init__(self): self.__ispec = {} self.set_introspection(DBusIntrospectable.IFACE, DBusIntrospectable.ISPEC) def set_introspection(self, interface, introspection): self.__ispec.setdefault(interface, []).append(introspection) @dbus.service.method(IFACE) def Introspect(self): parts = [] parts.append("<node>") for iface, intros in self.__ispec.items(): parts.append("<interface name=\"%s\">" % iface) parts.extend(intros) parts.append("</interface>") parts.append("</node>") return "\n".join(parts) class DBusProperty: """A mixin for dbus.Object classes to support dbus properties. Register properties by passing the XML introspection to 'set_properties'. The class needs to provide 'get/set_property'. In case the base Object is a FallbackObject, 'get/set_property' also need to handle an additional relative path parameter. Whenever a property changes, 'emit_properties_changed' needs to be called (except if the annotations disable it). In case of FallbackObject, with a relative path to the real object (defaults to the main one). """ IFACE = "org.freedesktop.DBus.Properties" ISPEC = """ <method name="Get"> <arg type="s" name="interface_name" direction="in"/> <arg type="s" name="property_name" direction="in"/> <arg type="v" name="value" direction="out"/> </method> <method name="GetAll"> <arg type="s" name="interface_name" direction="in"/> <arg type="a{sv}" name="properties" direction="out"/> </method> <method name="Set"> <arg type="s" name="interface_name" direction="in"/> <arg type="s" name="property_name" direction="in"/> <arg type="v" name="value" direction="in"/> </method> <signal name="PropertiesChanged"> <arg type="s" name="interface_name"/> <arg type="a{sv}" name="changed_properties"/> <arg type="as" name="invalidated_properties"/> </signal>""" def __init__(self): self.__props = {} self.__impl = {} self.set_introspection(DBusProperty.IFACE, DBusProperty.ISPEC) def set_properties(self, interface, ispec, bl=None, wl=None): """Register properties and set instrospection for the given property spec. Provide a black list or white list, for optional, not implemented properties.""" ispec = filter_property_spec(ispec, wl=wl, bl=bl) self.__props[interface] = list_spec_properties(ispec) self.__impl.setdefault(interface, []) self.set_introspection(interface, ispec) def get_properties(self, interface): """Returns a list of (interface, property) for all properties of the specified interface and subinterfaces""" result = [(interface, p) for p in self.__props[interface].keys()] for sub in self.__impl[interface]: result.extend(self.get_properties(sub)) return result def get_value(self, interface, prop, path="/"): """Returns the value of a property""" interface = self.get_interface(interface, prop) if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: value = self.get_property(interface, prop, path) else: value = self.get_property(interface, prop) prop_sig = self.__props[interface][prop]["type"] return apply_signature(value, prop_sig) def get_interface(self, interface, prop): """Returns the real interface that implements the property""" if prop in self.__props[interface]: return interface for sub in self.__impl[interface]: if self.get_interface(sub, prop): return sub def implement_interface(self, iface, sub_iface): """Set a sub interface. All actions on that interface will check the sub interface in case the property is not found.""" self.__props.setdefault(iface, {}) self.__props.setdefault(sub_iface, {}) self.__impl.setdefault(iface, []).append(sub_iface) def emit_properties_changed(self, interface, properties, path="/"): """Emits PropertiesChanged for the specified properties""" combos = {} for prop in properties: iface = self.get_interface(interface, prop) if iface is None: raise ValueError("Property %s not registered" % prop) combos.setdefault(iface, []).append(prop) for iface, props in combos.items(): values = {} inval = [] for prop in props: emit = self.__props[iface][prop]["emit"] if emit == "false": raise ValueError("Can't emit changed signal for %s" % prop) elif emit == "true": values[prop] = self.get_value(iface, prop, path) elif emit == "invalidates": inval.append(prop) if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: self.PropertiesChanged(iface, values, inval, rel=path) else: self.PropertiesChanged(iface, values, inval) @dbus.service.method(dbus_interface=IFACE, in_signature="ss", out_signature="v", rel_path_keyword="path") def Get(self, interface, prop, path): return self.get_value(interface, prop, path) @dbus.service.method(dbus_interface=IFACE, in_signature="ssv", out_signature="", rel_path_keyword="path") def Set(self, interface, prop, value, path): interface = self.get_interface(interface, prop) if self.SUPPORTS_MULTIPLE_OBJECT_PATHS: self.set_property(interface, prop, value, path) else: self.set_property(interface, prop, value) @dbus.service.method(dbus_interface=IFACE, in_signature="s", out_signature="a{sv}", rel_path_keyword="path") def GetAll(self, interface, path): values = {} for iface, prop in self.get_properties(interface): values[prop] = self.get_value(iface, prop, path) return values @dbus.service.signal(IFACE, signature="sa{sv}as", rel_path_keyword="rel") def PropertiesChanged(self, interface, changed, invalidated, rel=""): pass �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1665307075.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/dprint.py������������������������������������������������������������0000644�0001750�0001750�00000020024�14320510703�017013� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011,2013,2016 Christoph Reiter # 2020 Nick Boultbee # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import import sys import time import os import traceback import re import logging import errno from senf import print_, path2fsn, fsn2text, fsnative, \ supports_ansi_escape_codes from quodlibet import const from . import logging as ql_logging class Color: NO_COLOR = '\033[0m' MAGENTA = '\033[95m' BLUE = '\033[94m' CYAN = '\033[96m' WHITE = '\033[97m' YELLOW = '\033[93m' GREEN = '\033[92m' RED = '\033[91m' BLACK = '\033[90m' GRAY = '\033[2m' class Colorise: @classmethod def __reset(cls, text): return text + Color.NO_COLOR @classmethod def magenta(cls, text): return cls.__reset(Color.MAGENTA + text) @classmethod def blue(cls, text): return cls.__reset(Color.BLUE + text) @classmethod def cyan(cls, text): return cls.__reset(Color.CYAN + text) @classmethod def white(cls, text): return cls.__reset(Color.WHITE + text) @classmethod def yellow(cls, text): return cls.__reset(Color.YELLOW + text) @classmethod def green(cls, text): return cls.__reset(Color.GREEN + text) @classmethod def red(cls, text): return cls.__reset(Color.RED + text) @classmethod def black(cls, text): return cls.__reset(Color.BLACK + text) @classmethod def bold(cls, text): return cls.__reset('\033[1m' + text) @classmethod def gray(cls, text): return cls.__reset(Color.GRAY + text) _ANSI_ESC_RE = re.compile(u"(\x1b\\[\\d\\d?m)") _ANSI_ESC_RE_B = re.compile(b"(\x1b\\[\\d\\d?m)") def strip_color(text): """Strip ansi escape codes from the passed text""" if isinstance(text, bytes): return _ANSI_ESC_RE_B.sub(b"", text) return _ANSI_ESC_RE.sub(u"", text) def frame_info(level=0): """Return a short string describing the current stack frame which can be used for debug messages. level defines which frame should be used. 0 means the caller, 1 the caller of the caller etc. """ info = "" # The frame of the calling function if hasattr(sys, "_getframe"): frame = sys._getframe() else: return "" for i in range(level + 1): try: frame = frame.f_back except AttributeError: break f_code = frame.f_code co_name = f_code.co_name co_varnames = f_code.co_varnames # the calling function got arguments if co_varnames and co_varnames[0] in frame.f_locals: # the first one could be the class cls = frame.f_locals[co_varnames[0]] # If it's an instance get the class if not hasattr(cls, '__name__'): cls = cls.__class__ # the arg has an attr that is named like the function if hasattr(cls, co_name): info = cls.__name__ # else, get the module name if not info: info = frame.f_globals.get("__name__", "") info = str(info) # append the function/method name if info: info += "." + co_name return info def _should_write_to_file(file_): """In Windows UI mode we don't have a working stdout/stderr. With Python 2 sys.stdout.fileno() returns a negative fd, with Python 3 sys.stdout is None. """ if file_ is None: return False try: return file_.fileno() >= 0 except (IOError, AttributeError): return True def _supports_ansi_escape_codes(file_): assert file_ is not None try: return supports_ansi_escape_codes(file_.fileno()) except (IOError, AttributeError): return False def _print_message(string, custom_context, debug_only, prefix, color, logging_category, start_time=time.time()): if not isinstance(string, (str, fsnative)): string = str(string) context = frame_info(2) # strip the package name if context.count(".") > 1: context = context.split(".", 1)[-1] if custom_context: context = "%s(%r)" % (context, custom_context) timestr = ("%08.3f" % (time.time() - start_time))[-9:] info = "%s: [%s] %s:" % ( getattr(Colorise, color)(prefix), Colorise.magenta(timestr), Colorise.blue(context)) lines = string.splitlines() if len(lines) > 1: string = os.linesep.join([info] + [" " * 4 + l for l in lines]) else: string = info + " " + lines[0] if not debug_only or const.DEBUG: file_ = sys.stderr if _should_write_to_file(file_): if not _supports_ansi_escape_codes(file_): string = strip_color(string) try: print_(string, file=file_, flush=True) except (IOError, OSError) as e: if e.errno == errno.EIO: # When we are started in a terminal with --debug and the # terminal gets closed we lose stdio/err before we stop # printing debug message, resulting in EIO and aborting the # exit process -> Just ignore it. pass else: raise ql_logging.log(strip_color(string), logging_category) def format_exception(etype, value, tb, limit=None): """Returns a list of str""" result_lines = traceback.format_exception(etype, value, tb, limit) return [fsn2text(path2fsn(l)) for l in result_lines] def format_exception_only(etype, value): """Returns a list of str""" result_lines = traceback.format_exception_only(etype, value) return [fsn2text(path2fsn(l)) for l in result_lines] def format_exc(limit=None): """Returns str""" etype, value, tb = sys.exc_info() return u''.join(format_exception(etype, value, tb, limit)) def extract_tb(*args, **kwargs): """Returns a list of tuples containing (fsnative, int, str, str) """ return traceback.extract_tb(*args, **kwargs) def print_exc(exc_info=None, context=None): """Prints the stack trace of the current exception or the passed one. Depending on the configuration will either print a short summary or the whole stacktrace. """ if exc_info is None: exc_info = sys.exc_info() etype, value, tb = exc_info if const.DEBUG: string = u"".join(format_exception(etype, value, tb)) else: # try to get a short error message pointing at the cause of # the exception text = u"".join(format_exception_only(etype, value)) try: filename, lineno, name, line = extract_tb(tb)[-1] except IndexError: # no stack string = text else: string = u"%s:%s:%s: %s" % ( fsn2text(path2fsn(os.path.basename(filename))), lineno, name, text) _print_message(string, context, False, "E", "red", "errors") def print_d(string, context=None): """Print debugging information.""" _print_message(string, context, True, "D", "green", "debug") def print_w(string, context=None): """Print warnings""" _print_message(string, context, True, "W", "yellow", "warnings") def print_e(string, context=None): """Print errors""" _print_message(string, context, False, "E", "red", "errors") class PrintHandler(logging.Handler): """Converts logging records to our logging format""" def emit(self, record): print_func = { 'DEBUG': print_d, 'INFO': print_d, 'WARNING': print_w, 'ERROR': print_e, 'CRITICAL': print_e, }.get(record.levelname, print_d) exc_info = record.exc_info context = "%s.%s" % (record.module, record.funcName) record.exc_info = None print_func(self.format(record), context=context) if exc_info is not None: print_exc(record.exc_info, context=context) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/enum.py��������������������������������������������������������������0000664�0001750�0001750�00000003010�14035600052�016455� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. def enum(cls): """Class decorator for enum types:: @enum class SomeEnum(int): FOO = 0 BAR = 1 Result is an int subclass and all attributes are instances of it. Each subclass has a property `values` referring to *all* known instances. """ type_ = cls.__bases__[0] d = dict(cls.__dict__) new_type = type(cls.__name__, (type_,), d) new_type.__module__ = cls.__module__ map_ = {} for key, value in d.items(): if key.upper() == key: value_instance = new_type(value) setattr(new_type, key, value_instance) map_[value] = key new_type.values = set(map_.keys()) def value_of(cls, s, default=None): for v in cls.values: if v == s: return v if default is not None: return default raise ValueError("Can't find %s (try %s)" % (s, cls.values)) new_type.value_of = classmethod(value_of) def repr_(self): name = type(self).__name__ try: return "%s.%s" % (name, map_[self]) except KeyError: return "%s(%s)" % (name, self) setattr(new_type, "__repr__", repr_) return new_type ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/environment.py�������������������������������������������������������0000664�0001750�0001750�00000005151�14035600052�020065� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Varisour function for figuring out which platform wa are running on and under which environment. """ import os import sys import ctypes import configparser import fnmatch from gi.repository import GLib, Gio def _dbus_name_owned(name): """Returns True if the dbus name has an owner""" if not is_linux(): return False return dbus_name_owned(name) def is_flatpak(): """If we are running in a flatpak""" return is_linux() and os.path.exists("/.flatpak-info") def matches_flatpak_runtime(pattern: str) -> bool: """Pass a fnmatch pattern for matching the flatpak runtime ID""" if not is_linux(): return False config = configparser.ConfigParser() try: with open("/.flatpak-info", "r", encoding="utf-8") as f: config.read_file(f) runtime = config.get("Application", "runtime") except (OSError, configparser.Error): return False return fnmatch.fnmatchcase(runtime, pattern) def is_plasma(): """If we are running under plasma""" return _dbus_name_owned("org.kde.plasmashell") def is_unity(): """If we are running under Ubuntu/Unity""" return _dbus_name_owned("com.canonical.Unity.Launcher") def is_enlightenment(): """If we are running under Enlightenment""" return _dbus_name_owned("org.enlightenment.wm.service") def is_linux(): """If we are on Linux (or similar)""" return not is_windows() and not is_osx() def is_windows(): """If we are running under Windows or Wine""" return os.name == "nt" def is_wine(): """If we are running under Wine""" if not is_windows(): return False try: ctypes.cdll.ntdll.wine_get_version except AttributeError: return False else: return True def is_osx(): """If we are running under OS X""" return sys.platform == "darwin" def dbus_name_owned(name): """Returns True if the dbus name has an owner""" BUS_DAEMON_NAME = 'org.freedesktop.DBus' BUS_DAEMON_PATH = '/org/freedesktop/DBus' BUS_DAEMON_IFACE = 'org.freedesktop.DBus' try: bus = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, BUS_DAEMON_NAME, BUS_DAEMON_PATH, BUS_DAEMON_IFACE, None) return bus.NameHasOwner('(s)', name) except GLib.Error: return False �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/fifo.py��������������������������������������������������������������0000644�0001750�0001750�00000015565�14266344767�016504� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # 2017-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import signal import stat from tempfile import mkstemp try: import fcntl except ImportError: pass from gi.repository import GLib from senf import fsn2bytes from quodlibet import print_d, print_e from quodlibet.util.path import mkdir FIFO_TIMEOUT = 10 """time in seconds until we give up writing/reading""" class FIFOError(Exception): pass def _sigalrm_timeout(*args): raise TimeoutError def _write_fifo(fifo_path, data): """Writes the data to the FIFO or raises `FIFOError`""" assert isinstance(data, bytes) # This will raise if the FIFO doesn't exist or there is no reader try: fifo = os.open(fifo_path, os.O_WRONLY | os.O_NONBLOCK) except OSError: try: os.unlink(fifo_path) except OSError: pass raise else: try: os.close(fifo) except OSError: pass try: signal.signal(signal.SIGALRM, _sigalrm_timeout) signal.alarm(FIFO_TIMEOUT) with open(fifo_path, "wb") as f: signal.signal(signal.SIGALRM, signal.SIG_IGN) f.write(data) except (OSError, TimeoutError): # Unable to write to the fifo. Removing it. try: os.unlink(fifo_path) except OSError: pass raise FIFOError(f"Couldn't write to fifo {fifo_path!r}") def split_message(data): """Split incoming data in pairs of (command, FIFO path or `None`) This supports two data formats: Newline-separated commands without a return FIFO path. and "NULL<command>NULL<fifo-path>NULL" Args: data (bytes) Returns: Tuple[bytes, bytes] Raises: ValueError """ assert isinstance(data, bytes) while data: elem, null, data = data.partition(b"\x00") if elem: # newline-separated commands yield from ((line, None) for line in elem.splitlines()) data = null + data else: # NULL<command>NULL<fifo-path>NULL cmd, fifo_path, data = data.split(b"\x00", 2) yield (cmd, fifo_path) def write_fifo(fifo_path, data): """Writes the data to the FIFO and returns a response. Args: fifo_path (pathlike) data (bytes) Returns: bytes Raises: FIFOError """ assert isinstance(data, bytes) fd, filename = mkstemp() try: os.close(fd) os.unlink(filename) # mkfifo fails if the file exists, so this is safe. os.mkfifo(filename, 0o600) _write_fifo( fifo_path, b"\x00".join([b"", data, fsn2bytes(filename, None), b""]) ) try: signal.signal(signal.SIGALRM, _sigalrm_timeout) signal.alarm(FIFO_TIMEOUT) with open(filename, "rb") as h: signal.signal(signal.SIGALRM, signal.SIG_IGN) return h.read() except TimeoutError: # In case the main instance deadlocks we can write to it, but # reading will time out. Assume it is broken and delete the # fifo. try: os.unlink(fifo_path) except OSError: pass raise FIFOError("Timeout reached") except OSError as e: raise FIFOError(*e.args) finally: try: os.unlink(filename) except OSError: pass def fifo_exists(fifo_path): """Returns whether a FIFO exists (and is writeable). Args: fifo_path (pathlike) Returns: bool """ # https://github.com/quodlibet/quodlibet/issues/1131 # FIXME: There is a race where control() creates a new file # instead of writing to the FIFO, confusing the next QL instance. # Remove non-FIFOs here for now. try: if not stat.S_ISFIFO(os.stat(fifo_path).st_mode): print_d("%r not a FIFO. Removing it." % fifo_path) os.remove(fifo_path) except OSError: pass return os.path.exists(fifo_path) class FIFO: """Creates and reads from a FIFO""" _source_id = None def __init__(self, path, callback): """ Args: path (pathlike) callback (Callable[[bytes], None]) """ self._callback = callback self._path = path def destroy(self): """After destroy() the callback will no longer be called and the FIFO can no longer be used. Can be called multiple times. """ if self._source_id is not None: GLib.source_remove(self._source_id) self._source_id = None try: os.unlink(self._path) except OSError: pass def open(self, ignore_lock=False): """Create the FIFO and listen to it. Raises: FIFOError in case another process is already using it. """ from quodlibet import qltk mkdir(os.path.dirname(self._path)) try: os.mkfifo(self._path, 0o600) except OSError: # maybe exists, we'll fail below otherwise pass try: fifo = os.open(self._path, os.O_NONBLOCK) except OSError: return while True: try: fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB) except InterruptedError: # EINTR continue except BlockingIOError: # EWOULDBLOCK if not ignore_lock: raise FIFOError("fifo already locked") except OSError as e: print_d(f"fifo locking failed: {e!r}") break try: f = os.fdopen(fifo, "rb", 4096) except OSError as e: print_e(f"Couldn't open FIFO ({e!r})") else: self._source_id = qltk.io_add_watch( f, GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP, self._process, ) def _process(self, source, condition): if condition in {GLib.IO_ERR, GLib.IO_HUP}: self.open(ignore_lock=True) return False while True: try: data = source.read() except InterruptedError: # EINTR continue except (BlockingIOError, PermissionError): # EWOULDBLOCK, EACCES return True except OSError: self.open(ignore_lock=True) return False break if not data: self.open(ignore_lock=True) return False self._callback(data) return True �������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/http.py��������������������������������������������������������������0000644�0001750�0001750�00000017514�14455205526�016521� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import json from typing import Optional, Any, Callable from gi.repository import Soup, Gio, GLib, GObject from gi.repository.GObject import ParamFlags, SignalFlags from quodlibet.const import VERSION, WEBSITE from quodlibet.util import print_d, print_w PARAM_READWRITECONSTRUCT = \ ParamFlags.CONSTRUCT_ONLY | ParamFlags.READABLE | ParamFlags.WRITABLE class HTTPRequest(GObject.Object): """ Class encapsulating a single HTTP request. These are meant to be sent and received only once. Behaviour is undefined otherwise. """ __gsignals__ = { # Successes 'sent': (SignalFlags.RUN_LAST, None, (Soup.Message,)), 'received': (SignalFlags.RUN_LAST, None, (Gio.OutputStream,)), # Failures 'send-failure': (SignalFlags.RUN_LAST, None, (object,)), 'receive-failure': (SignalFlags.RUN_LAST, None, (object,)), # Common failure signal which will be emitted when either of above # failure signals are. 'failure': (SignalFlags.RUN_LAST, None, (object,)), } message = GObject.Property(type=Soup.Message, flags=PARAM_READWRITECONSTRUCT) cancellable = GObject.Property(type=Gio.Cancellable, flags=PARAM_READWRITECONSTRUCT) istream = GObject.Property(type=Gio.InputStream, default=None) ostream = GObject.Property(type=Gio.OutputStream, default=None) def __init__(self, message, cancellable): if message is None: raise ValueError('Message may not be None') inner_cancellable = Gio.Cancellable() super().__init__(message=message, cancellable=inner_cancellable) if cancellable is not None: cancellable.connect(lambda *x: self.cancel(), None) self.connect('send-failure', lambda r, e: r.emit('failure', e)) self.connect('receive-failure', lambda r, e: r.emit('failure', e)) # For simple access self._receive_started = False self._uri = self.message.get_uri().to_string() def send(self): """ Send the request and receive HTTP headers. Some of the body might get downloaded too. """ session.send_async(self.message, 1, self.cancellable, self._sent, None) def _sent(self, session, task, data): try: status = int(self.message.get_property('status-code')) if status >= 400: msg = 'HTTP {0} error in {1} request to {2}'.format( status, self.message.get_method(), self._uri) print_w(msg) return self.emit('send-failure', Exception(msg)) self.istream = session.send_finish(task) print_d('Got HTTP {code} on {method} request to {uri}.'.format( uri=self._uri, code=status, method=self.message.get_method())) self.emit('sent', self.message) except GLib.GError as e: print_w('Failed sending {method} request to {uri} ({err})'.format( method=self.message.get_method(), uri=self._uri, err=e)) self.emit('send-failure', e) def provide_target(self, stream): if not stream: raise ValueError('Provided stream may not be None') if not self.ostream: self.ostream = stream else: raise RuntimeError('Only one output stream may be provided') def cancel(self): """ Cancels the future and currently running HTTPRequest actions. It is safe to run this function before, during and after any action made with HTTPRequest. After HTTPRequest is cancelled, one usually would not do any more actions with it. However, it is safe to do something after cancellation, but those actions usually will fail. """ if self.cancellable.is_cancelled(): return False self.cancellable.cancel() # If we already have input stream, we can just close it, message # will come out as cancelled just fine. if self.istream and not self._receive_started: if not self.istream.is_closed(): self.istream.close(None) def receive(self): """ Receive data from the request into provided output stream. The request must be already sent, therefore this function will be usually called from the 'sent' signal handler. On completion of data receipt, HTTPRequest lifetime is ended and inner resources are cleaned up (except persistent connections that are part of session, not request). .. note:: Be sure to clean up resources you've allocated yourself (e.g. close GOutputStreams, delete files on failure et cetera). """ if not self.istream: raise RuntimeError('Cannot receive unsent request') if not self.ostream: raise RuntimeError('Cannot receive request without output stream') if self._receive_started: raise RuntimeError('Can receive only once') self._receive_started = True def spliced(ostream, task, data): try: ostream.splice_finish(task) self.istream.close(None) self.emit('received', ostream) except GLib.GError as e: self.istream.close(None) self.emit('receive-failure', e) # Do not ask splice to close the stream as Soup gets confused and # doesn't close connections # https://bugzilla.gnome.org/show_bug.cgi?id=711260 flags = Gio.OutputStreamSpliceFlags.NONE self.ostream.splice_async(self.istream, flags, GLib.PRIORITY_DEFAULT, self.cancellable, spliced, None) FailureCallback = Callable[[HTTPRequest, Exception, Any], None] def download(message: Soup.Message, cancellable: Gio.Cancellable, callback: Callable, data: Any, try_decode: bool = False, failure_callback: Optional[FailureCallback] = None): def received(request, ostream): ostream.close(None) bs = ostream.steal_as_bytes().get_data() if not try_decode: callback(message, bs, data) return # Otherwise try to decode data code = int(message.get_property('status-code')) if code >= 400: print_w("HTTP %d error received on %s" % (code, request._uri)) return ctype = message.get_property('response-headers').get_content_type() encoding = ctype[1].get('charset', 'utf-8') try: callback(message, bs.decode(encoding), data) except UnicodeDecodeError: callback(message, bs, data) request = HTTPRequest(message, cancellable) request.provide_target(Gio.MemoryOutputStream.new_resizable()) request.connect('received', received) request.connect('sent', lambda r, m: r.receive()) if failure_callback: request.connect('send-failure', failure_callback, data) request.send() def download_json(message: Soup.Message, cancellable: Gio.Cancellable, callback: Callable, data: Any, failure_callback: Optional[FailureCallback] = None): def cb(message, result, d): try: callback(message, json.loads(result), data) except ValueError: callback(message, None, data) download(message, cancellable, cb, None, True, failure_callback=failure_callback) session = Soup.Session() ua_string = "Quodlibet/{0} (+{1})".format(VERSION, WEBSITE) session.set_properties(user_agent=ua_string, timeout=15) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1663102510.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/i18n.py��������������������������������������������������������������0000644�0001750�0001750�00000026306�14310167056�016313� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # # 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 2 of the License, or # (at your option) any later version. import os import sys import gettext import locale from senf import path2fsn, fsn2text, text2fsn from quodlibet.util.path import unexpand, xdg_get_system_data_dirs from quodlibet.util.dprint import print_d def bcp47_to_language(code): """Takes a BCP 47 language identifier and returns a value suitable for the LANGUAGE env var. Only supports a small set of inputs and might return garbage.. """ if code == "zh-Hans": return "zh_CN" elif code == "zh-Hant": return "zh_TW" parts = code.split("-") is_iso = lambda s: len(s) == 2 and s.isalpha() # we only support ISO 639-1 if not is_iso(parts[0]): return parts[0].replace(":", "") lang_subtag = parts[0] region = "" if len(parts) >= 2 and is_iso(parts[1]): region = parts[1] elif len(parts) >= 3 and is_iso(parts[2]): region = parts[2] if region: return "%s_%s" % (lang_subtag, region) return lang_subtag def osx_locale_id_to_lang(id_): """Converts a NSLocale identifier to something suitable for LANG""" if not "_" in id_: return id_ # id_ can be "zh-Hans_TW" parts = id_.rsplit("_", 1) ll = parts[0] ll = bcp47_to_language(ll).split("_")[0] return "%s_%s" % (ll, parts[1]) def set_i18n_envvars(): """Set the LANG/LANGUAGE environment variables if not set in case the current platform doesn't use them by default (OS X, Window) """ if os.name == "nt": from quodlibet.util.winapi import GetUserDefaultUILanguage, \ GetSystemDefaultUILanguage langs = list(filter(None, map(locale.windows_locale.get, [GetUserDefaultUILanguage(), GetSystemDefaultUILanguage()]))) if langs: os.environ.setdefault('LANG', langs[0]) os.environ.setdefault('LANGUAGE', ":".join(langs)) elif sys.platform == "darwin": from AppKit import NSLocale locale_id = NSLocale.currentLocale().localeIdentifier() lang = osx_locale_id_to_lang(locale_id) os.environ.setdefault('LANG', lang) preferred_langs = NSLocale.preferredLanguages() if preferred_langs: languages = map(bcp47_to_language, preferred_langs) os.environ.setdefault('LANGUAGE', ":".join(languages)) else: return def fixup_i18n_envvars(): """Sanitizes env vars before gettext can use them. LANGUAGE should support a priority list of languages with fallbacks, but doesn't work due to "en" no being known to gettext (This could be solved by providing a en.po in QL but all other libraries don't define it either) This tries to fix that. """ try: langs = os.environ["LANGUAGE"].split(":") except KeyError: return # So, this seems to be an undocumented feature where C selects # "no translation". Append it to any en/en_XX so that when not found # it falls back to "en"/no translation. sanitized = [] for lang in langs: sanitized.append(lang) if lang.startswith("en") and len(langs) > 1: sanitized.append("C") os.environ["LANGUAGE"] = ":".join(sanitized) class GlibTranslations(gettext.GNUTranslations): """Provide a glib-like translation API for Python. This class adds support for pgettext (and upgettext) mirroring glib's C_ macro, which allows for disambiguation of identical source strings. It also installs N_, C_, and ngettext into the __builtin__ namespace. It can also be instantiated and used with any valid MO files (though it won't be able to translate anything, of course). """ def __init__(self, fp=None): self.path = (fp and fp.name) or "" self._catalog = {} self.plural = lambda n: n != 1 gettext.GNUTranslations.__init__(self, fp) self._debug_text = None def ugettext(self, message): # force unicode here since __contains__ (used in gettext) ignores # our changed defaultencoding for coercion, so utf-8 encoded strings # fail at lookup. message = str(message) return str(gettext.GNUTranslations.gettext(self, message)) def ungettext(self, msgid1, msgid2, n): # see ugettext msgid1 = str(msgid1) msgid2 = str(msgid2) return str( gettext.GNUTranslations.ngettext(self, msgid1, msgid2, n)) def unpgettext(self, context, msgid, msgidplural, n): context = str(context) msgid = str(msgid) msgidplural = str(msgidplural) real_msgid = u"%s\x04%s" % (context, msgid) real_msgidplural = u"%s\x04%s" % (context, msgidplural) result = self.ngettext(real_msgid, real_msgidplural, n) if result == real_msgid: return msgid elif result == real_msgidplural: return msgidplural return result def upgettext(self, context, msgid): context = str(context) msgid = str(msgid) real_msgid = u"%s\x04%s" % (context, msgid) result = self.ugettext(real_msgid) if result == real_msgid: return msgid return result def set_debug_text(self, debug_text): self._debug_text = debug_text def wrap_text(self, value): if self._debug_text is None: return value else: return self._debug_text + value + self._debug_text def install(self, *args, **kwargs): raise NotImplementedError("We no longer do builtins") _initialized = False _debug_text = None _translations = { "quodlibet": GlibTranslations(), } def set_debug_text(debug_text=None): """ Args: debug_text (str or None): text to add to all translations """ global _debug_text, _translations _debug_text = debug_text for trans in _translations.values(): trans.set_debug_text(debug_text) def iter_locale_dirs(): dirs = list(xdg_get_system_data_dirs()) # this is the one python gettext uses by default, use as a fallback dirs.append(os.path.join(sys.base_prefix, "share")) done = set() for path in dirs: locale_dir = os.path.join(path, "locale") if locale_dir in done: continue done.add(locale_dir) if os.path.isdir(locale_dir): yield locale_dir def register_translation(domain, localedir=None): """Register a translation domain Args: domain (str): the gettext domain localedir (pathlike): A directory used for translations, if None the system one will be used. Returns: GlibTranslations """ global _debug_text, _translations, _initialized assert _initialized if localedir is None: iterdirs = iter_locale_dirs else: iterdirs = lambda: (yield localedir) for dir_ in iterdirs(): try: t = gettext.translation(domain, dir_, class_=GlibTranslations) except OSError: continue else: print_d("Translations loaded: %r" % unexpand(t.path)) break else: print_d(f"No translation found for domain {domain!r} in {localedir!r}") t = GlibTranslations() t.set_debug_text(_debug_text) _translations[domain] = t return t def init(language=None): """Call this sometime at start before any register_translation() and before any gettext using libraries are loaded. Args: language (str or None): Either a language to use or None for the system derived default. """ global _initialized set_i18n_envvars() fixup_i18n_envvars() print_d("LANGUAGE: %r" % os.environ.get("LANGUAGE")) print_d("LANG: %r" % os.environ.get("LANG")) try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass # XXX: these are our most user facing APIs, make sre they are not loaded # before we set the language. For GLib this is too late.. assert "gi.repository.Gtk" not in sys.modules assert "gi.repository.Gst" not in sys.modules if language is not None: os.environ["LANGUAGE"] = text2fsn(language) print_d("LANGUAGE: %r" % os.environ.get("LANGUAGE")) _initialized = True def get_available_languages(domain): """Returns a set of available translations for a given gettext domain. Args: domain (str) Returns: Set[str] """ langs = {"C"} for locale_dir in iter_locale_dirs(): try: entries = os.listdir(locale_dir) except OSError: continue for lang in entries: mo_path = os.path.join( locale_dir, lang, "LC_MESSAGES", "%s.mo" % domain) if os.path.exists(mo_path): langs.add(fsn2text(path2fsn(lang))) return langs def _(message): """ Args: message (str) Returns: str Lookup the translation for message """ t = _translations["quodlibet"] return t.wrap_text(t.ugettext(message)) def N_(message): """ Args: message (str) Returns: str Only marks a string for translation """ return str(message) def C_(context, message): """ Args: context (str) message (str) Returns: str Lookup the translation for message for a context """ t = _translations["quodlibet"] return t.wrap_text(t.upgettext(context, message)) def ngettext(singular, plural, n): """ Args: singular (str) plural (str) n (int) Returns: str Returns the translation for a singular or plural form depending on the value of n. """ t = _translations["quodlibet"] return t.wrap_text(t.ungettext(singular, plural, n)) def numeric_phrase(singular, plural, n, template_var=None): """Returns a final locale-specific phrase with pluralisation if necessary and grouping of the number. This is added to custom gettext keywords to allow us to use as-is. Args: singular (str) plural (str) n (int) template_var (str) Returns: str For example, ``numeric_phrase('Add %d song', 'Add %d songs', 12345)`` returns `"Add 12,345 songs"` (in `en_US` locale at least) """ num_text = locale.format_string('%d', n, grouping=True) if not template_var: template_var = '%d' replacement = '%s' params = num_text else: template_var = '%(' + template_var + ')d' replacement = '%(' + template_var + ')s' params = dict() params[template_var] = num_text return (ngettext(singular, plural, n).replace(template_var, replacement) % params) def npgettext(context, singular, plural, n): """ Args: context (str) singular (str) plural (str) n (int) Returns: str Like ngettext, but with also depends on the context. """ t = _translations["quodlibet"] return t.wrap_text(t.unpgettext(context, singular, plural, n)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656278102.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/importhelper.py������������������������������������������������������0000664�0001750�0001750�00000005751�14256146126�020255� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys import importlib from os.path import join, splitext, basename from quodlibet import util, print_d def load_dir_modules(path, package): """Load all modules and packages in path (recursive). In case the module is already loaded, doesn't reload it. """ # needed for pickle etc. assert package in sys.modules try: modules = [e[0] for e in get_importables(path)] except OSError: util.print_w("%r not found" % path) return [] # get_importables can yield py and pyc for the same module # and we want to load it only once modules = set(modules) loaded = [] for name in modules: try: mod = load_module(name, package, path) except Exception: util.print_exc() continue if mod: loaded.append(mod) return loaded def get_importables(folder): """Searches a folder and its subfolders for modules and packages to import. No subfolders in packages, .so supported. The root folder will not be considered a package. returns a tuple of the name, import path, list of possible dependencies """ def is_ok(f): if f.startswith("_"): return False if f.endswith(".py"): return True return False def is_init(f): return f == "__init__.py" first = True for root, dirs, names in os.walk(folder): # Ignore packages like "_shared" for d in dirs: if d.startswith("_") or d.startswith("."): print_d("Ignoring %r" % os.path.join(root, d)) dirs.remove(d) if not first and any((is_init(n) for n in names)): yield (basename(root), root, [d for d in (join(root, name) for name in names) if is_ok(d)]) else: for name in filter(is_ok, names): yield (splitext(name)[0], join(root, name), [join(root, name)]) first = False def load_module(name, package, path): """Load a module/package. Returns the module or None. Doesn't catch any exceptions during the actual import. """ fullname = package + "." + name try: return sys.modules[fullname] except KeyError: pass loader = importlib.find_loader(fullname, [path]) if loader is None: return # modules need a parent package if package not in sys.modules: spec = importlib.machinery.ModuleSpec(package, None, is_package=True) sys.modules[package] = importlib.util.module_from_spec(spec) mod = loader.load_module(fullname) # make it accessible from the parent, like __import__ does vars(sys.modules[package])[name] = mod return mod �����������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/iso639.py������������������������������������������������������������0000664�0001750�0001750�00000051465�14035600052�016566� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from .i18n import register_translation # Based on https://pkg-isocodes.alioth.debian.org/ # which is licensed under LGPL-2.1+ # Generated using _print_iso_639() (see below) _ISO_639 = [ ('Afar', 'aa', 'aar', ''), ('Abkhazian', 'ab', 'abk', ''), ('Achinese', '', 'ace', ''), ('Acoli', '', 'ach', ''), ('Adangme', '', 'ada', ''), ('Adyghe; Adygei', '', 'ady', ''), ('Afro-Asiatic languages', '', 'afa', ''), ('Afrihili', '', 'afh', ''), ('Afrikaans', 'af', 'afr', ''), ('Ainu', '', 'ain', ''), ('Akan', 'ak', 'aka', ''), ('Akkadian', '', 'akk', ''), ('Albanian', 'sq', 'alb', 'sqi'), ('Aleut', '', 'ale', ''), ('Algonquian languages', '', 'alg', ''), ('Southern Altai', '', 'alt', ''), ('Amharic', 'am', 'amh', ''), ('English, Old (ca. 450-1100)', '', 'ang', ''), ('Angika', '', 'anp', ''), ('Apache languages', '', 'apa', ''), ('Arabic', 'ar', 'ara', ''), ('Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)', '', 'arc', ''), ('Aragonese', 'an', 'arg', ''), ('Armenian', 'hy', 'arm', 'hye'), ('Mapudungun; Mapuche', '', 'arn', ''), ('Arapaho', '', 'arp', ''), ('Artificial languages', '', 'art', ''), ('Arawak', '', 'arw', ''), ('Assamese', 'as', 'asm', ''), ('Asturian; Bable; Leonese; Asturleonese', '', 'ast', ''), ('Athapascan languages', '', 'ath', ''), ('Australian languages', '', 'aus', ''), ('Avaric', 'av', 'ava', ''), ('Avestan', 'ae', 'ave', ''), ('Awadhi', '', 'awa', ''), ('Aymara', 'ay', 'aym', ''), ('Azerbaijani', 'az', 'aze', ''), ('Banda languages', '', 'bad', ''), ('Bamileke languages', '', 'bai', ''), ('Bashkir', 'ba', 'bak', ''), ('Baluchi', '', 'bal', ''), ('Bambara', 'bm', 'bam', ''), ('Balinese', '', 'ban', ''), ('Basque', 'eu', 'baq', 'eus'), ('Basa', '', 'bas', ''), ('Baltic languages', '', 'bat', ''), ('Beja; Bedawiyet', '', 'bej', ''), ('Belarusian', 'be', 'bel', ''), ('Bemba', '', 'bem', ''), ('Bengali', 'bn', 'ben', ''), ('Berber languages', '', 'ber', ''), ('Bhojpuri', '', 'bho', ''), ('Bihari languages', 'bh', 'bih', ''), ('Bikol', '', 'bik', ''), ('Bini; Edo', '', 'bin', ''), ('Bislama', 'bi', 'bis', ''), ('Siksika', '', 'bla', ''), ('Bantu languages', '', 'bnt', ''), ('Bosnian', 'bs', 'bos', ''), ('Braj', '', 'bra', ''), ('Breton', 'br', 'bre', ''), ('Batak languages', '', 'btk', ''), ('Buriat', '', 'bua', ''), ('Buginese', '', 'bug', ''), ('Bulgarian', 'bg', 'bul', ''), ('Burmese', 'my', 'bur', 'mya'), ('Blin; Bilin', '', 'byn', ''), ('Caddo', '', 'cad', ''), ('Central American Indian languages', '', 'cai', ''), ('Galibi Carib', '', 'car', ''), ('Catalan; Valencian', 'ca', 'cat', ''), ('Caucasian languages', '', 'cau', ''), ('Cebuano', '', 'ceb', ''), ('Celtic languages', '', 'cel', ''), ('Chamorro', 'ch', 'cha', ''), ('Chibcha', '', 'chb', ''), ('Chechen', 'ce', 'che', ''), ('Chagatai', '', 'chg', ''), ('Chinese', 'zh', 'chi', 'zho'), ('Chuukese', '', 'chk', ''), ('Mari', '', 'chm', ''), ('Chinook jargon', '', 'chn', ''), ('Choctaw', '', 'cho', ''), ('Chipewyan; Dene Suline', '', 'chp', ''), ('Cherokee', '', 'chr', ''), ('Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; ' 'Old Church Slavonic', 'cu', 'chu', ''), ('Chuvash', 'cv', 'chv', ''), ('Cheyenne', '', 'chy', ''), ('Chamic languages', '', 'cmc', ''), ('Coptic', '', 'cop', ''), ('Cornish', 'kw', 'cor', ''), ('Corsican', 'co', 'cos', ''), ('Creoles and pidgins, English based', '', 'cpe', ''), ('Creoles and pidgins, French-based', '', 'cpf', ''), ('Creoles and pidgins, Portuguese-based', '', 'cpp', ''), ('Cree', 'cr', 'cre', ''), ('Crimean Tatar; Crimean Turkish', '', 'crh', ''), ('Creoles and pidgins', '', 'crp', ''), ('Kashubian', '', 'csb', ''), ('Cushitic languages', '', 'cus', ''), ('Czech', 'cs', 'cze', 'ces'), ('Dakota', '', 'dak', ''), ('Danish', 'da', 'dan', ''), ('Dargwa', '', 'dar', ''), ('Land Dayak languages', '', 'day', ''), ('Delaware', '', 'del', ''), ('Slave (Athapascan)', '', 'den', ''), ('Dogrib', '', 'dgr', ''), ('Dinka', '', 'din', ''), ('Divehi; Dhivehi; Maldivian', 'dv', 'div', ''), ('Dogri', '', 'doi', ''), ('Dravidian languages', '', 'dra', ''), ('Lower Sorbian', '', 'dsb', ''), ('Duala', '', 'dua', ''), ('Dutch, Middle (ca. 1050-1350)', '', 'dum', ''), ('Dutch; Flemish', 'nl', 'dut', 'nld'), ('Dyula', '', 'dyu', ''), ('Dzongkha', 'dz', 'dzo', ''), ('Efik', '', 'efi', ''), ('Egyptian (Ancient)', '', 'egy', ''), ('Ekajuk', '', 'eka', ''), ('Elamite', '', 'elx', ''), ('English', 'en', 'eng', ''), ('English, Middle (1100-1500)', '', 'enm', ''), ('Esperanto', 'eo', 'epo', ''), ('Estonian', 'et', 'est', ''), ('Ewe', 'ee', 'ewe', ''), ('Ewondo', '', 'ewo', ''), ('Fang', '', 'fan', ''), ('Faroese', 'fo', 'fao', ''), ('Fanti', '', 'fat', ''), ('Fijian', 'fj', 'fij', ''), ('Filipino; Pilipino', '', 'fil', ''), ('Finnish', 'fi', 'fin', ''), ('Finno-Ugrian languages', '', 'fiu', ''), ('Fon', '', 'fon', ''), ('French', 'fr', 'fre', 'fra'), ('French, Middle (ca. 1400-1600)', '', 'frm', ''), ('French, Old (842-ca. 1400)', '', 'fro', ''), ('Northern Frisian', '', 'frr', ''), ('Eastern Frisian', '', 'frs', ''), ('Western Frisian', 'fy', 'fry', ''), ('Fulah', 'ff', 'ful', ''), ('Friulian', '', 'fur', ''), ('Ga', '', 'gaa', ''), ('Gayo', '', 'gay', ''), ('Gbaya', '', 'gba', ''), ('Germanic languages', '', 'gem', ''), ('Georgian', 'ka', 'geo', 'kat'), ('German', 'de', 'ger', 'deu'), ('Geez', '', 'gez', ''), ('Gilbertese', '', 'gil', ''), ('Gaelic; Scottish Gaelic', 'gd', 'gla', ''), ('Irish', 'ga', 'gle', ''), ('Galician', 'gl', 'glg', ''), ('Manx', 'gv', 'glv', ''), ('German, Middle High (ca. 1050-1500)', '', 'gmh', ''), ('German, Old High (ca. 750-1050)', '', 'goh', ''), ('Gondi', '', 'gon', ''), ('Gorontalo', '', 'gor', ''), ('Gothic', '', 'got', ''), ('Grebo', '', 'grb', ''), ('Greek, Ancient (to 1453)', '', 'grc', ''), ('Greek, Modern (1453-)', 'el', 'gre', 'ell'), ('Guarani', 'gn', 'grn', ''), ('Swiss German; Alemannic; Alsatian', '', 'gsw', ''), ('Gujarati', 'gu', 'guj', ''), ("Gwich'in", '', 'gwi', ''), ('Haida', '', 'hai', ''), ('Haitian; Haitian Creole', 'ht', 'hat', ''), ('Hausa', 'ha', 'hau', ''), ('Hawaiian', '', 'haw', ''), ('Hebrew', 'he', 'heb', ''), ('Herero', 'hz', 'her', ''), ('Hiligaynon', '', 'hil', ''), ('Himachali languages; Western Pahari languages', '', 'him', ''), ('Hindi', 'hi', 'hin', ''), ('Hittite', '', 'hit', ''), ('Hmong; Mong', '', 'hmn', ''), ('Hiri Motu', 'ho', 'hmo', ''), ('Croatian', 'hr', 'hrv', ''), ('Upper Sorbian', '', 'hsb', ''), ('Hungarian', 'hu', 'hun', ''), ('Hupa', '', 'hup', ''), ('Iban', '', 'iba', ''), ('Igbo', 'ig', 'ibo', ''), ('Icelandic', 'is', 'ice', 'isl'), ('Ido', 'io', 'ido', ''), ('Sichuan Yi; Nuosu', 'ii', 'iii', ''), ('Ijo languages', '', 'ijo', ''), ('Inuktitut', 'iu', 'iku', ''), ('Interlingue; Occidental', 'ie', 'ile', ''), ('Iloko', '', 'ilo', ''), ('Interlingua (International Auxiliary Language Association)', 'ia', 'ina', ''), ('Indic languages', '', 'inc', ''), ('Indonesian', 'id', 'ind', ''), ('Indo-European languages', '', 'ine', ''), ('Ingush', '', 'inh', ''), ('Inupiaq', 'ik', 'ipk', ''), ('Iranian languages', '', 'ira', ''), ('Iroquoian languages', '', 'iro', ''), ('Italian', 'it', 'ita', ''), ('Javanese', 'jv', 'jav', ''), ('Lojban', '', 'jbo', ''), ('Japanese', 'ja', 'jpn', ''), ('Judeo-Persian', '', 'jpr', ''), ('Judeo-Arabic', '', 'jrb', ''), ('Kara-Kalpak', '', 'kaa', ''), ('Kabyle', '', 'kab', ''), ('Kachin; Jingpho', '', 'kac', ''), ('Kalaallisut; Greenlandic', 'kl', 'kal', ''), ('Kamba', '', 'kam', ''), ('Kannada', 'kn', 'kan', ''), ('Karen languages', '', 'kar', ''), ('Kashmiri', 'ks', 'kas', ''), ('Kanuri', 'kr', 'kau', ''), ('Kawi', '', 'kaw', ''), ('Kazakh', 'kk', 'kaz', ''), ('Kabardian', '', 'kbd', ''), ('Khasi', '', 'kha', ''), ('Khoisan languages', '', 'khi', ''), ('Central Khmer', 'km', 'khm', ''), ('Khotanese;Sakan', '', 'kho', ''), ('Kikuyu; Gikuyu', 'ki', 'kik', ''), ('Kinyarwanda', 'rw', 'kin', ''), ('Kirghiz; Kyrgyz', 'ky', 'kir', ''), ('Kimbundu', '', 'kmb', ''), ('Konkani', '', 'kok', ''), ('Komi', 'kv', 'kom', ''), ('Kongo', 'kg', 'kon', ''), ('Korean', 'ko', 'kor', ''), ('Kosraean', '', 'kos', ''), ('Kpelle', '', 'kpe', ''), ('Karachay-Balkar', '', 'krc', ''), ('Karelian', '', 'krl', ''), ('Kru languages', '', 'kro', ''), ('Kurukh', '', 'kru', ''), ('Kuanyama; Kwanyama', 'kj', 'kua', ''), ('Kumyk', '', 'kum', ''), ('Kurdish', 'ku', 'kur', ''), ('Kutenai', '', 'kut', ''), ('Ladino', '', 'lad', ''), ('Lahnda', '', 'lah', ''), ('Lamba', '', 'lam', ''), ('Lao', 'lo', 'lao', ''), ('Latin', 'la', 'lat', ''), ('Latvian', 'lv', 'lav', ''), ('Lezghian', '', 'lez', ''), ('Limburgan; Limburger; Limburgish', 'li', 'lim', ''), ('Lingala', 'ln', 'lin', ''), ('Lithuanian', 'lt', 'lit', ''), ('Mongo', '', 'lol', ''), ('Lozi', '', 'loz', ''), ('Luxembourgish; Letzeburgesch', 'lb', 'ltz', ''), ('Luba-Lulua', '', 'lua', ''), ('Luba-Katanga', 'lu', 'lub', ''), ('Ganda', 'lg', 'lug', ''), ('Luiseno', '', 'lui', ''), ('Lunda', '', 'lun', ''), ('Luo (Kenya and Tanzania)', '', 'luo', ''), ('Lushai', '', 'lus', ''), ('Macedonian', 'mk', 'mac', 'mkd'), ('Madurese', '', 'mad', ''), ('Magahi', '', 'mag', ''), ('Marshallese', 'mh', 'mah', ''), ('Maithili', '', 'mai', ''), ('Makasar', '', 'mak', ''), ('Malayalam', 'ml', 'mal', ''), ('Mandingo', '', 'man', ''), ('Maori', 'mi', 'mao', 'mri'), ('Austronesian languages', '', 'map', ''), ('Marathi', 'mr', 'mar', ''), ('Masai', '', 'mas', ''), ('Malay', 'ms', 'may', 'msa'), ('Moksha', '', 'mdf', ''), ('Mandar', '', 'mdr', ''), ('Mende', '', 'men', ''), ('Irish, Middle (900-1200)', '', 'mga', ''), ("Mi'kmaq; Micmac", '', 'mic', ''), ('Minangkabau', '', 'min', ''), ('Uncoded languages', '', 'mis', ''), ('Mon-Khmer languages', '', 'mkh', ''), ('Malagasy', 'mg', 'mlg', ''), ('Maltese', 'mt', 'mlt', ''), ('Manchu', '', 'mnc', ''), ('Manipuri', '', 'mni', ''), ('Manobo languages', '', 'mno', ''), ('Mohawk', '', 'moh', ''), ('Moldavian; Moldovan', 'mo', 'mol', ''), ('Mongolian', 'mn', 'mon', ''), ('Mossi', '', 'mos', ''), ('Multiple languages', '', 'mul', ''), ('Munda languages', '', 'mun', ''), ('Creek', '', 'mus', ''), ('Mirandese', '', 'mwl', ''), ('Marwari', '', 'mwr', ''), ('Mayan languages', '', 'myn', ''), ('Erzya', '', 'myv', ''), ('Nahuatl languages', '', 'nah', ''), ('North American Indian languages', '', 'nai', ''), ('Neapolitan', '', 'nap', ''), ('Nauru', 'na', 'nau', ''), ('Navajo; Navaho', 'nv', 'nav', ''), ('Ndebele, South; South Ndebele', 'nr', 'nbl', ''), ('Ndebele, North; North Ndebele', 'nd', 'nde', ''), ('Ndonga', 'ng', 'ndo', ''), ('Low German; Low Saxon; German, Low; Saxon, Low', '', 'nds', ''), ('Nepali', 'ne', 'nep', ''), ('Nepal Bhasa; Newari', '', 'new', ''), ('Nias', '', 'nia', ''), ('Niger-Kordofanian languages', '', 'nic', ''), ('Niuean', '', 'niu', ''), ('Norwegian Nynorsk; Nynorsk, Norwegian', 'nn', 'nno', ''), (u'Bokm\xe5l, Norwegian; Norwegian Bokm\xe5l', 'nb', 'nob', ''), ('Nogai', '', 'nog', ''), ('Norse, Old', '', 'non', ''), ('Norwegian', 'no', 'nor', ''), ("N'Ko", '', 'nqo', ''), ('Pedi; Sepedi; Northern Sotho', '', 'nso', ''), ('Nubian languages', '', 'nub', ''), ('Classical Newari; Old Newari; Classical Nepal Bhasa', '', 'nwc', ''), ('Chichewa; Chewa; Nyanja', 'ny', 'nya', ''), ('Nyamwezi', '', 'nym', ''), ('Nyankole', '', 'nyn', ''), ('Nyoro', '', 'nyo', ''), ('Nzima', '', 'nzi', ''), ('Occitan (post 1500)', 'oc', 'oci', ''), ('Ojibwa', 'oj', 'oji', ''), ('Oriya', 'or', 'ori', ''), ('Oromo', 'om', 'orm', ''), ('Osage', '', 'osa', ''), ('Ossetian; Ossetic', 'os', 'oss', ''), ('Turkish, Ottoman (1500-1928)', '', 'ota', ''), ('Otomian languages', '', 'oto', ''), ('Papuan languages', '', 'paa', ''), ('Pangasinan', '', 'pag', ''), ('Pahlavi', '', 'pal', ''), ('Pampanga; Kapampangan', '', 'pam', ''), ('Panjabi; Punjabi', 'pa', 'pan', ''), ('Papiamento', '', 'pap', ''), ('Palauan', '', 'pau', ''), ('Persian, Old (ca. 600-400 B.C.)', '', 'peo', ''), ('Persian', 'fa', 'per', 'fas'), ('Philippine languages', '', 'phi', ''), ('Phoenician', '', 'phn', ''), ('Pali', 'pi', 'pli', ''), ('Polish', 'pl', 'pol', ''), ('Pohnpeian', '', 'pon', ''), ('Portuguese', 'pt', 'por', ''), ('Prakrit languages', '', 'pra', ''), (u'Proven\xe7al, Old (to 1500); Occitan, Old (to 1500)', '', 'pro', ''), ('Pushto; Pashto', 'ps', 'pus', ''), ('Reserved for local use', '', 'qaa-qtz', ''), ('Quechua', 'qu', 'que', ''), ('Rajasthani', '', 'raj', ''), ('Rapanui', '', 'rap', ''), ('Rarotongan; Cook Islands Maori', '', 'rar', ''), ('Romance languages', '', 'roa', ''), ('Romansh', 'rm', 'roh', ''), ('Romany', '', 'rom', ''), ('Romanian', 'ro', 'rum', 'ron'), ('Rundi', 'rn', 'run', ''), ('Aromanian; Arumanian; Macedo-Romanian', '', 'rup', ''), ('Russian', 'ru', 'rus', ''), ('Sandawe', '', 'sad', ''), ('Sango', 'sg', 'sag', ''), ('Yakut', '', 'sah', ''), ('South American Indian languages', '', 'sai', ''), ('Salishan languages', '', 'sal', ''), ('Samaritan Aramaic', '', 'sam', ''), ('Sanskrit', 'sa', 'san', ''), ('Sasak', '', 'sas', ''), ('Santali', '', 'sat', ''), ('Sicilian', '', 'scn', ''), ('Scots', '', 'sco', ''), ('Selkup', '', 'sel', ''), ('Semitic languages', '', 'sem', ''), ('Irish, Old (to 900)', '', 'sga', ''), ('Sign Languages', '', 'sgn', ''), ('Shan', '', 'shn', ''), ('Sidamo', '', 'sid', ''), ('Sinhala; Sinhalese', 'si', 'sin', ''), ('Siouan languages', '', 'sio', ''), ('Sino-Tibetan languages', '', 'sit', ''), ('Slavic languages', '', 'sla', ''), ('Slovak', 'sk', 'slo', 'slk'), ('Slovenian', 'sl', 'slv', ''), ('Southern Sami', '', 'sma', ''), ('Northern Sami', 'se', 'sme', ''), ('Sami languages', '', 'smi', ''), ('Lule Sami', '', 'smj', ''), ('Inari Sami', '', 'smn', ''), ('Samoan', 'sm', 'smo', ''), ('Skolt Sami', '', 'sms', ''), ('Shona', 'sn', 'sna', ''), ('Sindhi', 'sd', 'snd', ''), ('Soninke', '', 'snk', ''), ('Sogdian', '', 'sog', ''), ('Somali', 'so', 'som', ''), ('Songhai languages', '', 'son', ''), ('Sotho, Southern', 'st', 'sot', ''), ('Spanish; Castilian', 'es', 'spa', ''), ('Sardinian', 'sc', 'srd', ''), ('Sranan Tongo', '', 'srn', ''), ('Serbian', 'sr', 'srp', ''), ('Serer', '', 'srr', ''), ('Nilo-Saharan languages', '', 'ssa', ''), ('Swati', 'ss', 'ssw', ''), ('Sukuma', '', 'suk', ''), ('Sundanese', 'su', 'sun', ''), ('Susu', '', 'sus', ''), ('Sumerian', '', 'sux', ''), ('Swahili', 'sw', 'swa', ''), ('Swedish', 'sv', 'swe', ''), ('Classical Syriac', '', 'syc', ''), ('Syriac', '', 'syr', ''), ('Tahitian', 'ty', 'tah', ''), ('Tai languages', '', 'tai', ''), ('Tamil', 'ta', 'tam', ''), ('Tatar', 'tt', 'tat', ''), ('Telugu', 'te', 'tel', ''), ('Timne', '', 'tem', ''), ('Tereno', '', 'ter', ''), ('Tetum', '', 'tet', ''), ('Tajik', 'tg', 'tgk', ''), ('Tagalog', 'tl', 'tgl', ''), ('Thai', 'th', 'tha', ''), ('Tibetan', 'bo', 'tib', 'bod'), ('Tigre', '', 'tig', ''), ('Tigrinya', 'ti', 'tir', ''), ('Tiv', '', 'tiv', ''), ('Tokelau', '', 'tkl', ''), ('Klingon; tlhIngan-Hol', '', 'tlh', ''), ('Tlingit', '', 'tli', ''), ('Tamashek', '', 'tmh', ''), ('Tonga (Nyasa)', '', 'tog', ''), ('Tonga (Tonga Islands)', 'to', 'ton', ''), ('Tok Pisin', '', 'tpi', ''), ('Tsimshian', '', 'tsi', ''), ('Tswana', 'tn', 'tsn', ''), ('Tsonga', 'ts', 'tso', ''), ('Turkmen', 'tk', 'tuk', ''), ('Tumbuka', '', 'tum', ''), ('Tupi languages', '', 'tup', ''), ('Turkish', 'tr', 'tur', ''), ('Altaic languages', '', 'tut', ''), ('Tuvalu', '', 'tvl', ''), ('Twi', 'tw', 'twi', ''), ('Tuvinian', '', 'tyv', ''), ('Udmurt', '', 'udm', ''), ('Ugaritic', '', 'uga', ''), ('Uighur; Uyghur', 'ug', 'uig', ''), ('Ukrainian', 'uk', 'ukr', ''), ('Umbundu', '', 'umb', ''), ('Undetermined', '', 'und', ''), ('Urdu', 'ur', 'urd', ''), ('Uzbek', 'uz', 'uzb', ''), ('Vai', '', 'vai', ''), ('Venda', 've', 'ven', ''), ('Vietnamese', 'vi', 'vie', ''), (u'Volap\xfck', 'vo', 'vol', ''), ('Votic', '', 'vot', ''), ('Wakashan languages', '', 'wak', ''), ('Wolaitta; Wolaytta', '', 'wal', ''), ('Waray', '', 'war', ''), ('Washo', '', 'was', ''), ('Welsh', 'cy', 'wel', 'cym'), ('Sorbian languages', '', 'wen', ''), ('Walloon', 'wa', 'wln', ''), ('Wolof', 'wo', 'wol', ''), ('Kalmyk; Oirat', '', 'xal', ''), ('Xhosa', 'xh', 'xho', ''), ('Yao', '', 'yao', ''), ('Yapese', '', 'yap', ''), ('Yiddish', 'yi', 'yid', ''), ('Yoruba', 'yo', 'yor', ''), ('Yupik languages', '', 'ypk', ''), ('Zapotec', '', 'zap', ''), ('Blissymbols; Blissymbolics; Bliss', '', 'zbl', ''), ('Zenaga', '', 'zen', ''), ('Standard Moroccan Tamazight', '', 'zgh', ''), ('Zhuang; Chuang', 'za', 'zha', ''), ('Zande languages', '', 'znd', ''), ('Zulu', 'zu', 'zul', ''), ('Zuni', '', 'zun', ''), ('No linguistic content; Not applicable', '', 'zxx', ''), ('Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki', '', 'zza', ''), ] _ISO_639_1 = {} _ISO_639_2 = {} _LOWER = {} def _fill_mappings(): for entry in _ISO_639: name, _1, _2B, _2T = entry _LOWER[name.lower()] = name if _1: _ISO_639_1[_1] = entry _ISO_639_2[_2B] = entry if _2T: _ISO_639_2[_2T] = entry _fill_mappings() ISO_639_2 = list(_ISO_639_2.keys()) def _gettext(name, cache=[]): if not cache: t = register_translation("iso_639") cache.append(lambda s: t.wrap_text(t.gettext(s))) return cache[0](name) def get_name(iso_code): """Returns the English name for the iso_639_1/2 code or an empty string if the code is not known. """ if iso_code in _ISO_639_1: return _ISO_639_1[iso_code][0] elif iso_code in _ISO_639_2: return _ISO_639_2[iso_code][0] return u"" def translate(text): """Given an iso code or a name tries to return a translated version for the current locale. If no translation is found returns an empty string. """ # try to convert iso codes to English names and then translate name = get_name(text) if name: return _gettext(name) else: # not an iso code, try to match with the English name. # If all fails just return the original input lower = text.lower() if lower in _LOWER: return _gettext(_LOWER[lower]) return u"" def _print_iso_639(): """Prints the _ISO_639 list from above based on iso_639.xml. Maybe depend on the xml at runtime? """ import os import pprint from xml.etree import cElementTree as ET from .path import xdg_get_system_data_dirs entries = [] for data_dir in xdg_get_system_data_dirs(): iso_path = os.path.join(data_dir, "xml", "iso-codes", "iso_639.xml") if os.path.exists(iso_path): tree = ET.ElementTree(file=iso_path) for elm in tree.iterfind("iso_639_entry"): iso_639_1_code = elm.attrib.get("iso_639_1_code", "") iso_639_2B_code = elm.attrib["iso_639_2B_code"] iso_639_2T_code = elm.attrib["iso_639_2T_code"] if iso_639_2B_code == iso_639_2T_code: iso_639_2T_code = "" name = elm.attrib["name"] entries.append( (name, iso_639_1_code, iso_639_2B_code, iso_639_2T_code)) break else: raise Exception("iso_639.xml not found") pprint.pprint(entries) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/json_data.py���������������������������������������������������������0000664�0001750�0001750�00000011415�14037102221�017460� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import from typing import Dict import json from collections import namedtuple from quodlibet.util.dprint import print_d, print_w from quodlibet.util.misc import total_ordering @total_ordering class JSONObject: """ Base class for simple, named data objects that can be edited and persisted as JSON. """ NAME = "" # The format for JSONObject. Field = namedtuple('Field', ['human_name', 'doc']) EMPTY_FIELD = Field(None, None) # Override this to specify a set of field names, # or a dict of field: FieldData # Must include "name" if dict is specified. FIELDS: Dict[str, Field] = {} @classmethod def _should_store(cls, field_name): """Decides if a field should be stored""" return not field_name.startswith("_") def __init__(self, name): if not name: raise ValueError("%s objects must be named" % type(self).__name__) self.name = str(name) @property def data(self): """A list of tuples of the persisted key:values in this class""" if self.FIELDS: return [(k, self.__getattribute__(k) if hasattr(self, k) else None) for k in self.FIELDS] else: print_d("No order specified for class %s" % type(self).__name__) return dict((k, v) for k, v in self.__dict__.items() if self._should_store(k)) def field(self, name): """Returns the Field metadata of field `name` if available, or an null / empty one""" if isinstance(self.FIELDS, dict): return self.FIELDS.get(name, self.EMPTY_FIELD) @property def json(self): return json.dumps(dict(self.data)) def __eq__(self, other): return self.data == other.data def __lt__(self, other): return self.data < other.data def __str__(self): return "<%s '%s' with %s>" % (self.__class__.__name__, self.name, self.json) class JSONObjectDict(dict): """A dict wrapper to persist named `JSONObject`-style objects""" def __init__(self, Item=JSONObject): self.Item = Item dict.__init__(self) @classmethod def from_json(cls, ItemKind, json_str): """ Factory method for building from an input string, a JSON map of {item_name1: {key:value, key2:value2...}, item_name2:...} """ new = cls(ItemKind) try: data = json.loads(json_str) except ValueError: print_w("Broken JSON: %s" % json_str) else: for name, blob in data.items(): try: new[name] = ItemKind(**blob) except TypeError as e: raise IOError("Couldn't instantiate %s from JSON (%s)" % (ItemKind.__name__, e)) return new @classmethod def from_list(cls, json_objects, raise_errors=True): new = cls() for j in json_objects: if not isinstance(j, JSONObject): msg = ("Incorrect type (%s) found in list of objects" % j.__class__.__name__) if raise_errors: raise TypeError(msg) else: print_d(msg) else: if not j.name and raise_errors: raise ValueError("Null key for %s object %s" % (cls.__name__, j)) if j.name in new: print_w("Duplicate %s found named '%s'. Removing..." % (cls.__name__, j.name)) new[j.name] = j return new def save(self, filename=None): """ Takes a list of `JSONObject` objects and returns the data serialised as a JSON string, also writing (prettily) to file `filename` if specified. """ print_d("Saving %d %s(s) to JSON.." % (len(self), self.Item.__name__)) try: obj_dict = dict((o.name, dict(o.data)) for o in self.values()) except AttributeError: raise json_str = json.dumps(obj_dict, indent=4) json_str = json_str.encode("utf-8") if filename: try: with open(filename, "wb") as f: f.write(json_str) except IOError as e: print_w("Couldn't write JSON for %s object(s) (%s)" % (type(self).__name__, e)) return json_str ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/library.py�����������������������������������������������������������0000644�0001750�0001750�00000007330�14266344767�017214� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2017 Joe Wreschnig, Michael Urman, Iñigo Serna, Christoph Reiter # 2013-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import re import os from typing import Iterable from senf import fsn2bytes, bytes2fsn, fsnative from quodlibet import _ from quodlibet import app from quodlibet import config from quodlibet.qltk.notif import Task from quodlibet.util.dprint import print_d from quodlibet.util import copool, is_windows from quodlibet.query import Query from quodlibet.qltk.songlist import SongList from quodlibet.util.string import split_escape, join_escape def background_filter(): """Returns a filter function for AudioFile or None if nothing should be filtered. The filter is meant to be used globally to hide songs from the main library. Returns: function or None """ bg = config.gettext("browsers", "background") if not bg: return query = Query(bg, SongList.star) if query.is_parsable: return query.search def split_scan_dirs(joined_paths): """Returns a list of paths Args: joined_paths (fsnative) Return: list """ assert isinstance(joined_paths, fsnative) if is_windows(): # we used to separate this config with ":", so this is tricky return list( filter(None, re.findall(r"[a-zA-Z]:[\\/][^:]*", joined_paths))) else: return list(filter(None, split_escape(joined_paths, ":"))) def get_scan_dirs(): """Returns a list of paths which should be scanned Returns: list """ joined_paths = bytes2fsn(config.getbytes("settings", "scan"), "utf-8") return [os.path.expanduser(p) for p in split_scan_dirs(joined_paths)] def set_scan_dirs(dirs): """Saves a list of fs paths which should be scanned Args: list """ assert all(isinstance(d, fsnative) for d in dirs) if is_windows(): joined = fsnative(u":").join(dirs) else: joined = join_escape(dirs, fsnative(u":")) config.setbytes("settings", "scan", fsn2bytes(joined, "utf-8")) def get_exclude_dirs() -> Iterable[fsnative]: """:return: a list of paths which should be ignored during scanning""" paths = split_scan_dirs( bytes2fsn(config.getbytes("library", "exclude"), "utf-8")) return [os.path.expanduser(p) for p in paths] # type: ignore def scan_library(library, force): """Start the global library re-scan Args: library (Library) force (bool): if True, reload all existing valid items TODO: consider storing scan_dirs in Library instead of passing around always """ paths = get_scan_dirs() exclude = get_exclude_dirs() copool.add(library.rebuild, paths, force, exclude, cofuncid="library", funcid="library") def emit_signal(songs, signal="changed", block_size=50, name=None, cofuncid=None): """ A generator that signals `signal` on the library in blocks of `block_size`. Useful for copools. """ i = 0 with Task(_("Library"), name or signal) as task: if cofuncid: task.copool(cofuncid) total = len(songs) while i < total: more = songs[i:i + block_size] if not more: return if 0 == ((i / block_size) % 10): print_d("Signalling '%s' (%d/%d songs)" % (signal, i, total)) task.update(float(i) / total) app.library.emit(signal, more) i += block_size yield ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/logging.py�����������������������������������������������������������0000664�0001750�0001750�00000004060�14035600052�017145� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import import collections import threading class Logs: """Thread safe log store""" MAX_LOG_SIZE_DEFAULT = 500 def __init__(self, max_log_size=MAX_LOG_SIZE_DEFAULT): self._iter_lock = threading.Lock() self._log = collections.deque(maxlen=max_log_size) def _save_iter(self): # only pop/append/len are threadsafe, implement iter with them with self._iter_lock: temp = collections.deque() for i in range(len(self._log)): item = self._log.popleft() yield item temp.append(item) while temp: self._log.appendleft(temp.pop()) def log(self, string, category=None): """Log str/unicode. Thread safe. """ self._log.append((category, string)) def clear(self): """Remove all entries. Thread safe. """ with self._iter_lock: for i in range(len(self._log)): self._log.popleft() def get_content(self, category=None, limit=None): """Get a list of unicode strings for the specified category. Oldest entry first. Passing no category will return all content. If `limit` is specified, the last `limit` items will be returned. Thread safe. """ content = [] for cat, string in self._save_iter(): if category is None or category == cat: if isinstance(string, bytes): string = string.decode("utf-8", "replace") content.append(string) if limit is not None: assert limit > 0 return content[-limit:] return content _logs = Logs() log = _logs.log get_content = _logs.get_content ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/massagers.py���������������������������������������������������������0000664�0001750�0001750�00000013720�14035600052�017507� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Iñigo Serna, Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import locale import re from typing import List, Dict from quodlibet import _ from .iso639 import ISO_639_2 class ValidationError(Exception): pass class Massager: """Massage a tag value from various 'okay' formats to the 'correct' format.""" tags: List[str] = [] error = "Metaerror. This should be overridden in subclasses." options: List[str] = [] _massagers: "Dict[str, Massager]" = {} def validate(self, value): """Returns a validated value. Raises ValidationError if invalid. """ raise NotImplementedError def is_valid(self, value): """Returns True if a field is valid, False if not""" try: self.validate(value) except ValidationError: return False return True @classmethod def _register(cls, other): """Register a new massager implementation""" assert issubclass(other, Massager) assert other.tags for tag in other.tags: cls._massagers[tag] = other return other @classmethod def get_massagers(cls): """Returns all massager subclasses""" return set(cls._massagers.values()) @classmethod def for_tag(cls, tag): """Returns a massager instance for the tag or raises KeyError""" return cls._massagers[tag]() def validate(tag, value): """Validate a value based on the tag. Raises ValidationError if invalid """ try: return Massager.for_tag(tag).validate(value) except KeyError: return value def is_valid(tag, value): """Returns True if the fields is valid""" try: return Massager.for_tag(tag).is_valid(value) except KeyError: return True def error_message(tag, value): """Returns an error message for invalid tag values""" try: return Massager.for_tag(tag).error except KeyError: return u"" def get_options(tag): """Returns a list of suggested values for the tag. If the list is empty this either means that the tag is unknown or the set of valid values would be too large""" try: return list(Massager.for_tag(tag).options) except KeyError: return [] @Massager._register class DateMassager(Massager): tags = ["date"] error = _("The date must be entered in 'YYYY', 'YYYY-MM-DD' or " "'YYYY-MM-DD HH:MM:SS' format.") __match = re.compile(r"^\d{4}([-.]\d{2}([-.]\d{2}([T ]\d{2}" r"([:.]\d{2}([:.]\d{2})?)?)?)?)?$").match def validate(self, value): value = value.strip().replace(".", "-").replace("/", "-") if not self.__match(value): raise ValidationError return value @Massager._register class GainMassager(Massager): tags = ["replaygain_album_gain", "replaygain_track_gain"] error = _("Replay Gain gains must be entered in 'x.yy dB' format.") __match = re.compile(r"^[+-]\d+\.?\d+?\s+dB$").match def validate(self, value): if self.__match(value): return value else: try: f = float(value.split()[0]) except (IndexError, TypeError, ValueError): try: f = locale.atof(value.split()[0]) except (IndexError, TypeError, ValueError): raise ValidationError else: return (u"%+f" % f).rstrip("0") + " dB" @Massager._register class PeakMassager(Massager): tags = ["replaygain_album_peak", "replaygain_track_peak"] error = _("Replay Gain peaks must be entered in 'x.yy' format.") def validate(self, value): value = value.strip() try: f = float(value) except (TypeError, ValueError): try: f = locale.atof(value) except (TypeError, ValueError): raise ValidationError else: if f < 0 or f >= 2: raise ValidationError return str(f) @Massager._register class MBIDMassager(Massager): tags = ["musicbrainz_trackid", "musicbrainz_albumid", "musicbrainz_artistid", "musicbrainz_albumartistid", "musicbrainz_trmid", "musicip_puid"] error = _("MusicBrainz IDs must be in UUID format.") def validate(self, value): value = value.encode('ascii', 'replace').decode("ascii") value = u"".join(filter(str.isalnum, value.strip().lower())) try: int(value, 16) except ValueError: raise ValidationError else: if len(value) != 32: raise ValidationError else: return u"-".join([value[:8], value[8:12], value[12:16], value[16:20], value[20:]]) @Massager._register class MBAlbumStatus(Massager): tags = ["musicbrainz_albumstatus"] # Translators: Leave "official", "promotional", and "bootleg" # untranslated. They are the three possible literal values. error = _("MusicBrainz release status must be 'official', " "'promotional', or 'bootleg'.") options = ["official", "promotional", "bootleg"] def validate(self, value): if value not in self.options: raise ValidationError return value @Massager._register class LanguageMassager(Massager): tags = ["language"] error = _("Language must be an ISO 639-2 three-letter code") options = ISO_639_2 tags = ["language"] def validate(self, value): # Issue 439: Actually, allow free-text through return value def is_valid(self, value): # Override, to allow empty string to be a valid language (freetext) return True ������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1681489057.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/matcher.py�����������������������������������������������������������0000644�0001750�0001750�00000042141�14416276241�017156� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2021 Joschua Gandert # # 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 2 of the License, or # (at your option) any later version. from difflib import SequenceMatcher from operator import itemgetter from typing import Generic, TypeVar, Mapping, Union, List, Sequence, \ Optional, Tuple T = TypeVar('T') Real = Union[int, float] AttributeGetter = itemgetter AttributeGetterToWeight = Mapping[AttributeGetter, Real] SUPPORTED_NUMBER_TYPES = (int, float) class _MatchData(Generic[T]): a_value: T best_b_idx: Optional[int] second_best_b_idx: Optional[int] def __init__(self, a_idx: int, a_value: T, b_size: int): self.a_idx = a_idx self.a_value = a_value self.b_idx_to_similarity = [0.0 for _ in range(b_size)] self.best_b_idx = None self.best_b_similarity = float('-inf') self.second_best_b_idx = None self.second_best_b_similarity = float('-inf') self.continue_attr_index = 0 # rarely needed since in a lot of cases there won't be conflicts self._sorted_b_similarity_with_idx_pairs = None self.is_fully_measured = False def add_similarity(self, b_idx: int, similarity_part: float): """ Add part of the similarity (i.e. the first attribute) to the similarity between a_value and the b_value at the supplied index. """ self.b_idx_to_similarity[b_idx] += similarity_part b_idx_total_similarity = self.b_idx_to_similarity[b_idx] if b_idx_total_similarity > self.best_b_similarity: self.second_best_b_idx = self.best_b_idx self.second_best_b_similarity = self.best_b_similarity self.best_b_idx = b_idx self.best_b_similarity = b_idx_total_similarity elif b_idx_total_similarity > self.second_best_b_similarity: self.second_best_b_idx = b_idx self.second_best_b_similarity = b_idx_total_similarity def replace_best_with_next_best(self): if self._sorted_b_similarity_with_idx_pairs is None: # We sort so last = best as calling pop() on a list is O(1) # We negate the index here, so that the sorting is correct if the # similarities of two b's are the same (lowest index last) self._sorted_b_similarity_with_idx_pairs = sorted( ((s, -i) for i, s in enumerate(self.b_idx_to_similarity))) if not self._sorted_b_similarity_with_idx_pairs: return self._sorted_b_similarity_with_idx_pairs.pop() if not self._sorted_b_similarity_with_idx_pairs: # None left, which means all others a's have better values # than this one. As a result, this a will stay alone :( self.best_b_idx = None self.best_b_similarity = float('-inf') return sim, idx = self._sorted_b_similarity_with_idx_pairs[-1] self.best_b_idx = -idx self.best_b_similarity = sim class ObjectListMatcher(Generic[T]): """ Utility class that compares the objects of two lists (all the same type), and finds the best matches. What is considered a good match depends on the supplied mapping, which maps "attribute getter" functions to their weight. Weights are normalized, so you can use values > 1. A specific getter has to return objects of only one of these types: - Real number (e.g. int or float) - compared by 1 - abs(delta) / max_delta - Other non-Sequence - converted to str which is a Sequence and then.. - Sequence - compared using difflib.SequenceMatcher The problem this solves is called the "Assignment problem". Note that this class will not necessarily call every attribute function and thus not use its weight in the calculation, as it will avoid doing unnecessary calculations when the current best match for an element is undefeatable. For example, let's say we have an attribute x with weight 0.8 and an attribute y with weight 0.2. If, after checking the similarity on attribute x with all items, the highest similarity is 0.8 (it was equal to the compared item) and the second highest has a similarity of 0.5, then we won't check attribute y at all, as the second best cannot possibly win with the remaining weight (0.5 + 0.2 < 0.8). However, whenever there's a conflict (two elements match to one), the full similarity scores of the affected elements will always be calculated.""" similarity_matrix: List[List[float]] minimum_similarity_ratio: float _matcher: SequenceMatcher _attr_with_weight: List[Tuple[itemgetter, float]] _b_idx_to_a_match_data: List[Optional[_MatchData]] def __init__(self, attr_to_weight: AttributeGetterToWeight): self.update_attr_to_weight(attr_to_weight) self._matcher = SequenceMatcher() self.should_store_similarity_matrix = False """Whether or not to store the similarity_matrix. You may want to enable should_go_through_every_attribute to make similarity scores between different a_items more comparable. Without it, the algorithm may have stopped before evaluating all attributes for one a_item.""" self.similarity_matrix = [] """This will be recreated whenever get_indices is called, given that if should_store_similarity_matrix is True. It's a matrix that has the same number of elements as a_items. Each of those lists has the same number of elements as b_items. Those elements represent how similar an a item is to each b item. So matrix[a_idx][b_idx] gives you the similarity between the a item and b item at those indices. A similarity of 1 means that every attribute was evaluated and equal to the other.""" self.minimum_similarity_ratio = 0.0 """A value in the range [0, 1] that defines what similarity is required to be a valid match. Setting this to a reasonable value will speed up the calculation as low-quality matches will be discarded before a match conflict can even arise. Note that this isn't using the absolute similarity for comparison, because that would lead to confusing results, given that by default this class only evaluates weights and attributes if there is no decisive winner (best match) yet. Instead, it's using the absolute similarity divided by the current maximum possible weight. Enable should_go_through_every_attribute so the full and thus absolute similarity score is compared to the minimum.""" self.should_go_through_every_attribute = False """Whether or not to go through every attribute and weight. If False, this class only goes through weights until one element is undefeatable.""" @classmethod def for_sequence(cls, weights: Sequence[Real]): """Creates a matcher where itemgetter(n) is mapped to weights[n]""" attr_to_weight = {itemgetter(n): w for n, w in enumerate(weights)} return ObjectListMatcher(attr_to_weight) @classmethod def for_one_attr(cls, attr: AttributeGetter): """Creates a matcher where a single attribute of the objects are compared.""" return ObjectListMatcher({attr: 1}) @classmethod def of_identity(cls): """Creates a matcher where only the objects themselves are compared.""" return cls.for_one_attr(lambda i: i) def update_attr_to_weight(self, attr_to_weight: AttributeGetterToWeight): if not attr_to_weight: raise ValueError("there must be at least one weight") # normalize weight_sum = sum(attr_to_weight.values()) self._attr_with_weight = [] for attr, weight in attr_to_weight.items(): if weight <= 0: raise ValueError("weights <= 0 are not allowed") self._attr_with_weight.append((attr, weight / weight_sum)) # from largest to smallest weight self._attr_with_weight.sort(key=lambda i: i[1], reverse=True) weight_left = 1.0 self._weight_left = [] for _, weight in self._attr_with_weight: self._weight_left.append(weight_left) weight_left -= weight def get_indices(self, a_items: List[T], b_items: List[T]) -> List[Optional[int]]: """ :return: the indices of b ordered so that they match elements in a. Size of a_items and b_items can differ. If there are more a_items than there are b_items, None is used if no match could be assigned to an a. The returned list always has the size of a_items. In terms of performance, it's preferable to supply the smaller list as a_items. """ if not b_items: return [None for _ in a_items] self._b_items = b_items b_size = len(b_items) self._b_idx_to_a_match_data = [None for _ in range(b_size)] self._a_idx_to_match_data = [] for a_idx, a in enumerate(a_items): match_data = _MatchData(a_idx, a, b_size) self._a_idx_to_match_data.append(match_data) self._measure_similarity_to_find_best_b_match(match_data) if self._is_below_minimum_similarity(match_data): match_data.best_b_idx = None else: self._handle_conflicts_if_any(match_data) result = [md.best_b_idx for md in self._a_idx_to_match_data] if self.should_store_similarity_matrix: matrix = [md.b_idx_to_similarity for md in self._a_idx_to_match_data] self.similarity_matrix = matrix # cleanup del self._b_items del self._b_idx_to_a_match_data del self._a_idx_to_match_data return result def _is_below_minimum_similarity(self, match_data): cont_attr_idx = match_data.continue_attr_index similarity = match_data.best_b_similarity # If this hasn't gone through every attribute and weight yet, we normalize the # similarity, so it's in the range of [0, 1]. Without this, minimum_similarity # would be somewhat unpredictable. # # For example, a b_item might be undefeatable with a similarity of 0.52. If we # wouldn't normalize it, it would not pass a minimum of 0.6, even if it could # easily achieve that with the remaining weights. if cont_attr_idx < len(self._attr_with_weight): # The index cannot be zero here, as we'll always go through at least one # attribute before reaching this. As a result the weight_left[index] will # never be one, and so a ZeroDivisionError is impossible in this function. cur_total_weight = 1 - self._weight_left[cont_attr_idx] similarity /= cur_total_weight return similarity < self.minimum_similarity_ratio def _handle_conflicts_if_any(self, a_match_data_to_check): while True: best_b_idx = a_match_data_to_check.best_b_idx if best_b_idx is None: # a1 has no matches left or could not find a match return other_a_match_data = self._b_idx_to_a_match_data[best_b_idx] if other_a_match_data is None: self._b_idx_to_a_match_data[best_b_idx] = a_match_data_to_check return # We have found a conflict and will now solve it. a_match_data_to_check = self._get_losing_match_data(a_match_data_to_check, other_a_match_data) def _get_losing_match_data(self, a1_match_data, a2_match_data): """Return the match data of the element that lost the conflict""" # b is matched to a previous a (a2), so we have to find a better match but first # we need to fully measure the similarity of both, so the comparison is fair self._finish_similarity_measures(a1_match_data) self._finish_similarity_measures(a2_match_data) # As the index of a1 will almost always be larger than a2, we use <= # here, since in case they're equal in terms of similarity, we want to # give some weight to the current order of b (index 0 preferred to 1). if a1_match_data.best_b_similarity <= a2_match_data.best_b_similarity: a1_match_data.replace_best_with_next_best() # still need to find a better match for a1 return a1_match_data else: # a1 is better so replace a2 in map best_b_idx = a1_match_data.best_b_idx self._b_idx_to_a_match_data[best_b_idx] = a1_match_data a2_match_data.replace_best_with_next_best() # we need to find a new match for a2 return a2_match_data def _finish_similarity_measures(self, a_match_data): """Only if this was called, is match data full measured and only then can match_data.replace_best() be called.""" if a_match_data.is_fully_measured: return # figure out total similarity (without stopping) if we didn't self._measure_similarity_to_find_best_b_match(a_match_data) a_match_data.is_fully_measured = True def _measure_similarity_to_find_best_b_match(self, a_match_data): continue_attr_idx = a_match_data.continue_attr_index can_stop = continue_attr_idx == 0 and not self.should_go_through_every_attribute attr_size = len(self._attr_with_weight) for attr_idx in range(continue_attr_idx, attr_size): # stop if one has more similarity than is possible for the rest if can_stop and self._is_max_similarity_undefeatable(attr_idx, a_match_data): a_match_data.continue_attr_index = attr_idx return self._measure_similarity_for_attr(attr_idx, a_match_data) a_match_data.continue_attr_index = attr_size def _is_max_similarity_undefeatable(self, attr_idx, a_match_data): # Must only be called at the start of the loop. # We need a second best, so we can check if they have any chance. if a_match_data.second_best_b_idx is None: return False # Any similarity has to be in [0, 1], so the following is the maximum # similarity that could be achieved with the remaining attr / weights optimal_second_best_similarity = self._weight_left[attr_idx] # Now we add the second best similarity, since we want to know if it's # even possible for the second best to win against the current best optimal_second_best_similarity += a_match_data.second_best_b_similarity return optimal_second_best_similarity < a_match_data.best_b_similarity def _measure_similarity_for_attr(self, attr_idx, a_match_data): get_attr, weight = self._attr_with_weight[attr_idx] a_attr = get_attr(a_match_data.a_value) # isinstance does not work with Union, so we need to use a tuple here if isinstance(a_attr, SUPPORTED_NUMBER_TYPES): self._add_number_similarity(a_match_data, a_attr, get_attr, weight) return if not isinstance(a_attr, Sequence): a_attr = str(a_attr) def get_attr(obj, original_get_attr=get_attr): return str(original_get_attr(obj)) # replace it so we don't have to do this again for this attr_idx self._attr_with_weight[attr_idx] = (get_attr, weight) self._add_sequence_similarity(a_match_data, a_attr, get_attr, weight) def _add_number_similarity(self, a_match_data, a_attr, get_attr, weight): deltas = [abs(get_attr(b) - a_attr) for b in self._b_items] max_delta = max(deltas) if max_delta == 0: if a_match_data.best_b_idx is None: # We try to set a match here manually to avoid the situation where # nothing is matched to an a element just because all are the same. # In all other cases MatchData's add_similarity takes care of this. for b_idx, match_data in enumerate(self._b_idx_to_a_match_data): # find the first b index that's not matched to an a element if match_data is None: a_match_data.best_b_idx = b_idx a_match_data.best_b_similarity = 0 break # no delta, so all the same and no change in similarity return # also let's avoid division by zero for b_idx, delta in enumerate(deltas): # if delta is small relative to max, similarity is higher # for example, if delta is 0, b_attr is the same as a_attr similarity = weight * (1 - delta / max_delta) a_match_data.add_similarity(b_idx, similarity) def _add_sequence_similarity(self, a_match_data, a_attr, get_attr, weight): matcher = self._matcher # set_seq2 is used here as it caches information (contrary to 1) matcher.set_seq2(a_attr) for b_idx, b in enumerate(self._b_items): matcher.set_seq1(get_attr(b)) a_match_data.add_similarity(b_idx, weight * matcher.ratio()) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/misc.py��������������������������������������������������������������0000644�0001750�0001750�00000004601�14266344767�016501� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys import tempfile from functools import wraps from senf import path2fsn from .environment import is_linux def cmp(a, b): return (a > b) - (a < b) def cached_func(f): """Decorator which caches the return value of a function which doesn't take any input. """ res = [] @wraps(f) def wrapper(): if not res: res.append(f()) return res[0] return wrapper def total_ordering(cls): """Adds all possible ordering methods to a class. Needs a working __eq__ and __lt__ and will supply the rest. """ assert "__eq__" in cls.__dict__ assert "__lt__" in cls.__dict__ cls.__le__ = lambda self, other: self == other or self < other cls.__gt__ = lambda self, other: not (self == other or self < other) cls.__ge__ = lambda self, other: not self < other cls.__ne__ = lambda self, other: not self.__eq__(other) return cls def hashable(cls): """Makes sure the class is hashable. Needs a working __eq__ and __hash__ and will add a __ne__. """ # py2 assert "__hash__" in cls.__dict__ # py3 assert cls.__dict__["__hash__"] is not None assert "__eq__" in cls.__dict__ cls.__ne__ = lambda self, other: not self.__eq__(other) return cls def get_module_dir(module=None): """Returns the absolute path of a module. If no module is given the one this is called from is used. """ if module is None: file_path = sys._getframe(1).f_globals["__file__"] else: file_path = getattr(module, "__file__") file_path = path2fsn(file_path) return os.path.dirname(os.path.realpath(file_path)) def get_ca_file(): """A path to a CA file or None. Depends whether we use certifi or the system trust store on the current platform. """ if is_linux(): return None import certifi return os.path.join(get_module_dir(certifi), "cacert.pem") def NamedTemporaryFile(*args, **kwargs): """Like tempfile.NamedTemporaryFile, but supports unicode paths on Py2+Windows """ return tempfile.NamedTemporaryFile(*args, **kwargs) �������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/modulescanner.py�����������������������������������������������������0000664�0001750�0001750�00000011130�14035600052�020352� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys import importlib from os.path import dirname from traceback import format_exception from quodlibet.util.path import mtime from quodlibet.util.importhelper import get_importables, load_module from quodlibet.util import print_d class Module: def __init__(self, name, module, deps, path): self.name = name self.module = module self.path = path self.deps = {} for dep in deps: self.deps[dep] = mtime(dep) def has_changed(self, dep_paths): if set(self.deps.keys()) != set(dep_paths): return True for path, old_mtime in self.deps.items(): if mtime(path) != old_mtime: return True return False def __repr__(self): return "<%s name=%r>" % (type(self).__name__, self.name) class ModuleImportError: def __init__(self, name, exception, traceback): self.name = name self.exception = exception self.traceback = traceback class ModuleScanner: """ Handles plugin modules. Takes a list of directories and searches for loadable python modules/packages in all of them. There is only one global namespace for modules using the module name as key. rescan() - Update the module list. Returns added/removed module names failures - A dict of Name: (Exception, Text) for all modules that failed modules - A dict of Name: Module for all successfully loaded modules """ def __init__(self, folders): self.__folders = folders self.__modules = {} # name: module self.__failures = {} # name: exception @property def failures(self): """A name: exception dict for all modules that failed to load""" return self.__failures @property def modules(self): """A name: module dict of all loaded modules""" return self.__modules def rescan(self): """Rescan all folders for changed/new/removed modules. The caller should release all references to removed modules. Returns a tuple: (removed, added) """ print_d("Rescanning..") info = {} # get what is there atm for folder in self.__folders: for name, path, deps in get_importables(folder): # take the basename as module key, later modules win info[name] = (path, deps) # python can not unload a module, so we can only add new ones # or reload if the path is the same and mtime changed, # but we can still pretend we removed something removed = [] added = [] # remove those that are gone and changed ones for name, mod in list(self.__modules.items()): # not here anymore, remove if name not in info: del self.__modules[name] removed.append(name) continue # check if any dependency has changed path, new_deps = info[name] if mod.has_changed(new_deps): del self.__modules[name] removed.append(name) self.__failures.clear() # add new ones for (name, (path, deps)) in info.items(): if name in self.__modules: continue try: # add a real module, so that pickle works # https://github.com/quodlibet/quodlibet/issues/1093 parent = "quodlibet.fake" if parent not in sys.modules: spec = importlib.machinery.ModuleSpec( parent, None, is_package=True) sys.modules[parent] = importlib.util.module_from_spec(spec) vars(sys.modules["quodlibet"])["fake"] = sys.modules[parent] mod = load_module(name, parent + ".plugins", dirname(path)) if mod is None: continue except Exception as err: text = format_exception(*sys.exc_info()) self.__failures[name] = ModuleImportError(name, err, text) else: added.append(name) self.__modules[name] = Module(name, mod, deps, path) print_d("Rescanning done: %d added, %d removed, %d error(s)" % (len(added), len(removed), len(self.__failures))) return removed, added ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684322551.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/path.py��������������������������������������������������������������0000644�0001750�0001750�00000034756�14431134367�016503� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011-2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import io import re import stat import sys import errno import codecs import shlex from urllib.parse import urlparse, quote, unquote from gi.repository import GLib from senf import (fsnative, bytes2fsn, fsn2bytes, fsn2text, path2fsn, uri2fsn, _fsnative) from . import windows from .environment import is_windows from .misc import NamedTemporaryFile if sys.platform == "darwin": from Foundation import NSString def mkdir(dir_, *args): """Make a directory, including all its parent directories. This does not raise an exception if the directory already exists (and is a directory).""" try: os.makedirs(dir_, *args) except OSError as e: if e.errno != errno.EEXIST or not os.path.isdir(dir_): raise def uri2gsturi(uri): """Takes a correct uri and returns a gstreamer-compatible uri""" if not is_windows(): return uri try: # gstreamer requires extra slashes for network shares return GLib.filename_to_uri(uri2fsn(uri)) except (GLib.Error, ValueError): return uri def iscommand(s): """True if an executable file `s` exists in the user's path, or is a fully qualified and existing executable file.""" if s == "" or os.path.sep in s: return os.path.isfile(s) and os.access(s, os.X_OK) else: s = s.split()[0] path = os.environ.get('PATH', '') or os.defpath for p in path.split(os.path.pathsep): p2 = os.path.join(p, s) if os.path.isfile(p2) and os.access(p2, os.X_OK): return True else: return False def listdir(path, hidden=False): """List files in a directory, sorted, fully-qualified. If hidden is false, Unix-style hidden files are not returned. """ assert isinstance(path, fsnative) if hidden: filt = None else: filt = lambda base: not base.startswith(".") if path.endswith(os.sep): join = "".join else: join = os.sep.join return [join([path, basename]) for basename in sorted(os.listdir(path)) if filt(basename)] def mtime(filename): """Return the mtime of a file, or 0 if an error occurs.""" try: return os.path.getmtime(filename) except OSError: return 0 def filesize(filename): """Return the size of a file, or 0 if an error occurs.""" try: return os.path.getsize(filename) except OSError: return 0 def escape_filename(s: str, safe: bytes = b''): """Escape a string in a manner suitable for a filename. Args: s (str) The string to convert safe (bytes) A string of characters that needn't be quoted Returns: fsnative """ s = str(s) quoted = quote(s, safe=safe, encoding='utf-8') if isinstance(quoted, bytes): return bytes2fsn(quoted, "utf-8") return bytes2fsn(quoted.encode("ascii"), "utf-8") def unescape_filename(filename: _fsnative) -> str: """Unescape a string in a manner suitable for a filename. Args: filename (fsnative) Returns: str """ assert isinstance(filename, fsnative) return fsn2text(unquote(filename)) def join_path_with_escaped_name_of_legal_length(path: str, stem: str, ext: str) -> str: """Returns a path joined with the escaped stem and the unescaped extension. Stem is trimmed until the filename fits into the filesystems maximum file length""" # returns the maximum possible filename length at path (subtract one for dot) max_stem_length = os.pathconf(path, 'PC_NAME_MAX') - 1 - len(ext) escaped_stem = escape_filename(stem) while len(escaped_stem) > max_stem_length: # We don't want to break the escaping, so we only trim the actual name stem = stem[:max_stem_length] max_stem_length -= 1 escaped_stem = escape_filename(stem) return os.path.join(path, f'{escaped_stem}.{ext}') def stem_of_file_name(file_name: str) -> str: """:return: file name without the extension. Note these examples showcasing edge cases: >>> stem_of_file_name('a.b.c') 'a.b' >>> stem_of_file_name('.test') '.test' """ return os.path.splitext(file_name)[0] def extension_of_file_name(file_name: str) -> str: """:return: extension of the file name. Is empty, or starts with a period. Note these examples showcasing edge cases: >>> extension_of_file_name('a.b.c') '.c' >>> extension_of_file_name('.test') '' """ return os.path.splitext(file_name)[-1] def unexpand(filename): """Replace the user's home directory with ~ or %USERPROFILE%, if it appears at the start of the path name. Args: filename (fsnative): The file path Returns: fsnative: The path with the home directory replaced """ sub = (os.name == "nt" and fsnative(u"%USERPROFILE%")) or fsnative(u"~") home = os.path.normcase(get_home_dir()).rstrip(os.path.sep) norm = os.path.normcase(filename) if norm == home: return sub elif norm.startswith(home + os.path.sep): filename = sub + filename[len(home):] return filename if is_windows(): def ismount(path): # this can raise on py3+win, but we don't care try: return os.path.ismount(path) except OSError: return False else: ismount = os.path.ismount def find_mount_point(path): while not ismount(path): path = os.path.dirname(path) return path def xdg_get_system_data_dirs(): """http://standards.freedesktop.org/basedir-spec/latest/""" if os.name == "nt": from gi.repository import GLib dirs = [] for dir_ in GLib.get_system_data_dirs(): dirs.append(dir_) return dirs data_dirs = os.getenv("XDG_DATA_DIRS") if data_dirs: return [os.path.abspath(d) for d in data_dirs.split(":")] else: return ("/usr/local/share/", "/usr/share/") def xdg_get_cache_home(): if os.name == "nt": from gi.repository import GLib return GLib.get_user_cache_dir() data_home = os.getenv("XDG_CACHE_HOME") if data_home: return os.path.abspath(data_home) else: return os.path.join(os.path.expanduser("~"), ".cache") def xdg_get_data_home(): if os.name == "nt": from gi.repository import GLib return GLib.get_user_data_dir() data_home = os.getenv("XDG_DATA_HOME") if data_home: return os.path.abspath(data_home) else: return os.path.join(os.path.expanduser("~"), ".local", "share") def xdg_get_config_home(): if os.name == "nt": from gi.repository import GLib return GLib.get_user_config_dir() data_home = os.getenv("XDG_CONFIG_HOME") if data_home: return os.path.abspath(data_home) else: return os.path.join(os.path.expanduser("~"), ".config") def parse_xdg_user_dirs(data): """Parses xdg-user-dirs and returns a dict of keys and paths. The paths depend on the content of environ while calling this function. See http://www.freedesktop.org/wiki/Software/xdg-user-dirs/ Args: data (bytes) Can't fail (but might return garbage). """ assert isinstance(data, bytes) paths = {} for line in data.splitlines(): if line.startswith(b"#"): continue parts = line.split(b"=", 1) if len(parts) <= 1: continue key = parts[0] try: values = shlex.split(bytes2fsn(parts[1], "utf-8")) except ValueError: continue if len(values) != 1: continue paths[key] = os.path.normpath(os.path.expandvars(values[0])) return paths def xdg_get_user_dirs(): """Returns a dict of xdg keys to paths. The paths don't have to exist.""" config_home = xdg_get_config_home() try: with open(os.path.join(config_home, "user-dirs.dirs"), "rb") as h: return parse_xdg_user_dirs(h.read()) except EnvironmentError: return {} def get_temp_cover_file(data): """Returns a file object or None""" try: # pass fsnative so that mkstemp() uses unicode on Windows fn = NamedTemporaryFile(prefix=fsnative(u"tmp")) fn.write(data) fn.flush() fn.seek(0, 0) except EnvironmentError: return else: return fn def _strip_win32_incompat(string, BAD=r'\:*?;"<>|'): """Strip Win32-incompatible characters from a Windows or Unix path.""" if os.name == "nt": BAD += "/" if not string: return string new = "".join((s in BAD and "_") or s for s in string) parts = new.split(os.sep) def fix_end(string): return re.sub(r'[\. ]$', "_", string) return os.sep.join(fix_end(p) for p in parts) def strip_win32_incompat_from_path(string): """Strip Win32-incompatible chars from a path, ignoring os.sep and the drive part""" drive, tail = os.path.splitdrive(string) tail = os.sep.join(_strip_win32_incompat(s) for s in tail.split(os.sep)) return drive + tail def _normalize_darwin_path(filename, canonicalise=False): filename = path2fsn(filename) if canonicalise: filename = os.path.realpath(filename) filename = os.path.normpath(filename) data = fsn2bytes(filename, "utf-8") decoded = data.decode("utf-8", "quodlibet-osx-path-decode") try: return bytes2fsn( NSString.fileSystemRepresentation(decoded), "utf-8") except ValueError: return filename def _normalize_path(filename, canonicalise=False): """Normalize a path on Windows / Linux If `canonicalise` is True, dereference symlinks etc by calling `os.path.realpath` """ filename = path2fsn(filename) if canonicalise: filename = os.path.realpath(filename) filename = os.path.normpath(filename) return os.path.normcase(filename) if sys.platform == "darwin": def _osx_path_decode_error_handler(error): bytes_ = bytearray(error.object[error.start:error.end]) return u"".join("%%%X".__mod__(b) for b in bytes_), error.end codecs.register_error( "quodlibet-osx-path-decode", _osx_path_decode_error_handler) normalize_path = _normalize_darwin_path else: normalize_path = _normalize_path def path_equal(p1, p2, canonicalise=False): return normalize_path(p1, canonicalise) == normalize_path(p2, canonicalise) def limit_path(path, ellipsis=True): """Reduces the filename length of all filenames in the given path to the common maximum length for current platform. While the limits are depended on the file system and more restrictions may apply, this covers the common case. """ assert isinstance(path, fsnative) main, ext = os.path.splitext(path) parts = main.split(os.sep) for i, p in enumerate(parts): # Limit each path section to 255 (bytes on linux, chars on win). # http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits limit = 255 if i == len(parts) - 1: limit -= len(ext) if len(p) > limit: if ellipsis: p = p[:limit - 2] + fsnative(u"..") else: p = p[:limit] parts[i] = p return os.sep.join(parts) + ext def get_home_dir(): """Returns the root directory of the user, /home/user or C:\\Users\\user""" if os.name == "nt": return windows.get_profile_dir() else: return os.path.expanduser("~") def is_hidden(path: _fsnative) -> bool: """Returns if a directory / file is considered hidden by the platform. Hidden meaning the user should normally not be exposed to those files when opening the parent directory in the default file manager using the default settings. Does not check if any of the parents are hidden. If the file / dir does not exist, the result is implementation defined. :param path: the path to check :return: True if and only if the path is considered hidden on the system """ if sys.platform == "windows": return bool(os.stat(path).st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN) basename = os.path.basename(path) # Let's allow "...and Justice For All" etc (#3916) return basename.startswith(".") and basename[1:2] != "." def uri_is_valid(uri): """Returns True if the passed in text is a valid URI (file, http, etc.) Args: uri(text or bytes) Returns: bool """ try: if isinstance(uri, bytes): uri.decode("ascii") elif not isinstance(uri, bytes): uri = uri.encode("ascii") except ValueError: return False parsed = urlparse(uri) if not parsed.scheme or not len(parsed.scheme) > 1: return False elif not (parsed.netloc or parsed.path): return False else: return True class RootPathFile: """Simple container used for discerning a pathfile's 'root' directory and 'end' part. The variable depth of a pathfile's 'end' part renders os.path built-ins (basename etc.) useless for this purpose""" _root = '' # 'root' of full file path _pathfile = '' # full file path def __init__(self, root, pathfile): self._root = root self._pathfile = pathfile @property def root(self): return self._root @property def end(self): return self._pathfile[len(self._root) + len(os.sep):] @property def pathfile(self): return self._pathfile @property def end_escaped(self): escaped = [escape_filename(part) for part in self.end.split(os.path.sep)] return os.path.sep.join(escaped) @property def pathfile_escaped(self): return os.path.sep.join([self.root, self.end_escaped]) @property def valid(self): valid = True if os.path.exists(self.pathfile): return valid else: try: with io.open(self.pathfile, "w", encoding='utf-8') as f: f.close() # do nothing except OSError: valid = False if os.path.exists(self.pathfile): os.remove(self.pathfile) return valid ������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/picklehelper.py������������������������������������������������������0000664�0001750�0001750�00000005611�14035600052�020171� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """One interface for pickle/cPickle for both Python 2/3""" from io import BytesIO, BufferedReader import pickle from pickle import PicklingError, UnpicklingError, PickleError PickleError def pickle_dumps(obj, protocol=0): """Like pickle.dumps Raises: pickle.PicklingError """ if not 0 <= protocol <= 2: raise ValueError("Only protocol 0, 1, 2 allowed") try: # pickle.PicklingError is not cPickle.PicklingError # so this makes sure we only raise pickle.PicklingError even if # we use cPickle return pickle.dumps(obj, protocol) except PicklingError: raise except Exception as e: raise PicklingError(e) def pickle_dump(obj, file, protocol=0): """Like pickle.dump Raises: pickle.PicklingError """ if not 0 <= protocol <= 2: raise ValueError("Only protocol 0, 1, 2 allowed") try: return pickle.dump(obj, file, protocol) except PicklingError: raise except Exception as e: raise PicklingError(e) def pickle_load(file, lookup_func=None): """Allows unpickling with manual control over class lookup on both Python 2 and Python 3. Will unpickle from the current position to the final stop marker. lookup_func gets passed a function for global lookup, the mod name to import and the attribute name to return from the module The lookup function passed to the callback can raise ImportError or AttributeError. Args: file (fileobj) lookup_func (callable or None) Returns: The unpickled objects Raises: pickle.UnpicklingError """ if lookup_func is not None: class CustomUnpickler(pickle.Unpickler): def find_class(self, module, name): func = super().find_class return lookup_func(func, module, name) unpickler_type = CustomUnpickler else: unpickler_type = pickle.Unpickler # helps a lot, but only on py3 if isinstance(file, BytesIO): file = BufferedReader(file) inst = unpickler_type(file, encoding="bytes") try: return inst.load() except UnpicklingError: raise except Exception as e: # unpickle can fail in many ways raise UnpicklingError(e) def pickle_loads(data, lookup_func=None): """Like pickle_load() but takes bytes instead of a file-like Args: data (bytes) lookup_func (callable or None) Returns: The unpickled objects Raises: pickle.UnpicklingError """ return pickle_load(BytesIO(data), lookup_func=lookup_func) �����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/songwrapper.py�������������������������������������������������������0000644�0001750�0001750�00000011732�14327505043�020100� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Michael Urman # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _, ngettext from quodlibet.qltk.notif import Task from quodlibet.util import copool from quodlibet.util.dprint import print_w from quodlibet.formats import AudioFileError from quodlibet import util from quodlibet import qltk from quodlibet.util.misc import total_ordering, hashable @hashable @total_ordering class SongWrapper: __slots__ = ['_song', '_updated', '_needs_write'] def __init__(self, song): self._song = song self._updated = False self._needs_write = False def _was_updated(self): return self._updated def __setitem__(self, key, value): if key in self and self[key] == value: return self._updated = True self._needs_write = (self._needs_write or not key.startswith("~")) return self._song.__setitem__(key, value) def __delitem__(self, key): retval = self._song.__delitem__(key) self._updated = True self._needs_write = (self._needs_write or not key.startswith("~")) return retval def __getattr__(self, attr): return getattr(self._song, attr) def __setattr__(self, attr, value): # Don't set our attributes on the song. However, we only want to # set attributes the song already has. So, if the attribute # isn't one of ours, and isn't one of the song's, hand it off # to our parent's attribute handler for error handling. if attr in self.__slots__: return super().__setattr__(attr, value) elif hasattr(self._song, attr): return setattr(self._song, attr, value) else: return super().__setattr__(attr, value) def __hash__(self): return hash(self._song) def __eq__(self, other): if hasattr(other, '_song'): other = other._song return self._song == other def __lt__(self, other): if hasattr(other, '_song'): other = other._song return self._song < other def __getitem__(self, *args): return self._song.__getitem__(*args) def __contains__(self, key): return key in self._song def __call__(self, *args): return self._song(*args) def pop(self, *args): self._updated = True self._needs_write = True return self._song.pop(*args) def update(self, other): self._updated = True self._needs_write = True return self._song.update(other) def rename(self, newname): self._updated = True return self._song.rename(newname) def ListWrapper(songs): def wrap(song): if song is None: return None else: return SongWrapper(song) return [wrap(s) for s in songs] def check_wrapper_changed(library, songs): need_write = [s for s in songs if s._needs_write] if need_write: total = len(need_write) def generate(): msg = ngettext("Saving %d file", "Saving %d files", total) % total with Task(_("Auto-Saving"), msg) as task: yield for i, song in enumerate(need_write): try: song._song.write() except AudioFileError as e: dialog = qltk.ErrorMessage( None, _("Unable to edit song"), _("Saving %s failed. " "The file may be read-only, corrupted, or you " "do not have permission to edit it.") % util.bold(song('~basename')), escape_desc=False) dialog.run() print_w("Couldn't save song %s (%s)" % (song("~filename"), e)) else: task.update((i + 1) / total) yield # Small enough to see if there's only one or two, very small if lots interval = max(250 // total, 5) copool.add(generate, timeout=interval, funcid="update_wrapped_songs") _inform_library_of_changed(library, songs) def background_check_wrapper_changed(library, songs): for song in songs: if not song._needs_write: continue try: song._song.write() except AudioFileError as e: print_w("Couldn't save song %s (%s)" % (song("~filename"), e)) _inform_library_of_changed(library, songs) def _inform_library_of_changed(library, songs): changed = [] for song in songs: if song._was_updated(): changed.append(song._song) elif not song.valid() and song.exists(): library.reload(song._song) library.changed(changed) ��������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.014269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/��������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�016455� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/__init__.py���������������������������������������������������0000664�0001750�0001750�00000006325�14035600052�020572� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011,2013 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. def isascii(string): """Returns if the passed str/unicode is an ascii encoded string or unicode string containing only ascii code points. """ try: if isinstance(string, bytes): string.decode("ascii") else: string.encode("ascii") except UnicodeError: return False return True def decode(s, charset="utf-8"): """Decode a string; if an error occurs, replace characters and append a note to the string.""" try: return s.decode(charset) except UnicodeError: from quodlibet import _ return s.decode(charset, "replace") + " " + _("[Invalid Encoding]") def encode(s, charset="utf-8"): """Encode a string; if an error occurs, replace characters and append a note to the string.""" try: return s.encode(charset) except UnicodeError: from quodlibet import _ return (s + " " + _("[Invalid Encoding]")).encode(charset, "replace") def split_escape(string, sep, maxsplit=None, escape_char="\\"): """Like unicode/str/bytes.split but allows for the separator to be escaped If passed unicode/str/bytes will only return list of unicode/str/bytes. """ assert len(sep) == 1 assert len(escape_char) == 1 if isinstance(string, bytes): if isinstance(escape_char, str): escape_char = escape_char.encode("ascii") iter_ = lambda b: (bytes([v]) for v in b) else: iter_ = iter if maxsplit is None: maxsplit = len(string) empty = string[:0] result = [] current = empty escaped = False for char in iter_(string): if escaped: if char != escape_char and char != sep: current += escape_char current += char escaped = False else: if char == escape_char: escaped = True elif char == sep and len(result) < maxsplit: result.append(current) current = empty else: current += char result.append(current) return result def join_escape(values, sep, escape_char="\\"): """Join bytes/unicode so that it can be split with split_escape. In case values is empty, the result has the type of `sep`. otherwise it has the type of values. Be aware that split_escape(join_escape([])) will result in ['']. """ assert len(sep) == 1 assert len(escape_char) == 1 # don't allow auto decoding of 'values' if values and isinstance(values[0], bytes): if isinstance(escape_char, str): escape_char = escape_char.encode("ascii") assert not isinstance(sep, str) escaped = [] for value in values: value = value.replace(escape_char, escape_char + escape_char) value = value.replace(sep, escape_char + sep) escaped.append(value) return sep.join(escaped) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1677345651.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/date.py�������������������������������������������������������0000664�0001750�0001750�00000002161�14376441563�017764� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from datetime import datetime from time import localtime, strftime from typing import Text, Optional def format_date(seconds: float, format_setting: Optional[Text] = None) -> Text: """Formats a date either with the default format, or the passed strftime-compatible format string""" try: date = datetime.fromtimestamp(seconds).date() except (OverflowError, ValueError, OSError): text = u"" else: if format_setting: format_ = format_setting # use default behaviour-format else: today = datetime.now().date() days = (today - date).days if days == 0: format_ = "%X" elif days < 7: format_ = "%A" else: format_ = "%x" stamp = localtime(seconds) text = strftime(format_, stamp) return text ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/filter.py�����������������������������������������������������0000664�0001750�0001750�00000001540�14035600052�020312� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2019 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys import unicodedata _remove_punctuation_trans = dict.fromkeys( i for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith('P')) def remove_punctuation(s: str) -> str: """Removes all known Unicode punctuation from the given string""" return s.translate(_remove_punctuation_trans) def remove_diacritics(s: str) -> str: """Canonicalises and removes all diacritics from the given string""" return "".join(c for c in unicodedata.normalize('NFKD', str(s)) if not unicodedata.combining(c)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/splitters.py��������������������������������������������������0000664�0001750�0001750�00000007557�14035600052�021074� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011-2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import re from quodlibet.util import re_escape DEFAULT_TAG_SPLITTERS = ["/", "&", ","] DEFAULT_SUB_SPLITTERS = ["\u301c\u301c", "\uff08\uff09", "[]", "()", "~~", "--"] def split_value(s, splitters=DEFAULT_TAG_SPLITTERS): """Splits a string. The first match in 'splitters' is used as the separator; subsequent matches are intentionally ignored. """ def regex_for(sp): return r'{start}\s*{split}\s*{end}'.format( start=r'(?:\b|(?<=\W))', split=re_escape(sp), end=r'(?:\b|(?=\W))') if not splitters: return [s.strip()] values = s.split("\n") for spl in splitters: spl = re.compile(regex_for(spl), re.UNICODE) if any(spl.search(v) for v in values): return [st.strip() for v in values for st in spl.split(v)] return values def find_subtitle(title, delimiters=DEFAULT_SUB_SPLITTERS): if isinstance(title, bytes): title = title.decode('utf-8', 'replace') for pair in delimiters: if (len(pair) == 2 and pair[0] in title[:-1] and title.endswith(pair[1])): r = len(pair[1]) l = title[0:-r].rindex(pair[0]) if l: subtitle = title[l + len(pair[0]):-r] return title[:l].rstrip(), subtitle else: return title, None def split_title(s, tag_splitters=DEFAULT_TAG_SPLITTERS, sub_splitters=DEFAULT_SUB_SPLITTERS): title, subtitle = find_subtitle(s, sub_splitters) return ((title.strip(), split_value(subtitle, tag_splitters)) if subtitle else (s, [])) __FEATURING = ["feat.", "featuring", "feat", "ft", "ft.", "with", "w/"] __ORIGINALLY = ["originally by ", " cover"] # Cache case-insensitive regex searches of the above __FEAT_REGEX = [re.compile(re_escape(s + " "), re.I) for s in __FEATURING] __ORIG_REGEX = [re.compile(re_escape(s), re.I) for s in __ORIGINALLY] def split_people(s, tag_splitters=DEFAULT_TAG_SPLITTERS, sub_splitters=DEFAULT_SUB_SPLITTERS): title, subtitle = find_subtitle(s, sub_splitters) if not subtitle: parts = s.split(" ") if len(parts) > 2: for feat in __FEATURING: try: i = [p.lower() for p in parts].index(feat) orig = " ".join(parts[:i]) others = " ".join(parts[i + 1:]) return orig, split_value(others, tag_splitters) except (ValueError, IndexError): pass return s, [] else: old = subtitle # TODO: allow multiple substitutions across types, maybe for regex in (__FEAT_REGEX + __ORIG_REGEX): subtitle = re.sub(regex, "", subtitle, 1) if old != subtitle: # Only change once break values = split_value(subtitle, tag_splitters) return title.strip(), values def split_album(s, sub_splitters=DEFAULT_SUB_SPLITTERS): name, disc = find_subtitle(s, sub_splitters) if not disc: parts = s.split(" ") if len(parts) > 2: lower = parts[-2].lower() if "disc" in lower or "disk" in lower: return " ".join(parts[:-2]), parts[-1] return s, None else: parts = disc.split() if (len(parts) == 2 and parts[0].lower() in ["disc", "disk", "cd", "vol", "vol."]): try: return name, parts[1] except IndexError: return s, None else: return s, None �������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/string/titlecase.py��������������������������������������������������0000664�0001750�0001750�00000006670�14035600052�021013� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Javier Kohen # 2010,2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import unicodedata # Cheat list for human title-casing in English. See Issue 424. ENGLISH_INCORRECTLY_CAPITALISED_WORDS = \ [u"The", u"An", u"A", u"'N'", u"'N", u"N'", u"Tha", u"De", u"Da", u"In", u"To", u"For", u"Up", u"With", u"As", u"At", u"From", u"Into", u"On", u"Out", #, u"Over", u"Of", u"By", u"'Til", u"Til", u"And", u"Or", u"Nor", # u"Is", u"Are", u"Am" ] # Allow basic sentence-like concepts eg "Artist: The Greatest Hits" ENGLISH_SENTENCE_ENDS = [".", ":", "-"] def iswbound(char): """Returns whether the given character is a word boundary.""" category = unicodedata.category(char) # If it's a space separator or punctuation return 'Zs' == category or 'Sk' == category or 'P' == category[0] def utitle(string): """Title-case a string using a less destructive method than str.title.""" new_string = string[0].capitalize() # It's possible we need to capitalize the second character... cap = iswbound(string[0]) for i in range(1, len(string)): s = string[i] prev = string[i - 1] # Special case apostrophe in the middle of a word. # Also, extra case to deal with Irish-style names (eg O'Conner) if u"'" == s \ and string[i - 1].isalpha() \ and not (i > 1 and string[i - 2].isspace() and prev.lower() == u"o"): cap = False elif iswbound(s): cap = True elif cap and s.isalpha(): cap = False s = s.capitalize() else: cap = False new_string += s return new_string def title(string, locale="utf-8"): """Title-case a string using a less destructive method than str.title.""" if not string: return u"" # if the string is all uppercase, lowercase it - Erich/Javier # Lots of Japanese songs use entirely upper-case English titles, # so I don't like this change... - JoeW #if string == string.upper(): string = string.lower() if not isinstance(string, str): string = string.decode(locale) return utitle(string) def _humanise(text): """Reverts a title-cased string to a more natural (English) title-casing. Intended for use after util.title() only""" def previous_real_word(ws, idx): """Returns the first non-null word from words before position `idx`""" while idx > 0: idx -= 1 if ws[idx] != "": break return ws[idx] words = text.split(" ") # Yes: to preserve double spacing (!) for i in range(1, len(words) - 1): word = words[i] if word in ENGLISH_INCORRECTLY_CAPITALISED_WORDS: prev = previous_real_word(words, i) # Add an exception for would-be ellipses... if (prev and (not prev[-1] in ENGLISH_SENTENCE_ENDS or prev[-3:] == '...')): words[i] = word.lower() return u" ".join(words) def human_title(text): """Returns a human title-cased string, using a more natural (English) title-casing e.g. Dark night OF the Soul -> Dark Night of the Soul.""" return _humanise(title(text)) ������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1675520038.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/tags.py��������������������������������������������������������������0000644�0001750�0001750�00000023710�14367464046�016501� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007-2008 Joe Wreschnig # 2014 Christoph Reiter # 2014-2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import _, ngettext """Database of all known tags, their translations and how they are used""" class TagName: """ Text: desc -- translated description plural -- translated plural description or None role -- translated role description (for people tags) Types: user -- user editable tag e.g. "foo" hidden -- if user tag should only be shown in the tag editor (e.g. tracknumber is hidden, since ~#track/~#tracks are more useful for displaying) has_sort -- has a sort user variant e.g. "foosort" machine -- user tag is not human readable. Something people might want to hide in the tag editor. internal -- generated by QL e.g. "~foo" hidden -- if it is replaced by another tag (for backwards compat) has_sort -- has a sort user variant e.g. "~foosort" has_roles -- has a roles variant e.g. "~foo:roles" numeric -- e.g. "~#foo" """ def __init__(self, name, options, desc, plural=None, role=None): # I don't think this categorization is any good.. but at least # there is any.. self.name = name self.desc = desc self.plural = plural self.user = "u" in options self.internal = "i" in options self.numeric = "n" in options self.machine = "m" in options self.has_sort = "s" in options self.has_roles = "r" in options self.hidden = "h" in options self.role = role # some sanity checks assert self.user or self.internal or self.numeric assert not (set(options) - set("uinmshr")) if self.has_roles: assert self.internal if self.has_sort: assert self.user or self.internal if self.machine: assert self.user if self.hidden: assert self.user + self.internal == 1 def __repr__(self): return "%s(%r)" % (type(self).__name__, vars(self)) def _get_role_map(tags): roles = {} for (name, tag) in tags.items(): if tag.role: roles[name] = tag.role if tag.has_sort: roles[name + "sort"] = tag.role return roles T = TagName _TAGS = dict((t.name, t) for t in [ T("album", "us", _("album"), _("albums")), T("arranger", "u", _("arranger"), _("arrangers"), _("arrangement")), T("artist", "us", _("artist"), _("artists")), T("author", "u", _("author"), _("authors")), T("comment", "u", _("comment")), T("composer", "us", _("composer"), _("composers"), _("composition")), # Translators: conducting as in conducting a musical performance T("conductor", "u", _("conductor"), _("conductors"), _("conducting")), T("contact", "u", _("contact")), T("copyright", "u", _("copyright")), T("date", "u", _("date")), T("description", "u", _("description")), T("genre", "u", _("genre"), _("genres")), T("performer", "uisr", _("performer"), _("performers"), _("performance")), T("grouping", "u", _("grouping")), T("language", "ui", _("language")), T("license", "u", _("license")), T("location", "u", _("location")), T("lyricist", "u", _("lyricist"), _("lyricists"), _("lyrics")), # Translators: Also e.g. "record label", "publisher" T("organization", "u", _("organization")), T("title", "u", _("title")), T("version", "u", _("version")), T("website", "u", _("website")), T("albumartist", "us", _("album artist")), T("bpm", "u", _("BPM")), T("isrc", "u", "ISRC"), # Translators: This used to be called "part". T("discsubtitle", "u", _("disc subtitle")), T("part", "u", _("disc subtitle")), T("discnumber", "uh", _("disc")), T("tracknumber", "uh", _("track")), T("labelid", "u", _("label ID")), T("originaldate", "u", _("original release date")), T("originalalbum", "u", _("original album")), T("originalartist", "us", _("original artist")), T("recordingdate", "u", _("recording date")), T("releasecountry", "u", _("release country")), T("initialkey", "u", _("initial key")), # for backwards compat T("performers", "ishr", _("performers")), # http://musicbrainz.org/doc/MusicBrainzTag # Note: picard has changed musicbrainz_trackid to mean release track. # We can't do that because of existing libraries, so use a new # musicbrainz_releastrackid instead. T("musicbrainz_trackid", "um", _("MusicBrainz recording ID")), T("musicbrainz_releasetrackid", "um", _("MusicBrainz release track ID")), T("musicbrainz_albumid", "um", _("MusicBrainz release ID")), T("musicbrainz_artistid", "um", _("MusicBrainz artist ID")), T("musicbrainz_albumartistid", "um", _("MusicBrainz release artist ID")), T("musicbrainz_trmid", "um", _("MusicBrainz TRM ID")), T("musicip_puid", "um", _("MusicIP PUID")), T("musicbrainz_albumstatus", "um", _("MusicBrainz album status")), T("musicbrainz_albumtype", "um", _("MusicBrainz album type")), T("musicbrainz_releasegroupid", "um", _("MusicBrainz release group ID")), # Translators: "gain" means a volume adjustment, not "to acquire". T("replaygain_track_gain", "umn", _("track gain")), T("replaygain_track_peak", "umn", _("track peak")), # Translators: "gain" means a volume adjustment, not "to acquire". T("replaygain_album_gain", "umn", _("album gain")), T("replaygain_album_peak", "umn", _("album peak")), T("replaygain_reference_loudness", "umn", _("reference loudness")), T("added", "n", _("added")), T("lastplayed", "n", _("last played")), T("disc", "n", _("disc")), T("discs", "n", _("discs")), T("track", "n", _("track")), T("tracks", "n", _("tracks")), T("laststarted", "n", _("last started")), T("filename", "i", _("full name")), T("basename", "i", _("filename")), T("dirname", "i", _("directory")), T("mtime", "n", _("modified")), T("playcount", "n", _("plays")), T("skipcount", "n", _("skips")), T("uri", "i", "URI"), T("mountpoint", "i", _("mount point")), T("length", "n", _("length")), T("people", "isr", _("people")), T("rating", "in", _("rating")), T("year", "in", _("year")), T("originalyear", "in", _("original release year")), T("bookmark", "i", _("bookmark")), T("bitdepth", "n", _("bitdepth")), T("bitrate", "in", _("bitrate")), T("filesize", "n", _("file size")), T("format", "i", _("file format")), T("codec", "i", _("codec")), T("encoding", "i", _("encoding")), T("playlists", "i", _("playlists")), T("samplerate", "n", _("sample rate")), T("channels", "n", _("channel count")), ]) def _get_sort_map(tags): """See TAG_TO_SORT""" tts = {} for name, tag in tags.items(): if tag.has_sort: if tag.user: tts[name] = "%ssort" % name if tag.internal: tts["~%s" % name] = "~%ssort" % name return tts def _get_standard_tags(tags, machine=False): stags = [] for name, tag in tags.items(): if tag.user and tag.machine == machine: stags.append(name) if tag.has_sort: stags.append("%ssort" % name) return stags TAG_TO_SORT = _get_sort_map(_TAGS) """A mapping of tag -> sorttag. e.g. artist -> artistsort""" MACHINE_TAGS = _get_standard_tags(_TAGS, machine=True) """A sequence of editable tags that are not human-readable. e.g. musicbrainz_albumid """ USER_TAGS = _get_standard_tags(_TAGS, machine=False) """A sequence of tags that are human-readable and can be edited. e.g. album """ TAG_ROLES = _get_role_map(_TAGS) """A mapping from tags to their translated role description. e.g. conductor -> conducting """ def readable(tag, plural=False): """Gives a translated description for a tag. Also supports internal, numeric tags. If plural is True, will return a plural description if possible. album -> album albumsort -> album (sort) ~foo -> foo ~people:roles -> people (roles) """ try: if tag[0] == "~": if tag[1] == "#": tag = tag[2:] else: tag = tag[1:] except IndexError: return ngettext("Invalid tag", "Invalid tags", 1) def desc(tag): if plural: plural_desc = _TAGS[tag].plural if plural_desc: return plural_desc return _TAGS[tag].desc if tag in _TAGS: return desc(tag) elif tag == 'people:real': return desc('people') else: roles = False if tag.endswith(":roles"): roles = True tag = tag[:-6] parts = [] if tag.endswith("sort"): v = _TAGS.get(tag[:-4]) if v is not None and v.has_sort: tag = tag[:-4] # Translators: e.g. "artist (sort)" parts.append(_("sort")) else: v = _TAGS.get(tag[:-4]) if roles: v = _TAGS.get(tag) if v is not None and v.has_roles: # Translators: e.g. "performer (roles)" parts.append(_("roles")) if tag in _TAGS: desc = desc(tag) if parts: desc += " (%s)" % ", ".join(parts) return desc return tag def sortkey(tag): """Sort key for sorting tag names by importance. tags.sort(key=sortkey) """ # last one -> most important order = [ "album", "artist", "title", ] try: return (-order.index(tag), tag) except ValueError: if tag in MACHINE_TAGS: return (2, tag) else: return (1, tag) ��������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/tagsfrompath.py������������������������������������������������������0000664�0001750�0001750�00000005421�14035600052�020220� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # # 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 2 of the License, or # (at your option) any later version. import os import re from senf import fsnative, fsn2text from quodlibet.util import re_escape class TagsFromPattern: def __init__(self, pattern): self.headers = [] self.slashes = len(pattern) - len(pattern.replace(os.path.sep, '')) + 1 self.pattern = None # patterns look like <tagname> non regexy stuff <tagname> ... pieces = re.split(r'(<[A-Za-z0-9~_]+>)', pattern) override = {'<tracknumber>': r'\d\d?', '<discnumber>': r'\d\d??'} dummies_found = 0 for i, piece in enumerate(pieces): if not piece: continue if piece[0] + piece[-1] == '<>': piece = piece.lower() # canonicalize to lowercase tag names if "~" in piece: dummies_found += 1 piece = "<QUOD_LIBET_DUMMY_%d>" % dummies_found pieces[i] = '(?P%s%s)' % (piece, override.get(piece, '.+?')) if "QUOD_LIBET" not in piece: self.headers.append(piece[1:-1]) else: pieces[i] = re_escape(piece) # some slight magic to anchor searches "nicely" # nicely means if it starts with a <tag>, anchor with a / # if it ends with a <tag>, anchor with .xxx$ # but if it's a <tagnumber>, don't bother as \d+ is sufficient # and if it's not a tag, trust the user if pattern.startswith('<') and not pattern.startswith('<tracknumber>')\ and not pattern.startswith('<discnumber>'): pieces.insert(0, re_escape(os.path.sep)) if pattern.endswith('>') and not pattern.endswith('<tracknumber>')\ and not pattern.endswith('<discnumber>'): pieces.append(r'(?:\.[A-Za-z0-9_+]+)$') self.pattern = re.compile(''.join(pieces)) def match(self, song): return self.match_path(song["~filename"]) def match_path(self, path): assert isinstance(path, fsnative) tail = os.path.splitdrive(path)[-1] # only match on the last n pieces of a filename, dictated by pattern # this means no pattern may effectively cross a /, despite .* doing so sep = os.path.sep matchon = sep + sep.join(tail.split(sep)[-self.slashes:]) # work on unicode matchon = fsn2text(matchon) match = self.pattern.search(matchon) # dicts for all! if match is None: return {} else: return match.groupdict() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/thread.py������������������������������������������������������������0000664�0001750�0001750�00000007740�14035600052�016776� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """Utils for executing things in a thread controlled from the main loop""" from multiprocessing import cpu_count try: from concurrent.futures import ThreadPoolExecutor except ImportError as e: raise ImportError("python-futures is missing: %r" % e) from gi.repository import GLib from quodlibet import util @util.enum class Priority(int): HIGH = 0 BACKGROUND = 1 class Cancellable: """Subset of Gio.Cancellable so it can be used as well""" def __init__(self): self._cancelled = False def is_cancelled(self): return self._cancelled def reset(self): self._cancelled = False def cancel(self): self._cancelled = True _pools = {} _prio_mapping = { Priority.HIGH: GLib.PRIORITY_DEFAULT, Priority.BACKGROUND: GLib.PRIORITY_LOW, } def _get_pool(priority): """Return a (shared) pool for a given priority""" global _pools if not priority in _pools: try: cpus = cpu_count() except NotImplementedError: cpus = 2 max_workers = int(cpus * 1.5) _pools[priority] = ThreadPoolExecutor(max_workers) return _pools[priority] def _wrap_function(function, cancellable, args, kwargs): def wrap(): # check once we are scheduled if not cancellable.is_cancelled(): try: return function(*args, **kwargs) except: # ThreadPool catches the exception for the async result # which we don't use. Print instead as if it was not caught. util.print_exc() raise return wrap def _wrap_callback(priority, cancellable, callback): def callback_main(cancellable, callback, result): if not cancellable.is_cancelled(): callback(result) return False def callback_thread(future): global _prio_mapping result = future.result() if not cancellable.is_cancelled(): glib_priority = _prio_mapping[priority] GLib.idle_add(callback_main, cancellable, callback, result, priority=glib_priority) return callback_thread def _call_async(priority, function, cancellable, callback, args, kwargs): assert cancellable is not None assert function is not None assert callback is not None if args is None: args = tuple() if kwargs is None: kwargs = {} pool = _get_pool(priority) wrapped_func = _wrap_function(function, cancellable, args, kwargs) wrapped_callback = _wrap_callback(priority, cancellable, callback) future = pool.submit(wrapped_func) future.add_done_callback(wrapped_callback) def terminate_all(): """Terminate all pools, doesn't wait for task completion. Can be called multiple times and call_async() etc. can still be used. """ global _pools for key, pool in list(_pools.items()): del _pools[key] pool.shutdown(wait=False) def call_async(function, cancellable, callback, args=None, kwargs=None): """Call `function` in a thread that gets passed the `cancellable` and the passed args/kwargs. The return value will get passed to `callback` which will be called in the main thread. It will not be called if the `cancellable` gets cancelled and is not guaranteed to be called at all (on event loop shutdown for example) """ _call_async(Priority.HIGH, function, cancellable, callback, args, kwargs) def call_async_background(function, cancellable, callback, args=None, kwargs=None): """Same as call_async but for background tasks (network etc.)""" _call_async(Priority.BACKGROUND, function, cancellable, callback, args, kwargs) ��������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684322551.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/thumbnails.py��������������������������������������������������������0000644�0001750�0001750�00000013052�14431134367�017677� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2009-2014 Christoph Reiter # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import hashlib from tempfile import gettempdir from typing import Optional from gi.repository import GdkPixbuf, GLib from quodlibet import print_w from senf import fsn2uri, fsnative import quodlibet from quodlibet.util.path import mtime, mkdir, xdg_get_cache_home from quodlibet.util import enum from quodlibet.qltk.image import scale def get_thumbnail_folder(): """Returns a path to the thumbnail folder. The returned path might not exist. """ if os.name == "nt": thumb_folder = os.path.join(quodlibet.get_cache_dir(), "thumbnails") else: cache_folder = os.path.join(xdg_get_cache_home(), "thumbnails") thumb_folder = os.path.expanduser('~/.thumbnails') if os.path.exists(cache_folder) or not os.path.exists(thumb_folder): thumb_folder = cache_folder return thumb_folder @enum class ThumbSize(int): NORMAL = 128 LARGE = 256 LARGEST = LARGE def get_cache_info(path, boundary): """For an image at `path` return (cache_path, thumb_size) cache_path points to a potential cache file thumb size is either 128 or 256 """ assert isinstance(path, fsnative) width, height = boundary if width <= ThumbSize.NORMAL and height <= ThumbSize.NORMAL: size_name = "normal" thumb_size = ThumbSize.NORMAL else: size_name = "large" thumb_size = ThumbSize.LARGE thumb_folder = get_thumbnail_folder() cache_dir = os.path.join(thumb_folder, size_name) uri = fsn2uri(path) thumb_name = hashlib.md5(uri.encode("ascii")).hexdigest() + ".png" thumb_path = os.path.join(cache_dir, thumb_name) return (thumb_path, thumb_size) def get_thumbnail_from_file(fileobj, boundary) -> Optional[GdkPixbuf.Pixbuf]: """Like get_thumbnail() but works with files that can't be reopened. This is needed on Windows where NamedTemporaryFile can't be reopened. :returns: Pixbuf or None. Thread-safe. """ assert fileobj try: path = fileobj.name assert isinstance(path, fsnative), path return get_thumbnail(path, boundary) except GLib.GError: try: loader = GdkPixbuf.PixbufLoader() loader.set_size(*boundary) loader.write(fileobj.read()) loader.close() fileobj.seek(0, 0) # can return None in case of partial data return loader.get_pixbuf() except (GLib.GError, EnvironmentError) as e: print_w(f"Couldn't load thumbnail with PixbufLoader either: {e}") return None def get_thumbnail(path, boundary, ignore_temp=True): """Get a thumbnail pixbuf of an image at `path`. Will create/use a thumbnail in the user's thumbnail directory if possible. Follows the Free Desktop specification: http://specifications.freedesktop.org/thumbnail-spec/ If ignore_temp then no thumbnail cache will be created for files in the default temporary directory. Can raise GLib.GError. Thread-safe. """ assert isinstance(path, fsnative) width, height = boundary new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size # larger than thumbnails, load directly if width > ThumbSize.LARGEST or height > ThumbSize.LARGEST: return new_from_file_at_size(path, width, height) path_mtime = mtime(path) if path_mtime == 0: return new_from_file_at_size(path, width, height) # embedded thumbnails come from /tmp/ # FIXME: move this to another layer if ignore_temp and path.startswith(gettempdir()): return new_from_file_at_size(path, width, height) thumb_path, thumb_size = get_cache_info(path, boundary) cache_dir = os.path.dirname(thumb_path) try: mkdir(cache_dir, 0o700) except OSError as e: print_w(f"Couldn't create cache dir {cache_dir!r} ({e}") return new_from_file_at_size(path, width, height) try: pb = new_from_file_at_size(thumb_path, width, height) except GLib.GError as e: # in case it fails to load, we recreate it print_w(f"Couldn't load from {thumb_path!r} ({e}), recreating.") else: meta_mtime = pb.get_option("tEXt::Thumb::MTime") if meta_mtime is not None: try: meta_mtime = int(meta_mtime) except ValueError: pass else: if meta_mtime == int(path_mtime): return pb info, pw, ph = GdkPixbuf.Pixbuf.get_file_info(path) # Too small picture, no thumbnail needed if pw < thumb_size and ph < thumb_size: return new_from_file_at_size(path, width, height) thumb_pb = new_from_file_at_size(path, thumb_size, thumb_size) uri = fsn2uri(path) mime = info.get_mime_types()[0] options = { "tEXt::Thumb::Image::Width": str(pw), "tEXt::Thumb::Image::Height": str(ph), "tEXt::Thumb::URI": uri, "tEXt::Thumb::MTime": str(int(path_mtime)), "tEXt::Thumb::Size": str(os.path.getsize(path)), "tEXt::Thumb::Mimetype": mime, "tEXt::Software": "QuodLibet" } thumb_pb.savev(thumb_path, "png", list(options.keys()), list(options.values())) try: os.chmod(thumb_path, 0o600) except OSError: pass return scale(thumb_pb, boundary) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/trash.py�������������������������������������������������������������0000664�0001750�0001750�00000011636�14035600052�016647� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011 Christoph Reiter # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import stat import sys import errno import time import shutil from urllib.request import pathname2url from os.path import join, islink, abspath, dirname from os.path import isdir, basename, exists, splitext from quodlibet import config from quodlibet.util.path import find_mount_point, xdg_get_data_home from quodlibet.util.environment import is_flatpak _TRASH_TMPL = """[Trash Info] Path={path} DeletionDate={date}""" class TrashError(EnvironmentError): pass def is_sticky(path): return bool(os.stat(path).st_mode & stat.S_ISVTX) def _get_fd_trash_dirs(path): """Returns verified trash folders for the given path. Returns (rootdir, filesdir, infodir), or raises a TrashError if a valid trash folder structure could not be found. The returned trash folders are not guaranteed to be on the same volume as the original path: a fallback may be returned instead. Returned paths are absolute. This method may create partial or complete trash directory structures as part of its search. """ path = abspath(path) mount = find_mount_point(path) xdg_data_home = xdg_get_data_home() xdg_home_mount = find_mount_point(xdg_data_home) trash_home = join(xdg_data_home, "Trash") # Build a list of trash roots to try. trash_roots = [] if mount != xdg_home_mount: root = join(mount, ".Trash") uid = str(os.getuid()) if isdir(root) and not islink(root) and is_sticky(root): trash_roots.append(join(root, uid)) else: trash_roots.append(join(mount, ".Trash-" + uid)) trash_roots.append(trash_home) trash_roots = [abspath(r) for r in trash_roots] # Try and verify each potential trash path, and create its # required structure if needed. for trash_root in trash_roots: if path.startswith(join(trash_root, "")) or path == trash_root: # Can't move files to the trash from within the trash root. # But a fallback root may be OK. continue # makes things easier subdirs = [join(trash_root, s) for s in ("files", "info")] subdirs_valid = True for subdir in subdirs: if not isdir(subdir): try: os.makedirs(subdir, 0o700) except OSError: subdirs_valid = False if not os.access(subdir, os.W_OK): subdirs_valid = False if subdirs_valid: return tuple([trash_root] + subdirs) raise TrashError("No valid trash folder exists for %r" % (path,)) def trash_free_desktop(path): """Partial implementation of http://www.freedesktop.org/wiki/Specifications/trash-spec This doesn't work for files in the trash directory. """ path = abspath(path) if not exists(path): raise TrashError("Path %s does not exist." % path) trash_dir, files, info = _get_fd_trash_dirs(path) info_ext = ".trashinfo" name = basename(path) flags = os.O_EXCL | os.O_CREAT | os.O_WRONLY mode = 0o644 try: info_path = join(info, name + info_ext) info_fd = os.open(info_path, flags, mode) except OSError as e: if e.errno != errno.EEXIST: raise i = 2 while 1: head, tail = splitext(name) temp_name = "%s.%d%s" % (head, i, tail) info_path = join(info, temp_name + info_ext) try: info_fd = os.open(info_path, flags, mode) except OSError as e: if e.errno != errno.EEXIST: raise i += 1 continue name = temp_name break parent = dirname(trash_dir) if path.startswith(join(parent, "")): norm_path = path[len(join(parent, "")):] else: norm_path = path del_date = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime()) data = _TRASH_TMPL.format(path=pathname2url(norm_path), date=del_date) os.write(info_fd, data.encode()) os.close(info_fd) target_path = join(files, name) try: shutil.move(path, target_path) except OSError: os.unlink(info_path) raise def use_trash(): """If the current platform supports moving files into a trash can.""" # TODO: Use the glib API for trashing which supports trashing there if is_flatpak(): return False return ( os.name == "posix" and sys.platform != "darwin" and not config.getboolean("settings", "bypass_trash")) def trash(path): if os.name == "posix" and sys.platform != "darwin": trash_free_desktop(path) else: raise NotImplementedError ��������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660768424.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/urllib.py������������������������������������������������������������0000664�0001750�0001750�00000002542�14277250250�017024� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import from .misc import get_ca_file from urllib import request as request_module from http.client import HTTPException Request = request_module.Request UrllibError = EnvironmentError def urlopen(*args, **kwargs): try: return request_module.urlopen(*args, **kwargs) except HTTPException as e: # https://bugs.python.org/issue8823 raise EnvironmentError(e) def install_urllib2_ca_file(): """Makes urllib2.urlopen and urllib2.build_opener use the ca file returned by get_ca_file() """ try: import ssl except ImportError: return base = request_module.HTTPSHandler class MyHandler(base): def __init__(self, debuglevel=0, context=None): ca_file = get_ca_file() if context is None and ca_file is not None: context = ssl.create_default_context( purpose=ssl.Purpose.SERVER_AUTH, cafile=ca_file) base.__init__(self, debuglevel, context) request_module.HTTPSHandler = MyHandler ��������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/winapi.py������������������������������������������������������������0000664�0001750�0001750�00000036632�14035600052�017020� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. """ Error handling: every function which has ctypes.HRESULT as restype will automatically raise WindowsError if a bad result is returned. For all other functions check the return status and raise ctypes.WinError() """ import sys import ctypes from .enum import enum if sys.platform == 'win32': from ctypes import wintypes, cdll, windll, oledll class GUID(ctypes.Structure): # https://msdn.microsoft.com/en-us/library/windows/desktop/ # aa373931%28v=vs.85%29.aspx _fields_ = [ ("Data1", wintypes.DWORD), ("Data2", wintypes.WORD), ("Data3", wintypes.WORD), ("Data4", wintypes.BYTE * 8), ] def __init__(self, name=None): if name is not None: IIDFromString(str(name), ctypes.byref(self)) def __str__(self): ptr = wintypes.LPOLESTR() StringFromIID(ctypes.byref(self), ctypes.byref(ptr)) string = str(ptr.value) CoTaskMemFree(ptr) return string LPGUID = ctypes.POINTER(GUID) IID = GUID LPIID = ctypes.POINTER(IID) REFIID = ctypes.POINTER(IID) CLSID = GUID REFCLSID = ctypes.POINTER(CLSID) WORD = wintypes.WORD DWORD = wintypes.DWORD ULONG = wintypes.ULONG SHORT = wintypes.SHORT ULONG_PTR = wintypes.WPARAM LONG_PTR = wintypes.LPARAM LRESULT = LONG_PTR HHOOK = wintypes.HANDLE HRESULT = ctypes.HRESULT HC_ACTION = 0 HC_NOREMOVE = 3 VK_MEDIA_NEXT_TRACK = 0xB0 VK_MEDIA_PREV_TRACK = 0xB1 VK_MEDIA_STOP = 0xB2 VK_MEDIA_PLAY_PAUSE = 0xB3 WM_KEYDOWN = 0x0100 WM_KEYUP = 0x0101 WM_SYSKEYDOWN = 0x0104 WM_SYSKEYUP = 0x0105 CallNextHookEx = windll.user32.CallNextHookEx CallNextHookEx.argtypes = [ HHOOK, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM] CallNextHookEx.restype = LRESULT class KBDLLHOOKSTRUCT(ctypes.Structure): _fields_ = [ ("vkCode", DWORD), ("scanCode", DWORD), ("flags", DWORD), ("time", DWORD), ("dwExtraInfo", ULONG_PTR), ] LPKBDLLHOOKSTRUCT = PKBDLLHOOKSTRUCT = ctypes.POINTER(KBDLLHOOKSTRUCT) LowLevelKeyboardProc = ctypes.WINFUNCTYPE( LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM) _SetWindowsHookExW = windll.user32.SetWindowsHookExW _SetWindowsHookExW.argtypes = [ ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, wintypes.DWORD] _SetWindowsHookExW.restype = HHOOK def SetWindowsHookExW(idHook, lpfn, hMod, dwThreadId): assert idHook == WH_KEYBOARD_LL assert isinstance(lpfn, LowLevelKeyboardProc) return _SetWindowsHookExW(idHook, lpfn, hMod, dwThreadId) UnhookWindowsHookEx = windll.user32.UnhookWindowsHookEx UnhookWindowsHookEx.argtypes = [HHOOK] UnhookWindowsHookEx.restype = wintypes.BOOL WH_KEYBOARD_LL = 13 LPWIN32_FIND_DATAW = ctypes.POINTER(wintypes.WIN32_FIND_DATAW) IIDFromString = windll.ole32.IIDFromString IIDFromString.argtypes = [wintypes.LPCOLESTR, LPIID] IIDFromString.restype = HRESULT StringFromIID = windll.ole32.StringFromIID StringFromIID.argtypes = [REFIID, ctypes.POINTER(wintypes.LPOLESTR)] StringFromIID.restype = HRESULT CoInitialize = windll.ole32.CoInitialize CoInitialize.argtypes = [wintypes.LPVOID] CoInitialize.restype = HRESULT LPDWORD = ctypes.POINTER(wintypes.DWORD) REFKNOWNFOLDERID = ctypes.POINTER(GUID) CLSCTX_INPROC_SERVER = 1 SetEnvironmentVariableW = ctypes.windll.kernel32.SetEnvironmentVariableW SetEnvironmentVariableW.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p] SetEnvironmentVariableW.restype = ctypes.c_bool GetEnvironmentStringsW = ctypes.windll.kernel32.GetEnvironmentStringsW GetEnvironmentStringsW.argtypes = [] GetEnvironmentStringsW.restype = ctypes.c_void_p FreeEnvironmentStringsW = ctypes.windll.kernel32.FreeEnvironmentStringsW FreeEnvironmentStringsW.argtypes = [ctypes.c_void_p] FreeEnvironmentStringsW.restype = ctypes.c_bool SHGetFolderPathW = ctypes.windll.shell32.SHGetFolderPathW SHGetFolderPathW.argtypes = [ wintypes.HWND, ctypes.c_int, wintypes.HANDLE, wintypes.DWORD, wintypes.LPWSTR] SHGetFolderPathW.restype = HRESULT SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath SHGetKnownFolderPath.argtypes = [ REFKNOWNFOLDERID, wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)] SHGetKnownFolderPath.restype = HRESULT CoTaskMemFree = windll.ole32.CoTaskMemFree CoTaskMemFree.argtypes = [ctypes.c_void_p] CoTaskMemFree.restype = None GetCommandLineW = cdll.kernel32.GetCommandLineW GetCommandLineW.argtypes = [] GetCommandLineW.restype = wintypes.LPCWSTR CommandLineToArgvW = windll.shell32.CommandLineToArgvW CommandLineToArgvW.argtypes = [ wintypes.LPCWSTR, ctypes.POINTER(ctypes.c_int)] CommandLineToArgvW.restype = ctypes.POINTER(wintypes.LPWSTR) LocalFree = windll.kernel32.LocalFree LocalFree.argtypes = [wintypes.HLOCAL] LocalFree.restype = wintypes.HLOCAL WaitNamedPipeW = windll.kernel32.WaitNamedPipeW WaitNamedPipeW.argtypes = [wintypes.LPCWSTR, wintypes.DWORD] WaitNamedPipeW.restype = wintypes.BOOL LANGID = wintypes.WORD GetUserDefaultUILanguage = ctypes.windll.kernel32.GetUserDefaultUILanguage GetUserDefaultUILanguage.argtypes = [] GetUserDefaultUILanguage.restype = LANGID GetSystemDefaultUILanguage = ctypes.windll.kernel32.GetSystemDefaultUILanguage GetSystemDefaultUILanguage.argtypes = [] GetSystemDefaultUILanguage.restype = LANGID class SECURITY_ATTRIBUTES(ctypes.Structure): _fields_ = [ ("nLength", wintypes.DWORD), ("lpSecurityDescriptor", wintypes.LPVOID), ("bInheritHandle", wintypes.BOOL), ] LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES) PSECURITY_ATTRIBUTES = LPSECURITY_ATTRIBUTES CreateNamedPipeW = windll.kernel32.CreateNamedPipeW CreateNamedPipeW.argtypes = [ wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, LPSECURITY_ATTRIBUTES] CreateNamedPipeW.restype = wintypes.HANDLE LPOVERLAPPED = ctypes.c_void_p PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000 PIPE_REJECT_REMOTE_CLIENTS = 0x00000008 PIPE_ACCESS_DUPLEX = 0x00000003 PIPE_ACCESS_INBOUND = 0x00000001 PIPE_ACCESS_OUTBOUND = 0x00000002 PIPE_TYPE_BYTE = 0x00000000 PIPE_TYPE_MESSAGE = 0x00000004 PIPE_READMODE_BYTE = 0x00000000 PIPE_READMODE_MESSAGE = 0x00000002 PIPE_WAIT = 0x00000000 PIPE_NOWAIT = 0x00000001 FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000 FILE_FLAG_WRITE_THROUGH = 0x80000000 FILE_FLAG_OVERLAPPED = 0x40000000 PIPE_UNLIMITED_INSTANCES = 255 NMPWAIT_USE_DEFAULT_WAIT = 0x00000000 NMPWAIT_WAIT_FOREVER = 0xffffffff ConnectNamedPipe = windll.kernel32.ConnectNamedPipe ConnectNamedPipe.argtypes = [wintypes.HANDLE, LPOVERLAPPED] ConnectNamedPipe.restype = wintypes.BOOL DisconnectNamedPipe = windll.kernel32.DisconnectNamedPipe DisconnectNamedPipe.argtypes = [wintypes.HANDLE] DisconnectNamedPipe.restype = wintypes.BOOL ReadFile = windll.kernel32.ReadFile ReadFile.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD, LPDWORD, LPOVERLAPPED] ReadFile.restype = wintypes.BOOL CloseHandle = windll.kernel32.CloseHandle CloseHandle.argtypes = [wintypes.HANDLE] CloseHandle.restype = wintypes.BOOL MOVEFILE_WRITE_THROUGH = 0x8 MOVEFILE_REPLACE_EXISTING = 0x1 MoveFileExW = windll.kernel32.MoveFileExW MoveFileExW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR, wintypes.DWORD] MoveFileExW.restype = wintypes.BOOL GetStdHandle = windll.kernel32.GetStdHandle GetStdHandle.argtypes = [DWORD] GetStdHandle.restype = wintypes.HANDLE SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, WORD] SetConsoleTextAttribute.restype = wintypes.BOOL GetConsoleOutputCP = windll.kernel32.GetConsoleOutputCP GetConsoleOutputCP.argtypes = [] GetConsoleOutputCP.restype = wintypes.UINT SetConsoleOutputCP = windll.kernel32.SetConsoleOutputCP SetConsoleOutputCP.argtypes = [wintypes.UINT] SetConsoleOutputCP.restype = wintypes.BOOL WinError = ctypes.WinError S_OK = HRESULT(0).value MAX_PATH = wintypes.MAX_PATH INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value STD_INPUT_HANDLE = DWORD(-10) STD_OUTPUT_HANDLE = DWORD(-11) STD_ERROR_HANDLE = DWORD(-12) class COORD(ctypes.Structure): _fields_ = [ ("X", SHORT), ("Y", SHORT), ] class SMALL_RECT(ctypes.Structure): _fields_ = [ ("Left", SHORT), ("Top", SHORT), ("Right", SHORT), ("Bottom", SHORT), ] class PCONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): _fields_ = [ ("dwSize", COORD), ("dwCursorPosition", COORD), ("wAttributes", WORD), ("srWindow", SMALL_RECT), ("dwMaximumWindowSize", COORD), ] GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo GetConsoleScreenBufferInfo.argtypes = [ wintypes.HANDLE, ctypes.POINTER(PCONSOLE_SCREEN_BUFFER_INFO)] GetConsoleScreenBufferInfo.restype = wintypes.BOOL FOREGROUND_BLUE = 0x0001 FOREGROUND_GREEN = 0x0002 FOREGROUND_RED = 0x0004 FOREGROUND_INTENSITY = 0x0008 BACKGROUND_BLUE = 0x0010 BACKGROUND_GREEN = 0x0020 BACKGROUND_RED = 0x0040 BACKGROUND_RED = 0x0040 class COMMethod: def __init__(self, name, offset, restype, argtypes): self._name = name self._restype = restype self._offset = offset self._argtypes = argtypes def __get__(self, instance, owner): func = ctypes.WINFUNCTYPE( self._restype, *self._argtypes)(self._offset, self._name) def wrapper(self, *args, **kwargs): return func(self, *args, **kwargs) setattr(owner, self._name, wrapper) return getattr(instance or owner, self._name) class COMInterface(type(ctypes.c_void_p)): def __new__(mcls, cls_name, bases, d): offset = 0 for base in bases: for realbase in base.__mro__: offset += len(realbase.__dict__.get("_methods_", [])) for i, args in enumerate(d.get("_methods_", [])): name = args[0] restype = args[1] if restype is None: continue argtypes = args[2:] m = COMMethod(name, offset + i, restype, argtypes) d[name] = m return type(ctypes.c_void_p).__new__(mcls, cls_name, bases, dict(d)) class IUnknown(ctypes.c_void_p, metaclass=COMInterface): IID = GUID("{00000001-0000-0000-c000-000000000046}") _methods_ = [ ("QueryInterface", HRESULT, LPGUID, wintypes.LPVOID), ("AddRef", wintypes.DWORD), ("Release", wintypes.DWORD), ] LPUNKNOWN = ctypes.POINTER(IUnknown) CoCreateInstance = windll.ole32.CoCreateInstance CoCreateInstance.argtypes = [REFCLSID, LPUNKNOWN, wintypes.DWORD, REFIID, wintypes.LPVOID] CoCreateInstance.restype = HRESULT class IShellLinkW(IUnknown): IID = GUID("{000214F9-0000-0000-C000-000000000046}") _methods_ = [ ("GetPath", HRESULT, wintypes.LPWSTR, wintypes.INT, LPWIN32_FIND_DATAW, wintypes.DWORD), ] class IPersist(IUnknown): IID = GUID("{0000010c-0000-0000-C000-000000000046}") _methods_ = [ ("GetClassID", HRESULT, LPGUID), ] class IPersistFile(IPersist): IID = GUID("{0000010b-0000-0000-c000-000000000046}") _methods_ = [ ("IsDirty", HRESULT), ("Load", HRESULT, wintypes.LPOLESTR, wintypes.DWORD), ] class ITEMIDLIST(ctypes.Structure): pass IBindCtx = ctypes.c_void_p ITEMIDLIST_ABSOLUTE = ITEMIDLIST ITEMIDLIST_RELATIVE = ITEMIDLIST PIDLIST_ABSOLUTE = ctypes.POINTER(ITEMIDLIST_ABSOLUTE) PCUIDLIST_RELATIVE = ctypes.POINTER(ITEMIDLIST_RELATIVE) PIDLIST_RELATIVE = ctypes.POINTER(ITEMIDLIST_RELATIVE) PCIDLIST_ABSOLUTE = ctypes.POINTER(ITEMIDLIST_ABSOLUTE) ITEMID_CHILD = ITEMIDLIST PCUITEMID_CHILD = ctypes.POINTER(ITEMID_CHILD) PCUITEMID_CHILD_ARRAY = ctypes.POINTER(PCUITEMID_CHILD) class IShellFolder(IUnknown): IID = GUID("{000214E6-0000-0000-C000-000000000046}") _methods_ = [ ("ParseDisplayName", HRESULT, wintypes.HWND, ctypes.POINTER(IBindCtx), wintypes.LPWSTR, ctypes.POINTER(wintypes.ULONG), ctypes.POINTER(PIDLIST_RELATIVE), ctypes.POINTER(wintypes.ULONG)), ("EnumObjects", None), ("BindToObject", HRESULT, PCUIDLIST_RELATIVE, ctypes.POINTER(IBindCtx), REFIID, ctypes.c_void_p), ] CLSID_ShellLink = GUID("{00021401-0000-0000-C000-000000000046}") SHGetDesktopFolder = oledll.shell32.SHGetDesktopFolder SHGetDesktopFolder.argtypes = [ctypes.POINTER(IShellFolder)] SHGetDesktopFolder.restype = HRESULT ILCombine = windll.shell32.ILCombine ILCombine.argtypes = [ctypes.c_void_p, ctypes.c_void_p] ILCombine.restype = ctypes.c_void_p ILCreateFromPathW = windll.shell32.ILCreateFromPathW ILCreateFromPathW.argtypes = [wintypes.LPCWSTR] ILCreateFromPathW.restype = PIDLIST_ABSOLUTE ILFree = windll.shell32.ILFree ILFree.argtypes = [PIDLIST_RELATIVE] ILFree.restype = None SHOpenFolderAndSelectItems = windll.shell32.SHOpenFolderAndSelectItems SHOpenFolderAndSelectItems.argtypes = [ PCIDLIST_ABSOLUTE, wintypes.UINT, PCUITEMID_CHILD_ARRAY, DWORD] SHOpenFolderAndSelectItems.restype = HRESULT SFGAOF = wintypes.ULONG SHParseDisplayName = windll.shell32.SHParseDisplayName SHParseDisplayName.argtypes = [ wintypes.LPCWSTR, ctypes.POINTER(IBindCtx), ctypes.POINTER(PIDLIST_ABSOLUTE), SFGAOF, ctypes.POINTER(SFGAOF)] SHParseDisplayName.restype = HRESULT @enum class FOLDERID(str): LINKS = "{bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968}" @enum class SHGFPType(int): CURRENT = 0 DEFAULT = 1 @enum class CSIDL(int): DESKTOP = 0x0000 PERSONAL = 0x0005 APPDATA = 0x001A MYMUSIC = 0x000d PROFILE = 0x0028 @enum class CSIDLFlag(int): PER_USER_INIT = 0x0800 NO_ALIAS = 0x1000 DONT_UNEXPAND = 0x2000 DONT_VERIFY = 0x4000 CREATE = 0x8000 MASK = 0xFF00 @enum class KnownFolderFlag(int): SIMPLE_IDLIST = 0x00000100 NOT_PARENT_RELATIVE = 0x00000200 DEFAULT_PATH = 0x00000400 INIT = 0x00000800 NO_ALIAS = 0x00001000 DONT_UNEXPAND = 0x00002000 DONT_VERIFY = 0x00004000 CREATE = 0x00008000 NO_APPCONTAINER_REDIRECTION = 0x00010000 ALIAS_ONLY = 0x80000000 ������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/windows.py�����������������������������������������������������������0000664�0001750�0001750�00000012432�14035600052�017213� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013,2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from __future__ import absolute_import import sys import os import ctypes if sys.platform == 'win32': from . import winapi from .winapi import SHGFPType, CSIDLFlag, CSIDL, GUID, \ SHGetFolderPathW, S_OK, MAX_PATH, \ KnownFolderFlag, FOLDERID, SHGetKnownFolderPath, CoTaskMemFree, \ CoInitialize, IShellLinkW, CoCreateInstance, CLSID_ShellLink, \ CLSCTX_INPROC_SERVER, IPersistFile def open_folder_and_select_items(folder, items=None): """Shows a directory and optional files or subdirectories in the file manager (explorer.exe). If both folder and items is given the file manager will display the content of `folder` and highlight all `items`. If only a directory is given then the content of the parent directory is shown and the `folder` highlighted. Might raise WindowsError in case something fails (any of the files not existing etc.) """ if items is None: items = [] assert isinstance(folder, str) for item in items: assert isinstance(item, str) assert not os.path.split(item)[0] desktop = winapi.IShellFolder() parent = winapi.IShellFolder() parent_id = winapi.PIDLIST_ABSOLUTE() child_ids = (winapi.PIDLIST_RELATIVE * len(items))() try: winapi.CoInitialize(None) winapi.SHParseDisplayName( folder, None, ctypes.byref(parent_id), 0, None) winapi.SHGetDesktopFolder(ctypes.byref(desktop)) desktop.BindToObject( parent_id, None, winapi.IShellFolder.IID, ctypes.byref(parent)) for i, item in enumerate(items): attrs = winapi.ULONG(0) parent.ParseDisplayName( None, None, item, None, ctypes.byref(child_ids[i]), ctypes.byref(attrs)) winapi.SHOpenFolderAndSelectItems( parent_id, len(child_ids), winapi.PCUITEMID_CHILD_ARRAY(child_ids), 0) finally: for child_id in child_ids: if child_id: winapi.CoTaskMemFree(child_id) if parent_id: winapi.ILFree(parent_id) if parent: parent.Release() if desktop: desktop.Release() def _get_path(folder, default=False, create=False): """A path to an directory or None. Takes a CSIDL instance as folder. """ if default: flags = SHGFPType.DEFAULT else: flags = SHGFPType.CURRENT if create: folder |= CSIDLFlag.CREATE # we don't want env vars folder |= CSIDLFlag.DONT_UNEXPAND buffer_ = ctypes.create_unicode_buffer(MAX_PATH) try: result = SHGetFolderPathW(0, folder, 0, flags, buffer_) except WindowsError: return None if result != S_OK: return None return buffer_.value def _get_known_path(folder, default=False, create=False): """A path to an directory or None Takes a FOLDERID instances as folder. """ if default: flags = KnownFolderFlag.DEFAULT_PATH else: flags = 0 if create: flags |= KnownFolderFlag.CREATE flags |= KnownFolderFlag.DONT_VERIFY ptr = ctypes.c_wchar_p() guid = GUID(folder) try: result = SHGetKnownFolderPath( ctypes.byref(guid), flags, None, ctypes.byref(ptr)) except WindowsError: return None if result != S_OK: return None path = ptr.value CoTaskMemFree(ptr) return path def get_personal_dir(**kwargs): r"""e.g. 'C:\Users\<user>\Documents'""" return _get_path(CSIDL.PERSONAL, **kwargs) def get_appdata_dir(**kwargs): r"""e.g. 'C:\Users\<user>\AppData\Roaming'""" return _get_path(CSIDL.APPDATA, **kwargs) def get_desktop_dir(**kwargs): r"""e.g. 'C:\Users\<user>\Desktop'""" return _get_path(CSIDL.DESKTOP, **kwargs) def get_music_dir(**kwargs): r"""e.g. 'C:\Users\<user>\Music'""" return _get_path(CSIDL.MYMUSIC, **kwargs) def get_profile_dir(**kwargs): r"""e.g. 'C:\Users\<user>'""" return _get_path(CSIDL.PROFILE, **kwargs) def get_links_dir(**kwargs): r"""e.g. 'C:\Users\<user>\Links'""" return _get_known_path(FOLDERID.LINKS, **kwargs) def get_link_target(path): """Takes a path to a .lnk file and returns a path the .lnk file is targeting. Might raise WindowsError in case something fails. """ assert isinstance(path, str) CoInitialize(None) pShellLinkW = IShellLinkW() CoCreateInstance( ctypes.byref(CLSID_ShellLink), None, CLSCTX_INPROC_SERVER, ctypes.byref(IShellLinkW.IID), ctypes.byref(pShellLinkW)) try: pPersistFile = IPersistFile() pShellLinkW.QueryInterface(ctypes.byref(IPersistFile.IID), ctypes.byref(pPersistFile)) try: buffer_ = ctypes.create_unicode_buffer(path, MAX_PATH) pPersistFile.Load(buffer_, 0) finally: pPersistFile.Release() pShellLinkW.GetPath(buffer_, MAX_PATH, None, 0) finally: pShellLinkW.Release() return ctypes.wstring_at(buffer_) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet/util/winpipe.py�����������������������������������������������������������0000664�0001750�0001750�00000011562�14035600052�017177� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014,2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import threading import ctypes if os.name == "nt": from . import winapi from gi.repository import GLib def write_pipe(pipe_name, data): """Writes the data to the pipe or raises EnvironmentError""" assert isinstance(data, bytes) # XXX: otherwise many consecutive open fail, no idea.. pipe_exists(pipe_name) filename = NamedPipeServer._get_filename(pipe_name) with open(filename, "wb") as h: h.write(data) def pipe_exists(pipe_name): """Returns True if the named pipe named 'pipe_name' currently exists""" timeout_ms = 1 filename = NamedPipeServer._get_filename(pipe_name) try: if winapi.WaitNamedPipeW(filename, timeout_ms) == 0: raise ctypes.WinError() except WindowsError: return False return True class NamedPipeServerError(Exception): pass class NamedPipeServer(threading.Thread): """A named pipe for Windows. * server: server = NamedPipeServer("foo", lambda data: ...) server.start() glib_loop() server.stop() * client: with open(NamedPipeServer.get_filename("foo"), "wb") as h: h.write("Hello World") """ def __init__(self, name, callback): """name is the name of the pipe file (should be unique I guess) callback will be called with new data until close() is called. """ super().__init__() self._event = threading.Event() self._filename = self._get_filename(name) self._callback = callback self._stopped = False @classmethod def _get_filename(cls, name): return u"\\\\.\\pipe\\%s" % name def _process(self, data): def idle_process(data): if not self._stopped: self._callback(data) return False GLib.idle_add(idle_process, data) def start(self): super().start() # make sure we can use write_pipe() immediately after this returns self._event.wait() if self._stopped: # something went wrong (maybe another instance is running) raise NamedPipeServerError("Setting up named pipe failed") def run(self): buffer_size = 4096 try: handle = winapi.CreateNamedPipeW( self._filename, (winapi.PIPE_ACCESS_INBOUND | winapi.FILE_FLAG_FIRST_PIPE_INSTANCE), (winapi.PIPE_TYPE_BYTE | winapi.PIPE_READMODE_BYTE | winapi.PIPE_WAIT | winapi.PIPE_REJECT_REMOTE_CLIENTS), winapi.PIPE_UNLIMITED_INSTANCES, buffer_size, buffer_size, winapi.NMPWAIT_USE_DEFAULT_WAIT, None) if handle == winapi.INVALID_HANDLE_VALUE: raise ctypes.WinError() except WindowsError: # due to FILE_FLAG_FIRST_PIPE_INSTANCE and not the first instance self._stopped = True self._event.set() return self._event.set() while 1: data = bytearray() try: if winapi.ConnectNamedPipe(handle, None) == 0: raise ctypes.WinError() while 1: readbuf = ctypes.create_string_buffer(buffer_size) bytesread = winapi.DWORD() try: if winapi.ReadFile( handle, readbuf, buffer_size, ctypes.byref(bytesread), None) == 0: raise ctypes.WinError() except WindowsError: break else: message = readbuf[:bytesread.value] data += message if winapi.DisconnectNamedPipe(handle) == 0: raise ctypes.WinError() except WindowsError: # better not loop forever.. break finally: if self._stopped: break if data: self._process(bytes(data)) # ignore errors here.. winapi.CloseHandle(handle) def stop(self): """After this returns the callback will no longer be called. Can be called multiple times. """ self._event.wait() if self._stopped: return self._stopped = True try: with open(self._filename, "wb") as h: h.write(b"stop!") except EnvironmentError: pass self._callback = None self.join() ����������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735241.9776022 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.egg-info/�����������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015664� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692735241.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.egg-info/PKG-INFO���������������������������������������������������������0000664�0001750�0001750�00000000526�14471213411�016765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Metadata-Version: 2.1 Name: quodlibet Version: 4.6.0 Summary: a music library, tagger, and player Home-page: https://quodlibet.readthedocs.org Author: Joe Wreschnig, Michael Urman, & others Author-email: quod-libet-development@googlegroups.com Maintainer: Steven Robertson and Christoph Reiter License: GPL-2.0-or-later License-File: COPYING ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692735241.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.egg-info/SOURCES.txt������������������������������������������������������0000664�0001750�0001750�00000065573�14471213411�017571� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.deepsource.toml .readthedocs.yaml COPYING MANIFEST.in NEWS.rst README.rst exfalso.py operon.py poetry.lock pyproject.toml quodlibet.py setup.cfg setup.py data/README.rst data/exfalso.1 data/io.github.quodlibet.ExFalso.appdata.xml.in data/io.github.quodlibet.ExFalso.desktop.in data/io.github.quodlibet.QuodLibet-search-provider.ini data/io.github.quodlibet.QuodLibet.appdata.xml.in data/io.github.quodlibet.QuodLibet.desktop.in data/net.sacredchao.QuodLibet.service.in data/operon.1 data/org.mpris.MediaPlayer2.quodlibet.service.in data/org.mpris.quodlibet.service.in data/quodlibet.1 data/quodlibet.bash data/quodlibet.zsh docs/Makefile docs/README.rst docs/bugs_repo.rst docs/changelog.rst docs/conf.py docs/contact.rst docs/downloads.rst docs/extra.css docs/features.rst docs/icons.rst docs/index.rst docs/license.rst docs/packaging.rst docs/requirements.txt docs/screenshots.rst docs/development/contributing.rst docs/development/devenv.rst docs/development/faq.rst docs/development/flatpak.rst docs/development/formats.rst docs/development/guidelines.rst docs/development/index.rst docs/development/maint.rst docs/development/overview.rst docs/development/plugins.rst docs/development/testing.rst docs/development/tools.rst docs/ext/contributors.py docs/favicon/Makefile docs/favicon/README.rst docs/favicon/favicon.ico docs/favicon/favicon.svg docs/guide/config_files.rst docs/guide/editing_tags.rst docs/guide/faq.rst docs/guide/index.rst docs/guide/interacting.rst docs/guide/overview.rst docs/guide/queue.rst docs/guide/renaming_files.rst docs/guide/searching.rst docs/guide/shortcuts.rst docs/guide/stats_rating.rst docs/guide/browse/album.rst docs/guide/browse/audiofeeds.rst docs/guide/browse/filesystem.rst docs/guide/browse/index.rst docs/guide/browse/iradio.rst docs/guide/browse/overview.rst docs/guide/browse/paned.rst docs/guide/browse/playlists.rst docs/guide/browse/podcasts.rst docs/guide/browse/search.rst docs/guide/browse/soundcloud.rst docs/guide/commands/Makefile docs/guide/commands/exfalso.rst docs/guide/commands/index.rst docs/guide/commands/operon.rst docs/guide/commands/quodlibet.rst docs/guide/images/browser-window.png docs/guide/images/main-overview.png docs/guide/images/playlist-browser.png docs/guide/images/plugins.png docs/guide/images/queue.png docs/guide/playback/backends.rst docs/guide/playback/index.rst docs/guide/playback/replaygain.rst docs/guide/playback/images/replaygain_force.png docs/guide/playback/images/replaygain_plugin.png docs/guide/playback/images/replaygain_pref.png docs/guide/tags/index.rst docs/guide/tags/internal_tags.rst docs/guide/tags/patterns.rst docs/guide/tags/tags.rst docs/guide/tags/tied_tags.rst docs/images/album-list-2017-08.png docs/images/album.png docs/images/covergrid-plus-waveform-2017-08.png docs/images/exfalso.png docs/images/paned.png docs/images/plugins.png docs/images/queue_2browsers.png docs/images/soundcloud-browser-2017-08.png docs/images/tagedit.png docs/images/tagrename.png docs/tables/default.rst docs/tables/osx_exfalso.rst docs/tables/osx_quodlibet.rst docs/tables/windows.rst docs/tables/windows_portable.rst docs/translation/faq.rst docs/translation/howto_manual.rst docs/translation/index.rst gdist/__init__.py gdist/appdata.py gdist/bash_completions.py gdist/clean.py gdist/coverage.py gdist/dbus_services.py gdist/docs.py gdist/gettextutil.py gdist/icons.py gdist/man.py gdist/po.py gdist/scripts.py gdist/search_provider.py gdist/shortcuts.py gdist/tests.py gdist/util.py gdist/zsh_completions.py po/POTFILES.in po/POTFILES.skip po/bg.po po/cs.po po/da.po po/de.po po/el.po po/en_CA.po po/en_GB.po po/es.po po/eu.po po/fi.po po/fr.po po/gl.po po/he.po po/hu.po po/id.po po/it.po po/ja.po po/ko.po po/lt.po po/lv.po po/nb.po po/nl.po po/pl.po po/pt.po po/quodlibet.pot po/ro.po po/ru.po po/sk.po po/sr_RS.po po/sr_RS@latin.po po/sv.po po/tr.po po/uk.po po/zh_CN.po po/zh_TW.po quodlibet/__init__.py quodlibet/_import.py quodlibet/_init.py quodlibet/_main.py quodlibet/build.py quodlibet/cli.py quodlibet/commands.py quodlibet/config.py quodlibet/const.py quodlibet/exfalso.py quodlibet/main.py quodlibet/remote.py quodlibet/update.py quodlibet.egg-info/PKG-INFO quodlibet.egg-info/SOURCES.txt quodlibet.egg-info/dependency_links.txt quodlibet.egg-info/top_level.txt quodlibet/browsers/__init__.py quodlibet/browsers/_base.py quodlibet/browsers/filesystem.py quodlibet/browsers/iradio.py quodlibet/browsers/podcasts.py quodlibet/browsers/tracks.py quodlibet/browsers/albums/__init__.py quodlibet/browsers/albums/main.py quodlibet/browsers/albums/models.py quodlibet/browsers/albums/prefs.py quodlibet/browsers/collection/__init__.py quodlibet/browsers/collection/main.py quodlibet/browsers/collection/models.py quodlibet/browsers/collection/prefs.py quodlibet/browsers/covergrid/__init__.py quodlibet/browsers/covergrid/main.py quodlibet/browsers/covergrid/models.py quodlibet/browsers/covergrid/prefs.py quodlibet/browsers/covergrid/widgets.py quodlibet/browsers/paned/__init__.py quodlibet/browsers/paned/main.py quodlibet/browsers/paned/models.py quodlibet/browsers/paned/pane.py quodlibet/browsers/paned/prefs.py quodlibet/browsers/paned/util.py quodlibet/browsers/playlists/__init__.py quodlibet/browsers/playlists/main.py quodlibet/browsers/playlists/menu.py quodlibet/browsers/playlists/prefs.py quodlibet/browsers/playlists/util.py quodlibet/browsers/soundcloud/__init__.py quodlibet/browsers/soundcloud/api.py quodlibet/browsers/soundcloud/library.py quodlibet/browsers/soundcloud/main.py quodlibet/browsers/soundcloud/query.py quodlibet/browsers/soundcloud/util.py quodlibet/errorreport/__init__.py quodlibet/errorreport/faulthandling.py quodlibet/errorreport/logdump.py quodlibet/errorreport/main.py quodlibet/errorreport/sentrywrapper.py quodlibet/errorreport/ui.py quodlibet/ext/__init__.py quodlibet/ext/_shared/__init__.py quodlibet/ext/_shared/squeezebox/__init__.py quodlibet/ext/_shared/squeezebox/base.py quodlibet/ext/_shared/squeezebox/server.py quodlibet/ext/_shared/squeezebox/util.py quodlibet/ext/covers/__init__.py quodlibet/ext/covers/artwork_url.py quodlibet/ext/covers/discogs.py quodlibet/ext/covers/lastfm.py quodlibet/ext/covers/musicbrainz.py quodlibet/ext/editing/__init__.py quodlibet/ext/editing/iconv.py quodlibet/ext/editing/kakasi.py quodlibet/ext/editing/resub.py quodlibet/ext/editing/titlecase.py quodlibet/ext/events/__init__.py quodlibet/ext/events/advanced_preferences.py quodlibet/ext/events/appinfo.py quodlibet/ext/events/auto_update_tags_in_files.py quodlibet/ext/events/automask.py quodlibet/ext/events/autorating.py quodlibet/ext/events/bansheeimport.py quodlibet/ext/events/clock.py quodlibet/ext/events/discord_status.py quodlibet/ext/events/equalizer.py quodlibet/ext/events/gajim_status.py quodlibet/ext/events/headphonemon.py quodlibet/ext/events/inhibit.py quodlibet/ext/events/iradiolog.py quodlibet/ext/events/jep118.py quodlibet/ext/events/language.py quodlibet/ext/events/mediaserver.py quodlibet/ext/events/mqtt.py quodlibet/ext/events/musicbrainzsync.py quodlibet/ext/events/notify.py quodlibet/ext/events/notify_bookmarks.py quodlibet/ext/events/qlscrobbler.py quodlibet/ext/events/radioadmute.py quodlibet/ext/events/randomalbum.py quodlibet/ext/events/rbimport.py quodlibet/ext/events/screensaver.py quodlibet/ext/events/searchprovider.py quodlibet/ext/events/seekbar.py quodlibet/ext/events/seekpoints.py quodlibet/ext/events/squeezebox_sync.py quodlibet/ext/events/stop_on_pause.py quodlibet/ext/events/synchronize_to_device.py quodlibet/ext/events/synchronizedlyrics.py quodlibet/ext/events/telepathy_status.py quodlibet/ext/events/themeswitcher.py quodlibet/ext/events/thumbrating.py quodlibet/ext/events/toggle_menu.py quodlibet/ext/events/viewlyrics.py quodlibet/ext/events/visualisations.py quodlibet/ext/events/waveformseekbar.py quodlibet/ext/events/write_cover.py quodlibet/ext/events/animosd/__init__.py quodlibet/ext/events/animosd/config.py quodlibet/ext/events/animosd/main.py quodlibet/ext/events/animosd/osdwindow.py quodlibet/ext/events/animosd/prefs.py quodlibet/ext/events/listenbrainz/__init__.py quodlibet/ext/events/listenbrainz/listenbrainz.py quodlibet/ext/events/mpdserver/__init__.py quodlibet/ext/events/mpdserver/avahi.py quodlibet/ext/events/mpdserver/main.py quodlibet/ext/events/mpdserver/tcpserver.py quodlibet/ext/events/mpris/__init__.py quodlibet/ext/events/mpris/mpris2.py quodlibet/ext/events/mpris/util.py quodlibet/ext/events/trayicon/__init__.py quodlibet/ext/events/trayicon/appindicator.py quodlibet/ext/events/trayicon/base.py quodlibet/ext/events/trayicon/menu.py quodlibet/ext/events/trayicon/prefs.py quodlibet/ext/events/trayicon/systemtray.py quodlibet/ext/events/trayicon/util.py quodlibet/ext/gstreamer/__init__.py quodlibet/ext/gstreamer/compressor.py quodlibet/ext/gstreamer/crossfeed.py quodlibet/ext/gstreamer/karaoke.py quodlibet/ext/gstreamer/mono.py quodlibet/ext/gstreamer/pitch.py quodlibet/ext/playlist/__init__.py quodlibet/ext/playlist/export_to_folder.py quodlibet/ext/playlist/export_to_sonos.py quodlibet/ext/playlist/export_to_squeezebox.py quodlibet/ext/playlist/remove_duplicates.py quodlibet/ext/playlist/shuffle.py quodlibet/ext/playorder/__init__.py quodlibet/ext/playorder/follow.py quodlibet/ext/playorder/playcounteq.py quodlibet/ext/playorder/queue.py quodlibet/ext/playorder/reverse.py quodlibet/ext/playorder/shufflebygrouping.py quodlibet/ext/playorder/skip_disliked.py quodlibet/ext/playorder/track_repeat.py quodlibet/ext/query/__init__.py quodlibet/ext/query/conditional.py quodlibet/ext/query/missing.py quodlibet/ext/query/pythonexpression.py quodlibet/ext/query/savedsearch.py quodlibet/ext/query/unique.py quodlibet/ext/songsmenu/__init__.py quodlibet/ext/songsmenu/albumart.py quodlibet/ext/songsmenu/ape2id3.py quodlibet/ext/songsmenu/bookmarks.py quodlibet/ext/songsmenu/console.py quodlibet/ext/songsmenu/cover_download.py quodlibet/ext/songsmenu/custom_commands.py quodlibet/ext/songsmenu/duplicates.py quodlibet/ext/songsmenu/editplaycount.py quodlibet/ext/songsmenu/embedded.py quodlibet/ext/songsmenu/exact_rating.py quodlibet/ext/songsmenu/filterall.py quodlibet/ext/songsmenu/filterbrowser.py quodlibet/ext/songsmenu/forcewrite.py quodlibet/ext/songsmenu/html.py quodlibet/ext/songsmenu/ifp.py quodlibet/ext/songsmenu/import_export_tags_and_track_user_data.py quodlibet/ext/songsmenu/lastfmsync.py quodlibet/ext/songsmenu/makesorttags.py quodlibet/ext/songsmenu/playlist.py quodlibet/ext/songsmenu/refresh.py quodlibet/ext/songsmenu/replaygain.py quodlibet/ext/songsmenu/splitting.py quodlibet/ext/songsmenu/tapbpm.py quodlibet/ext/songsmenu/website_search.py quodlibet/ext/songsmenu/wikipedia.py quodlibet/ext/songsmenu/brainz/__init__.py quodlibet/ext/songsmenu/brainz/mb.py quodlibet/ext/songsmenu/brainz/query.py quodlibet/ext/songsmenu/brainz/util.py quodlibet/ext/songsmenu/brainz/widgets.py quodlibet/ext/songsmenu/fingerprint/__init__.py quodlibet/ext/songsmenu/fingerprint/acoustid.py quodlibet/ext/songsmenu/fingerprint/analyze.py quodlibet/ext/songsmenu/fingerprint/search.py quodlibet/ext/songsmenu/fingerprint/submit.py quodlibet/ext/songsmenu/fingerprint/util.py quodlibet/formats/__init__.py quodlibet/formats/_apev2.py quodlibet/formats/_audio.py quodlibet/formats/_id3.py quodlibet/formats/_image.py quodlibet/formats/_misc.py quodlibet/formats/_serialize.py quodlibet/formats/aac.py quodlibet/formats/aiff.py quodlibet/formats/dsf.py quodlibet/formats/midi.py quodlibet/formats/mod.py quodlibet/formats/monkeysaudio.py quodlibet/formats/mp3.py quodlibet/formats/mp4.py quodlibet/formats/mpc.py quodlibet/formats/remote.py quodlibet/formats/spc.py quodlibet/formats/trueaudio.py quodlibet/formats/vgm.py quodlibet/formats/wav.py quodlibet/formats/wavpack.py quodlibet/formats/wma.py quodlibet/formats/xiph.py quodlibet/images/Makefile quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/128x128/status/quodlibet-missing-cover.png quodlibet/images/hicolor/16x16/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/16x16/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/16x16/status/quodlibet-missing-cover.png quodlibet/images/hicolor/24x24/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/24x24/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/24x24/status/quodlibet-missing-cover.png quodlibet/images/hicolor/256x256/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/256x256/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/256x256/status/quodlibet-missing-cover.png quodlibet/images/hicolor/32x32/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/32x32/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/32x32/status/quodlibet-missing-cover.png quodlibet/images/hicolor/48x48/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/48x48/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/48x48/status/quodlibet-missing-cover.png quodlibet/images/hicolor/64x64/apps/io.github.quodlibet.ExFalso.png quodlibet/images/hicolor/64x64/apps/io.github.quodlibet.QuodLibet.png quodlibet/images/hicolor/64x64/status/quodlibet-missing-cover.png quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg.in quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso.svg quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg.in quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet.svg quodlibet/images/hicolor/scalable/status/quodlibet-missing-cover.svg quodlibet/library/__init__.py quodlibet/library/album.py quodlibet/library/base.py quodlibet/library/file.py quodlibet/library/librarians.py quodlibet/library/playlist.py quodlibet/library/song.py quodlibet/mmkeys/__init__.py quodlibet/mmkeys/_base.py quodlibet/mmkeys/gnome.py quodlibet/mmkeys/keybinder.py quodlibet/mmkeys/osx.py quodlibet/mmkeys/winhook.py quodlibet/operon/__init__.py quodlibet/operon/base.py quodlibet/operon/commands.py quodlibet/operon/main.py quodlibet/operon/util.py quodlibet/order/__init__.py quodlibet/order/reorder.py quodlibet/order/repeat.py quodlibet/packages/README.rst quodlibet/packages/__init__.py quodlibet/packages/update.sh quodlibet/packages/raven/__init__.py quodlibet/packages/raven/base.py quodlibet/packages/raven/breadcrumbs.py quodlibet/packages/raven/context.py quodlibet/packages/raven/events.py quodlibet/packages/raven/exceptions.py quodlibet/packages/raven/middleware.py quodlibet/packages/raven/processors.py quodlibet/packages/raven/versioning.py quodlibet/packages/raven/conf/__init__.py quodlibet/packages/raven/conf/defaults.py quodlibet/packages/raven/conf/remote.py quodlibet/packages/raven/handlers/__init__.py quodlibet/packages/raven/handlers/logbook.py quodlibet/packages/raven/handlers/logging.py quodlibet/packages/raven/scripts/__init__.py quodlibet/packages/raven/scripts/runner.py quodlibet/packages/raven/transport/__init__.py quodlibet/packages/raven/transport/base.py quodlibet/packages/raven/transport/eventlet.py quodlibet/packages/raven/transport/exceptions.py quodlibet/packages/raven/transport/gevent.py quodlibet/packages/raven/transport/http.py quodlibet/packages/raven/transport/registry.py quodlibet/packages/raven/transport/requests.py quodlibet/packages/raven/transport/threaded.py quodlibet/packages/raven/transport/threaded_requests.py quodlibet/packages/raven/transport/tornado.py quodlibet/packages/raven/transport/twisted.py quodlibet/packages/raven/utils/__init__.py quodlibet/packages/raven/utils/compat.py quodlibet/packages/raven/utils/conf.py quodlibet/packages/raven/utils/encoding.py quodlibet/packages/raven/utils/http.py quodlibet/packages/raven/utils/imports.py quodlibet/packages/raven/utils/json.py quodlibet/packages/raven/utils/ssl_match_hostname.py quodlibet/packages/raven/utils/stacks.py quodlibet/packages/raven/utils/testutils.py quodlibet/packages/raven/utils/transaction.py quodlibet/packages/raven/utils/urlparse.py quodlibet/packages/raven/utils/wsgi.py quodlibet/packages/raven/utils/serializer/__init__.py quodlibet/packages/raven/utils/serializer/base.py quodlibet/packages/raven/utils/serializer/manager.py quodlibet/packages/senf/__init__.py quodlibet/packages/senf/__init__.pyi quodlibet/packages/senf/_argv.py quodlibet/packages/senf/_compat.py quodlibet/packages/senf/_environ.py quodlibet/packages/senf/_fsnative.py quodlibet/packages/senf/_print.py quodlibet/packages/senf/_stdlib.py quodlibet/packages/senf/_temp.py quodlibet/packages/senf/_winansi.py quodlibet/packages/senf/_winapi.py quodlibet/pattern/__init__.py quodlibet/pattern/_pattern.py quodlibet/player/__init__.py quodlibet/player/_base.py quodlibet/player/nullbe.py quodlibet/player/gstbe/__init__.py quodlibet/player/gstbe/player.py quodlibet/player/gstbe/plugins.py quodlibet/player/gstbe/prefs.py quodlibet/player/gstbe/util.py quodlibet/player/xinebe/__init__.py quodlibet/player/xinebe/cdefs.py quodlibet/player/xinebe/player.py quodlibet/plugins/__init__.py quodlibet/plugins/cover.py quodlibet/plugins/editing.py quodlibet/plugins/events.py quodlibet/plugins/gstelement.py quodlibet/plugins/gui.py quodlibet/plugins/playlist.py quodlibet/plugins/playorder.py quodlibet/plugins/query.py quodlibet/plugins/songshelpers.py quodlibet/plugins/songsmenu.py quodlibet/qltk/__init__.py quodlibet/qltk/_editutils.py quodlibet/qltk/about.py quodlibet/qltk/appwindow.py quodlibet/qltk/bookmarks.py quodlibet/qltk/browser.py quodlibet/qltk/cbes.py quodlibet/qltk/ccb.py quodlibet/qltk/chooser.py quodlibet/qltk/color.py quodlibet/qltk/completion.py quodlibet/qltk/controls.py quodlibet/qltk/cover.py quodlibet/qltk/data_editors.py quodlibet/qltk/dbus_.py quodlibet/qltk/delete.py quodlibet/qltk/download.py quodlibet/qltk/edittags.py quodlibet/qltk/entry.py quodlibet/qltk/exfalsowindow.py quodlibet/qltk/filesel.py quodlibet/qltk/getstring.py quodlibet/qltk/icons.py quodlibet/qltk/image.py quodlibet/qltk/info.py quodlibet/qltk/information.py quodlibet/qltk/lyrics.py quodlibet/qltk/maskedbox.py quodlibet/qltk/matchdialog.py quodlibet/qltk/menubutton.py quodlibet/qltk/models.py quodlibet/qltk/msg.py quodlibet/qltk/notif.py quodlibet/qltk/paned.py quodlibet/qltk/playorder.py quodlibet/qltk/pluginwin.py quodlibet/qltk/prefs.py quodlibet/qltk/properties.py quodlibet/qltk/queue.py quodlibet/qltk/quodlibetwindow.py quodlibet/qltk/ratingsmenu.py quodlibet/qltk/renamefiles.py quodlibet/qltk/scanbox.py quodlibet/qltk/searchbar.py quodlibet/qltk/seekbutton.py quodlibet/qltk/shortcuts.py quodlibet/qltk/showfiles.py quodlibet/qltk/songlist.py quodlibet/qltk/songlistcolumns.py quodlibet/qltk/songmodel.py quodlibet/qltk/songsmenu.py quodlibet/qltk/tagscombobox.py quodlibet/qltk/tagsfrompath.py quodlibet/qltk/textedit.py quodlibet/qltk/tracker.py quodlibet/qltk/tracknumbers.py quodlibet/qltk/unity.py quodlibet/qltk/util.py quodlibet/qltk/views.py quodlibet/qltk/window.py quodlibet/qltk/wlw.py quodlibet/qltk/x.py quodlibet/query/__init__.py quodlibet/query/_match.py quodlibet/query/_parser.py quodlibet/query/_query.py quodlibet/session/__init__.py quodlibet/session/_base.py quodlibet/session/_xsmp.py quodlibet/session/gnome.py quodlibet/session/xfce.py quodlibet/session/xsmp.py quodlibet/unisearch/__init__.py quodlibet/unisearch/db.py quodlibet/unisearch/parser.py quodlibet/util/__init__.py quodlibet/util/atomic.py quodlibet/util/collection.py quodlibet/util/collections.py quodlibet/util/config.py quodlibet/util/copool.py quodlibet/util/dbusutils.py quodlibet/util/dprint.py quodlibet/util/enum.py quodlibet/util/environment.py quodlibet/util/fifo.py quodlibet/util/http.py quodlibet/util/i18n.py quodlibet/util/importhelper.py quodlibet/util/iso639.py quodlibet/util/json_data.py quodlibet/util/library.py quodlibet/util/logging.py quodlibet/util/massagers.py quodlibet/util/matcher.py quodlibet/util/misc.py quodlibet/util/modulescanner.py quodlibet/util/path.py quodlibet/util/picklehelper.py quodlibet/util/songwrapper.py quodlibet/util/tags.py quodlibet/util/tagsfrompath.py quodlibet/util/thread.py quodlibet/util/thumbnails.py quodlibet/util/trash.py quodlibet/util/urllib.py quodlibet/util/winapi.py quodlibet/util/windows.py quodlibet/util/winpipe.py quodlibet/util/cover/__init__.py quodlibet/util/cover/built_in.py quodlibet/util/cover/http.py quodlibet/util/cover/manager.py quodlibet/util/string/__init__.py quodlibet/util/string/date.py quodlibet/util/string/filter.py quodlibet/util/string/splitters.py quodlibet/util/string/titlecase.py tests/__init__.py tests/conftest.py tests/gtk_helpers.py tests/helper.py tests/test___init__.py tests/test_appdata_files.py tests/test_browsers___init__.py tests/test_browsers__base.py tests/test_browsers_albums.py tests/test_browsers_collection.py tests/test_browsers_covergrid.py tests/test_browsers_filesystem.py tests/test_browsers_iradio.py tests/test_browsers_paned.py tests/test_browsers_playlists.py tests/test_browsers_podcasts.py tests/test_browsers_search.py tests/test_browsers_soundcloud.py tests/test_cli.py tests/test_commands.py tests/test_config.py tests/test_desktop_files.py tests/test_errorreport.py tests/test_formats___init__.py tests/test_formats__audio.py tests/test_formats__id3.py tests/test_formats__image.py tests/test_formats_aac.py tests/test_formats_aiff.py tests/test_formats_all.py tests/test_formats_apev2.py tests/test_formats_dsf.py tests/test_formats_midi.py tests/test_formats_mod.py tests/test_formats_mp3.py tests/test_formats_mp4.py tests/test_formats_mpc.py tests/test_formats_remote.py tests/test_formats_spc.py tests/test_formats_trueaudio.py tests/test_formats_vgm.py tests/test_formats_wav.py tests/test_formats_wavpack.py tests/test_formats_wma.py tests/test_formats_xiph.py tests/test_gio.py tests/test_https.py tests/test_icons.py tests/test_image_support.py tests/test_library_album.py tests/test_library_file.py tests/test_library_librarians.py tests/test_library_libraries.py tests/test_library_playlist.py tests/test_library_song.py tests/test_metadata.py tests/test_mmkeys.py tests/test_operon.py tests/test_order.py tests/test_pattern.py tests/test_player.py tests/test_player_gst.py tests/test_player_xine.py tests/test_playlist_menu.py tests/test_playlist_util.py tests/test_plugins___init__.py tests/test_plugins_cover.py tests/test_plugins_events.py tests/test_plugins_playlist.py tests/test_plugins_songsmenu.py tests/test_po.py tests/test_qltk___init__.py tests/test_qltk__editutils.py tests/test_qltk_about.py tests/test_qltk_bookmarks.py tests/test_qltk_browser.py tests/test_qltk_cbes.py tests/test_qltk_ccb.py tests/test_qltk_chooser.py tests/test_qltk_completion.py tests/test_qltk_controls.py tests/test_qltk_cover.py tests/test_qltk_data_editors.py tests/test_qltk_delete.py tests/test_qltk_download.py tests/test_qltk_edittags.py tests/test_qltk_entry.py tests/test_qltk_exfalso.py tests/test_qltk_filesel.py tests/test_qltk_getstring.py tests/test_qltk_image.py tests/test_qltk_info.py tests/test_qltk_information.py tests/test_qltk_lyrics.py tests/test_qltk_maskedbox.py tests/test_qltk_models.py tests/test_qltk_msg.py tests/test_qltk_notif.py tests/test_qltk_paned.py tests/test_qltk_playorder.py tests/test_qltk_pluginwin.py tests/test_qltk_prefs.py tests/test_qltk_properties.py tests/test_qltk_queue.py tests/test_qltk_quodlibetwindow.py tests/test_qltk_ratingsmenu.py tests/test_qltk_renamefiles.py tests/test_qltk_scanbox.py tests/test_qltk_searchbar.py tests/test_qltk_seekbutton.py tests/test_qltk_songlist.py tests/test_qltk_songlistcolumns.py tests/test_qltk_songmodel.py tests/test_qltk_songsmenu.py tests/test_qltk_tagscombobox.py tests/test_qltk_tagsfrompath.py tests/test_qltk_textedit.py tests/test_qltk_tracker.py tests/test_qltk_unity.py tests/test_qltk_util.py tests/test_qltk_views.py tests/test_qltk_window.py tests/test_qltk_wlw.py tests/test_qltk_x.py tests/test_query.py tests/test_query__match.py tests/test_remote.py tests/test_session.py tests/test_setup.py tests/test_soundcloudFile.py tests/test_soundcloudLibrary.py tests/test_unisearch.py tests/test_update.py tests/test_util.py tests/test_util_atomic.py tests/test_util_collection.py tests/test_util_collections.py tests/test_util_config.py tests/test_util_copool.py tests/test_util_cover.py tests/test_util_dbusutils.py tests/test_util_dprint.py tests/test_util_environment.py tests/test_util_fifo.py tests/test_util_i18n.py tests/test_util_json_data.py tests/test_util_library.py tests/test_util_logging.py tests/test_util_massagers.py tests/test_util_matcher.py tests/test_util_modulescanner.py tests/test_util_path.py tests/test_util_picklehelper.py tests/test_util_string.py tests/test_util_string_filter.py tests/test_util_string_splitters.py tests/test_util_string_titlecase.py tests/test_util_tags.py tests/test_util_tagsfrompath.py tests/test_util_thread.py tests/test_util_thumbnails.py tests/test_util_trash.py tests/test_windows.py tests/data/2822400-1ch-0s-silence.dsf tests/data/5644800-2ch-s01-silence.dsf tests/data/adif.aac tests/data/coverart.wv tests/data/empty.aac tests/data/empty.flac tests/data/empty.ogg tests/data/empty.opus tests/data/empty.xm tests/data/h264_aac.mp4 tests/data/h265_aac.mp4 tests/data/image.bmp tests/data/image.gif tests/data/image.jpg tests/data/image.png tests/data/image.svg tests/data/lame.mp3 tests/data/mac-396.ape tests/data/mutagen-bug.mp3 tests/data/non-compliant.xspf tests/data/silence-44-s.ape tests/data/silence-44-s.flac tests/data/silence-44-s.mp3 tests/data/silence-44-s.mpc tests/data/silence-44-s.ogg tests/data/silence-44-s.spx tests/data/silence-44-s.sv8.mpc tests/data/silence-44-s.tta tests/data/silence-44-s.wv tests/data/sine-110hz.flac tests/data/soundcloud_track_response.json tests/data/test-2.wma tests/data/test.aiff tests/data/test.asf tests/data/test.lnk tests/data/test.m3u8 tests/data/test.m4a tests/data/test.mid tests/data/test.mp2 tests/data/test.png tests/data/test.spc tests/data/test.vgm tests/data/test.wav tests/data/test.wma tests/data/test2.lnk tests/data/valid_podcast.xml tests/data/with-id3.dsf tests/data/without-id3.dsf tests/plugin/__init__.py tests/plugin/test_albumart.py tests/plugin/test_bansheeimport.py tests/plugin/test_brainz.py tests/plugin/test_clock.py tests/plugin/test_console.py tests/plugin/test_cover_download.py tests/plugin/test_covers.py tests/plugin/test_custom_commands.py tests/plugin/test_duplicates_browser.py tests/plugin/test_fingerprint.py tests/plugin/test_html.py tests/plugin/test_mediaserver.py tests/plugin/test_mpdserver.py tests/plugin/test_mpris.py tests/plugin/test_playlist.py tests/plugin/test_prefs.py tests/plugin/test_query.py tests/plugin/test_randomalbum.py tests/plugin/test_rbimport.py tests/plugin/test_replaygain.py tests/plugin/test_scrobbler.py tests/plugin/test_seekbar.py tests/plugin/test_songsmenu.py tests/plugin/test_style.py tests/plugin/test_synchronize_to_device.py tests/plugin/test_synchronizedlyrics.py tests/plugin/test_test_plugins.py tests/plugin/test_titlecase.py tests/plugin/test_trayicon.py tests/plugin/test_viewlyrics.py tests/plugin/test_waveformseekbar.py tests/plugin/test_website_search.py tests/plugin/test_plugins/pickle_plugin.py tests/quality/__init__.py tests/quality/test_flake8.py tests/quality/test_mypy.py tests/quality/test_source.py�������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692735241.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.egg-info/dependency_links.txt���������������������������������������������0000664�0001750�0001750�00000000001�14471213411�021733� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692735241.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.egg-info/top_level.txt����������������������������������������������������0000664�0001750�0001750�00000000012�14471213411�020410� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/quodlibet.py������������������������������������������������������������������������0000775�0001750�0001750�00000000621�14035600052�014544� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env python3 # Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from quodlibet.main import main if __name__ == "__main__": sys.exit(main()) ���������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.034269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/setup.cfg���������������������������������������������������������������������������0000644�0001750�0001750�00000001461�14471213412�014025� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[flake8] ignore = E12,E261,E265,E713,W602,E402,E731,W503,W504,E741,E305,W601,E722,E275 builtins = exclude = build,dist,quodlibet/packages,dev-utils max-line-length = 88 [mypy] python_version = 3.8 ignore_missing_imports = True mypy_path = quodlibet/packages exclude = (quodlibet/packages/.+/.+\.py|dev-utils/.*) follow_imports = silent disable_error_code = annotation-unchecked [mypy-quodlibet.packages.*] ignore_errors = True [mypy-tests.*] ignore_errors = True [mypy-gi.repository] ignore_errors = True [mypy-gdist.*] ignore_errors = True [tool:pytest] junit_suite_name = quodlibet addopts = --tb=short filterwarnings = ignore::DeprecationWarning markers = quality: Code quality tests (e.g. PEP-8 compliance) network: Tests that need working internet connectivity [egg_info] tag_build = tag_date = 0 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/setup.py����������������������������������������������������������������������������0000775�0001750�0001750�00000010711�14035600052�013715� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env python3 # Copyright 2010-2015 Christoph Reiter # 2015 Nick Boultbee # 2010 Steven Robertson # 2007-2008 Joe Wreschnig # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import sys import types from gdist import GDistribution, setup def exec_module(path): """Executes the Python file at `path` and returns it as the module""" globals_ = {} with open(path, encoding="utf-8") as h: exec(h.read(), globals_) module = types.ModuleType("") module.__dict__.update(globals_) return module def main(): assert sys.version_info[0] == 3, "Quod Libet is Python 3 only now" # distutils depends on setup.py beeing executed from the same dir. # Most of our custom commands work either way, but this makes # it work in all cases. os.chdir(os.path.dirname(os.path.realpath(__file__))) const = exec_module(os.path.join("quodlibet", "const.py")) # convert to a setuptools compatible version string version = const.VERSION_TUPLE if version[-1] == -1: version_string = ".".join(map(str, version[:-1])) + ".dev0" else: version_string = ".".join(map(str, version)) package_path = "quodlibet" packages = [] for root, dirnames, filenames in os.walk(package_path): if "__init__.py" in filenames: relpath = os.path.relpath(root, os.path.dirname(package_path)) package_name = relpath.replace(os.sep, ".") packages.append(package_name) assert packages setup_kwargs = { 'distclass': GDistribution, 'name': "quodlibet", 'version': version_string, 'url': "https://quodlibet.readthedocs.org", 'description': "a music library, tagger, and player", 'author': "Joe Wreschnig, Michael Urman, & others", 'author_email': "quod-libet-development@googlegroups.com", 'maintainer': "Steven Robertson and Christoph Reiter", 'license': "GPL-2.0-or-later", 'packages': packages, 'package_data': { "quodlibet": [ "images/hicolor/*/*/*.png", "images/hicolor/*/*/*.svg", ], }, 'scripts': [ "quodlibet.py", "exfalso.py", "operon.py", ], 'po_directory': "po", 'po_package': "quodlibet", 'shortcuts': [ "data/io.github.quodlibet.QuodLibet.desktop", "data/io.github.quodlibet.ExFalso.desktop" ], 'dbus_services': [ "data/net.sacredchao.QuodLibet.service", # https://github.com/quodlibet/quodlibet/issues/1268 # "data/org.mpris.MediaPlayer2.quodlibet.service", # "data/org.mpris.quodlibet.service", ], 'appdata': [ "data/io.github.quodlibet.QuodLibet.appdata.xml", "data/io.github.quodlibet.ExFalso.appdata.xml", ], 'man_pages': [ "data/quodlibet.1", "data/exfalso.1", "data/operon.1", ], "search_provider": "data/io.github.quodlibet.QuodLibet-search-provider.ini", "bash_completions": [ ("data/quodlibet.bash", "quodlibet"), ("data/quodlibet.bash", "operon"), ], "zsh_completions": [ ("data/quodlibet.zsh", "_quodlibet"), ], "coverage_options": { "directory": "coverage", }, } setup(**setup_kwargs) if __name__ == "__main__": main() �������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735242.0276024 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�013344� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/__init__.py�������������������������������������������������������������������0000644�0001750�0001750�00000021476�14455205526�015500� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import sys import unittest import tempfile import shutil import atexit import subprocess import locale try: import pytest except ImportError: raise SystemExit("pytest missing: sudo apt-get install python3-pytest") try: import pyvirtualdisplay except ImportError: pyvirtualdisplay = None import quodlibet from quodlibet.util.path import xdg_get_cache_home from quodlibet import util from senf import fsnative, path2fsn from unittest import TestCase as OrigTestCase class TestCase(OrigTestCase): """Adds aliases for equality-type methods. Also swaps first and second parameters to support our mostly-favoured assertion style e.g. `assertEqual(actual, expected)`""" def assertEqual(self, first, second, msg=None): super().assertEqual(second, first, msg) def assertNotEqual(self, first, second, msg=None): super().assertNotEqual(second, first, msg) def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None): super().assertAlmostEqual(second, first, places, msg, delta) def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None): super().assertNotAlmostEqual(second, first, places, msg, delta) # silence deprec warnings about useless renames failUnless = OrigTestCase.assertTrue failIf = OrigTestCase.assertFalse failUnlessRaises = OrigTestCase.assertRaises assertEquals = assertEqual failUnlessEqual = assertEqual failIfEqual = assertNotEqual failUnlessAlmostEqual = assertAlmostEqual failIfAlmostEqual = assertNotAlmostEqual skip = unittest.skip skipUnless = unittest.skipUnless skipIf = unittest.skipIf def is_ci(): """Guesses if this is being run in (Travis, maybe other) CI. See https://docs.travis-ci.com/user/environment-variables """ return os.environ.get('CI', "").lower() == 'true' _DATA_DIR = os.path.join(util.get_module_dir(), "data") assert isinstance(_DATA_DIR, fsnative) _TEMP_DIR = None def get_data_path(filename): return os.path.join(_DATA_DIR, path2fsn(filename)) def _wrap_tempfile(func): def wrap(*args, **kwargs): if kwargs.get("dir") is None and _TEMP_DIR is not None: assert isinstance(_TEMP_DIR, fsnative) kwargs["dir"] = _TEMP_DIR return func(*args, **kwargs) return wrap NamedTemporaryFile = _wrap_tempfile(tempfile.NamedTemporaryFile) def mkdtemp(*args, **kwargs): path = _wrap_tempfile(tempfile.mkdtemp)(*args, **kwargs) assert isinstance(path, fsnative) return path def mkstemp(*args, **kwargs): fd, filename = _wrap_tempfile(tempfile.mkstemp)(*args, **kwargs) assert isinstance(filename, fsnative) return (fd, filename) def init_fake_app(): from quodlibet import app from quodlibet import browsers from quodlibet.player.nullbe import NullPlayer from quodlibet.library import SongFileLibrary from quodlibet.library.librarians import SongLibrarian from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions from quodlibet.util.cover import CoverManager browsers.init() app.name = "Quod Libet" app.id = "io.github.quodlibet.QuodLibet" app.player = NullPlayer() app.library = SongFileLibrary() app.library.librarian = SongLibrarian() app.cover_manager = CoverManager() app.window = QuodLibetWindow(app.library, app.player, headless=True) app.player_options = PlayerOptions(app.window) def destroy_fake_app(): from quodlibet import app app.window.destroy() app.library.destroy() app.library.librarian.destroy() app.player.destroy() app.window = app.library = app.player = app.name = app.id = None app.cover_manager = None def dbus_launch_user(): """Returns a dict with env vars, or an empty dict""" try: out = subprocess.check_output([ "dbus-daemon", "--session", "--fork", "--print-address=1", "--print-pid=1"]) except (subprocess.CalledProcessError, OSError): return {} else: out = out.decode("utf-8") addr, pid = out.splitlines() return {"DBUS_SESSION_BUS_PID": pid, "DBUS_SESSION_BUS_ADDRESS": addr} def dbus_kill_user(info): """Kills the dbus daemon used for testing""" if not info: return try: subprocess.check_call( ["kill", "-9", info["DBUS_SESSION_BUS_PID"]]) except (subprocess.CalledProcessError, OSError): pass _BUS_INFO = None _VDISPLAY = None def init_test_environ(): """This needs to be called before any test can be run. Before exiting the process call exit_test_environ() to clean up any resources created. """ global _TEMP_DIR, _BUS_INFO, _VDISPLAY # create a user dir in /tmp and set env vars _TEMP_DIR = tempfile.mkdtemp(prefix=fsnative(u"QL-TEST-")) # force the old cache dir so that GStreamer can re-use the GstRegistry # cache file os.environ["XDG_CACHE_HOME"] = xdg_get_cache_home() # GStreamer will update the cache if the environment has changed # (in Gst.init()). Since it takes 0.5s here and doesn't add much, # disable it. If the registry cache is missing it will be created # despite this setting. os.environ["GST_REGISTRY_UPDATE"] = fsnative(u"no") # In flatpak we might get a registry from a different/old flatpak build # when testing new versions etc. Better always update in that case. if util.is_flatpak(): del os.environ["GST_REGISTRY_UPDATE"] # set HOME and remove all XDG vars that default to it if not set home_dir = tempfile.mkdtemp(prefix=fsnative(u"HOME-"), dir=_TEMP_DIR) os.environ["HOME"] = home_dir # set to new default os.environ.pop("XDG_DATA_HOME", None) os.environ.pop("XDG_CONFIG_HOME", None) # don't use dconf os.environ["GSETTINGS_BACKEND"] = "memory" # don't use dconf os.environ["GSETTINGS_BACKEND"] = "memory" # Force the default theme so broken themes don't affect the tests os.environ["GTK_THEME"] = "Adwaita" if pyvirtualdisplay is not None: _VDISPLAY = pyvirtualdisplay.Display() _VDISPLAY.start() _BUS_INFO = None if os.name != "nt" and sys.platform != "darwin": _BUS_INFO = dbus_launch_user() os.environ.update(_BUS_INFO) quodlibet.init(no_translations=True, no_excepthook=True) quodlibet.app.name = "QL Tests" # try to make things the same in case a different locale is active. # LANG for gettext, setlocale for number formatting etc. # Note: setlocale has to be called after Gtk.init() try: if os.name != "nt": os.environ["LANG"] = locale.setlocale(locale.LC_ALL, "en_US.UTF-8") else: os.environ["LANG"] = "en_US.utf8" locale.setlocale(locale.LC_ALL, "english") except locale.Error: pass def exit_test_environ(): """Call after init_test_environ() and all tests are finished""" global _TEMP_DIR, _BUS_INFO, _VDISPLAY try: shutil.rmtree(_TEMP_DIR) except EnvironmentError: pass dbus_kill_user(_BUS_INFO) if _VDISPLAY is not None: _VDISPLAY.stop() _VDISPLAY = None # we have to do this on import so the tests work with other test runners # like py.test which don't know about out setup code and just import init_test_environ() atexit.register(exit_test_environ) def unit(run=[], suite=None, strict=False, exitfirst=False, network=True, quality=True): """Returns 0 if everything passed""" # make glib warnings fatal if strict: from gi.repository import GLib GLib.log_set_always_fatal( GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR | GLib.LogLevelFlags.LEVEL_WARNING) args = [] if is_ci(): args.extend(["-p", "no:cacheprovider"]) args.extend(["-p", "no:stepwise"]) if run: args.append("-k") args.append(" or ".join(run)) skip_markers = [] if not quality: skip_markers.append("quality") if not network: skip_markers.append("network") if skip_markers: args.append("-m") args.append(" and ".join(["not %s" % m for m in skip_markers])) if exitfirst: args.append("-x") if suite is None: args.append("tests") else: args.append(os.path.join("tests", suite)) return pytest.main(args=args) def run_gtk_loop(): """Exhausts the GTK main loop of any events""" # Import late as various version / init checks fail otherwise from gi.repository import Gtk while Gtk.events_pending(): Gtk.main_iteration() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656278102.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/conftest.py�������������������������������������������������������������������0000664�0001750�0001750�00000003104�14256146126�015553� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # 2022 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys import pytest from _pytest.config import Config from _pytest.reports import TestReport from quodlibet.util.logging import _logs LOG_JOINER = "\n\t" @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): """A pytest hook which takes over sys.excepthook and raises any uncaught exception (with PyGObject this happens often when we get called from C, like any signal handler, vfuncs tc) """ assert sys.excepthook is sys.__excepthook__ exceptions = [] def on_hook(type_, value, tback): exceptions.append((type_, value, tback)) sys.excepthook = on_hook try: yield finally: sys.excepthook = sys.__excepthook__ if exceptions: tp, value, tb = exceptions[0] raise tp(value).with_traceback(tb) @pytest.hookimpl(hookwrapper=True) def pytest_report_teststatus(report: TestReport, config: Config): """Spits out relevant logs only if a test fails.""" yield if report.failed: msg = (f"\nERROR: failed {report.nodeid}:{LOG_JOINER}" + LOG_JOINER.join(_logs.get_content())) print(msg) return report.outcome, ".", msg # Each test should clear the logs. This won't work well if parallelised _logs.clear() return None ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1692735242.0309358 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/�������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�014255� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/2822400-1ch-0s-silence.dsf�����������������������������������������������0000664�0001750�0001750�00000010134�14035600052�020202� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������DSD �������\��������������fmt 4���������������������+�������������������data ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/5644800-2ch-s01-silence.dsf����������������������������������������������0000664�0001750�0001750�00000334534�14035600052�020312� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������DSD �������\�������������fmt 4���������������������"V�����������������data �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/adif.aac�����������������������������������������������������������������0000664�0001750�0001750�00000010000�14035600052�015613� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADIF�>������! d! d! d! d! d��������������������������������������������������������������������������������������������������������������������������������������������������8! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������7��������������������������������������������������������������p! d������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/coverart.wv��������������������������������������������������������������0000664�0001750�0001750�00000110071�14035600052�016456� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������wvpk����z�����"V��1# !RIFF$ �WAVEfmt �����D�����data� �BWWGHC����������������������������e���� �2<g~J4���>ԡO�v_ Ih�t G3z|8Cp‡z1: Yp1ѳ00X8�E�f�?<�n�~PgC=�xG0� ��)\O8���NX3GY9S3SO8q`�'PAzh��3 }8Ss��< �f@ǀ�e ��D �>l���0z`88s�z!x i�O'�>�h�#8 ~o@�pwc ��0z-`�3 @O>O q@~VO=>'z4c�<>A |y�O#CH�G=9ҩ=#=HO~d�?7=`�!|�f�`�8tq�H @?:= `�N}�=�FcG�8`�HOp c=�x�< :t �p�c�e�zQx!:� �@z�F x�hF �ta�CO0�z1|6G=�c ���=Y~D0�C= >!:u0�/v�|ѣpG0:�0�a�84F8�<Dl0�|s�9��|0Sf@Ox�}.LTѳ~JϢs�?2�>ѩ|40�8�:!=��� �h � c@�C~PzF?3k9E?2GF342k90�3=jpOЃ~V< �4z1#�8!842C?S�s�<�N=� = I?*:0x�� ��':�  <kc�1�`�1���0� g8ҩ<�>9�>}C��|~c�FFxo 1�@|4t�~n�:`�|�q�:�>ԩcOl�?O�2�zփ��D?1SO�(�:(|2O5�0q�ԩ=z/#=h���~C3zc�? |s�?6ѧ@S 2~B�f�?z��� ��� s=s=!<�c��>�< 1��d�3G!�@3th38>f�$x�=1�!<|C�GtGz�Ip�@�>gz�38ty� Mx'z2�sOc��f �E40�< s>d�4zpi��1��c@�|�tq �<�0�38pd�d�< G0C0�£e�88C0gf��f�G2���?00�C=f �c���t I�>ѡ'> y�O03�~N3�H88C> Yc`��q�?4s�h�x�`�1}0O{@OCh@?g= @8S>�>'n� �>13DI/h�ǐ}:S �>=~d f_ �>7j`�f�3���.}1��Fc�O� T<�=>}:G}>�'x=!&g��~` �y � a@3�� �9j�|s��>A>`u =q�4x�?9�4�"z�<Ff`��CD `я=GS;K?00h`��}φp 3= `0��>O}C #�>42Ou�H?1����>ӏaz/ |2C�OH4z u�/1}8'T`�x8p/ "=8@�i��52�x9'�~B�>'C:0T??��~@4:>tC}>0>1Op Ⴡ�x�8�D3�h�D  ~ahCd�Cg}�r�d�@��f�Oz҃Fl`�40��F�pG#C}2��Y<c},h@2k�;0�_ it m�3f� `p@�}s�Ct�#�v�3O0:@O8�> Գ~Bx�8D |F>Wc�?�~`�0�|OpzӁ�1��?4�C�>1c@�N=< �|:1��3gz1h�:4O q@e�:��у\x@z³|c ��>h@4x}G p`�i�?`�O0:��>C}6pht3x�z ɀN�| 2CtYhG8L}EFODQ= �г5:� |2�LOtG0GxГF< 0Nѳ~H 8>h�h?Da�}:s�?<C31'}c� `}~l�@CO}pj48u qF0 d�?A4x� YpA8CxOt1���fG=a�z'4>i@t�c��f�O:<t�F4:0gl�x�>5�x`@q� i�/xA 3tԡѣ<гc�g}O �� �h��~b@��>ԡc`��d@Y y�c��q� ��F= y�?2c�:uSgAn�zgx9S��800��h`�8DL1C4z< �t�8l�?'�^:!1} =�}2'֡s� `` �ѩ��~@~j`�'z9z �@4�`�30��G}'x9`�8N=�`�88F�p pѳN}4e�O5PT�~n� �>G:�FgF `�x|2s@�>z�=00��>G2Gx`0|3CC:<c�f�?t Y#8c` ��3<s}8��|69s�O:(2'�~L�z:N= 3:~Tq�O2�< q�O8�v�3?Be�x�>i�#:~p` ��� i��4C >�>ֈԣ�Iˀ>1�� 'l�2CCx9StY I�D =' �N0�/ }�Cx5CAc��f �8`@0s�|�c �B�|310��xЃN��=t #= `z Q >gc�� '< @xGS"z�##4D3Qz'd�?3��f��>9�:0�`�#��ѣ!�80xԃNу |.>~b�'�|�!wvpkp����z�"V��"V��1+&ȋBWWGHC��������������������������� � <`,HcH�pC2їH?¡G�>�~`�C�g1��g}8t ��~f�?0�KA}23�1��� �xQ�40 p p @H?թc�=I 2`0z3= A 9�zA�~j� F�~f`��=ԩ`�I?15HP4<c=h:t }2�QG>Ќ�a�83xСG=k�4O <A0Wxx A24x��t�10�1�~l�x�h4TC=j,|��`p49��YPx}(te�L?CPO| �=/�|<=�@L>~D4xCL38o�> c=��~F=�xԏNF3|O`�|9�ـ|O i�3f�t@#84s�2gx~l�Ozԓ~npj�>Ca�'4x�ѩDd � A}0C<�Cz `0�@d�~d�Ha�p�2c�I >gs�?2 `p!) }G'z z9l��z`4?@>8O>c�?W:S:p }<�|3/D?$0��XOz>10�`��>x18|:C?h0l��N='cp�EO@`���>C� y���:~P`pux}g= `000�`��4�`�O�f|2O0zCa}0�pO��>4|$@?3�gz~j�dA?02C �4n_|00�1t xң|2O0c���p �S�|29Уp '1}69�c��~f�0Tj```��tA2/�c�@ = ��|60���=YX344��O}�~PF�Czi�O8p �0@ @�|`F4zgx=q�S30xֳpG`�8z<y`�:8p��c� 6ouj�<�<a``��>�0zM y��< �Ft��f�c��N= IY�< A?Otq �z8�>< ԓ �<':DO8#�h�2�1��O= A�~P"8p}61�>Hc���1O@?Oj1���d�zf�_I�!c��f@?s�0g4 zֳ A4`�?3x胁��4�>O�8u gX?5�< sh(8e��>�t|C�F >x}2|4�<�:0l�Ɂ�c��O>�e�/c `��u A:|<�zOz��4g2�<�!�f`4�^D?p 'Ɛ��>G`�\\�x�}4GCCOg}!zC�pI裁�Ozҡ=POH��|4 a�10d��v�60p�xO�0� .= 9 a�1��?9! q�|<�|2?j�uS}0s�'=|x҃>�)"L0!}s�#p |*x!8p `g= >g|��}0G9Oq�:6[?1YFc���@�Fpc}8�`t�>�|>0�0|4S> Q4zg:t �|$z��>z>0~B�C�|91|:g�C?s�?'w@?D>h1��^�N=u�za�~j�?4��<A>�=<a�;9!��p> g5|�?S}zЩ�FO| = l�`�xgp�i3z#>1'=Q8uti@H:h�A>| A}8cf�h<�=gp�x�>d@>Џ'�F}0SA3CO2����>ҩ/p<XϢ{ �>~b�O``@0�2�3=CCx�p΁1 �y`�g<чC�#2�}h00�zS= p i� QOc��i���Cz}> �Pp�'}CNC<`��s�j!=}s�30� @�N= g��p��>ѩC�>= f�'u1�� }�@>Ӄ>աCҳ |1oDOti� �8�Ρ@=k~H1��;`�>�0h�<СԳό�Ztcя Q?8  `:t �Lg`�O gd�t �<3}Ct� Џ90�g<i�SG=A?;c�#8e@d��f�xҏ��|2j4d`�1�'!|4�Cg`�=�~u ��i �90� @?-Y}<ti�p�t�-}>Dc`��4i�_C=kD;'�[C0` �'h�?+d� 32�F�>z�z��u“>Oc��f� c��f`��O ||:?Jk~b�N=�~`� S̀f``�� h�x:uACb�^ H1��;ߐp~b� `�>'T?!p� i�1OA�1��c���gC\\x80G�4�~@?;G}?k�=q �� Qd `4)�N}�=�@�F:p 0c��fd�1�:#�~m�z0�1��zGt�x�@ �p�f���pc� �\O>�|z9�`` �s�s�y`�x�G==G8�= h�~`��8�>l�= � �g�<< =Y?1g1�� �P#`�|��0�3x1OtI?4x }4 >�<~j�#O5x�0�`�x >�@�>�~L <AB>Y��~x�0/�G}"|6p <�>чx�1C!8d��F8e���� �||g}1K3:02c �!|:�C�><`@ϢDQ�8�ue� Y3�l�0�z�zЌ1���p�c�90zСOX]Hz�>O� @~v�Oѩ�C3s�>ч8 <kDOQ= `wvpk<����z�D��"V��1~LBWWGHC�������������R��������������D gz `"�|HNG|80hd�~b���|_d�>�h�^c4p�O �0g=p_Dz8p�q};�<jd�8<s�O|Ot`~~3�ht#}2'= |�`}c@�4�:p<f�3��>1>9E?A �N=5<AFDO�h�� ��i� <i`�1<ԏG0d �гG0xXрe�v` ��f�!�> 15:5�P��G��f�`t p|:өg�p >'X!}>ѯ `@�~N� `�P :է�Nc��~h�S0�|6c�ǀz֩x�4t�Oc��f�3$c�3�uI/h�?7>�u2�48g=' Z��|рh$@�>�~L G�F`t < |6҇l� g:0�:E809G=T?08e�Q:p'0@N0z�cg=kt@@_e�Fԏa�3'>x `0!g> q@}  Q>�>'t��~x�f�?c�OH�>AL)�!<>я D4:3L h q� `:�==A>Oi�>=ԃq�:[ 9c��> z�Oi� !|0�>Ӏ����t y�hta�3�FO8�N}ko�>�^:у>�=g@ԩCGxg=Y�FP?> < � ��Ā �?3�|C?0:��Ȁ�N�� ��7�0@z�~d�?<?@�48tԧ2C�^0s�|1<q``�� �pD?c�h0Gx��p�~TO:5u�?CcD3')zd� YO'pA?C�> < QS3�2���Os30`�!<i�38�f `��ѡ4HO:00:@3s� I �pzԏ< �pq�3G= 'gh��Ij�@�|0:u!�20�F>:Gd� @|<�z a`�G|d@:0� `Dof�ty��!�~NFpI��f�OxPO8p�l�3s@�tQd�O>�uczg:u '' I S>�d�x�p�f��0 | �Ft#�00 ��>�<i�3g= Y>9}|ѩG=Г>}>c��>O�d�8s�Գ>< >'zO!@:`�_�8G=j2��c�'=q�`�>'D �8��f�Q#c`��2�zGz0>O#}��1OxЏD4�GGh>g:54�O�~f��|0s�ta � �F�|10�Y?GC�p`g\0}":E?1'�Og0�':�C8�>�f�2>|8ty�>!}9!zO 3= �>ԏ }6�0zև@�~``� g�ԩ'�> | � �|O A3�i� �sQ:�>ѳ>)<��f��>ӳ��~ǸI Az!�d� �htg! @Xz�N��<\3e�OC>փv�C�}'c�~D ��0s�?3zԳFi�O� x9|>�(L3`�O0�< 8'= FO5:<0 УFϢ'`` ��f��~LOc�� 0>ч2O�^z14��b� >9xг>y�t1t<GD3:4`�v�_ Ȁ>փ>ψ ~@ g�Gh4Cd�\= Y '!�0@i<O42SO8,C|6<G=Yzpq�F:~B3 H~@� �>184z�>p �8�f`�4OpG,8��<}&:#x�v�!�N>zԈ|'�>�}GxС@�FOCt <A} tOz>AO:|S?s��h 7B#Pi�O2�c`��<S>� |8x�x8#f�p ԣ~B?60P4d�O Q 1��` �S�f��~Z}<>'z�F�IO40�`'d�h�:tq�?Lq�N�>IHGXO230�|<`�x9Ol�#80��A3&>�@�N1'='Ti�3�q� �;}0�:u 'x�=y���~Ry�xg0�g`�|�3Of��@+BOz �I:�>�>�``�g� Ѓ5CC�4zuh<0�i�?�4c�� �3� z1pjD'}6|у`�:5|�3g=q��~d@�h�C?|�|Sh���< �8�~k�oVf�az1�����p ��< `Op `9��e@i �#D��|>|;s� SN>�N=|C4s�?2k �,0�>�4� 2c�>gxx }1<�Ya t�c!Fc��0�I'}o�1��O2�`#:�~J}!A3�g=�D3| P?3G>�p A30��s�Q�N}Sl �>F2CQp s=I�>':t `d`�<C}0<'xGO c�C�1��T< ^2� �[�4X?0S?:g�Сǁ�z �Oh�}6  `�f�O EC`�ǀ~b � C}$<y�>1�' Gx|$:0�:$zz¡1�>�'zЃN}<�<y`�Gc�ppOp`k`�8' �pi� ��<�x H�8G)�'`�P>80z҃>~1'=1џ"tq�g:�?by��~n�2gwvpkN����z�f�"V��1H\7BWWGHC�������������������������� ��=Y`�>1C Qt`SzN O 5z0�G}4�c��X�24s� `��= y� ԟ5x8584c��}2d�?| i�?Ї85:``���~�_ht q�Y�0�ЏOI�O#9`�<y` ��~z�6S8G2$z�} 1��zС02C|�zty|7���ܢ0Y�>Oi�4TĀtg4ѓ~{�|�HOC8>��>G$H?2t IOz�N!z�>ң> zЩ4t�Gsx�F©'!<`@`�C�0�>С|:�F 'z Г `D?6{9s�t`�Ot��>ֳ�>C� ��:`@LOPpЩ�<s` `��x�4|=` Fi4� @8Txgx��z1��`�гEGd`��>�20�IСS~z�c��2op=y~Dl�C! �SO<i<c`�>1Ot9φ@:8 Ih �8Ei4Ou=,:#`�_ zG�}>sh�}CϚ|҃~l �����=q�:t<i3c �X#xa4@#�>ӣf��=g>��>A`�?20�q�L2C#8c:u �8q�x�Qz�NЃ>0��s�3ǁ� }��>�p� }c �>F::_��z�p �O�~Vi�!z>#�~K:��< oWPN7pjh8�>�>ϊ>GL s�9` �C?00�C:!�)g=��@85t�q��}S2'T3���Nz>҃f �7d@?::c}:>O�>!x't `zЩ10�` ����>׃>׃>�N= Q?0�=A�|0Q�AOz�@0xq�4~Jf�?3S<i@O21ѣ�³>g:t ~D|_d�� �t |�?3C�>ko�<G}!)0�:41�`��XD3��>S}O@<i�q�p��p9gz�`@���<Q<A=A�?9c��~@�|0O�>�~D88�!<Y0c�8d�@Ozip `0}$c ���>�`�i�0�� �L�t zҏ�`�d�?C 48s�j�;S�<� ��CC8810t�Oz4z@�4c�?5= �|2pQ�~l� `�p�?3O�2p Ч8u�}0ѣGb&�N90�|3�<k00i�i�Y_ ' �ph4:0d8Oe�гѧxc��}2gx0kz >ƀ�< ��4c ���`�;'':pt�V�ң@0�A Сhtj�< 9O�<�f��>ѓ~T:c���x'l�>�f� �xO >G:t�>ҏ Á!@#Tc ���3>'�'8>�4Dg�^ч}Oe�<y�?0s�� ҃>9s�  Q3 1xҏ'tS}2s�3OC1�� DS<a@�>p�3#t�>�01SA41��?�|8O�|( 8`�8tA A:4z'z �@;/@d`�O`'=Ok0�IO< ht y�~t�?2'c� E?:>Ǣ(CŐF�0Pa�f�}ѩ Ї:8O8`0t�c�4C �NN='0c@�>= at<~e�;�:sz `�d��>Щg>�p�C0z!8tԳN>�x�0|'|s�Oz@�^s�=5!<I?1_:�0�3}0D3'p�� �N}�cl�?0t�c�a� >gh�F>1)z�<A O �>)8D�uFz9s�?10\tj4O5��=Yc �z�/4D~t�|4=i�~`�3 =�~h@p�3f� f�C>ѧ8841xG:�FzgzOp y�~l�?$D?0ѡgl�F3?o�X�phd�1OpQq�~J�uy�D88d@|>� ``x'~ROh� 0O<�`cH `DC}0zp]3�|;2�A?3�HN=>�=I:0zև�~`�a`�O�p 'd�Џ C>1�@4��u�8����� `0�zӀ#:S>z'}68 <A�pf�C?0O8 )8D<�O<C?zҩ u'�>OГ '`�z=[a:�f�ƀ�< i��|GC�'�t QO< >0c��p}Gz9|01�h�OLMm�s�ԣ~L a�s�<j q��~l�>=GP?@OT0Ou0�20�|4Щs� x|`4zh�F1>'8d�z }�~l�> c}$z9�f�#z78D?C8pas@�52CO:��0x�>ׇz1c �g!:s�"x �0�|G}C�>өc�??aO`@G4 �4s� `0#�^0~n�Ј02C�!h���py�O<a:�#=cN=Y |���}2 88!8E�D aH�>ѓ~b  9���<<Q3|00��k��<Ix�C8�>'``�1� 7P�== Ѓ~@��>�F?0��~z�#}6��|20 �'~D?%1��?2?BO>ө�~B30�<`pSc��~`�0@=s�3G==�>2)<'@>>9©�0x|O |s�8 У~b�a�?0~d�G �ѳ>:�f�?3�N> �wvpkx����z�X�"V��1uBWWGHC�������������������������� �f�c�f��<C~Rd�@@OC8`@8 }ӏ1OφN I��0=�u hszhtOgd�z�N�N= � `�?5uh@s�?30� a�zЃp �0�A|G}(x�u:pc>O#@h��0<У5t�Oxo '�_<<hGg|<��}:��i�?6<a�4}ѡ5z�>c��08cz �`�G} w>|:2W}׃!||>�`���>� �S|C I?"<Сg}xb� G~Fd�d�?G��<GDF�>'0��a�l@�>4H3|:z9g < q@?6'=Iz�F?7S85x� С0<m�G2�a>�s`�g=0�t |2S?2G}O0G}8g1OpI39À^8E� p>֣Ft =i�s=}6e �=�0zc AzѧCx�F~@thFz1+)>Gc�чTOx��|'= Ij�0�� �<x�>O G4}6c�|8ч| 0��~b�d�!�@<�c��NL?08:u `>ѳ0z�0� �Oz�}0�3�> '= GxСSa>gx�8u� �Op� G�>z|3= A?5�|2Og��L}7/�>�p:p�<Q�>DO1��`��}8�Щc��> �Q�F8�PxӀ> 1��?3�|O5000��:_z҃~h`�O1}O���>�`�t G}�>� �?C�O!= �48`�}` ��|0S#=< 8�Щ<Y8#t@0�a= �<0�SzG8��y`�1[x:5x�CxЃ����000�� �= `<c��pGpi�G}:c�3�1��,POc�':8�d��Ftj��pI~w��t \��|4g`� v�?8>~f� 1��LCl�t'5D��O2=s}3u�x 1��3я 9Sz3� =Y |0 ч<j�c��'��@:p3}gc� `4zD2c�q�O:�>ѡc�# q@< I>�>��u�~b��x}6G�u1��Ta�210��:�^�>�=@= �x� `�xGx�e� �30xe�/8cH��f�# A0��N}�|O��<e�> #ѡС'ѳ>=!�8O�'=Àt|'}pGG y��>0SЇC}2s�;_}8<'d `�SOnph0� `@D8�>O����>5�:>9ѓ�><A }C>9p�CP8sT�><80zֳ�F3}>c�> 8Gzj?`1��h���#8>�0:e�i��>��z�>?Wk(=3:pjpi��>= �d�s=�~TX �~F?pjt��� �>`�9ғGs@ �4x���Fl�pA:d�= I0�D?5c��C `d��0 n��FoE `|>�h>=i�'�DOp }6G0�<|84=I~d:C:4|GA}4?@Si�>я >1S3O4Cx 38� �<a�|2CGt�>O'~l�s�� ���|g=�A?1|00 Q�N�t СSO<y�8D��<0�h3XzÁ!��>h4= q@841��4c��ѡg=>Џ��|8d`�“>֡C!��0�e�9O5z�F>9C� �xy��g}8c�ԡs� @3uq@:�p> i�EA!zOYtG�7':4�|�� @5X?�@0Y�4{ �tYxg@�|-:GhFp 0:�|G� z3}03}2уF:�~d`��>!:d�Fpt�p3�4�У12}2?`�3�<GE�f��>�^5|20��D>!|0gt u�:� �4��>�C:4g}8�:G�>t10��x45ߝo q�-!|0�}4}2N Y� �s�=@�|=C~``�:u I 'C1��3S@z1��30�'pj�>�>5Q?1�@e�?0Of@300��4�<c:!|1[}�oȀ~F8t D?1u0t�}|8C4O 'Sc`��1��!|}}<z~` �z�`�?>ҟ5Ѓ8� `(2�h0�~f�>Gx d�c�G8S1��3g}2t�NHo�6w=��gL�~f�N=|:C�Cy�DCS`�8ui�3c ��8f�|ѧ@ FOx�>�= �00�9s 9<0�<�xԣxԃ#z�у4�~F?0s�� `� |6pq��CxԳ a��p�  `3H���|0��>ӌ` ��S�<':<��F>i@q���v?5ѧ<y ��0�<pA q�c� a�?� !pi �h��~j�?<�zЇd� ֣>�>g8��~f�<e� ҡOp2�`�Gя L2s`�Gf�_ �x ``��>�>ֳO1�ht `>!q��0ggO��d�Ϻ2?`��}6�x�=�= h��8�~w�_ O1OtG='G=F'`�@DC?;' �xС9sx�5|'ujp�0� ��O|�F? �0')}t|CF�'�1��g!|?LO|1Op}<0�i@FE?0?FwvpkJ����z��"V��1yBWWGHC�������������������������� �}Oe�<y�?0s�� ҃>9s�  Q3 1xҏ'tS}2s�3OC1�� DS<a@�>p�3#t�>�01SA41��?�|8O�|( 8`�8tA A:4z'z �@;/@d`�O`'=Ok0�IO< ht y�~t�?2'c� E?:>Ǣ(CŐF�0Pa�f�}ѩ Ї:8O8`0t�c�4C �NN='0c@�>= at<~e�;�:sz `�d��>Щg>�p�C0z!8tԳN>�x�0|'|s�Oz@�^s�=5!<I?1_:�0�3}0D3'p�� �N}�cl�?0t�c�a� >gh�F>1)z�<A O �>)8D�uFz9s�?10\tj4O5��=Yc �z�/4D~t�|4=i�~`�3 =�~h@p�3f� f�C>ѧ8841xG:�FzgzOp y�~l�?$D?0ѡgl�F3?o�X�phd�1OpQq�~J�uy�D88d@|>� ``x'~ROh� 0O<�`cH `DC}0zp]3�|;2�A?3�HN=>�=I:0zև�~`�a`�O�p 'd�Џ C>1�@4��u�8����� `0�zӀ#:S>z'}68 <A�pf�C?0O8 )8D<�O<C?zҩ u'�>OГ '`�z=[a:�f�ƀ�< i��|GC�'�t QO< >0c��p}Gz9|01�h�OLMm�s�ԣ~L a�s�<j q��~l�>=GP?@OT0Ou0�20�|4Щs� x|`4zh�F1>'8d�z }�~l�> c}$z9�f�#z78D?C8pas@�52CO:��0x�>ׇz1c �g!:s�"x �0�|G}C�>өc�??aO`@G4 �4s� `0#�^0~n�Ј02C�!h���py�O<a:�#=cN=Y |���}2 88!8E�D aH�>ѓ~b  9���<<Q3|00��k��<Ix�C8�>'``�1� 7P�== Ѓ~@��>�F?0��~z�#}6��|20 �'~D?%1��?2?BO>ө�~B30�<`pSc��~`�0@=s�3G==�>2)<'@>>9©�0x|O |s�8 У~b�a�?0~d�G �ѳ>:�f�?3�N> �f�c�f��<C~Rd�@@OC8`@8 }ӏ1OφN I��0=�u hszhtOgd�z�N�N= � `�?5uh@s�?30� a�zЃp �0�A|G}(x�u:pc>O#@h��0<У5t�Oxo '�_<<hGg|<��}:��i�?6<a�4}ѡ5z�>c��08cz �`�G} w>|:2W}׃!||>�`���>� �S|C I?"<Сg}xb� G~Fd�d�?G��<GDF�>'0��a�l@�>4H3|:z9g < q@?6'=Iz�F?7S85x� С0<m�G2�a>�s`�g=0�t |2S?2G}O0G}8g1OpI39À^8E� p>֣Ft =i�s=}6e �=�0zc AzѧCx�F~@thFz1+)>Gc�чTOx��|'= Ij�0�� �<x�>O G4}6c�|8ч| 0��~b�d�!�@<�c��NL?08:u `>ѳ0z�0� �Oz�}0�3�> '= GxСSa>gx�8u� �Op� G�>z|3= A?5�|2Og��L}7/�>�p:p�<Q�>DO1��`��}8�Щc��> �Q�F8�PxӀ> 1��?3�|O5000��:_z҃~h`�O1}O���>�`�t G}�>� �?C�O!= �48`�}` ��|0S#=< 8�Щ<Y8#t@0�a= �<0�SzG8��y`�1[x:5x�CxЃ����000�� �= `<c��pGpi�G}:c�3�1��,POc�':8�d��Ftj��pI~w��t \��|4g`� v�?8>~f� 1��LCl�t'5D��O2=s}3u�x 1��3я 9Sz3� =Y |0 ч<j�c��'��@:p3}gc� `4zD2c�q�O:�>ѡc�# q@< I>�>��u�~b��x}6G�u1��Ta�210��:�^�>�=@= �x� `�xGx�e� �30xe�/8cH��f�# A0��N}�|O��<e�> #ѡС'ѳ>=!�8O�'=Àt|'}pGG y��>0SЇC}2s�;_}8<'d `�SOnph0� `@D8�>O����>5�:>9ѓ�><A }C>9p�CP8sT�><80zֳ�F3}>c�> 8Gzj?`1��h���#8>�0:e�i��>��z�>?Wk(=3:pjpi��>wvpk ����z��:��1BWWGHC������ ��������������������-�D>\2�>G4O00�yh��}?/4:8O,c��pGt$n��'g0��<0��?=�xУ�~`@Ox= >O �G=G}>= `{:<C�c���nf�'4�}~b@:zI=o�>@�!@ Q� �l�#�~Fx}G:'=y�N= y�Q�~P =G}:O#<y�p 0G�}0�s�xG`� �>a�p=hpI0=9�G:�n}0'}:c�YtxO i� xԡc�S��0 |'}(8t�~p�z�900��< ��>փ0p`�~D@4�f�Cx}�< <i ��= c��0�`tYϢ#20�a��uЩs?=1� �x8tS<C?}6ѡt`�4z10�Y':ugC cx|4�4z�sgzЧ:tSz|0/hN= ࣁ�>94�>Сg�>A?6�`� `�xGc��f� 8:z�41�_},<0|\L΁�Q3s�L i�d�L `『|0�8|u1:�L8< �pq�G=gp `d� A  ~`�OQ9�O>Wf� �8��>1`l� Yx��=�8e�?4N= Y��` ��7 +}gw'85D4z�~K�f��D gE |Ssx9�@0�_С�NCxg ~z � гd � � }:O8OGit�xO >ЩG | � �XN=q_ �~AA3�`2�O C>D'd�< `:0 =�0�` `���lAAy��ƀ �>gg a�'=� < �8�F?C3�4'�Q��f � Y 3:@?S�>�~p ]O2s��:�>�Sh�57�v�oz>�NCx �0c��},a�k>'�48CO8����8up3= �0s�c��G�@� 1s�? p��>'x� a�?z,x12|'=480̀>1���q �|04c�����|c�O:=Gf�0�|2џsGz9|5O `Df�z�� �!xGx�x|:'=@zG=a �1��v��>wOd�?6�|0}8'p�Oz@8t:d� �>Q#1b� ��W�5�4O4/p�~F�Fp�84}2O`Hx2�Yـ<1��> 5w=k@ �c@�@c��~`@1�`��|0Wt 8�F:v�k�Q��I4:5�thp'p��d�3g~|�I?g\1� @��<}6c�i�3h�< ~J#:e�G|c@1�` ��~tӓ~a�_ D �xGѳ~`�x >ѧ2��<9s�~iA 9�VO�<G:>9!�ѩ�0s�|8 `}:c �x� �Gp��>'`��>^ CxGC0�: Cx `== `�| 20�'0xғt 5zg𤧁@�p4:<S?:1�@@Ϣ AcGz!\؁�bHk�o|0l�3Sǀ> wCxҧx|:1�z�~`�~Nzx1 l� c0:�D2�9= `0C}2s� Գ~V �8u�N= �:pYF a`� <��>ӓ�>Gx9' �~bp�/x9p�t �/ kc��>G}8?j�s�>x�O1}6}:10O�~H|4CS�= �f��Otp S�f�s�:DG=9gz}.:5z'zi`� 1�}=g}S?:�>4Pti�?0hpCd�?4}8OF3@3G!LH<#`�=3=c8<�D?6}3}6S7|c�C842O'8O8 T?Gwvpk ����z�?�:��1R/VBWWGHC��� ���� ��������������������;�`�:<Sz�n}2S�>O�P0C0<qx֓F?|4� @HOzx�0x1|S0ѡ̀>g= 8�~L`Ox�~D`��}SuA g=C�~b�?000�'dh�G82��G�~H� � �:e�xc ���h� �h0z�=i@��x ЩS�=wxՓ>�{�ǁ�8D3�'zgz�ui`�xgQ= `:я�f�tIp|0g=`�3�c@�4GN��S�>ѣ!Փf`�:�@ 1�8D>#=�>�̀|4'}&6�9OtQ?0�9�5Sp `8c�?6Su|(x'}чz:sx���>9O�<�>O �0=k4`�Op~P 2�w>�q�?6 `>=� �3 ҡ809}c�'ch��< y�C= 1�x9G<ich ��>֣>סui�1П0'}0OHxa�x9v�/x�~H?7O hDOСc�4��`�O8<�0gh��FFDO@OX�>Џ�l�>gxzSd�OO0$`�I?1�ap~a�x�u `�>�5c��|<�!|� }00�c�|G�tp�A?s�f�a��f�`�?=>�`��>p i`�“~@?�'X � �?!�08�Щ1��?0��ge 9td� s h�?I �@xO G|�<�>'X�>9P `pQ?10P?2��f �Y�3 �R~P ``�L3Ct 1�@3��~T?)2� !0 >GuDzgCD hc�d�`�L:4x9=j4:t'32=a�f�d�x|0:49�0�c=A8u``�� zOjt s�>ң>< ad�X8F@xԧ}4c``��x��tQ}:< 7h�z/ U��4xУ 3�>>�f @�f�t G4�0�>C=f�胁1��1= `p�0�z֣>�D�>‡x>ӏA>�>�p|0�h��f�A`�ЩC�>ӡ�pг> <|1#XD?#2�}2ѣFc��#S Gd��~|�_p0g}6?n�Sx }�>�N=  a�8g=a�©}<pЇzG �6ot#G0@�~P i�d`@90�гc ��>>ҧCx> xG8 a@/c�~JC8sDQ#:4h�uA>2�`�= 1=`!<i�C?O:4@=jN\B1� яC}<���>֓O5| �s��g <y�Џ#>1S �>C�>�f�?1G}2O�| x1��N}ԇi:�@Y= �'= >�ƒf� pp<Щ~X 3}<:t�'}8p#f�c=�> �A�>'zЏ c�C��|̀`� �8t 8e��s� S}�|0c�>�1c� hpa�s�n�oI}<p i@ gp��>է��zЯ =A?40�'>'DO|`�� �0�:@z֣> ��Fa�ԡ�`�x�0�̀>G0�a��>©�Fz �}:�f�z�N=c`��<0�@ [|<!<A�f�Oc��~`�Oz�O�xGx1c�O884ѣ>1~~��Sxz}1�xЏz�^�|2Oe�#:5d�~f�O8k;s�O:��`��> �0x ��FOb;ԃ�D At A?3�g}!|6�:t Џ}c��'x҇:��<ip�ЏGp)= `f��,x�>hC�5``�1�c��|G8>O 1�O\0=�}G18'`�18�C i� f�:d�?1s�< >~APETAGEX��;�� ���������������������Date�2004�������Track�02/10�������Title�Silence�������Genre�Silence �������Artist�piman�jzig�������Album�Quod Libet Test Data�������Replaygain_Album_Gain�+9.27 dB�������Replaygain_Track_Gain�+9.27 dB�������Replaygain_Track_Peak�0.229712820826�������Replaygain_Album_Peak�0.229712820826�����Cover Art (Back)�hello.jpg��JFIF��`�`���C�     �C   ������������������������������������ ���!(9B��������������@> ,r�)� ���������!1A�2Q"$3Rab�?ljRCIG4剡dhVdK쯦woDv8qhĸcBem}?� H$)B,@�%������������1A"2a�?*OTbPm>c% y}7�'����������!�1A"%23Bq��?jWH+)<P`D*m~|jYqU=Ezs&%BvA:\_tL�����������!�1AQa��?!.!|L@m� myrFpW^mk� �����_������������!�1�?RdC7AMZkԠE:S+%{`SC$ �o_�����������!1�AQa�?'y={M mWU Qvh2TfFŦ(������������1!A��?I>*@0m`$u<r!Oo�����Cover Art (Front)�hello.jpg��JFIF��`�`���C�    $.' ",#(7),01444'9=82<.342�C  2!!22222222222222222222222222222222222222222222222222���"������������ ����}�!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�������� ���w�!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz� ��?�+k3jFgh%$ݫq&n6j3Gq!Ͻq7>)5we;Yʇ.N;`NsZMtkQ=3MKn턀? lێ@APETAGEX��;�� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/empty.aac����������������������������������������������������������������0000664�0001750�0001750�00000005021�14035600052�016055� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������P?��libfaac 1.28��B� 2�GP!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#P!�I�#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/empty.flac���������������������������������������������������������������0000664�0001750�0001750�00000143330�14035600052�016244� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fLaC���"���y�+ B�zbܷH2ĺJ�,������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Y�k?O?s???????9>?3y?̟>?O????ϟy??ϟ??'<3??O>I??Ny||??�C3'?????????????g|????s?|g?yg????|ϟ???'?'????9????sϟ>?'Oy?4uYl??93??>?ϟ?y3???O?y?????9?93???<<3O???<9ϓ???9?~O??g?~?ϞNO'�Cɟϓsϟ9?g'??|?ϙ?'?3|?'?????<????d????g???ϟ???>yϟ?g?9?<??~?9?I???ϟ?|??Ye?3??>|?gg??>|~s<?3s???''<~???O<??~Og????~yy?????g??O?9??g?ϙ?y???>y?|?�Cs|??N̟?3g???>sg?L??3O?3y???>3ϟ?'33?~||g???O?|g<??6Yb???s~y<??O?ϟ?ϟ?g?????ϟ ?s?s??<?g???|g$3?f?真?�Cy~Iϟ?'?'O<<?'&?O3>g~gg?ϟ?g>sϓ9?L><??g??<~?<?'3??g?XYw??gϟ?|?s??y??2g<s??|>g???????ɟ??s<g?<'?s|y>>|<??3g??ygys?s~~?????$s???y?g<???O3?y??3'??ϟ9?????9?O4Yp9???3s<'?????~<'?yy????g??ϟ????9?O?ɟ??>?9???3?? ?s|???93???????<O?fss??>?~g??'g???~g???3g?3??ϟ??s Yy???s?9ϟϟ9<?|???9??|>~Ϝ?yg?3???f3>??''???|?'????$??'>'?'9??9?9|y'|??|@O?<|??>3s??&~3???????<~r'??s~???'???s3ϟ??ϙ?9?|'?N<??Y~???O??'<?????O???9?????|''~?y???3>????s?????9??93<?|??ϒ?9?@?????3OI????O???&s????ϟy~'?<???<?O?~??<???<?|<3????gYS3y9?'?93??>?ϟ?y3???O?y????????<<3O???<9ϓ???9?~O??�Cg?<3'?9gy?s?~'?y??9y>?>O???3?9?y|'s?<9O?Ϟ|9?~?g?3???zY T?y??<>yIg9<3??>|?gg??>|~s<?3s???''<~?dϟy3?~Og????~yy?????g??O?9??g???~?3????|??'???O???>?'???f??'O>?>s3<?L??3O???s???ɟ???y<????y?9g??s<=Y ]&gO??|ys??g9?>~gO?~???<?<???y?ϟ?????3????9&9I93?g9>?|g<??y~Iϟ?'?'O<<?'&?O3>g~gg??ϟ?>sϓ9?L><??g??<~?<?'&Y Z???y??r??gϟ?|?s??y??2g<s????y??~?'??????ɟ??s<g?<'$9'?󟟟'|???>~?9~y?yO?g?'O<s's????O̓?$??9~?>???|||9??=Y O33y?99ϟy???3s<'?????~<'s???????g??ϟ????9?O?ɟ??>?9??'??'?y??y??9??39gsϟ'??|?ssO<3'??3???yϟd~?yϟ??3???~??O@1Y H?'?????>Ny?<N??~?Oys3?3ϟg???>s?>9?ssy|~???9?s'???~O9????'??|ϟ?|?II?D<<O?<|??>3s??&~3???9??<~r'??s~???'???s3ϟ??ϙ?9*YA???|'???3?sO?s???????9>??s????9<'??$?????ϟy??ϟ??'<3@?????~?|9>s~?9ϟϟs??????3?g?'?????9?????g>s|~|???~sO3kYF?g9?<???~g?<?'y??g?s>|y?>3?'g?OO??3??ϓs?>g?y???'??|<3????gyϟ?|'Oɟϓsϟ9?g'??|?ϙ?'?3|?'???ϟsO'gL?Oy????ϟ???>yϟ?g?9?<??~˛Y???>O??|y??<>yIg9<3??>|?gg??>|~s<?3s??ϟ?'??????dϟy3?~Og????~yy?????g??O?~?g?3??????s|??N̟?3g?'O>?>s3<9?s~??$3y???>3ϟ?'3Y'y3?~<gO??|ys??g9?>~gO?~???<?<??g?????ϟ?????3????9&9@|g9<'?3g???O?3O???'>?<?~?O??ϟgy9??>|?3ϓ?9??>L??93?<?ssY?$3?f?真?O<?y9ss<?<?????̙|?<??d?<????O?<?gOg~?>???'??s?�C~?<?'3??g?ϟN???????f????g?????$s???y?~?93>y?ϟ????$?<??y??Y'?s|y>??9?f~?????'~????'|?'3yy>??ϟ??><?3<'y<~>g?>3|>|?????|???|?fg???|?ssO<?y?g???ϟ|9?OOs??<?Y??ɟ??>?9???3????s?9ϟϟ9<?|???9??|>~?|ϟϟ~'?3??g?<~O???|?'????$??'???<<O?<|??>332g>????9??<~r'??s~???'???sY�?|?II???|'???3?sO?s???????'O??>?s????9<'??$?????ϟy?93ϟ??ϙ?9?|'?N<???????3OI????O???3?g?'|?yO9ϟy~'?<???<?O?~??<?VHY ?????9??93<?|??ϒ?9??瓞|3|?3'??3~ϟϟ?y3???O?y?????9?93???O?~>O?D|~|???~sO3?33O9>?s?9???r??s~rs?rs??'|?'?????<????d????g<>|?Y?9?~|<?g??3?<???'Oϟ????'??ϟL??|???|??~g>|?>s$??????3>I????s~~~~s?|9?~?g?3??????s|???>?'???f??'O>?>s3<9?s~??$3y???>i Y#'~yy?????g??O?9??g?ϙ?y???>y?|?9O|?????????>?'?<>?~?ϟ????'??O@3ϟ?'33?~||g???O?|g<??y~Iϟ?'?'O??3?y?|rg?|?ϟ?>sϓ9?L|Y$33??ɟy??????y??r??gϟ?|?s~s?9?>~y&>|?O??~|?y??~?'??????ɟ??<?ss|?O|9'?󟟟'|???>~?9~y?yO?g??~???O?<??s's????O̓?$??9~?>NY-?s<g?<'?s|y>??9?f~??y332?'????'|?'3yy>?y??3'??ϟ9?????9?ϟ???ϟ?'?ϟ?<O?393???????<O?fss???gs'???>pY*???ϟ?rg&|??Or<?Ϟ?39?g>>??Oys3?3ϟg???>s?>9?ssyOϟ|?????|ϟ??>O9?s?|??O????9??~<?3?????????9???̙ϟ<y~|???>O39???gg3Y?9???ϟ????39???9?????<?9???????9>?3y?̟>?Oϟs???'???s3ϟ??ϙ?9?|'?N<???????3Oϟs??????3?g?'|?yO9ϟy~'?<???<?O?:xY8???>????3?>s9O̜??'?3~gO?y9?'?9??3~ϟ???O?s?g?sLy?????<|@y?'??9??y?y9?????39??<g?<3'?9gy?sg'??>gO?3??9?y|'s?<9SY1??~>O?9?~|<?g??3?<???'Oϟ????'??9ϟ??ϟ|??~g>|?>s$??????3>I??�C>?9ɟϟ??y?yϟ'??>?~?3????|0|??N̟?3g???>sg?L??3O???s???Y6'??s??|ϟ<gy??|ys??ϟ?????~?????ɟ???y<????y?9g??s?ɜy|??'s??~Iϟ?'?'O<<?'&?O3>g~gg?ϟ?g3??>OY ?Oy????d3??ɟy??????y??r??gϟ????|3?~s?9?>~y&>|?O??~|?y??~?'???@?9??>L??93?<?ss|?O|9'?󟟟'|???>~?9~y?<~g???~???O?<??s's????O̓?$??9~TY!9???Oϟg'?~?9'?sg??9~g??9??s 9?f~?????'~?~y??????�C?>???|||9???'??'?y??y??9?|>|?????|???|?fg????????9>3'??3???yY"<?g??ϟ????9?O?ɟ??>?9???3????sϟ??'|sgg3|ϟϟ~'?3??g?<~O???|?�Bg??'g???~g???3g?3??ϟ??s???????????????ϟ?|ɟ??<?y?y#��jUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPTUU*UUUtTUWҪUU]UUURUUU]UU]RꪪuҪWUUUUU]UUUUWUUUUUUwUUtUUjUUUUtUUrҪuUUUUUUURUUUT]UU\uUʾUWʪUUUUrꪪUU]U)URRUUUUU%UTUUUUUWUUUUU*.UUUUVUU]UjUUUU]U*UU*UW*uUU]URUW]UTUUUJUU]jU*U.ꪪUU]UUUUP��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/empty.ogg����������������������������������������������������������������0000664�0001750�0001750�00000016660�14035600052�016120� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������OggS���������>1n����@vorbis����D������ɯ������OggS����������>1n���'-Cvorbis���Xiph.Org libVorbis I 20030909����vorbis"BCV��� R!%BJc)RR)%cJhs9'A1.bkiRV!%S [hRT)cRJhs9FsB'c.b[Ic1&SJ(c1cPJ%tBG%t9c1"[ŞJ魅[JR*Td!|F[Jc1cdˁАU����@BCV� ��0EQАU�@��Eqq$G,BCV�@����(#9dIi'뺮n۶m۶ � ��4TD!����db@h*�� ��@$'IRa,&IRʣ<IƠRJ)RJ)RJa,GIRJb,FIRʣ<IƞRJ)RJ)Rʂ<iIנRJr4hɦRJDRJ)RJ)R|J)R՞\I)ROJ)RJ)RJ)RF ����F9D33MAR4{%Int9ݜr'��� B )B )B 1ĐCN9TPI%UTQeeYfeYfeYguYH!ZhXc椭9J餔RJ)t9!����! 2(B 1SNA%T@h*���@���(鈎舎舎xx(g院i*˶lۺ۾۶nqqqqqC ����B!B )S9J ������(8H$Yeiiy'zz(h{gzz隮꺮몮*k۶m۶m۶m۶m۶-!�� ��ɑIqɑ$ 4d� � ��EQq$ǒ,IDɴTdOtQu 4d��� ������C4DCtDKDQEQEQEQEQEQEQEQEQEQEQEQEQEQ<<<BCV���:#9b)")c9@h*�@�@��"9eYyy'(j@h*���@������XHx舒((((((((((((((���(GJA{xZ;bsgI˵tB(-טyǘsB bwJ9H5B��0H i i�������Hhh�������(������������������������������������������������������������������� y""�������h �������()������������������������������������������������������������������� i""�������h x �������(ij����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������p�� Y� ������������������������������������������������������������������������������ ��`� 2PhȊ� N�8��$i��8i��`i(�i���������������������������������������������������������������� ��`� 2PhJ� �,e4 i�x@����4%(4d%��`P˲,σi(B4Mi'43Ex&<L( DQU��8��ؠ)8@!+��Xy牢i*4DQM4Uy(i M<QETUׅy(iDQ4MTUuy(EQ4MTUue i꺮 DQ4MSU]W(i20ETUueY2@UUueY+ PUu]Ym�뺲,����*ф @!+(��S0&!$B&J RR(TJ !Rj)eJ) B)T��؁�؁PhJ� � D)cLBc9!T1眓P2sI)c9礔9sRJǜs9)s9眔RJsNJ)%A'9��T��`#A�R� cYig$iy(fYy'<OD4Uy(i*=Q4MSuU,zh0MQ4MUu]虦.d4Uu]n躲 \UU]W몪ڲ���VG8) ,4d%��@cR !BJ)R ��p��0 "���TRJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)QJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJRJ)RJ)RJRJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)�F8�>P Y ���(bb9)-X!sR-g1)XcΘsJI\J礴s9QJ)sΥbK))Xk9Zs9j9sls9[5�0� lXh,А�@H��aR1s:(d1 B1會B1B!R2sB!TJ眃B!PJsB!JIB!B)A!JIB!B B!PB%RR!B!RJJ%B!RJJRJ(!PJ*)PB!PJ*)RJ!B)TR !B(��� :ɨM�� �@xAI1"!娵b1c<$sRkhH1jS!ŤՎɔrTC)2dILXB#M����L�Q1��A U DD�hut1 t.  � p7x< @GQR����`��� \FGH������@"DDD3Waq�� �����@@@����� ���@@OggS�z�����>1n���OQ*-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+'ؽۉ �20�=ܰ=����DD�����������˂�~lXӞ? n����@H���������e 2@B%=XӞ? ���� D���������THX0H,�=XӞ? n����@D���������@BE =ܰ=����DD���������@ e=ܰ=����@���������B2�=XӞ? n����@$$��������� E, ap%$�=ܰ=����H���������D `@P�=XӞ? ���� "��������� `b=ܰ=����@DD���������@"R@ =X^? 6���� I$���������H"0�=ܰ=����HD$���������B@ʠ=ܰ=����D"���������ʀ"�=ܰ=����$��������� AA�=ܰ=����D���������pU=XӞ? n����@D" ���������`@d@=ܰ~l����@""���������AeAPp~lXӞ? n����@H���������e 2@B%=XӞ? ���� D���������THX0H,�=XӞ? n����@D���������@BE =ܰ=����DD���������@ e=ܰ=����@���������B2�=XӞ? n����@$$��������� E, ap%$�=ܰ=����H���������D `@P�=XӞ? ���� "��������� `b=ܰ=����@DD���������@"R@ =X^? 6���� I$���������H"0�=ܰ=����HD$���������B@ʠ=ܰ=����D"���������ʀ"�=ܰ=����$��������� AA�=ܰ=����D���������pU=XӞ? n����@D" ���������`@d@=ܰ~l����@""���������AeAPp~lXӞ? n����@H���������e 2@B%=XӞ? ���� D���������THX0H,�=XӞ? n����@D���������@BE =ܰ=����DD���������@ e=ܰ=����@���������B2�=XӞ? n����@$$��������� E, ap%$�=ܰ=����H���������D `@P�=XӞ? ���� "��������� `b=ܰ=����@DD���������@"R@ =X^? 6���� I$���������H"0�=ܰ=����HD$���������B@ʠ=ܰ=����D"���������ʀ"�=ܰ=����$��������� AA�=ܰ=����D���������pU=XӞ? n����@D" ���������`@d@=ܰ~l����@""���������AeAPp~lXӞ? n����@H���������e 2@B%=XӞ? ���� D���������THX0H,�=XӞ? n����@D���������@BE =ܰ=����DD���������@ e=ܰ=����@���������B2�=XӞ? n����@$$��������� E, ap%$�=ܰ=����H���������D `@P�=XӞ? ���� "��������� `b=ܰ=����@DD���������@"R@ =X^? 6���� I$���������H"0�=ܰ=����HD$���������B@ʠ=ܰ=����D"���������ʀ"�=ܰ=����$��������� AA�=ܰ=����D���������pU=XӞ? n����@D" ���������`@d@=ܰ~l����@""���������AeAPp~lXӞ? n����@H���������e 2@B%=XӞ? ���� D���������THX0H,�=XӞ? n����@D���������@BE =ܰ=����DD���������@ e=ܰ=����@���������B2�=XӞ? n����@$$��������� E, ap%$�=ܰ=����H���������D `@P�=XӞ? ���� "��������� `b=ܰ=����@DD���������@"R@ =X^? 6���� I$���������H"0�=ܰ=����HD$���������B@ʠ=ܰ=����D"���������ʀ"�=ܰ=����$��������� AA�=ܰ=����D���������pU[ܰ[���������������@���������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/empty.opus���������������������������������������������������������������0000664�0001750�0001750�00000050511�14035600052�016323� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������OggS���������N;����OpusHeaddD�����OggS����������N;���yHOpusTags���libopus 0.9.14���&���ENCODER=opusenc from opus-tools 0.1.2 OggS��������N;���+ 2fgigijiijiijkjjjjjkkklkkkkllnlmkllmklklkkmkkklkH,JkY!�(A!㨂u pXBj+B?1uu!FOѤz4E0 33  cIZv&TDEs#*oQP͑9M 4'ydnnI)k;5yv)#7uUmMo$"}4vdKTr /ҳa=rQYEk(G g4'(U~8A&Jc_"9<R9RX qc6Ҡh,l2%m%a%Kzi&$_a{2i? 96q'8GSUx2UgA@)T 1!(\!n--L eP?gYaҏVvs%|^q4ۍΛ a߂G-̦`|OTeș" 67B18>@�MX1DyyKS$y1a5_ 'T8rGi4 E_V?3 ܸCe> #!@@ϪٽI|n5 a@#~yE"qM2ejjؿδ ҜOɪ{ackE#Q_TZ_̉PHg|]P_LIq^`;[xYa3 b=z?7 Gӽঔ,9ƎStV8rȽk BEԠ`iM+0ġkT}-�#+k Ժ]}E5a'"?#@u)X{ݫVs$Y4'<j`,GCXK*e1:/cyDa=RÈ]_g?LCF[\f 2r4\G!wKwi,x]/or jРȁviʦ- _ Έkjȃ5aB;j; O9=`BCT0x)*ɥu_d@CϽT;QNCUƶOfc*:yW?yjJa5߂GS`Ψ18" ! p r>9 Oqfj0W3rZ85>"tp*N/rHm/^V2asm{=h%Ta8Ds,du'Qc dj簘4rGJI⣩<s#2bG>hR1,QaK*s4Fwt}6Կ;:o%يa.tqof&ԈIP$rhA/?N2) sn˒ri|- έ0AhxNa[b(<3G)~$(0…x4*ҩocvΪ[^ΒyC%VLar>˂Pup;.Wĥ3U&~fZT0/JH Yj`TzO쮻}C2gy5|b5KW:\dg{:5zӬ6a3gXGZul&m~g?6]o6[ƽ͸*}G IiHuTzq?(p'p,vޡ/`ƺa>/KgA2%sĥ-lRb3*9c kPz0do>YyJ\^A~h,mDoG.bIKh an\O'BGx$v{\ {a|.fX.7Q&qREJh}#1Z$Hq'q1 pe&2aߴGzfRHe;)$!U\h7TAWGUWX\U˧D# s=:Ց5K.Fg,+ʩ%&5*^#aHwӾJf)X.fp߁uLk!9ipzjzl@IrMT+B}pBHv~= D`l- ia4^ }P{gr^aAH'0ۻځ"�.1I0T c=_m,l?Ot<7/'*>_.ZmmW,lLƢda@ou = R`6dfE@R)7âB`G6RRq9GuT.%a@",z'k*Ctq�8|F8cM&av?~ѹ5'>9`t)Á\T]Cr9iIg v՟alL�GVWTV XXPB!a$b„lOfM3S,i2=Oc%b8kwyo $Vb]<3šy<-~eV[OQ3Y㭱?TduL֑anmRfl&H.^ZVirg?#M?{g.y"Pզt]zkWsZiŪ1 Tp3 :?o[ޖa8)}Z`Wĭ^@;puf\9'Au֡'/hF;fGA<2 &OCe[&3_QEN ֋"8q_2:8a@|Ct׌|בNNr2⡥f?}�i!PA"LjG^Xр3H6Awp�MD^9)?IYoM%KNw�eEy}=Z&`#ޅ k @/6y>m(/YS,Sc;9+ yQc�8HeOS݁yua{(WV}@} Qq#Mye1ju8a F~UyU@ ÙV,!VZ}},۵@󰱾ݿ{PaK�Ͱ@O@4 eUAs(x..GXCJN:9czSO16BS<]w}l4Yb $fSтQڦsc�3\hRS5{E/yayÀ��Lq?lx}}J <4qoi Q;TGzxSHER2w%DxO0mmo~5r=\}a+@2M쳜8/W ]9dZlNĒd3QM4/WԜi7ƍUR#nB )lx *ѽ[2kSzBcqaꔚ1}Eb?ۧImA`�͹!8YU<l/3Jjp_sbg>GHS q*=> CɔK{X^H~8f)θ:b6ލYΆaO9]ZcP.-e|ٞ$aV:aK!h2`�ejwf;OhP]C*;.vIW7rM0 0DFc8a{Xr}VptةEָ6 l0hڊ֒:eE!|7ywPtBLF lsrM}aiÑnGo3R{ 9y+)Jy&R̆+ 4|<*iZ_`g=n=Im*7KIJqUkB5@a괢{}@ E&3miF`^#-%佯pi] xgF] ;תcHEblj7C\[L$y;R!ͦsk͔9q<N*M52 ذd1^!ً }q}\60>a#q)z310H o+M3Mb=} Y{d Lyjir^$b?qt^6cDJUU({t)u!}a`ӭb .EGuXY+NפD|(@@ޤFx!>Y3s+VFsC4ef1;eqN@}a<@rQjrBBv #M(l6*'gwb0>V%C?)6ٍnl}^N ٞ`̛ia{x+|yNF8hkw–N97A;[f3 mn>ȜykJ$K 󀨾W''|? WܞN(6̌)(ysaAg<n;a^"&Q$HP]xcc(DD 6B[]XS#{W#26nLI=VqzY|-_aAg=VH>zL:ͭU*w 2`lgA좥3j-5ao-C@CExNpG>*SJatU# 6KVKHzL<ijey\1 jalheN%ea_p?ltqS'n;)@Њu:-*ha :6@r[t< >.29q)fWkVZdtp&:~^,Əfwx'/^,NxٺQa괭]< h&W&m2kKV-N W6e`S d]][gCDhjLyc(7Bå0 hcce ǵaA"�QoZ\ZcqEzX zʅvr먾#Vs#׆y=edZyx-S=0$Ʀ]y/(szeX*a52PR^ڲc܅4cZ裰X+J0*\R S"!2͝s  ^ɸ WWAqՊ"uVvJԸi\9ɒ d*#Ftj6*G6=ϢuSIزA Aaj>r[f [u }&{)ڔem>m>nW8_%#xoC(ٹI]rD?+Pw@D#(0Vaa!1!s-SfRQs6D2:O ~p&pp:AEk/AKŰR'ӡyZ֧kDAOggS���w�����N;���Z 2kkklkkkklllkmjklknlkkmkllklllllmlklkkllmlnmllllmmnoQ1#_x޲,Ş6fTۻ̯Oq/U .[x"+TOל..I]$zS>qJ{^r4MFQ'AS~Wi`acN%H?lU&= &=llzӯ3H7|֠PKՒ΍gws5gњU^ͮkHѴq8bX(fa5c9F_?o.5F˚~(xW!ؓ�AF/6L?TIP0@N%sܴ(ܥD}BQ^]< au>4~Gh0S7(x:8biET<g - A ޲Kl;&Xɬ@ps7[am[א=N,܏Ud)R&hD_ihoTrm_7C.)=gV.X$@3z8+@%gD>o`a폆VQBhU r̼u!o{Kز>m`ݿB_GC_=Vdw^hrTQ^~^~p:h $ǎ{˜ 9^FKa+«xr:7x,==`&%'8f!n6owɀ Kq9E1mTAh>E<vA&[`x9Oaս:F@&pFZ:+BGuJߌ7vJQ+OVy TܓL3SL�+Iel@Fvo5~s-):~ƛA&rY' `$mu|~ëu["Hs!)[�{Y`"gPȶ JԌ,}~SK(nzj]-=q+Ja:"ߠMZ7a̅+7ar/@*:} t Q/*(NNLf~A49;d~9`+oLub~ 0amhTfÎOX)qd3@̿.Ð@+篘 =|&i,2l2^L+ĸ P 4C"l-X]dq1>+BaꡪE異lǂ< xë7p*]"t<tO/b$p8ɒcu9JpoJ!&auC8n߇Yp~`?ͅ,/5S=0б'?PW[:lmmWhN#. e]T~5OkgEȎ'tTa@cچ0G�MyK/c HdQt-$<BH<+ xa]Sb?aJR5<Pl%̘,,q,VQa+"Kh8t�;- z 5?fw[yckSت#ܖFBt\ibX{4? D}8Ad a? M X~ۿ_$8@q6H'ds,[NfvrHs%[&9 oL{g#(/؎Ca1SL~O;aKo\hC ߲,ysC|ې \S̚R9ۤ)HO w z 6�>EkR8 h8w:.5aáAK\__̀T]9 KWp+1ECPI:DLTw-t2t=]Y�wJGLg'5~"qsa\KG�\ǭVN5̵O;SUF$ug5%?M q!#`Dp w&[+(qa‹Jc/}s0m$LG=eJYay �gjɠ$"r#\W$c. in*70`3ᾘ}ΚaO9]:I 폞BZs|띨UEo`9_6Є5mNhZ O0�=Cr E\tJ7pIꀑaV_oQLٳf'seW&"� r8c<0LYӵԃ**\RvO=Xf' m=_2Ma{Omg͝7zm:*%��nV24HzޘRrsLVhB�f-Tl,l1/J=Y;vaX^""UdZP<kp _}N,_S?"}?0Jg;t*T%4zmhUB-Yā<VP<87ZaYȿ+$GGiJ�b΁uPHMƑݡ%sa>X!+ ^4BP{$0&"ql'1 j V~c}Za=r8KR,I Xv^#3_:،}=B>'>iKɏ8}t�l}<ZG*2j'% 0whyإa*.fHOBįZ8]L}0JZ4 v^FOHTū|0,6, &P}4V4.Ftc晎ܹM, sJqya!ӝp3v/}Qe;ygWK:֭|e4h7d禼;@15 d#d%˸4k�pta5#<z3=F@"1]<*_Dsk5hz۳>ȩDHQl0豈x#Jc<#aPmnN=Qo+/E9YLm aJ@2bzv_ M,hyƨ\RlPg59vxxB_?HUtߤ:k҈- 'P&e\7T*GpIaB=� OI -K$[׭P/|&xuCEEM2OFÓ=}%ޙXD&ˀ)F8yNoVHTl ɽThiNaMcUl;&dpxy(<G5DJXt';oIS$Lظ(axKV 5O >Uwa#/:kuw6N'.*sOGAl^pRot ?)�kfyLQ`~>8۲}w}C #57a@f�s/WȫpAhQ*?EtsIe}D2k0r[+%<h+ۑǖ8հ5vO{iqnh4Wla2>_mRBvh4\ԻO*Yr*F(u}@  M]GmiTi(ADX(oㆮ<2#O) ?}G7aQp$mRݪ5xv]x颛,>$>oU?vnj=Q GtL-w0=bJmkxa\\?|R~<s%Pa)<S"ϒ=D(ɺD J?SS 榷7JTAq Pd|e*a443 Wμy8 .zkaftrd!<86L=�ޖݣТF)@:<)g.S)T,0ުbuG>$~݂fDc>[ .Ca�[=Yh,nц@9TU(Z+, .`E?IEfSPn_Z9E$)3&tPyȼ`eDƽ(.atzʧϒ+NGHxK_OXj)#ࢸ5wҽ$ƂbH4φL;s* H x~Z}U a)?r{}\|82@J}#�=GvM^ (mr)NJ8J(MM�3#NaGhWa窝-?GYȂ_F̶n CXƯ0v·8%Zk7!YclEW'߁ȪS2?6a03KW(9UeoM,/l-KF7۴Mjas��-7 3zȰP] :܁ψUjPぷ5a|UpO%A.>݆24ȕR~Jd5UmJ^xE{1_x$ DoAE!:A5pqcYߌWME1Žk]]U u AyaսG i5dt ׀m5!5/>"铩e"zNko> }_U uc+SÃyYHls,pfaB}jq<oH1A] =�j^٭vVm(~z>/N,w31rXƠ6Z%JQrܗOgJCqi#Cߦpo]tya] hdiih$vI+PE~#]6R\'8lTa݅XR+4Y{q )#NyjwXdx!OSHC^ۖah# Cl<$%* #FQg `?כihY83%T}0S]CmE#Qd9#aGE[+braՀQFDM-܆2h5T5VզXTyDRr]pӖM5ʐ8@%Cyu/WFFiA4+zoۭD7(|ʡy/Ut6mS5CX;IĪcB/kT 1 kGerfm4N7+9+ۨԩ)He�F:B: /OggS��2�����N;���)*2llmlllllmlmlmkkkllkllkllkklkmllkklkllmmlklkllkoțozZa*BȤVJ (({eh<mIi*L3=`O {rJd/aM@MDESDfg )O(?@a)l)eaꎵVZMZ۲_ (ʟDꢺ9ͯ @ыkI nܑV"ۥDɘLߗwshM*iC|8GIaղe w`2fh=֎yl=d .|լa$;'g5zŠt}U;.إ.ˆsG}J?!a sFvN D.*.�WfCɃ %Iq<_"ja `\:"gHs-Yz d(715a24K`[jvC<ш^JcV25}$cߓ+/n48KrLQ)znFf,)+ c^"aH$aqaL&4F&Rſh5y☀#;!ew_:;L IdWӨB<aBn^x`*ޠPuAeHſ7ٮ3`~xP!a3JKW.f%#| =dn"OD_ΏxYf@›L:(2Lb(e%h(bRP La괹0)96QÛ.Q┧w7FlLb'dN!ʃܵ k1'ݖS-GKMS#NH^aV^ɽpfRk?&m@P#q(U1|vR3{e1N}@,oҖ.۰ Ca^.C2[G~6�k�B,SGqWjm;P. `esG\Z?Cs8Kh@,<8x'϶aERȾ]naTpd%6A�d�i`rZhf܊ T<WIq[I21y]b4?H~Y̮=I80al45Faҙ _BsD:z,Tk*$>M!2ZN:9cT,q-\>]KjWbodI} #)l|<ZEwx;7j/61rj:`aW9E+JT\o�3m/VF!::j `KHA{]?G:" yZHygްVE'DI?u9+,/]Z9Ua R0s*> Ike:]KO”4-#˙gsd1:)Alu9o9 ڄ,;M%y^g ]`8qax{1j71w1oX;@2ݔ.ZJv%m>=dx\  ̪屹 YG$D\P.PKC*#&˴Q^Be>`'dx9o ̡g˜aꡯʬGB߲HsSg!A|ǶGޚaC[#N !Ƴ2&md(%n ֖WjD&q${liaJ>{Y}D$rB ɚOS תq7a'l9_YvhH,dĎ3Ō{"_olSŘӥ0aAI1z<)yI}U 6q?gr"~I cU5G%%ݹ%>/?WU `ʎALiJ*_vcK?yƃ@<// -l>,av I\Dd' r';t1Kgꃴ;Rb|<EIWHzރ,,KEY/M4b4>uVaa괧 D׳ن Izær֔sل} u/Y9jɄάzyQ.a 54Iibc,<7ѥa@f�_Lpm /yB";l�YEPn GudL>O:J;ׯB D / ڃζ*7όn[5GစaD+yT!:>H6/1h;. AEt `)xK*6(bFFYO!ӱ]ѩ@4>;h{aH#W]m@.Xt@H]mzOIer-< //nՅi"xT_PAgff*;e arLרp51TYi5 Ya|:XU:}`8Mզ/ϩQb0/q)a^U9ҡ̗Ù$jR@*#[Y \REYi7ic8:>km|ANaҿM&a筣ϵk~)k) % ƒ‡RF.i"`mSP/Ȇ2Wv N+?XZ]KZo; T!*_9ap"lzi-@v}~Wp0HR oqAJI,ZVq8 lɒ)楗g,-[Ŗx$-0oS8*D5O:X%mLNJ.|=7W&r<?9K!2Pљojvړ ,` *pUщ=Aw>p f~ꙶw�aƼ^'!XJ-IfZ"Q Q=-5`0̎Y-piN=M8}4ؒi)2{M<@*a܇vSzfjr`z9'ֆ%WCS`ҷ)D6H0�6Y  4> WU6xX)NNT<daߴE]5  kTTNtIn0^' @RZDNsMDȋtBR'ĄGCCyɵiTASDkvSa GeͣOTuC\_{ @TW2B齫8D"w#_u[lAа3,riѼ3.S^ޓ+eB_ o]N;.qN\`]ux,uڄ$Ĕ@`ԍ"pFqs,RSe@XqKj_*A;)FhRɆ $sQd0ZRloțOE10;QNjU/{;C& l3@0kk$IL4Yq&r6>߈L.#i/˃#2+1 -=v&CaphhS L1!~qEnnj ~#$۟@=1He+}.u"L}|p$hح@ejb{\7 =uå5buuIDۦ7Y8CL͎dv_6bi a{O~h@ao.n F~.;9 I /5 \aꡪ?AR¨<x`cr>\D\ψ;?!o腩hpZ?~dӷ,nA'"gw:ׇR_[ YRR0q{d a}A00q"ĢᣄNgMyte@Mv` JWooïT{>!v0rEnΖ}?��T#*�$-VO(/4KaAgR}^M}O~F+Qq?hxb` S2tZpc_GznOܰ+c ko}7sM[&Z`@s >ay[r7I_I!$CѺw2W&G)P{Fe Yt(wt*z("yDn5i:_Av̔T?'tm a?(Tjdi >!ɞ7gk:aXsԴQ[N l ̐@+%E+'BKC P ^G,'0m+R;}|kPm-[aB㘍>>3~{Ė[p8 |y(ɲn,->J({H$}y5t rVřeTTL-! :&`*aôr_uB;?Y/{k-o{ /fCNDg?3 lH:_4s{Wl U0rJ]u0w>eHBY2havNEp -E9mXS7� K&ym, h9SC*8b׋̖ύg?oNOh!qa42\ՁGMx �e#Ⱥh vdJp&vHfkp,W\@g*?W|P&Q� 9F}NLTa괮(my"gMo ˂Y&p#F۷"hJYlY' i/㔗!qZvN'H|Kq3L m|=78ULaA= RFՁ.4wGf5{gU6>*TohAq+3yWēlr_:�ŗ;If Nc9 Ca괢w6̼0rDmH[v,YT>^[(:|!Wf.-K(Hא#N,6ef -8Vay9"C$7>Z(T2Ώns dgDLw*߆-=J{𝔢ovsMb.m{ڄ_i2a9~BR :kI-T7f'-9_bW A:P"⏦O Hαp5j"pg_ޟE18So͠5]mL0KhܨKZŠ SDm1+1~:~54#aϽ}lF5Aj$S/S!H׌"$ J>FER.'.5gpKZ49W.)*D 9OggS�G�����N;���smc#kklkklklmkkkmlkkkklmlkklkmllllkllla=4 /NĄxVq<OA:\=.8uJ_qݪ0;J=j^@d O�*Mr5ax{ܱ0`:i-*Hk™3"340JNz �\n-ak†^�rwY-\,>}ɐ~Y\aea{&NܢDuMS6W?}8 9}\Z[Ga5<TW󤂅Ȣ>*vJRs$e6l3HEC.u/A+oE:a �13XpjBmDtdpIS*cJ9$إyB.fÏ9v�pS}>.bGarLc0δfG&:aBF6'8RO)MC 44RS9|c�^_P(/W|,z㩒hXdQs�@$k )ahʅ:6O,=K:"6eƹ܏A$V;x]o<D׺Lԃ!)tG mw>^a"saß[ +s3,x9M <yj[6* U'7㥗 z%7+C(ZRfXG|r,=m7?a@e[kccGzVR_4?sD'JF|՘a2mD'`UIx!$ܽ%* ۮ,i7ME_u*C1`Eo]j�ͨl "aēz8LJlV5,!?J.1ص jS*ιGHtEwxyjO6k+=`q~9 af88FMй&Y@xn:R Gk /KK!C"7ɃRē(5 Q<)AԳԵ2a; VaNMW9piE] ]3ip]Y4&PY|usr%>@(tM;4b68siW`*OPZa .!^f�v,I}#h nOW3N9iزhb]l*ӽ>O70((Ÿ)zO91?y;6][:K`Y\%a� ȸ>i!sM(/ R>In`6vuÁ'iaJ.73$Qp2_*t))f'') )?ДBg&Ba3=۷G7/5L!c'[w>miYN@-$!,wbvL,gg_"o'0J,xC=^뿃^yI�zaӌҮH"a2aHPd~jYDE J<EFCW,տP`䭻`cԳl\FZ |LmS; =Rfa܄\zFm1KM W#xgRgڶ%эZ6u+à#&-bKYƾ@{o<H$A^[%&a<%a1c@T2776`PM"�i,")3l.هlGl)B& 0Gu}߀mU"Bs7ug*j´ shn@P"50Ia窤{1h$#ث�ݠ%A#A ۔9`2:,}%c>5n~ oD/v,5]C&jy▧g- JeLa2(ԑWtsmP?`ſΉs<&zkfUSEfL}G]~C�TƺmFPD2Ⱦ}JrK AN!aAOx,_Xfsqg3?Eb[Nuwz&hB$Oz8*vGMl&u<Jħ,8K(<~sU~)/b9kJaI2} x&}U^ '{iס:VyD9O1rd^Ɲ>7ʳ 'dFyŻt)Q^Sh=ɍ&ߗD5paEť4DgAX9n.Ȼ@TKH ǰ5iՑd}F/슁d·*@*d/gzCTa </hoact[ZIn>ƿ njbN^"-DzO�A* ,fuy&=$GsK/Gn1V꣺/)ADa:i3W�:uw {!B?~#ջ!w�`z'Akl.%RP3NT9O jJw3r6eAb巎^TA+uE%a@aɏy "@B=1 hPBH/#܇*DW$Ӊ/pԍ9:{VK>b~XsUʚ6u\e$lC,\qI\aüEX/PW~.E%r E[Dc$NJ$U0\h(<ܛ*,ZwX&V"!CA J!a<q 'gi?axQRjSֹ}_u aG +S^L0~V0ų>G]b'g˄}r -_#`a{vk?]\D |oxm4X'ŕS,ހ!�! "'u,( e $Y=DRx&Sil /a몏 bANnz-iz.h)x#$xϯlGe45tTQ9`@a伴NJ{"~OF BHa-3ڬ3Y9@![I 9ʒ3%Cʂ]Xܟ&RDV[J$j5H?JP!'lOX2a3TbWUW u?hqkxF'l 4=ψ}^7.-MkDcNh$뾃}Vwd2> ^?C$<a@x|i_ lZKv<1EcZDF/Ĩw7D@h׬59)i+؆\O[I3;=aLJf4"i$,bs+ aeCL%`wYK=r޲ c)lpB(Xj Y{I�ۧ )a+1 8*Y:9k;<8!�H \~xomESNaNӕnaźr}i},{VG؄8x5hgQ"G^ `䏿Mti/:e4MZ�cMD0[Gbr'FR0f?3튳%f%%]2UH`g8`KK\b ACc>mP֗hW px���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/empty.xm�����������������������������������������������������������������0000664�0001750�0001750�00000030544�14035600052�015765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Extended Module: test song�����������rst's SoundTracker ����������}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������2��arrive.wav��������������(�����������������������������������������������������������������������������������������������������@����������������������������������������������� ���������������������������������������������������������������������������������.���������@�arrive.wav������������v�+�b]j,=CYG/ym%�U �&�pA.B< u4U�>�0B+�bENuA3�{2:'� 3�Y*Q?QG*�X4Y�kfXxv{AEu�7L2kj��i�y#d^GB])O���o� �IF1i?�V�5-"}2IK)�&�Id�hK\�toPU�NWD����[=@j_gn�lR�H@ ~ 4�?g)����n��LJv\WI�Q �L0��f�g |QSm$"Pc�yP:f ~6*  2nSi �3t4�D�V��R� I{lSbf�f�/�E�|���+i+)�RA��E�KY!A�)Kp+^��m.�1;v,Z+�j~��6E�@QN�/ s�"Y��-Vy7�dk~/<O$��� 3�&��"�B/XHvKkE!-�.�b:�, "dx$QME��y+\�p�D_]u�&\U |�o 28*?�� ��C�"6� �M� �)����@�96|��Nyc���PAKY:3,F�8myq8Ld/Z#Tp�]�Dv/��]�]_}�=a^s���((�%�J/Zb�[sK*&J"�AR �OI���;76�X&M9|�+��_h�*k3�}x1}�AB@i;n>��/�+:�lFo���y�Q;a[�rYy! ��`�N vZ��lM�,�?%rb1�L9vd�4�!�Y_PM5w �7/�nADb�<7'L�5Gv>tG l�~9b�������D�a?�e�t�n�_�]���m+c:�p7y*�R�%�8pU�O$u��(`W/4QN�+gCx*8g��;a* TdZJFMbZ��J ;C�U! A0<;* sB�oM{t�`�gHKLQ"t,x����q��;gKt�PY���h�g�T@�yK2"'�TZemD{^?y�O�_H3`@��/�u��rIH%&�*2*R!f|6�)ITaWNQ��|$ )Yz][oYXS*��<sqWA:Q3c�v��Q1�>��L��?)�vJ  &#6m0�0+ rAj7"�\�ya_������k��_s�R !c��"�L��hPA U�&<RL�7i���U<�w�#� #;'%@3��5e Ov1>`�K.F|g9"DJ- �Z986B �V�a���n�x#n�2@8�Z�y��M^�'�Ow 5���d�e��ucO|O�>ydA[q�b2�����~��p@moee)����Y�Wbg$c-.,`2, |f7;(wyH�U o*���l0�e�fFe���=I��T>JUsB�FcbN��\%@)~FD�#���9~(uK%I��Ce !%�FnN1EE? W*?�<  { �6S�l(s�ZN'Q<d = b�j#.%}VEZf�Vx2T'?:s|FS ]$�G ][�jd-zX3@U�� su0(AG lxb�ln-%_gK~G4�;]D5gY,�<Irw/:C���2�D�+s9v"G^�GXtD /WEBVA]�{�a�� q":�gg�p�m��@R�(k)iJ|1�� 3\z`h�@(>5p����c�[��]-�3Q{s�?��Hax?5.;*�K][z�M.b\Zx6L��#�]�s�&�}�nk�o�a�y��V�BM]rN5�����#i��!G# 3K"���]�|k����t'#Lto6W�K8a[%LlC 8u� m}<��Kk��97-�X�E�!��O��6N�W���F�P��[C$-Npco>��|Z_wx0kEar� �%�|��K�lV}7&-\yx:�z�6�9O�'�<[m|PI6b&�3sG8dU*>&t�cy�0�^~y�t1j$_�t�<e�?T]����� �����A3t�i7kj6gdB0(jM�BXhw�x�R:0lx��i mJ���Mmqs �k����9�e{tN(�������\�9p:8�p4m�WF�:K[�Of+`9Wm1_~ YC� V0d}�EGg�+3J&�o(4hY��.b�C]3��xJB-)Rw�me\{�w�W��3�C;9j"�<D]-dR��B@�\�MQ+X�A Z�D8y�Zi�1a/G�SMB4=W*r~79Rz�#fXhaL a�9s,.� f~cZ�t�Q�[<30��"���x)YM�� <I9��%�oU�%�faa�GfD�"��;i}~FE~w"$]�#.iMG7��z���7p�z�%�L+G����@Y+�u- hfb'�/�u6Xr�A^])O�2rb�^%1.A:����]�1�� ����X0xckm�+��u4Y�A�-��O5Z7�e;}/��VHGj>G3WC��0P'a`&7NK+D:1�y<U2_) ���X�f^!��{8��<��.bkdet:��eD��ZdJ }>�$5R�0��&7 �TM��'�e�W%-T`��rQxVJ�+(~!� �v(^1�v �J���k����U�iUEwbmU6��03#-��:��ym�XJV)��s�I#w= fzo,I�uZF*3* 2HP3`�.B-S;qG2V}sp_����dE�t>?@w�D[�1h2��~�)� �3�I�U�e�}���[�9n |b`{Np5�SZ)d�!�7��GB{hDT�Zjyb����k�)zwFJL�k���9]h\9�g��C��9\�CLv�A�[Ac:@kI�!AqufWMB(P������"<LX]S1���(>A��!? |�TC;OCxO�,Z[����gvA1�s� �S"?vo Q ttV<l����S� � �r�ZBv� �=8~��ZV�3jc�����K� Z 4\&NddP8*9rf�c#).5�X���S��\/,8o�?�j@�����<S:7)(�Z�m�]�2�~V��%uM��m�<�� ��~��[~)�d��A��mmX�uqhfHpw3@3?��?&�|�9�K��/d ���\�'�iWc~��P2}biL]+�G�&�PP-^D�&gn@�A��=�O� �Wt �C�U�K�/�5!hs$BPb\ �]�y�n�Z�U�x��'pCC�tVr�V���08�2J��1Z,�8$\L�-H[iiS+��9)B,v������ HN�=�8L0E(�r v'V ��Nk�;���q� /z}Cm�^�Lm���%�N�|������|�����������y�;�:;.>1�+�)(+^K�2w*�f��*��y! $�@xP"�"�]=<_v}TB�j�I�Z?e�>t5�?�?R�Z h`�L�"��.��i?D4q(| �K��)G{ #C��B�1�����6N=�j����Q�\#/lJ'�����sz)��S B����&>]�4��a&ZC;f�u,��Oc�~�*��I��V>r�?L8s �R���s�%�z[t,���-,'#�z�WmvnZ s�}-^����T��+��u&j��Js]s"����R�H}�%���p���m�"�?��� ��c�,�Ap/a��Q�%� ��$�a����Z�v;#o1ttHT��$/RFc�� Lc�-� �7�>��3[K�t�k�3�,&*�tlt�<5�;~o �O�3�7�N�t���Dz�3giP;wAN��!ThmpyvV+#v{#?2�2n%�w���;�i 2�v����i�!�� -R�� .[�������/��I��=I�)lOE\4���6�H<}�"K��lio�� ���!�Hw*�@�-���Q��cKWR !2��=�!�3�T�S��du9*B]�Km�/_2sh]�r�@�J���1|4�\%hSV;/2gp= go���{�<��G~c�x_�.���)4S<��&2<WJp~m ��=>?T*5, {p}m~�$T���/�H.���?g�K�z<>(�����]0Nd5�U�W�Y�r���@kd2��}����"���������T�%FJ@P <2'��� Jxo%�.�X=n}�ia�/�U,X?,�T�~���/c~iL8:Po{>�q�N%Q?$K[8H�LOr�P���.�QWqa*(2@�#����#�2�(���m��1UA��<��r��S+)�`�b��VH~r[XUV0Y���%% �\4o =�Y���� �/^=bD���_=�~�������OG*����� Qg=��,3 ���r�f�b�i�v������5|C�,�ldQ>7nD@7N��EX������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/h264_aac.mp4�������������������������������������������������������������0000664�0001750�0001750�00000010703�14035600052�016165� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ftypmp42���isomiso2avc1mp41���free��mdat��EH, #x264 - core 148 r2708 86b7198 - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=2 deblock=1:0:0 analyse=0x1:0x111 me=hex subme=6 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=230 keyint_min=23 scenecut=40 intra_refresh=0 rc_lookahead=30 rc=crf mbtree=1 crf=51.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=20000 vbv_bufsize=25000 crf_max=0.0 nal_hrd=none filler=0 ip_ratio=1.40 aq=1:1.00����e�7s*/Ш P������� `ԭ����� �,@����L��b���������������������������������������������������������������������������������� ��� A"lF�����������������Lavc57.25.0�0@���Ay����������������      ���!AC ����������������  ���#Ag:" ���������������� ��� AE<����������������  ���tF����������������  ���Do����������������  ���"A4 ����������������  ��� AE,o����������������  ���tF����������������  ���Do���������������� ���"A4����������������.  ��� A E,o����������������  ���,tF����������������  ���.Do����������������  ���"A34����������������.  ��� AQE,o���������������� ���ptE����������������  ���rD_����������������  ���"Aw4����������������  ��� AE,o����������������  ���tE���������������� ���D_����������������  ���"A4����������������  ��� AE,o����������������  ���tE���������������� ���D_����������������  ���"A4����������������?�� moov���lmvhd����yy����e��������������������������������������������@���������������������������������iods�����O��|trak���\tkhd���yy���������e����������������������������������������������@�����������$edts���elst���������e��:0�����mdia��� mdhd����yy�_�eU�����-hdlr��������vide������������VideoHandler���minf���vmhd��������������$dinf���dref���������� url �����_stbl���stsd����������avc1�������������������������H���H�������������������������������������������5avcCM@(�gM@((݀@���@� e�he,���stts������������+(����������+(���������� ���������� ���������� ���������� ���������� �������������stss�������������ctts������������:0�����I8�����+(����������K)����������������������K*����������������������K*����������������������K*����������������������GI����� �����������������FP����� ����������������� ���stsc�������������������stsz����������������$���#���%���'���$���#���"���&���$���#���"���&���$���#���"���&���$���#���"���&���$���#���"���&���$���#���"���&���stco����������0����(��c����������<��j����������A��l����������A��o����������F��m����trak���\tkhd���yy�����������������������������������������������������@��������������$edts���elst�����������������mdia��� mdhd����yy��D���U�����%hdlr��������soun������������Mono���minf���smhd�����������$dinf���dref���������� url �����jstbl���jstsd����������Zmp4a���������������������D�����6esds����%��@�����������V����stts����������4������stsc�������������������stsz�����������4���������������������������������������������������������������������������������������������������������������������������������������������������������������stco�������4����K��O��S��W��[��_������������ ����4��8��b��f������������ ����9��=��d��h����������������9��=��g��k����������������>��B��i�������udta��� nameMono���oudta���gmeta�������!hdlr��������mdirappl������������:ilst���2too���*data�������HandBrake 1.0.7 2017040900�������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/h265_aac.mp4�������������������������������������������������������������0000664�0001750�0001750�00000012732�14035600052�016172� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ftypisom���isomiso2mp41���free�� hmdat��N, GۻUNx265 (build 95) - 2.1:[Windows][GCC 4.9.4][32 bit] 8bit - H.265/HEVC codec - Copyright 2013-2015 (c) Multicoreware Inc - http://x265.org - options: 1280x720 fps=25/1 bitdepth=8 wpp ctu=64 min-cu-size=8 max-tu-size=32 tu-intra-depth=1 tu-inter-depth=1 me=3 subme=5 merange=16 no-rect no-amp max-merge=2 temporal-mvp early-skip rskip rdpenalty=0 no-tskip no-tskip-fast strong-intra-smoothing no-lossless no-cu-lossless no-constrained-intra no-fast-intra open-gop no-temporal-layers interlace=0 keyint=250 min-keyint=25 scenecut=40 rc-lookahead=40 lookahead-slices=4 bframes=3 bframe-bias=0 b-adapt=1 ref=3 limit-refs=3 no-limit-modes weightp weightb aq-mode=2 qg-size=32 aq-strength=1.00 cbqpoffs=0 crqpoffs=0 rd=3 psy-rd=1.00 rdoq-level=0 psy-rdoq=0.00 log2-max-poc-lsb=8 no-rd-refine signhide deblock=0:0 sao no-sao-non-deblock b-pyramid cutree no-intra-refresh rc=crf crf=51.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ipratio=1.40 pbratio=1.30�� &QkZRnF@���������ТJù���������(`�������������������������������������w�������������p�������������^�������������������������������������d������������l������������'��libfaac 1.28���G���6WB I$Jb̀V@[�T� h��<��m�H��#��#��#���0�$ 2m$$���Q��H�'`�Y�?�%`��#��#���8) I$Jb̀V@[�T� h��<��m�H��#��#��#���<8u.F m$FJb̀V@[�T� h��<��m�H��#��#���;%} i$&_+����8�"�K�)�#��#��#���8�_Hci$$���Q��H�'`�Y�?�%`��#���2�- I$&���Q��H�'`�Y�?�%`��#��#���9XUq (I$Jb̀V@[�T� h��<��m�H��#��#���3"%U_pC� 2m$$���Q��H�'`�Y�?�%`��#���3�"ci$$���Q��H�'`�Y�?�%`��#��#���2�B-W@ I$&���Q��H�'`�Y�?�%`��#��#���9xUWC�1I$`Jb̀V@[�T� h��<��m�H��#��#���3%RW� 2 m$$���Q��H�'`�Y�?�%`��#���3�"ci$$���Q��H�'`�Y�?�%`��#��#���3�-W0(I"I���Q��H�'`�Y�?�%`��#��#���9ИUWC�1I$`Jb̀V@[�T� h��<��m�H��#��#���3"%RW I$&���Q��H�'`�Y�?�%`��#���3�"ci$$���Q��H�'`�Y�?�%`��#��#���3�B-W0(I"I���Q��H�'`�Y�?�%`��#��#���9иUWC�1I$`Jb̀V@[�T� h��<��m�H��#���3%RW I$&���Q��H�'`�Y�?�%`��#��#���3�"ci$$���Q��H�'`�Y�?�%`��#��#���2�-W@ I$&���Q��H�'`�Y�?�%`��#��#���9زUWC�1I$`Jb̀V@[�T� h��<��m�H��#���3"%RW I$&���Q��H�'`�Y�?�%`��#��#���3�"ci$$���Q��H�'`�Y�?�%`��#��#���3�B-W0(I"I���Q��H�'`�Y�?�%`��#���8U}0 m$FJb̀V@[�T� h��<��m�H��#��#�� Nmoov���lmvhd������������������������������������������������������������@��������������������������������htrak���\tkhd������������������������������������������������������������������@�����������0edts���(elst����������������� �����mdia��� mdhd��������������a��yU�����-hdlr��������vide������������VideoHandler���minf���vmhd��������������$dinf���dref���������� url �����?stbl���stsd����������hvc1�������������������������H���H�������������������������������������������uhvcC`��������]��� ��@ `��������] !��(B`��������]-YYd+@���@��B"��Drb@���0stts������������������������������stss�������������ctts������������ ������������������������������������������������������������������������������������������������������������������������������������������������������stsc�������������������stsz����������������:���4���<���@���?���<���6���=���7���7���6���=���7���7���7���=���7���7���7���=���7���7���6���=���7���7���7���<���stco����������,����g������A��������Y��������d������ '�� p�� �� �� 3�� v�� �� �� >�� �� �� �� D��trak���\tkhd����������������������������������������������������������������@��������������0edts���(elst������������������������|mdia��� mdhd��������������D��U�����-hdlr��������soun������������SoundHandler���'minf���smhd�����������$dinf���dref���������� url �����stbl���gstsd����������Wmp4a���������������������D�����3esds����"��@���������� stts���������������3������stsc������������������������������������������������������������������������� ��������� ���������������������������������������������������������������������������������������������������stsz�����������4���������������������������������������������������������������������������������������������������������������������������������������������������������������stco�����������U������5��������M��������X������ �� d�� �� �� '�� p�� �� �� 2�� {�� �� �� >�� ���budta���Zmeta�������!hdlr��������mdirappl������������-ilst���%too���data�������Lavf57.25.100��������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/image.bmp����������������������������������������������������������������0000664�0001750�0001750�00000002212�14035600052�016032� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������BM���������|���������� �������������������������������BGRs(` @33ff&@ff < $\2�����������������������������������������������u=stB������������������������������������������������+Հss��������������������������������������������r^sssq$������������sdsssss����sxsttssq ��������ssssssqsr��������q$sr}��������ss����������������rr�f������������s~s�����ss����������������sr����������������q+sp)����ss����������������ssm�����������������UssR����ss����������������sr`��������������������sta����ss����������������srS��������������������ssd����ss����������������ttc������������������stQ����ss����������������ss����������������u#st.����ss����������������ss��������������rrs�����ss����������������r&ssf��������oss��������ss��������������������rstssss��������ss���������������������svssrt!������������r{rk������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/image.gif����������������������������������������������������������������0000664�0001750�0001750�00000000225�14035600052�016023� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a����sssrssrstt������������������!�� �,�������BPIBXا7JU%+^Hd㳾NV2r @]`]A(اI-AmC"�;���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/image.jpg����������������������������������������������������������������0000664�0001750�0001750�00000001267�14035600052�016045� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������JFIF��%�%���C�       �C ����������������������$���������"�!1���������������'��������!�1"2Aaq� ��?�'NJ9U񡳮l>^'b ^*e#D\* 'q)',KNڧq{ %V#i}-m X vhrFT>ANxI8TY|bbNLzLEr('eɟeM[1X4 $ <Y?#M4MO/(1ӛiFLv`2֌׬ 6ЏFF5|}_A҇mdHf$ Hj ru,O�y) Wy7~z$29$;qG² |nl潖#"|x$E^QyYvΡ02ªDCQFȯ$G =R>wbޤ(pU�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/image.png����������������������������������������������������������������0000664�0001750�0001750�00000001055�14035600052�016044� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������a���sBIT|d��� pHYs����+���tEXtSoftware�www.inkscape.org<��IDAT8=hSa(V$UtRRi EGAqT(`gԂ&qhQqE(v 7iҥ;5s{P6Z=s7w2-/Z+ tgi#I|^asJJyZnmnR\0,VGh32 \)fmN  1On` Kjt{W`8(0罭F5l6\w\|J�uCc@_L9Q`5k 8l?K  enSQ`\Y$�雠W`0u~,G�Pe.KL>HkZ*[6L1Z[Bs"R-}K/e:SHa7u����IENDB`�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/image.svg����������������������������������������������������������������0000664�0001750�0001750�00000007226�14035600052�016065� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg8" version="1.1" viewBox="0 0 4.2333335 4.2333332" height="16" width="16" sodipodi:docname="image.svg" inkscape:version="0.92.1 r15371" inkscape:export-filename="/home/lazka/Desktop/test/image.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96"> <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1366" inkscape:window-height="674" id="namedview10" showgrid="false" units="px" inkscape:zoom="15.610417" inkscape:cx="-6.6063539" inkscape:cy="9.4561455" inkscape:window-x="0" inkscape:window-y="26" inkscape:window-maximized="1" inkscape:current-layer="svg8" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" /> <defs id="defs2" /> <metadata id="metadata5"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> <g transform="matrix(0.31181588,0,0,0.45905051,-19.184577,-57.606888)" id="layer1" style="fill:#73d216"> <g id="text4487" style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:6.61458302px;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#73d216;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" aria-label="QL"> <g transform="translate(1.211806,-3.3890332)" id="g4498" style="fill:#73d216"> <path style="stroke-width:0.26458332px;fill:#73d216" d="m 63.89053,129.73077 c -0.836179,-0.032 -1.648547,0.44658 -2.035225,1.18693 -0.507499,0.94941 -0.530472,2.0949 -0.312481,3.1289 0.199986,0.92522 0.897171,1.80492 1.872575,1.95332 0.828891,0.15869 1.763669,-0.10576 2.27347,-0.80695 0.697313,-0.91034 0.757099,-2.14483 0.587855,-3.23753 -0.151491,-0.96061 -0.784469,-1.93906 -1.784305,-2.15763 -0.196932,-0.0468 -0.399643,-0.0671 -0.601889,-0.067 z m 1.462442,6.8678 c 0.458198,0.50126 0.916396,1.00253 1.374594,1.50379 -0.420302,0 -0.840603,0 -1.260905,0 -0.380683,-0.41169 -0.761366,-0.82338 -1.142049,-1.23507 -1.102074,0.11737 -2.297754,-0.20075 -3.038575,-1.06471 -0.934863,-1.04533 -1.098815,-2.54844 -0.894668,-3.88469 0.184978,-1.26405 1.032444,-2.4689 2.284028,-2.85483 1.245685,-0.37945 2.750188,-0.18983 3.685306,0.77838 1.000843,0.99417 1.215466,2.50553 1.042512,3.84849 -0.147897,1.23482 -0.872683,2.41978 -2.050243,2.90864 z" id="path4489" inkscape:connector-curvature="0" /> <path style="stroke-width:0.26458332px;fill:#73d216" d="m 69.089178,129.02281 c 0.347955,0 0.695909,0 1.043864,0 0,2.27893 0,4.55786 0,6.83679 1.252292,0 2.504584,0 3.756876,0 0,0.29283 0,0.58567 0,0.8785 -1.600247,0 -3.200493,0 -4.80074,0 0,-2.57176 0,-5.14353 0,-7.71529 z" id="path4491" inkscape:connector-curvature="0" /> </g> </g> </g> </svg> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/lame.mp3�����������������������������������������������������������������0000664�0001750�0001750�00000004046�14035600052�015616� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������d��������������������������������Xing��������&����PLAME3.99r����,<��5 $#M���&J&���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������d��%<��� � 5܀���4�����%Yw$ #p\cÂ@BPc�&>�h|�������(呤@ a鏂`$22019tS2 2R1E"200?0`.1$"�(tP8+V GYWG; ھ "j1*-t 9U΋OaCϬu˝Vj+.EpiѦI)DQ_yوfQAXfYV[S,9j勷2ݜk;9~??>/wy?zo=s_ܿ{>)�@0#ZXǏE$M@F,Hl F={d)W2ja -i7+OTL_o\C|EǾnYig88X|2cpU@Ybj[ eP;� >f@2b3QvC+p$ }Z NgSϰ؀6YϥWG ,P\$x;B aSRSNAEPlW+$Y[(ѝM#LHoA5baN`Tip]IHB" @9A0#'^rύQb mRv]Z`0΁D:W rKg])!!Fw8gCRI ϗu%GD.ʹG-;c3'<|KSxkӔr"�eD󙓕 Q8 MV� Hd�y5m�� �U?`k��4��MD� y3IGꄡYLX"څ>6[Y2WPD[A.Sp/Ehi g%Xf2/&rۊM9l#婫.AV RCJv[#( Jr@ A@ E'iL GVa2N>: KC40l3]WXԘ֬5&֬5&IC֫ƪaRj2IbRgV&5FX(*(S P wLAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUpdgP/3Z�� ��%E$q��4��UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU0dKk �� ������� ��4��UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/mac-396.ape��������������������������������������������������������������0000664�0001750�0001750�00000000150�14035600052�016015� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MAC x��D��,����������z��������RIFF$ �WAVEfmt �����D�����data� �X�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/mutagen-bug.mp3����������������������������������������������������������0000664�0001750�0001750�00000003720�14035600052�017111� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ID3���� FOOB������aaaaaaaaaaaaaaaaaaaaaaa vvvvvvvvvvvvvvvvveeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyy loooooooooooooooooooooooooooooonnnnnnggggggggggggg ttttttttttttttttiiiiiiiiiiiiiittttttttttllllllllllllllleeeeeeeeeeeeeeeeeeeTPE1������aaaaaaaaaaaaaaaaaaaaaaa vvvvvvvvvvvvvvvvveeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyy loooooooooooooooooooooooooooooonnnnnnggggggggggggg artist name�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������d�u�=�@��"`�1 @�?˼N(|rrDO xKإ2Mw3ŕQv. sR܄$dyA�� 0�#����4�`��� ADYa ^O-c7 EbJ!SwukrA%5:=ʹjw0l%RPn@MD] uؕd oA`�� 0������=� ���[[6mes| !)V+ -.Xڤ4ϹR[" !mdj���0�����<� ���=|TVYrK>͎pu1D{-eRa7tfTb)JT*vdkB�@���0����=�`���PTdZOz SGm=F*=)2gK̘Y +ci7bpynd dA@�� `0������0�a����U^!62z)}H:]X7NqUlλcjk)h{ech辅*kTd(jA@�� 0������8 ��{T:TVuw0QlKJ4������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/data/non-compliant.xspf�������������������������������������������������������0000664�0001750�0001750�00000001016�14244626671�017752� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version='1.0' encoding='utf-8'?> <playlist version="1"><title>100% 😈2021-04-18T17:45:49.936318 /music/Funk & Disco/Average White Band - Pickin' Up The Pieces/Average White Band - Your Love Is a Miracle.flacYour Love Is a MiracleAverage White BandPickin' Up the Pieces: The Best of Average White Band (1974-1990)15223866 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/silence-44-s.ape0000664000175000017500000022414114035600052017055 0ustar00nicknickMAC 4,'I C(|'|<zD|RIFF$ WAVEfmt Ddata YE?ڪJN9T`TnhO( ZOC)3 jU 9D y#< ZJ& k , ng} vibMQKNk[+`娺 .6.OnfB8keFq5N^  &iޖu 𜮓; C^"|[I'E&AX.混[ܼeV*8I06 }q֕"b!V&6"Nl+JF#Fl--6FھQnhlCnR8!tj Rs Z@Ќgjϑ#+ғ3~ Y S#dZQ4/.~}7{GwwmDLUZ귀M.u5*GxBHn[.m@q$^n$HudZ/z~`]oއ`lF!ung mX^? ّ=|} ͖.BY %j5mhډ2E5ÎT"0QجpĻt=}+! MJlRP^-7(P]έQRzvG\pQ=U=h^$I^Ypp}2K]MkC~.d;*FuTEۿ FvQ.z,z/9 2{M3nJ0gfhJ0"Ck)aN]L ϙ!u];Q=LJw݉brH]%熼;pZ͂&Q?-$ŚlŚ(f%7,YcE0Cי1xMJ`E` T{N4>w.Pg0]|zYmmKXvck~s(xnX3فobƅɼx tG^\'6B{gGcC LUxb@pXV^uNQETqQx`G$S7ǙWspQ3"maؐҢ}} ZFڷ;Ffؒ{f!Z> V#1mƺ"}.C;0\ ,BF 8lXOiw7м2mBDu $zT\Zv¦ܷ|>j[ogĔ^˭u>~甴<]VE *6ESmLD5^,ulf̻ m}Nek} ]Ի:KT O`0ykeFxkAJX4Ϋ刯E0XЖʦ!̘J ߂c>jǶ*k&zK"LI-Af Pn2 \k{-o PxVaWN8 A$jhXʷs|7Mr^IVu@hX o`cq6_ E񧇟c1džE\6/zL5@"c\yޔS310P%{MbRu?>LHtj5l A԰|egpkٛ(&zH $πwq_PV4ołK҃ENJ".?RwͻkX)Dhy8d yq "4ҪL`F2z wGL0^aKM$>t3 XOh_{>0lCj3bV_&cT\1/u!q1'\=َt\UDlW֮鷞Jhp 7$) , ft|&b i%ȹLzx 8* ba Z2#$jhЯ\R&N@D/;ǬûZd࿕#W:B";U|)( Z +m&~L6 $Lx/u5腪ks<@KŸi:EFqT:T">4m+g"4+7cNk-;++!cP?k ?' 5+$c| Nc $q^:k1ӠɺdչA0U+Ȏfư%b~yYNTSIExo?7;Ip͙\ ;2+>ZV^ׯ,ow?NKդsa1׻ٿ>A"M0Y4gFyV x {j6-mz@ 1?ᄀs@5Ddh?%Pir Ymp^B_gLz2V˘&C"# v^ԥym5Fxlq {89@Jr@R=4&c\k Tϧ'z'|.mRD؝1%[ˢso ] /ӃcВRf>%X}Y 4l, Wt\>6si2IrPGWCK풟6i*! Ȳ1 joUqM;ȭg%X:+֯N{{uŌkһUdrɨvl5J9>D]ƉF]X^ t~jqpQjInkx43$QLr% .)[ƀE$-,Xv~!2J(RLy큑U]2(ԐCYUry'`f ?*$/8--[b\*Te2bꠋ|1r6XQaqP~"]< yh ƵG;&K%NULm jxsS^Z (&p$z vVH '*c3us[ j2*:Ո4 LN'=VzqțhѬtB1#q~9'q.7 x"0[ jvŶXqo:$Oj@"Nlٴ%GElO22 >.Uߍ$j4?&ݮ&ȊeLlGWE)Gh$U6t &F#mcmb,S)tJgF4( d|@ѽqb ?k;@ݼZz'k{+)_(O+s6$pn:)e9QTjʂ>}cA}znqG=,,GGmz!Sa@BlgPknpv=í\ɋxZ# - qʖܨ:S* .Tl !6%-5$ %DViÉ_y[|#5ؕ 1rkn_GLeۺp$n^ˢ6֗-S!IXZP ,Ƭ$a"ARHIp/"IʗVKty[ԒN@sz-JVfI N|lCALEILqqG=~ ` Y qo֢8gj?$/G,Ώ_ (/OxVf[V~$t~%yXn(1=>mϗgbe{);k׮pq6ˉ3dMWRw#y@D# -=kGD718 f]@waWYP`cX Xͩ}uULP)sɟKvEz \0c#]2'mWZx7H{x,:6yg҄)#mcjLgS1^D]-,h0kL8>z ldq׋ m,U GC;ڄp\UUK EXVdLdjmQscnGD̏|̗ΰ#!$a|a#n(bED|`|ڇwCc__@U4 * ;~9۰w@|wؐvQk7tK!S??t*(!uBo+"ahk2\ i@X^&QxG@a= `Ǩ-!:T!ðL"vhBN:\fδSo#6HX%gZ 'ZAxE҉ 8*vW1OkvC!u&<(dn@|4Kw!EWb}d~EӱxW*-7yC_QP4xm&]]НpQeߤ3S~ޏԆȟNub[88iJUs#g\$>/J 78Ukz3"n./Θ,Ls^EP~ /&[pŞ SrIC֢x/5 zBAj m@0ٷ=?ElxGW/3UWJj]H+؈ ('.p!Q8Pvd<>e2NUͯ)AXM?LTj rr<Ầaǡ]C^9ݕ & ;ŨbĽ3C!il;؎[8g[`i F`߿Svgo ~Iwԏu k:}@ WD Y]8pgkcډLVҋy$c &4lc$?gb@-Emb3v#[6Gjمe,YZC`"xo8џ޾ 4.y;ML1(yc^dWZTZ<|9*[m9@ iO-δO5m j4G  N)8Cu~wF #%cw  ,, qju8u|';WA\qѵ]o6fOC3:^fuD( 7B#yG-USG֦*YR/-f9>pg@P1?x؍\_dHɱӶ5%1#*u`ueNo$ϯ;O@k"M2j+tn.Wy#$yǾD6F'z&qסn?dOՑq?;cO-p R:6ٰ"k^tvF+(\Y'xwƀ&Vj@:MY-݈V(ᗜlT6|ZkNVxLD*ÔECv&oQYC L[h;gJ4 o9bSpDE1,'8pc/0~K}eb,NFFRg6i7 XљJGUG=l}u<5־vC.}gc(x{JO:Hν㮥 y N IoBPnʻ#ɱD]eb&TZ/߻J#91v=k=}(6axX=5R~bT ^R<>dvbZ\B;.?MýZ\ xر$-(Ū%m@w0 AAw=,˙޴a\owY/ΈTs#)Y S]yG,_Wp$d Wzn~[2b"rX;he=`ى{ٗ;"jB?>%wI#)3%0WH O)[:vyѝ]~镋-R\crQ++}qE_k6kM?*l^2kJf%_o>VlsE%R }~W 87}rfIw/>?HHTE [Nl_7 ZPn#c7x掎Ic8(ǕNjp)>*8,HrJ t=vh5Pvף6ڗڕh_ktw0tIotr|S+,z8 =c9|U;?Ѻxja$P%T/̢VsU:F\mKR΁oϾWM?}0FzR^ 8Y/*SX*goCIA4bM2=XjN$vѹYېN*!V\楇hB:Xt{jD]h?>kݹU6.*8' !4ӣ1~21G?Ioxm$"\Tdܧ:1 =!A9X3wD3pVJ7"ôӿS7C#_[,)h@YGh\ze** 7I Ch7Y#Y}5RlYK|SlsU6ST(H ,j +XV1qi"dyYQ.de K!l ʑ}w7`wҢsl %T/qzܺ4bѬY!{ݵAQPN6wgb^:Tr8J-;_Pʧ. nzF ./ғy,O{1`uP#3?`v{~CdQɶo5r֭X691N,V1@v*& <Pqtuݸ<;$Y'ad/'mI/V6q Mk|Bٿʵ.qa)ʉ7k Gg;~dG[gmp+֍"2%‘+P[C$Z]㽒wπ,Ҡ7FG.$G9fڒ%:6e{|v ص|D)Ou"YL^bvLw!"3#ZT :" a3h6' xxLj^AdO ,nui&@Mݾr/MUx" =NkRLj 8_9>6]aïzDŽa:}Wt.V'uZ}6e NKInZ!N{vdٝ\eu)j4#(hh'$`KbNCylLkѶO՗2mVxDIH -+wjvm%>^f+=HwǞ2E2#uiU/ nA[KK>\KER(fSZr1Cj7 I: ASNڄ4'ۃ)A $O9hM=Tx pڕuoSjVPMj!1S.h+"Z8].~^dLz x[z`했CjC;k4:%YyC@O37LB53Bu+%zAMUB+X & wVz Na ކY^"a_śͮ̋ (r1YǖqZkrLoַ,D#a J=b)GzOjӖ"Uc$⼭Z;,lVZŰVDY'rR90w4!F_hoƭkN\BQ1KTI Őt Hox;V?HݽlW+K:EFS|UwW@Fġ冑+-V$=ljf5{]/ ܣGfێ*S3/u^7߬ƙp߱M>\yC [$,9P MOmv캀';Ķ}NR򊧑 k%TΔ@Y&-6;*W)Lecar.m9ӱ3 |}׮^x~*(/K!DQ,l: !0La  Gi9(=dc5Ȓ:bxTǺ6M}!͖A R{ƀ 1Rt7-cYz.ᡁ0,A2pߣr /h+XҾVBfy/4z5vR|_Y\Ez0 Y%;V`1i2pFK/y:q*)kk/9kSRF#^ D3\tj"T=p1*¾\:͑s D ; HnDD l[fhmbF#eKXGr" aD[J]>"Q$= L\!]dmPəQh!!8x3 aءG@ܻP` $9Pe_]+Rzqe_XO`g[Q5@)铇gmQXuncBEcXO.9JDgKz*` X QN!"K~+c87>?!wOS8>Lvf+5WD\("תP|syIz lpj Ʃ%F](0V_W6̥l=skj` |ڔ,rC#h߼DQZ[QArh8Rsq$z'7ȡlT "~zڎƖfnKA=%II Zm VUtUPa-˨ Yڞ. wڎ-%.Rr26BR2FUO9;z9=CeFH!s7`YZ[`fg)+c/p넲wg-@m}%P嫘o֝GcblU^ (^?`źj;7.R IS^.dcȁ[yW`#^-ե /AfB~}hHI$Mq [s?/m[%fQ'QqS#cǀ2ڕgr7JJAP5o[Nq;a4^bpƯfRU1z s=/ǓD.Ƭo,!nRR,_j[4 x@m)H@mI em7GR=8d&?JSnO(>әƅSFrۜ_, 0 h:_FI vT? ?-U 88fy7axZ'%o\yp9>އfUdmZFdwn,o (N4֥ RGg!G;QS;E\UҎ3&o o/sRyikKrkyc!MA\j7k,uė7{Fj*EÂ^2O?% iI+8Ka]_|w$?؊C 7+)uuq=pHTYE  ZD3FW #.@hթ4S (n_m>.#;'eBA9IW#3,mT'=gOמZ4qdk אMȭaܘ!u}ڢB.`@X!z8@*f~`ҥv: 9mjeBIz=)'JưfRۛM.cZ\䗮)0l'lIL&!zQ:d\&u0t@ SfKn;3Ye% zu@,7N], /VӾt^ThRR D^,X3G<EO.<6 ߀UQjFƈNLRZ[SOܝ#x1qZYsGb`^jahq#UDx1CoЦje5oT;lAPf^=kgy.#d<=Q\UV)L7?9 L ޲dSVؗXj= qr )k{b5z8VR? @.uݫ-ϊ:l?(cFK|Uth|{WIA9]32 M%\P[Hx]+K df q<9)uW҉#;wR&4lj4vv 4Z>3WXa{G d <_\Cm}5+# 4l (hRu eDGD?16nxe 4vdʊ㓌s޸nҭh%wM:hTjTkʩR%w 0d']Yrb'_ڊG&KamNNfƦ ̄n4\|$$Y= e{ V H5N$kN J_W~ #ž%?@([%F~"H^ѹTX4J5$5 B,Ž4WcE79BC]?#&bC_D׫BdJ]WL0xK+dVW! )DzMƍ Mjsp=iĤDYv"컖g' [ ̞,=h`كMؔ`E'mPצ]#p/7X?Cux40=~AML<{Pt+hjhyŏݼ˱ |loI [d 8 @= skpGx6coy<)܁h",ТV4.B< `_ `xŵaW@iJQ|=W@xB$7B,|UkC lT< H8z8}['"Z(s迕: . 7hX4'TZv}=ѯ@JfE&.̈j\Gf3F`,iuּ\?$MU?i#5M3yK:;AU\JV>u͑7&bH%Qp$}߿@L19$EH e6ӌf뮎73>8=,1ڽ'6CzyK=Ӭk2 zTZzU@8v| BOQbX} 菙,>/ZHѤwMEi?+ZC\ftjԞH# e4+g]INP2B9BւvOgmskzL6w$wq۴O'$4ݖ:\ Mab ;pC{OԒjΉ!tN  6ξ(RwwbJcV$rD=2]n/u̪PvT tH Lg [Y5+X- D~-&)^u+ZFqM43=S#3Wa"8|Ξr0]KA)~Qjӡ"@GĖL,_˞VE~u|ՒgѣYߓ~ADKb7=7tOjQLyCZ /lTѪ(u lh $ (}aHHSE^a]o"[ëoWsȧPkWqX>,t s̓y@4ǽפlG---I1Y0269[['v|`X3g^suj'@+`NB*8(xTSIY`0k,/soP.Txa9~%x*/VL> 5'uwW-K6)X|!-aE#bNlVwl"LI`e2bGyf8GX0GwdAFƊhv?f,UsHVv1Th X$q1Ū Y>* c2gÍΏB%yҐ2sڪK$`)Gh-oPAPV^(kt!^W%qUտL#֢}<<^}9<ݠR|-sk C+;8M=?#y$ c 2/zSq7 JVH'Vׁ eQOul6ym@:LͿ6h8Fpi2v+f:2su xo[xjb~J-;Z;3Hbo8#H@pI;%y=\=M"71oz+hr ܸMbch_B1-d2wBŠՓoɢG ;4:)'JUt+vb>|y0`h.dI6ۺZكͅPT!c"E,H0B#/·hFiu_HrFQ~^l$"{c #!%35yx{(M<i? %z"6=dQ @fBEO(<`/4mqw`wO$wFX<`z_-F%~?U12_|yhBR},D溴C *KU=!9kFc[xKd%V>4(3~ j+u4҄nt]x{~nuԬ&ŻS orp>0u|ʯ8\[<'o :?c=A*zB>[Y4jWrã4@垖7z8"rdfذuF1@ oƝuNc\l1~3&MI&vFFs<_dp8*|*kb1nϳM^/*3MT V/RxUY*0D @ r`̇EH4A/{KYk)<pq .ʓ dטFU8H%Wm0(<PCw8Uhରq$#tIxurF>Q,LBfW`,4]# c7xg^l xMP^>^ҿCGtovV PnDGVѨl\q ꉑU1FIEolq7O7n}"LHø.pP+ x&j ̍3"2ך leRdDkG+z@p;v7 TGZuB8\<rKJB3D4 FΚ"T4[k C z0 )FPB5&"8 % aMckt[j?Ӊ Ұ@3/Th0;7,D6z2}  /m18kl&1wZѭ.D ygϖ^OfX n^YdnRľTdu]z\KI'v1rqY jpNcpi?7ɪ)Z{.5Ce !T>H{H  rU 8pqF-%kbฬ %'RmP\ dE%:._{-p!8 b?~>C `jNra|@N$g([h y5 Ce0KNsZ/o}^ uS:0¹:{q{\jee*4~ )jh5#'k@n_5h]7#[kTVDk=( G<(q(|G@o2D3̾BaUĆ;ugsweKC5:q3k11{Izx[^|AT)/ |gWL@p6|%]KH9eQ.yf4d-wMGA' 7.q'@Fȭ0]99a+i]He+8k*S!Z%5`{#Kh~<oe HYy):<]nqc۱R9Q'|<;>By)hOsAŸݲ4wȧ>9nI+K6PC8 u^ gըUjtl.psútU 1:Sf)bD`C&dVkB ;[ّi k Eap_{H+x CP5',TL,шdiFN)\]$  Va!#8-r1:L tP##mTΰZƩat\n.55]Ʋ6)~&PCX'קx*.{`#OX~ߔ3%췽31Vta B=ȧ~53FBDMW!2-.utVV֠uG 7J, ^ (u hc5 T^hkmPr /Iٯuf`cڤXq͛c„ E}u拌ٙp~݈TR-8@1OvU6NOUkۯ^,KvW&!7Tn3:h/JI6_7]k&NlW]<[ J6훰-Xz}c1*)9giuH-%h?-Cva8FqK?~|鯄~"/%͋aXgJ"+ ~Y1X׀p% FA/MG7F(JſfB)sTLUD8X2"bv1>L ːkKA~} ?b_0PMe*v :bUPTrY &Mx~rFX R &ն| 44~OJ|-m@m9C2A;>wv-,a rra [f\|Joa3 UZ~#XE A{!I XVs;qFzUR/.OR7B$` ƶo48Tu,Q`*4*z2)$2n qD,rUK՗3&?nJIgXPG4NUm@ifHH,Y .eչ :ʹ0(4T)TZH|꨺wL Ml۝5R[B2SgXr`C#z!*6o2i3m2"-= CjgKڮYY^p`qsҫRtxnR>SePIuAߴg-:OQֿ!y t0Y0w&k2#|5D聒a">l?=h1M,sٶy,+hGhd*76'wPM)2!R&QqnV<{\q<|(j;"H9)1DuIzIPv7t {—>tţp59ר]ȗ(T>iF5=^J-]=c~ Mjh\%q~YyhWl8 p>UcXfZw[NRHe5*eM=-1fh&PCY۝@`AD~3@5?NGz&ՄIfYWTjQ)-chٺ7z)=b;^|1Ƒ![`D'Lӂou5ݏ,3H!=1،%/Wc$^BXX~kQ2mrŠwy`'Y\΀"M`"BS~@?dV>>iO9 ,U4Gx:VLHyވf/߃^<x.Pn4!%ɠK;\5\:]K@|x +_75{ds$\jKIM5TlѐrNLPۨAƸm%WoeRRyF$@՜r>>2S5jS Zd*`"x{fS.EV+ I4Y1fu ɭ Q渽Ryz,kA d%)t@=l cgױEOj= 8'.ዟ޲(iR0!B)ݒ?Ԕ86)Ow[QI`Ɍ' ÛJ;%Iqe[ E $/_J _\O7>$x_ߋ xC#UJ# 7ѰR73Fd9ieX5IZ6a*JۤzXK~$x%DVֹXjmzpjS lI _mbg"hW-9JK24~Ï)fNL A{*`̤ DrcO!BTn*,5)2a VJYT 8bBd[.wIl_=bMJfX) ~&[8M;U2b44$B"<5Of9i0vu%e!DZʧ8 Ԏ@M/p7D q_9EgNt/Xž;!io!hQe4p\ ch4 >!GJMgE !P\O`* e)}'! x:N勹<J̱+<^zJ `nyDl /Z VagL)Gt mrAq+cvaM|g 5Uasb&)bL2f=bA qdDb!*C`cUl\_eqޝpoJ7#q&ne=!G(2|LڈaNC Enksˎ~M[JwC&0!c{=s\QD&=!a,7.NFd\V$ 0/iY:, ˃D[I2O?~&)Ǯ4 &95 WkԸ׀i[bw&Q {3WL߮bw$zm1T%P[ AU[I0| d̞[tNs\K` U],wZzzӭ:~g#_)?,MYSQ6 \ 83*BƤļ#\RfѼMNCz,FJ^ nnp's'j BdO6* hne/Pam-"KְIX[OD/^-P"IvH9o,)dD|u8`JtEVj(rs ddL2R_\ǻack_P|f.5( G_ٞկ?)`_)8ix{ gqۏ0pjFTB<P D$LY,L5YkpAv׾IH>YAx6],\2?Gפ$E'k 'dt1*K02B,vl'5QȲahJiPkhO0 03|}4~?zn*%.5XqaKg#2V] đ Kamp ң}ʀJ0) Cb66LH9ecy m\\%!Ra$j{IY)C{*&j"#Ur*BO 5)bxY<` Z+x(lqҡ~82kR>n`Ŀ݆`v'%ĢZ]" {Fp)IΏl3H]%hϝjn"EA^<@|C8wpxաns2sQDP;>T\23@fR M"O-?3=*G {42ťU\5;G"ɼ4G%JU@6'ݎ+&4@uW@L[wdחp ;ϻdߥ2[Lu; ̈́FLq({āL fYQ6o^3f(,Dky&(DvpKpϲg%u8nd%|܅ M1i-mƴMևd x{3nUeӖͫx h:2?_ď"hu>{~ /d 4QW7cB@bH@VfȠ[ՁmcEY$7dh&R}ڤr*hKgg-'$d1qDD pC-=L=#/IўgJ:&507eb@.S 3k Yf4P=];ȽP("XFoJ'ӤcçIM,x5Covuu+AkA]ЕXM$kp;`NgUw'QInS u:_ヮn'[u6ĹEPZ3I>C(p3UC+P/(}mGd+5éd/EvV([EN.$bHDshDsSpj0Z 뵛)H6v8 8ީ]"aPHG= cW q9$Fb(Ƽrh? Ow6o%6mZ'j Cw>=-qu:1m + ۛ\ReLm p+ND?"3r/dI6$ԩ}^qHp/DplN!0uՓ{ Z>t/3<: 3̔g*#hS- VD$dfw6@V`I1AT&FA+0{yWO+*:'{|}KCs<)pօIȖ=h0^Db3J{))|{k0y-~^^qͪ|||n3kEtr4*g2BScķ+'ڡr))h3NhΘO %3@ .[4\_nn]B_ ڕt'x\=O'm(}ϞU *A-$9{Ѐv{mH) 2=t ǥsY"5q*\Vf+UçF@L-R0zsQAkA`2KnqEbR[ʂDkMVǭ(M2 :g6U#r!Ԋ޻zw+児lx1U m-`",D!?3y4, ౹kF`kuvdT͝xtUyڹ20@S4*%v2(+?h?QGak';S? >opЄ$TޡNa HxD,SBE.P<h"0 3RoX;`~얢|zrٿ { :31# }`1.D?$ RYW{c X[R[..~ 1 pzg5L8#Sv ت]pO{ '5R 3=\*O6 wluǾi_| 71jNbTD%AA m\+ 8& RfL:R)6K?eUI]hP2"nc֤~A-8/mZRuR\, &4`yT]d_?Uf&@Ӆ'#SH{ I6*{gKƴ-uJ |_{TX룞m1*S}=Py`H M[;ks vJ)F@?ý,zҥXL`XNԖik4?>kbD6U7a놔 JE=,ᴟPMAY"1%¾-_C4ԏWDӆ!(XV8 -b/GRȚ\쌿@w &a!GȲMâtu݁Hu|9Ѐ^։>#"+-[lu"kc?(b]Fh f;S۳W5Dtp8¯v#|!\ނY9Lṯ"h.{+OR  8Q n9ޚX+TN[iT_nV(*0sWSGl*P0aq<R7d{Wկ (² fV7ǁC5G\Ù;LE8 Mtp"H#bܓZݸ%> -hpwz z746{yj/,/MlpvK|^[Ӱ9!O^BR·(⪯E(4X N;gYե({w h81EZn!ԯF\] Qk9 PQs\+}(Vm{\H^\O1rrI`ǮD&/?sI݂ba  vyxnk._!rj- |Kl-oE-ؤc r<2'}pE_hhyK&ҕamX(LWۙ3r ݦwc~۪le\3f6]zX9"Hm䯏!C2'7W7rBU,JI"֫ʦC%ԉg`ԲD}0 >dܗ"~u,~1OR5ɗ蜀͝Z6cX {0‚6[-1$BBD^j"X'O,Vmr #Z w,^؄{0DXF,Ns@;:n HyDӿ!È\xiL,3y[@ Э$@Alr ҏ@ oc֦B47{=S4Kx/iogbdt ubϷ|= $ĉ:O`hgH+?6?xB@`U#X 'V6` -cqPS@n` _* 9br68yiw#ʗKӱ: LqQ(mD`b-KDYŀZ_=Gs^Ԟ+#xq`Yrl%/oDe})'XdWcF (ExX l|7y2Jnrc}0!$%ۨe0KE0|rlc^ ڸb6L3e\0բ=q쇢*]*ʽDLIY %PT?4ݞ_b?p)VїH lzw1P%hcO0ʪvl\1-|Wx.V&a59S:ZAANn"-=i+;'E,U*)4؀mI|i*B炑I[-@  :ā%rp <;`ɏ hۏJXT4/w_0C UE_ RfdY Rˌq]q(8ݨTY6_+&) #,>gQ a#hFt|yVDpI"α|a#!AYu[ Y*ӕ akT.@C}~2hXbrrA#3Oy? d7bYc*Mr{;Rie`8Ue|&(a2%%ZH*Z+?='h=< -ip. m%\yphX Dp 74fs:+Fd>By՚$1[&k>$q' $C(zMNj8?ރ[L6$ԢcNdtU/Unb'|@D0= ttN8()qcQg8-.; zؒq[n Q[N+ @k9r x:V,g׊,(cSv&x;HhMJoBxT>"r`nosL_g{ h"I(LI`mRH ?tT|!JTP08 TP~( ȆA٧%* YZ/+zD6py6t7 Hboe51v8=/6`-~΍d; /ޥfY<~yf*5iʠOªrO2 ]GrTi%KB,H|l f8i90ixpa7fDlY sɷ? ."g@n)/v{BUM a"wQ9 ̠$==@VM:@2(_ Iю {.neU殱0 '?B͡Hy"BD 4Ux4&Q)N6 u_(TX2W~پ~3T{|:v.rZ O!wKXl{p#;7 sw=ZtŃ _ |D R-n4!^_QNT7tRd1xX(zƮPDc.L`pjx;8uk`kV D]oҀ1eJ` m_qфsx]~4#7E 8o )Y@L`)wvPLu;JؠZϿ|el7%'08Eg]Ij/̗30&jH  IS<^&v%M!ҥ"0+qNF h/K.7,S$i &c Msku5<`@\b1r;DmOhLtg)d&cldEjDiҌH16Ӥ8e߹_LS `+3Ƭݠ!=:.IQ V;^An&l}~EO<)kD=1mc`.% $?RђS^13Yӣ~Q'UZ Dو:l ;fE4ar!1xJ=H V97K`/rgbxL_N燀2]t/CxGkk/^eJE΅lT[3!wco_0܀@lQ"mQ;U3,M[㡉-G٫ތPlyx#MJ!aݜH 䕰7#`"g/^P5%,E倄flԐyrrFc+d1l],xR92T{EPHtcF>:`U ] B+Z9 D4Զ }/{Ȧ2:H8:iџP"hW.k]xӦIbY$XX ?xRɹ!gn'WVlJ< 9 \]pY: *Cñdpqb$!K#IpcD'3$Lx (d:S s}7[2JC9 kɴSͭ2ȋq̗2N6 hLn= Y88eIF N_gL1Ptuiv g^Z"ăf xp_!><՟dxU GK\+6V"匥<o!rm %yhȕo@e;m\\yѸ)ޚTUe&ģ tt1GKhBxSd#v\.ߟseuH!2@s%iLMYyC4/5eрK 9M;㠡:uň G>+VUa7V#t4\~wwpzLeE8 M E#1ƅ(^@nh)Tԧ)Jօ6!o~f0v8i{ iO RQ*,Jbb0P/bp$^Dr w'CsFHz} }o.pCP%lD!gB (`^Nrz3TLhH8 } l>&&$6ޢ< QN}uPD ' 6\>'JXA ~(vU+WYmQj؆)Wz}jRa$qEMw8:Fڅ; WE8Cd9#ǃKK(y<$@xLmPZ }mLTc^ ^z),/s: Mt hπjM x73R3uHԬUjpS.vSeVtkzBe7coC;eߐk8$LR@Y`NP0y 5}PAnCx?PKfXōWY`h{汀hx0Ϣ7*nE\,U/*:5{/~Q,x? @kRG| #h ww8CnE/:Q"4$8. |oQ⫙(3-zUVViIdEvb < ,Aq1Ud m-.ν$&b im8|ǭD߯+:XKPPE;nkPn)dkp g]B3&ZE)E'Ee$sd봇VIoB/xy<.,MUspڎU]xvE`jƎx]<5#b.7{X1ۅN[_7?MϢj7@l;^dGX7+e$_ q"$F0 ĸ|I?QYPHU#νP%õ[& [p@K7u{DrU][g1UF9|ԝ c,f"oܤ_GMWBN7Zt>gl9v/TrS\C )).]@^ < &(oi }Nҫ itnW~(G4OƠF=Q"+E `w,\|Th%SyX$Wk^5u%b=xqb*!^s$+r@^, ބP.E?/-}wS\YGدGW&u<<LRm*.^*oB1IXJl@ @8UX3u&'mPd{Drkر2>1agcHHL>NBdd`@ջZ0y؂qi< tx#.`+}ˉ4\:4ec#iTfe]ԙB73q =^5nrSd8-NJ ~4LN@bT$h7c)w;g%Fz7v{)[p,p9OpW}7+L%r+ [6Pҍcr6'45eP2}17,Ͷ`,v Tw_iFHNH{2em pȶKY%a_&$]83:[1 d9Hgݩh  ^}2V)쐅db:}c}^;y>{xmU(ImԈr(  .$53/ `xZ f, zd#>Zot}0 kkޚS)+_kUEU&2[mB{R9>@U%3=OTtZj!)t$đGcA>9ōoY헣22W_Q3!zzg@o~9pX $eX! $%e.t󭣊Q`ϵP`ldFq!3hI&L,k7-:F*-<SSf#(Mn ov?o.,֘m&DӇ1 cr ps5=478,[X]5q152s3؍5-oD& Mrx lϞ>So0 oZM <i.}N1n 0* |iB>ַՍV%s$Ut!)vے'Ȃ>ָ&Z|՗6.mg}¬{k<[4X@ =<[[btZIb%l.60\'{@?/Dy5K •;W{ .n`|WJ#[ )SI h_HJzRKѦLmja|mܰEF Ox,aF'tYNS|4"+CԚޚOf { Y*>@ H'pj#3gF*3/$(" qN319]8pG[}3-6_rΌ~E0#} 耟xv$ ˴\BS3l@2KߵV2Gd#Gş@Ow# B\H|gⒿxDWV蔘dx4f" 6}r^>8pJ;[e_`Ǹɭ&.EiUI_j00sik&uϰqy4f$Dj0;}`>h5ۘ,do`)k$$z wͶ_:Z<PL9_p.(DX>lJ~B$/<{4@xEaLza)Oʼn.@+4U-O@pg $з %G4Ct:9=dm-Y)_uaHud4526HX2Nm q}r#&[lD ?·grM$AVBI:6qxO\IpfeRd|E|z.׫qZ_7L85ҦyB{ \!JG1yo7{ HL~ sP%7Vh0]L5UoP 0y̦^rX: @do4Rs^|;qeXv1&d#JPˎМ𵹀W\۫6>Sm# Y ؒ}^OĢ = iPP1̲8gaFNإ}J@>`.]XH[lIVsfc;@ҷ*[HP(p(4xgCILqэkaxkK3D#: ęV~Ӎƚ|xl L]f<g`spJI|^'iS Yx)Bsz/UudI ؀(uS/-JyMfWS[_da#cx_ZEe'+]]eNh7ҡ}? Gt)Cd}a;X ۈ f K8.SdP)53ūO{`1CSGAx-pI>,DjCpac)]=kw+8`!ڋb=>_+$Oʠf x.,UST!uHgoCa1x$Ӭ \WK@cU#`ttC Nk%HIJ-M^!\}^e"ND@zN4|Xr\ d,DXڮU#kL=|frV s۳~yDx+OH0e#a6!``<Ā>vy:A\$ 8:;œH@ß<7t:J a Ѯ!$@oEIL /l M͝>|_q2gxϵzZ|R>ftL/3>EBMwJԥ^mNPUDeLDSqJ#k, n(%KѤ<.jѾeC?G03M>^jVTS1u:%XBQdtIUZt%`-QX7 M-E,+SIb۷/cDwobu]5nǿr=(qa",A04`ҡ]A>g [uw@%L{lS9B=>L P ##xo^B/W? "M`(G!|N]p6}5}y0su1_uVBɊ1Ó{v; BJ<2 :pC+^kW|rMb(( h1I $ BR=A?n4]70 x\3V/5b=vq-i $a8e\;r<,L4(  ]'˜ƪ9<u@0\EcNXR6m6(UM3̇sʭv.Ѻ p7X |gS cGpwLr v. ,zQB|l ^TpFW } 8f ZqQv 8KԢ2x.% &xZkpN討]VHQDy|w&;\2V}jA=ʶ@mÛ*YB* $cm HMc EҼ=B[XT 7[F%ꑶ L(>cwh#h Pفk|f[9R7 [=1$rG xŰ'NI rP2I}j(7,4ƼfX7L{@3|3pޕ3i>='<{mϱgvPy+vIbk Dآk 8Ch KeNF^9Np@loJ{3W(3m8qD; `ք_|T G&@=xi:RL 0`\b%h9X D!3<rL/DpjUjt΁I VoxjhdatŻ7tn5\A.B(=hƺ *q"yw,M +bt#,شd¦cdW8n&]"4\H7I>U5 _9ƈ o7WW>E3"h\% ?䵙e/64 ʼAbˈq40_*WXq/J'~u/\6 e_OzyqQpjiJL9x7#t;7UQh|@1Ch?VP9pB*viCk &a`n~o*"& +>PTDXދGt2(>":P/](hD ʍ~Yp@<I 3Dx1OA l404dyfooW MDI ZMlA̚<`@";/+P#c[y3J-Txf+-$BA1]E,3\dcjdDDdtJ+ k4$H3@(O( i\Xz%tԥl,G~[T?,E0 (ck| [~YhV:t(-n|A coڙLD eܤanzL@n/m+#=U"\}(=12UB Pj{1c d+|2 #uusES$Ti0` F\E@NE@B{j\=0!AiRz O(R+~RjLMǺDrY4&y_}na8KW]lX&3WP?L0_dUZdD"@R$v\G~8:ߪL T/-ԐϱM8;=ywP*Z t +TWLW)(%[H64a<~RG ,S܆pLߪf8>P0ѭmT9HڃD/n}˜liv7Wyg&D#bKGp'T}Zl*EL50d$k_wn4M"A\ ZPuX4}9pHٺWŽEB HaTqh TC.`@2 Az3^[NEJy)ιAX){um(TrBMԩyhĆ0 B΅&)ӎ^ndpbRM]5\5eCzOn" &}#/G\H_2p'ƚ^;"s(DAxt18ʚ+\&%I`J]T$Yd8[Y.1Z J5l#AsF)"K%/Ys Ń!vsU`(Odmk9Z<  #F96`>2JT*:o7ns#1Yw@80[AL3qCSQOF["Zȸ~g ˩*"YtC8H3[Z\^K()'<2 !$R샘_V_eN`gL!fs` 1-uLuth}|4J0F` 0 lV \f|0K5@]Eq>ra1g. B.jXu n^:Ε|fN9f- H lX[scN|F% rgGbc m tx- h"`he$l`; EZ~zbW59~Ķt`LvmL:o F%]&49dx"n,돎[B)38&PF=P9ˢCrm\gYwøt*k$/,QBP}Eᬯ,a]K{G^I%AqژAgxj{&/P 1 n$Ԣ:" 7^ D]_ |cXb[XjV1o@ "\3LG@gV2_r:.afo0Ū ~=c GxLܻ *FŴv'WjtFfmE9\IcشjZ-DaQ/~P==Kk}\qyYq7B񤍗&7,ʃt&Ef9ڻ8/Mpݼ$sĠBȞLI2׼w)N ~To2“j4$!E\9un4> չRrip}-qW t84D\ԑhLDIIFXts.(AiѶ%0U-ٺt4Ϭ9ZBӝpt9U=$>`3; )x~1/xO0<P_grirl@= @~/*W %-cyu,Hp__0t,ex -1$ǝ YR9d;qT"X.wMwZZS|  !Zڇ嘄J]a[)! Qa<.3zr0=[bMHwj^9+mq£r9DC1p$Eb $ΤnDIߦNBVYZED S5ojQN9A(L DUyADHrv{gkqq IJ\Gg6Q,(O!k4|>!o" VmO^{< ZtD[ W8" _ 7v Lz&@udٝF'@Rؕ2*zٌ`z@N<T,iOut& @];<,~#P=\׳< 0>)u;ࣜb${33o dXo5 pqə'38}W|$,BCTݍV|<Ć lKE ߶>SN? uv Tz\o-O $ixdL #0W1v$2P!?Аauoh6tCTG"U\,#8:u/##.x9Քq3tdݨM8Z~\5ra$b0>pj ymJḯé\v 1%Cl|c;.Vca_r0!L֡ {LEۂp@?nùN l{,^۪֋&9*_u [ , C,;W% ??K.[roku){-o(ph#HPDS\hN 1! < ;iv%G@/pL&[Ilueb1OdJ.me2Pt?2ޫ LhP*Fv';j3 *pm5>(pq {\ԯ+= 8M@X$_lL<<gj q?p5<D2;b `8ڂ!rKZ s<@o@~ &Wly15z;iU,^,kohJ!͠pJ hyQ#;#KB Ai 'u1;D@5$zN\(0T)wC.']vXVm@fŏRx;=a`3O#=M3KC!83-q Tf#Pj sNXhQ/ixV"deHl%HB"]m}f}WY^do愫F P>n48e_ܻU 8Vu>_(; :P2"% R = ,z7b ԒνZ! .%~6|7,2K!_vUUw R(]bp| d}K6-B3==)814ưPaFPI{)A^5(;[531@6 ([^1Ӿ*>ipfcn8 ~3ޣX8TX/wy:^:\6ia (>Yh-<`? ԕtL7΄e !W0igi!Hqe~nApcb]| VBs=^hX2(@0 d4@ X0;j,|,̓ՄYGsȤ4_{5 \,@8$)(1,6U%sytFx2Z_p@oՌ2SlZRzCK,]D_E%p{V #=8J}(pGwa1=~ dǫW}HMj1 r:ą'NkX\E%. 81#58 mUx vWD]P_bbTzjdyQ#$rlͭy^T^'F$|<*?6րc <>Y_AB{BR`}Sc}J>U.,3}O,"H!:Yw ihU2vIVZ2\->)`y4g|hosһ\u9:ߵ!pR\7p\f/ o>gk"> Q=y# @]HY7;dn41lb|^F[,6io^L/ca<Zd.3Ȝ츝+a60LzNBcEYņ1sW|:0z1h2^(e6I5|lU83WϢ kW7W% dmx,H;">גj^2}('n78,6[/Kh ǧp]./,ZKpY Thy {\(3M;iZCBk{hϠ츣-f"*;*㥳҇A{7K='iQӹ.=]\ 6z y(  J3ugwD >um_[SzASCNc\Mu[#h!9ahPܣKqڴpw8;wOu_h̘Gm4}*ԤL*DcVK# ?4NP.X񡕷ߡSkYBĸ@yb:PO0t;QOl C)xv_c0+W N:$azR+ V60q@MJ{41u`KM*縝!btejok,~DA!GuoC0$vg?zH679a!z0Ɛ7j{y䠮Wݫ/b, a љflV*~̝441Î,i{ iA{{}f_(VȻ~3E:,H3uVO> a\20H$ K z2"8bI28dLG@8WA7UD3L2]IȀZ& @&lp-2.J||;\=c<a7Wʮc4-Bj"RνxYxdp<#N0`PbGITjT"C V/~ʟk0^u86[0:nE"P:~뛫wm%P^:HW,0vPa'cKn8)TxsOW̧yn1ٕNf`伊 Hx/t0UӔ2F5XRǁQrFY0j:S334ufc4cv%nDQYk>EZA t#sGJ?pUg7& O%aFf[˒d>DͲ7a]%T/Hh& yi*K#Ut!,i|厉ȥ8Q_X8 =/Czc(|hɮbcr)f4 H+O*(ּiNBcEg̀#>Dmz ZZ; X X~*`y=x $1Q0F'Ys}n\ ȟr K9c Xpqھ;Tp]cU@ G40VxQEy-Z a^OL}^ kz%BpX}ζ8څ6(Xy¤ ~A˴ lKT/$kڭanM5ʙwFqkB f#hd9B766>i>e. 5{`=B|L8{J`Eh)AhM- ,LF ȦsOUT̸C-xa^iZ?'2$Bn nKD x:#@ (D"+3Rt&a`Y/ (;rsCQDi. CE7[wlo$:p ?D`N'vA`PC,OPP(7Ȝ –?i_l4`RH}cУKVL2&:(1 "f iQ G+41m'+*7} WL09C ||%^p쵝6 {5KOO5L,{Ki}=lrZn̙ 9mx@K̓,lNJ-E g%!pܖF_;ZwĈS/]PO*Ɓ\]j~Ħ}[eIeT|_a*|fG@L 捰`<1$ T7acD#g.e|t`|J9y$0_Hl'*zH"~zZQ0P }z%l.v 02 PLd{n v(ƕO`>WMĊo:NEcNۄ-lĔ\?DbdzФ,]&/T1oFIxwx#Ĉ9{,n<([ _3p ex6 $@u op3j=2 eKBP-S k/K-83A\CY N#HT69¦FK{۱XHv}Ag_ZWEC\ nGD߁ ,<< E-CۭTv⻎MS^LHāM?7 zӱgWQs%vnPD[r}*sv_,!ȶc+py5N  Ur1e\^K,cwHi9Pg6,A70O'f+%肐(2>Gфsź @aa LY=gɒnϲZd"Q:zjllնrwuY >LYV\59p$GtD0I8rؐ ߲9bXZgg1HT }+ Jq+H`D}ηV\zs){L8extOB{4!phW`F(~X_V qt%{so S(Y$o@,Z"` ~m[xUl3[[E%:_׶o A*`[GgTq_1 !/puJd0NKRpb9IF H pr -,gG]b5asp7~5A IDphhKRLsDŽzit^ET]Y ǎG\)hhG\gx&H,;9lw(l};1}+;V,ڵ2I|E֝12>͕;1%݋p8 .U^<*A|;(5gD*5Z$ ,c \0/ 5a"VMA_m x[`shpe\guN6$iZ{+2&n/̈́niUP'j6,9O_ާ)C0xXJ _ ;fL^|s $ M "6␨y(hAc舰@",mHy4 CaJ:?\qdO,1Pd19Aɻo8ɦ >[EZ$N7! ۺoDO{i_`vaqJn r7CGCe&(uSF >RO t= 7RH*$N{9#*gbq|0wr:wS<kup4<)dL*]*(w|D qm qE` |_d|,"yDXwݨd=M6Ld|ed ԩ?6c$T{l"4Y: /:v~(șUvFD9SgޟBZtL<&C<8 ifu ҢLf_=>y4) ی2~?qNI/*~BJ;Q)T>:(G,+ <ҷWLMdzC Xc%8`oL`րzҟ |*K%,5ViKƎ X'̠ 6(v8. n@ rlNB @vLqI^b47/ncX>!edh 3G xH@ bHOFPS5rE LSxj{~O;ph$PadO#Lјm:6x"R@H%{~+"A ABmJצ ~D 3Chv;<g&RtNRpZE|iʁ ;VK.E%Gl<_9b و&Ex?īFm "(@W׶4o_(xTO,)G7:glp:Ы"1&F $zcxqW]8̮*]Ul>-T}Ģӱ}$l?OL+cuqil 3.!7Kf}H/{Fvƶ`z53-Yv~LBEl=.c?ٙxb8}=mdֹ}ʏHYg פJ{`0΃#kɒ+\} % e~$ ,Њ c1GP& L \38;0K50Thk lx\Q6K`fh˜?f*[Al}9d,/9O6,08c5ep4Yay؉T0`x(;Ïwē<lԛ @v]zcxL$*<O0*ME2kJ!q:D5ɡR!ЎϺnZ?k@T[Rr^OzPS : ?! 4d) brIBΨ(Þjt4I4تӹzr&O1 kE փ3DL xgՆc$~qkR{x0g˛/IS%@ !BB?3'zUD=8K.[^-%l_0 %d dcBq(:!M#NDBYTj>:h`1ĤZ t).3bI8A i~8< wHS,O#@\J$@^H#lN,KA@|tɼmqH ^Y&h ^_ٍ,֟J-ŠwM0u)$)4K<kMZeeiS`CMyu#n/ee 7\Q7K7!%UmeQXh7!j/`2*Z+ڙHe3MLɺx1H٬.+ey&Ng]fPъ.U#hy  ΂ 30dzs/0= u 0RuOX ׭.HRfbU.ao~1FN#=(:) ƥ4 r[_f1p٧X1tRl!ԛXW񤌾i<ך.М3y$tҡ;ԗYڡ kcsEGq)^-JEZV7 x[#9_Ȅ\tTVB?IO?Bv%$HKxjDP|'oC)fw=fb W'a 06͠qc2=v-hkl:(nyJ -L::B}A MB౶**5@eL0dC^pj2 Gmu *o &yfZ;!=2q[*eKi3hY$2B:y=w y I1\?_=| @~sr%KMuxt cYZ n#=xǐ֓RM˨YW4 jdB33k|:ǘ4vr\ܞb:H$K:$9XJi0ѻ` @yO~x=f$ȲK8ps:3Ii{V3StnRiEM$W2ѱL|37PkBX-\C@958>ip0\;mӝq'-/-ϟ$!ΐTXn_|im xu $|BU=|F,/-p%=Y,iTJ78 `Dd1SU4 0' ,%Aa.&Zl,M?@u'bg8w(+ _I7ٟ܀pS\\rr TWYZ7~L.f01Dh'.V9Q,>v2Fb[n@ QPxUPw, , 3c@8h\i>KJ_q!lQ'{JY /1 _f~ Mo5RLmXjGٌ J­@dk!= 㣣O8To; `dTV]Iv榇"M`3+ &,' Z])mUz>Akzt UOB]/qRGG-nw? ~W,g/@TSVZg*aG>5# Lܑ~ { 4 Y}J6B@ |_Y&,9X0[3oQ/ W:VַFI.Ii:sZ~W崑%3v#}KǕb]VQ7}+~(ma>0>OLj-.»8T;y? NV% hjI!j#k q2mZ;88K3W_>ݻYհռe㸶.tҖb{&'C,^Ymد;>Hy9յ%`j\300r/ͤCIqMx#4jŘr18mᐢOla ub%S^nk$670h6OQv@?QU+;X>Hhmäp$\ |_l7B0"P`:lQ-k~5LU_͑jp wD,뗝sF֬8?p[gGXYi se9L'DS79Ц9Qhġ#஛BDh[Jl{ԭ ~k`M}/ )%9I|(hl?# N^P^W=Cx N|U6KGp1p7,aBQUqoz`]&9ۯ$ScMuxl2K"SM\Fmh}N+VIp'!n[@t*sQmB"3q"+sΡ8#8'#faXj Ld|] u$4-|^X'lweֿ=WW)}8 S+tiS!W t:HD5QK.D%UHA e5acnn(ibؚ 㮀v?sϐ!Ҍ~evYV))կ%n@fz-\ʍ\s)C{JiNYTJhRU9A p0wS<ў |s$P.`3CIt)}p5ea3/8;=P$dtl +cZd,m~:CpPnӭX ; *\lnxZ$mDUQYܿ;PTص'o^}1->4ؙc5?s+x0p8u%U^iԞ%@.W]5\srN8ED]n.(;2,M@4]Ƒ. S`jӽ'4k!`=JE[3WUhBR2czw$T.(α'$ x0ԪNU@pdo'|@#RHc875*]{h8 71u<;;} @vJg;@|/=3(ڼP¶(\wZ_+3g`/@$R3 S4 _eb&|'{1F+HQ)'TdSHn3*vmKˍb̨Q& ESAbPwۓ-Mno:~|ahYxc41 `ic&m}[Cv\%; H^ :gR{p$ Hț.ب63ci&*P =KE/M,^ub8ۯ~aIvM!:4X%Gz]Gv7m\eß}-ԧ\Jk7pҊ|~;DW²(Mf>;AY晹clnAQ _+nc%9m"zto=Gb%'Ѐāu9Hoh 3 Fv$8_* X)^do%$;(EH 3% χk]|#1 (9_Gv-l3h9 = RۃA$R;cD"/YXiwEk!V{pN=mQ]_9Wy{;r[}$P H,|fQwG?l. - HEpܠZ3*fhxi| RDYk"Xs$랏iʨ 0f lOSQRu*J 7_V`^Jo26Eh8=a(z}Qt*QyTҎ&8041J7u_'$ XVV׶?3y?̟>?O????ϟy??ϟ??'<3??O>I??Ny||??C3'?????????????g|????s?|g?yg????|ϟ???'?'????9????sϟ>?'Oy?4uYl??93??>?ϟ?y3???O?y?????9?93???<<3O???<9ϓ???9?~O??g?~?ϞNO'Cɟϓsϟ9?g'??|?ϙ?'?3|?'?????yϟ?g?9?|?gg??>|~sy?|?Cs|??N̟?3g???>sg?L??3O?3y???>3ϟ?'33?~||g???O?|gg~gg?ϟ?g>sϓ9?L><??g??<~?<?'3??g?XYw??gϟ?|?s??y??2gg???????ɟ??s>|?9???3?? ?s|???93???????<O?fss??>?~g??'g???~g???3g?3??ϟ??s Yy???s?9ϟϟ9<?|???9??|>~Ϝ?yg?3???f3>??''???|?'????$??'>'?'9??9?9|y'|??|@O?<|??>3s??&~3???????<~r'??s~???'???s3ϟ??ϙ?9?|'?N<??Y~???O??'<?????O???9?????|''~?y???3>????s?????9??93?ϟ?y3???O?y????????<<3O???<9ϓ???9?~O??Cg?<3'?9gy?s?~'?y??9y>?>O???3?9?y|'s?<9O?Ϟ|9?~?g?3???zY T?y??<>yIg9<3??>|?gg??>|~s?'???f??'O>?>s3<?L??3O???s???ɟ???y<????y?9g??s<=Y ]&gO??|ys??g9?>~gO?~????|gg~gg??ϟ?>sϓ9?L><??g??<~?<?'&Y Z???y??r??gϟ?|?s??y??2g~?9~y?yO?g?'O<s's????O̓?$??9~?>???|||9??=Y O33y?99ϟy???3s<'?????~<'s???????g??ϟ????9?O?ɟ??>?9??'??'?y??y??9??39gsϟ'??|?ssO<3'??3???yϟd~?yϟ??3???~??O@1Y H?'?????>Ny?<N??~?Oys3?3ϟg???>s?>9?ssy|~???9?s'???~O9????'??|ϟ?|?II?D<<O?<|??>3s??&~3???9??<~r'??s~???'???s3ϟ??ϙ?9*YA???|'???3?sO?s???????9>??s????9<'??$?????ϟy??ϟ??'<3@?????~?|9>s~?9ϟϟs??????3?g?'?????9?????g>s|~|???~sO3kYF?g9?<???~g?|y?>3?'g?OO??3??ϓs?>g?y???'??|<3????gyϟ?|'Oɟϓsϟ9?g'??|?ϙ?'?3|?'???ϟsO'gL?Oy????ϟ???>yϟ?g?9?O??|y??<>yIg9<3??>|?gg??>|~s?>s3<9?s~??$3y???>3ϟ?'3Y'y3?~~gO?~????|?3ϓ?9??>L??93????'??s?C~?<?'3??g?ϟN???????f????g?????$s???y?~?93>y?ϟ????$???9?f~?????'~????'|?'3yy>??ϟ??><?3<'y<~>g?>3|>|?????|???|?fg???|?ssO?9???3????s?9ϟϟ9<?|???9??|>~?|ϟϟ~'?3??g?<~O???|?'????$??'???<<O?<|??>332g>????9??<~r'??s~???'???sY?|?II???|'???3?sO?s???????'O??>?s????9<'??$?????ϟy?93ϟ??ϙ?9?|'?N<???????3OI????O???3?g?'|?yO9ϟy~'?O?D|~|???~sO3?33O9>?s?9???r??s~rs?rs??'|?'?????|?Y?9?~||?>s$??????3>I????s~~~~s?|9?~?g?3??????s|???>?'???f??'O>?>s3<9?s~??$3y???>i Y#'~yy?????g??O?9??g?ϙ?y???>y?|?9O|?????????>?'?<>?~?ϟ????'??O@3ϟ?'33?~||g???O?|gsϓ9?L|Y$33??ɟy??????y??r??gϟ?|?s~s?9?>~y&>|?O??~|?y??~?'??????ɟ??~?9~y?yO?g??~???O?NY-?s??9?f~??y332?'????'|?'3yy>?y??3'??ϟ9?????9?ϟ???ϟ?'?ϟ?pY*???ϟ?rg&|??Or>??Oys3?3ϟg???>s?>9?ssyOϟ|?????|ϟ??>O9?s?|??O????9??~O39???gg3Y?9???ϟ????39???9?????<?9???????9>?3y?̟>?Oϟs???'???s3ϟ??ϙ?9?|'?N<???????3Oϟs??????3?g?'|?yO9ϟy~'?????3?>s9O̜??'?3~gO?y9?'?9??3~ϟ???O?s?g?sLy?????<|@y?'??9??y?y9?????39??<g?<3'?9gy?sg'??>gO?3??9?y|'s?<9SY1??~>O?9?~||?>s$??????3>I??C>?9ɟϟ??y?yϟ'??>?~?3????|0|??N̟?3g???>sg?L??3O???s???Y6'??s??|ϟg~gg?ϟ?g3??>OY ?Oy????d3??ɟy??????y??r??gϟ????|3?~s?9?>~y&>|?O??~|?y??~?'???@?9??>L??93?~?9~y?<~g???~???O????|||9???'??'?y??y??9?|>|?????|???|?fg????????9>3'??3???yY"?9???3????sϟ??'|sgg3|ϟϟ~'?3??g?<~O???|?Bg??'g???~g???3g?3??ϟ??s???????????????ϟ?|ɟ??<?y?y#jUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUPTUU*UUUtTUWҪUU]UUURUUU]UU]RꪪuҪWUUUUU]UUUUWUUUUUUwUUtUUjUUUUtUUrҪuUUUUUUURUUUT]UU\uUʾUWʪUUUUrꪪUU]U)URRUUUUU%UTUUUUUWUUUUU*.UUUUVUU]UjUUUU]U*UU*UW*uUU]URUW]UTUUUJUU]jU*U.ꪪUU]UUUUP././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/silence-44-s.mp30000664000175000017500000004000014035600052016775 0ustar00nicknickID3 TIT2 SilenceTPE1 pimanjzigTRCK02/10TALBQuod Libet Test DataTDRC2004TCON SilenceTIT1 SilenceTLEN3000du=@"`1 @?˼N(|rrDO xKإ2Mw3ŕQv. sR܄$dyA 0#4` ADYa ^O-c7 EbJ!SwukrA%5:=ʹjw0l%RPn@MD] uؕd oA` 0= [[6mes| !)V+ -.Xڤ4ϹR[" !mdj0< =|TVYrK>͎pu1D{-eRa7tfTb)JT*vdkB@0=`PTdZOz SGm=F*=)2gK̘Y +ci7bpynd dA@ `00aU^!62z)}H:]X7NqUlλcjk)h{ech辅*kTd(jA@ 08 {T:TVuw0QlKJ48'ދ}D9<!cW=vEFbJd/z 09 \E7i*of81CQIxD1,Q,<_/m u,V)JȆݕZkU d6SB@ 07 o*ikP)U1u(1wR+TQԠt뻋<޻ j29N؄[Jd>lB`` 5  صĨ3`:4\ȴ"bY Ӟ"0-d/uҥmguΔB(tndEyA 0#4 HG*P̿b7xxrmCMMm*̺t A"(BT.?8EdK`@ : Hm~˩2 NPrYЪ1E叼XRZa饔ƠmV߲-C8غdQz @0P@8 In͠*Y#V$.9sgnF̛?ԺbR\Vko*U(VIi{dXXA@ `0/ ,`rј MvX*<>YLzJ1ץ/;  ]&up+C dbz@@t: :D\=XYzSsWN}x^w]!F U̐FY׭$FЁte Q;1F!-UPYoLdgtA 4 j6VӔ*{۟8^(rm&^HXRFKA"Դð"j#:* dmv 02`̯ar-Xʱ+84ΕT1XqǸQs醘–ݩKe+ ]S*cRduuA@ "- |AuOހom61WϨp9 Xѵ9}$KS<Ӹ啇Bd|`@ 05 iud5'2haµ2$!/&p4  vZc9frdf@ ;`@M93bRqό]͹(u2"*+bխǘ?C\(tsKըV6']9[h;s=PdqA  .`B2ELv6dgA  #&< (krqt))G yN Jlz C)Ňʹ3*79xdrA@3 h(Uƚ,r ET7_۰}L)!!I;Ifw=p^S _do0-amWIn qѭ =gy+0V̪'L9 (ֵHsoZkklh0,T>d@#A9`Y̎\fmy$'@WHbFbVyၢڌqel) g jdcB(G`@z'8jF@, ZY&&BrVI킡g?]}vwo:-[8VJd A`? @1i2iy/9q]UB Lː8bF@SX2r˫w~xyd C`wlx:iL)_d(fcSIKi&=A׳mR_|(ed@B<@?`@t ;L&jVy#3|2mbb6STÙ vm <e(d6>*Ld B\@Hx('p( i^ZÝNF 95 ^A)xf.pnJk*X|ukh}&dj  #P`H`@?l5=F93/`tIi&4͇aQr__{Pd  #8A`4`,1{o:+ile.Yn B)VdV2R.y˸^X-sgʿQd`A:`krFRN;vuHe8C-6*IlxH<+lqL|貔p9rKd@7#$ E`@;}LPF͇ cLcZFVS:Vޛ :4*&⬏m@d@` C`.]P iUM2sT0q  i00+&ctdC4dYhQ" d@B G`Feڻ̿UU |[,aRmj"l 2<7H[2w2Ċ<uJd@@ #8I @N*Ne<}^qG_Q./My};(Bs.&Rd~@ 8N c]Zx)jm6Dle(At: w)SEt4\95h{uOAQ !dmA #8hH @ :IgނYY;* }ܶlIr.;Ww{F=/ =MCdA  #$ I @eG&/j7 (ʚ_](y9 b(.hRS⡋ k>,FXjqPldA 0TJ @&Tִw&igE2l]Hkuu%ԉ45Լx,Yd` "F @NJ(ʞPmUF@*vJC7wl;x`v'.X"eg81d@"8D @.o&Sdɭ"+]"'סyh ...lP)C>AXSjHtXdA#&B$F`@!aκ^Y%ϵC([uB7kCb]Ej)Zy iA&=*+isOd~ DI @R<6N-/ۀ;,?'jYMʃBBŦ^OJViMdA0\J qnat9B QzU .*4Ir9X(Y_ed`  @E s-^8ysK!qVd:@(BR)`7,s8Caf%&\M ҙd@cB$<`R[O*Y+T9<v)iWj+nyuk1朗k8;,kv}?9_ldA $E r>Ol]ڹ~ *zXA׵.JE񖔧LBjԊm,L> G{zM37d}@ p`M`"o㯘wș6sz}ۈ Kf( SIsݼ`vlYA&P]UE.d`#&@ mF m|MmQ7R;A-EkDEڻ5[tjwShCbI8_BdA B @D`@s+;)3gӭD o\kxFaeE`PjtikFiJr hqqZUdAP`J @\t-{onAŚ[Zzw])SL"0_:y?RƤpo%owxRid (@@ ;o-)dy2U zBfQ ԲH׹'Զ0,fG6R̙TTR7d@ BDH @9 0vPW6ANufm( r-x5ZuY#nʽ̎b@dA@ `8L`@၃dbD-|r$$XJP-Yȓ29>IT7bkȏ)J:ud@@$I jA/._Z0XY\J5*ck qΕk73}MUߺǨQ X duA A@H`@=k!g\/d,fg19ԭ ׿td"B @H @/Mc2G~M Pj]4iu`pAPB]1/75AR%Qހ<xUdpA @p@L` pv8b*ӲyÈ NCOϣRc;ooAԤ}8sg^Xj_dA #`?`@#i2Vt2KڅYas$Aık9ʠ)g/0wG_5ta c6d@#B$`F`@U!.=j]| w8[e)l^lIDpUUrӣ+Uѭ35e)r76<d "E @yOm?۟wMwYP*w\Bv1BRPT pe\(ME{AZϩd*d}@B<H@hO05ZT*koSu(9E o˭&{aً9MOoȻed HL @޻?EP r/ hSc' :v)S6ruo ȊВP@FF]ιH@5d@ (F 6*1X)P `:cj 4yuB ,6dOPTmOMd"B E RZ5Iy Ϥ ru 4"+B$vAJ'O -a]DlXmwaN89fLd A`: cѡqd:s+[7`N˿/g/MXg;! * ldP8Yd@h"8E`ަ8XAC,"= ^f\ܙ܌BqN!wDS/spㅫ/!>ǰSmdxA <@> @ߛȂg~ԗul~Vd?d|V*d4\2|W$adB8I v|ԑV5A\v ډ׋eTdJKOMA¬G^̟^dcz1KH=xH ^%PY0.Th` 6xadA`08 EpjDJ < kJ5#nSd)[G; aT1F_6>͸8{㥍WK2OP6A ), 5Kd 0HJ @DYH,츹p -$=4`|v OuI$6J_zQ}_є_[dyAD`K @QozV:ySԀ]NǏ̋r9IiVMM}=Ġ23[ޔS?d 4`>`:wyIM6M ($ P{A* y1h) 6)1yKRdAbTC @l ClU;onTF;E=oRt[h8"1dyA  T+dG @.|ݯخ"s>oQ%?w<)bU6R{,!<ar1dd}`#@B ;z{W,˽Xj6c; ^tK3``Jzd=tBd"B(`G`ʐuo]%K;Ao5q<ػ zPH|.( @˄"hvCQ=PDj96鈅SJ 4da  ch`E` kk.¨jݖ2f̨m|$X󘁲u]u67KbЙ +d#8B G`eOs눷 HRaxRG/cVAlaf w(5ک+d@A`6 ]^gY y)9GrpD.K_r\au3y55=5d :d #&BD`G` \7yFU_-8NF~kڴu[*nL^2ݫ8ddk@`0TE`@c=Xҁy.)"o9*Su(YH!5>,8{!:Uф"c|*"H.Qdw@@  J W*D>ռU oCZѬسEiQ@y9\9B&ٛK{Nq]hd@`bBJ`GC:2RI`<sh 2,hᅡYk/Pv,1U:HMA])FdA "8pL @0qQ8f6pHbCTV_? myK O/-?H:4B1dz  p `N sCI;( ?B$@O&5unk5KX~r>P|n+d `0#8`RIՏ3VU6jȵĝ p)]?Ic*1CMEqH$:V'J[rd` #3`I4+%/ ^JS#I %R$B.1uH +h7=P^uW"d@cBA x5kS'AV(ߗ]<~]fa X"Qt"2ˤLy7DjZd #&DH`@ z CΤ"l~E}q֒^&qqg̵=2!Q؅ ݨ}\dK<dzA`? YmW|t2[b#/|д;yN&ZƢUE7*yd@#8B8`G`RR8,0bW " @m7c F:=mK=iRWyv֛`ĩXb")dw 0t`N`=2(~Pw3iS:Qz (vmaFZ|V.5kC%RQ$ʪIdvA #`J`Rmqr>V*Ċ5 7 ikE,r+eg/8aeadwA0lP`Æ"*IŨx4,y:lNEwxʂ+I TXĐ48P9U9NᨹQ!zndA `J`@2TcX޻}S?9Jf8&} ox}R.qkq[\Ķ:=Id"A|E`v] *]fpJ`fS: T4X*kEXǙ,2^J hMV&o.d@X#$B(A 1Wo\%F>9kXŬjPa0Je"vr d5  SadA B`@AI* " |L(͓ %c*d` 8B`@ 5ٗybr_p~ vE&:ئcRyIs*/6DbQ4=>Ӏ'duA #8 I ,c$1* )NW*Pj*Kc 44۳P]ԕ 8eq d @  AD @ƥvîqz+ 6:28 Et[̪[(ڑO>.l8CY$d@#F @iԏ,RUe1ޞ4}|-#%{Ot<;|TVs !d $D @gAoJsYAj.8C U ,"]bFmx]ʏ2fw-uNrdd 4@9`{6kM_q^jtsϱ:0qi|gMMI)kTɢjX}AXQ5z;R8]IdcBTJ`1MMHM 6ܣfOwo @h=ad@#A`G`@`'`DISa1Kw{z ÚbId]^7gzo G m *d@"P`H WRAw%LAME3.93LAME3.93d@(>`dAB C`dlA` ,`C`@d@#AD`d@`"8A@9 d#BAપdi 4TAGSilencepimanQuod Libet Test Data2004././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/silence-44-s.mpc0000664000175000017500000000364114035600052017067 0ustar00nicknickMP+\ggЙs4}>|n"vKd"墲*{eiy\=sy4g/cX@Occ{҄-y^g2;ZK'?I%.]$Q(w%3VI9_x{zÿLvZhߞ0|6H }7ܤ>_I]Y-&D.;"0I,H)zZb>sϱ ӷ]g;l*,/*'o֕ 5H6P&C(jAon]~пB8 xqKrJy=A8p:P1(iĝ7X?ZE?l:яӼ1F8Tp=|'mX/D*H hrn@{j-y-B^ BN9qL6.[`[&dN"hG Nc].h>;R'=2L<N7nc͔K H^2{fUt R{:r2q%L&9$ws> ǽ>{E0织F6/""K{|̜ [ĞK~zw69UTUDDWvB}|*^l] wLxInL sGSTI*}{O nQi5urNl im;IZX\^&ЖV*UAޮhn ȇYQ|8VM3yll mS33a)IqeZ9[f[-+gրOE uG&WG5&6|_{;V]sϤL/O} ۚ\%1b- ZU̓RT}:pFg+i}WiY y럻+)2n$pմs9doZW dǩdoz۶mےcpz_UUU]?Vt.\tپpkU`__G뼪j$ҤLT1n@vorbisDɯOggS>1n*־CvorbisXiph.Org libVorbis I 20030909)rating:quodlibet@lists.sacredchao.net=0.0album=Quod Libet Test Data title=Silence artist=piman artist=jzig genre=Silence date=2004tracknumber=02/10vorbis"BCV R!%BJc)RR)%cJhs9'A1.bkiRV!%S [hRT)cRJhs9FsB'c.b[Ic1&SJ(c1cPJ%tBG%t9c1"[ŞJ魅[JR*Td!|F[Jc1cdˁАU@BCV 0EQАU@Eqq$G,BCV@(#9dIi'뺮n۶m۶  4TD!db@h* @$'IRa,&IRʣP Y (bb9)-X!sR-g1)XcΘsJI\J礴s9QJ)sΥbK))Xk9Zs9j9sls9[50 lXh,А@HaR1s:(d1 B1會B1B!R2sB!TJ眃B!PJsB!JIB!B)A!JIB!B B!PB%RR!B!RJJ%B!RJJRJ(!PJ*)PB!PJ*)RJ!B)TR !B( :ɨM @xAI1"!娵b1c<$sRkhH1jS!ŤՎɔrTC)2dILXB#MLQ1A U DDhut1 t.   p7x< @GQR` \FGH@"DDD3Waq @@@ @@OggSz>1nOQ*-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+++-+++*,***+++,+'ؽۉ 20=ܰ=DD˂~lXӞ? n@He 2@B%=XӞ?  DTHX0H,=XӞ? n@D@BE =ܰ=DD@ e=ܰ=@B2=XӞ? n@$$ E, ap%$=ܰ=HD `@P=XӞ?  " `b=ܰ=@DD@"R@ =X^? 6 I$H"0=ܰ=HD$B@ʠ=ܰ=D"ʀ"=ܰ=$ AA=ܰ=DpU=XӞ? n@D" `@d@=ܰ~l@""AeAPp~lXӞ? n@He 2@B%=XӞ?  DTHX0H,=XӞ? n@D@BE =ܰ=DD@ e=ܰ=@B2=XӞ? n@$$ E, ap%$=ܰ=HD `@P=XӞ?  " `b=ܰ=@DD@"R@ =X^? 6 I$H"0=ܰ=HD$B@ʠ=ܰ=D"ʀ"=ܰ=$ AA=ܰ=DpU=XӞ? n@D" `@d@=ܰ~l@""AeAPp~lXӞ? n@He 2@B%=XӞ?  DTHX0H,=XӞ? n@D@BE =ܰ=DD@ e=ܰ=@B2=XӞ? n@$$ E, ap%$=ܰ=HD `@P=XӞ?  " `b=ܰ=@DD@"R@ =X^? 6 I$H"0=ܰ=HD$B@ʠ=ܰ=D"ʀ"=ܰ=$ AA=ܰ=DpU=XӞ? n@D" `@d@=ܰ~l@""AeAPp~lXӞ? n@He 2@B%=XӞ?  DTHX0H,=XӞ? n@D@BE =ܰ=DD@ e=ܰ=@B2=XӞ? n@$$ E, ap%$=ܰ=HD `@P=XӞ?  " `b=ܰ=@DD@"R@ =X^? 6 I$H"0=ܰ=HD$B@ʠ=ܰ=D"ʀ"=ܰ=$ AA=ܰ=DpU=XӞ? n@D" `@d@=ܰ~l@""AeAPp~lXӞ? n@He 2@B%=XӞ?  DTHX0H,=XӞ? n@D@BE =ܰ=DD@ e=ܰ=@B2=XӞ? n@$$ E, ap%$=ܰ=HD `@P=XӞ?  " `b=ܰ=@DD@"R@ =X^? 6 I$H"0=ܰ=HD$B@ʠ=ܰ=D"ʀ"=ܰ=$ AA=ܰ=DpU[ܰ[@././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/silence-44-s.spx0000664000175000017500000005755614035600052017140 0ustar00nicknickOggS'ǑrPSpeex 1.1.12PDOggS'0Encoded with Speex 1.1.12album=Quod Libet Test Data artist=piman artist=jzig title=Silence date=2004 genre=Silencetracknumber=02/10OggSn'+-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNmC_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNkmE_mm/mmomUՅ]]]]XUՅ]]]]\ֵtNmW_mm/mmܡm%UՅ]]]]XUՅ]]]]\ֵtNFS_mm/mmwUՅ]]]]XUՅ]]]]\ֵtNqm`3_?%/mmmmUՅ]]]]XUՅ]]]]\ֵtNam}_mmcmҵ0?omUՅ]]]]XUՅ]]]]\ֵtN<m_mm/mmmUՅ]]]]XUՅ]]]]\ֵtNmP_mm@/mmhUՅ]]]]XUՅ]]]]\ֵtN(խa_'@mmUՅ]]]]XUՅ]]]]\ֵtNm}_mmثtbmmUՅ]]]]XUՅ]]]]\ֵtN(mmB_jȯmmsmUՅ]]]]XUՅ]]]]\ֵtN@ma_o/mm[AmUՅ]]]]XUՅ]]]]\ֵtNmn_mm/mmUՅ]]]]XUՅ]]]]\ֵtN_"mt"_jVm mmUՅ]]]]XUՅ]]]]\ֵtN,mj_mm/mmo5UՅ]]]]XUՅ]]]]\ֵtNm^c_m@/mm(m[mUՅ]]]]XUՅ]]]]\ֵtN_Dg,_mUՅ]]]]XUՅ]]]]\ֵtNpm]_m/mg8տoUՅ]]]]XUՅ]]]]\ֵtNZmd#_m/mm#mUՅ]]]]XUՅ]]]]\ֵtND+^_mm+ m`mmUՅ]]]]XUՅ]]]]\ֵtN;mk_mmٯmO#omUՅ]]]]XUՅ]]]]\ֵtN.m~#_'mfmUՅ]]]]XUՅ]]]]\ֵtNPj_mm/mmrWڵ5UՅ]]]]XUՅ]]]]\ֵtN/ƀ_mm@/mm۠mmUՅ]]]]XUՅ]]]]\ֵtNtmx_mm/mmUՅ]]]]XUՅ]]]]\ֵtN1mk_mm/mmѠmmUՅ]]]]XUՅ]]]]\ֵtN[m@_[m/mmڎmUՅ]]]]XUՅ]]]]\ֵtNmFmR_mm/mmޔmUՅ]]]]XUՅ]]]]\ֵtN'mW"_mm@/mmmUՅ]]]]XUՅ]]]]\ֵtNFm#_m/mmUՅ]]]]XUՅ]]]]\ֵtNCmu_mm/mmXmmUՅ]]]]XUՅ]]]]\ֵtNm\_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNrp_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNcmOʀ_mmm@mmUՅ]]]]XUՅ]]]]\ֵtN5m_mmA/mРmmUՅ]]]]XUՅ]]]]\ֵtN8mu_/mmLmmUՅ]]]]XUՅ]]]]\ֵtNzmR_o@/mmmmUՅ]]]]XUՅ]]]]\ֵtNPcmU_/mumUՅ]]]]XUՅ]]]]\ֵtN j_mmfm$OhUՅ]]]]XUՅ]]]]\ֵtNYmV_m/mmߋoUՅ]]]]XUՅ]]]]\ֵtNmp_mm˯mkmUՅ]]]]XUՅ]]]]\ֵtN(mU_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNq:kH_mm/mmܠmmUՅ]]]]XUՅ]]]]\ֵtNpmI_lm/mm mmUՅ]]]]XUՅ]]]]\ֵtNZmq_?m'/mmcomUՅ]]]]XUՅ]]]]\ֵOggS'B-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNHmi#_@/mm`mmUՅ]]]]XUՅ]]]]\ֵtNP^ԿZQS_mgpmUՅ]]]]XUՅ]]]]\ֵtN1ma_ikAUՅ]]]]XUՅ]]]]\ֵtN_oڵ@/mm mmUՅ]]]]XUՅ]]]]\ֵtNHmv_mm@/mmҞlmUՅ]]]]XUՅ]]]]\ֵtNmc_oow/mހmmUՅ]]]]XUՅ]]]]\ֵtNKmr__mۅmmmmUՅ]]]]XUՅ]]]]\ֵtNkmj_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNp_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtNbI#_m/ٱWmmUՅ]]]]XUՅ]]]]\ֵtN+.O_mmu/m mmUՅ]]]]XUՅ]]]]\ֵtN7ms_mm@/mmԎ%[mUՅ]]]]XUՅ]]]]\ֵtNԛ_mo@/mm`mmUՅ]]]]XUՅ]]]]\ֵtNfηz_mm/mmޠmmUՅ]]]]XUՅ]]]]\ֵtN{_[m/dm mmUՅ]]]]XUՅ]]]]\ֵtN_mb_mm mmkmUՅ]]]]XUՅ]]]]\ֵtNEmT_mjҿmJmmUՅ]]]]XUՅ]]]]\ֵtNsFs_mm/_mUՅ]]]]XUՅ]]]]\ֵtN*ԿR_mm"mm×UՅ]]]]XUՅ]]]]\ֵtNmp_z'YmӬ5oUՅ]]]]XUՅ]]]]\ֵtN=mq_mm/mm߀mmUՅ]]]]XUՅ]]]]\ֵtNwmE_mm/mӭmmUՅ]]]]XUՅ]]]]\ֵtNmo_mom:mUՅ]]]]XUՅ]]]]\ֵtNP`Կm~_omoUՅ]]]]XUՅ]]]]\ֵtNm[_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNfη]_mm2/m|Ӄ'UՅ]]]]XUՅ]]]]\ֵtN'mq_mm@/mm٠mmUՅ]]]]XUՅ]]]]\ֵtNmX+_m[m/mm@mmUՅ]]]]XUՅ]]]]\ֵtNbm~_mm/mmҗ[mmUՅ]]]]XUՅ]]]]\ֵtNm[_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtN mZ_F/mm`mmUՅ]]]]XUՅ]]]]\ֵtNT,v_@/mm܀mmUՅ]]]]XUՅ]]]]\ֵtNtFO_mmmmUՅ]]]]XUՅ]]]]\ֵtN8οmp_ummUՅ]]]]XUՅ]]]]\ֵtN&_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNmOO_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtN3mՐ3_m/mm`mmUՅ]]]]XUՅ]]]]\ֵtNlmJ_m[m/mmՏUՅ]]]]XUՅ]]]]\ֵtNQm}_mm/mm[mmUՅ]]]]XUՅ]]]]\ֵtNmo_mm`mmUՅ]]]]XUՅ]]]]\ֵtNJTӶS_ml @/mڀmmUՅ]]]]XUՅ]]]]\ֵtN~mw_mmMmmmUՅ]]]]XUՅ]]]]\ֵtN2UI_mm/mm,[m[mUՅ]]]]XUՅ]]]]\ֵOggSO'r&:-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tN mp#_mo/mm׳mmUՅ]]]]XUՅ]]]]\ֵtNBmv_mm/}WmmUՅ]]]]XUՅ]]]]\ֵtN'Կmp_m/mm۠mmUՅ]]]]XUՅ]]]]\ֵtNpm~Vmm/mm@mmUՅ]]]]XUՅ]]]]\ֵtNPmn_mmCdmmmUՅ]]]]XUՅ]]]]\ֵtN7mq_mmomխmmUՅ]]]]XUՅ]]]]\ֵtN:Կ{_mmѠmmUՅ]]]]XUՅ]]]]\ֵtNP\moO_m3UՅ]]]]XUՅ]]]]\ֵtNvF؀_mm/kMmmUՅ]]]]XUՅ]]]]\ֵtN=Xm_mmݠmmUՅ]]]]XUՅ]]]]\ֵtN$mi_mm/mmѠomUՅ]]]]XUՅ]]]]\ֵtN/ _mmGm mmUՅ]]]]XUՅ]]]]\ֵtNvmh_mmomUՅ]]]]XUՅ]]]]\ֵtN*mz_o/mmmmUՅ]]]]XUՅ]]]]\ֵtNhmx?_m/mm mmUՅ]]]]XUՅ]]]]\ֵtNcmJ_m[mg/ZmmUՅ]]]]XUՅ]]]]\ֵtNNmq_/UՅ]]]]XUՅ]]]]\ֵtNqmd_mm@/mm mmUՅ]]]]XUՅ]]]]\ֵtNukR_MmmUՅ]]]]XUՅ]]]]\ֵtNkms_o/mm mmUՅ]]]]XUՅ]]]]\ֵtN{Կ_mm0/m[ mPmmUՅ]]]]XUՅ]]]]\ֵtN1mn_mm/mmї[mUՅ]]]]XUՅ]]]]\ֵtNFm[_/mlmUՅ]]]]XUՅ]]]]\ֵtN'my_o@/mmPUՅ]]]]XUՅ]]]]\ֵtNrFKX_mm/mmm5UՅ]]]]XUՅ]]]]\ֵtNmQ_mmu/m;ͿmۅUՅ]]]]XUՅ]]]]\ֵtNԿmN_mm/mmݠmmUՅ]]]]XUՅ]]]]\ֵtN mE_lo/mm׈mmUՅ]]]]XUՅ]]]]\ֵtNymi_?/ym֐oUUՅ]]]]XUՅ]]]]\ֵtNƿӚ_mmٯNmUՅ]]]]XUՅ]]]]\ֵtN8 dg_mmm٠mmUՅ]]]]XUՅ]]]]\ֵtNP9ԿO_mmj[mUՅ]]]]XUՅ]]]]\ֵtNyƿ|_mm@/mm@mUՅ]]]]XUՅ]]]]\ֵtNNً_mm/mmڨo4mUՅ]]]]XUՅ]]]]\ֵtNfJE_mmkm۠mmUՅ]]]]XUՅ]]]]\ֵtNRm~_2[mٯmkm@mmUՅ]]]]XUՅ]]]]\ֵtN@mu_mm/mm_mڵUՅ]]]]XUՅ]]]]\ֵtNu>ˀ_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNm@_mmͯmdmmUՅ]]]]XUՅ]]]]\ֵtNCmj"_m/mm mmUՅ]]]]XUՅ]]]]\ֵtNlmzH_mmmmUՅ]]]]XUՅ]]]]\ֵtNGm\#_m/mmmmUՅ]]]]XUՅ]]]]\ֵtN&οm_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtN9mkN~_mmUՅ]]]]XUՅ]]]]\ֵtNsmn_omڗ/RmmUՅ]]]]XUՅ]]]]\ֵOggS'ț-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tN=mr_mmm+sUՅ]]]]XUՅ]]]]\ֵtN/mm_mm/mmmڵUՅ]]]]XUՅ]]]]\ֵtN_mm/mmzmmUՅ]]]]XUՅ]]]]\ֵtN)me*_ڴmM mmUՅ]]]]XUՅ]]]]\ֵtN#mg_mm@/mm7mUՅ]]]]XUՅ]]]]\ֵtN2Կm_oڗm@/mm]UՅ]]]]XUՅ]]]]\ֵtNԿmQ_m)m`mmUՅ]]]]XUՅ]]]]\ֵtN=d_mm/mmo[mUՅ]]]]XUՅ]]]]\ֵtN"mTc_mmQ@mmUՅ]]]]XUՅ]]]]\ֵtNbmx_m_G/m`mmUՅ]]]]XUՅ]]]]\ֵtNJms_mmHmm!տUՅ]]]]XUՅ]]]]\ֵtNm__mm/mmoڕUՅ]]]]XUՅ]]]]\ֵtNF][_m/mmvmUՅ]]]]XUՅ]]]]\ֵtNPmoj_m@/mmHUՅ]]]]XUՅ]]]]\ֵtNI o#_/mmCUՅ]]]]XUՅ]]]]\ֵtNzԿ^_/UՅ]]]]XUՅ]]]]\ֵtNmX_mm/mmߠmmUՅ]]]]XUՅ]]]]\ֵtN.mI_vm@/mm׿o7mUՅ]]]]XUՅ]]]]\ֵtN Y_mm@/mmޗ?UՅ]]]]XUՅ]]]]\ֵtNƿmH_mm}/mmmmUՅ]]]]XUՅ]]]]\ֵtN mx,_oo:/mӠmmUՅ]]]]XUՅ]]]]\ֵtNCmh_mmCZHmmUՅ]]]]XUՅ]]]]\ֵtN5ֶm_6m!/Ƿm͝UՅ]]]]XUՅ]]]]\ֵtN9T_mm@/mm mmUՅ]]]]XUՅ]]]]\ֵtNom@\%@/mm#oUՅ]]]]XUՅ]]]]\ֵtNjmn_mmׯmmѠmmUՅ]]]]XUՅ]]]]\ֵtN5m}_mQm mmUՅ]]]]XUՅ]]]]\ֵtN`_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNxI_mm!/momUՅ]]]]XUՅ]]]]\ֵtNW_mmٯmmmmUՅ]]]]XUՅ]]]]\ֵtNBԿO_o5@/mm֠mmUՅ]]]]XUՅ]]]]\ֵtNu6V_mm@/mm'mUՅ]]]]XUՅ]]]]\ֵtN#㏀_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNimR_mm:@mmUՅ]]]]XUՅ]]]]\ֵtN:VB_mۯp WmUՅ]]]]XUՅ]]]]\ֵtN@ֿ_m/mm,mUՅ]]]]XUՅ]]]]\ֵtN&6_Vm/mmܐUՅ]]]]XUՅ]]]]\ֵtNPXm\_j呯hUՅ]]]]XUՅ]]]]\ֵtNdοV_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtN_m H_/mm݀mmUՅ]]]]XUՅ]]]]\ֵtN|Os m|S_6m@/mmڗmmUՅ]]]]XUՅ]]]]\ֵtNPml_Q[mK`[mUՅ]]]]XUՅ]]]]\ֵtNm\_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNwmOʀ_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtNsmE_mm@/mmmUՅ]]]]XUՅ]]]]\ֵOggS0'm,-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNmh_mm/ҶmmUՅ]]]]XUՅ]]]]\ֵtN>mz~_o@/mmUՅ]]]]XUՅ]]]]\ֵtND,_m/mlmmUՅ]]]]XUՅ]]]]\ֵtN%F#_/mmԀmmUՅ]]]]XUՅ]]]]\ֵtNSmI_/mmmUՅ]]]]XUՅ]]]]\ֵtNLm{_mmkm-@ mmUՅ]]]]XUՅ]]]]\ֵtNma_mm@/mmҗ[mmUՅ]]]]XUՅ]]]]\ֵtN,~܀_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNcoƀ_mm/mmzomUՅ]]]]XUՅ]]]]\ֵtNmma_mm/mUՅ]]]]XUՅ]]]]\ֵtN8mp_mm/mmހmmUՅ]]]]XUՅ]]]]\ֵtN|mY#_mڵ1mmUՅ]]]]XUՅ]]]]\ֵtNgfZ_jbگmmUՅ]]]]XUՅ]]]]\ֵtNm~,_/mmmmUՅ]]]]XUՅ]]]]\ֵtNgS_mo*ȯmmUՅ]]]]XUՅ]]]]\ֵtNEmx_mmQ/խa?mUՅ]]]]XUՅ]]]]\ֵtN'mi_mm/mmܗmmUՅ]]]]XUՅ]]]]\ֵtNmO_mm/mm@mmUՅ]]]]XUՅ]]]]\ֵtNmO,_om/ZUՅ]]]]XUՅ]]]]\ֵtNXmu_mmmHooUՅ]]]]XUՅ]]]]\ֵtNO_m`mmUՅ]]]]XUՅ]]]]\ֵtNgO[_joA+mmUՅ]]]]XUՅ]]]]\ֵtN(ԿmH_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtN mT_멿m`mmUՅ]]]]XUՅ]]]]\ֵtNBm_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtN}GVmm/mmڨmvmUՅ]]]]XUՅ]]]]\ֵtNjmU_mmm`mmUՅ]]]]XUՅ]]]]\ֵtN"mh_mm/mmW[omUՅ]]]]XUՅ]]]]\ֵtNFm _mm/VmmUՅ]]]]XUՅ]]]]\ֵtNMX_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNrmu_mڵ/mmUՅ]]]]XUՅ]]]]\ֵtN)mx_mm/mmUՅ]]]]XUՅ]]]]\ֵtNmb_mm/Ӣm%UՅ]]]]XUՅ]]]]\ֵtNƿVƣ_/mmڀmmUՅ]]]]XUՅ]]]]\ֵtN|mc_om/moUՅ]]]]XUՅ]]]]\ֵtNJm_mmѯmmmUՅ]]]]XUՅ]]]]\ֵtNCƿcE_mmζommUՅ]]]]XUՅ]]]]\ֵtN.ms_m/mmڠmmUՅ]]]]XUՅ]]]]\ֵtNaܿ γ_oo5/mmԀmmUՅ]]]]XUՅ]]]]\ֵtNIm_mm/mm?mmUՅ]]]]XUՅ]]]]\ֵtN<m՞_mm)m mڏmUՅ]]]]XUՅ]]]]\ֵtNNX`S_mڴٯ-ٿ@mmUՅ]]]]XUՅ]]]]\ֵtNW_mQp mmUՅ]]]]XUՅ]]]]\ֵtNdF_mmf/ ڵUՅ]]]]XUՅ]]]]\ֵtN~mb_n/mm׀mmUՅ]]]]XUՅ]]]]\ֵOggSz'F]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNZmH_mMmkmmUՅ]]]]XUՅ]]]]\ֵtNucG[m/m܀mmUՅ]]]]XUՅ]]]]\ֵtNP6NӶmK_mmqf[jVڵUՅ]]]]XUՅ]]]]\ֵtNmf_mm/mm@mmUՅ]]]]XUՅ]]]]\ֵtNImw_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtNRm}_mm@/mmԠmmUՅ]]]]XUՅ]]]]\ֵtN6?F_mmL|A[_a@@=Y.]?j'5ؗh̙# <L05hGnK 0%rǚ@% 01+$脫CQ])S?_,ɞ1D,֮W4,+ӆ\gk_̣A%i_׃M0{AP$d ܣ#&*OVOZu~Gi q-eO_pJ 2h * Sݗ׎ndosKi/-/gNOE:f,K-sKR~AP*{_4=Ueи~Zٝ H4gST5 SE././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/silence-44-s.tta0000664000175000017500000023527414035600052017111 0ustar00nicknickID3TDRC2004TALBQuod Libet Test DataTRCK02/10TPE1 pimanjzigTIT2 SilenceTCON SilenceTTA1Dz)RLZRZZ'` _ @ @  P@@(@   P@ @ (( P P(A@!  (HB%%B D@APPP`(`P@IPPP(@TC@!PX @a @A& d(00 L @&" E(EaPtP`LLT EP[2`0`ee$@Y ˀ d0lr1I&a2`* eeTILR6 e0&P  eQ[0 `*&`eT`e0 ` e2*0 P6 0 ee@ eP6LB52PL `R\! &@``( &P2jL`ʘee &Ap0 P 0PeL $e0 0WRI(1a(I dP6L C eS IIL0 Pm2lj T@6LA  @5 0 @1&(I&P0PF5&6$ (T0`0!L` @Y5ʀ2jd0$P)ee!L2j`V @0P$0LLe3(l@T&eLʀ2`(cB(eP L L2 &@5 PV@5՘@P( 2p'!M ` I` ʨjE e ( $P! a`P6\6'` * e@eTC@T P@A0`k*ajP6 C2 (`!@ 0 CH`@( &0Y 2PL`)j@Ym #C1($ ( <& (S`rɐ00 `00 f ePF2j%L5&P2a$@x!R2TP`” '0 &af0LAPV6 C`d2ef&$S!L! L2l&IT d& 0$0A a3 C( aC (ʀ0A abʨ`@! (AJ *V-  x&a`Ն0@0T 00 . a( OQca! A`L`j  @\m$&aA(0!yõ2@9aTl\0! Pa&aL@6SaIՆ0eI0$ aeCLj#a0  6\m&eCjL2dAePa(=̜ - y( @50 a d$ a A23P$Px2&'I R6L2@! 0WIxP)0P)0՘dL.d!L0$3Ax6u{0Pa` Pa` CH$ Cr$Lep9 ddM2 d0pfA L`j6'S[ɐ &$3x8<$O5&gAIPF5D02<'3  @6!Leh 0d g&a0 CA2C0I1WIfH0&a۬$2Hf0eaA2C2HfB$3\MƩ@sj.r3a'dj*aN<CPL jC yS! @fN23(Y mI"0 @$3d\$p2(0jF L&0 rmd&@$@ٓ! f0 %0a$ aL&a83&a83d3 0uIf!y<3'pm&C9 s5!L2 AP69@pfRa298$$\md& !0 3Cv &Paesِ32O29 3`393 3932C(0 (sِ!L2C`LLL_z83 1W{ 0sfG ˆs'APA!2030sfC(0&dR3?*V'3.0`LL0`LL"!F@PFj 3a&g&eLL00L0m0@V M 3 $arfd@ ?LL03sٜmɑhE$ j$<&rfe$<2sL"2e3?G- B*Vl8<HxfrFF29PFC 393`<[T0_#P  O"@&Ϝ?ơ$#E@593` y'&HxȄarf@8g@ ZACˆs~03`.{nYoMjbO1Ih`1HxHIyGʔSo ) *P[$Rf0ayQA֖I 5C03'09y2sddp eEϜ3 3j@`LLly8y+ 2,19&kLq@*sIms>A0wX՟)y&9<e31VEBʂǾ0fRTQE|HF$p W6!DTE`6syjDL2GWA`p3g 3 3k38PFa,2rxC`91G@*:L9PV9aʨogY&y `99@ -'93(#gϸVUa''(#0a愙9}Th @9<0 3ԍ99 Gsp>!-a@mYTa1hc@fM*"`9H9zpH1V*"0 V{sO*BcA3g#3j 0s& 3ϸH|8 jTjPFg8g&f|au#HF|1`朧@F@2b 3gN0)?xUi10 jLxʮ8͢ 2B͙L9̉(#fy&@9YF7=h,H9<33kGc!9)sNPU#Z/wi@d+VBD GcPa@0V"3u@9<!V9a90ảap9Yi9$/w` 910F¤vvT!PD̜<@F:Xe *زKPĪ *F?gOZ=0R9fq]bBQ#9j޲ !b0mLErV2"Ӟ5cPa@BUqs TPul€` %WIf> &Z9$$#O VcPSvcaĪ)aŪ 9c@3Ta@ kTPFGle5HAԤɁ"T{$X 3, @c€sx0XPX!Tg*xS3$0`3\X5B:P*X砊 |  _Tg$|?V`;Ö:U#cmIP'Ϝ8jy@"\<35|jLD 膧p:Aj:j@OcU|Xkݡ[vV Lnha1Ta@1j c,g>F,EDYT@@UJM380S?Q0bPe\!0*Y]uz:kWX51t !I |j"VP9@@|jq,ޭ5z˂00b8Y\8$H,du1!2Ta@RiF nIa.0 ԈFQN91joX)ӌ}*@8ͨªBTxge!e#Vh\X+}v1"0.@ƢbU:Jƈ߆~ْ,V!eXC%Ee왾# U81.=eF)[0bmg k}<֊*`vb@eBT1F!rh=fע,HBjCFa@c up:F L+1@s!pp:F@1ƥǸjDcU.F`q:Uq@08jfb@@#V2I7Us9 HVy@̧FPI~VLx3.v*E@#VO9P*FŚ~e*De3?*v-!n3ŀB>T_݁W|U)SUdE@F`RMKc*XuUA2ƨ . hqa( :B@c4PW}0Zq@e:x4U¡8b1i0,pbExY G]1q3wiBWLt1+-U:VQjBjaq@H8!uXx@c|spr1jDS.<\ZA@2QXc]z !d#sq.񔍺!X5B`CF u*~jE VR8" u#X1b1ZXcTXu#V0b)FĪ#0ƫ>UGd.T/ĊUhĪ#@2Q`1 `QGisAxueP+"vz0b1 #FD:B!XuW}ejĢbغB4"ZCVbĪ#cXWP+4Zq@Eօj`6u<$ª#c(ZǏx@`q1*jq fU 놮8bF}YUZpuQ8 h *Vz"b`ݿ^ǃDH(вA0Z11ՊƷ ?LЪ1` 1PQGh٨/)F\uDcvWQ8[w>@F)T#P->HVX1ԊVQ1w?EP,UG#C8PD#uSp@018̙[!C-:úl}AěfRa8 P[X8V ,C[Q8 c KeEUGq$cq@@G#z Bj]UǨ9]jXZq@1 $bQu@Z uiv jq1 @OٳkǵR85pucQWjPxG\#pB(.A٬Q/:@@(:ЈƤP+cq-;_Hň=h Z eYX@(V!Fak;ή IrX+j1 dG]PQnp@0TUG4ԭ~UG 0U#d !ưVa8 R7 1BPţcUG(v׊c9  ,8"ԭO0Ckq@W! 5j#pcTT/?> @P֏ǶQI)aX+p#c+~UGPW!Pţd8@2.U±:<&Y,@ l"H W!18Rt^Z)U^g򺆩‚P:.]WLkEP uG uO^:BDUG kŁa2 Z6֗~DafUa`+N!k  *R0 cX+ uſǰI P \u$82g]-z6~{wĪGȲA@88 v=õƈ=/cmg*e/A+f&$$W!ZdAí  :a8 Haq@p6T;a8 ūZ Bq#8p@E]<Ł]z<$a-z1>^.J 0!:BdG]l 11x@eX+>(1U ŁW=B (<ǵŁQtV=>BCFs&Aka V@0eRHXa E=WaZ@ (  @ AErQi@KNtDaZaZ =ӿ.I` [e ChiaiIi¥LA0v2à0HdV:Bp͎kK`xK ail1P%='U@EUd<>r2r06,opƕؘ֖p=ņ 2& 2ò Qh%ijg}g p-i8UA8Z,ed!%$$ _:WRþ3(P% 8Z\.qZ@P'MKaZJ`iZ@ƴ,iB++.d`L˒Ro`ư,i` .7,[dH-L @09 @Ppѐ.e „KXiNVf ,aL1ZZ0ۮXW */cLж.6( -&r$$ $ ( MI-L @Pp)SJCPvG]qK@$ ZBI@̘6< 0-npeP .eRN'XYka 2%Mi r (eIcZ! P`1lK vb  n1,ჼD,VR ukhp[9LTa0`i)QM$@B3(4Ű-iX ے&&\dwж0 4%l"Ű-i -Lp*7,[a8l- Jp+ Es[APex]PpXha`ia '(Y7' Km Ű-aA:L4lY+ % &I .6@(iZ4 wm)HTs0@T M S{ne"8,rR[9 l-Ll0&P-/vDL @F\l"bږ4Ŵ-ѹA6@T e [9i[B ʁ@I!p&bؖt8,@([wN-F0Le5\h`Zh[@t _^Ʃ&K"XL"&DbɾX-K@ö`HiۆN %  q؆  l(g߶`[4C i,i0r @Ib 0ʂԺpY@&H .6ٲAi+@@ .6Bce; Lp Cm0$P,K@ pM pM @NK:(%djQEs-i@(ရb,CUs-iBr8$DBUlX~{Zx@CyieI#L N M"2p[2@([98lá`XH ŰmY 6 öB0IAscӥ,muϠQٲLP(aۆ99† |ML$8X4Mp`ۛ2:% 2! % @Fd"@(/2b[H`1l0%"2l{`8X4t-- eIDPŲ0(NeHa/ Mr)d &D@FDmIazyɎeIIn2MC{+)0+G|Lla 8/0:&u`i)6M$XLmJa/L &x%+Ҷņ4ؖa֒[#Jc P@(7ۗ'ىtWXTm0؋L$*Vm&)9Leܰc-!*m IWH0(NFA܏Mvq0ۙ!ܦC0!) E$"xaf n4@@q,%" d͍]mI8 " Ul/e"vb&"8Z8 " E2CF ӢJNHF$]4 &xqQd8X%/A@"!,qodI`/2L@qU9,]/-f_`mbld/2xBIx}$t0E& K4b- @(7hya0(NzI0VH@qrY`1]1ݖaAxކ#L,e [n6d[Np*0^d"!I`H,̮Zrk$[D,6Mb, `a6@@ͽ fcn( E& (Aod[B7vx[B0Ds a%k68ФA".0( nixD 6:2 `Z8mӄblJ:ȋLQ2 $2Pl0Y5Ǝ$%jv6"!I^d"@(ZY` C($/2X8ȋL$e0nξ VXT{)\ai ذmtJPA -L"Eia$/22 7l[Za/d[Aa-1-@(餗v:U Z1/9Y8ȋL$ gܗ LI%&`[ i/ vXQa  Y8ɋL$b-Cx, Pvކp٦A؇( IkYfWh@V d%T]g"; Ha"^`4dvvA$l$re æ)0MX m:48ɋLFy,ձryDq- @FrM$E&{`1\i@(78}DqrKAҭ E Y8ȋL$ jt& ,6Mbe\4jM Iov]LRWYD0D5N4(CD$r. ,A 2 bd /0 MODd /0X caH"Io8Y %m^iӲd/b" y'2 ©\ 7Hݒl  a5Ht:6l}$h d /2e&blA%v%p7:W]lJ8ؖvc"([8#Y8ȋ:m&)tH2 A^`"%&ZtT)p e tľ\`J"m77\.าPZd J: &*$/0 o ::D6݀3Ă #-"uLnE`;~ @mpڦI,6:/Uf)-}FM򎛖] mndIvti*/0 t^a% n0 ,2 bM tW$-2HKr$Odd*L%;&ݱr&%+)} IL×)D *w@qRdSEnKvLn0P;~>@AѭMU\a e '*M x H$Y0dd`aTQ&Io8.2Lb2Lb(NGFcr[2LPaS y/  ]0]\".7D-` bxLK{Jo6Pҩcp[I ,6Lbd`/0!^ʳBPZdaoidaFeZAI'"? nvIѢ*%@U0,&2]6|}Y@Xna{9| dQE9@VvA@@T0r h8!V2|/`" { @qpYI d@(Tr& { ^`"%7 #.0 %=`"m& '{*.0 H]K2c/)hoؘdV$3f6IdRB `[b "sS{[`1ܶaS\a0þa(pe88Ld2Lɾ2 p^nɤA*FCѠn$_(Efb8T$bibFϵi [@qrYarYarYI , &8,1e& '{ pd.p4W^)c_QR8GbX mJz(_(^P(`"+ E2BIF)MD@N &2* p7, hi 4zh{GU$BÙFXn !d_XE&AFE0,$e)Ӄ}#G6a T23f :nA Д2bm : ddt7G"9 .6I$ (‹MdvT| i-'H(Ⱥde&1pۆILq>7C3p^[$ al LI @qrY Z80L$N ^@/}E G$LqLD`스(Cy1D 1:/و"A,U4vMl!m@@B v022a 21222@P ibӊ;$zE%XKF@ƙW(1EeR`Q 4goi6 !% 6Q$ @@Aإ Jqje"Meb@/4PlA&q,q+Pl,`T| v<2d2b3b( FŮ4opqİH(S d3I!@-h~83I0a3 2ClIfNmpmZ4Yѓ;}  2ld& L`rfe 沙 Qm8pF9Yo3Hǜ@f̜D(0\Ɯk'5@HAjeo<&Pa&@m Lj6e _$S8sĄ0a0 @Ն\ouc& \6 R$M & L83$<93WdA ee!lL2a&0ɄI@0j30Ljxe L09l9g&L$mL5HjAx R3 !|BxY .{8<*9(Hf39Ph 3\7 I(#!vL0m < <ժZ3?s&(#am'm A2j 9r5&y`LLY[2,<9P٪c\C*C[z" ΐXɁ0 I.)(;dHx&LʸZM6"frX[պ#(`LL03Cə frf393030sݞ !Lə P6̫}<0g 9h@$#& v<bDfI?9I0sA0aL"0\ۓI DM&*L>GlTa@d9穠lɧֈŠD"3(#_dDf}Id<Μ0sγPF|5B`\ӬT6 -UDZ,BCT#":@ am$͉!0aE|g%̉ 3'393&1fyXR&*y'A#ԨAq@@2rxO<$0F .l٨_ !*eRa@$#|*RWxT!̙%QnMBH^`g"ed;z0 P sΣ >bƣQ̜0sΑr F5 zXy?8 4)bD Vb$#s+u 10 Jpuu:T4b1c[vCq]1jЈU#ˆU#(b]Pc\):["`@E@jFUX@2 u1b8Dz*XuU:jTpqpcdPCd b)FЮB2ղ3ˆU#0agX ˆUj!lG\5B.)"{<HiF 0hW!H8 c5j *jj4p@jVQP Qq`Pc!@2Qj `#,kN80@]a @cVDDCaЮ f:ƁQuu(hbxD1Eq#VpbP Q+V!@A-qpAj:8XZq@@T!h;C) \q@XZ8 T:SBHC#b10c \AW}lgc-1.RWXh`U p@,!Tƫcm3C`D]c@Y0zq` jLQ1bXZq@Hg**:Ʊ>51b3Oc #V!d  uQ+vvKqT%m]J *n-:ے(XBj Y#~]2E01t C$c: 1uDž1 㨋6>4N3^C¡e Sj%0  \z@P RFڍi6֊#F,ňXf9lN4bR?4bHU ƀ`jPPc!(:` .t@@T 4 k*TkDDZq@HwUPl7oC54ZqbWcc\6H@z뱮#d^{G]eGe5tx`Ɔ(㈇4h Mjcu5ja,CxfX+z PjňUG4zBqh Zq@BB0Wu!$cq*Vz` PS~`tG Z1e9ԊP ,VqhRxʎv8,F:HXZqC:B u.ԈW! LuY 1 @TVjxzmZqaB c>KA0zmB\vʮ "V4@0;tphᨷJ!0hU cW! dgۻG, P+U:Bz#Eg+*FV(k;kjѳxغ!RV&H"TˆƈjG]nQW11kP+u=czgV4S8 *Xxcu W:1v1.!gtwb@0W `Ċ:B8"jU?#PJ 8h+:BH> QqUG@(1٨ Ԩ:Bau [p l *2Gx=V  uvX8 Q%q<͎G%'A)@*AX8x]_G;&d2E lJ"P€ $*a8bŁW=B!d1ٮjUh k1 cXٱ^PB5BŁW=B@^`,^>N1 KJX"C[vʂƠq~ɉ &r@T8QDZYC Q/u,, j -pUtI',[n0I% ZcV uB5,ú2+2+!P.|sC5Tc8n:6HX Unh ҁZ TW$mHKNd`1,aò  t UcZD@hqC[Ae4S  $bhK p(S2+`Qb1,K8ZW<䑖 :fMR6[2Qĵ MQoŕ@0UKjc[& n.,Kx@Zk=ȅW-+EH%C2i $Aǰ]Tn@0( [HcXp]6 ` m%=VCkaY e0LAa(XUCNk\le Łz1-{ԷchP8* Aq$p[m ix E֊ x)T k1e-"8qR>KMBDh)i ˅`CZ.4) Jh!HR` m ֊PLw$ ڄ"le -a -|[hIX D^hA)0%Y,Q4|,6( BR e2,6 i0(A[hPB@(aVPeX=cB@ 6HX X1WhΖev:&H, (Q^5u}LI^vjih!@TxiW=BzPx#BqU>zƈoݣ^񠢇,z켓uF8Ί)@֦A ^6Űqj]qð.zMӲȉ*0 0XLMpYJ $qGl4RA/;HX\C{ (iX)ch[z HC 2( ae0e d,lm6IL $kT0i*J 6$r0cZ0lBW9x׿  ]v)06MKH&KpH 6 @BB HUXC,Yk4€L ^"H,6$Xl Dƴ 2^A}VVլ$ rv8tZ*/@HP^$0eIT 2$MRi ( )%+>v0@ư,.61A!].[ *S$q9,K XTpQp!t0RF-- .e \*S` וWaY9(4n]`HphW*/´@1,K@`  Aј]cX0A@PpiTJJ *j(c}|*O`Z@ `@aX0$l ò ò "ư,i` ˒& ( ) 2Z6=L¤4U[y %Ե ǥ&TT]8} %l XiJ 0q R'Xa0p &@B\l h./aR \l QUl TaT%v,lK@0eI*6.A6; Bm0l0dsr9 .FoS{q B 6Hl6 pJS@d [cXZ8 \l  ( vFsr#h41[[Ҥ40(MIkaB "! /c[ \[pJ*a.WXL @ KK [RL9 V m"%)/x0i- 8A6bd}З $ s PQ?ƉuY<遊妵- 0-K@+=^4P)He Ӳ  T= e@aZ0 tt@LZ{yRk&@h (L)0eIȘ4Aư,icڭrVRiCt]QW=BH;li2H1+K@҆AҰbX4A2-}*e jLS[,idPR8) jSò 4tBLu9L&J[ K 0R` cX4A% 2"K`]zٻp-i++8^#xM$@.60! hHyCY fh]4A_2/Ia^2"e xc|L)(^(SYP@BFlBIkԨRC_e bxKy:.6(NPF}[@h^ZXZ0,eIB .6 ˒2l6,aB .e KOtJZC X }Lmheul @f&h͆P(. 'Us0@koa鶡1,K@0R$0a[m6 (L %MPPpѐDĶ7; &1,Kò @b > DiѶ ƎU Nat+Od3ZcsUaKaZ@@aZ )bH@1Z蘶0)kR)@qe 7K fKcsڲ'DY4-ј,iZm/`ka2H`&Г27- 1[[An6[5G[ ʆK9JVۮ˫]$%p-/vL@P‹>F-- 1lK Ll{+ :oiebH±#N@7yM$0lK@شB?M$$0͞hSʣj_,1T r.e"bcvLaM斿52%@B,,"PI!Mf I5%ЋL$@P8r9 In2( vKνׂPr,K&Ki& %Lxс,mJA d[ ``ۗhbn2(N%mIm@T豂%JBS5u4aS{HxK˒{`J",f{[A X ض@ICx" 7q,)êe1I/rd &D@(z A~QOmgX,KDŰm$P/2$/Cf@F$#PTKDb48M$@F#rp˒Qa öM&DŰmaJ8C& (\.pr>ȋLHeI\'yhRm䲤eIm @IKxBF#D@q,iB DKyLbض4UEm ö  pЋC{CDrI^t ư\"wiŋDlͬrE&2/CVX4`Y@&ɈeI"p&`1l0Aja+PA/:!pЋL$UKAh N6- PhL0PlKD ߮.K&&D@N Xl_$W`⠪Z\]a⠪V-&)p(:E&x_ ]Tym!`Yd= 2M&2& dF2As7\M"dU//ТU/id[J0Л$FAAhRDZ &xM˖p˒Pvs"I"xс&ꕷ4p؆ -" .v~IOh82:M&-;ے2a/d9,i#v!r56]]mIi0Mvgے2a/ Iے2̶% 8X.H 8% "mIrыA@I7J8M @(79 P@z*KR r:؋L$+VJ8bo pқ$nB 'Ɂji,2|Jom(nNbO& (\nd !D pJ[Vcö ё" @(iE,qpkOk&KJa/dcrY1K;% L$%&PB I_$ey.iYmwa P1[ \A2 "j$ iF\i p&xyQ T.|!`ɶ 0a7 MˁK A&e(e{L@q-ـ](2`anrIzY` A$+q54 L4HPIo0AarpنA`"jit:6w۞/@B"(tH,˜xLX.4IX-O;H]E"p6F\Y \AhH&yDq-Cٶ fےe`1r4U-i%ze`o' 8YTY$B JJm; "mmd/6H%[3 7ȂXafSr\in4`1ݶ o/Cj0}ED e.E bmAm; "XNcso˧HB-<)D`cm JzX^NE&poBI2H,8%i}sae`bJo4pjvmJ/2Y% 8, m; 6cP$vl&V !MTE(Nt۾@ Y8L$k 7cտV%$PݾYLY0eEE"E:s%"QaStOlI(N.-&P҃D2 "B7vzs@Y8e$T҃QF`t.(#Qa (.4Lr &n- &2:ٛ:/4(jA,i jm([D 0IPFkui"ɢ KM PC@(| tۦA t]`J"ڿ-2 Ndw(3U¢ep7@@qN $–h P@&j<^. Q0I%=/6Jv"]qܒa 5I̲KyѪ8](U@ 2P,,$ONbV~PFŦ(j ;TKЋb0@j$$rmA^x:7]^N HN 2 brY2 "@/PTvh),MH lLvUdQѠLpP]D"P1- .&ϩbLW$d;H,L/ r[V-Ku3Ր,rU7D`qM\yYFe9:7u#(w.;hTTP"do`"C ,wk֞}LL(4oA&4nnj&@ɦ U&* Tޤs5%!P e\'&r~3Nf" ]J;|(_`"X_H@ɭm+K a5v{h@br[A@䶌זi@ ~(Ŧ6 "*"C2x~uo- br[ATLn4Mm1O*s!Qn`0nI@І*C0- UmE$TҩZ:7B 1 ^2:&/4^pjo0p*o0rd2Cx Yii*T`t/lNDdo $ZzjoLd ԾDPCy ap[fW{JfCSزAivvVR[ I*.C"; 2 bTҡt{ hAcD eB-d$QrI6p`S$m0rP`bvT`9l vIa ×L@TCygbL,  sG7w(* ;Av0If22"860HB:طY@Ex(o0mbp[AJxn"1μtݕD T ^mi*᡼0- X-݈FWWXNnK @KDTCyBKO Ld@-=7E[:Tl1yH T n4lb'D @"1Ld^0um)0$//0&jboB< NP*` XN/4‹Ld2&2b\ut*o0ܖi*oAb bho T2 be;LbeHO M%T\0- bD"#"x(@F@{6HTRvE(0PXn$!Fukae 1@EP 5A@"sͿP<o! 6U92eݖi2:-D'P-Mb{iM$HyҲB  &2оM 0m9:7@qp[I ˅o'"0UL3;7,L @r Meb*xEHR,6 14,"_.CytpX= 9+ e1{YI,-<7%=_'<{R Zxho`" MeJC{*^iP,$Te0Sb6$! $,xho4 SaB+ DS{e&1B Fe/47dj"" (S{Ú/4ĂQ"P` ծEliyC`WeX޺A&em&[ʇI8XUYY@Ly$b8XUYVM2U;ʅٞK\0@en' %hi+X-ip_P0Ɲ]F@ȂQ0[8ٮHЩt 0p/Q` *E4l`Q$5k! @e&1P1xYI `9|UFe!5&mFnO r6Mb,i", oU0XvUX( lwܦ   H@P@P@@(@ ( (  @(@ @@!@@!@@AA@! R(PH@D@ H@@(@E @$ $`(&&)` `0s P@a& (LB`($(@(I$@ Id(($$@@A)(@AU(LP `$ &0E ( a. @Q eL(c( L `! `(  &I\6 0`H`$@L@Pe0 L2\f2`& l@jT0(c2 `eC 1 eTl.00 2`ʨV $eC$L$C`rP$CP $s5N 2$ee@IA LPeL 2S &eCʆ0e0A5&I!0! Cՠ`@P0 OC 0L P @T`0&I!P I(!LՀ@Ԗjf$((j LA0$T.d@5`&(C `1 e I 0 Tc!LBY0PT& @5`@%L & T!@2( 21 C`Be@@Y@`@@&A (clSap(`P6L`eeP6ɔ$ eP[P$ a`e@2 C&` $$ PI2&0 Wd&LPPV ՘P@YI`(``0@՘Y L.@0 Ԩ0'`&)Ce&axLCjTc @22Ȑ2@3I$ a@e@Y5eՆ&a0I(Q 2d&$ a&aHH0P\!$L'aOZ IeC`:Lm!L@&aHLd (L22!BPj @WR (`T՘dL`((T 0ee @&aL `p̩ms5e&0LI0 CI@m ɓF `YTC  a0$L`TILf0L 6C2$0&a0ɐ a21 0 @ʀ`0P&KIP6&A`PP)3Q!L@Pe00e!Tc2II0 CIf0V L2L2 e00 j @ 0 3P 0L0@!L\m&, 02(00W0ɐ @ddP6jL2C\ < 0 dAL&Lp2P6 CU Aʨa'ala0bf2j@f`0Pa R AA&a0'a@(0$ ` fd0\3Ղ! 0! e$e a2JHdLRF # $C.{Nf8A0 CfIP dQ T<  e00l8$ A ef`00 Cd(M5 KjLʆ00 Cj !`rِ uj3@2kb$ L“3OP60 C Ս A2& gr2HZ 23@A2I y(.0 L a C& A LII($ @C1@\ə'@s2O$2HF ea L(̈́ˆ!L2df &0 # 6fee0!L 0pjd,L``0E$3&a6d!g(d&0&0l42HfL`3 j2IlHfBڞ$B* I.{0 !9Lj3LdA2 5Hf$f8L2HfpfLpA2&a8$ g&LMb `n3 @YY W=((\$ 0#$32 3_O?X4R e4 *"&09V$0C`@ A2I932pfa0WӜ3P|IPdre'e@fș 0g0 lCle?GBE P1r!@&L(:y P#ၜ0ə 2b2&e3'arfL&C6HfL`H|3)Cf.O"@$3(\$ a8yma̜gL(d&0і(Hms&&GՐeL 3je 0h@HXF>9\L-LL(dF <  $<$02Hm0 L2Hf2əPo L(d&LفkSK6'D00&frfPL2\''3՘@\!<Ty0(b&'gp <Ԁdmf 5ȵMf}jé a&LI rL23jfgIBL23@Yy&!3OefB՞`c.1T0$2+Km8yLb !k1j L0s0<&̜90ả&̜D&̜"fNۃ# ?k=bcPae51P5BrsdD0 IA1F:RW!Lj8 2X+@0 PF\s@E&̜9eOīC(8V$F rU#4C %1X(#9p0`F2rxL9(s[<" 9<5PsaΜ@9s"0 c*(Gd5F]Z#d * XGZcj"$3'`.j@3'f| jO<5B|dD2agfy~C,rZ\Z(!b]! #FFTQg Tfy*p*"930dmb@̜!f3BPFO5rx%93&̜30s>+|<#H<ՠ0yNIf 2rx$3sAޠ fWۻB,6 С5B1 JҲb:j uMd1'f 0 9D `LBfes>q}PZ# !T8@9<\FBPF0a朧$Sy> 9‘vҀ \@Ö2IŨ Y5B dўp ˆAO

g1gn@i@Tht0vUPAam3 #?g` * 8PJ1V1s# `9OڒC.#_eɈBTft:{H` * d`@M]XFACq1*R1*)U#| dj#FڸnW83j#9 `ԛ^]ԊJ1+{ĭX.k @B@cF20 #,@59穀9|u eÃ9$L-?*@ˠ0sN!sr v&yCgU#d `cձuQ !2If1hp 3T@I~>c@!/vUqY * @Uc0@U#@n:* - H1XjA ͟+U# *,QU!0g1!TP?,^!D١W}B(aĪ1 )Uk;*0bU? ` XT8j!X5B1b)"̉˟@2bp)K@M݊F!Ѳ^3;dgѰX5>Ve"f<5Ơp1.$E1Ҳ3€FݵPEYaP)B y׸jR&-;xU#$Kq1Ts! ԘpWЈ[7pa@R8 ab- *Xuԭ:TB@o64e8$Wja@cHt!Q6k5iɲcq5B "u<$0*Fa_aˆU#`lRz˂@v ui iĭb@!X5B0b*xfVHx.]q11.s+TQkǐ0b!X5B,!,ˢ}) :*CPA뎣#!dczF\X1JG!ĊU#oguрP qEPQU93ΨzUZ8j zjgZtTQ pMP#VB͡Z#@#V!^x# 0Z1ܵxˎX$P+aĪ2*9JgP#V@B&[#$u!cGll>VLLPUG HFuկW!VP#V!!+~Uf/CD1ԊF:B@Oz|=XYd BV:FaĪ#$cuA@:B$c\DKg#  j,|UGˆUhĪ#0bF:B1 `QG@+nݤKk=Ŭ!Zی" eXDT6aEgX+!۳ !8j1uaĺ=RؚKua2[P+s14FĪ#*Xcc Vj T0ba8 d#PQKgG ^4BPAkab#4f8a,VZw|` YG!d+*Xu/hW}k$!XkT+&jb@`bx:FaZG!tW}dccq@aZG"@Y^!0b#C8 Ƭjq!ec]Zq@H8"dVU0q`8p@PV#b#@Ez::B$#:ȡ #uA՞a-{p@,C-{p@qj|zvA*R^0cZu#Hac< V;{E3a18 18 5bĺ=]8u$P$#:-[ d mp@0F<#uFi_4EP+X4S8 H8"H8"H]Ǡ, !c!c:T ۳Xl1( Y4`ZC8 _=;$bZGq+eU[}W;) @e'@ AXU@2Q/iZG@(FuDF}TPv4jC,CV aĵP@DZCdUigNd$DPVYJbDz( jŠ݊Cau{k5kPQ+u@Eqq:B&NH8”]HgV z` =[ b*=]8YPSvb 4bbZ+4-*h k1 .*xz!\B uS1*B0'xZgZF*غ c@Tpc=BcxE,k=B$8ꂌ11+ o!m K9H@an(#X#zЪ-{Ԣ SvGPuH5etw@ʮ3q3zC@`!# z_xQ zL`+n(2-펺@cX+@2^ HqXpŵ>#1=Ut@\8^k2Q(Akc\rV!qG0egkDZ-i '\-sA KahESV0 C!#oG]0k=BdGXz|,DKHa0h2Uk 2!< kr KH"c pV)lw!qG!qG֊ ׊Z עHYըǡk=Bm}i! A+9Ly͵}l)H$0$8EP`\!8xê٨?ZjFh`Y@)\ P [OBSH(Q+Ҡ:@Z֊xhі( $chٺ4@8V<qc])\uHe*9Lye@VQ8CZ9H@W\gqx@0UI*=+@G\AJ5eZ+dG,HfGEqc`ZpPQW=4;qDU$8Z#c8nl]z ]ABfU0T҅m@cֽ+⠻ሷC_,%㤊@2#z3z;` zGax@X)8pZ\Xq@B8kA[HZx@tc~MA+2 `eRM#M Cx[ͦA` ^ &@azLZ%¥ $1&ʖNb6 maRtP% ]Z!R(tABB:Ha]Q:>i%h (ڃȁqtYҁd)Ҡ,e ܲAZB $&q\le bhK̡-ᶋ 8+|xA,zG}@Юn'-aB1.$-aQa X bk=ƢgR(4誃@hUG lU 18W:H$x  *xh[H"@E]!B!Xw\HB8 a@ahKx@ź Cĺm9R ڔ l( $$«0DaPZ$,A0jD 8e:z!0&6lYjbҲР4(p&b^_ueucq& (x)V< Pz€MAZkfk)lw+ԸQ=L K7p˥:pFP ȰriJI}$BB 2( J jnxp[7G4XQQ`kSPc%O$B 2àl F@/ 6!(P@deZ M 02*`) (Lڱûf'X@[H0`kS` m RzƣVBq!1+欻Ǡ%C[hNˎA ULۄ5@`1AWCkð'@  (:_SN'BF 2ʂCX   q6 ,u= %1`Rq$쏯1H-L @(qզ ԥǠ.q\HeXo^cX@@q<`҂òLA,WjK>e G|Y :H\6q uŐ1_@xNk$DucZu,qØ޲QN1YV4n6+ HJ" [HX,޻JlUri ( Dm A!c%@dLS @ NwWXx@00hk @P)T e9 $aVAa֦#?h+ $aY%L+ u!\xG1\ 6ŁjFv5kZx@@bB#< ԩ_Ѡ4h% ò^8Z,uڲW ?.C0= -0ipF (LDch[z $&0jS*zԛ-LȘ0A * $ [; e\d[HU찴)% KH0e i Pq '-YL[; Mm4g/a*p[@U0(NZŰ,a՘rS p) lm ,e +X] bˎ_@@qr¶=L[&e Gm,z ThFCk (B8mciZhR&sk K_]ɔl) &D4 e.Lے usRaYŞ`I$%%X@B 6X zIk,e BI)Tm=PH ikhNFQeBPT>ԊNRrMfZ:6X,a@iYdNBX4cf۵2HI$mK@j |?pWB,V0@vB'K`1-K qLȲx]Lڶ %X`,e ^4PNBX]q@8ZWQ4ઃ1Ԩ-ugz-a@81M%փ TWHBG]q]PxQk}S*ҶE"- @(lڔZ% [&lm"eI1v4)-*Ĵ`mc4Z+@ `MKHB&*4b)X@`1L6 n!h0à5@XaX@$4R21P6lm _dư,1mK@` ˒&StsER` &Aa֦ i 9[[@ òҝ]y1y)TX4!jaZ!Q@(^|)@ Q7ֵ0"^L5(zT6m ,eI՘4A%6=Х $0h- c`) [t9ZZLX,K9HJ >ѭ $$4RPh rL 6òIiXa0`ilNZJZU}0Pn5@0& jSp`cXa 6`L˒& v.-Yka zMm/vLe i 56zKH@qR2%MP(aUmT.`0V2Dmt*ȊHZq`8W$B_# CvP Tt$x૛ LC%M 1,K @bכ|`+9 Z  (LDqeel+  v@% 0R`+Ҡ0( L")V&&\ 9r9:f$4 viDȘ4A@\T6\cᲄQiIaY`1,KٶrxM$BV& .aYdKabj %PP,i[ "㰤 (L7,00wHE%Ddiltdž//@8YZ@hL$@Y2YғD 'ud 4V&¤4Y D@Fle"XLے % %@HhL$@B,0ٕ7-L 2%@ˆ.h,KzK;Lv) _OMR2r&KP(4 p!$a@(a­HDpiPpkŴmaJ(t(2t04'_. AaM0%=m_ rIM$0n6a`,\ȩ ōU/m 3hŴmimas-aPZ#PQ/h A/me `Y$a[Hö2@PBijIL$!qn g˅1ٖ0`Y¤4X0 wYeKH$Lj@ D1l[J4M$`1Ea[!UzB6㰥Sѡ\´@hKBv8iYfcm#$,K@Hh]lDcض!Q&Da>&wk]@ٲ HhMH@a`-aBƆr..@Bl"Q,Ka,aB\l .6~&@*vNm5G&`ÖNEl"¥Ka,aư]M&*4& \l)mK2J+:̰M$@ [9D 2gcvnm"0f 7xƕeasڲ'xdadd.76p i,i%+2Z貤f ( &0f Im0ŦPh !&0) C(4kMNeI v>Ћ8[4rML-a, .6!M%M 0m&pp& eI = EEg˒&1l01lWaD&pyK~<Aရ4f @P8&XY^y[=] BΛږ&@P8VlKaröIr4&'y@abNSn27H j`0 t D8k@Զ40AHhP 4: p0YI^l"[6`4+oj4dY$4Fm/^,f˒& /6bڶ4 aZ  pnoeIeBqI.I^l" vDcڶY8l@Tˎ] Ҁi   n65Hd1[4lYưmirK9ö 0`1,[axyK0P]iz :5'T'Ւ&0B t0&2@(ŴmW` H6LPhdۍ %4PlKB D@Tˎ]A]Lmʨwy{aXhizyN`mIamA0 Yii @q-i6abf鲤A^ A^d"2LdM7-!oQA^d"2:ȋ;F%Mb a8`1<-2Q{%%8ٖ4䪗dd/չ֞ś#[aIln$bi)Q<&0 DeItٲ@N4Io6XLm8BIy PRMD`1]e(J:͝C׶4N dT0bo,j4D¡H,DB Ȃ$#SafUp V"3M$`(N. &{ tL3nltr)Z8] `~le1d\c/h6*diB$6p%SZђȃRm&j / /2ٶ 5"D.Oy Rn ']e`d"J:M2@_ޢRUd Y8kVXZ.1md /2ٶM;Fm%zL"{Jwaf), Le&8ضa͞"3.DF`UD"#"M&2NjORp dۆ Lqm 1i ;'oz㢮 `.P0lۆ 4PB 'D`1\.ácqm8t9F$]M`@&U],2# &mn*0ضap7,M&2Pڇ22`a\ AdB],2Pt];Pj38 &]8(St]4X8ț;F*&&bXLrE-& Nd@quQ04ٛdd`a\J:_ʳcvulܢ @qnm3D8l@(/2()E1۶app,a y;GvnlLB  f"E`Gp $̂ atZDY84Tȭ)HDX8ț8M&2Pl0D@ɿ&Ʉ)N.AI'} t9 tD!Ѡ^Y$Fm&1Pl[v ڇ;YRl!+_)J:5Z8444D8ٮ 0! '6Lbd o0!Lm,䥜N(Nm=I(f6LbNA`"4}[fA^&J.&=w݆U^[7&&D4bea`Wp &2 t DF~ )5Il`,,Ҷ&C%&2vɎm& Ȓ&1ۗ Y8Ld,6;vuHXw%"/Bq-ZZ@$HDTcQ!!aM!dܗ L Z8K9H , Tqrن%tLl- bi(oeM#W`FwŜ1=&Dl m9@qmS$FU,6!!9 .0(Nֆj-0v禗߂ (/r{vW`E2-.$ T[D H76Uܸf$abrٲcrۆI {M\ vIe ɾ,o7g7b ۠ZOUM) HMr&Q"RA^MTL.0P y)p i*o nl/* "dV&"ParYP@R `ČKӦ &b2 QvqMP da+1 Pat XP@Ą͕"3Pabde0jmRbr٦I v&IT #@h$_`"* _@bg$*&c6  Ld@% d,gmJ8E|+O]oK[^@ P1l$vmo_)̀Ne^@ \a E2P 'ۀ2vFcQ(♞ 2d: v&brنIanm+2$1@(ط/I `! L5Qd ͕"3I&JarI VswɨE sm+$WZwf#&("ParaV|.$2ف etY&tb,ep@MP 'wOlιk[!žYHDl@B "BP '{I '{e&1XV_Av\"pǥ2Lbrn[xHRl!,dor P~Hdo2 "MA 6xfi)F ̂˖6:'^ZJV{ -/1ui)  'b@҃~ ?m`P<Eebo0dv ) ("" dkB/6 "BE .@cG7 ()Q.sWlv0 `b;)NuE|\٤NJf*ɄP,J,)ڮ XZHNx*`9\C@^eE6(do0 SapI Jxh/d[:wjob@K"BK @wE"3km-IL>$&j2P '{dQ0ISr ) @h|S{[!",}D=.Pd@&V^uI" `%0*d_@X&P d_`@4- m2BKT nK8i , bNdbpۦ Zxhw73@%;p vI4@2t깣͛`&D$0*}b*L^,`iz 21()|9r154 5P^2Q 0tqj]0p$tdlEc}Qm]!C*d_@bpۦ Z88P d^tԹC TMGؗ1չ喒E+[H d@-<8P d*FV,xu !lXL C Dij-/Yt<3\s063&ə eTc!2Cʘgrk<M"ed&'՞9 0d&mr @mM=8@20LLd&g&1'ϓmr^`2jp$3(d& m |4B 70 HI4Rd@.I pS328ƨ( 0ELf9REIfr%RIe&'GʙsfNd K@@DA=9PFeuN\oGc9xqxLЖBFr&g&C`<*ə e&< 39$px"4ehL͆ A!B94 3@0B#"fNŐ`gLUǨm@ir+dTP5FUe3:Bdd1'uky@ g&LfM>CcĠY`E!b&`Wg{7F("jT"0ả2rx0 y"k*"`2QK>ə aCPF2rx̣KPAUN`eF~@m,"?qTPo a0gOULKDpc G`,;Gar<9<S_#TjƠVPDA2z yr`y7P̙#`PF&T|*U8”IƠ€Q#cU# C9 0sS /{"C0axҡ5Bc5*vͰx`CoQ5ց""F`FCl䇡cv+a]X`Ú6&R 0Fd`U@S"PA9@91 9<2rx*j;pٲ482r7q5z"F@R;0so҈֠FϤ99L@9G9nZ"bb#0&̜)Df@fyj2oQ (#9?cQ5j0szCU>Zi&1I9g~*X h0aǨ[KaY=xT95  3糊`<TvDUf<@ɇ ÜTMbP39<4@ xjT9mkz&!YxPU ux ]T 1H1v3, Q4 1 \q>LmCF@Lynm;0P:n£k}>u/|TBfRY12eqHزH𐂺EpQ:B#!X8pHHk,Yfn=Y2c\k @\@ꈧ҅#H1ƵRGB@Zjc? c@ꈃ+ u/)bX Haˤ#"rЃOgL3)C:P:t!b1b1 Xk T8UˆP#C0;p PXC8֭B: !kƵ L"j0 pCkC@#:0Z8 XZxHq\G`1:Buܺ  Ef_1k !!aY]40#ԮHtˆU1kC@ :1@2E$c\Xǐ1VZDZl dx}IA*Fĥ\8(א xq! cQǡJ@ٸ0V{R1c2ղgX XUR ԨUq RG|׸4S-eBTX,C-<kCQCbP`b[Wz!b-h pC-늀0VHd bңc B"JFu q,=tˆcaD])9JgpCDa`=C0Z1"ふ!DcC_ѭ@T G@#:kC0f*1L_.5B 1^j( jP X*FZu|H06CKzE qFu X5:FcPDHx]8baZF1F]CF@W{cT8Խ5>u F07k}J=Gʔ2H @#u$Z1ƪ"Bm6֊Hw` p@@#u 0b] hYѪ`գFD\Aw+J9B1JX@@<>j@ĵP 1h67k|H` 6;2J+pcfQ/QG@6P-%:Ƹ1eJz{vڽ h@a  Ċk0=0ejW @5Fĵr+>k +0 ,h  1q/|aĵe*zlw^x@4 [QF\1@d#]륏Z CYx@0Ƶpu](+8@ak!C-< öXz8> P&1)~?RHGX!q$c1Exz!*+J3)S-< ` @ V=+9dC? X,5>V$6Kb]I,0APRiͅHX *Ƹ1H#vWbԭԡOv_ Iht G3z|8Cp‡z1: Yp1ѳ00X8Ef?<n~PgC=xG0 )\O8NX3GY9S3SO8q`'PAzh3 }8Ss< f@ǀe D >l0z`88sz!x iO'>h#8 ~o@pwc 0z-`3 @O>O q@~VO=>'z4c<>A |yO#CHG=9ҩ=#=HO~d?7=`!|f`8tqH @?:= `N}=FcG8`HOp c=x< :t pcezQx!: @zF xhF taCO0z1|6G=c =Y~D0C= >!:u0/v|ѣpG0:0a84F8<Dl0|s9|0Sf@Ox}.LTѳ~JϢs?2>ѩ|408:!= h c@C~PzF?3k9E?2GF342k903=jpOЃ~V< 4z1#8!842C?Ss<N= = I?*:0x ':  9>}C|~cFFxo 1@|4t~n:`|q:>ԩcOl?O2zփD?1SO(:(|2O50qԩ=z/#=h~C3zc? |s?6ѧ@S 2~Bf?z s=s=!<c>< 1d3G!@3th38>f$x=1!<|CGtGzIp@>gz38ty Mx'z2sOcf E40< s>d4zpi1c@|tq <038pdd< G0C0£e88C0gffG2?00C=f ct I>ѡ'> yO03~N3H88C> Yc`q?4shx`1}0O{@OCh@?g= @8S>>'n >13DI/hǐ}:S >=~d f_ >7j`f3.}1FcO T<=>}:G}>'x=!&g~` y  a@3 9j|s>A>`u =q4x?94"zO}C #>42OuH?1>ӏaz/ |2COH4z u/1}8'T`x8p/ "=8@i52x9'~B>'C:0T??~@4:>tC}>0>1Op Ⴡx8D3hD  ~ahCdCg}rd@fOz҃Fl`40FpG#C}2Y Գ~Bx8D |F>Wc?~`0|OpzӁ1?4C>1c@N=< |:13gz1h:4O q@e:у\x@z³|c >h@4x}G p`i?`O0:>C}6pht3xz ɀN| 2CtYhG8L}EFODQ= г5: |2LOtG0GxГF< 0Nѳ~H 8>hh?Da}:s?i@tcfO:5x`@q i/xA 3tԡѣ<гcg}O  h~b@>ԡc`d@Y ycq F= y?2c:uSgAnzgx9S800h`8DL1C4z< t8l?'^:!1} =}2'֡s `` ѩ~@~j`'z9z @4`30G}'x9`8N=`88Fp pѳN}4eO5PT~n >G:FgF `x|2s@>z=00>G2Gx`0|3CC:i#:~p`  i4C >>ֈԣIˀ>1 'l2CCx9StY ID =' N0/ }Cx5CAcf 8`@0s|c B|310xЃN=t #= `z Q >gc '< @xGS"z##4D3Qz'd?3f>9:0`#ѣ!80xԃNу |.>~b'|!wvpkpz"V"V1+&ȋBWWGHC  <`,HcHpC2їH?¡G>~`Cg1g}8t ~f?0KA}231 xQ40 p p @H?թc=I 2`0z3= A 9zA~j F~f`=ԩ`I?15HP4Ќa83xСG=k4O ~D4xCL38o> c=~F=xԏNF3|O`|9ـ|O i3ft@#84s2gx~lOzԓ~npj>Ca'4xѩDd A}0C<Cz `0@d~dHap2cI >gs?2 `p!) }G'z z9lz`4?@>8O>c?W:S:p }<|3/D?$0XOz>10`>x18|:C?h0lN='cpEO@`>C y:~P`pux}g= `000`4`Of|2O0zCa}0pO>4|$@?3gz~jdA?02C 4n_|001t xң|2O0cp S|29Уp '1}69c~f0Tj```tA2/c@ = |60=YX344O}~PFCziO8p 0@ @|`F4zgx=qS30xֳpG`8z0zM y< FtfcN= IY< A?Otq z8>< ԓ <':DO8#h21O= A~P"8p}61>Hc1O@?Oj1dzf_I!cf@?s0g4 zֳ A4`?3x胁4>O8u gX?5< sh(8e>t|CF >x}2|4<:0lɁcO>e/c `u A:|<zOz4g2<!f`4^D?p 'Ɛ>G`\\x}4GCCOg}!zCpI裁Ozҡ=POH|4 a10dv60pxO0 .= 9 a1?9! q|<|2?juS}0s'=|x҃>)"L0!}s#p |*x!8p `g= >g|}0G9Oq:6[?1YFc@Fpc}8`t>|>00|4S> Q4zg:t |$z>z>0~BC|91|:gC?s?'w@?D>h1^N=uza~j?4= g5|?S}zЩFO| = l`xgpi3z#>1'=Q8uti@H:hA>| A}8cfh<=gpx>d@>Џ'F}0SA3CO2>ҩ/p<XϢ{ >~bO``@023=CCxp΁1 y`g<чC#2}h00zS= p i QOciCz}> Pp'}CNC<`sj!=}s30 @N= gp>ѩC>= f'u1 }@>Ӄ>աCҳ |1oDOti 8Ρ@=k~H1;`>0h<СԳόZtcя Q?8  `:t Lg`O gdt <3}Ct Џ90g<iSG=A?;c#8e@dfxҏ|2j4d`1'!|4Cg`=~u i 90 @?-Y}<tipt-}>Dc`4i_C=kD;'[C0` 'h?+d 32F>zzu“>Ocf cf`O ||:?Jk~bN=~` S̀f`` hx:uACb^ H1;ߐp~b `>'T?!p i1OA1cgC\\x80G4~@?;G}?k=q  Qd `4)N}=@F:p 0cfd1:#~mz01zGtx@ pfpc \O>|z9`` ssy`xG==G8= h~`8>l= g<< =Y?1g1 P#`|03x1OtI?4x }4 ><~j#O5x0`x >@>~L Y~x0/G}"|6p <>чx1C!8dF8e ||g}1K3:02c !|:C><`@ϢDQ8ue Y3l0zzЌ1pc90zСOX]Hz>O @~vOѩC3s>ч8 h^c4pO 0g=p_Dz8pq};1>9E?A N=5 15:5PGf`t p|:өgp >'X!}>ѯ `@~N `P :էNc~hS0|6cǀz֩x4tOcf3$c3uI/h?7>u248g=' Z|рh$@>~L GF`t < |6҇l g:0:E809G=T?08eQ:p'0@N0zcg=kt@@_eFԏa3'>x `0!g> q@}  Q>>'t~xf?cOH>AL)!<>я D4:3L h q `:==A>Oi>=ԃq:[ 9c> zOi !|0>Ӏt yhta3FO8N}ko>^:у>=g@ԩCGxg=YFP?> < Ā ?3|C?0:ȀN 70@z~d? < QS32Os30`!:Gd @|<z a`G|d@:0 `Dofty!~NFpIfOxPO8pl3s@tQdO>uczg:u '' I S>dxpf0 | Ft#00 ><i3g= Y>9}|ѩG=Г>}>c>Od8sԳ>< >'zO!@:`_8G=j2c'=q`>'D 8fQ#c`2zGz0>O#}1OxЏD4GGh>g:54O~f|0sta  F|10Y?GCp`g\0}":E?1'Og0':C8>f2>|8ty>!}9!zO 3= >ԏ }60zև@~`` gԩ'> | |O A3i sQ:>ѳ>)<f>ӳ~ǸI Az!d htg! @XzN<\3eOC>փvC}'c~D 0s?3zԳFiO x9|>(L3`O0< 8'= FO5:<0 УFϢ'`` f~LOc 0>ч2O^z14b >9xг>yt1tփ>ψ ~@ gGh4Cd\= Y '!0@i184z>p 8f`4OpG,8<}&:#xv!N>zԈ|'>}GxС@FOCt AO:|S?sh 7B#PiO2c` |8xx8#fp ԣ~B?60P4dO Q 1` Sf~Z}<>'zFIO40`'dh:tq?LqN>IHGXO230|<`x9Ol#80A3&>@N1'='Ti3q ;}0:u 'x=y~Ryxg0g`|3Of@+BOz I:>>``g Ѓ5CC4zuh<0i?4c 3 z1pjD'}6|у`:5|3g=q~d@hC?||Sh< 8~koVfaz1p < `Op `9e@i #D|>|;s SN>N=|C4s?2k ,0>4 2c>gxx }1<Ya tc!Fc0I'}o1O2`#:~J}!A3g=D3| P?3G>p A30sQN}Sl >F2CQp s=I>':t `d`<C}0<'xGO cC1T< ^2 [4X?0S?:gСǁz Oh}6  `fO EC`ǀ~b  C}$1' Gx|$:0:$zz¡1>'zЃN}<<y`GcppOp`k`8' pi <x H8G)'`P>80z҃>~1'=1џ"tqg:?by~n2gwvpkNzf"V1H\7BWWGHC =Y`>1C Qt`SzN O 5z0G}4cX24s `= y ԟ5x8584c}2d?| i?Ї85:``~_ht qY0ЏOIO#9`Oi4TĀtg4ѓ~{|HOC8>>G$H?2t IOzN!z>ң> zЩ4tGsxF©'!<`@`C0>С|:F 'z Г `D?6{9st`Ot>ֳ>C :`@LOPpЩ<s` `x4|=` Fi4 @8Txgxz1`гEGd`>20IСS~zc2op=y~DlC! SO1Ot9φ@:8 Ih 8Ei4Ou=,:#`_ zG}>sh}CϚ|҃~l =q:tӣf=g>>A`?20qL2C#8c:u 8qxQzNЃ>0s3ǁ }>p }c >F::_zp O~Vi!z>#~K:< oWPN7pjh8>>ϊ>GL s9` C?00C:!)g=@85tq}S2'T3Nz>҃f 7d@?::c}:>O>!x't `zЩ10` >׃>׃>N= Q?0=A|0QAOz@0xq4~Jf?3Sg:t ~D|_d t |?3C>koS}O@~D88!`i0 Lt zҏ`d?C 48sj;S< CC8810tOz4z@4c?5= |2pQ~l `p?3O2p Ч8u}0ѣGb&N90|3ƀ< 4c `;'':ptVң@0A Сhtj< 9O<f>ѓ~T:cx'l>f xO >G:t>ҏ Á!@#Tc 3>''8>4Dg^ч}Oe9s  Q3 1xҏ'tS}2s3OC1 DSp3#t>01SA41?|8O|( 8`8tA A:4z'z @;/@d`O`'=Ok0IO< ht y~t?2'c E?:>Ǣ(CŐF0Paf}ѩ Ї:8O8`0tc4C NN='0c@>= at<~e;:sz `d>Щg>pC0z!8tԳN>x0|'|sOz@^s=5!ghF>1)z)8DuFz9s?10\tj4O5=Yc z/4D~t|4=i~`3 =~h@p3f fC>ѧ8841xG:FzgzOp y~l?$D?0ѡglF3?oXphd1OpQq~JuyD88d@|> ``x'~ROh 0O<`cH `DC}0zp]3|;2A?3HN=>=I:0zև~`a`Op 'dЏ C>1@4u8 `0zӀ#:S>z'}68 <ApfC?0O8 )8D<OOГ '`z=[a:fƀ< i|GC't QO< >0cp}Gz9|01hOLMmsԣ~L as=GP?@OT0Ou020|4Щs x|`4zhF1>'8dz }~l> c}$z9f#z78D?C8pas@52CO:0x>ׇz1c g!:s"x 0|G}C>өc??aO`@G4 4s `0#^0~nЈ02C!hpyOѓ~b  9<<Q3|00k'``1 7P== Ѓ~@>F?0~z#}6|20 '~D?%1?2?BO>ө~B30<`pSc~`0@=s3G==>2)<'@>>9©0x|O |s8 У~ba?0~dG ѳ>:f?3N> wvpkxzX"V1uBWWGHC fcf<C~Rd@@OC8`@8 }ӏ1OφN I0=u hszhtOgdzNN= `?5uh@s?30 azЃp 0A|G}(xu:pc>O#@h0<У5tOxo '_<c08cz `G} w>|:2W}׃!||>`> S|C I?"<Сg}xb G~Fdd?G'0al@>4H3|:z9g < q@?6'=IzF?7S85x С0s`g=0t |2S?2G}O0G}8g1OpI39À^8E p>֣Ft =is=}6e =0zc AzѧCxF~@thFz1+)>GcчTOx|'= Ij0 <x>O G4}6c|8ч| 0~bd!@<cNL?08:u `>ѳ0z0 Oz}03> '= GxСSa>gx8u Op G>z|3= A?5|2OgL}7/>p:pDO1`}8Щc> QF8PxӀ> 1?3|O5000:_z҃~h`O1}O>`t G}> ?CO!= 48`}` |0S#=< 8Щ~f 1LClt'5DO2=s}3ux 13я 9Sz3 =Y |0 чѡc# q@< I>>u~bx}6Gu1Ta210:^>=@= x `xGxe 30xe/8cHf# A0N}|O #ѡС'ѳ>=!8O'=Àt|'}pGG y>0SЇC}2s;_}8<'d `SOnph0 `@D8>O>5:>9ѓ>9pCP8sT><80zֳF3}>c> 8Gzj?`1h#8>0:ei>z>?Wk(=3:pjpi>= ds=~TX ~F?pjt >`9ғGs@ 4xFlpA:d= I0D?5cC `d0 nFoE `|>h>=i'DOp }6G0<|84=I~d:C:4|GA}4?@Si>я >1S3O4Cx 38 <a|2CGt>O'~ls |g=A?1|00 QNt СSOh4= q@8414cѡg=>Џ|8d`“>֡C!0e9O5zF>9C xyg}8cԡs @3uq@:p> iEA!zOYtG7':4| @5X?@0Y4{ tYxg@|-:GhFp 0:|G z3}03}2уF:~d`>!:dFptp34У12}2?`3^5|20D>!|0gt u: 4>C:4g}8:G>t10x45ߝo q-!|0}4}2N Y s=@|=C~``:u I 'C13S@z130'pj>>5Q?1@e?0Of@3004<c:!|1[}oȀ~F8t D?1u0t}|8C4O 'Sc`1!|}}<z~` z`?>ҟ5Ѓ8 `(2h0~f>Gx dcG8S13g}2tNHo6w=gL~fN=|:CCyDCS`8ui3c 8f|ѧ@ FOx>= 009s 9<0<xԣxԃ#zу4~F?0s ` |6pqCxԳ ap  `3H|0>ӌ` S<':<F>i@qv?5ѧ>g8~f>ֳO1ht `>!q0ggOdϺ2?`}6x== h8~w_ O1OtG='G=F'`@DC?;' xС9sx5|'ujp0 O|F? 0')}t|CF'1g!|?LO|1Op}<0i@FE?0?FwvpkJz"V1yBWWGHC }Oe9s  Q3 1xҏ'tS}2s3OC1 DSp3#t>01SA41?|8O|( 8`8tA A:4z'z @;/@d`O`'=Ok0IO< ht y~t?2'c E?:>Ǣ(CŐF0Paf}ѩ Ї:8O8`0tc4C NN='0c@>= at<~e;:sz `d>Щg>pC0z!8tԳN>x0|'|sOz@^s=5!ghF>1)z)8DuFz9s?10\tj4O5=Yc z/4D~t|4=i~`3 =~h@p3f fC>ѧ8841xG:FzgzOp y~l?$D?0ѡglF3?oXphd1OpQq~JuyD88d@|> ``x'~ROh 0O<`cH `DC}0zp]3|;2A?3HN=>=I:0zև~`a`Op 'dЏ C>1@4u8 `0zӀ#:S>z'}68 <ApfC?0O8 )8D<OOГ '`z=[a:fƀ< i|GC't QO< >0cp}Gz9|01hOLMmsԣ~L as=GP?@OT0Ou020|4Щs x|`4zhF1>'8dz }~l> c}$z9f#z78D?C8pas@52CO:0x>ׇz1c g!:s"x 0|G}C>өc??aO`@G4 4s `0#^0~nЈ02C!hpyOѓ~b  9<<Q3|00k'``1 7P== Ѓ~@>F?0~z#}6|20 '~D?%1?2?BO>ө~B30<`pSc~`0@=s3G==>2)<'@>>9©0x|O |s8 У~ba?0~dG ѳ>:f?3N> fcf<C~Rd@@OC8`@8 }ӏ1OφN I0=u hszhtOgdzNN= `?5uh@s?30 azЃp 0A|G}(xu:pc>O#@h0<У5tOxo '_<c08cz `G} w>|:2W}׃!||>`> S|C I?"<Сg}xb G~Fdd?G'0al@>4H3|:z9g < q@?6'=IzF?7S85x С0s`g=0t |2S?2G}O0G}8g1OpI39À^8E p>֣Ft =is=}6e =0zc AzѧCxF~@thFz1+)>GcчTOx|'= Ij0 <x>O G4}6c|8ч| 0~bd!@<cNL?08:u `>ѳ0z0 Oz}03> '= GxСSa>gx8u Op G>z|3= A?5|2OgL}7/>p:pDO1`}8Щc> QF8PxӀ> 1?3|O5000:_z҃~h`O1}O>`t G}> ?CO!= 48`}` |0S#=< 8Щ~f 1LClt'5DO2=s}3ux 13я 9Sz3 =Y |0 чѡc# q@< I>>u~bx}6Gu1Ta210:^>=@= x `xGxe 30xe/8cHf# A0N}|O #ѡС'ѳ>=!8O'=Àt|'}pGG y>0SЇC}2s;_}8<'d `SOnph0 `@D8>O>5:>9ѓ>9pCP8sT><80zֳF3}>c> 8Gzj?`1h#8>0:ei>z>?Wk(=3:pjpi>wvpk z:1BWWGHC -D>\2>G4O00yh}?/4:8O,cpGt$n'g0<0?=xУ~`@Ox= >O G=G}>= `{:@!@ Q l#~Fx}G:'=yN= yQ~P =G}:O#ap=hpI0=9G:n}0'}:cYtxO i xԡcS0 |'}(8t~pz900< >փ0p`~D@4fCx}< 94>Сg>A?6` `xGcf 8:z41_},<0|\L΁Q3sL idL `『|08|u1:L8< pqG=gp `d A  ~`OQ9O>Wf 8>1`l Yx=8e?4N= Y` 7 +}gw'85D4z~KfD gE |Ssx9@0_СNCxg ~z гd }:O8OGitxO >ЩG |  XN=q_ ~AA3`2O C>D'd< `:0 =0` `lAAyƀ >gg a'= < 8F?C34'Qf Y 3:@?S>~p ]O2s:>Sh57voz>NCx 0c},ak>'48CO88up3= 0scG@ 1s? p>'x a?z,x12|'=480̀>1q |04c|cO:=Gf0|2џsGz9|5O `Dfz !xGxx|:'=@zG=a 1v>wOd?6|0}8'pOz@8t:d >Q#1b W54O4/p~FFp84}2O`Hx2Yـ<1> 5w=k@ c@@c~`@1`|0Wt 8F:vkQI4:5thp'pd3g~|I?g\1 @<}6ci3h< ~J#:eG|c@1` ~tӓ~a_ D xGѳ~`x >ѧ2<9s~iA 9VO9!ѩ0s|8 `}:c x Gp>'`>^ CxGC0: Cx `== `| 20'0xғt 5zg𤧁@p4: wCxҧx|:1z~`~Nzx1 l c0:D29= `0C}2s Գ~V 8uN= :pYF a` <>ӓ>Gx9' ~bp/x9pt / kc>G}8?js>xO1}6}:10O~H|4CS= fOtp Sfs:DG=9gz}.:5z'zi` 1}=g}S?:>4Pti?0hpCd?4}8OF3@3G!LH<#`=3=c8<D?6}3}6S7|cC842O'8O8 T?Gwvpk z?:1R/VBWWGHC ;`:OP0C0g= 8~L`Ox~D`}SuA g=C~b?000'dhG82G~H  :exc h h0z=i@x ЩS=wxՓ>{ǁ8D3'zgzui`xgQ= `:яftIp|0g=`3c@4GNS>ѣ!Փf`:@ 18D>#=>̀|4'}&69OtQ?095Sp `8c?6Su|(x'}чz:sx>9O<>O 0=k4`Op~P 2w>q?6 `>= 3 ҡ809}c'ch< yC= 1x9G֣>סui1П0'}0OHxax9v/x~H?7O hDOСc4`O8<0ghFFDO@OX>Џl>gxzSdOO0$`I?1ap~axu `>5c|<!| }00c|GtpA?sfaf`?=>`>p i`“~@?'X ?!08Щ1?0ge 9td s h?I @xO G|<>'X>9P `pQ?10P?2f Y3 R~P ``L3Ct 1@3~T?)2 !0 >GuDzgCD hcd`L:4x9=j4:t'32=afdx|0:490c=A8u`` zOjt s>ң>< adX8F@xԧ}4c``xtQ}:< 7hz/ U4xУ 3>>f @ft G40>C=f胁11= `p0z֣>D>‡x>ӏA>>p|0hfA`ЩC>ӡpг> <|1#XD?#2}2ѣFc#S Gd~|_p0g}6?nSx }>N=  a8g=a©}<pЇzG 6ot#G0@~P id`@90гc >>ҧCx> xG8 a@/c~JC8sDQ#:4huA>2`= 1=`!֓O5| sg <yЏ#>1S >C>f?1G}2O| x1N}ԇi:@Y= '= >ƒf pp<Щ~X 3}<:t'}8p#fc=> A>'zЏ cC|̀` 8t 8es S}|0c>1c hpasnoI}<p i@ gp>էzЯ =A?40'>'DO|` 0:@z֣> Faԡ`x0̀>G0a>©Fz }:fzN=c`<0@ [|1~~Sxz}1xЏz^|2Oe#:5d~fO8k;sO:`> 0x FOb;ԃD At A?3g}!|6:t Џ}c'x҇:hC5``1c|G8>O 1O\0=}G18'`18C i f:d?1s< >~APETAGEXM Date2004Track02/10TitleSilenceGenreSilence ArtistpimanjzigAlbumQuod Libet Test DataReplaygain_Album_Gain+9.27 dBReplaygain_Track_Gain+9.27 dBReplaygain_Track_Peak0.229712820826Replaygain_Album_Peak0.229712820826APETAGEXM ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/sine-110hz.flac0000664000175000017500000014665214035600052016717 0ustar00nicknickfLaC" @X"ߌodZb reference libFLAC 1.3.0 20130526 TRACKNUMBER=1 ALBUM=TestsARTIST=Quod Libet DATE=2014TITLE=110Hz test trackCOMMENTS= Nick Boultbeee #Z'Z0kA|{.>zy=)zOdblMyx  @mN5%"%@͠l6Kp]=Jl{n[ǘ8< kp|>vxzh,5VigV(3L-APF:YfFa2dxE8VS!9F0è:(:AŁa4Z xw`r@AaT"FIrqRDTUseKuR3L$Q9%SHz(%ǔj;mNx<<.MO-nAboY-i/D&oKzI/[Ѹ H4 ~gih` 筴 4WWƩ{pI.Tiy0VA Pxab 4肵XRXRFx!`F*h!E`(ET*<:pŠq88*$*$2Ò )BVVcC ds^:Jt4B i[PBbT,XN, ,A7T]_4l |eм?ַ)kdf؛5N 6/MkM{z@55"h5A6k|L. [_bm}-NN? %F֯X$bJ.mM ٨e%lwܬ"E#,+(R N* $2ü"S) R20Q(!#Bü2QP"SУ* s’hWUKy?N  8&@с$7qP!<$p5h ?D'\<^כri>.G=/{tl4>MjOVRJZO=6~ȴzLXp^/wҡ׸h`hj5=Pud`ws(2s$U `$1A!C DX$ XU B a(e A CA3Q`0 x1V+v%:Bu!tf$Rʔ"]&$Fkꯖ ,Pi4Y& į[h 0=M&^Rh5. y6?P5o-%"=A%g_'DIZZ^ԗP  N/ Bٶ7;? Xݩ ~v\&JYĊi]ZL9C!!c2B r+EQ\39(2A(; )p:QqT+B)PшAvbGX[Ď,<6GMr%$פ>I%

.I)/k-= `5ľ M@ Ŧ @!Mm $Q[,a<ųTYe<x#9!"XW: 80,$bQ\1 #98 :K@$CA ( 3qH"8rB!HC1ańJ TDR5ш$u幤4HoSH-ĸ'-0Kp[ 6 a,~mN~v&|]:j&$yJ=p@Ⱥ>]Nɧ 8,.Ԭ%-'_] Lj~^ n~[KI%eԖZ\T _+[{dkߧL=CE q9k`iqe7hK!gUv9aFI!bw:TR0TdxTw#aD9'QDAD vC :$2;,#)L)`cg( TF@Aa3xWRDȞWN) i5VA j Q3+Ooվ}mxYOPk|/Ͱ>R}<}}~V~~(_4`:.Mm"u=D)K.,HARȥLg,ȂDn4 FC%J,04 :<-P4=ԒƑ $SzCL$U֯DZ'4آJ[ Ri̢D^!$(kx,Q.%*^(H#Bؕ4~J' Iϧ $P@> /d72uܵz3R0XyN/ U-ߞB񆘔$NVN$E떭骊R]_k/2Ѥsf11KA#Q",4͗oVM)nrHYQ XLgx(RUVD\ƺ1bZ #cOKDD-3z-AAᏄE 9/zEqtM f|+l,hy jLn -9IRQc F g X4 eGz?<r^e5W2Nlh1ͪ1HyIe4L8(.M1j5ѥ!c\xPHazISd4ζ4Ab#լJƜO9y=6p@(OL[ :*E$<~pEq=!sT5qbuŹӏk&j"sb*I OyGF 1^ocLm$Irܛc_\Wc78yhj$RNp(40 hXőYMb\h@HVg؁ᇙElJ,S JRU%a'&u #QG$Hb٤<ﬨ(լhd$,ǕUy QsL=/$߹QNfOv-n!MeTHҵjaCHjxSQyFmcJ%u94J4QhℕcJ4 V7zal묋q&-%ZA,B)3R!vclpҫ`J-% C0ISJ(ʞrK)$GE$vN3203.X,v*(&wl?fL䶲>80+9 !DI.Q#Sa>VӳI'R[YGmkTsh([LeےFj*BrvHQ*e&Ne'2R2e j8ʜJ%nEѲTٻF5ɣRttJnO;8E7#ӛL8Cq( 8r)>ӥڤ'eE2CXH2vFk_6ZȻ9,CɔϪoͺr:M$K4%)K2Ҷ܂q&398eҵg7k 43S'j#D'%!B8D)*RML+n1DV2%jg$Mg7DR]"(T̚LN9S}YZT휊DQtv}ʒv]*TVs*}:]-eE":\t}vvR{Lq>TSkc}ۢ)ʕ]>KIrdiVZjG5eLNDIMȤl2\H!̢t 暚Q'&e7nVKJV̩HMJ$kIXV $)MS*vIt>T"gHBgeN!Ȥr *#bL7iftHRk):twg37NNElRYHZmHQ)BMfoRvSi3jg# ))9Tfm%H;m1.D&HNۉ4؝+]j$k)&N%ڥHGMզ4K#+\'.RtG'vqO)>SnI6s8!B 9"ؤuoN Q0c9>TYNeeIHԋ\ʔB)EHEjNNVuhBSvgR%EԄTDYDqkf#}:fISqeL +H4}E$*V%i6d4bNEKmx )3V螴g1'o'bINsȊZid)cR;v;9e0s>mӘ$Ѕ1$bT|E$rytQ jo+;)jlͽ g1tbd:]ңȦ8iI9>O&E'Vr8'o.Qei"DR):TcR.H%vj+S96N+rvR(bM[FnNjBTZmM:Vs(!Dsq J3ۦE%#K؋ q+99;)9ԞBtHH6].*||˦EDT:L&tnΑ b˺ZԖ7OHRtS8 %bge'Nn4crFh%NE'n"DD%nNn6R$'nhNNG 1ILVNi$.nC+8 m)87dMRVrmvE$G%'hrr9,O(BHIj!c".v[bg#idgi%9*yST'5Kryj'JE>M<&]I{t5h&""I̩NEdS9 d&ԊJq:)JB21[$dԑ&V%J!dQ%ٴL.ZSJ+IͬFdmMSt:Vh]Y6OQHNC,EkoV]JʜѝzEݺBȩITDZxHIݓ̵(VIܨ&p&0"1$wA)(`BRQ#qar Qbð9!)v2JUJW3us$4y[E7Ng'PԵ宗AxmmMuo ?\씤V6 _omIW#[L%4/E}ɰMnoS4c|r=[h˪g= #]RFzZdIKST'x'q73;cܙ.;U6viItt2ЯңʑZR(bFí+G!qwG! ;qP¸g Q))!qQbAL^+D[iPS!̤u3],e?/WS9y7ġ-8L%pjRټnk ޽/Il ӦM@$o'ZN{d\7Z[ZkJu-`?i۽=,\^jժK^ȲiާK)\Ú:PU9N1ΣaR 8 XÐc )0Sw QL1BQ!gWWUbH8aXb! w9\e0:b1ȃvrJT3UU|cHm]7ip[z}}z/+.\|-/ֽoޓSz_O.Dztnmk] A?ohSvm҇5uWFj/*2zz;V* *, .C9N* B83H00ds2BASHpb Q!98BbU \1RACs+1F$Bj;ݹ/M}XZiskߵmѳ)e"P.IJ_֒RkYvZIA4`^-~kool R/t[̋Ai۵a2].m('.'/{b&{sD"{LjK2d[HR + r;hE0(4)caQ9qF e@p 8DxU`CwaA1)HG) S!ԄY+Y]h^Lgg.}?4b?>mf \ԓEZ&LDe_ȸ-~>N'iKz^ˁ<&RM POMLDVkW!TU2J;sb38)q)gFrcVcA!00WuAH DXPD#sHp1bGC9C:c)]N[;HEd#Uvo&b7'<ؖmzpN-ڛ7 6Kdk씵+K{RJ|{ȹy6}dNhzɓ˕K l'>~&WڹͨDk=QHK%Qd)PAcB,!&ňRäV(DSf W )N)ca#w Ha(( B V(* ; -=ӞvEs5^BչsywBvyJ6e5GnɢekМ%.OfvY)i>\&VO'KWb`>͂ۃzZOpYBKAm>5ݢە/7|늼zFyK+{YԈ"X;J*) AS00)J)㸃,2*üc"N2+b*(bAT)D91GP9 a\)bREB"YJE,ĺ0RܕlU]N&qzޕͦ4ᶻo}i^]m֭N$k7ZLսkkRZZjlzil=V|52\-0Ly(7[ CfSͫZzL+4GKB!Ԥr\R1R9&*qJQ q;dYC 󎀈8A(BPp8 (9qHB´#:!3Rt B0)d;+c5{&ɨ%(Jb}xܴ'?\ }l=p~O\o_oZڿ>˓e.r/$ț%kZߥfֿ\WNrlz7`6a-_%n$QƘi[yֈiQyUNw3"f92J9LQPvGTS4ZFQ0B9F B!È@1+QQCAfH|ۥF-xCA%#QZa'%,Ų[ܱBF7xQSͥec뒤]M5V~O5IF\[,P 4HL[Ź55j&bPHf&(\?cĜIRFp,(0p1H;( ^p&%B8Eb)Q;"Rv"Q8m C)5%4HbX0t%DBrdn!Tc.PDM+XK)ЅG38s}%Der9!QHVRNߧgE PC VY< Rl8AS.eeآ H;ba "RZaF|GiR!MT0QF&E9Ve6sqG4 :%)#db\"MoȅiL8B؊(pb#SVZ4N!A xpFv!DTnm39*+]Z$ "DE<Rc靖tSb^(vV}l bS,S?GKCDKf]Uj GgtKٰTNeQLj{"rUpƺ8I%$(1h溩4cԤEK+CLr]*%ם=*# 3i[NZFn!l"9%//9d}rX%VZJH)1CgI'eoE.TBCʞ̿ER/!)(B'EPp¤]ggg!H];}Nvvp@PB? 20ݻnNgl%+R!Ĺ99"F٫$i v1*Dq.B+(&'#Rj" 3p( \))9;n#R8$mq "s} V!Htp̤YvV|OH(/1b~0(8@3Ɏ0Su0O]nlW֡8 +g?_([/ԚF{IUnsLze=EQk0DT2S )L+Xk-o#ȸrHFƺU]iD"1 B'%D(aB^3+lܑF2Vn"pA!M6'0 $$HNip7dԑ%73T1@ 42g5h q 0@Q!CQ?G1H0pAZb'+[>38Y>t]<\X^(Z.R:^`M!Sˈ8BϷiۥ s;nݻv8 B|C PcaAюх f 6:(bq-M$e e R1A'$(!#Srq.'"Tɱ (pDMF%SL1FvNjcALgQ/>H@eBCEG3;^]-UWꪪKBTJW+Uw;]>)Z)wR}k}rNS+ 3Cäk'.RhVHQ"`YҭE2 rإc1aTC)\#3 9JR 1!G)L#)Lb1Jr!b)JRsR0aadb1٢&h2K]t9N#:x|/^Z~UWUsԮ=^ZzKS\M׹x9p>=Uj[Y}fSG&Rdvĉ33ddb!ca D! A F7s1 S1C)aXW9b)b)Lc9B+0 F0a4!Dha!؄DfhБ! %G%LfXa~>-ZM2/ode?}/rZuz!-TU/uKߩk~_^>-{}{<.)"Sﴝ2]d3&l̘N"F:wr+s9c!r31b!LG9R9A!gS)G)G1\1\f9RW*Ȃ%PDP("B BDDdsSCN{{48]'woW?No++-+JR\֔SSEw)Uχx/꾽z'?~dsdapXY "AaaX"HW#f3Hb1!CDEs!! B16!A!!⸬r ;)!Bc1!\"D#!LLh73F1*dI%Ĺ,T"в*u*ΧSJS^W^O+m:|.׻ݴT//Kűm˔2b7nI #!+b6#!ơ4aA0D0`D c!NWG!r)b1NC)W)r1 B!h2B#!26ɱ+)]6RIe-媸.?WZZuUʥ~e鵧׫mޖNuiu?S|OU~UUV:\Y*tT&#i4M"bq8،؄ffc F!Af5s!H! b1LC!S1N)!b!Drq0C0 12cfa0Dcc"$Jԝ}x{紨[ {m~niJ~+"T+y{u<>*ǧa}Z\W{ZTVoLV"2Ăb"Ff1)̢1Uf1Cb)"S1B183)H#!c9G33G+bg#Hd%l6MM6Tr*v}e,[_-+?u_ܷUuJU+ԧz^W H-^+ΥQTWS{--zi~\cld=8j2J" (&"($jB؄c)!Xg3"Lsq R1R#c!NS)e!#1AWb 1Hb:1q1hf!QjH͛dQ̺y*.Y9Xֻ<-VAk~^^^uuU)UTuryJ)6e֝Z:N:oKUׯUXbϔ*wv䨜[&l10Q"D2a02 C!!jr!va!s3 1DaG9 v!L;HaBa0fcBhlD̙$$njBIEck==jמu~UWS^u>]Ҕ}+֝2Z]r\ J Ju:#󺻿??SizNjŲX$:rvLԜJhɍHFF$ "4aS)B!b19fSq9CqCacCCa!F4j !3! Smv*yrx ~Lu;}6N[}Wk׭eե?HpFyxx?wqn0RB8ө_L'eL- a|{AfcuVbhek.f؅SVU1B! Sq3xs8b9qC83c1 b eF@dLr 0#:NR $: I3Ur";ѹWrs}M.6w3=OiP%i$r}P}p P6 2'[iJSh.SN&S\τa3 ( ܋rQGXjŜd2ʲ+bwF;!\Vњ"f"! 匣8:R01b8H2wA X1v;Te!B$Ċx$"Q(SL܌rѽ9}m].4%-G-PJp͵uM4 `/}] @` imzhK] ` |~d0JNv}1hK[ff,őiW[$KJ *Jc΢11bBav0+gGQg02(T2AJZ+39LRBHc$fLTtbXUM"!(Fr&k濚n>W N]-z \F{ m`5CP-)hP~(piv}.u4X_/6=Y5sqSb5G+VBHҵbD, U!)T1 rYFtE )Qd!R*LR T8GЍ3d(:L+,r(vr1Fu!,GYIFXI\kf63]7 NTMo͵Wi_? %r0vnu)] xJ aPŨO ;kz Q<- FԶ/rQ=,iƎ,KbE<刷[)]c)JKPF)LC)gRCP: qJS`3G#CX c$4bD[w)EX@Dzng"zUU]jM#y}qW<&)h{[1{\yeIPM<$ӂ\&+~a*ml p - \6_:51-OF'BQJKD(J!QԌDdxS3"YGxmu;ҙ|L5>|l>婲Z~X/2^;LO&npzn=0 ArJmnDmf a(O.`!ZjVkƐ̬!f4e3UrTeKV3"q(R$E1J*F;V*Q*EIWP: 0DE!;QPTF;Nr9Y9&Y݈̆Z-VѨܬjkitL}7e2~Oe'@ QLo6N Q^RunK׭e^?aja5Dc ajM777=K!ک,ǑJDj"dfhQVV3V9Uњ*C:cQXCDb* W$w2) G%IYIC3LIT{]ՙ*_OMD`۾R %-@ H)F\h!B S5%܎EKNΞ"*JL9 -]"룢bY 1y:S-r劎b)?)S 1ڦ(`p0PbęD8FH$'NvMNմƈ! 4hLDBfdFٓ3flщ) Pnb|1DPBvhnbRvJY(aB#s+TDqaEik:]sQg.~r) !Ps)(aQjuc\È8!~\CeGbQ>Tn**IRDm4m97N#TE7$ȍLQ̑T&X$N!1A 1nhj'fɚ((bF̑""M#TNt;NC\ EQ blcmV0hS (0CϽbjQXE9,En*:ZN#vq#vNf lɤ7R&F0jdDg "f2 r8GlHFȈDLؘNijȄjȄh#Y PQ9!SpIjDXGD1[s+;vc[)os{rT*>GY R-ϝ1۔V,YUT tWH8ÐR FBQ++LVY"vVtVtK 'QIȭ]S&!;Hb("&d2d$Lj Q!, Q+S&7j3\̈́Q8B8 Ã8@AII19Hg (BT(Elv%O*yuQd#8Gn[T>Ֆ쾮oR *;K<\*v9ױs8@x"i$5N")T$dP'fQ;4DE3FQ + ș nhȉ(1ƦbR2Crbq4 (NMDYQRrv3Bv'%Egd:y/ޡr<ˆ;.@g!Tr=!㐨TC˼tVtZ[QR˭i8e%ȭiMd8‚E'M!&m‚9#S%dhN2E426$%&CBDb65%T&ƬL8܉+2%6fQᕮdJbi4Yv+yaFyȭz9JbQ=CH/#b厅!T9*-+/=|) gʋeeGAHv|T.q#S | cb'av\V}]ҹnHwlvR'ғS(" 8 ؎#p8#\'C( D( C&$؈Ĭԉ+33V' Q82#BSQM 9bv (nn Q6̣]I)'I*;Tu-GR=e#|E|!ҔHw./Bg,aX|R:tŨS}#HT| 9~(n1ޑsBSdS)Nj8n!Fc9c)5ɛ&$77-~$)36DF%'Le&%6H+3I#3DrHѲrricgB9"gcBӥ1B1ROУ#t9Ä,bƮxZ xvyUU-cttvC\02k39ݵeri9lݫ"iFݶ"#RQ99 Q)hH6m g L 8ᜄLhMq( 9hno40 2)9'MIY̤h'3ڧEg#vw}K⣡f $LsJ-~ r9 ϡ%2ggo/EOwg!̺Y) EHɢبMRtjݧ%Hb #ɴ"D"5mBsvIfLJ);cR(4bsV&Bq;FI19#S.hnҌP%Fpj"\ek7"*VRtkM*XEg3SBr+;UgO˾[gYcH]|9G̭+.˭ݗyYr쬨u.9:KH+Y]ȣGF6d6J6'Nh'Nȍ"&LՓ5%FqLRl١"f옑)%%Q+dq.hզ'ͣrD'qRdۤ51tTY&ڥR̲D\!L).g#w;:-Yuʊ!R #(tH,|]MfQe.Jf($[H!9'I3DVč&DZP#F4CLJeI352)&ЕBDjjhժ%jJN3aeDS)>nӲʙRr*~ EYQQf[}l,˯O[eerTQuv]t֫8±SR?e䈩SڱF)/1L9ϒL'6(D2hHEdJFrd"Е6$ȉQJ"6Ia94HfSs\'Fq*RVmRs8ґStgӑL(„v֢Xq3Ϭ\B-CR|rQdgo2RYu7!Ls}>Y5G#ʕ7#446BtԎ3RrFEd!)*5[A*d2dDY(4M D̚""L̦䈕"C9D٥3iH*JҲiu"ֲ+tؤX`a GSeeE **[y=Hv0*B8KuT^X]RvY/#lKeMq (R):XE1LH77DRjBV؊3S(Ԝ6DЙfɛ#sRl&%lmA24DvզHIdMv+t"]SҤMlRܬe"S}T1i.TTYjbvHtK,I{>eEI}eI5]RDT,J*TqERrl%"Qsj!D#Fț52#R(7fQnk8"!!C96iRrfM 4hݢDѻFSTtє4e3tIuDr)?1IqkuӣsY*.T]>+>K,ϯGgQlBRNv)NtR:ZΛʹY+8 <$ Ԥy#0Z )$%?PICX\{T0=ĦH,Y)Sρt@/=pi 0 ?lռԼA:|& P%AvZOtK`\ VhmKeX/ .=8Z($ Y| Iq" 2tG[*JYJD3;Y@4"Ⱗ@ap) W,qX;`USPpr)aHC"B2¨Š$31aPIR Z*Yb1aDs4U+N4(hQ%rUsk,Pjs~2ݶtkhl@47˱BtL_NjVzS%|f O+{rOf]^Ю0G9UGW {|}>32wkyx' _Q))RV"JȁeAHOIi9%[!.)q+1n-12YjDb:j貧cr,^AM$\KZI9d-r!R!Xآs)!jzVK-"}Jɢ^]]YTQ/QEqj7xEBn89ڳ#euW~kȌ~ّ{?vݡ{?8/br~`ׁ;7bz/t^=x^x]_F㷳(/ư^;:a# W4A.ΕB+jfƁ!#33 (4v;H0+r QPdQNA)F9 c00D HvuTRP.BN:rNI40$8 ugUp{$ i$)n pZӤRjZƨ5tof"8X, _--5m7ϱMiF/jи.ಃ?e'\-i&([)ѽdiEQ (Ab+RТC3eV$tDp9EHU$fA˜+3`|@t $9!9hx1cHAPd1Xh0hVJDZLy (H]E&%j}.HH@Vz`k za$`\d{&ț-'^ZIj^g٥Oи@5 IzKY-ktM&N<8[h__'e;l1n zpŪܱ]XMJЂH]k&aTK1r<ΒT⚑O]d0Sb%)X[SHD lKsz$ҘreZS&:sޛbCk)rjEi[,U) S<9b:hneXF+tA Ub^n x3FVoЍ 6t*ϊ߫{"0o?G{T3v~n k%)ktdXxo׻ġ|kj'=yVdE!,FgyH挄4`(S G1 09B8 (b10A(va8BaP43*A;"r#E<IFxhqrHk iO$`5M]b8廭&'44PI- `.i-GA6EɭmKZtP{T@Z0z  8M/m}nԼMZ뎜̪VE+]%")H"Xć IhRCl[oA5+Mm$t 8k>q(MX-IjQ7VG+7!HYHX"%Q B%iuX<Xw1e Cs,F&"H+,rأ1c%VRs5hHR2Ӗt)S†s<$_NBĘR&۳{Z'K&-TL$< S7̶/k^.o&xicSOB|[kKZJf}\ 1MzY9YԍeլC)D;H#3U"D&G3gq"^wH$Gb¡*+lTF(dVQbNY,C$VC*19hzXj7+ynKIBJ]V|Zs)Tر.4}5Mݻ|.epM ajh?ރH`xh%paơϝjrPa,MIO1OMTsD(_TN]"%eZntHu|agcV3%b8c(r$V*v)s,n`*9v2L;F"ňy QZP"u)EDf2,Wx(7?7E}-q- &*y9JD#i rLzUu"JUb)X;t B" b[,8Ф ɒs%ԴqO,7zl6] XJ[ 6-&_-rNn}m__^bz_W+k;jeҴ̈́>[԰&zoT*1lu3G1bAXAHq)F˜PQ8g`19 #I0 ,ҍ( I9 4K8 9-qQQ$ qD AL9BA1()*+rt3XIYC8C{ne|هs.?$kMIk-Zܷj]?YETO,Wni[ڭԍhvʹ_r=&#=go[dzۭi^צ[K8ĜIK;2,t0+))( (;{1!ChI81CK 4E([<ҋ9œayX88C8„(QQ(S@bSDPb e:Trjby9۴nҝm-ˣeF`F \Q#t,ԜwvO쮺ywnT]O4H7ƬZy-gՉj%&zMJJɁ2ONv=o/3}GRYn3U"܎"Js!aE@ L1eKY Y0 YBXqO (Œ0yK4A&ag4<ak<yq$Q&4J$X!G0^I)'ŠŽ54D Bb DPCVn!Mgruo|xz/@uD`}0fkW~UgUEUTWO6r[W$ojS#Q__uSi~ZtSdIJrN2=ĢǪr4D vJG(BeYZS^K I$Q%Ae< qe 9Y"V-IfEAŘI Hc9y!K hJ \c1Z `$0A`$ aF! эILEKг8%Ϳ6 p_.ȿ{ZnZKMY^ȵid) DE4H̼5UM6z=_]ݪYbH\zF~v?B{/~?WqS9hi e-G IE$T)J$r+aPD)aE :0`0+9Ia&YYeQIYA!8bieiiEAf<In0dC*CW!Ec9AaVb1t jJ$j&58wW+}+o'F4_g.UQM{{uvE_6y+"eG^?ydNחn&KeMc%(辸cJJ#(KيFAXEEq@ S)0Ibs4H=4OiYX4yŐyFQYm ĬaLa(Q )qE8 SA&)RC!HB<7d2:niQ$%  C~}L/O;ܯt(TivM_*QEO%YbR-d77 -be5[ֵ-? 6ݦw~fo3Yv\g"!܆)LG('ҘK!Am=aIAh$h 1^yoIQ;ooꪛ9?WdOkr?UUgE5w#Vwn1~Vmx5sKgWKۅ\UTWS$# Fʑf0"B00!'1(ô"PRC:40uP@tP G 4gSQHD cWq Z!CDQxbE2 INOB/!KU,Q\,ҋxp,@OP|> On _"ȸ0zl֖֒d&Ah=d^n!(pJ|iz| [Z_`Ke' p 0<8@Xx.0 s !(eҒD*(D2ʞ)c3βDbHp,F<;C<:( H+,;(RH)a`AGPE rq2(G 0 ,0(p(+b1OU9g{50Sؕ(ikXj?|j\[T2m˳տG 0d|Z^֛^:jk%=@5P%Bd/ZuL*>%%j q=7h,4By$ź3;, B1cwP*V xg$9@A`BAVq q8bQa`1B3( Щ w (K<"NC4:YeJhE4 U,]}+RuF^A$ހT~$+JI\ LП%-A:Ѩ}[M[Ozk]_ORI>h$/_-DkahlKHAdqeDb!5I*@yJr,@!c#F!1*9a0$!DbƁ@A FHœÐcwD,*b8 be $)nE) Ӊ9xǜ$`x`=Majo==kQqO 'f>My7 jO|<C}jl4.&FJɡJῥWmO٪]ViX}[ 8IJ&سc8"JXCwse2#(PqQ!HQ*q rqA;4 a(b 3q`#(U,:"I,;e;y"Td2#,AĹ}Lؙd"Zۢ`/h/~Ij5 0ya8$0xݏf,BU1c ~ДlO"x.R$xk%C\m{H a1iS9~BH,碦‰v[R!8ǝHA9cXCB4Uє0TC gRxg(#ätXUfÌaDA E!G(Q !ZVIhVvId <)eI 5$qe[0H=IF ~q.%GQu|zoikpY6JZiZZInhұ&%#x6K>x.x``.|.z&й-7Z.L4u-\%cc妗7sq,pEбB X ࠐN+Jq*iJ! @84*2 Dw ÈP<fX0b)  s) c JdH.jٲ h0AJ!B°WAcB; caC!H"QZDɧNgʈ). _c-5WMW-׮kz]Ij|Z&_גޕjO/ڷ~WVjRez^_$uqzYl55&I C G3(s#b; EQE!1raE0a(C!9(!8B R) qqG9A3 Df#0LfQ2LͦwgBSL&ov_mazlzjV%/ZvחzKt?KzJ^֥֭-Kj@\/-u¡|YeK*Mb!t39E;w!V9C@1;QHa109 q;(QN!0Q 0AD cA !1cq @!Ca3 F`B0D! ɑhj5FPBkTK ypUTxuqJQ\)+S[˳z_7II)zKK^%%kԭo[t:;AiΡ`^RU:ת=_YqU'!Sd"A,FB&10301C 100d A5$V!”Bq0r c  AE(@(L!1E9 DS f1QR3fH:wtE3):t,<++ťԴSk|_^o_/oMJۧJ-d-i-KK|׿ץi[ֿK^[i2zm~ծ[IjS:V|+EѢ|hnNCV6Fd!0C1DaC3A!!)9E9 Sq(0QAaDC QE Aa139JQTDea hbBcfDS$۳RXWBŷǥW=J~Wk]_iK~}%m-/K|楫z%$'Kڷ+Y+o䭾oJ>dn?G _n~gkI̱RRfFL&#!\w:X*Hc!rSG883La8qH(  PC08RabQ!B2A a01Clb2FCi V찋nSߔ֦Ww_RZ[/-z]4z/^֒zZ+{u%)I~iokK=QUJ~W,tytbeT">Vu2Y v*b0Rr q v90QF!(8 1L(A910r88ANQ9D 11 bAG8Fc!B) bFfrYӐFtOϿ:ӡ|z.]ETU(r|OKkY:Od-$I+J&:z-/9Q\wE\^ׯmܧenܖىJf0!6aa A0381R)a!0 +ra9 R(b(C08B!AR9QgB23Jb;D[" ڲR!HQ2kz\WW+庿m۫oked:ץ%ik%zI[k.KZOI>ֵ'ޕ+m֝WwMu*u"߭1[TsTbj؉I$ Ɓ)WN!JQV9cAa !1P188Q098eA (c )E( s9NqaHrE*NqLblb2c4f)+}U˺SNrv}Դﵓ+i6p-Z7{e{^N'KI2]jWUwau G\Y{ eOuD&II ؜0&,w+ L,)Hg!ArcQJa ;qq1(; s(!)9 A 19G !\sBc!B f1l" lD63$C\di>qfl/;vo_/֧ׯJZ/׵߫kۯk׿RIy^ԽڲRյmz'/KS )KA`^W:ΥUz__|[;.Ct*MQj_!YU+f,sa0!)LSS0j +qE saDcA0C1D8˜ QQJp!9Qq gB(BG1J) u1#Ȝ#Q pJ!#%{CNd/:q-2\+!#PD%*hQ%"$"#"DI D,!DBDD`IH D"B,$E.S Ȅ[!"A!z!F"|DZrmIDw˾-ً8Ad63i<{e8Y%驤xp꘴ҬSiVR)BLQR\ ,HYR(B$DHD"4 D$LHp"RE BIbąHA QPD2Qf _"zKiLOdD4\̨qlĘhŏʳi Cj89y{0d:'ȍkpe0FY("VMP.!r #HD!2 E@AdHI "b "!@(!1 " D"QR$(()R XQN"O"^)蹡4Sq9Lh14mm!m7ܳZl3٥+1'i~FH-N#H4N adEȕY K'( a"1 XHJ DHDHPI! !!D DBBd!ABD RH"RFB,$BВQaBj & D,%Sե1F&Dk+pMi~dMFWiҟ[vqoHGdŦY4Lq/K K&$ &+ ( `!R!$BXDHR%B$ "H(iB'LB`V!1JhDiP)p%&d+.2N]dy|Odg_w5Qyftv=X2_Z8GIʨȹ#BS$'"XH aPFB#@Q "B" D!2 R @D QD RB A"I Ah)M" b(VXIKYi4K]b{-6NSv[v^GQ;?l[ֹ^hG/C"{ bd')-L\W "d F%HIBQ#! 2%P. EP "$@V !1 D,P\ M"PY$XI ". xDG$)zD،WV^N2-DcFn[o!H:N}~˹Q؎гĦRLօd-bIDRb"$BB,0 ўȴL+X d~~l\/J\&]&&QdzPҚB$Qb Yۆxb$0,-1orLUYH9W%"r)\BYk=S1r%2RcrY=&8|c si/qZtXKZC!J4; Awu[YtGD4$(iBL5۝\=BkjMP{x`'~Z^^F5>%bړ^_a|gy/Ii/zؾCE>_B5~ `נM- [Jʌ:fhraM$CMQ \SqJ[J%b)s ic@1qJ)SC´x9sЅ^"䊶+D[jei #r1[Sw=,fSiݓL6@Z I2mgO%i6Gki%NzJ__a0>$cAitji@҂p|>ɼ|7RkMa-[4)1Qha#3iXEi2TwQTPTіw(s8 !L \r`8eHe Q(s<;2C xH9Ď*ìA\b1A c:,9DA)D,Β IQiiW1ۑ}>=I%뤵CGiϳFz߹<+c?hF ͸}~.謈Мtm#3wswWO^gWExQ:`]ì`a&? 4YSrz* & W3w?{W(6wH"4''/~`x '0Z'Oaj\]'%ϧ6`Ves!L^V Х!DaJV;$9!:rK$-ŌtQq5( \<dYsIŔRzIq 5R":"!֠XƵD%jz EK&Ϊur% %ۣeSgԭ%WpjZg_ȟA P7@l\6L GbT `M ~'2Fj M% ˙0LY XBG 4WT)T0 x,;  9aXH(Gd,sp!B@H!80fXb9*B30;LuHC\bZ6Y򋸻Ioь h/=cͮsfٿhͲNfxz:[F͛vQp~^^@' 7K6eg|e6n+}>@,8If 8[4FĔҦЎF2HIRS2qfGb>jsJYky̘Q&!zq8%F (ZQ) T^ Hd tTBc\氄 4V+؎e*bD% TLTo'd>(jX? [l]"^ jzI6?L՛a^_M[얟Ar[lKz[ȶoO\<`J-%=m%WQyXG҉).ď!bH]H_9M!6!&$80^\Jai51&=qn$KQ)0B"*\ż4HIE"c2JJ\Rz.W x23ʲ @h8xoTVyBFQeX[A,/-s-J%q5h:(+> I>'|lmtmZj MKϱ+idZ0ұpyp>M}jm]jfN`4``R|[)n9 1Vu]jCGgyK'k#LB9J# wC9a1gb Lqa8ApD"RSxq<1!9HW9 u&SsǂmTCD41MfYį=-PONpzn\?Qѫ#B>?_ùO^̏Z?DS2~KfL׻ ooԟtU" CnT/7<DDJ G O FPEt]osÄQi$ؐ )$mZ%]|TAH;Jv+{VVz+@~ߞjXRt Rߺ+\)]`X]VӣUʾzNlYiZu"K8ngɌƌFb؄3 B!BH 8'j@ F)03C1A ́@D@0A0Ѓ C"! 8Lr16FjQ$hMRE3G-,X:WrOXuS\W^/ʧ<݂_W[חu窷KggdvCR^ tks(ĤȈl4Fal! d1 C " cF20C02!@@ 1aCD1" b$2!H@ȁhA BDb'% Q80Cel$>B)0=׭ijí^E@E,sqߩxX)!Ga]ΰ}*XjYH(nm5'M%jMԛ47 ƂSahF#P3 C1 C `D1a10@1`F1L0h!8CJQ25ё$f.3.1LTV[R +_Wr8w*|~^U/U<֝Jz^WR茶9-N'w9nZB+&m q3QDlB!Cj 1b @EA % 40f 6 (b0@1AjPB@FB1 #@"ĄA#6Fvȕ jE%tA>)c=K^uSVx.):9Uì9k `Z~KzE¹aNN{:<+v/N-q-- س,Ή)%X(1&4##3Jf#2A df1 `#C fA 1A30a7& 3 F0fab CQ0HQ&$̍4"f(1?NB%R:-\T+aHgV~ñ}APTr燪z\RRǂGWUuz/@|zX.pU_uVR2r)<"Lp7"R4CcrHfF11D&h A L AC`b 47(3aDc#1l&s223lhI3S2]vO&IӮaDn"PT9H.Qc~ǣES ZRxJZ-,)Jo=OGJǗ]tWSȭ:]i$epm Dƃ" &aL Lc0̂0d"+2Pn0"!ba0A J1L #B0N6Ё(s61!"Q,dMR[&Ȳ!dYǞ)QR *)k)PX.P@_ʮUp\W-J{r]ި_j-xX+aXv:>l>O|#7IZ6q1IaJdf&%2pAbc31CDB & ` C l 04l3F! )d2 PܘNCFL7E4L4#c:CxJq!rⰢ"A^V ^^uu,=;^W)KUyh^ޔjauNH<; u9j[ϻz>By2d'$475 Q!D43 1Af#3(ha1d 0d!a A" JB@60C1 !! H3AG8eFfR2T#IaK5'Gqm+ I1s f 4GR)F8gXd1L9"w  f X!W)14f# Ub*Z"2#&./.%|Tz -Y7jE<&kIkRI)%?πbl| Yk/zMY.ĥ<@[Nmҷٰ-7EJh_T 8, $aꥹ[64 HB+!cL+$wђA!K chrC"1b(bBHV:$r :0Gx*ؠI`01*FHᄇ<0`Q+1E,( 8Z(h%OBVPL=ҝ5%iH}&EEi+i6ȟ7Df[V6adJ͐?Mo-Ѱ.[%5()7%*iL@- y4B Krb]Ivw :@RAaT+"E: 19D2H8#p !C@ CA fXs@`(1 W0E bDNegYhƝT @ 4kMd"-Eyܖ zMiOlkr[qfV\KNVZjZ}^X iy-i.F٤4-VFPnZM*/hJƞs8_Znb`ƐҍkXWFm-i/\2.o>jjMZEim'@%6\x`&S}.px 0Si*gG2]DV1O $X!)"hX0H<3P4"`#8u cc4+¨S2BR  9"# HFNhf*PcuD9!bѱq 0&\Z P 5BmwD  p{ti6h%AIi2L֒NE%NJ5eyz/ P7zJ' &L8oɕv/ j Ckal,S0UUPGZEc!Q*T;92 h$9x,8cc @B@@Q`WH0W@CV 3A  3t D+!XSRΜ).RBrݪL!(ˉ J(/klMզM~Űd/K`cI5%$\ ZdcxG{xyr-%'I.%:m-]wzl= > S{rJ!:ƈYք"Hb* qTB^! RCRaH#8)`q19 pFœQ ( фh4 Y@sCE0!!#9b'Crʼq!E/UqYr _afN=~P{֥m"xm{Rlr&&ǠZ|L..P7^ZIz͠Y$=z'Vm djqe&lkݶ5x.pXP$(kYDzca‰1%kV!#DxwK )E@RB((Wa p$xH2 3sHT)Fc*BZ huT*Shb2S$#YURČXe!EI* z RЗA'TpA=EǷ6,ƮJn& zKjM-xJtMH ͳ^ּ PL|6/Mj}$q DAm%rAux,y k xa"sr)␁x:3)(8d9 ! `BA`E !2¬S, XeDUq*!SC$"9Zq!B -nN !HZ`ܸ|in (ߵ@߀&@4p|\m :%/7O[Ѵ>DKZJlDKlMJN?idz{XJYVJLf8ZF!sC )1,¼3:X!)Fp H#B0F$rp8FPøb+;#1)( H!!r K,u@ǃIxHu$RؤyIW< h\jwqqw{iM $ P>И$H ZI&Ei6G[.%klLn5-7p_zpOcx|dֵJj|/_+ PojH(a,x" )bu-O#CFb;W $ h8bBC+B(T 00ecHFR)K$3 !0B+$b P CSS(; xFi }=IR%v"m%7DLѻ%2SBVɳ&H)FͲ'MP23CSRSBQ9&2pҘj2m%"iMbQG$LEeh%K&%Js+[zk}'}ŝ<]bΎPXv; v#ȶ{PܺϦv]J]o1rTO.,v7ILs!I6̦&hG54)#MP2#$&jnh Ă8fjhM Y63rQ6L7rR(%ē2S8ݓ(V&ȩ&֙䙺Yf'ϣI󳲣R9ɗ?{-ܲ-jN%s<ŒCHr*)g"">vȤTdFE'̍6FM۳Sq MQ&dؐ VRSqhДա6%%3h ffQ"D"$ș+fT$HD4KaJr~Eվ,]e9G!ۧGg"QHaD|R{-]Щ[tYj,Y2ȬR˜tEBcHkmt]Ĩ&n4"$F6#L2"DL7$'6Y ͓fjJɛ$MVؙ2bm ID(8e77'M ۡ$fI4,nGnBȹD+9tYdbY>YHv)gy]1l˽Ys~Zu PScʟ]Eg'bS)$"rt)9E5jOTF)1"j'$h #$FFH!HDnj&HJ؝;"dg52"fП#iVFL7MdJ&j"+t[)VVr;++;9:L.s\tVt9 BStQYsJ.ɲM{vʚM5Ҥ'2i%R4Е)l"Ln!)$jnn%hBBSBRbDsFBa 72EՒM I ZMDsq"ĩIZmI̦8GjKR7GJT锟TwE#!R.v[IeVYoKo +,睝kQ"ٿ_#OYg#eg1FGlVĚ޵E"(FR( (BR5#q!.h!"hDi"$BFFcSq!CJ''f)6LH57Ԋ$#ɩG5mۛD&G$խڥo;TR:t*\ggeEJ|*-x~bsE7|wyK|E!Sݧe+|b(R;*%i6!ĄT#DɓllՑfɑ'#fՑ3"&q(l# rA93q(jnDr(8&䩒mtjD,IK#Ie0O}BTvl" |gGO/ֺO=OZ~ة|tV\fr-G0vdEY[VnJJԊդ&5!2RrmIDL9JN%lJ̉ Z ݲ#hJFQ) Lmp(j[4%$ș5hѶ#Mm[$fv*r),ծVivYwoo\9ceEgBQEI=ⷎbXtR{BUS=JSG"!R]Y۴jFTQ$iYDS.F$mZ&ɓ5M FDԜeR$BRVXcY[>\^_^`acE~Uϝ]@jS3 C8F$2Q 1FcM HPł aQ:L3Cbq*ANR* αC$!d2ȵ1#Y׊5niT{Bص-_&JXH  (qh.tJ}Ѱ_l&+lIro$WWm=pjsmz 6=ƪ`{$Ng,A"9%_1c I; ;8gH;D sRb"@!Q:FqNQ2qp XgA@HbB Hkh!F #0fAZU:Qa!F.8HcИԐ4 4AM?n?TzoT'\^EҖpt~<[ W> L @x }>jdI% a7k8ݖNG0YӄAa.to 0, Pv4@4IA4.>J|vdIvx$`- p[(4nOh pI <сeI۝c6&n$NsN,SY2Ra"'D4R3b! IbES(:@@CA^r 123CPsA Hft HaTRrZ2d h!c%J2,d`AxED$W,0 el$` 4@LlZ{4nYڃPߖ?]o]zM 4^o'Z6( p|C[ dap' 'iA% Ne 0/iAO 1}DST OdiрxP=ĉ( J.~ 0 Ɂ4}\T&{#|&}+m -PJ[p$@xMݦsys7 +0ӒG)tFÉFH:TH4 a,9aH( R"DQqQ (9X XbE*,+Je4#̢9 sHBEi^w)&%֫!DYD<-Yjx= 5MFQ3@<(li0ȷp^ٲ~vmO@ylo&_M'_+=BlhKp qj]j=D]^L!e<]K;E ,ɂ,de[haᄄi]HF;F<se Xr¼` 8)*XPzTmlkjihtgLfdcbZX0d$ P1pb.)5ɫvTGa+[YdIcuE#-.ϿBjT*{:cer?0 gb:>fsլJݑ)C>pc#8DR[bVPMQ*&jȉ!)7#qnDlH"|F4I&&Dؑ( 4D#jJmvN!馩tK]gZΖxY>tZ)1y#YmŞع+~-;c+*\'!S8LnӘ"C>2FSrjjRnr'N$ČbQ!2fhɑ71")) "ClJnDT%&ۚ)"%"Dht+;Kc9F.aFxoϢܺ rm!\\Fl}NeR#鎕Hc+G1r.Xb~EVXEh&Q5j"Vܖ69L6DHJj͚f57b$"s44&ȍ1!!2B"blEfJJI̐C(I J3+jOm̤&}4.]oXbdZT {Ugn}=gG)+V^"bvyu.\t˷gk91MEc*jҳRnNDQ3eBr'6DԉMni I!3&LHJ͘nQ"bL"1"4'aPB+*4F)MFr"RVVNOȤt|gK,*}*/)LZHYoYqLyU]܃TA-01iN.cvoY CԼ􊓦MIVE2k 3Stȍ3lnĤ !""Fla)3"54Q96FhjLٶ$&ͳDhM(†ZPQQ+:^BtrxADvV]EejjEn&ZD%m єڙI 19cDh1lg 5Bq)lfd6FՉ""6̐NFP˄(P̢s(m[d5یx'S,#cti>TXʰ.y7֡Ծ Xq"-rDBXI!`AR+q! #A : G`f*r@: BøCx)c9!Ea +hC,#HrU if-N|q 8,һT&Il=oדA{ZפMv&ȹ `(\>=m$ o\ I p{V?Jّ.,T{ L?J4Az٪YY2pAH)sa ,)#91s Q  0DAN1B1PA`RB88V r °R: 0D a\G9J$%I#̗C3*g*QS{{{sy(yB!4Gp_ JH '`؝x7V_"d'lԒ^76Gȴ@OLGغ`^@i@N pyA0-Bqiy۟ 8i Rk%r X hBԫu"{ hSDIPvHVV܀,AJ (h QF0 Q 2`:Kxea8 ÊAq:NvRè)u !hR]3k5U9Ġp.&wu7i/lt_K֓A"n(.M'Yk-&%ltl I+-d5mI6m}n%֟|r\IL3)]MnMUҖFGvCMGrc*9!R*‹@A!AQ`cAaJ)PDŒPaT $< G,b \*)B"Fq((Gs !t0 Fx`A S)yMhYD3b.0ǹ I\j'd>/Rl$i@ Kn=fH[2:nMY8A8>OZk^׷FI@j(>N %p'uk .19<Yi?M.Bp.zOV_--67/'./7epl&1iSrZܚsȾxV" 20#2L ;$qa:A`RBCQE(Thf2äQT hg8GB`(AKMBc"#9Ǝ⢎1&G;Jtr8XQg !././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919751.0 quodlibet-4.6.0/tests/data/soundcloud_track_response.json0000664000175000017500000000603414231604507022441 0ustar00nicknick{ "kind": "track", "id": 212471383, "created_at": "2015/06/29 11:38:50 +0000", "duration": 3677940, "commentable": true, "comment_count": 436, "sharing": "public", "tag_list": " andyc glastonbury essentialmix ramrecords radio1 \"andy c\"", "streamable": true, "embeddable_by": "all", "purchase_url": null, "purchase_title": null, "genre": "Drum & Bass", "title": "Andy C - Glastonbury Essential Mix @ BBC Radio 1 - 27th June - 2015", "description": "Glastonbury was FIRE! Thanks for all the msgs.. \n\nHere is my set...enjoy the vibes! :)", "label_name": "", "release": "", "key_signature": "", "isrc": null, "bpm": null, "release_year": null, "release_month": null, "release_day": null, "license": "all-rights-reserved", "uri": "https://api.soundcloud.com/tracks/212471383", "user": { "avatar_url": "https://i1.sndcdn.com/avatars-000005594674-1tznko-large.jpg", "id": 3446998, "kind": "user", "permalink_url": "https://soundcloud.com/andyc_ram", "uri": "https://api.soundcloud.com/users/3446998", "username": "ANDY C ram", "permalink": "andyc_ram", "created_at": "2011/03/02 23:49:15 +0000", "last_modified": "2020/11/19 16:13:21 +0000", "first_name": "Andy", "last_name": "C", "full_name": "Andy C", "city": "Hornchurch", "description": "Back & Forth out now!\n\nhttps://RAM.lnk.to/BackForth\n\nFor UK / World bookings (exc North America): \nlucy.putman@paradigmagency.com\nand tom.schroeder@paradigmagency.com\n\nFor North America bookings:\nkevin.gimble@unitedtalent.com", "country": null, "track_count": 36, "public_favorites_count": 0, "reposts_count": 0, "followers_count": 0, "followings_count": 0, "plan": "Pro Unlimited", "myspace_name": null, "discogs_name": null, "website_title": "", "website": "http://www.andyc.cc", "comments_count": 7, "online": false, "likes_count": 0, "playlist_count": 5, "subscriptions": [ { "product": { "id": "creator-pro-unlimited", "name": "Pro Unlimited" } } ], "locale": null }, "permalink_url": "https://soundcloud.com/andyc_ram/essential-mix-bbc-radio-1", "artwork_url": "https://i1.sndcdn.com/artworks-000121689963-0b0pdr-large.jpg", "stream_url": "https://api.soundcloud.com/tracks/212471383/stream", "download_url": "https://api.soundcloud.com/tracks/212471383/download", "waveform_url": "https://wave.sndcdn.com/U2ozCLWr72k1_m.png", "available_country_codes": null, "secret_uri": null, "user_favorite": true, "user_playback_count": 4, "playback_count": 363310, "download_count": 0, "favoritings_count": 10061, "reposts_count": 1417, "downloadable": false, "access": "playable", "policy": null, "monetization_model": null } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test-2.wma0000664000175000017500000005510614035600052016106 0ustar00nicknick0&ufbl3&ufbl4 testܫG Seh݀cBl?[FZ0ܤ@#w<+""z_. Sejӫ Se<FC|K)9>A\.sk en-us]&EG_eRů[wHgDLz4DeviceConformanceTemplateM2 IsVBR˥r2CiR[ZX0"N)54I"t E˖^ @^PWMFSDKVersion10.00.00.3646WMFSDKNeeded0.0.0.0000(ASFLeakyBucketPairsr] 0uR ȯ6m*0W # b@BG\3 "@KLWM/Pictureimage/jpegthumbnailJFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+k3jFgh%$ݫq&n6j3Gq!Ͻq7>)5we;Yʇ.N;`NsZMtkQ=3MKn턀? lێ@ IsVBR.MediaFoundationVersion 2.112@Rц1HARц1H%Windows Media Audio 9.1 Professional.192 kbps, 44 kHz, 2 channel 24 bit 2-pass VBRbܷ Sez@iM[_\D+Pÿa $bD"""u{F`ɢ z6&ufblF݀cBl?[]"+4`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h]|" &`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h F&`h F&`HUD)54IF"3I8݀cBl?[././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.aiff0000664000175000017500000004150414035600052016065 0ustar00nicknickFORMC;AIFFCOMM@@ SSND>ID3 ID3{TIT2 test.aifTPE1artistTALBalbumTCONgenreTCOPTLANTPUBTXXX TRACKTOTAL././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.asf0000664000175000017500000002514614035600052015735 0ustar00nicknick0&ufblܫG Seh`Ȩ@5HCf*t_ _@ mmf_. Se.ӫ Seܷ Se@iM[_\D+Pÿa B@ PP@Rц1HARц1HMicrosoft G.723.18 kHz Mono, 5333 Bit/sB6&ufbl(`Ȩ@5HC_]xPF2 @#N.: #>Ý@U: *fTZ"-;|r*Di)ûfE]wxhP] g- SMzqtbd&ܪnt3Yd%8d(ZZDp&aʴn&X!8xG]xP&i҄S8AG3'vZjHl>CԲFݢe#i#8|z5LLe:Rq]gxXP)ŪIKX&au_z9ߢuqjw̽M&yL GQࡺ ҅#NEYN]xP].63 6q'l Ct<A6Ѷ -;"^ ­(:$kW$ωd]WxGP"CVʠ $78J2$2jʶcJ &P˭ J$&)xYSCI=aF!*$Z* `H#+|]xPRi#N p B$z'Bm9QB#"XuJ$2HÑP Zy]Gx7Pa6 r,몀ZZ| q)sE[}Ӽ|S O  Tuijw A]x Pmp$ꓞIA"|qڄ.j0>Zq4蚨ɘx+Wp$(^IGV˄\]7x 'P1p$^ ڹU!llg vN$}A|nlEЌ8e2ǍJr!lwW$BC]x P sxn]*ad˳݊N^uxGE7̱. :Tb zHVF"$Jarϑ;8J]'x P1L 0w-68ud{Pr5:\5JZ}6:J q-"P@e]x PeZuJvW2DPmUj *a@l W Տ+|ߔRL@x]x P:TQDr񀘝Re>tgWiKؚCmE)xj%Aӫ]xP]E#̺uVhbEyTBd%(8ʁkݞMӄO JY$4픘]xP>(E~]  Meq!VgeIGa=P`G[F9uߥi佡]xqPMOƧ *1(h•G2RC [ZY"(ܲ]Ggw0 ȊUq|ht f.DU]xP"rUQ4Q; bǥrmw*uhmzq ؋2 e*ZT ]oxa PݒR/qOe 5 ^X2 WPW0z9"*fh$1(*dVM`d quU]x P P pO=g&j@XTg3g 'kSz_tUc::xx]^ xQ Pf\I\H` #ܝ:qt.18ȫt𚳊X4짵˙XJ겹O8P*l] x Pj 2w CB AYZ.!]Ĥw0QlQ7&tL{v"LMcޤpM[]N xA PtX%y˻6Z8|5ՔɚtS&CbY^̂%"sguY$FRy / dPuL\ P] x PE*$SbMV[2D$?,© E"2j 5;LMUrV ,kWsZ0]> x1 PE nXC8Qo1Yv Cn;f=@cn#. ڢe򫿴`^X}] x P2X/`ȼ2Q1ldF2i2xUy.hxV/~\ ]. x# PZBDG3FIJ¥2b.2an D ´kʘA]9[(uvB9k8] x P(pdn^`X3`A٫-h8GH PC1q ~z6)~kN0fw IXwz&ڱmM*q8] xPer½c/KKyCy݈ AY-XVZe@Iع4V0QIM] xPu VO1B+)c PnXT04Q#C̾:E~pltrP)ҳr{]xP-?ciuoa͢Ѓ\٫xUi.Ѣufn7բU6D(g=\]x {PQvТ7Fc6re8 C?D"-KkV/DHTfIG+:vx42@A]x!PiF+Ċ\΃2%ɲe}؊"@=ts t$r/ $B- `+&Ȣ]vx"kPmǎZK?$]ⴰinoleԚUF*J`Ķ<Ċ7L| .]x#PUzE^6òHXhrF 7LsWP)f4AR1L,J?a "jEqڷFb/uWԡ%;]fx$[PYZ(bO6SߵQ69M[ben 쫧 ڦwRztdAC9ZRuq\tF'&@vg`G]x%PƆB_0mS>a:J #g ;RwBB$90V$U{Pյ"J!,ꏛ%:s ]Ux&KP -0tV @g3]٠J"(<Ш)=QS|swײ~4PYȋ )]x'PQcKD ld͓b!{5U5z(&h mukf2tK}"%arh#]Ex(;Pm[k5@t]_ܺuuݸ#ᅡ^x5EJ4E% E)igE~> *Ejf&LY,VR2$#2EPإI$Dw6;BC ]x+P!30P|6YM(  ?l#H@1fa47F  "?@(u:4k?,$/&q.]%x,P:fC0h*%":#B!~N)BR^B97=ډ ZY \l3]x-P "5tϭDMsFrU'c?kuPZKl/|e/рrE5_Zjiex]x. PiǀBEtVۊGrSڔn U]JAVj[յC$ &sV(i]x/P]B3J.2"ȸOK*:)$d Q/L ie$@+gm&4U)dȜ]x0P]FX:lDoo6X$a%:6C\ϻ:ȳj&-^j4tB(r^]}x1uP#ݓ,_ am{Qw vжzDÄ:Yw UM3Nd҄V_a!Bdt9]x2PFd' oঢƠ> a4&Jݎ@,'9ᮣ"E|qn#‰NMcdXw]mx3ePQ!:}Uu Sä1kn|LuҭMSIh4=L8XεmrEprjǭ]x4PkZ߼߰Dg'q{Dp(L)I2T]Ľ&I$ϡB BHfrZ4ј# !:H VeNa1Pz]x>P}¬ $j0Ъi.!B"@Bu"7 /S!b0/bܘHҭ 9z.#T" t] x?P !j2*%yF ?j$"/2:SjSe:BHA$kDžc],T"'q6ؐl4F]x@P*Uw`2`8-**[ņeUڥ"rx  ]xAP:U,3؟CjakI_2e響! Eo2tf"5 XMS!:W€{]txBnPEBiѝ, .D)JJkwc5^ZhG r%! QS!buSFWSCL]xCPQO)beHw}Ȝ͢F)bEL܈H,鄌s)j5X|T?X1N#zK]& p]dxD^ Pٲ)J lyCe}WN_K٨B5'*8XYL" Gb]xE P^Q=H)|vkƂutF) idzuځI@ŵ6i¾e=XY&M)]T xFO!PZ`tI*Z.ԮBddK2E4QwPυff%f5 (Mx10{!k®xg] xG!Pa„Ѩ}wۍ3G`QXt`-λduMS=#&H@iD5*$T/]D!xH@"P)6hɉh5,:1Blq뢞I)CRQ(Nq6>6CwH.3t4j>:vHN]!xI"P :>ێ[xunpJtg"pfj-ү[tM(XӉ]3"xJ0#P{iˋJ ]uX|ԋz@M0;WtV!5f':%h r%=*Yl{\]"xK#PV^'R%(+3Ћez t04krYO9ы7kkDpl9ڤ&7 Btۨ_]##xL $P42Bs  }Ak#Y*tvkb2;tM26^`Y6u>fB@]#xM$P!X\$ W2w&$8Ҁ S&xtm0A#С4)9#P ?z]$xN%PM"`f&H8UY^M底_PqM]Ԫu b\"Pxi*Țuf%DE1]$xO%P1FѪW}EYdH PNjʬ vBTAӐYf)%:q  % [(`B3i@D]%xP&PR D5 P] DRaQh=˱D)pYN L=QJ.GcN{4]{%xQx&P/zEqkt5x y+*qe1 Vb^:G}Lq Z2uwF bJ T]%xR&PR*uȗx^ ȓyQK)"U &-[1 eKCT:׃\V *E\dD]K(xWJ)PQ#9ZfAT؞kaY /t}Al-.Q ga-"%ߚ XρlS& ](xX)P%2;t4oRxt\D9.FPE5;1rl{E{s(F켂en%ywh ;c3];)xY:*PB຅b#@q=/ soLB,DҬ ӵl])xZ*Pa*G\1] n\ ( yU&߅ Nƙvj7lop %4]+*x[)+Pllbf#s 2*f@jp2YB+ Ç[9@=첥-$B;H-]*x\+P:▱k ~^GD/tW@:U˶f>$7xHQ#VLcn]+x],Pޥ-'m)kUU#[I, o,rQxq0LR"䊕'\Do]+x^,P~JD $Q2, H$!&Ϥ"L3cl O>J4z9":;#̉] ,x_ -<>F4+9:_h+PJ_RbxKHo!X?.0JJ*D7G׼././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.lnk0000664000175000017500000000322614035600052015743 0ustar00nicknickLF KjKj g,'-PO :i+00/C:\R1B8Windows<:B8*Windowsb2'Y>+ explorer.exeF@ O@ O*explorer.exeF-EC:\Windows\explorer.exeCreated by RelativePrime ..\..\..\..\Windows\explorer.exedata\bin\quodlibet.exe!%SystemRoot%\system32\SHELL32.dll%windir%\explorer.exe%windir%\explorer.exe$ CBg (# 1SPSXFL8C&mm.S-1-5-21-309868742-1720036613-2531456424-1001`Xxy-pcn cqG#^AF'n cqG#^AF'././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1653812665.0 quodlibet-4.6.0/tests/data/test.m3u80000664000175000017500000000032114244626671015765 0ustar00nicknick#EXTM3U #EXTINF:0,lame.mp3 lame.mp3 #EXTINF:0,test.wav test.wav #EXTINF:2,Quod Libet - 110Hz test track sine-110hz.flac #EXTINF:0,non existing file non_existing_audio_file.mp3 #EXTINF:0,no audio file image.jpg././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.m4a0000664000175000017500000001176414035600052015646 0ustar00nicknickftypmp42mp42isommdatlibfaac 1.24B 2G!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I#!I##moovlmvhdELII_@iodsOttrak\tkhdELII@mdia mdhdELIID~!hdlrsounminfsmhd$dinfdref url stblgstsdWmp4aD3esds"@ b sttsstsz (stsc, stco I ctts #udta meta!hdlrmdirapplilst!toodataFAAC 1.24#ARTdataTest Artist----meancom.apple.iTunesnameiTunNORMjdata 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000covr_dataPNG  IHDRԚsIDATxc| XoIENDB`/data JFIFddC    "##! %*5-%'2( .?/279<<<$-BFA:F5;<9C  9& &99999999999999999999999999999999999999999999999999" ?jfree././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.mid0000775000175000017500000001010014035600052015720 0ustar00nicknickMThd`MTrk4XXXXXX Tempo/TimeSigYQRX/MTrk~bbbbbbb aaaaaaaaaaaa?C_`CC_`CC_`C?_H?F_FC_`C?_H?F_FC_@CJ_`JJ_`JJ_`JK_HKF_FB_`B?_H?F_FC_@CO_`OC_HCC_CO_`ON_HNM_ML_LK_KL_0L0D_0DI_`IH_HHG_GF_FE_EF_0F0?_0?B_`B?_H?B_BF_`FC_HCF_FJ_@JO_`OC_HCC_CO_`ON_HNM_ML_LK_KL_0L0D_0DI_`IH_HHG_GF_FE_EF_0F0?_0?B_`B?_H?F_FC_`C?_H?F_FC_@CC_`CC_`CC_`C?_H?F_FC_`C?_H?F_FC_@CJ_`JJ_`JJ_`JK_HKF_FB_`B?_H?F_FC_@CO_`OC_HCC_CO_`ON_HNM_ML_LK_KL_0L0D_0DI_`IH_HHG_GF_FE_EF_0F0?_0?B_`B?_H?F_FC_`C?_H?F_FC_@C0>_0>?_0?<_0<0F_0FE_0EB_0B0J_0JI_0IE_0EH_0HF_0FB_0B?_0?0>_0>?_0?<_0<0F_0FE_0EB_0B0O_0OJ_0JF_0FD_0D?_0?;_0;8_080>_0>?_0?<_0<0F_0FE_0EB_0B0J_0JI_0IE_0EH_0HF_0FB_0B?_0?0?_0?@_0@=_0=0G_0GF_0FC_0C0P_0PK_0KG_0GE_0E@_0@<_0<9_09E_`EE_`EE_`EA_HAH_HE_`EA_HAH_HE_@EL_`LL_`LL_`LM_HMH_HD_`DA_HAH_HE_@EQ_`QE_HEE_EQ_`QP_HPO_ON_NM_MN_0N0F_0FK_`KJ_HJI_IH_HG_GH_0H0A_0AD_`DA_HAH_HE_`EA_HAH_HE_@EQ_`QE_HEE_EQ_`QP_HPO_ON_NM_MN_0N0F_0FK_`KJ_HJI_IH_HG_GH_0H0A_0AD_`DA_HAH_HE_`EA_HAH_HE_E/MTrkPiano 1 Roland SC-55?>_`>>_`>>_`>:_H:>_`>:_H:>_@>F_`FF_`FF_`FF_HF?_`?:_H:>_@>J_`J`J_`JJ_HJI_II_0I`D_`DD_HDB_BB_0B`?_`?:_H:C_`C:_H:F_@FK_`K`K_`KK_HKI_II_0I`D_`DD_HDB_BB_0B`?_`?:_H:>_`>:_H:>_@>>_`>>_`>>_`>:_H:>_`>:_H:>_@>F_`FF_`FF_`FF_HF?_`?:_H:>_@>J_`J`J_`JJ_HJI_II_0I`D_`DD_HDB_BB_0B`?_`?:_H:>_`>:_H:>_@>@_`@@_`@@_`@<_H<@_`@<_H<@_@@H_`HH_`HH_`HH_HHA_`A<_H<@_@@L_`L`L_`LL_HLK_KK_0K`F_`FF_HFD_DD_0D`A_`A<_H<@_`@<_H<@_@@M_`M`L_`LL_HLK_KK_0K`F_`FF_HFD_DD_0D`A_`A<_H<@_`@<_H<@_@/MTrkGGGGGGG XXXXXXXXXXXX?:_`::_`::_`:6_H6:_`:6_H6:_@:C_`CC_`CC_`CB_HB:_`:6_H6:_@:F_`F`F_`FF_HFD_DD_0D`@_`@@_H@?_??_0?`:_`:6_H6>_`>`C_@CF_`F`F_`FF_HFD_DD_0D`@_`@@_H@?_??_0?`:_`:6_H6:_`:6_H6:_@::_`::_`::_`:6_H6:_`:6_H6:_@:C_`CC_`CC_`CB_HB:_`:6_H6:_@:F_`F`F_`FF_HFD_DD_0D`@_`@@_H@?_??_0?`:_`:6_H6:_`:6_H6:_@:<_`<<_`<<_`<8_H8<_`<8_H8<_@<E_`EE_`EE_`ED_HD<_`<8_H8<_@<H_`H`H_`HH_HHF_FF_0F`B_`BB_HBA_AA_0A`<_`<8_H8<_`<8_H8<_@<H_`H`H_`HH_HHF_FF_0F`B_`BB_HBA_AA_0A`<_`<8_H8<_`<8_H8<_</MTrkPiano 1 Roland SC-55?+_`++_`++_`+'_`'+_`+'_`'+_`++_`++_`++_`++_`+'_`''_`''_`'+_`++_`++_`++_`++_`++_`+%_`%%_`%%_`%%_`%'_`''_`''_`''_`'+_`+'_`'+_`++_`+'_`''_`'+_`++_`+%_0%1_01%_0%1_01%_0%1_01%_0%1_01'_0'3_03'_0'3_03'_0'3_03'_0'3_03+_`+$_`$+_`++_`++_`++_`++_`+'_`'+_`+'_`'+_`++_`++_`++_`++_`+'_`''_`''_`'+_`++_`++_`++_`++_`++_`+%_`%%_`%%_`%%_`%'_`''_`''_`''_`'+_`+$_`$+_@+2_@22_@22_@22_`22_`22_@22_@22_@22_`22_`2+_@++_@++_@++_`++_`+,_@,,_@,,_@,-_`-(_`(-_`--_`--_`-)_`)-_`-)_`)-_`--_`--_`--_`--_`-)_`))_`))_`)-_`--_`--_`--_`--_`--_`-'_`''_`''_`''_`')_`))_`))_`))_`)-_`-&_`&-_@-)_`))_`)-_`--_`-'_0'0'_0'0'_0'0'_0'0)_0)0)_0)0)_0)0)_0)0-_`-)_`)-_0-)_0)-_0-/MTrkHHHHHHH ZZZZZZZZZZZZ?C_`C`C_`CC_HCX=_`==_H=C_`C`C_`CC_HCX=_`==_H=C_`C`C_`CC_HCX=_`==_H=E_`E`E_`EE_HEX?_`??_H?E_`E`E_`EE_HEX?_`??_H?/PPĞJ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.mp20000664000175000017500000001562014035600052015656 0ustar00nicknickhϥΧwmc浰c[EZvlbt873mrֶN34>E~Vu,[i.V %`WFbɐsM ێ(ծޓvo~17oZkZtɕ>d jgs_-I3~:}獕SU>AS R#Euc5i8PՃ)v&p!K-P1sT҉$zK$GܻYvs#cFpgⵌaaf n״g+^:si5t57~8~ jD%ܭJˇ@ _$$G|Sĵ86re(؝D( VnKjvZ\CkMk4kZmz䇗$ִI"3]ߞ7z+FikIh:{olr|٭WܷT3 gI-k]Te vrd- ~G4#T&Ff9Ѥ^7Cq!iaLvSZUI5v~8,xUmjnk`:ajڭu*Wń_4$N%oV*-é,N*ն.mbh,S)XiXw;N(Ui [pi$ml5Mb@I3}}ے'%u(Ǽl6@o26ͥff͍_aƝ`#ZҌr[vئ"`|`\ʾ.t5uCc΢? hTtӃf65SudF孺Y#j6Ş I3}wwj4KZ6$^9 ̛u6ڋ+D 5cak0ݭZV-LUWqh}j%]ᣍelL9l=TX[aX"5G ZR|w۫bp#T ㎰. Mg!pZRұ׀;:jD*/A00|6΃uhMuˀSr&!r5%hDHSJԜ.Չl`A`޽:@d5`p-TG$I3~7]:q fG`І8Uh0y#V5NmE4I]U"u,4vU!ik[6ucR-UhGN6lרRm7ڽ%&ۆLgصI"3n8~7},k\3QȤ9eT1y[ rwB36{):C(X 3TF۶$#ZF  8<+2䵜>Ѷ qMjT^wv&I3} 3M24LC+M[m6`㹮i8fRaشg Z־G!`5h4R Fͭ"y@x,˵&J,!F9k@8iH1U3~/[(2RY F]2ncz9Ş_krm[Tͧ |@$I߭~7㊟mb6k1ZP{HU$*RAt3-3Zܐ'VDԄ skX,R !Vl,SJE܍൛Rs') U34T浣~59lV "3n㈝vf4 UN1D,Uk'15LkFlrK+ZB:|%sd8ꮼ0T] ”ES>3jvtqtobv9:f@\ b]]Ia`Q3}ߎߍL^7a:GܡDkKOWf#n6nNzm\ز$x[ys *N\eT*NffO}S kDIIQ"|T%aGI"ߍߎ8܄ )yF:Yk,Ģedqk[PV lcQݚӷ ξ fI Hwcf'&ki0 yxI>-XHv;@I"m~wrd71MڧD!,<m[XRsI3]<ыm%qZv B+An Fޘ50KHaojT[.YuZ-jۧx[[h\dn3~:~7'd dY\&(%MHZ0ח8yԭU[K+!Q)4# M.]17tZ|˫)x3.)kWL`R@P\2|J$}m$3nwu2lzW戮9F"O wI/ͭLx\/[̱d44@R$Q0<~Jyƴԏزo A],tF T$3m}߈wjxE4ɴq_8m-, F}P9hݪ.>|>u6 e8n)-s-ZsU h³\&Զ427Q(jƨ޺͋4Dgk[A኏僚Ui8 J7~8۝;𷙅`OMPг))a9]LEEK/H xلRc@&U{mcWMdImE#tɵh$JkH *o,0{vI3۝ێ7I-%Na )v$a.Ў YS.kW$QlJuIIVOj䥗51RpF;SXtikw."on-K#HMlJIbN=#)* 2󋻃g*^T{"{Âēe1-S[MracOL9$hKòz"i3n7~/K75С.7HR=KZFQ,JG m{+#v4$uRZL۾k-=8˧Me4_{w([WfI.387>0NeiMsS)"6›HYN+Dʈy/2W37!M:q*H76T!Dm`2 ֕-U5SF3b73mgcMlg'%z\'q[C!C&) a% OأqlBK9쐄.n<ѽm!@3}ߍםلe6ʝ9M%cf}IèK$[-hK8AZ \VăS©њ%f p5i]-a>"kHǪcbTuiIZX䪲E[M6#'YJrۏ0/hӒ[xx}lƜ[H|7%iělkH 4glSB#)d&8 I3ߎw9~7I0n~nFs<": R)f=@詩Cpۂ*VB%NynsQiK%L-5aե $s0gf 5jbMIHX<]rP"3}ߎ~xn 5"\Yjΐ?lV#\ՑNBZ6b{!6rN6X\%I,o8$9[[ll jȒ--BkDžDkxTRG4I3 J*QRs#FNSy#!¹kZj =*k:`D$ 5hMxm\8|Wƨo^Կ'fM4[S*9䪻l;la7w!k1]x1@>ōI~88oBl.`˚VU׏4c,Kmp#[X+y.x4 ! e$4vYhAf)jw0h 1٬f0ś{Sg;qbMk/ՑSf:םlWyMLxhPTԚKX>CWH2Y0Ajs5hR 8k&$j$"ID۱W6i䗌'M,ҽL6(=IݑiI^#6Me  I37^9w[o)*ms,Gm}l2L*[P.0aN MUvԍ/5Bg=͙*^B 3'${~vy2]&Rܐ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.png0000664000175000017500000000037414035600052015744 0ustar00nicknickPNG  IHDR&PLTE~DbKGDH pHYs  tIME#7@K7iTXtCommentCreated with GIMPd.eVIDATx nH@ IENDB`././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.spc0000664000175000017500000020106014035600052015740 0ustar00nicknickSNES-SPC700 Sound File Data v0.30eEGame SelectSuper Mario All-StarsDatschge257000Koji Kondo0 "= e!%`+%+tò@2<< 01LJa   j))QQ e;     @2nAAA02nAAA Ͻ]==? H?6` ??<]?S iMLL]EFD\\kkm8`CC+?.??????iML \LS`QQ ??_GG1?== G&?_G&/uoʐ?" Ȱ$G(`P`a`\|ՠ԰ G^ GEԠԡ aa`a? ? 4 zM]-ݍz+/K|=  m!z!z}\?-G$o$$(?++(noŀ<́<ł<̃<o,?(>? h? /-G$?pq/? ?g == G_< T VzRnTTRhdz``fzbnhh`jbZ\zXnZZX^G1?( == Go - -\ 001o`_`=$G:M}\](8 HH GI/GNI=! oQ(10oԑ-? P1? @Aoհ? ա? Աձoձ-ΞDo XoZ? [YZ? \oRoT? UST? VoPoա-G$o? ? o/ՐՁ? -G$Հ? ՑoՀooԐ-? ? o-G$Ձo@? A? Ԁ0011@0A1oJ? `? bHoh? iah? d? jch? fo`bHo? ? N? ]y?=`DoM}dM+(HL`LLH l?M}?HG$ ? n/-? ? ԡ? Ԡ? `P(Հam? pqoa`okH-Do" {   ) Z c , 0 S | Z W  ? # G^/`?G/?R 0? G$^I10}\ed`dP!QݐH?3o G^M` / ? oqeqp\0100@h?h)h0m- /# 1-0/A-@/-/G\?/$G `? ? LްDu/ @ `Ա`ՠHh(/ݍ?2_qo ?:10 A@??} ?  qp?ްQ`_? mQQz? zoQ`HHY!o )4BQ^gnswz|}~X !++43,< MlL\=-\acNJHEIKF_e , J *Ver S1.20*h/ ^/^1o S? /9(xCxx xx x Io_ h \?ňĨʼnx;xC JJM?o ж,-/Mx \?Ғ( JJM?Ĩʼnň_" o.X:,,0*/:,,0@?:,, ]A?}/ A?:,,hnh8hHh_??r/.?/e.\?o:,,D??r:,,ĩ:,,Ĩ-:,,D? /:,, ]@m?=nm)(_(xxx #!`o#@\?ŌĬōon#:;/7I=?ĬōŌ _" oY:0*:0`?: ]a?}/ a?:hoh9hIh/ ?@?r ?/e@\?o:Џ D ?@?r:ĭ:Ĭ-: D ? /I=?:0" ]`m?=nm-,_`(8 HHl?@I=?/ ]Pm?=nm+*o-\?L_]]T?=n+=*o  \?( JM?& ?" 'ĪŋŊo%hh '%&hHo&' \?ŊĪŋo'? ?rJJM?Ī D? o ? /P?Q?oĪ( D? o,?#:Dr[Snnv~n PV=FfwN#+#""t"#Z!!A$"$#!$p$!!""#####$#K!"("A! !c!ARB.8;V}ZB81D!![ FF2F2222PTF8*TF8* 2 P P:,0< `F` 2   ol2-+(&$!$! d88?1)FM#88?1*F88?1)FM#M#88P 88 ?1 )F M# 88 ?1 *F *F0F 88 ?1 )F M# 88 ?1 *F *F0FF 7 TFP```````````````````] cZZ Z 'c PP F A P(2<FPJFPZdZUPKIFDB@><72-+(&$!$!  <<0F F F< 0<0F 1 T Y P8#8#8# 8( 8 * x* x* x* x* x* xF &" $! "'"$& " "'"$& " "'"$& " OL KF FF F3T03T0 F  <0 P F < 2 2 <  F P FF$$      00  r$$  !  r$$  !  00T<$ <|T(2<FPJFA<72-(# 2P<( T TF8*TF8*TF8*   20 (2 2288?1)FM#88?1*FF0#M T F88T * *0#  #`T(2&- F* <& .5 <JO6$0 ` F??F*?811#8 T  ?8 1 *  #     l88KFHFF TP < (  T?1#  T#  *  * Y1 188TF8* * ** 1 11 8 08 * ** 1 11 8 08 8 4808#8#8# 8 8 8MYYYYYYYYY 1 T #  A??F F F F F F  ##*     #  1  8  ?  >  >  S FY YYMF?8*##FF?8??81F$**1##188??F 8 8 8 8 n'n$ dd 8# *8@@6@Q@6@Q@l@MAhABBBBBBCElIElIlIOOOO \;\nnCuCupuux[xÂނTT007vvjjj/j&p j@ & j  j@jp&pjj UP2e2Ler1 z$zBC {4.z?1@!zf{?1$] =pBԒO/ 1ӖNԖ 0 ܿ0 :RӖ&1o02/A4@!>"!?R% `P&-AB5.$`>#U O_/TT~ҶB0MnNe# NB0/?/3# ?C12#>! QO"01L+N}1*?C-// /@#/OP A4,*[+k.",<"2]z]ӣ;l",z,ԕ/P2<0>/Y.Nz1MM@{]<>A1DANC,!A1DANjDDUUUfffzC4C4CDCCzDCD3D3C3vUUDDDC33jTEDD4D33ZweuUeVTUZTUDUDEDDZCT34C$B$JUUueeeeeZ3434#C#CJVfUUdCD2:UR"ܬZZ̻ZZF˼JZjjjjZZjjjZۼZ#2EUffjDDUTVfffzC4C4CD4Dz44D43D33jwfeeeeTUjDUDD4C4Bf4TDC3DDDZEEETET4EZCD43D#C#JVTveVeVeZ33C33C#3VVTD2!:4S/ZZ̻˼Z˻ZܼFJZ̼jjjjZZjjjZZ"DDFVgkDDTUefff ,OձOKO / 4! [OſM߰N.2,l԰Z#.., 1@N?1.!+>Kn%/1O ??°!,0/O>-.,=@.%/ İ:`дOE--ĠԵ2/?N# M,K? M 0* /1<:/O.l:LlO]a;"ޠ,= -m[\?N] ?OO:% /?ÐL0> -.ϐ%0  CL00_>!Ґ !Pр)/@M P>0,n/ $[N.;ҀK?2pL/"3pD.0...p9~1pP.\NP>>-L>@a @,\ @"L$@@N#0,_[_0L=0OM0l@.0! . ^! 10 1! M.O@n OP ?0#<!. ./  z-]Ν1zB+D$!vnc̊/E.0 5-/"Q 0 1.UB)22S/F! !" 3./0͊U2%0%OߊcΊT5A#?̊B# 1&PBzdEgPUB42݊?zE14->/"/!#&"A51 " ?Q5` AQ>`$ GM3?%"/34"Bϊ/*". C?F/C7aA.ъ/" P"eFR"WAE? ﻊ. 30@d!$e%.""VA"z D-͊켊z Sz1BDS3zAv5fU0#EBz2ˊ.zDCz435gS4$S!!j%CW- Ί zBzT?z#!5EC2zECDCjd$2"!zUz˾ڭzj#3Rz"#3D z#$C3Zgc4AC/z2$1z! zj""z"#Cj5DVEUDz $z@1j.ɫj/ܙZ!!j"EfBj#C3FfCj# 3Vj@W@ʾjjܫZ#/j5UTj"!#Egej2"#Fj0V@۽j!j캾jj3ESz4Cj!D2Dj/VAj!j!ۛjj#DDz!DCj0#U23j VRj#zjj"5Tz!D3jB4eB2j!fRjD.zjj4Uz!TBjA 5v13j WbjF/zj j4Ez"DCj0FeB2z41jF>zj ˼j#4Tz!4Dj0Fu23z41jU/z!j ʼj#$Tz"ECj"Fv2#z4AjV/z!j˻j$Tz"D3jCFv2#z41jU>zk˻DC eC "S z0!-z#%zm@B$Dz"z@$#""#"z!1݊!T?z=BڜP!F"B݊U/g,#33"D/DR̚C Dag?&de #D2̚6@$2C##!ʚG_513#!ܪB? B2"ݚwO$>A21˽ VO%?12!͚U?$5Aڰ43"1B4F@1D/AݚW?U1"ݚe2u 1"!켪C!A02 B"/ܼ3" B1#122#˽B"!11ɮ#$Aʾ$2"ʾ3"3 $ ?$2Ъ#"#?##.24>$2 VCF,E# T "# CTS2C3DU0"$0ݚd"6c"0f,16b1 ˬ0sٿ" G^40.30!4"#1"D23 !B!쪾2 ! # !/۪#!"""ۚUC E  432"ܚfBCDB C! VC32 DB 41FBD25A݊WaʫEAD@51̊3VOݚE0EO#40C5.E.D#C "34T $C͚DA3"5R4BݚU0D FA#U?ݚ$e.Ce?$eݚ%t$Ce.&dܚGc5A%TFcܚFbEAERVR̪4 3?DBg@͚f0e/U0f0͚d $TS!ۼu˿&T%CC!۽&cߚ5R6A$B5SКEBEA416BDBE032E1D1CD U D!C3" 41v2 u3 3!u!!S/" 242S2""B!! !#C# D!B1#B3D!zu"2#12 D!zT"3."#C zS!42#Dze#C.2Dzt#0ڰd.B#C zf$1ٯT#.C$C" 2 2$.24-C#21#$.B4>C!3 1#03$.B6>C"2 23?3#D"3 Њ3$ ۿC"!#D"3 ъ131ڿ3"#/E"3 240ʿD"$/#!4E?ʿ4/!3/""C!E0ɠD"/$/3"ЊE"E?C#!3/3# "!""4/""" К"2""!D#"" ߚ#!#"#.4.3"" ""2#""4.3"" ""2##!"3.3""2"2 #.!4.32"њ"2"22"4.C2К3!2#!"4.4""К3""3#-34.32" 3!333"DD""#2"3""DD"1#2"3"""3.C"1К4"#3"24-D"1њ$""3"34-4""2"2C3 2DD!2њ3"2424D!"њ3""3#24.423!#3"#4-4""К4!#C23442!њ3"#4#2DC"1њ333 "-#4.4""3!33!.25-41"3!33#BDC""2"33#"D4""##"3""4.32!њ3"2C#2D-C"22224#25-4""#"33#3542"њ3"34 #34.D""њ3"33#3542"њ3"34 #34.4""3"3C3C5=C"23"#43E4"232#3#2"3.D!3њ3#23#2!4.D!23"3C3BD-D1"њ32"/3#2D42"Қ3"3C324.42!К4"3C$34.4"2#2#.4#-34-D"2h^1t S.F! 22"CGk CL2Mn"<`2 #0E+m$ݨ@-QNC"3"  ܴ$1 Ϩ_.n1и  T.#̨QS B,1Ϩ&-RNC"/=D,Q-e#. D?Ϩ!0T @"A$ # A/B 2>C^0/DV.PK!##!d^C+?21d3 L%r4`&@!Pb 03ޘ> 6OD R@Cc#ET0#6Ϙ"?=A>$="  132&+CU,uE^"0"b aT.ӈPCsU 2"-0#!2!-!+A3 10Na O܈t4FD4@0/0 "Q?!D!"DBdoNM,"!,F!./"# $ !>"1јSD?vb oT-@@2 TE>5/!0=QFE20?M,"R#O#/$eO-1"N$ 24  D/B/ 1# 4#"# /AҘA /!"@2 /=7AԘ-0- &< D N33 D,!.Q Bވe1#"B5= ܈ $O324!$>!0 #˘C11 <1#3 b2B>TT#@ 21R31"A߈5.SR,^DS`$133!1 ̈e 3 0`333 .R12B A@2#3@&.Nu A.R2 a0N33?.1005,/B%?! ݈-S? D?5ш@0_ b%B#!%.E+N#/2 cC##PЈ!1xTlA1"$14 .x N`!2A4x7<"3 xPۯ3NC -x.1Rx6^bxOU 13x%P/xR/3?h0&S2BxO/x/. 0x$4/h2,6-x 2?-"xB3x"#.F xA x?"!6xc1xO30x/e#x.=xOxR=1x2/x$?0!x62x6x>"xE 3x"x!$2h,bx!ChTDh?$=h c1h_?h %Ch52h &^h0 hQ00hF."hRhEh-. hn h!th-E/d%*hA!h$3hP1h/EX6 'h0"h-C 2h $/h # BX !hO.h3/h!4d03XE-!h 4 d!3h2h20X2_h2!!X@SXEbTNUX 4 2 h0X%AdX!-X5P!!TO$ X1"F!X.cX1.X 2 X#2X1CX 1QD">qX0$TE X/1BX 00Hd!XX?# /H,}3X"$.Dg"#X"$XC  D`"X3 X/.X"bX3?1H`XX$H31OX! 2H H!OCHSڰR H  #H ?SH#3H$OH-A "HB1H>2BH!0H/,H AH@3D1!8WA5 H!% 8# $P8PCH B 8DR H2#88%,?.H1 8/dH#A( 8&+H 4"HA"8Q 8#48%@(*N8B!82(q@Q81(B(@";(nW(1>(c"(2A/(P> (.$1( " >3($ (.!1(20E @61#! 0!!$!$ P0! 0A01@"/" ? 6 -O2 1 2/1^ ! CB5D"E2#C  "D!B2"#DC#4DC43#34C!""""#2! N:J"2P0䖰vRdPp#",0? -5? _ +,_P <ݯ@/R7ִ ..+V墴/M*OE+o __ MP!n C2ߤҼ Ӷ?2<.jnN;- .?ձѲZ/- ./D/A n4QM͠ ޤ/ ... Ф -"  &¤ !"A AO?4"/>?M;B23D$32=nZZ$E@Eϐ3/"*E 0RTBM"BO=@\T~2 ۿ]N1A!͐M-n]D%fE;P0@ [\L !.,2`RNN=42_U""@a  0->A"N =C /A0=ߔ].1ѐ1/DB -0---OO.&-DM23/- 00M ],Pl]m /"c`B $D0τn$23?!߄k6C$dF4WT%Ѐ/3]t1">>EcR=O  #EUDS/!?2Bھ#41 "tq@It@p $Tt`-1/"tѧOK# -/tL!.pdtlNpSQڽdo[ @p )Bt/ "t <.+tC=p#C2tB!=``" UTGt",tp`S#$PTd4[d Akd/2d10d ."0d ,d=L`PD"-+-`$-PA,K,TI6@QP P 0T%1Ed/TPO2P3 4?2TNB\PP?P #13OP/PDoPVT"D4@PPDq+4n*/D"@,D N/4N, >B-0 5 Q!4@4 ?$`< A$- - /S  !3 _nk@/ . ! @jaͯ jjEFUuCjSݯ jj55VTuDkb͠  *  ,=L/6Q ?@@>1= &-^-, >ܶ>//tA^,"] .?=O> /n2a_11NMN!A/ S>λ=_ao1>Ŗ!</   ]-;,/>Ѧ;2KMJ+%C<3ݦ<Ñ MD zjЮ . NҖ-; ϭ> //0.v,-M0<񲰆 , -$@vjʊN-; ,-Ҋ01">>N"ÿ -  -< ,--_m @=Ov:.L1¢<.[. -.^^A. ?&.?=".LO Y!2mi[-_!> %ݲ/n=pP n^ LԶ_.**[=N!@Ԥ@@qn_¶..!>?+ݦ!om _JOQ泦?1 nͦl=L>=2,2@0 @!-[ NO e'nʮڢ _- ODF- @Ѣ01 2/k_" á?!!]=S,i/ NԴ+00N.~!2.LB 2"1B@?Dd0г=}*$L fUA-\^[#9%>@">/$ L$N- _ >>P0#/k $  =-!= ,!*ߦ?k!/>ݦ>,#":L/.1NT0!----O/0@O=P PN @2^1]]/ "0P1Ң Ж!_/>`BӒT0@"..@"a!, ? 0m.3n CeNQ 1/ . 1=>BSS/ , 2#LN20+>.#\ "M!$=>,A& '-M,+C1Ԗ.M䖣-02M "#-#4! _LO K" $!@0#ݺ㿆3 Q =/$0^0!A^M@+P1EB/N,N/% _B #2!A/OAЂ0/4˼0Q҆:#/v AGĶ A1v]Wz<$v+|?>ON?#reBQ$-3v!@J-v!vP-aІ!/r M/v ;T@"rO2E0_/rE!RvO,v3 v> v"/.v/b0/FQrrͭv3v;"?f?[A2f! =bϝ›vM$b/@3fA=bt?f0LMbb%bRv\sbRD-޾V O3@3f?f# f>"fMf@ f!@/bC1$#"fMfA>2V\< b3V>V=,NfRAU3RGT+0əV03CV! 0@V.  V"AVV>AfV1/1RTR$V! -4F:U RCܼR1%UCRT 2V#! V@AVBV"3F`4V AFrFQ4F0rF GFP!"!V 1!F0t R3#FrV4FR2F@q #FBc Fa%V AV3FbCV AV3Fr#V AF u FQ3V AV!2Fq3V AF1e Fa#VAF1eFa3V AFAe FQ2V AF1eFa3V AFAeFa3W A,.,1"#"^2s2"""2""xED4342#"M2!0tqd3"/xPpR'$ 2"$?"!tBe$5o%Dd$BA# ChPB]C>x>x-x޳xxd/d ` !hKO\dC4ARBE3dA$>Fh-0OBhA"dDQ dC!A3?hSF O=DdBAQ$332X"]%?@?T#T#ݴ/D !D-BD00U4H"d$^H>bADQ3H? XXXH˽H8 ( 5#823$3283%2B$2383#3"C"@382!B"""!(CD#$R1$#7vCSC2AC1#"1B""%cU3UcC$$3"B$3"̽4->߈5߈=/2"2RAx#B3x멻ax!x"A4D"dxCB!Uc"x1?݈x413D$5tD22""xx d1x2"C0!3Dx2TfD@=#hd">@9ܼxxh!P@x#4U2T2Ux!"!4 xxx#0"2Cx4CCC#1h@!!hhڽɿhAx"231344x4""2hh̻ hURhV@!%UUSh3EC32!#h4 h˽h#h$34EEhdT53C#"!X" = hݭhʽh"3%Dx"3C""h1!hܻhXACSDTh$433!2d"3hhX%Vh"#D2D3#Ch4!"!"Xά˙X˛ͼX 2h!"33"433XUUceTT2XhX!!X3$CTTXTE3Uc333HC32ͽX̽˺Xh!#C34XeWEE333#Hv!ܽXH̬X33X4$EC4E45XU4"!X۬X̼X2"C3XCDDD33#2HVvVU#2XXH#D3X"DC3TCD3XC321HܺͻXHX14C33XT4C3533"H#ۻX̻H!H3TEWgfFeHSSC4##""8#H˜H̺X""34X3$3C323"HE12H̻˺HH#"3CHBDDDUEDeHCST2"H˻H˻H3243H3CDDCS338uRD228 ͻH̼˼8 5H2FDUUVEeHED4C"!HHͼ( #sU 1]?ٚD='An =!\Ѫ0 P/ D"3$ Cm 3L Ϛ1%+*G !B "2? 5 ,,/L4b00Ѷ 5+/1q/ 3C2JQҺ/./Զ00, 2JN@]1N{>5/\?4! V,!m5"벰 ϻ 2/\1" #a, 2T R"!0?0-2/1!2nOo aCR">PO- %.!. ,к?1.N?k =DϺ?#?3  B .^ O *""<,4ү"[ ]=4C.+R2*Ѷ>c >  "/@?_6, S$3AR-!L0l1 -/A 2 3!  % N> P#% 1 #l;˴2.>ߤL!#S>YQ10!/1ӴO  !/!0SQ?10AC/<"S 0?%dN0Q/-? ,ӰT#$ݾ ?,`1.o = 0 Q,$?:@"2!3B 2/32 3o, / 0Z!ԑ%O_PL&U$AE=E$#A @,.<-C 50!B/3/CCn%#/_-!O/A!" N B\O *[/_Z #0\-/,Q]2 ? .0ް/ ðT?ba./,Ԯմm@"$D/AB=F ?>_L+!?P@B? 2^"ĥO ?S5C$/,L=20"a /Ӱ 0.MN>-A0@ д=MMM=N@ !C5!ONQC@!/a0?><=.DD;.M0 B6O!1߰B@ .A/ \=35#+2C"4D?AmN@13 Q=а@$B1C!# ,1-1KVD_/M]YJ!.??@>߰/[<-l0mQ&o"!3/_=0?#"v35.,"Z[>0$#N<-- 3/O >-R! - ĠR.< ,٠C@>@.! <&EO0.-"Π_>3A !%4CP>- - " ? </ސ$ 2ഠ2//AEF.!-^RFA>.JM= $/ !#@l9Pa#NsNT< ɠ"`R@1>%?5 1 L ! =!$"۔/L =`"31a$-#<^TίN߀/2;1CdBU11]/ .B!A 1/o-K2W$U Ӕ+ AS"!/>33No=K!0M -p  A- !2!<$ O+>31  QB"P1>Op;ppppѐ1/p>CL4?%$p.?pA:p%.Qt+L4p"p?. >4p%$4.p +-p`? #!O`. $`4Ap 1 p.p!B"`@  `%2d1=Tm#ud`P 1:_bPt1rd+P0P0>_ PP,>>T 1P.?@@ E@Tq.N@."4,\aJ-4 /"Q00 4$+R.0?$ $.  $ 1B ?, "0 0!Af ̈q""!hm$42#BX2ChX@PhNm tH1_ H_/SL1D 5*Vx`DD4 ZxbHB*[XX 4DC!!x7zX2hXA43X336A3@&X. Xx#CQ,""x2  XXhy] h?! !$N=6X?p2 ! 1! +FfeDC2=>bM?]KD1x"  Rh1@xO C" Q?!*դ-AO4?&@>>OA&P/> 41ۻO2! Na#O."!huh̼5Om%%Etx! NhH >."F^5#$L!1 !] #x@"#b  ,Nє$5`6R4є !#0C3,^/-;P$!!"#s3”!B@$ ߈ô 1  / A!DҔ/!OΘ!0 ?` \|K>xS! t"#DUD2""N0!@. E\M?2Ф/Դ  @"/>0=վ*J&ӈ2=!""?"Δ@?DA !O!!0@宴/ _!/#n)Ѽ-._^1;!?#dZN>ӔAR; </ ,.#!< ,[C%%2R; /2-¢ݰ !M=.KO"[1P2O >de1" +1\>\1!$?A# 1/=5^5",">4 !O  N# @x\M0?/\ @ @:t6a?-!>xRo{*N xoxOK̈́m_@00 >„^M> S0Ĥ  "!;M;_<-Tń?LOPB  t?l5ftYrN&A1/P0. p.1Ӏ ̄=t;t S`$x< ,t//#$x=> t"/M"d63 ުx. A C, /tE0&ϻxL-<]t*% 30 M>/݄Otc>D>?>t%Q?xYCt2Mt h:2>>tD3E?!Qx{>/hmM=t Ot #"xLOdOE1ed3l0d h$4:dD$x[xxM0#f-# !t<ބ@"@tRU dvOd >Nx.?tO2te?Pd3< dڮ¢d/520*xD;Odt /! d3M{+t*t-#>2dA=lt-xE/t!<OtB"d[-&d ]2="dd=<$T7bNdNdCTd/ݳh>!?Md4h?,?d1d^?!O?#Ld.@Tl!d,d hM>X# d =d d"0T"=2 T TT1.X[{dB#! T?. T;h>,?X@Sd ?X^n1<.STA3X<-dX.+^h/ dO TD""4_TT,-OT->!X/OT TL TTH>5X<\Z0 H$ ,֑DE#5OX=A-TDJE#bX!?.D@! D D`?&HN DC4$D 3@XT "H0;"D@!2T D =D H>MH 40l,H>OD? D @#D223D<\D0H>,T0OP4 r<4м-VC8.#4 Ͱ84 D0 #T_DLmP@Ca .?@P"3#D0=4D24P4.?`8 4444_0r4D4QS/2 8*?> ^8?/4P@0$=޲O4!$^@.$$S_%.aA$M0n(="4@ 4O.$E$_@$11>N(O..M(<.-(/$.45/20 $E!#-M<> N,_>@Π@ 1!@O".@^!1 004B1@20P/5TDDT4"!"3C4TEDDD!!""""""" .Dm@,$?"- .4$<˜=A##=ҨϘbE @4?5!"ߘ" R?F  Tb?=?͘s.AgBQ!! "^ވ^=\"6E=2!%$  . !BO 5 3.! !2!6!V@5  1.>S-!2R!!""-  =A-ˆ_NG+c3$0S܈%]RΈ4>!A""#-!3Bߘ"$eWnT3-PC"-Ef7l@A+ >Έ#PCNB „T;$2-Q!Q .3-xU.4$>ވBO@BOxt.ֈN>?E/D2A3C4"" 2$B-Ax2" %x/"x"""x4 x@Ccx##1x 2$t%+S x!x^$"0?x%Cx #4xx04?x_2.CxD2x#h G=x/2h#DHc$e$T/hBX# X2ܻAXB Xe 5D2X34?X " X!!H#33X!" VQX5QX#0"XH01XD3H/6RD?˾H'tH ۼ˪Hd H.EUB2 X!43!X3H3ښ!H/%B!8QEX"  CHAHA H Hv%!8fAe2 H28ʰ B8#H A8e30T8C20HB8-%8_.DV`8EcT n"Z82 (ܾ@8#S("vc&U8VO8"8?(#@8C#g=8!B(1(/(23(S WR1(1$1%?(( ߝ4(C1" #D3(E>( E  !(E (21.$T "( (! EeA(1, 40230 / 0/ 3"3#"-3P .$ C03"!"23"# !:!":1Jn""J5 J̹&uDJ31 1J0$JjC fP˼32Z##0"zTj2j#0zWbj"4j3!Ί51j"B# j"3!z5bj3!!j$ Qz"Z5SB?AZ=#Ue3?aj0342S!j/#E2FRj52"zǚTjC5w jDf렪4j5wz!ڬ%Qj$Vz!ۚE/jPDz" ܚ50jO4{# .9`‡222 7 { |} { |} { |} { |} { |} ɪ { |} { |}{H} { |} { |} { |}{H |} {|}H${ y { }d -ɒHH0H $2 = = =H0 0 7 9 ; =?0  ?PdH $2 = = =00 0 7 9 ; =?H  ?PdHsHHmHiH 0 d mH{H}H~HH $dZd }HH $dZd }H"°Zjê <<22 ) Ɍ Ɏ ɐ ɑ ɒ Ɏɓɓɓ Y _ Y _ Y _i Y _ Y _ Y _ Y _n )A ɓ ɕ ɜɜɜɜ ɜɜɜɝɝ ɝɝ$A ɜ ɝ ɤɤɤɤ ɤɤɤɤɤ ɤɤ$A ɗ ɘ ɡɡɡɡ ɡɡɡɡɡ ɡɡ$ ɨɠɡ ɨT ɪɭ ɴ ɯɭ$ Y _ Y _ Y _j`` j@//<F ,xid6( Nintendo0j3././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test.vgm0000664000175000017500000000510514035600052015746 0ustar00nicknickVgm A P6M <  u R(R(R(R(R(R(R"R'R+R01S04R17S11R2RS21R4PS4TR50S5PR64S6PR8RS81R90S9RR:XS:RR<0S4S>0R@S@RA,SARBSBRDSDRESERFSFRHSHRI"SIRJSJRLSLRMSMRNSNRPRSPRQSQRRRSRRRTRSTRUSURRVSVRRXSSXRYSYSRZSZSR\SS\R]S]SR^S^SR`S`Ra SaRbSbRdSdReSeRfSfRhShRiSiRj SjRlSlRmSmRn SnRpSpRqSqRrSrRtStRuSuRvSvRxSxRy SyRzSzR|S|R}S}R~S~RSRSRSRSR?SRSRSRSRSRSR/SRSRSRSRSRSRSRSRSRSRSRSRSRSR2S+RS2R*S+RSRSRS-RRRRRRRFrRRRZRVrR^RbrRj RfqRn RrRz rRvR~ rRRrRRRB#rRJRFqRNRrR(rR#rR/R(rS0SRRSZSrSVRS^SqSbSjrSfSnrSrSzrSvS~rSSqSSrSBSJrSFSNrSR(tS#SrR(aR(rR#rRR(rR(rR#R-qR(rR(rR#RrR(aR(rR*rRR(rR(rR#RqR(rR(rR*RrR(rR(qS#rS-R(rR(rS*rSR(qR(rS#rSR(aR(rR+rR-R(rR(rR*qRR(rR(rR+rR/R(rR(tS#SrR(R(uS+S-qR(R(uS*SrR(aR(uR(tR(a R(rR*rRR(rR(rR$RA\.sk en-us]&EG_eRů[wHgDLz4DeviceConformanceTemplateL2 IsVBRt E˖p˥r2CiR[ZX . ު|O(Uݘ"#DIANEpT@^PWMFSDKVersion10.00.00.3646WMFSDKNeeded0.0.0.0000 IsVBR@Rц1HARц1HWindows Media Audio 9.1$ 64 kbps, 48 kHz, stereo 2-pass CBRaܷ Ser@iM[_\D+Pÿa aA  * u{F`ɢ 6&ufblvCO;J)rJ ]U  % "" w=  ]UU AA]U +(AA]U 8AA]UU HAA]U + XAA" w=  ]U hAA]U U  xAA] U  +AA] U  AA]U U  AA" w=  ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/test2.lnk0000664000175000017500000000103414035600052016020 0ustar00nicknickLF J1yJ1yJ1yB@2(EA{ AEE0~1.TXT&(EA{(EA{&.txt$$5d C:\Documents and Settings\test\Desktop\??.txtC:\Documents and Settings\test\Desktop\&.txt .\&.txt&C:\Documents and Settings\test\Desktop`Xxy-fcf85a601536[]SK)\(0%ܾl7'$[]SK)\(0%ܾl7'$././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1664110870.0 quodlibet-4.6.0/tests/data/valid_podcast.xml0000644000175000017500000001261414314050426017617 0ustar00nicknick 60 Nightline ABC News http://www.abcnewspodcasts.com Late-night television's award-winning news program. In-depth reporting on the major stories of the day combined with relevant topics in pop culture and entertainment. Late-night television's award-winning news program. In-depth reporting on the major stories of the day combined with relevant topics in pop culture and entertainment. Late-night television's award-winning news program. In-depth reporting on the major stories of the day combined with relevant topics in pop culture and entertainment. abc news, ABC, ABC News, ABC News Radio, radio, ABC Radio, Nightline, Juju Chang, Dan Harris, Byron Pitts, talk show, breaking news, podcast, audio, news, TV, show, shows, TV shows, politics, campaign, election, interviews, broadcast, technology, world, global en Copyright (c) 2017 ABC News Internet Ventures ABC News abc.podcast.support@abc.com News http://a.abcnews.com/images/NL_onthestreet_SQUARE.jpeg Nightline http://www.abcnewspodcasts.com Full Episode: Tuesday, November 28, 2017 ABC News Inside Prince Harry, Meghan Markle's engagement and the story behind the proposal; Women recount their sexual assaults at Massage Envy spa; 12-year-old cancer survivor makes his Carnegie Hall debut http://c.abcnewsradio.com/audio/3430905/3430905_2017-11-28-052205.96.mp3 Tue, 28 Nov 2017 05:27:13 EST News No 00:00 abc news, ABC, ABC News, ABC News Radio, radio, ABC Radio, Nightline, Juju Chang, Dan Harris, Byron Pitts, talk show, breaking news, podcast, audio, news, TV, show, shows, TV shows, politics, campaign, election, interviews, broadcast, technology, world, global http://a.abcnews.com/images/NL_onthestreet_SQUARE.jpeg Nightline http://www.abcnewspodcasts.com Full Episode: Saturday, November 25, 2017 ABC News Although police thought the shooting death of Burke O' Brien would result in a home-run case, the murder remains unsolved today. http://c.abcnewsradio.com/audio/3429849/3429849_2017-11-25-124749.256k.mp3 Sat, 25 Nov 2017 13:01:43 EST News No 00:00 abc news, ABC, ABC News, ABC News Radio, radio, ABC Radio, Nightline, Juju Chang, Dan Harris, Byron Pitts, talk show, breaking news, podcast, audio, news, TV, show, shows, TV shows, politics, campaign, election, interviews, broadcast, technology, world, global http://a.abcnews.com/images/NL_onthestreet_SQUARE.jpeg Nightline http://www.abcnewspodcasts.com ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/with-id3.dsf0000664000175000017500000000217314035600052016404 0ustar00nicknickDSD {\fmt 4+data ID3TIT2 DSF title././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/data/without-id3.dsf0000664000175000017500000001013414035600052017130 0ustar00nicknickDSD \fmt 4+data ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/gtk_helpers.py0000664000175000017500000000103614035600052016223 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. class MockSelData: # Gtk.SelectionData is missing a constructor def set(self, type, format, data): self.type = type self.format = format self.data = data def get_data_type(self): return self.type def get_data(self): return self.data ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1658948517.0 quodlibet-4.6.0/tests/helper.py0000644000175000017500000002212314270305645015204 0ustar00nicknick# Copyright 2013 Christoph Reiter # 2015 Anton Shestakov # 2017-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import contextlib import sys import shutil import locale import errno import io from pathlib import Path from gi.repository import Gtk, Gdk from quodlibet.util.i18n import GlibTranslations from senf import fsnative from quodlibet.qltk import find_widgets, get_primary_accel_mod from quodlibet.util.path import normalize_path def dummy_path(path): path = fsnative(path) if os.name == "nt": return normalize_path(u"z:\\" + path.replace(u"/", u"\\")) return path @contextlib.contextmanager def locale_numeric_conv( decimal_point=".", grouping=[3, 3, 0], thousands_sep=","): """Temporarily change number formatting conventions. By default this uses en_US conventions. """ # XXX: locale internals override = locale._override_localeconv old = override.copy() try: override["decimal_point"] = decimal_point override["grouping"] = grouping override["thousands_sep"] = thousands_sep yield finally: override.clear() override.update(old) def _send_key_click_event(widget, **kwargs): """Returns True if the event was handled""" assert widget.get_realized() assert widget.get_visible() ev = Gdk.Event() ev.any.window = widget.get_window() for key, value in kwargs.items(): assert hasattr(ev.key, key) setattr(ev.key, key, value) ev.any.type = Gdk.EventType.KEY_PRESS handled = widget.event(ev) ev.any.type = Gdk.EventType.KEY_RELEASE handled |= widget.event(ev) return handled def send_key_click(widget, accel, recursive=False): """Send a key press and release event to a widget or to all widgets in the hierarchy if recursive is True. The widget has to be visible for this to work, so this is needed: with visible(widget): send_key_click(widget, "a") Returns how often the event was handled. """ key, mods = Gtk.accelerator_parse(accel) assert key is not None assert mods is not None assert isinstance(widget, Gtk.Widget) handled = _send_key_click_event(widget, state=mods, keyval=key) if recursive: if isinstance(widget, Gtk.Container): for child in widget.get_children(): handled += send_key_click(child, accel, recursive) return handled def _send_button_click_event(widget, **kwargs): """Returns True if the event was handled""" assert widget.get_realized() assert widget.get_visible() ev = Gdk.Event() window = widget.get_window() ev.any.window = window ev.button.x = window.get_width() / 2.0 ev.button.y = window.get_height() / 2.0 for key, value in kwargs.items(): assert hasattr(ev.button, key) setattr(ev.button, key, value) ev.any.type = Gdk.EventType.BUTTON_PRESS handled = widget.event(ev) ev.any.type = Gdk.EventType.BUTTON_RELEASE handled |= widget.event(ev) return handled def send_button_click(widget, button, primary=False, shift=False, recursive=False): """See send_key_click_event""" state = Gdk.ModifierType(0) if primary: state |= get_primary_accel_mod() if shift: state |= Gdk.ModifierType.SHIFT_MASK assert isinstance(widget, Gtk.Widget) handled = _send_button_click_event(widget, button=button, state=state) if recursive: if isinstance(widget, Gtk.Container): for child in widget.get_children(): handled += send_button_click( child, button, primary, shift, recursive) return handled @contextlib.contextmanager def realized(widget): """Makes sure the widget is realized. view = Gtk.TreeView() with realized(view): do_something(view) """ own_window = False toplevel = widget.get_toplevel() if not isinstance(toplevel, Gtk.Window): window = Gtk.Window(type=Gtk.WindowType.POPUP) window.add(widget) own_window = True else: window = toplevel # realize all widgets without showing them for sub in find_widgets(window, Gtk.Widget): sub.realize() widget.realize() while Gtk.events_pending(): Gtk.main_iteration() assert widget.get_realized() assert window.get_realized() yield widget if own_window: window.remove(widget) window.destroy() while Gtk.events_pending(): Gtk.main_iteration() @contextlib.contextmanager def visible(widget, width=None, height=None): """Makes sure the widget is visible. view = Gtk.TreeView() with visible(view): do_something(view) """ own_window = False toplevel = widget.get_toplevel() if not isinstance(toplevel, Gtk.Window): window = Gtk.Window(type=Gtk.WindowType.POPUP) window.add(widget) own_window = True else: window = toplevel if width is not None and height is not None: window.resize(width, height) window.show_all() while Gtk.events_pending(): Gtk.main_iteration() assert widget.get_visible() assert window.get_visible() yield widget while Gtk.events_pending(): Gtk.main_iteration() window.hide() if own_window: window.remove(widget) window.destroy() while Gtk.events_pending(): Gtk.main_iteration() @contextlib.contextmanager def preserve_environ(): old = os.environ.copy() yield # don't touch existing values as os.environ is broken for empty # keys on Windows: http://bugs.python.org/issue20658 for key, value in list(os.environ.items()): if key not in old: del os.environ[key] for key, value in old.items(): if key not in os.environ or os.environ[key] != value: os.environ[key] = value @contextlib.contextmanager def capture_output(): """ with capture_output() as (stdout, stderr): some_action() print stdout.getvalue(), stderr.getvalue() """ err = io.TextIOWrapper( io.BytesIO(), encoding="utf-8", write_through=True, newline='\n') err.getvalue = lambda: err.buffer.getvalue().decode() out = io.TextIOWrapper( io.BytesIO(), encoding="utf-8", write_through=True, newline='\n') out.getvalue = lambda: out.buffer.getvalue().decode() old_err = sys.stderr old_out = sys.stdout sys.stderr = err sys.stdout = out try: yield (out, err) finally: sys.stderr = old_err sys.stdout = old_out @contextlib.contextmanager def temp_filename(*args, as_path=False, **kwargs): """ Creates an empty file, returning the normalized path to it, and removes it when done. with temp_filename() as filename: with open(filename, 'w') as h: h.write("foo") do_stuff(filename) """ from tests import mkstemp try: del kwargs["as_path"] except KeyError: pass fd, filename = mkstemp(*args, **kwargs) os.close(fd) normalized = normalize_path(filename) yield Path(normalized) if as_path else normalized try: os.remove(filename) except OSError as e: if e.errno != errno.ENOENT: raise def get_temp_copy(path): """Returns a copy of the file with the same extension""" from tests import mkstemp ext = os.path.splitext(path)[-1] fd, filename = mkstemp(suffix=ext) os.close(fd) shutil.copy(path, filename) return filename class ListWithUnused: """ This class stores a set of elements and provides the interface to check if it contains an arbitrary element, and then to know if some of the elements stored were never accessed. Some tests use this class to store whitelisted/blacklisted things that are deemed acceptable, but would trigger those tests if they weren't made special cases (e.g. UI messages that conform to a particular writing style, but can't be tested automatically). Since such whitelists reside in tests and not in the code that produces those special cases, it's easy to change (fix) the code and then forget to remove the special case from tests, leaving it there to never be used again. This class then provides a way to see if such particular element doesn't actually need to be in the whitelist anymore. """ def __init__(self, *args): self.store = set(args) self.unused = set(args) def __contains__(self, item): self.unused.discard(item) return item in self.store def check_unused(self): if self.unused: from quodlibet import print_w print_w('ListWithUnused has unused items: %s' % self.unused) def __(message): """See `quodlibet._`. Avoids triggering PO scanners""" t = GlibTranslations() return t.wrap_text(t.ugettext(message)) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735242.034269 quodlibet-4.6.0/tests/plugin/0000755000175000017500000000000014471213412014642 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/__init__.py0000664000175000017500000000313614035600052016754 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. import os import quodlibet from quodlibet import util from quodlibet.util import get_module_dir from quodlibet.util.modulescanner import ModuleScanner from quodlibet.plugins import list_plugins, Plugin, PluginImportException from tests import TestCase, init_fake_app, destroy_fake_app init_fake_app, destroy_fake_app # Nasty hack to allow importing of plugins... PLUGIN_DIRS = [] root = os.path.join(get_module_dir(quodlibet), "ext") for entry in os.listdir(root): if entry.startswith("_"): continue path = os.path.join(root, entry) if not os.path.isdir(path): continue PLUGIN_DIRS.append(path) PLUGIN_DIRS.append(os.path.join(util.get_module_dir(), "test_plugins")) ms = ModuleScanner(PLUGIN_DIRS) ms.rescan() # make sure plugins only raise expected errors for name, err in ms.failures.items(): exc = err.exception assert issubclass(type(exc), (PluginImportException, ImportError)),\ "'%s' plugin shouldn't have raised a %s, but it did (%r)."\ % (name, type(exc).__name__, exc) plugins = {} modules = {} for name, module in ms.modules.items(): for plugin in list_plugins(module.module): plugins[plugin.PLUGIN_ID] = Plugin(plugin) modules[plugin.PLUGIN_ID] = module.module class PluginTestCase(TestCase): """Base class for all plugin tests""" plugins = plugins modules = modules ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_albumart.py0000664000175000017500000000236314035600052020064 0ustar00nicknick# Copyright 2013 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.formats import AudioFile from quodlibet.qltk.cover import ALBUM_ART_PLUGIN_ID from tests.plugin import PluginTestCase from quodlibet import library, config from quodlibet import app A_SONG = AudioFile({'~filename': '/dev/null', 'artist': 'Mr Man', 'album': 'Bars of Foo'}) # Keep IDEs happy DownloadAlbumArt = AlbumArtWindow = CoverArea = None # TODO: Some real tests. class TAlbumArt(PluginTestCase): @classmethod def setUpClass(cls): app.library = library.init() config.init() @classmethod def tearDownClass(cls): config.quit() def setUp(self): globals().update(vars(self.modules[ALBUM_ART_PLUGIN_ID])) self.songs = [A_SONG] self.plugin = DownloadAlbumArt(self.songs, library) def testAlbumArtWindow(self): win = AlbumArtWindow(self.songs) win.destroy() def testCoverArea(self): win = CoverArea(None, self.songs[0]) win.destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_bansheeimport.py0000664000175000017500000001017414231604332021117 0ustar00nicknick# Copyright 2018 Phidica Veia # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sqlite3 from senf import fsn2uri from quodlibet.formats import AudioFile from tests.helper import temp_filename from quodlibet.library import SongFileLibrary from . import PluginTestCase def get_example_db(song_path, rating, playcount, skipcount, lastplayed, dateadded): # create a temporary database in memory db = sqlite3.connect(':memory:') # create a simplified version of a banshee track table csr = db.cursor() csr.execute('''CREATE TABLE CoreTracks( ArtistID INTEGER, AlbumID INTEGER, Uri TEXT, Title TEXT, Rating INTEGER, PlayCount INTEGER, SkipCount INTEGER, LastPlayedStamp INTEGER, DateAddedStamp INTEGER ) ''') # insert song and save song_uri = fsn2uri(song_path) csr.execute('INSERT INTO CoreTracks VALUES (?,?,?,?,?,?,?,?,?)', (1, 1, song_uri, 'Music', rating, playcount, skipcount, lastplayed, dateadded)) db.commit() # give the user the in-memory database return db class TBansheeImport(PluginTestCase): def setUp(self): self.mod = self.modules["bansheeimport"] def test(self): lib = SongFileLibrary() with temp_filename() as song_fn: song = AudioFile({"~filename": song_fn}) song.sanitize() lib.add([song]) # test recovery of basic song data = {"path": song("~filename"), "rating": 1, "playcount": 1, "skipcount": 2, "lastplayed": 1371802107, "added": 1260691996} db = get_example_db(data["path"], data["rating"], data["playcount"], data["skipcount"], data["lastplayed"], data["added"]) importer = self.mod.BansheeDBImporter(lib) importer.read(db) count = importer.finish() db.close() self.assertEqual(song("~#rating"), data["rating"] / 5.0) self.assertEqual(song("~#playcount"), data["playcount"]) self.assertEqual(song("~#skipcount"), data["skipcount"]) self.assertEqual(song("~#lastplayed"), data["lastplayed"]) self.assertEqual(song("~#added"), data["added"]) self.assertEqual(count, 1) # test recovery of different version of same song data_mod = {"path": song("~filename"), "rating": 2, "playcount": 4, "skipcount": 1, "lastplayed": data["lastplayed"] - 1, "added": data["added"] + 1} db = get_example_db(data_mod["path"], data_mod["rating"], data_mod["playcount"], data_mod["skipcount"], data_mod["lastplayed"], data_mod["added"]) importer = self.mod.BansheeDBImporter(lib) importer.read(db) count = importer.finish() db.close() self.assertEqual(song("~#rating"), data_mod["rating"] / 5.0) self.assertEqual(song("~#playcount"), data_mod["playcount"]) self.assertEqual(song("~#skipcount"), data_mod["skipcount"]) self.assertEqual(song("~#lastplayed"), data["lastplayed"]) self.assertEqual(song("~#added"), data["added"]) self.assertEqual(count, 1) # test that no recovery is performed when data is identical db = get_example_db(data_mod["path"], data_mod["rating"], data_mod["playcount"], data_mod["skipcount"], data_mod["lastplayed"], data_mod["added"]) importer = self.mod.BansheeDBImporter(lib) importer.read(db) count = importer.finish() db.close() self.assertEqual(count, 0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_brainz.py0000664000175000017500000003242114035600052017540 0ustar00nicknick# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet.formats import AudioFile from tests import skipUnless from . import PluginTestCase, modules brainz = modules.get("MusicBrainz lookup", None) TEST_SEARCH_RESULT = \ {'release-count': 1, 'release-list': [{'status': 'Official', 'artist-credit': [{'artist': {'sort-name': 'Necks, The', 'id': '51f8d454-f4a8-41e6-8bd7-a35921eeedd0', 'name': 'The Necks'}}], 'label-info-list': [{'catalog-number': 'FOM 0008', 'label': {'id': 'b887f682-e9e5-40d2-b4c7-cdbbcd2b3787', 'name': 'Fish of Milk'}}], 'title': 'Athenaeum, Homebush, Quay & Raab', 'country': 'AU', 'medium-count': 4, 'release-event-list': [{'date': '2002', 'area': {'sort-name': 'Australia', 'iso-3166-1-code-list': ['AU'], 'id': '106e0bec-b638-3b37-b731-f53d507dc00e', 'name': 'Australia'}}], 'medium-list': [{}, {'disc-list': [], 'format': 'CD', 'track-list': [], 'track-count': 1, 'disc-count': 1}, {'disc-list': [], 'format': 'CD', 'track-list': [], 'track-count': 1, 'disc-count': 1}, {'disc-list': [], 'format': 'CD', 'track-list': [], 'track-count': 1, 'disc-count': 1}, {'disc-list': [], 'format': 'CD', 'track-list': [], 'track-count': 1, 'disc-count': 1}], 'text-representation': {'language': 'eng', 'script': 'Latn'}, 'ext:score': '100', 'date': '2002', 'artist-credit-phrase': 'The Necks', 'release-group': {'secondary-type-list': ['Live'], 'type': 'Live', 'id': '88e47489-a3d0-3344-864d-4b09188ba9e0', 'primary-type': 'Album'}, 'id': '3663a8a9-1c67-41c2-82c8-6a241d1558f7', 'asin': 'B00007FKRD'}]} TEST_SEARCH_RESULT_2 = \ {'release-count': 1, 'release-list': [{'artist-credit': [{'artist': {'alias-list': [{'alias': u'\u30a2\u30d0', 'locale': 'ja', 'primary': 'primary', 'sort-name': u'\u30a2\u30d0', 'type': 'Artist name'}, {'alias': u'\u15c5\u15fa\u15f7\u15c5', 'sort-name': u'\u15c5\u15fa\u15f7\u15c5', 'type': 'Search hint'}, {'alias': 'Abba', 'sort-name': 'Abba'}, {'alias': u'Bj\xf6rn + Benny + Anna + Frieda', 'sort-name': u'Bj\xf6rn + Benny + Anna + Frieda'}], 'id': 'd87e52c5-bb8d-4da8-b941-9f4928627dc8', 'name': 'ABBA', 'sort-name': 'ABBA'}}], 'artist-credit-phrase': 'ABBA', 'barcode': '602537784608', 'country': 'XW', 'date': '2014-04-04', 'ext:score': '100', 'id': '9daa9d6e-7780-487f-9ef8-885755b73125', 'label-info-list': [{'label': {'id': '91edee57-cbb2-44f4-a6c7-a1a022aead78', 'name': 'Polar'}}], 'medium-count': 1, 'medium-list': [{}, {'disc-count': 0, 'disc-list': [], 'format': 'Digital Media', 'track-count': 19, 'track-list': []}], 'packaging': 'None', 'release-event-list': [{'area': {'id': '525d4e18-3d00-31b9-a58b-a146a916de8f', 'iso-3166-1-code-list': ['XW'], 'name': '[Worldwide]', 'sort-name': '[Worldwide]'}, 'date': '2014-04-04'}], 'release-group': {'id': 'b69d665a-3eee-39f3-b156-58b122232304', 'primary-type': 'Album', 'secondary-type-list': ['Compilation'], 'type': 'Compilation'}, 'status': 'Official', 'text-representation': {'language': 'eng', 'script': 'Latn'}, 'title': 'Gold: Greatest Hits'}]} TEST_DATA = \ {'status': 'Official', 'artist-credit': [{'artist': {'sort-name': 'Autechre', 'id': '410c9baf-5469-44f6-9852-826524b80c61', 'name': 'Autechre'}}, ' & ', {'artist': {'sort-name': 'Hafler Trio, The', 'id': '146c01d0-d3a2-44c3-acb5-9208bce75e14', 'name': 'The Hafler Trio'}}], 'label-info-list': [{'catalog-number': 'pgram002', 'label': {'sort-name': 'Phonometrography', 'id': 'a0759efa-f583-49ea-9a8d-d5bbce55541c', 'name': 'Phonometrography'}}], 'title': u'\xe6\xb3o & h\xb3\xe6', 'release-event-count': 1, 'medium-count': 2, 'cover-art-archive': {'count': '1', 'front': 'true', 'back': 'false', 'artwork': 'true'}, 'release-event-list': [{'date': '2003-12-04', 'area': {'sort-name': 'United Kingdom', 'iso-3166-1-code-list': ['GB'], 'id': '8a754a16-0027-3a29-b6d7-2b40ea0481ed', 'name': 'United Kingdom'}}], 'medium-list': [{'position': '1', 'title': u'\xe6\xb3o', 'track-list': [{'artist-credit': [{'artist': {'sort-name': 'Autechre', 'id': '410c9baf-5469-44f6-9852-826524b80c61', 'name': 'Autechre'}}, ' & ', {'artist': {'sort-name': 'Hafler Trio, The', 'id': '146c01d0-d3a2-44c3-acb5-9208bce75e14', 'name': 'The Hafler Trio'}}], 'number': '1', 'artist-credit-phrase': 'Autechre & The Hafler Trio', 'recording': {'artist-credit': [{'artist': {'sort-name': 'Autechre', 'id': '410c9baf-5469-44f6-9852-826524b80c61', 'name': 'Autechre'}}, ' & ', {'artist': {'sort-name': 'Hafler Trio, The', 'id': '146c01d0-d3a2-44c3-acb5-9208bce75e14', 'name': 'The Hafler Trio'}}], 'length': '974546', 'artist-credit-phrase': 'Autechre & The Hafler Trio', 'id': 'af87f070-238b-46c1-aa3e-f831ab91fa20', 'title': u'\xe6\xb3o'}, 'length': '974546', 'position': '1', 'id': '61af3e5a-14e0-350d-9826-a884c6e586b1', 'track_or_recording_length': '974546'}], 'track-count': 1, 'format': 'CD'}, {'position': '2', 'title': u'h\xb3\xe6', 'track-list': [{'artist-credit': [{'artist': {'sort-name': 'Autechre', 'id': '410c9baf-5469-44f6-9852-826524b80c61', 'name': 'Autechre'}}, ' & ', {'artist': {'sort-name': 'Hafler Trio, The', 'id': '146c01d0-d3a2-44c3-acb5-9208bce75e14', 'name': 'The Hafler Trio'}}], 'number': '1', 'artist-credit-phrase': 'Autechre & The Hafler Trio', 'recording': {'artist-credit': [{'artist': {'sort-name': 'Autechre', 'id': '410c9baf-5469-44f6-9852-826524b80c61', 'name': 'Autechre'}}, ' & ', {'artist': {'sort-name': 'Hafler Trio, The', 'id': '146c01d0-d3a2-44c3-acb5-9208bce75e14', 'name': 'The Hafler Trio'}}], 'length': '922546', 'artist-credit-phrase': 'Autechre & The Hafler Trio', 'id': '5aff6309-2e02-4a47-9233-32d7dcc9a960', 'title': u'h\xb3\xe6'}, 'length': '922546', 'position': '1', 'id': '5f2031a2-c67d-3bec-8ae5-8d22847ab0a5', 'track_or_recording_length': '922546'}], 'track-count': 1, 'format': 'CD'}], 'text-representation': {'language': 'eng', 'script': 'Latn'}, 'label-info-count': 1, 'country': 'GB', 'date': '2003-12-04', 'artist-credit-phrase': 'Autechre & The Hafler Trio', 'quality': 'normal', 'id': '59211ea4-ffd2-4ad9-9a4e-941d3148024a'} # This isn't a complete/original ngs result, it just contains the minimum # a pregap track and a normal track. # The original release used here does also contain a pregap. TEST_PREGAP = \ {'artist-credit': [], 'date': '2008-10-17', 'id': '87c070fc-90d5-39d1-b0ca-777236588378', 'medium-count': 1, 'medium-list': [{'format': 'CD', 'position': '1', 'pregap': {'artist-credit': [ {'artist': {'id': '90b18d97-718b-4a95-982d-b14019d084c0', 'name': 'Polarkreis 18', 'sort-name': 'Polarkreis 18'}}], 'artist-credit-phrase': 'Polarkreis 18', 'id': '2edd640f-2365-4440-b6e5-1f65dd72440b', 'length': '63000', 'number': '0', 'position': '0', 'recording': {'artist-credit': [ {'artist': {'id': '90b18d97-718b-4a95-982d-b14019d084c0', 'name': 'Polarkreis 18', 'sort-name': 'Polarkreis 18'}}], 'artist-credit-phrase': 'Polarkreis 18', 'id': 'e7f3e14b-7acf-47cc-bc26-d66269b821f4', 'length': '63000', 'title': 'Herbstlied'}, 'track_or_recording_length': '63000'}, 'track-count': 1, 'track-list': [{'artist-credit': [ {'artist': {'id': '90b18d97-718b-4a95-982d-b14019d084c0', 'name': 'Polarkreis 18', 'sort-name': 'Polarkreis 18'}}], 'artist-credit-phrase': 'Polarkreis 18', 'id': '03cdb09e-5a22-3e0d-88c9-da24793ccbab', 'length': '202106', 'number': '1', 'position': '1', 'recording': {'artist-credit': [ {'artist': {'id': '90b18d97-718b-4a95-982d-b14019d084c0', 'name': 'Polarkreis 18', 'sort-name': 'Polarkreis 18'}}], 'artist-credit-phrase': 'Polarkreis 18', 'id': 'b2bcb18f-ef9b-4e7e-ac4a-29234b3bac4e', 'length': '202106', 'title': 'Tourist'}, 'track_or_recording_length': '202106'}]}]} @skipUnless(brainz, "brainz plugin not loaded") class TBrainz(PluginTestCase): """Test CustomCommands plugin and associated classes""" def setUp(self): globals()["brainz"] = self.modules["MusicBrainz lookup"] def test_get_trackcount(self): get_trackcount = brainz.widgets.get_trackcount album = [ AudioFile({"tracknumber": "7"}), AudioFile({"tracknumber": "garbage"}), AudioFile({"tracknumber": "10/42"}), ] self.assertEqual(get_trackcount([]), 0) self.assertEqual(get_trackcount(album), 42) def test_get_artist(self): get_artist = brainz.widgets.get_artist self.assertEqual(get_artist([]), None) album = [ AudioFile({"artist": u"garbage"}), AudioFile({"albumartist": u"foo"}), ] self.assertEqual(get_artist(album), u"foo") album = [ AudioFile({"artist": u"garbage"}), AudioFile({"artist": u"bla"}), ] self.assertEqual(get_artist(album), None) album = [ AudioFile({"artist": u"bla"}), AudioFile({"artist": u"bla"}), ] self.assertEqual(get_artist(album), u"bla") def test_build_query(self): build_query = brainz.widgets.build_query album = [ AudioFile({"artist": u"garbage", "album": "blah"}), AudioFile({"albumartist": u"foo"}), ] self.assertEqual( build_query(album), '"blah" AND artist:"foo" AND tracks:2') def test_release(self): Release = brainz.mb.Release release = Release(TEST_DATA) self.assertEqual(release.id, "59211ea4-ffd2-4ad9-9a4e-941d3148024a") self.assertEqual(release.date, "2003-12-04") self.assertEqual(release.medium_format, "CD") self.assertEqual(release.country, "GB") self.assertEqual(release.disc_count, 2) self.assertEqual(release.track_count, 2) self.assertEqual(len(release.tracks), 2) self.assertEqual(release.title, u'\xe6\xb3o & h\xb3\xe6') self.assertTrue(release.is_single_artist) self.assertFalse(release.is_various_artists) self.assertTrue(release.artists) def test_release_tracks(self): Release = brainz.mb.Release release = Release(TEST_DATA) track = release.tracks[0] self.assertEqual(track.id, "61af3e5a-14e0-350d-9826-a884c6e586b1") self.assertEqual(len(track.artists), 2) self.assertEqual(track.title, u'\xe6\xb3o') self.assertEqual(track.tracknumber, "1") self.assertEqual(track.discnumber, "1") self.assertEqual(track.track_count, 1) self.assertEqual(track.disctitle, u"\xe6\xb3o") def test_labelid(self): Release = brainz.mb.Release release = Release(TEST_SEARCH_RESULT["release-list"][0]) self.assertEqual(release.labelid, u"FOM 0008") release = Release(TEST_SEARCH_RESULT_2["release-list"][0]) self.assertEqual(release.labelid, u"") def test_release_artist(self): Release = brainz.mb.Release release = Release(TEST_DATA) artist = release.artists[0] self.assertEqual(artist.id, "410c9baf-5469-44f6-9852-826524b80c61") self.assertEqual(artist.name, "Autechre") self.assertEqual(artist.sort_name, "Autechre") self.assertFalse(artist.is_various) def test_build_metadata(self): Release = brainz.mb.Release build_song_data = brainz.widgets.build_song_data apply_options = brainz.widgets.apply_options apply_to_song = brainz.widgets.apply_to_song release = Release(TEST_DATA) track = release.tracks[1] meta = build_song_data(release, track) self.assertEqual(meta["tracknumber"], "1/1") self.assertEqual(meta["discnumber"], "2/2") self.assertEqual(meta["labelid"], "pgram002") apply_options(meta, True, False, False, False, False) dummy = AudioFile() apply_to_song(meta, dummy) self.assertEqual(dummy("album"), u'\xe6\xb3o & h\xb3\xe6') self.assertEqual(dummy("date"), u'2003') self.assertEqual(dummy("title"), u'h\xb3\xe6') self.assertEqual(dummy("pgram002"), u'') def test_build_mbids_labelid(self): Release = brainz.mb.Release build_song_data = brainz.widgets.build_song_data apply_options = brainz.widgets.apply_options apply_to_song = brainz.widgets.apply_to_song release = Release(TEST_DATA) track = release.tracks[1] meta = build_song_data(release, track) apply_options(meta, True, False, False, True, True) dummy = AudioFile() apply_to_song(meta, dummy) self.assertEqual(dummy("musicbrainz_releasetrackid"), track.id) self.assertEqual(dummy("musicbrainz_albumid"), release.id) self.assertEqual( dummy.list("musicbrainz_artistid"), [u'410c9baf-5469-44f6-9852-826524b80c61', u'146c01d0-d3a2-44c3-acb5-9208bce75e14']) self.assertEqual(dummy("labelid"), u"pgram002") def test_pregap(self): Release = brainz.mb.Release release = Release(TEST_PREGAP) self.assertEqual(release.track_count, 2) self.assertEqual(len(release.tracks), 2) pregap = release.tracks[0] self.assertEqual(pregap.title, "Herbstlied") self.assertEqual(pregap.tracknumber, "0") self.assertEqual(pregap.track_count, 2) self.assertEqual(pregap.discnumber, "1") track = release.tracks[1] self.assertEqual(track.title, "Tourist") self.assertEqual(track.tracknumber, "1") self.assertEqual(track.track_count, 2) self.assertEqual(track.discnumber, "1") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_clock.py0000664000175000017500000000207514035600052017350 0ustar00nicknick# Copyright 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.qltk.entry import ValidatingEntry from tests.plugin import PluginTestCase from quodlibet import config class TClock(PluginTestCase): def setUp(self): config.init() self.mod = self.modules["Alarm Clock"] def tearDown(self): del self.mod config.quit() def test_alarm(self): def fake_entry(s): e = ValidatingEntry() e.set_text(str(s)) return e plugin = self.mod.Alarm() plugin.enabled() entries = [fake_entry(s) for s in ['1', '3', '5'] + ['HH:MM'] * 4] plugin._entry_changed(entries) plugin._ready() self.failUnlessEqual(config.get('plugins', 'alarm_times'), "1 3 5 HH:MM HH:MM HH:MM HH:MM") plugin.disabled() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_console.py0000664000175000017500000000326014231604332017717 0ustar00nicknick# Copyright 2017 Christoph Reiter # 2021 halfbrained@github # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.formats import AudioFile from quodlibet.util.songwrapper import SongWrapper from tests.plugin import PluginTestCase AUDIO_FILE = SongWrapper(AudioFile({'~filename': "/tmp/foobar"})) class Dummy: dummy_val = "str!" def dummy_meth(self, arg, varg=101): pass DUMMY_COMPLETIONS = [ ('dummy_meth', ' (arg, varg=101)'), ('dummy_val', ''), ] NAMESPACE_COMPLETIONS = ('dummy', '') class TConsole(PluginTestCase): def setUp(self): self.mod = self.modules["Python Console Sidebar"] def tearDown(self): del self.mod def test_sidebar_plugin(self): plugin = self.mod.PyConsoleSidebar() plugin.enabled() self.failUnless(isinstance(plugin.create_sidebar(), Gtk.Widget), True) plugin.plugin_on_songs_selected([AUDIO_FILE]) self.failUnlessEqual(plugin.console.namespace.get('songs'), [AUDIO_FILE]) plugin.disabled() def test_console_completion(self): plugin = self.mod.PyConsoleSidebar() plugin.enabled() plugin.console.namespace['dummy'] = Dummy() comp = plugin.console.get_completion_items('dummy.') self.failUnlessEqual(comp, DUMMY_COMPLETIONS) comp = plugin.console.get_completion_items('') assert NAMESPACE_COMPLETIONS in comp plugin.disabled() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_cover_download.py0000664000175000017500000000272314035600052021262 0ustar00nicknick# Copyright 2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.ext.songsmenu.cover_download import DownloadCoverArt, Config from quodlibet.formats import AudioFile from quodlibet.plugins import PluginManager from tests import init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase from quodlibet import config from quodlibet import app A_SONG = AudioFile({'~filename': '/dev/null', 'artist': 'Mr Man', 'album': 'Bars of Foo'}) class TAlbumArt(PluginTestCase): @classmethod def setUpClass(cls): config.init() init_fake_app() @classmethod def tearDownClass(cls): config.quit() destroy_fake_app() def setUp(self): self.mod = self.modules[DownloadCoverArt.PLUGIN_ID] self.songs = [A_SONG] config.add_section(PluginManager.CONFIG_SECTION) config.set(PluginManager.CONFIG_SECTION, '%s_preview_size' % DownloadCoverArt.PLUGIN_ID, 200) def test_cover_art_window(self): win = self.mod.CoverArtWindow(self.songs, app.cover_manager, transient_for=app.window, config=Config(), headless=True) win.destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1692733651.0 quodlibet-4.6.0/tests/plugin/test_covers.py0000644000175000017500000000764314471210323017564 0ustar00nicknick# Copyright 2012 Christoph Reiter # 2023 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import gi from tests import run_gtk_loop gi.require_version('Soup', '3.0') from gi.repository import Gtk from dataclasses import dataclass, field from time import time, sleep from typing import Any, Optional, List import pytest as pytest from quodlibet.formats import AudioFile from quodlibet.util.cover.http import ApiCoverSourcePlugin from senf import fsnative from tests.plugin import PluginTestCase, plugins AN_ARTIST = "The Beatles" AN_ALBUM = "Let It Be" A_SONG = AudioFile({"album": AN_ALBUM, "artist": AN_ARTIST}) AN_MBID = "82a4adf2-008b-3236-bb7a-bd93d7ed9677" def delay_rerun(self, *args): # Try to recover from any network blips sleep(10) return True class TCovers(PluginTestCase): def setUp(self) -> None: self.song = A_SONG self.blank_song = AudioFile() def test_cover_path_lastfm(self): plugin_cls = self.plugins["lastfm-cover"].cls assert isinstance(plugin_cls(self.song).cover_path, fsnative) assert isinstance(plugin_cls(self.blank_song).cover_path, fsnative) def test_cover_path_musicbrainz(self): plugin_cls = self.plugins["musicbrainz-cover"].cls assert isinstance(plugin_cls(self.song).cover_path, fsnative) assert isinstance(plugin_cls(self.blank_song).cover_path, fsnative) def test_cover_path_discogs(self): plugin_cls = self.plugins["discogs-cover"].cls assert isinstance(plugin_cls(self.song).cover_path, fsnative) assert isinstance(plugin_cls(self.blank_song).cover_path, fsnative) @dataclass class Results: covers: List[Any] = field(default_factory=list) success: Optional[bool] = None @pytest.mark.network @pytest.mark.flaky(max_runs=3, min_passes=1, rerun_filter=delay_rerun) @pytest.mark.parametrize("plugin_class_name", ["lastfm-cover", "discogs-cover", "musicbrainz-cover"]) def test_live_cover_download(plugin_class_name): results = Results() # Just in case overhanging events run_gtk_loop() def search_complete(source, data, results): results.covers = data def good(source, data, results): results.success = True header = data.read(4) data.close() assert header.startswith(b"\x89PNG") or header.startswith(b"\xFF\xD8") def bad(source, error, results): # For debugging results.covers = error results.success = False plugin_cls = plugins[plugin_class_name].cls song = A_SONG if "musicbrainz" in plugin_class_name: song["musicbrainz_albumid"] = AN_MBID plugin: ApiCoverSourcePlugin = plugin_cls(song) sig = plugin.connect("search-complete", search_complete, results) sig2 = plugin.connect("fetch-success", good, results) sig3 = plugin.connect("fetch-failure", bad, results) try: start = time() if "musicbrainz" in plugin_class_name: # Isn't called by fetch_cover() plugin.search() plugin.fetch_cover() while time() - start < 10 and results.success is None: Gtk.main_iteration_do(False) assert results.success is not None, "No signal triggered" assert results.success, f"Didn't succeed: {results.covers}" covers = results.covers assert covers, "Didn't get search results" first = covers[0] assert first["cover"].startswith("http") assert "dimensions" in first if "album" in first: # Only lastfm populates this currently assert first["album"] == AN_ALBUM, f"Downloaded wrong cover: {covers}" finally: plugin.disconnect(sig) plugin.disconnect(sig2) plugin.disconnect(sig3) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_custom_commands.py0000664000175000017500000000447714231604332021463 0ustar00nicknick# Copyright 2012-2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet.formats._audio import AudioFile from quodlibet.qltk.data_editors import JSONBasedEditor from quodlibet.util.collection import Playlist from quodlibet.util.json_data import JSONObjectDict from quodlibet import config from tests import init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase CustomCommands = Command = None class TCustomCommands(PluginTestCase): """Test CustomCommands plugin and associated classes""" def setUp(self): module = self.modules["CustomCommands"] globals().update(vars(module)) self.plugin = self.plugins["CustomCommands"].cls config.init() self.cmd_list = CustomCommands.DEFAULT_COMS self.commands = JSONObjectDict.from_list(self.cmd_list) init_fake_app() def tearDown(self): config.quit() destroy_fake_app() def test_JSONBasedEditor(self): ed = JSONBasedEditor(Command, self.commands, None, "title") ed.show_now() ed.destroy() def test_playlist_plugin(self): pl = Playlist("foo", songs_lib=app.library) pl.extend([AudioFile({"~filename": "/dev/null"})]) self.called_pl = None self.called_songs = None def proxy(songs, playlist=None): self.called_pl = playlist self.called_songs = songs plugin = self.plugin(playlists=[pl]) plugin._handle_songs = proxy # Test that as a Playlist plugin it delegates correctly plugin.plugin_playlist(pl) self.failUnless(self.called_songs) self.assertEqual(self.called_pl, pl) self.assertEqual(self.called_songs, pl.songs) def test_plugin_loads_json_once(self): plugin = self.plugin() self.failUnless(plugin._commands) # Hack the commands without the plugin noticing fake = {"songs": Command(name="bar")} self.plugin._commands = fake # Try again, to make sure it hasn't reloaded plugin = self.plugin() self.failUnlessEqual(plugin._commands, fake) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_duplicates_browser.py0000664000175000017500000000376314035600052022162 0ustar00nicknick# Copyright 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.plugins import PM from quodlibet.util.songwrapper import SongWrapper from tests import init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase class TDuplicates(PluginTestCase): @classmethod def setUpClass(cls): cls.mod = cls.modules["Duplicates"] cls.kind = cls.plugins["Duplicates"].cls cls.song = AudioFile({'~filename': '/dev/null', 'artist': 'foo BAR', 'title': 'no!'}) cls.song2 = AudioFile({'~filename': '/dev/null', 'artist': 'föo bár', 'title': 'no?...'}) @classmethod def tearDownClass(cls): del cls.mod del cls.kind def setUp(self): init_fake_app() self._turn_all_options_on() app.library.songs = [self.song, self.song2, self.song] self.plugin = self.kind([self.song], None) def _turn_all_options_on(self): for name in ['REMOVE_WHITESPACE', 'REMOVE_DIACRITICS', 'REMOVE_PUNCTUATION', 'CASE_INSENSITIVE']: # Get the actual values, don't hard-code here (kinda) cfg_name = getattr(self.mod.Duplicates, "_CFG_%s" % name) config.set(PM.CONFIG_SECTION, self.kind._get_config_option(cfg_name), True) # TODO: proper logic tests... def tearDown(self): self.plugin.destroy() del self.plugin destroy_fake_app() def test_starts_up(self): sws = [SongWrapper(s) for s in app.library.songs] self.plugin.plugin_songs(sws).destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_fingerprint.py0000664000175000017500000001406114035600052020602 0ustar00nicknick# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import time from gi.repository import Gtk try: from gi.repository import Gst Gst except ImportError: Gst = None else: chromaprint = Gst.ElementFactory.find("chromaprint") vorbisdec = Gst.ElementFactory.find("vorbisdec") from tests.plugin import PluginTestCase from tests import skipUnless, get_data_path from quodlibet import config from quodlibet.formats import MusicFile @skipUnless(Gst and chromaprint and vorbisdec, "gstreamer plugins missing") class TFingerprint(PluginTestCase): TIMEOUT = 20.0 def setUp(self): config.init() self.mod = self.modules["AcoustidSearch"] def tearDown(self): config.quit() self.mod def test_analyze_silence(self): pipeline = self.mod.analyze.FingerPrintPipeline() song = MusicFile(get_data_path("silence-44-s.ogg")) done = [] def callback(self, *args): done.extend(args) pipeline.start(song, callback) t = time.time() while not done and time.time() - t < self.TIMEOUT: Gtk.main_iteration_do(False) self.assertTrue(done) s, result, error = done # silence doesn't produce a fingerprint self.assertTrue(error) self.assertFalse(result) self.assertTrue(song is s) def test_analyze_pool(self): pool = self.mod.analyze.FingerPrintPool() song = MusicFile(get_data_path("silence-44-s.ogg")) events = [] def handler(*args): events.append(args) pool.connect("fingerprint-started", handler, "start") pool.connect("fingerprint-done", handler, "done") pool.connect("fingerprint-error", handler, "error") pool.push(song) t = time.time() while len(events) < 2 and time.time() - t < self.TIMEOUT: Gtk.main_iteration_do(False) self.assertEqual(len(events), 2) self.assertEqual(events[0][-1], "start") self.assertEqual(events[1][-1], "error") @skipUnless(Gst and chromaprint, "gstreamer plugins missing") class TAcoustidLookup(PluginTestCase): def setUp(self): config.init() self.mod = self.modules["AcoustidSearch"] def tearDown(self): config.quit() def test_parse_response_1(self): parse = self.mod.acoustid.parse_acoustid_response release = parse(ACOUSTID_RESPONSE)[0] self.assertEqual(release.id, "14bb7304-b763-456b-a438-7bab619d41e3") self.assertEqual(release.sources, 1) self.assertEqual(release.all_sources, 7) tags = release.tags self.assertEqual(tags["title"], u'Merkw\xfcrdig/Unangenehm') self.assertEqual(tags["artist"], u'Kinderzimmer Productions') self.assertEqual(tags["date"], u'2002-01') self.assertEqual(tags["tracknumber"], u'7/15') self.assertEqual(tags["discnumber"], "") self.assertTrue("musicbrainz_albumid" in tags) def test_parse_response_2(self): parse = self.mod.acoustid.parse_acoustid_response release = parse(ACOUSTID_RESPONSE)[1] self.assertEqual(release.id, "ed90bff9-ab41-4669-8d44-13c78e678507") tags = release.tags self.assertEqual(tags["albumartist"], u"Kinderzimmer Productions") self.assertEqual(tags["album"], u'Wir sind da wo oben ist') self.assertTrue("musicbrainz_albumid" in tags) def test_parse_response_2_mb(self): parse = self.mod.acoustid.parse_acoustid_response release = parse(ACOUSTID_RESPONSE)[1] self.assertTrue("musicbrainz_albumid" in release.tags) self.assertEqual(release.sources, 6) self.assertEqual( release.tags["musicbrainz_trackid"], "bc970841-b7d9-415a-b7e2-645b1d263cc3") ACOUSTID_RESPONSE = { u'status': u'ok', u'results': [{u'recordings': [{u'releases': [{u'track_count': 15, u'title': u'Spex CD #15', u'country': u'DE', u'artists': [{u'id': u'89ad4ac3-39f7-470e-963a-56509c546377', u'name': u'Various \ Artists'}], u'date': {u'year': 2002, u'month': 1}, u'releaseevents': [{u'date': {u'year': 2002, u'month': 1}, u'country': u'DE'}], u'mediums': [{u'position': 1, u'tracks': [{u'position': 7, u'title': u'Merkw\xfcrdig/Unangenehm', u'id': u'7426320b-7646-3d06-bd5a-4762ecc0536b', u'artists': [{u'id': u'ad728059-6823-4f98-a283-0dac3fb79a91', u'name': u'Kinderzimmer Productions'}]}], u'track_count': 15, u'format': u'CD'}], u'medium_count': 1, u'id': u'14bb7304-b763-456b-a438-7bab619d41e3'}], u'title': u'Merkw\xfcrdig/Unangenehm', u'sources': 1, u'artists': [{u'id': u'ad728059-6823-4f98-a283-0dac3fb79a91', u'name': u'Kinderzimmer \ Productions'}], u'duration': 272, u'id': u'9104a525-40b2-40dc-83bf-c31c3d6d1861'}, {u'releases': [{u'track_count': 12, u'title': u'Wir sind da wo oben ist', u'country': u'DE', u'artists': [{u'id': u'ad728059-6823-4f98-a283-0dac3fb79a91', u'name': u'Kinderzimmer \ Productions'}], u'date': {u'year': 2002, u'day': 22, u'month': 2}, u'releaseevents': [{u'date': {u'year': 2002, u'day': 22, u'month': 2}, u'country': u'DE'}], u'mediums': [{u'position': 1, u'tracks': [{u'position': 11, u'title': u'Merkw\xfcrdig/unangenehm', u'id': u'2520fe8a-005b-3a18-a8e2-ba9bef6009fb', u'artists': [{u'joinphrase': u' feat. ', u'name': u'Kinderzimmer Productions', u'id': u'ad728059-6823-4f98-a283-0dac3fb79a91'}, {u'id': u'bf02bc50-251d-4a47-b5f9-ca462038ae8a', u'name': u'Tek Beton'}]}], u'track_count': 12, u'format': u'CD'}], u'medium_count': 1, u'id': u'ed90bff9-ab41-4669-8d44-13c78e678507'}], u'title': u'Merkw\xfcrdig/unangenehm', u'sources': 6, u'artists': [{u'joinphrase': u' \ feat. ', u'name': u'Kinderzimmer Productions', u'id': u'ad728059-6823-4f98-a283-0dac3fb79a91'}, {u'id': u'bf02bc50-251d-4a47-b5f9-ca462038ae8a', u'name': u'Tek Beton'}], u'duration': 272, u'id': u'bc970841-b7d9-415a-b7e2-645b1d263cc3'}], u'score': 1.0, u'id': u'f176baca-a4f7-4f39-906b-43136d9b3815'}]} ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_html.py0000664000175000017500000000234714035600052017223 0ustar00nicknick# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests.plugin import PluginTestCase from quodlibet import config from quodlibet.formats import AudioFile SONGS = [ AudioFile({ "title": "one", "artist": "piman", "~filename": fsnative(u"/dev/null"), }), AudioFile({ "title": u"\xf6\xe4\xfc", "~filename": fsnative(u"/dev/zero"), }), AudioFile({ "title": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls"), }), ] for song in SONGS: song.sanitize() class THTMLExport(PluginTestCase): def setUp(self): config.init() self.mod = self.modules["Export to HTML"] self.to_html = self.mod.to_html def test_empty_export(self): text = self.to_html([]) self.failUnless(" # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import socket from senf import fsnative from gi.repository import Gtk from quodlibet.formats import AudioFile from quodlibet import app from quodlibet import config from tests.plugin import PluginTestCase, init_fake_app, destroy_fake_app from tests import skipIf, run_gtk_loop @skipIf(os.name == "nt", "mpd server not supported under Windows") class TMPDServer(PluginTestCase): def setUp(self): self.mod = self.modules["mpd_server"] def test_parse_command(self): parse = self.mod.main.parse_command self.assertEqual(parse(b"foo bar"), ("foo", ["bar"])) self.assertEqual(parse(b"foo\tbar"), ("foo", ["bar"])) self.assertEqual(parse(b"foo\t bar"), ("foo", ["bar"])) self.assertEqual(parse(b"foo\t bar quux"), ("foo", ["bar", "quux"])) self.assertEqual( parse(b"foo\t bar \"q 2\" x"), ("foo", ["bar", "q 2", "x"])) self.assertEqual(parse(b"foo 'bar quux'"), ("foo", ["'bar", "quux'"])) self.assertEqual( parse(b"foo \xc3\xb6\xc3\xa4\xc3\xbc"), ("foo", [u"\xf6\xe4\xfc"])) def test_format_tags(self): format_tags = self.mod.main.format_tags def getline(key, value): song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() song[key] = value lines = format_tags(song).splitlines() if not lines: return "" if len(lines) == 1: return lines[0] # hackery since title defaults to the filename.. for l in lines: if not l.startswith("Title"): return l self.assertEqual(getline("artist", "foo"), "Artist: foo") self.assertEqual(getline("genre", "foo\nbar"), "Genre: foo, bar") self.assertEqual(getline("artistsort", "foo"), "ArtistSort: foo") self.assertEqual(getline("tracknumber", "2/3"), "Track: 2/3") self.assertEqual(getline("discnumber", "2/3"), "Disc: 2/3") self.assertEqual(getline("date", "2009-03-04"), "Date: 2009") @skipIf(os.name == "nt", "mpd server not supported under Windows") class TMPDCommands(PluginTestCase): def setUp(self): self.mod = self.modules["mpd_server"] config.init() init_fake_app() MPDServerPlugin = self.mod.MPDServerPlugin MPDConnection = self.mod.main.MPDConnection MPDService = self.mod.main.MPDService class Server: def __init__(self) -> None: super().__init__() self.service = MPDService(app, MPDServerPlugin()) def _remove_connection(self, conn): pass server = Server() s, c = socket.socketpair() self.s = s c.setblocking(False) s.settimeout(1) self.conn = MPDConnection(server, c) self.conn.handle_init(server) run_gtk_loop() self.s.recv(9999) def _cmd(self, data): self.s.send(data) while Gtk.events_pending(): Gtk.main_iteration_do(True) if data.strip() != b"idle": return self.s.recv(99999) def tearDown(self): destroy_fake_app() config.quit() def test_currentsong_length(self): app.player.go_to(AudioFile({ "~filename": fsnative(), "~#length": 12.25, })) response = self._cmd(b"currentsong\n") assert b"Time: 12\n" in response def test_tagtypes(self): response = self._cmd(b"tagtypes\n") assert b"Time\n" not in response def test_commands(self): skip = ["close", "idle", "noidle"] cmds = [c for c in self.conn.list_commands() if c not in skip] for cmd in cmds: self._cmd(cmd.encode("ascii") + b"\n") def test_idle_close(self): for cmd in ["idle", "noidle", "close"]: self._cmd(cmd.encode("ascii") + b"\n") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_mpris.py0000664000175000017500000002110014231604332017400 0ustar00nicknick# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import time try: import dbus except ImportError: dbus = None from gi.repository import Gtk from senf import fsnative from tests import skipUnless, run_gtk_loop from tests.plugin import PluginTestCase, init_fake_app, destroy_fake_app from quodlibet.formats import AudioFile from quodlibet import config from quodlibet import app A1 = AudioFile( {'album': u'greatness', 'title': 'excellent', 'artist': 'fooman\ngo', '~#lastplayed': 1234, '~#rating': 0.75, '~filename': fsnative(u'/foo a/b'), "~#length": 123, "albumartist": "aa\nbb", "bpm": "123.5", "tracknumber": "6/7"}) A1.sanitize() A2 = AudioFile( {'album': u'greatness2\ufffe', 'title': 'superlative', 'artist': u'fooman\ufffe', '~#lastplayed': 1234, '~#rating': 1.0, '~filename': fsnative(u'/foo'), 'discnumber': '4294967296'}) A2.sanitize() MAX_TIME = 3 @skipUnless(dbus, "no dbus") class TMPRIS(PluginTestCase): BUS_NAME = "org.mpris.MediaPlayer2.quodlibet" def setUp(self): self.plugin = self.plugins["mpris"].cls config.init() init_fake_app() run_gtk_loop() app.window.songlist.set_songs([A1, A2]) app.player.go_to(None) self.m = self.plugin() self.m.enabled() self._replies = [] def tearDown(self): bus = dbus.SessionBus() self.failUnless( bus.name_has_owner(self.BUS_NAME)) self.m.disabled() self.failIf(bus.name_has_owner(self.BUS_NAME)) destroy_fake_app() config.quit() del self.m def test_name_owner(self): bus = dbus.SessionBus() self.failUnless(bus.name_has_owner(self.BUS_NAME)) def _main_iface(self): bus = dbus.SessionBus() obj = bus.get_object(self.BUS_NAME, "/org/mpris/MediaPlayer2") return dbus.Interface(obj, dbus_interface="org.mpris.MediaPlayer2") def _prop(self): bus = dbus.SessionBus() obj = bus.get_object(self.BUS_NAME, "/org/mpris/MediaPlayer2") return dbus.Interface(obj, dbus_interface="org.freedesktop.DBus.Properties") def _player_iface(self): bus = dbus.SessionBus() obj = bus.get_object(self.BUS_NAME, "/org/mpris/MediaPlayer2") return dbus.Interface(obj, dbus_interface="org.mpris.MediaPlayer2.Player") def _introspect_iface(self): bus = dbus.SessionBus() obj = bus.get_object(self.BUS_NAME, "/org/mpris/MediaPlayer2") return dbus.Interface( obj, dbus_interface="org.freedesktop.DBus.Introspectable") def _reply(self, *args): self._replies.append(args) def _error(self, *args): self.failIf(args) def _wait(self, msg=""): start = time.time() while not self._replies: Gtk.main_iteration_do(False) if time.time() - start > MAX_TIME: self.fail("Timed out waiting for replies (%s)" % msg) return self._replies.pop(0) def test_main(self): args = {"reply_handler": self._reply, "error_handler": self._error} piface = "org.mpris.MediaPlayer2" app.window.hide() self.failIf(app.window.get_visible()) self._main_iface().Raise(**args) self.failIf(self._wait()) self.failUnless(app.window.get_visible()) app.window.hide() props = { "CanQuit": dbus.Boolean(True), "CanRaise": dbus.Boolean(True), "CanSetFullscreen": dbus.Boolean(False), "HasTrackList": dbus.Boolean(False), "Identity": dbus.String("Quod Libet"), "DesktopEntry": dbus.String("io.github.quodlibet.QuodLibet"), "SupportedUriSchemes": dbus.Array(), } for key, value in props.items(): self._prop().Get(piface, key, **args) resp = self._wait()[0] self.failUnlessEqual(resp, value) self.failUnless(isinstance(resp, type(value))) self._prop().Get(piface, "SupportedMimeTypes", **args) self.failUnless("audio/vorbis" in self._wait()[0]) self._introspect_iface().Introspect(**args) assert self._wait() def test_player(self): args = {"reply_handler": self._reply, "error_handler": self._error} piface = "org.mpris.MediaPlayer2.Player" props = { "PlaybackStatus": dbus.String("Stopped"), "LoopStatus": dbus.String("None"), "Rate": dbus.Double(1.0), "Shuffle": dbus.Boolean(False), "Volume": dbus.Double(1.0), "Position": dbus.Int64(0), "MinimumRate": dbus.Double(1.0), "MaximumRate": dbus.Double(1.0), "CanGoNext": dbus.Boolean(True), "CanGoPrevious": dbus.Boolean(True), "CanPlay": dbus.Boolean(True), "CanPause": dbus.Boolean(True), "CanSeek": dbus.Boolean(True), "CanControl": dbus.Boolean(True), } for key, value in props.items(): self._prop().Get(piface, key, **args) resp = self._wait(msg="for key '%s'" % key)[0] self.failUnlessEqual(resp, value) self.failUnless(isinstance(resp, type(value))) def test_volume_property(self): args = {"reply_handler": self._reply, "error_handler": self._error} piface = "org.mpris.MediaPlayer2.Player" def get_volume(): self._prop().Get(piface, "Volume", **args) return float(self._wait()[0]) assert get_volume() == 1.0 app.player.volume = 0.5 assert get_volume() == 0.5 self._prop().Set(piface, "Volume", 0.25, **args) self._wait() assert app.player.volume == 0.25 def test_metadata(self): args = {"reply_handler": self._reply, "error_handler": self._error} piface = "org.mpris.MediaPlayer2.Player" # No song case self._prop().Get(piface, "Metadata", **args) resp = self._wait()[0] self.failUnlessEqual(resp["mpris:trackid"], "/net/sacredchao/QuodLibet/NoTrack") self.failUnless(isinstance(resp["mpris:trackid"], dbus.ObjectPath)) # go to next song self._player_iface().Next(**args) self._wait() self.m.plugin_on_song_started(app.player.info) self._prop().Get(piface, "Metadata", **args) resp = self._wait()[0] self.failIfEqual(resp["mpris:trackid"], "/net/sacredchao/QuodLibet/NoTrack") # mpris stuff self.failIf(resp["mpris:trackid"].startswith("/org/mpris/")) self.failUnless(isinstance(resp["mpris:trackid"], dbus.ObjectPath)) self.failUnlessEqual(resp["mpris:length"], 123 * 10 ** 6) self.failUnless(isinstance(resp["mpris:length"], dbus.Int64)) # list text values self.failUnlessEqual(resp["xesam:artist"], ["fooman", "go"]) self.failUnlessEqual(resp["xesam:albumArtist"], ["aa", "bb"]) # single text values self.failUnlessEqual(resp["xesam:album"], "greatness") self.failUnlessEqual(resp["xesam:title"], "excellent") self.failUnlessEqual(resp["xesam:url"], "file:///foo%20a/b") # integers self.failUnlessEqual(resp["xesam:audioBPM"], 123) self.failUnless(isinstance(resp["xesam:audioBPM"], dbus.Int32)) self.failUnlessEqual(resp["xesam:trackNumber"], 6) self.failUnless(isinstance(resp["xesam:trackNumber"], dbus.Int32)) # rating self.failUnlessAlmostEqual(resp["xesam:userRating"], 0.75) self.failUnless(isinstance(resp["xesam:userRating"], dbus.Double)) # time from time import strptime from calendar import timegm seconds = timegm(strptime(resp["xesam:lastUsed"], "%Y-%m-%dT%H:%M:%S")) self.failUnlessEqual(seconds, 1234) # go to next song with invalid utf-8 self._player_iface().Next(**args) self._wait() self.m.plugin_on_song_started(app.player.info) self._prop().Get(piface, "Metadata", **args) resp = self._wait()[0] self.failUnlessEqual(resp["xesam:album"], u'greatness2\ufffd') self.failUnlessEqual(resp["xesam:artist"], [u'fooman\ufffd']) # overflow assert resp["xesam:discNumber"] == 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1672734865.0 quodlibet-4.6.0/tests/plugin/test_playlist.py0000644000175000017500000001233714354764221020133 0ustar00nicknick# Copyright 2022 Felix Krull # # 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 2 of the License, or # (at your option) any later version. import os from textwrap import dedent from quodlibet.formats import AudioFile from tests.plugin import PluginTestCase from tests.helper import temp_filename class TPlaylistExport(PluginTestCase): def setUp(self): self.mod = self.modules["Playlist Export"] def test_m3u_playlist(self): plugin = self.mod.PlaylistExport() song1 = AudioFile( { "~filename": "/a/b/c.mp3", "~#length": 123, "artist": "a", "title": "c", } ) song2 = AudioFile( { "~filename": "/a/b/d.mp3", "~#length": 400, "artist": "b", "title": "d", } ) with temp_filename() as playlist_file_path: plugin.save_playlist( [song1, song2], playlist_file_path, self.mod.FORMAT_M3U, relative=False ) with open(playlist_file_path, "r") as f: result = f.read() assert result == dedent( """\ #EXTM3U #EXTINF:123,a - c /a/b/c.mp3 #EXTINF:400,b - d /a/b/d.mp3 """ ) def test_m3u_playlist_relative(self): plugin = self.mod.PlaylistExport() with temp_filename(as_path=True) as playlist_file_path: song1 = audio_file( filename=playlist_file_path.parent / "a" / "b.mp3", length=23, artist="a", title="b", ) song2 = audio_file( filename=playlist_file_path.parent.parent / "c.mp3", length=1, artist="a", title="c", ) plugin.save_playlist( [song1, song2], playlist_file_path, self.mod.FORMAT_M3U, relative=True ) result = playlist_file_path.read_text() assert result == dedent( f"""\ #EXTM3U #EXTINF:23,a - b {os.path.join("a", "b.mp3")} #EXTINF:1,a - c {os.path.join(os.pardir, "c.mp3")} """ ) def test_pls_playlist(self): plugin = self.mod.PlaylistExport() song1 = audio_file(filename="/a/b/c.mp3", length=123, artist="a", title="c") song2 = audio_file(filename="/a/b/d.mp3", length=400, artist="b", title="d") with temp_filename() as playlist_file_path: plugin.save_playlist( [song1, song2], playlist_file_path, self.mod.FORMAT_PLS, relative=False ) with open(playlist_file_path, "r") as f: result = f.read() assert result == dedent( """\ [playlist] File1=/a/b/c.mp3 Title1=a - c Length1=123 File2=/a/b/d.mp3 Title2=b - d Length2=400 NumberOfEntries=2 Version=2 """ ) def test_pls_playlist_relative(self): plugin = self.mod.PlaylistExport() with temp_filename(as_path=True) as playlist_file_path: song1 = audio_file( filename=playlist_file_path.parent / "a" / "b.mp3", length=23, artist="a", title="b", ) song2 = audio_file( filename=playlist_file_path.parent.parent / "c.mp3", length=1, artist="a", title="c", ) plugin.save_playlist( [song1, song2], playlist_file_path, self.mod.FORMAT_PLS, relative=True ) result = playlist_file_path.read_text() assert result == dedent( f"""\ [playlist] File1={os.path.join("a", "b.mp3")} Title1=a - b Length1=23 File2={os.path.join(os.pardir, "c.mp3")} Title2=a - c Length2=1 NumberOfEntries=2 Version=2 """ ) def test_m3u_relative_path_starting_with_octothorpe(self): plugin = self.mod.PlaylistExport() with temp_filename(as_path=True) as playlist_file_path: song = audio_file( filename=playlist_file_path.parent / "#file.mp3", length=1, artist="a", title="b", ) plugin.save_playlist( [song], playlist_file_path, self.mod.FORMAT_M3U, relative=True ) result = playlist_file_path.read_text() assert result == dedent( f"""\ #EXTM3U #EXTINF:1,a - b {os.path.join(os.curdir, "#file.mp3")} """ ) def audio_file(filename, length, artist, title): return AudioFile( { "~filename": str(filename), "~#length": length, "artist": artist, "title": title, } ) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1692735242.034269 quodlibet-4.6.0/tests/plugin/test_plugins/0000755000175000017500000000000014471213412017362 5ustar00nicknick././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_plugins/pickle_plugin.py0000664000175000017500000000141414035600052022557 0ustar00nicknick# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import shelve from tests import mkstemp from quodlibet.plugins.events import EventPlugin class PickleMe: pass class PickleTestPlugin(EventPlugin): PLUGIN_ID = "pickle_plugin" PLUGIN_NAME = "This is a test" def enabled(self): # https://github.com/quodlibet/quodlibet/issues/1093 fd, filename = mkstemp('.shelve') os.close(fd) os.unlink(filename) s = shelve.open(filename) s["foobar"] = PickleMe() s.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_prefs.py0000664000175000017500000000261714035600052017376 0ustar00nicknick# Copyright 2012 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from pytest import fixture from quodlibet import config, app from quodlibet.ext._shared.squeezebox.server import SqueezeboxException from quodlibet.plugins import Plugin from tests.plugin import (init_fake_app, destroy_fake_app, plugins) PREFS_PLUGINS = [p for p in plugins.values() if hasattr(p.cls, "PluginPreferences")] @fixture def fake_app(): config.init() init_fake_app() yield app destroy_fake_app() config.quit() @fixture(params=PREFS_PLUGINS, ids=lambda p: p.cls) def plugin_with_prefs(fake_app, request) -> Plugin: return request.param class TestPluginPrefs: def test_prefs_detected(self): assert PREFS_PLUGINS, "No plugins with preferences detected" def test_plugin_pref(self, plugin_with_prefs): plugin = plugin_with_prefs.cls if hasattr(plugin, "PLUGIN_INSTANCE"): plugin = plugin() try: plugin.PluginPreferences(Gtk.Window()) except (SqueezeboxException,): # TODO: fix squeezebox init errors where config exists pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_query.py0000664000175000017500000001155514035600052017425 0ustar00nicknick# Copyright 2016 Ryan Dellenbaugh # # 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 2 of the License, or # (at your option) any later version. import os from tests.plugin import PluginTestCase from tests import mkstemp from quodlibet.plugins import Plugin from quodlibet.plugins.query import QueryPlugin, QueryPluginError from quodlibet.plugins.query import QUERY_HANDLER from quodlibet.formats import AudioFile class FakeQueryPlugin(QueryPlugin): PLUGIN_ID = 'fake_query_plugin' PLUGIN_NAME = 'fake_query' key = 'fake' def search(self, data, body): return True fake_plugin = Plugin(FakeQueryPlugin) class TQueryPlugins(PluginTestCase): def test_handler(self): self.failUnlessRaises(KeyError, QUERY_HANDLER.get_plugin, 'fake') QUERY_HANDLER.plugin_enable(fake_plugin) self.failUnless( isinstance(QUERY_HANDLER.get_plugin('fake'), FakeQueryPlugin)) QUERY_HANDLER.plugin_disable(fake_plugin) self.failUnlessRaises(KeyError, QUERY_HANDLER.get_plugin, 'fake') def test_conditional(self): if 'conditional_query' not in self.plugins: return plugin = self.plugins['conditional_query'].cls() self.failUnlessRaises(QueryPluginError, plugin.parse_body, None) self.failUnlessRaises(QueryPluginError, plugin.parse_body, '') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'single=query') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'a=first,b=second') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'invalid/query') self.failUnless(plugin.parse_body('a=first,b=second,c=third')) self.failUnless(plugin.parse_body('@(ext),#(numcmp > 0),!negation')) body = plugin.parse_body('artist=a, genre=rock, genre=classical') self.failUnless(plugin.search( AudioFile({'artist': u'a', 'genre': u'rock'}), body)) self.failIf(plugin.search( AudioFile({'artist': u'a', 'genre': u'classical'}), body)) self.failIf(plugin.search( AudioFile({'artist': u'b', 'genre': u'rock'}), body)) self.failUnless(plugin.search( AudioFile({'artist': u'b', 'genre': u'classical'}), body)) def test_savedsearch(self): if 'include_saved' not in self.plugins: return plugin = self.plugins['include_saved'].cls() self.failUnlessRaises(QueryPluginError, plugin.parse_body, None) try: fd, filename = mkstemp(text=True) file = os.fdopen(fd, 'w') file.write("artist=a\nQuery 1\ngenre=classical\nAnother query") file.close() self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'missing query') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'artist=a') self.failUnless(plugin.parse_body(' quEry 1', query_path_=filename)) query1 = plugin.parse_body('Query 1', query_path_=filename) query2 = plugin.parse_body('another query', query_path_=filename) song = AudioFile({'artist': u'a', 'genre': u'dance'}) self.failUnless(plugin.search(song, query1)) self.failIf(plugin.search(song, query2)) finally: os.remove(filename) def test_python_expression(self): if 'python_query' not in self.plugins: return plugin = self.plugins['python_query'].cls() self.failUnlessRaises(QueryPluginError, plugin.parse_body, None) self.failUnlessRaises(QueryPluginError, plugin.parse_body, '') self.failUnlessRaises(QueryPluginError, plugin.parse_body, '\\') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'unclosed[') self.failUnlessRaises(QueryPluginError, plugin.parse_body, 'return s') self.failUnless(plugin.parse_body('3')) self.failUnless(plugin.parse_body('s')) body1 = plugin.parse_body("s('~#rating') > 0.5") body2 = plugin.parse_body( "s('genre').lower()[2:] in ('rock', 'pop')") body3 = plugin.parse_body("len(s('title')) < 6") song1 = AudioFile({'title': 'foobar', '~#rating': 0.8, 'genre': 'jazz'}) song2 = AudioFile({'title': 'baz', '~#rating': 0.4, 'genre': 'aapop'}) self.failUnless(plugin.search(song1, body1)) self.failIf(plugin.search(song1, body2)) self.failIf(plugin.search(song1, body3)) self.failIf(plugin.search(song2, body1)) self.failUnless(plugin.search(song2, body2)) self.failUnless(plugin.search(song2, body3)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_randomalbum.py0000664000175000017500000001042214035600052020551 0ustar00nicknick# 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 2 of the License, or # (at your option) any later version. from quodlibet import config, app from quodlibet.browsers.albums import AlbumList from quodlibet.formats import AudioFile from quodlibet.util.collection import Album from quodlibet.util.dprint import print_d from tests import init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase A1S1 = AudioFile( {'album': 'greatness', 'title': 'excellent', 'artist': 'fooman', '~#lastplayed': 1234, '~#rating': 0.75}) A1S2 = AudioFile( {'album': 'greatness', 'title': 'superlative', 'artist': 'fooman', '~#lastplayed': 1234, '~#rating': 1.0}) A1 = Album(A1S1) A1.songs = {A1S1, A1S2} A2S1 = AudioFile({'album': 'mediocrity', 'title': 'blah', 'artist': 'fooman', '~#lastplayed': 1234}) A2S2 = AudioFile({'album': 'mediocrity', 'title': 'meh', 'artist': 'fooman', '~#lastplayed': 1234}) A2 = Album(A2S1) A2.songs = {A2S1, A2S2} A3S1 = AudioFile( {'album': 'disappointment', 'title': 'shameful', 'artist': 'poorman', '~#lastplayed': 2345, '~#rating': 0.25}) A3S2 = AudioFile( {'album': 'disappointment', 'title': 'zero', 'artist': 'poorman', '~#lastplayed': 2345, '~#rating': 0.0}) A3S3 = AudioFile( {'album': 'disappointment', 'title': 'lame', 'artist': 'poorman', '~#lastplayed': 0, '~#rating': 0.25}) A3 = Album(A3S1) A3.songs = {A3S1, A3S2, A3S3} for song in [A1S1, A1S2, A2S1, A2S2, A3S1, A3S2, A3S3]: song["~#length"] = 100 class TRandomAlbum(PluginTestCase): """Some basic tests for the random album plugin algorithm""" WEIGHTS = {'rating': 0, 'added': 0, 'laststarted': 0, 'lastplayed': 0, 'length': 0, 'skipcount': 0, 'playcount': 0} def setUp(self): config.init() init_fake_app() app.player.paused = False # Only album browsers are supported currently app.library.clear() app.window.browser = AlbumList(app.library) self.plugin = self.plugins["Random Album Playback"].cls() self.albums = [A1, A2, A3] def tearDown(self): app.window.browser.destroy() destroy_fake_app() config.quit() def get_winner(self, albums): print_d("Weights: %s " % self.plugin.weights) scores = self.plugin._score(albums) print_d("Scores: %s" % scores) if not scores: return None return max(scores)[1] def test_empty_integration_weighted(self): # See issue #2756 self.plugin.use_weights = True self.failIf(self.plugin.plugin_on_song_started(None)) def test_empty_integration(self): # See issue #2756 self.plugin.use_weights = False self.failIf(self.plugin.plugin_on_song_started(None)) def test_score_rating(self): weights = self.plugin.weights = self.WEIGHTS.copy() weights['rating'] = 1 self.failUnlessEqual(A1, self.get_winner(self.albums)) def test_score_length(self): weights = self.plugin.weights = self.WEIGHTS.copy() weights['length'] = 1 self.failUnlessEqual(A3, self.get_winner(self.albums)) def test_score_lastplayed(self): weights = self.plugin.weights = self.WEIGHTS.copy() weights['lastplayed'] = 1 self.failUnlessEqual(A3, self.get_winner(self.albums)) def test_score_lastplayed_added(self): weights = self.plugin.weights = self.WEIGHTS.copy() weights['lastplayed'] = 1 # No data here weights['added'] = 1 self.failUnlessEqual(A3, self.get_winner(self.albums)) def test_score_mixed(self): print_d("Starting.") weights = self.plugin.weights = self.WEIGHTS.copy() weights['length'] = 1 weights['lastplayed'] = 2 weights['rating'] = 1 # A3 is #3 rating, #1 in lastplayed, #1 in length self.failUnlessEqual(A3, self.get_winner(self.albums)) weights['lastplayed'] = 1 weights['rating'] = 2 weights['length'] = 0.5 # A1 is #1 for Rating, #2 for lastplayed, #2 or 3 length self.failUnlessEqual(A1, self.get_winner(self.albums)) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_rbimport.py0000664000175000017500000000501614231604332020114 0ustar00nicknick# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import xml.sax from senf import fsn2uri from quodlibet.formats import AudioFile from tests.helper import temp_filename from quodlibet.library import SongFileLibrary from quodlibet.util.path import find_mount_point from . import PluginTestCase def get_example_xml(song_path, rating, lastplayed): song_uri = fsn2uri(song_path) mount_uri = fsn2uri(find_mount_point(song_path)) return (u"""\ Music Unknown 7 199 4799124 %s %s 1378717158 1339576187 1409855394 %d 1 191 %d 731881 audio/mpeg Unknown \ """ % (song_uri, mount_uri, lastplayed, rating)).encode("utf-8") class TRBImport(PluginTestCase): def setUp(self): self.mod = self.modules["rbimport"] def test(self): lib = SongFileLibrary() with temp_filename() as song_fn: song = AudioFile({"~filename": song_fn}) song.sanitize() lib.add([song]) with temp_filename() as xml_fn: with open(xml_fn, "wb") as h: x = get_example_xml(song("~filename"), 1, 1371802107) h.write(x) handler = self.mod.RBDBContentHandler(lib) xml.sax.parse(xml_fn, handler) self.assertEqual(song("~#rating"), 0.2) self.assertEqual(song("~#lastplayed"), 1371802107) self.assertEqual(song("~#playcount"), 1) with open(xml_fn, "wb") as h: x = get_example_xml(song("~filename"), 2, 1371802107 - 1) h.write(x) handler = self.mod.RBDBContentHandler(lib) xml.sax.parse(xml_fn, handler) self.assertEqual(song("~#rating"), 0.4) self.assertEqual(song("~#lastplayed"), 1371802107) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_replaygain.py0000664000175000017500000001363314035600052020412 0ustar00nicknick# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, GLib import re import time from quodlibet.ext.songsmenu.replaygain import UpdateMode, RGDialog, \ ReplayGainPipeline from quodlibet.formats import MusicFile from quodlibet.formats import AudioFile from tests.plugin import PluginTestCase from tests import get_data_path, TestCase class TReplayGain(PluginTestCase): # Give up analysis after some time, in case GStreamer dies. TIMEOUT = 20 @classmethod def setUpClass(cls): cls.mod = cls.modules["ReplayGain"] cls.kind = cls.plugins["ReplayGain"].cls @classmethod def tearDownClass(cls): del cls.mod del cls.kind def setUp(self): self.song = AudioFile({'artist': 'foo', 'album': 'the album'}) self.plugin = self.kind([self.song], None) def tearDown(self): self.plugin.destroy() del self.plugin del self.song def test_RGSong_properties(self): rgs = self.mod.RGSong(self.song) self.failIf(rgs.has_album_tags) self.failIf(rgs.has_track_tags) self.failIf(rgs.has_all_rg_tags) rgs.done = True rgs._write(-1.23, 0.99) self.failUnless(rgs.has_album_tags, msg="Didn't write album tags") self.failIf(rgs.has_track_tags) self.failIf(rgs.has_all_rg_tags) def test_RGSong_zero(self): rgs = self.mod.RGSong(self.song) rgs.done = True rgs._write(0.0, 0.0) self.failUnless(rgs.has_album_tags, msg="Failed with 0.0 album tags (%s)" % rgs) def test_RGAlbum_properties(self): rga = self.mod.RGAlbum([self.mod.RGSong(self.song)], UpdateMode.ALWAYS) self.failIf(rga.done) self.failUnlessEqual(rga.title, 'foo - the album') def test_delete_bs1770gain(self): tags = ["replaygain_reference_loudness", "replaygain_algorithm", "replaygain_album_range", "replaygain_track_range"] for tag in tags: self.song[tag] = u"foo" rgs = self.mod.RGSong(self.song) rgs.done = True rgs._write(0.0, 0.0) for tag in tags: self.assertFalse(self.song(tag)) def _analyse_song(self, song): mode = self.mod.UpdateMode.ALWAYS self.album = album = self.mod.RGAlbum.from_songs([song], mode) self.analysed = None def _run_main_loop(): def on_complete(pipeline, album): album.write() self.analysed = [album] pipeline = self.mod.ReplayGainPipeline() sig = pipeline.connect('done', on_complete) pipeline.start(album) start = time.time() while not self.analysed and \ abs(time.time() - start) < self.TIMEOUT: Gtk.main_iteration_do(False) pipeline.quit() pipeline.disconnect(sig) _run_main_loop() self.assertTrue(self.analysed, "Timed out") def test_analyze_sinewave(self): song = MusicFile(get_data_path("sine-110hz.flac")) self.failUnlessEqual(song("~#length"), 2) self.failIf(song("~replaygain_track_gain")) self._analyse_song(song) self.failUnlessAlmostEqual(song("~#replaygain_track_peak"), 1.0, msg="Track peak should be 1.0") track_gain = song("~#replaygain_track_gain") self.failUnless(track_gain, msg="No Track Gain added") self.failUnless(re.match(r'\-[0-9]\.[0-9]{1,2}', str(track_gain))) # For one-song album, track == album self.failUnlessEqual(track_gain, song('~#replaygain_album_gain')) def test_analyze_silence(self): song = MusicFile(get_data_path("silence-44-s.ogg")) self.failIf(song("~replaygain_track_gain")) self._analyse_song(song) self.failUnlessAlmostEqual(song("~#replaygain_track_peak"), 0.0, msg="Track peak should be 0.0") track_gain = song("~#replaygain_track_gain") self.failUnless(track_gain, msg="No Track Gain added") # For one-song album, track == album self.failUnlessEqual(track_gain, song('~#replaygain_album_gain')) class FakePipeline(ReplayGainPipeline): def __init__(self): super().__init__() self.started = [] def quit(self): pass def _setup_pipe(self): pass def start(self, album): self.started.append(album) super().start(album) def _next_song(self, first=False): GLib.idle_add(self._emit) def _emit(self): self.emit("done", self._album) class FakeRGDialog(RGDialog): def create_pipelines(self): self.pipes = [FakePipeline(), FakePipeline()] class TRGDialog(TestCase): def test_some_songs_needing_update(self): songs = [[a_song(x)] for x in range(8)] d = FakeRGDialog(songs, None, UpdateMode.ALBUM_MISSING) d.start_analysis() self.run_main_loop() d.destroy() # One should have got half of the albums needing update (and no more) self.failUnlessEqual(self.track_nums_from(d.pipes[0].started), [0, 4]) # And the other processor should get the other half self.failUnlessEqual(self.track_nums_from(d.pipes[1].started), [2, 6]) def run_main_loop(self, timeout=0.25): start = time.time() while abs(time.time() - start) < timeout: Gtk.main_iteration_do(False) def track_nums_from(self, album): return [s.songs[0].song("~#tracknumber") for s in album] def a_song(n): d = {'replaygain_album_gain': -6.0} if n % 2 else {} d['tracknumber'] = n return AudioFile(d) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919751.0 quodlibet-4.6.0/tests/plugin/test_scrobbler.py0000664000175000017500000000616514231604507020245 0ustar00nicknick# Copyright 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import threading from time import sleep, time from typing import List, Dict from quodlibet import config from quodlibet.ext.events.qlscrobbler import QLSubmitQueue from quodlibet.formats import AudioFile from quodlibet.util.picklehelper import pickle_load from senf import fsnative from tests import run_gtk_loop, init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase A_SONG = AudioFile({"~filename": fsnative("fake.mp3"), "artist": "Foo bar", "title": "The Title"}) class TScrobbler(PluginTestCase): @classmethod def setUpClass(cls): config.init() init_fake_app() @classmethod def tearDownClass(cls): destroy_fake_app() config.quit() def setUp(self): self.mod = self.modules["QLScrobbler"] self.plugin = self.plugins["QLScrobbler"].cls() # It's a class instance, so make sure :( self.plugin.queue.queue.clear() self.SCROBBLER_CACHE_FILE = self.mod.QLSubmitQueue.SCROBBLER_CACHE_FILE try: os.unlink(self.SCROBBLER_CACHE_FILE) except FileNotFoundError: pass def tearDown(self): del self.mod def test_queue(self): queue: QLSubmitQueue = self.mod.QLSubmitQueue() thread = threading.Thread(target=queue.run, daemon=True) thread.start() songs = [A_SONG] for song in songs: queue.submit(song) assert len(queue.queue) == 1 queue.dump_queue() loaded = self.load_queue() assert all(actual['a'] == expected["artist"] and actual['t'] == expected["title"] for actual, expected in zip(loaded, songs)) def load_queue(self) -> List[Dict]: try: with open(self.SCROBBLER_CACHE_FILE, 'rb') as f: return pickle_load(f) except FileNotFoundError: return [] def test_enabled_disabled(self): self.plugin.enabled() assert self.plugin._tid # Disable self.plugin.disabled() assert not self.plugin._tid def test_autosave(self): self.plugin.AUTOSAVE_INTERVAL = 0.1 self.plugin.enabled() assert not self.load_queue() assert not self.plugin.queue.queue, "Queue not empty in test" self.plugin.queue.submit(A_SONG) assert len(self.plugin.queue.queue) == 1, "Song wasn't queued" queue = self.retry_queue() assert len(queue) == 1, "Queued song didn't get persisted" self.plugin.disabled() def retry_queue(self): """Allows GTK looks, flushing of disk buffers etc""" queue = None start = time() while time() - start < 2: run_gtk_loop() queue = self.load_queue() if queue: break sleep(0.1) return queue ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_seekbar.py0000664000175000017500000000124614035600052017670 0ustar00nicknick# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests.plugin import PluginTestCase from quodlibet.player.nullbe import NullPlayer from quodlibet.library import SongLibrary class TSeekBar(PluginTestCase): def setUp(self): self.mod = self.modules["SeekBar"] def tearDown(self): del self.mod def test_create(self): SeekBar = self.mod.SeekBar SeekBar(NullPlayer(), SongLibrary()).destroy() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1618411562.0 quodlibet-4.6.0/tests/plugin/test_songsmenu.py0000664000175000017500000000506514035600052020275 0ustar00nicknick# Copyright 2013 Christoph Reiter, Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from senf import fsnative from quodlibet.plugins.songsmenu import SongsMenuPlugin from tests.plugin import PluginTestCase from quodlibet import config from quodlibet.qltk.songsmenu import SongsMenuPluginHandler from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary, SongLibrarian SONGS = [ AudioFile({ "title": "one", "artist": "piman", "~filename": fsnative(u"/dev/null"), }), AudioFile({ "title": "two", "artist": "mu", "~filename": fsnative(u"/dev/zero"), }), AudioFile({ "title": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls"), }), ] SONGS.sort() for song in SONGS: song.sanitize() class TPluginsSongsMenu(PluginTestCase): def setUp(self): config.init() self.h = SongsMenuPluginHandler() library = SongLibrary() library.librarian = SongLibrarian() self.lib = library self.parent = Gtk.Window() def tearDown(self): self.lib.destroy() self.parent.destroy() config.quit() def test_init(self): for id_, plugin in self.plugins.items(): if self.h.plugin_handle(plugin): self.h.plugin_enable(plugin) self.h.handle(id_, None, None, []) self.h.plugin_disable(plugin) def test_handle_single(self): self.skipTest("Pops up windows and needs user input.. so disabled." "Still worth keeping whilst we don't have unit tests " "for all plugins.") # Ignored... for id_, plugin in self.plugins.items(): if self.h.plugin_handle(plugin): self.h.plugin_enable(plugin, None) self.h.handle(id_, self.lib, self.parent, SONGS) self.h.plugin_disable(plugin) def test_handles_albums(self): for id_, plugin in self.plugins.items(): if isinstance(plugin, SongsMenuPlugin): ha = plugin.handles_albums self.failIf(hasattr(plugin, "plugin_single_album") and not ha) self.failIf(hasattr(plugin, "plugin_plugin_album") and not ha) self.failIf(hasattr(plugin, "plugin_albums") and not ha) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919642.0 quodlibet-4.6.0/tests/plugin/test_style.py0000664000175000017500000000573214231604332017423 0ustar00nicknick# Copyright 2015 Anton Shestakov # 2021 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from tests.helper import ListWithUnused as L from tests.plugin import PluginTestCase from quodlibet.util.string.titlecase import human_title class TPluginStyle(PluginTestCase): def conclude(self, fails): def format_msg(f): return "%s: '%s' plugin (%s)" % (f[1], f[0].name, f[0].cls) if not fails: return grouped = {} for f in fails: grouped.setdefault(f[2], []).append(f) lines = [] for reason in grouped: lines.append('== ' + reason + ' ==') for f in grouped[reason]: plugin, string = f[:2] pclass = plugin.cls.__name__ ppath = plugin.cls.__module__.rpartition('.plugins.')[2] lines.append("%s.%s: %r" % (ppath, pclass, string)) self.fail("One or more plugins did not pass:\n" + '\n'.join(lines)) def test_plugin_name(self): REASON_ABSENT = "plugin should have PLUGIN_NAME" REASON_CASE = "PLUGIN_NAME should be in Title Case" ok_names = L( 'Last.fm Cover Source', 'Last.fm Sync', 'Send to iFP', 'This is a test') fails = [] for pid, plugin in self.plugins.items(): if not hasattr(plugin.cls, 'PLUGIN_NAME'): fails.append((plugin, None, REASON_ABSENT)) continue name = plugin.cls.PLUGIN_NAME if name != human_title(name): if name not in ok_names: fails.append((plugin, name, REASON_CASE)) ok_names.check_unused() self.conclude(fails) def test_plugin_desc(self): REASON_ABSENT = "plugin should have PLUGIN_DESC or PLUGIN_DESC_MARKUP" REASON_DOT = ("PLUGIN_DESC / PLUGIN_DESC_MARKUP " "should be a full sentence and end with a '.'") skip_plugins = L('pickle_plugin') fails = [] for pid, plugin in self.plugins.items(): cls = plugin.cls if pid in skip_plugins: continue got = 0 if hasattr(cls, 'PLUGIN_DESC'): got += 1 desc = cls.PLUGIN_DESC if not desc.endswith('.'): fails.append((plugin, desc, REASON_DOT)) continue if hasattr(cls, "PLUGIN_DESC_MARKUP"): got += 1 desc = cls.PLUGIN_DESC_MARKUP if not desc.endswith('.'): fails.append((plugin, desc, REASON_DOT)) continue if not got: fails.append((plugin, None, REASON_ABSENT)) skip_plugins.check_unused() self.conclude(fails) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1650919751.0 quodlibet-4.6.0/tests/plugin/test_synchronize_to_device.py0000775000175000017500000012741114231604507022665 0ustar00nicknick# Copyright 2020 Daniel Petrescu # # 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 2 of the License, or # (at your option) any later version. import os from os import makedirs from pathlib import Path from unittest.mock import ANY, patch from gi.repository import Gtk from quodlibet import app from quodlibet import config from quodlibet import library from quodlibet import get_user_dir from quodlibet.formats import AudioFile from quodlibet.plugins import PM from quodlibet.qltk.ccb import ConfigCheckButton from quodlibet.util.path import strip_win32_incompat_from_path from tests.plugin import PluginTestCase QUERIES = { 'Directory': {'query': '~dirname="/dev/null"', 'terms': ('/dev/null',), 'results': 5}, '2 artists': {'query': 'artist=|("Group1","Group2")', 'terms': ('Group',), 'results': 4}, 'No songs': {'query': '#(length < 0)', 'terms': (), 'results': 0}, 'Symbols': {'query': '~dirname="/tmp/new"', 'terms': ('/tmp/new',), 'results': 1} } PATTERNS = [ ' - <artist> - <album>', '<title><albumartist| - <albumartist>|<artist| - <artist>>>' ] SONGS = [ AudioFile({'~filename': '/dev/null/Song1.mp3', 'title': 'Song1', 'artist': 'Artist1', 'album': 'Album1'}), AudioFile({'~filename': '/dev/null/Song2.mp3', 'title': 'Song2', 'artist': 'Artist1', 'album': 'Album1'}), AudioFile({'~filename': '/dev/null/Song3.mp3', 'title': 'Song3', 'artist': 'Artist1', 'album': 'Album2'}), AudioFile({'~filename': '/dev/null/Song4.mp3', 'title': 'Song4', 'artist': 'Artist2', 'album': 'Album2'}), AudioFile({'~filename': '/dev/null/Song5.mp3', 'title': 'Song5', 'artist': 'Artist2', 'album': 'Album2'}), AudioFile({'~filename': '/tmp/music/Song5.mp3', 'title': 'Song5', 'artist': 'Artist2', 'album': 'Album2'}), AudioFile({'~filename': '/tmp/music/Track1.mp3', 'title': 'Track1', 'artist': 'Group1', 'album': 'Album3'}), AudioFile({'~filename': '/tmp/music/Track2-1.mp3', 'title': 'Track2', 'artist': 'Group1', 'album': 'Album3'}), AudioFile({'~filename': '/tmp/music/Track2-2.mp3', 'title': 'Track2', 'artist': 'Group2', 'album': 'Album4'}), AudioFile({'~filename': '/tmp/music/Track3.mp3', 'title': 'Track3', 'artist': 'Group2', 'album': 'Album4'}), AudioFile({'~filename': '/tmp/new/', 'title': 'Abc123 (~!@#$%^&*|:\'",.\\/?+=;)', 'artist': r'[ÆÁàçÈéöø] <αΔλΛ> Привет こんにちわ مرحبا', 'album': r'{‰} → A∩B≥3 ⎈Ⓐ ░ ☔☃☂ ♂♀🤴 😀🎧 🪐👽🖖'}) ] class TSyncToDevice(PluginTestCase): QUERIES_SAVED = '\n'.join([details['query'] + '\n' + name for name, details in QUERIES.items()]) RENAMEPATTERNS = '\n'.join(PATTERNS) @classmethod def setUpClass(cls): plugin_id = 'synchronize_to_device' cls.module = cls.modules[plugin_id] cls.plugin = cls.module.SyncToDevice() cls.gtk_window = Gtk.Window() @classmethod def tearDownClass(cls): cls.gtk_window.destroy() del cls.plugin del cls.module def setUp(self): path_query = Path(self.plugin.path_query) path_query.parent.mkdir(parents=True, exist_ok=True) with open(self.plugin.path_query, 'w') as f: f.write(self.QUERIES_SAVED) path_pattern = Path(self.plugin.path_pattern) path_pattern.parent.mkdir(parents=True, exist_ok=True) with open(self.plugin.path_pattern, 'w') as f: f.write(self.RENAMEPATTERNS) path_dest = Path(get_user_dir(), 'export') path_dest.mkdir(parents=True, exist_ok=True) self.path_dest = str(path_dest) self.main_vbox = self._start_plugin() self.searches = {} for button in self.plugin.saved_search_vbox.get_children(): self.searches[button] = button.get_active() self.dest_entry = self.plugin.destination_entry self.path_dest_old_text = self.dest_entry.get_text() self.pattern_entry = self.plugin.export_pattern_entry self.pattern_old_text = self.pattern_entry.get_text() self.Tags = self.module.Entry.Tags def tearDown(self): for button, value in self.searches.items(): button.set_active(value) self.dest_entry.set_text(self.path_dest_old_text) self.pattern_entry.set_text(self.pattern_old_text) if os.path.exists(self.plugin.path_query): os.remove(self.plugin.path_query) if os.path.exists(self.plugin.path_pattern): os.remove(self.plugin.path_pattern) for root, dirs, files in os.walk(self.path_dest, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) def _start_plugin(self): return self.plugin.PluginPreferences(self.gtk_window) def _make_query_config(self, label): return self.module.PLUGIN_CONFIG_SECTION + '_' \ + self.plugin.CONFIG_QUERY_PREFIX \ + label.lower() def _select_searches(self, *labels): for button in self.plugin.saved_search_vbox.get_children(): if button.get_label() in labels: button.set_active(True) def _make_library(self, add_songs=True): app.library = library.init() if add_songs: app.library.add(SONGS) def _make_files_for_deletion(self, *files): if not files: files = ['song1.mp3', 'file1.txt', 'file2.csv'] for f in files: file_path = os.path.join(self.path_dest, f) song_folders = os.path.dirname(file_path) makedirs(song_folders, exist_ok=True) with open(file_path, 'w'): # Create a blank file pass return len(files) def _verify_child(self, model, path, iter_, *data): tag = model[path][self.plugin._model_col_id('tag')] self.assertTrue( any(tag.startswith(tag) for tag in data[0]), 'Song status "{}" does not start with "{}"'.format(tag, data[0])) filename = model[path][self.plugin._model_col_id('filename')] self.assertIsNotNone(filename, "filename field shouldn't be None") self.assertNotEqual(filename, '', "filename field shouldn't be empty") export = model[path][self.plugin._model_col_id('export')] self.assertTrue( any(export.startswith(export_path) for export_path in data[1]), 'Export path "{}" does not start with "{}"'.format(export, data[1])) song = model[path][self.plugin._model_col_id('entry')]._song if song and data[2] and data[3]: self.assertTrue(song[data[2]].startswith(data[3]), 'Data in given field "{}" does not start with {}'.format( song[data[2]], data[3])) return False def _model_set_value(self, column_name, cell_id, value): col_id = self.plugin._model_col_id(column_name) - 1 column = self.plugin.details_tree.get_column(col_id) self.plugin.renders[column].emit('edited', cell_id, value) def _model_get_value(self, cell_id, column): iter_ = self.plugin.model.get_iter(cell_id) return self.plugin.model.get_value( iter_, self.plugin._model_col_id(column)) def _model_remove_by_tag(self, rm_tag): iter_ = self.plugin.model.get_iter_first() while iter_: entry_tag = self.plugin.model.get_value( iter_, self.plugin._model_col_id('tag')) if entry_tag == rm_tag: self.plugin.model.remove(iter_) else: iter_ = self.plugin.model.iter_next(iter_) def _mark_song_unique(self, cell_edit, new_text='updated path', check=True): self._model_set_value('export', cell_edit, new_text) if check: self.assertEqual(self._model_get_value(cell_edit, 'export'), new_text) self.assertEqual(self._model_get_value(cell_edit, 'tag'), self.Tags.PENDING_COPY) def _mark_song_duplicate(self, cell_edit, cell_copy, check=True): new_text = self._model_get_value(cell_copy, 'export') self._model_set_value('export', cell_edit, new_text) if check: self.assertEqual(self._model_get_value(cell_edit, 'export'), new_text) self.assertEqual(self._model_get_value(cell_edit, 'tag'), self.Tags.SKIP_DUPLICATE) def _mark_song_delete(self, cell_edit, check=True): new_text = self.Tags.DELETE self._model_set_value('export', cell_edit, new_text) if check: self.assertEqual(self._model_get_value(cell_edit, 'export'), '') self.assertEqual(self._model_get_value(cell_edit, 'tag'), self.Tags.SKIP) def _mark_song_empty(self, cell_edit, check=True): new_text = '' self._model_set_value('export', cell_edit, new_text) if check: self.assertEqual(self._model_get_value(cell_edit, 'export'), new_text) self.assertEqual(self._model_get_value(cell_edit, 'tag'), self.Tags.SKIP) def test_pluginpreferences_missing_saved_queries_file(self): os.remove(self.plugin.path_query) self.main_vbox = self._start_plugin() self.assertFalse(os.path.exists(self.plugin.path_query)) self.assertEqual(type(self.main_vbox), Gtk.Frame) def test_pluginpreferences_no_saved_queries(self): with open(self.plugin.path_query, 'w') as f: f.write('') self.main_vbox = self._start_plugin() self.assertEqual(type(self.main_vbox), Gtk.Frame) def test_pluginpreferences_success(self): self.assertEqual(type(self.main_vbox), Gtk.VBox) self.assertEqual(len(self.plugin.queries), len(QUERIES)) self.assertTrue(all(isinstance(button, ConfigCheckButton) for button in self.plugin.saved_search_vbox.get_children())) self.assertFalse(any(button.get_active() for button in self.plugin.saved_search_vbox.get_children())) self.assertNotEqual( self.plugin.destination_entry.get_placeholder_text(), '') self.assertEqual(self.plugin.destination_entry.get_text(), '') self.assertNotEqual( self.plugin.export_pattern_entry.get_placeholder_text(), '') self.assertNotEqual(self.plugin.export_pattern_entry.get_text(), '') n_cols = self.plugin.model.get_n_columns() self.assertEqual(n_cols, len(self.plugin.model_cols)) self.assertTrue(self.plugin.preview_start_button.get_visible()) self.assertFalse(self.plugin.preview_stop_button.get_visible()) self.assertFalse(self.plugin.status_operation.get_visible()) self.assertEqual(self.plugin.status_operation.get_text(), '') self.assertFalse(self.plugin.status_progress.get_visible()) self.assertEqual(self.plugin.status_progress.get_text(), '') self.assertFalse(self.plugin.status_duplicates.get_visible()) self.assertFalse(self.plugin.status_deletions.get_visible()) self.assertTrue(self.plugin.sync_start_button.get_visible()) self.assertFalse(self.plugin.sync_stop_button.get_visible()) def test_select_saved_search(self): button = self.plugin.saved_search_vbox.get_children()[0] button.set_active(True) self.assertTrue(button.get_active()) query_config = self._make_query_config(button.get_label()) self.assertTrue( config.getboolean(PM.CONFIG_SECTION, query_config, None)) def test_destination_path_changed(self): self.dest_entry.set_text(self.path_dest) self.assertEqual(self.dest_entry.get_text(), self.path_dest) self.assertEqual( config.get(PM.CONFIG_SECTION, self.plugin.CONFIG_PATH_KEY, None), self.path_dest) def test_export_pattern_changed(self): pattern_new_text = PATTERNS[0] self.pattern_entry.set_text(pattern_new_text) self.assertEqual(self.pattern_entry.get_text(), pattern_new_text) self.assertEqual( config.get(PM.CONFIG_SECTION, self.plugin.CONFIG_PATTERN_KEY, None), pattern_new_text) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_no_searches_selected(self, mock_message): self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with( self.main_vbox, 'No saved searches selected', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_no_destination_path(self, mock_message): self._select_searches('Directory') self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with( self.main_vbox, 'No destination path provided', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_no_export_pattern(self, mock_message): self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.pattern_entry.set_text('') self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with( self.main_vbox, 'No export pattern provided', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_export_path_not_absolute(self, mock_message): self._select_searches('Directory') self.dest_entry.set_text('./path') self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with( self.main_vbox, 'Export path is not absolute', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_no_songs(self, mock_message): self._make_library() self._select_searches('No songs') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with( self.main_vbox, 'No songs in the selected saved searches', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_path_pattern_mismatch(self, mock_message): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.pattern_entry.set_text( str(Path('/dev/null', self.plugin.default_export_pattern))) self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_called_once_with(self.main_vbox, 'Mismatch between destination path and export pattern', ANY) @patch('quodlibet.qltk.ErrorMessage') def test_start_preview_destination_in_pattern(self, mock_message): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.pattern_entry.set_text( str(Path(self.path_dest, self.plugin.default_export_pattern))) self.plugin._start_preview(self.plugin.preview_start_button) mock_message.assert_not_called() self.assertTrue(self.plugin.status_progress.get_visible()) self.assertNotEqual(self.plugin.status_progress.get_text(), '') n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) query_terms = QUERIES[query_name]['terms'] self.plugin.model.foreach(self._verify_child, [self.Tags.PENDING_COPY], [self.path_dest], '~filename', query_terms) def test_start_preview_queries_directory(self): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self.assertTrue(self.plugin.status_progress.get_visible()) self.assertNotEqual(self.plugin.status_progress.get_text(), '') n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) query_terms = QUERIES[query_name]['terms'] self.plugin.model.foreach(self._verify_child, [self.Tags.PENDING_COPY], [self.path_dest], '~filename', query_terms) def test_start_preview_queries_artists(self): self._make_library() query_name = '2 artists' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self.assertTrue(self.plugin.status_progress.get_visible()) self.assertNotEqual(self.plugin.status_progress.get_text(), '') n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) query_terms = QUERIES[query_name]['terms'] self.plugin.model.foreach(self._verify_child, [self.Tags.PENDING_COPY], [self.path_dest], 'artist', query_terms) def test_start_preview_queries_multiple(self): self._make_library() queries = ('Directory', '2 artists') self._select_searches(*queries) self.dest_entry.set_text(self.path_dest) n_expected = 0 for query in queries: n_expected += QUERIES[query]['results'] self.plugin._start_preview(self.plugin.preview_start_button) self.assertTrue(self.plugin.status_progress.get_visible()) self.assertNotEqual(self.plugin.status_progress.get_text(), '') n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, n_expected) self.assertFalse(self.plugin.status_duplicates.get_visible()) self.assertFalse(self.plugin.status_deletions.get_visible()) def test_start_preview_export_path_check(self): def _verify_path(model, path, iter_, *data): song = model[path][self.plugin._model_col_id('entry')]._song expected_path = data[0] for part in data[1:]: field = part.replace('<', '').replace('>', '') expected_path = os.path.join(expected_path, song[field]) expected_path += '.mp3' export_path = model[path][self.plugin._model_col_id('export')] self.assertEqual(export_path, expected_path) return False self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) pattern = Path(self.plugin.export_pattern_entry.get_text()).parts self.plugin._start_preview(self.plugin.preview_start_button) self.plugin.model.foreach(_verify_path, self.path_dest, *pattern) def test_start_preview_pattern_custom_text(self): def _verify_path(model, path, iter_, *data): song = model[path][self.plugin._model_col_id('entry')]._song expected_path = os.path.join(data[0], 'A ' + song['artist'], '_' + song['title'] + '_', 'Unknown' + '.mp3') export_path = model[path][self.plugin._model_col_id('export')] self.assertEqual(export_path, expected_path) return False self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) pattern = str(Path('A <artist>', '_<title>_', '<albumartist|<albumartist>|Unknown>')) self.pattern_entry.set_text(pattern) self.plugin._start_preview(self.plugin.preview_start_button) self.plugin.model.foreach(_verify_path, self.path_dest) def test_start_preview_file_deletion(self): self._make_library() num_files = self._make_files_for_deletion() self._select_searches('Symbols') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self._model_remove_by_tag(self.Tags.PENDING_COPY) n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, num_files) self.assertFalse(self.plugin.status_duplicates.get_visible()) self.assertTrue(self.plugin.status_deletions.get_visible()) def test_start_preview_query_and_file_deletion(self): self._make_library() num_files = self._make_files_for_deletion() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_children = self.plugin.model.iter_n_children(None) n_expected = QUERIES[query_name]['results'] + num_files self.assertEqual(n_children, n_expected) def test_start_preview_unicode_basic_latin(self): # Characters in the range 0x0021 - 0x007E self._make_library() query_name = 'Symbols' self._select_searches(query_name) path_dest = os.path.join(self.path_dest, 'Привет') self.dest_entry.set_text(path_dest) self.pattern_entry.set_text('<title>') self.plugin._start_preview(self.plugin.preview_start_button) n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) export_path = self._model_get_value(0, 'export') expected_value = strip_win32_incompat_from_path(export_path) expected_path = str(Path(path_dest, expected_value)) self.assertEqual(export_path, expected_path) def test_start_preview_unicode_various_languages(self): # Characters in: 0x00A0 - 0x04FF, 0x3040 - 0x309F, 0x0600 - 0x06FF self._make_library() query_name = 'Symbols' self._select_searches(query_name) path_dest = os.path.join(self.path_dest, 'こんにちわ') self.dest_entry.set_text(path_dest) self.pattern_entry.set_text('<artist>') self.plugin._start_preview(self.plugin.preview_start_button) n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) export_path = self._model_get_value(0, 'export') expected_value = strip_win32_incompat_from_path(export_path) expected_path = str(Path(path_dest, expected_value)) self.assertEqual(export_path, expected_path) def test_start_preview_unicode_other_symbols(self): # Characters in the range 0x2030 - 0x1F47E self._make_library() query_name = 'Symbols' self._select_searches(query_name) path_dest = os.path.join(self.path_dest, 'مرحبا') self.dest_entry.set_text(path_dest) self.pattern_entry.set_text('<album>') self.plugin._start_preview(self.plugin.preview_start_button) n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, QUERIES[query_name]['results']) export_path = self._model_get_value(0, 'export') expected_value = strip_win32_incompat_from_path(export_path) expected_path = str(Path(path_dest, expected_value)) self.assertEqual(export_path, expected_path) def test_row_edited_unique_to_unique(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_unique(cell_id_edit, 'initial value') old_c_songs_copy = self.plugin.c_songs_copy self._mark_song_unique(cell_id_edit) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy) def test_row_edited_unique_to_duplicate(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy = 1 self._mark_song_unique(cell_id_edit, 'initial value') old_c_songs_copy = self.plugin.c_songs_copy old_c_song_dupes = self.plugin.c_song_dupes self._mark_song_duplicate(cell_id_edit, cell_id_copy) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy - 1) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes + 1) def test_row_edited_unique_to_delete(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_unique(cell_id_edit, 'initial value') old_c_songs_copy = self.plugin.c_songs_copy old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_delete(cell_id_edit) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy - 1) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_unique_to_empty(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_unique(cell_id_edit, 'initial value') old_c_songs_copy = self.plugin.c_songs_copy old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_empty(cell_id_edit) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy - 1) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_duplicate_to_unique(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy = 1 self._mark_song_duplicate(cell_id_edit, cell_id_copy) self.assertTrue(self.plugin.status_duplicates.get_visible()) old_c_songs_copy = self.plugin.c_songs_copy old_c_song_dupes = self.plugin.c_song_dupes self._mark_song_unique(cell_id_edit) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy + 1) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes - 1) self.assertFalse(self.plugin.status_duplicates.get_visible()) def test_row_edited_duplicate_to_duplicate(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy_1 = 1 cell_id_copy_2 = 2 self._mark_song_duplicate(cell_id_edit, cell_id_copy_1) old_c_song_dupes = self.plugin.c_song_dupes self._mark_song_duplicate(cell_id_edit, cell_id_copy_2) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes) self.assertTrue(self.plugin.status_duplicates.get_visible()) self.assertFalse(self.plugin.status_deletions.get_visible()) def test_row_edited_duplicate_to_delete(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy = 1 self._mark_song_duplicate(cell_id_edit, cell_id_copy) old_c_song_dupes = self.plugin.c_song_dupes old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_delete(cell_id_edit) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes - 1) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_duplicate_to_empty(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy = 1 self._mark_song_duplicate(cell_id_edit, cell_id_copy) old_c_song_dupes = self.plugin.c_song_dupes old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_empty(cell_id_edit) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes - 1) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_delete_to_unique(self): self._make_library() self._make_files_for_deletion() self._select_searches('Symbols') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self._model_remove_by_tag(self.Tags.PENDING_COPY) cell_id_edit = 0 old_c_songs_copy = self.plugin.c_songs_copy old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_unique(cell_id_edit, check=False) self.assertEqual(self.plugin.c_songs_copy, old_c_songs_copy) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_delete_to_duplicate(self): self._make_library() self._make_files_for_deletion() self._select_searches('Symbols') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self._model_remove_by_tag(self.Tags.PENDING_COPY) cell_id_edit = 0 cell_id_copy = 1 old_c_song_dupes = self.plugin.c_song_dupes old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_duplicate(cell_id_edit, cell_id_copy, check=False) self.assertEqual(self.plugin.c_song_dupes, old_c_song_dupes) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_delete_to_delete(self): self._make_library() self._make_files_for_deletion() self._select_searches('Symbols') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self._model_remove_by_tag(self.Tags.PENDING_COPY) cell_id_edit = 0 old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_delete(cell_id_edit) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete - 1) def test_row_edited_delete_to_empty(self): self._make_library() self._make_files_for_deletion() self._select_searches('Symbols') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) self._model_remove_by_tag(self.Tags.PENDING_COPY) cell_id_edit = 0 old_c_songs_delete = self.plugin.c_songs_delete self._mark_song_empty(cell_id_edit, check=False) self.assertEqual(self.plugin.c_songs_delete, old_c_songs_delete) def test_row_edited_empty_to_unique(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_empty(cell_id_edit) self._mark_song_unique(cell_id_edit) def test_row_edited_empty_to_duplicate(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 cell_id_copy = 1 self._mark_song_empty(cell_id_edit) self._mark_song_duplicate(cell_id_edit, cell_id_copy) def test_row_edited_empty_to_delete(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_empty(cell_id_edit) self._mark_song_delete(cell_id_edit) def test_row_edited_empty_to_empty(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_edit = 0 self._mark_song_empty(cell_id_edit) self._mark_song_empty(cell_id_edit) def test_row_edited_others_duplicate_to_unique_single(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_unique = 0 cell_id_duplicate = 1 self._mark_song_duplicate(cell_id_duplicate, cell_id_unique) self._mark_song_unique(cell_id_unique) self.assertEqual(self._model_get_value(cell_id_duplicate, 'tag'), self.Tags.PENDING_COPY) def test_row_edited_others_duplicate_to_unique_multiple(self): self._make_library() self._select_searches('Directory') self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) cell_id_unique = 1 cell_id_duplicate_1 = 0 cell_id_duplicate_2 = 2 self._mark_song_duplicate(cell_id_duplicate_1, cell_id_unique) self._mark_song_duplicate(cell_id_duplicate_2, cell_id_unique) self._mark_song_unique(cell_id_unique) self.assertEqual(self._model_get_value(cell_id_duplicate_1, 'tag'), self.Tags.SKIP_DUPLICATE) self.assertEqual(self._model_get_value(cell_id_duplicate_2, 'tag'), self.Tags.SKIP_DUPLICATE) self._mark_song_unique(cell_id_duplicate_1, new_text='new_text') self.assertEqual(self._model_get_value(cell_id_duplicate_2, 'tag'), self.Tags.PENDING_COPY) @patch('os.remove') @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_basic_success(self, mock_mkdir, mock_cp, mock_rm): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, 0) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_SUCCESS], [self.path_dest], '~filename', QUERIES[query_name]['terms']) @patch('os.remove') @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_duplicates(self, mock_mkdir, mock_cp, mock_rm): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] cell_id_copy = 0 for cell_id in range(cell_id_copy + 1, n_songs): self._mark_song_duplicate(cell_id, cell_id_copy) self.assertTrue(self.plugin.status_duplicates.get_visible()) self.plugin._start_sync(self.plugin.sync_start_button) self.assertFalse(self.plugin.status_duplicates.get_visible()) expected_sync = 1 expected_skip = n_songs - expected_sync self.assertEqual(self.plugin.c_files_copy, expected_sync) self.assertEqual(self.plugin.c_files_dupes, expected_skip) self.assertEqual(mock_mkdir.call_count, expected_sync) self.assertEqual(mock_cp.call_count, expected_sync) self.assertEqual(mock_rm.call_count, 0) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_SUCCESS, self.Tags.SKIP_DUPLICATE], [self.path_dest], '~filename', QUERIES[query_name]['terms']) @patch('os.remove') @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_deletion(self, mock_mkdir, mock_cp, mock_rm): self._make_library() n_files = self._make_files_for_deletion() query_name = 'Symbols' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] self.assertTrue(self.plugin.status_deletions.get_visible()) self.plugin._start_sync(self.plugin.sync_start_button) self.assertFalse(self.plugin.status_deletions.get_visible()) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(self.plugin.c_files_delete, n_files) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, n_files) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_SUCCESS], [''], '~filename', QUERIES[query_name]['terms']) @patch('os.rmdir') @patch('os.remove', side_effect=os.remove) @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_deletion_with_dirs(self, mkdir, cp, rm, rmdir): self._make_library() n_files = self._make_files_for_deletion('song1.mp3', 'song2.mp3', str(Path('other', 'file1.txt')), str(Path('other', 'file2.txt'))) n_dirs = 1 query_name = 'Symbols' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] self.plugin._start_sync(self.plugin.sync_start_button) n_children_updated = self.plugin.model.iter_n_children(None) self.assertEqual(n_children_updated, n_songs + n_files + n_dirs) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(self.plugin.c_files_delete, n_files + n_dirs) self.assertEqual(mkdir.call_count, n_songs) self.assertEqual(cp.call_count, n_songs) self.assertEqual(rm.call_count, n_files) self.assertEqual(rmdir.call_count, n_dirs) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_SUCCESS], [''], '~filename', QUERIES[query_name]['terms']) @patch('os.remove', side_effect=Exception('Mocked failure on remove file')) @patch('shutil.copyfile', side_effect=Exception('Mocked failure on copy')) @patch('os.makedirs') def test_start_sync_failures(self, mock_mkdir, mock_cp, mock_rm): self._make_library() n_files = self._make_files_for_deletion() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] n_total = n_songs + n_files n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, n_total) self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_failed, n_total) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, n_files) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_FAILURE], [self.path_dest, ''], '~filename', QUERIES[query_name]['terms']) @patch('os.rmdir') @patch('os.remove', side_effect=os.remove) @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_complex_success(self, mkdir, cp, rm, rmdir): case_insensitive_filesystem = \ os.path.exists(__file__) == os.path.exists(__file__.upper()) self._make_library() n_files = self._make_files_for_deletion('song1.mp3', 'file1.mp3', str(Path('other', 'file1.txt')), str(Path('other', 'file2.txt'))) n_dirs = 1 queries = ('Directory', '2 artists') self._select_searches(*queries) self.dest_entry.set_text(self.path_dest) self.pattern_entry.set_text('<title>') self.plugin._start_preview(self.plugin.preview_start_button) n_songs = 0 for query in queries: n_songs += QUERIES[query]['results'] n_songs_duplicate = 1 n_songs_existing = 1 if case_insensitive_filesystem else 0 n_total = n_songs + n_files n_children = self.plugin.model.iter_n_children(None) self.assertEqual(n_children, n_total) self.plugin._start_sync(self.plugin.sync_start_button) n_children_updated = self.plugin.model.iter_n_children(None) self.assertEqual(n_children_updated, n_children + n_dirs) n_expected_songs = n_songs - n_songs_duplicate - n_songs_existing self.assertEqual(self.plugin.c_files_copy, n_expected_songs) self.assertEqual(self.plugin.c_files_skip, n_songs_existing) self.assertEqual(self.plugin.c_files_dupes, n_songs_duplicate) self.assertEqual(self.plugin.c_files_delete, n_files + n_dirs) self.assertEqual(mkdir.call_count, n_expected_songs) self.assertEqual(cp.call_count, n_expected_songs) self.assertEqual(rm.call_count, n_files) self.assertEqual(rmdir.call_count, n_dirs) self.plugin.model.foreach(self._verify_child, [self.Tags.RESULT_SUCCESS, self.Tags.SKIP_DUPLICATE, self.Tags.RESULT_SKIP_EXISTING], [self.path_dest, ''], None, None) @patch('os.remove') @patch('shutil.copyfile') @patch('os.makedirs') def test_start_sync_twice(self, mock_mkdir, mock_cp, mock_rm): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) self.plugin._start_preview(self.plugin.preview_start_button) n_songs = QUERIES[query_name]['results'] self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, 0) mock_mkdir.reset_mock() mock_cp.reset_mock() mock_rm.reset_mock() self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_skip_previous, n_songs) self.assertEqual(mock_mkdir.call_count, 0) self.assertEqual(mock_cp.call_count, 0) self.assertEqual(mock_rm.call_count, 0) @patch('os.remove') @patch('shutil.copyfile') @patch('os.makedirs') def test_preview_sync_twice(self, mock_mkdir, mock_cp, mock_rm): self._make_library() query_name = 'Directory' self._select_searches(query_name) self.dest_entry.set_text(self.path_dest) n_songs = QUERIES[query_name]['results'] self.plugin._start_preview(self.plugin.preview_start_button) self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, 0) mock_mkdir.reset_mock() mock_cp.reset_mock() mock_rm.reset_mock() self.plugin._start_preview(self.plugin.preview_start_button) self.plugin._start_sync(self.plugin.sync_start_button) self.assertEqual(self.plugin.c_files_copy, n_songs) self.assertEqual(mock_mkdir.call_count, n_songs) self.assertEqual(mock_cp.call_count, n_songs) self.assertEqual(mock_rm.call_count, 0) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_synchronizedlyrics.py���������������������������������������������0000664�0001750�0001750�00000003270�14037102221�022215� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from pathlib import Path from tempfile import TemporaryDirectory from quodlibet import config from quodlibet.formats import AudioFile from tests.plugin import PluginTestCase class TSynchronizedlyrics(PluginTestCase): AN_LRC = """ [ti:Test Thing] [length:66:66.66] [01:23.45] This is some text [01:01.00]Starting here? [61:00.00]Past the hour mark now! """ def setUp(self): self.mod = self.modules["SynchronizedLyrics"] self.plugin = self.mod.SynchronizedLyrics() def tearDown(self): config.quit() def test_empty_parsing(self): assert self.plugin._parse_lrc("") == [] def test_lrc_parsing(self): assert self.plugin._parse_lrc(self.AN_LRC) == [ (1000 * 61, "Starting here?"), (1000 * (60 + 23.45), "This is some text"), (1000 * 61.0 * 60, "Past the hour mark now!") ] def test_build_data_for_no_song(self): assert self.plugin._build_data(None) == [] def test_build_data_for_munged_name(self): with TemporaryDirectory() as dir_: song = AudioFile({"~filename": f"{dir_}/ARTIST - TITLE.mp3", "artist": "ARTIST", "title": "TITLE"}) path = Path(dir_) / f"{song('artist')} - {song('title')}.lrc" with open(path, "w") as f: f.write(self.AN_LRC) assert len(self.plugin._build_data(song)) == 3 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_test_plugins.py���������������������������������������������������0000664�0001750�0001750�00000001015�14035600052�020766� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests.plugin import PluginTestCase class TTestPlugins(PluginTestCase): def test_pickle(self): plugin = self.plugins["pickle_plugin"].cls instance = plugin() instance.enabled() instance.disabled() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_titlecase.py������������������������������������������������������0000664�0001750�0001750�00000003013�14035600052�020223� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter <reiter.christoph@gmail.com>, # 2012,2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from tests.plugin import PluginTestCase from quodlibet import config class TTitlecase(PluginTestCase): def setUp(self): globals().update(vars(self.modules["Title Case"])) config.init() self.plugin = self.plugins["Title Case"].cls def test_all_caps(self): self.plugin.config_set("allow_all_caps", True) p = self.plugin("", "") self.failUnlessEqual(p.activated("", "foo bar")[0][1], "Foo Bar") self.failUnlessEqual(p.activated("", "FOO BAR")[0][1], "FOO BAR") def test_no_all_caps(self): self.plugin.config_set("allow_all_caps", False) p = self.plugin("", "") self.failUnlessEqual(p.activated("", "foo bar")[0][1], "Foo Bar") self.failUnlessEqual(p.activated("", "FOO BAR")[0][1], "Foo Bar") def test_humanise(self): self.plugin.config_set("human_title_case", True) self.plugin.config_set("allow_all_caps", False) p = self.plugin("", "") self.failUnlessEqual(p.activated("", "foo bar")[0][1], "Foo Bar") self.failUnlessEqual(p.activated("", "FOO the bAR")[0][1], "Foo the Bar") def tearDown(self): config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_trayicon.py�������������������������������������������������������0000664�0001750�0001750�00000007111�14035600052�020101� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013, 2016, 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import sys from gi.repository import Gtk, GdkPixbuf from quodlibet import app from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.qltk import Icons from tests.plugin import PluginTestCase, init_fake_app, destroy_fake_app from tests import skipIf, TestCase @skipIf(sys.platform == "darwin", "segfaults..") class TTrayIcon(PluginTestCase): """ Basic tests for `TrayIcon` Currently just covers the standard code paths without any real testing. """ def setUp(self): config.init() init_fake_app() self.plugin = self.plugins["Tray Icon"].cls() def tearDown(self): destroy_fake_app() config.quit() del self.plugin def test_enable_disable(self): self.plugin.enabled() self.plugin.disabled() def test_popup_menu(self): self.plugin.enabled() try: self.plugin._tray.popup_menu() finally: self.plugin.disabled() def test_get_paused_pixbuf(self): get_paused_pixbuf = \ self.modules["Tray Icon"].systemtray.get_paused_pixbuf self.assertTrue(get_paused_pixbuf((1, 1), 0)) self.assertRaises(ValueError, get_paused_pixbuf, (0, 0), 0) self.assertRaises(ValueError, get_paused_pixbuf, (1, 1), -1) def test_new_with_paused_emblem(self): new_with_paused_emblem = \ self.modules["Tray Icon"].systemtray.new_with_paused_emblem # too small source pixbuf for w, h in [(150, 1), (1, 150), (1, 1)]: pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, w, h) success, new = new_with_paused_emblem(pb) self.assertFalse(success) self.assertTrue(new) # those should work for w, h in [(20, 20), (10, 10), (5, 5), (150, 5), (5, 150)]: pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, w, h) success, new = new_with_paused_emblem(pb) self.assertTrue(success) self.assertTrue(new) @skipIf(sys.platform == "darwin", "segfaults..") class TIndicatorMenu(TestCase): def setUp(self): config.init() init_fake_app() def tearDown(self): destroy_fake_app() config.quit() def test_icons(self): from quodlibet.ext.events.trayicon.menu import IndicatorMenu menu = IndicatorMenu(app) # Slightly lame way to assert here, # but it does the job and is not *too* brittle icons = [item.get_image().get_icon_name()[0] for item in menu.get_children() if isinstance(item, Gtk.ImageMenuItem)] self.failUnless(Icons.EDIT in icons) self.failUnless(Icons.FOLDER_DRAG_ACCEPT in icons) self.failUnless(Icons.MEDIA_PLAYBACK_START in icons) self.failUnless(Icons.MEDIA_SKIP_FORWARD in icons) self.failUnless(Icons.MEDIA_SKIP_BACKWARD in icons) self.failUnless(Icons.APPLICATION_EXIT in icons) self.failUnless(Icons.FAVORITE in icons) def test_playlist_menu_populates(self): from quodlibet.ext.events.trayicon.menu import IndicatorMenu menu = IndicatorMenu(app) song = AudioFile({'~filename': '/dev/null'}) menu._new_playlist_submenu_for(song) self.failUnless(menu._playlists_item.get_submenu()) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_viewlyrics.py�����������������������������������������������������0000664�0001750�0001750�00000003477�14035600052�020464� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet.formats import AudioFile from quodlibet.util.songwrapper import SongWrapper from tests import init_fake_app, destroy_fake_app from tests.plugin import PluginTestCase AUDIO_FILE = AudioFile({'~filename': "/tmp/foobar", 'lyrics': 'Never gonna give you up'}) class TViewlyrics(PluginTestCase): def setUp(self): self.mod = self.modules['View Lyrics'] init_fake_app() self.plugin = self.mod.ViewLyrics() self.plugin.enabled() def tearDown(self): destroy_fake_app() del self.mod def test_no_song_started(self): self.plugin.plugin_on_song_started(None) def test_song_started(self): self.plugin.plugin_on_song_started(SongWrapper(AUDIO_FILE)) def test_on_changed_stopped(self): self.plugin.plugin_on_changed([]) tb = self.plugin.textbuffer actual = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True) # en_US is the default for tests so shouldn't need translation self.failUnlessEqual(actual, "No active song") def test_on_changed(self): app.player.info = AUDIO_FILE self.plugin.plugin_on_changed([SongWrapper(AUDIO_FILE)]) tb = self.plugin.textbuffer actual = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True) self.failUnlessEqual(actual, AUDIO_FILE("lyrics")) def test_startup_playing_then_edit(self): app.player.info = AUDIO_FILE self.plugin.enabled() self.plugin._edit_button.emit('clicked') �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_waveformseekbar.py������������������������������������������������0000664�0001750�0001750�00000003427�14231604332�021445� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter, # 2017-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gst from quodlibet.library.base import Library from tests.plugin import PluginTestCase from tests.helper import visible from quodlibet.player.nullbe import NullPlayer from quodlibet.formats import AudioFile class FakeRMSMessage: type = Gst.MessageType.ELEMENT def __init__(self, rms_values=None): self.rms_values = rms_values or [] def get_structure(self): class FakeStructure: def __init__(self, rms_values): self.rms_values = rms_values def get_name(self): return "level" def get_value(self, name): return self.rms_values return FakeStructure(self.rms_values) class TWaveformSeekBar(PluginTestCase): def setUp(self): self.mod = self.modules["WaveformSeekBar"] def tearDown(self): del self.mod def test_main(self): WaveformScale = self.mod.WaveformScale player = NullPlayer() player.info = AudioFile({"~#length": 10}) scale = WaveformScale(player) scale.compute_redraw_interval() scale.compute_redraw_area() with visible(scale): scale.compute_redraw_interval() scale.compute_redraw_area() def test_no_gstreamer_rms(self): player = NullPlayer() library = Library() bar = self.mod.WaveformSeekBar(player, library) message = FakeRMSMessage() bar._on_bus_message(None, message, 1234) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/plugin/test_website_search.py�������������������������������������������������0000664�0001750�0001750�00000003151�14035600052�021240� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from quodlibet.formats import AudioFile from quodlibet.pattern import Pattern from tests.plugin import PluginTestCase from quodlibet import config A_SONG = AudioFile({'title': 'foo', 'artist': 'barman', '~filename': '/tmp/dir/barman - foo.mp3', 'website': 'https://example.com'}) class TWebsiteSearch(PluginTestCase): def setUp(self): self.mod = self.modules["Website Search"] def test_full(self): plugin = self.mod.WebsiteSearch() plugin.chosen_site = True plugin._no_launch = True assert plugin.plugin_songs([A_SONG]) def test_website_for(self): song = A_SONG pat = Pattern("https://example.com/<artist>/<title>") url = self.mod.website_for(pat, song) assert url == "https://example.com/barman/foo" def test_website_for_dirname(self): song = AudioFile(A_SONG) pat = Pattern("https://example.com/<~dirname>") url = self.mod.website_for(pat, song) # This is probably what the user wanted, ish assert url == "https://example.com//tmp/dir" def test_website_for_website(self): song = AudioFile(A_SONG) pat = Pattern("<website>") url = self.mod.website_for(pat, song) assert url == "https://example.com" def tearDown(self): config.quit() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1692735242.034269 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/quality/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�14471213412�015034� 5����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/quality/__init__.py�����������������������������������������������������������0000664�0001750�0001750�00000000370�14035600052�017143� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/quality/test_flake8.py��������������������������������������������������������0000664�0001750�0001750�00000002614�14231604332�017623� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2020 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from pathlib import Path from typing import Iterable import pytest from pytest import fixture import quodlibet try: from flake8.api import legacy as flake8 except ImportError: flake8 = None from tests.helper import capture_output from quodlibet.util import get_module_dir def should_check(p: Path) -> bool: return (p.is_dir() and not (p.name.startswith(".") or p.name.startswith("_"))) def checked_dirs() -> Iterable[Path]: root_path = Path(get_module_dir(quodlibet)).parent return (p for p in root_path.iterdir() if should_check(p)) @fixture(params=checked_dirs(), ids=lambda p: p.name) def dir_to_check(request) -> Path: return request.param @pytest.mark.quality class TestFlake8: def test_directory(self, dir_to_check: Path): assert flake8 is not None, "flake8 is missing" style_guide = flake8.get_style_guide() with capture_output() as (o, e): style_guide.check_files([str(dir_to_check)]) raw = o.getvalue() errors = raw.splitlines() assert not errors, f"{len(errors)} error(s):\n{raw}" ��������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/quality/test_mypy.py����������������������������������������������������������0000664�0001750�0001750�00000001506�14231604332�017446� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from pathlib import Path import pytest api = pytest.importorskip("mypy.api") import quodlibet from quodlibet.util import get_module_dir @pytest.mark.quality class TestMypy: def test_project(self): root = Path(get_module_dir(quodlibet)) orig_cwd = Path.cwd() try: os.chdir(root.parent) out, err, status = api.run([str(root)]) assert status == 0, "Failed mypy checks: \n" + "\n".join([out, err]) finally: os.chdir(orig_cwd) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/quality/test_source.py��������������������������������������������������������0000664�0001750�0001750�00000011114�14231604507�017750� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014, 2015 Christoph Reiter # 2020-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import re from pathlib import Path from typing import List, Iterable, Pattern import pytest from gi.repository import Gtk from pytest import fixture from quodlibet.util import get_module_dir from tests.test_po import QL_BASE_PATH def iter_py_paths() -> Iterable[Path]: """Iterates over all Python source files that are part of Quod Libet""" import quodlibet root = Path(get_module_dir(quodlibet)).parent skip = [root / d for d in ("build", "dist", "docs", "dev-utils", Path("quodlibet") / "packages") ] # Path.glob() not efficient on big trees :( for dirpath, dirnames, filenames in os.walk(root): root = Path(dirpath) parents = root.parents if root.name.startswith(".") or any(s in parents for s in skip): # Don't test *any* subdirs of hidden / ignored parents dirnames.clear() continue for filename in filenames: if filename.endswith('.py'): yield root / filename def prettify_path(p: Path) -> str: return os.path.splitext(p.relative_to(QL_BASE_PATH))[0] @pytest.fixture(params=list(iter_py_paths()), ids=prettify_path) def py_path(request) -> Path: return request.param @pytest.mark.quality class TestLicense: ALLOWED_RAW = [""" 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 2 of the License, or (at your option) any later version. """, """ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """] ALLOWED = ["".join(license.split()) for license in ALLOWED_RAW] def test_license_is_compliant(self, py_path: Path): header = b"" with open(py_path, "rb") as h: for line in h: line = line.strip() if not line.startswith(b"#"): break header += line.lstrip(b"# ") + b"\n" norm = b"".join(header.split()) norm = norm.decode("utf-8") assert any([l in norm for l in self.ALLOWED]) # Don't mark this as quality - useful to execute _everywhere_ class TestStockIcons: @fixture def res(self) -> Iterable[Pattern]: return [re.compile(r) for r in ("(Gtk\\.STOCK_[_A-Z]*)", "[\"\'](gtk-[\\-a-z]*)")] @fixture def white(self) -> List[str]: # gtk setting keys start like stock icons, so white list them white = [x.replace("_", "-") for x in dir(Gtk.Settings.get_default().props) if x.startswith("gtk_")] # older gtk doesn't have those, but we still have them in the source white += ["gtk-dialogs-use-header", "gtk-primary-button-warps-slider"] # some more.. white += ["gtk-tooltip", "gtk-", "gtk-update-icon-cache-"] return white def test_icons_used(self, py_path: Path, res, white): if py_path.name in ("icons.py", "test_source.py"): return with open(py_path, "rb") as h: data = h.read().decode("utf-8") for r in res: match = r.search(data) if match: group = match.group(1) assert group in white ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684265741.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test___init__.py��������������������������������������������������������������0000644�0001750�0001750�00000003331�14430755415�016525� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests import TestCase import quodlibet from quodlibet import config from quodlibet.const import Version class TQuodlibet(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_first_session(self): self.assertTrue(quodlibet.is_first_session("quodlibet")) self.assertTrue(quodlibet.is_first_session("quodlibet")) quodlibet.finish_first_session("exfalso") self.assertTrue(quodlibet.is_first_session("quodlibet")) quodlibet.finish_first_session("quodlibet") self.assertFalse(quodlibet.is_first_session("quodlibet")) def test_dirs(self): self.assertTrue(isinstance(quodlibet.get_base_dir(), fsnative)) self.assertTrue(isinstance(quodlibet.get_image_dir(), fsnative)) self.assertTrue(isinstance(quodlibet.get_user_dir(), fsnative)) self.assertTrue(isinstance(quodlibet.get_cache_dir(), fsnative)) def test_get_build_description(self): quodlibet.get_build_description() def test_get_build_version(self): ver = quodlibet.get_build_version() self.assertTrue(isinstance(ver, tuple)) class TVersion(TestCase): def test_message(self): v = Version("foo", 1, 2, message="bla") self.assertRaises(ImportError, v.check, (1, 1)) try: v.check((1, 1)) except ImportError as e: self.assertTrue("bla" in str(e)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_appdata_files.py���������������������������������������������������������0000664�0001750�0001750�00000003424�14035600052�017552� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import subprocess from quodlibet import util from tests import TestCase, skipIf QLDATA_DIR = os.path.join(os.path.dirname(util.get_module_dir()), "data") def get_appstream_util_version(): try: result = subprocess.run( ["appstream-util", "--version"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) data = result.stdout except FileNotFoundError: return (0, 0, 0) text = data.decode("utf-8", "replace") return tuple([int(p) for p in text.rsplit()[-1].split(".")]) def is_too_old_appstream_util_version(): return get_appstream_util_version() < (0, 7, 0) class _TAppDataFileMixin: PATH = None def test_filename(self): self.assertTrue(self.PATH.endswith(".appdata.xml.in")) def test_validate(self): try: subprocess.check_output( ["appstream-util", "validate", "--nonet", self.PATH], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise Exception(e.output) @skipIf(is_too_old_appstream_util_version(), "appstream-util is too old") class TQLAppDataFile(TestCase, _TAppDataFileMixin): PATH = os.path.join( QLDATA_DIR, "io.github.quodlibet.QuodLibet.appdata.xml.in") @skipIf(is_too_old_appstream_util_version(), "appstream-util is too old") class TEFAppDataFile(TestCase, _TAppDataFileMixin): PATH = os.path.join( QLDATA_DIR, "io.github.quodlibet.ExFalso.appdata.xml.in") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1664110870.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers___init__.py�����������������������������������������������������0000644�0001750�0001750�00000004721�14314050426�020446� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import sys from tests import TestCase from quodlibet import browsers browsers.init() class TBrowsers(TestCase): def test_presence(self): self.failUnless(browsers.tracks) self.failUnless(browsers.paned) self.failUnless(browsers.iradio) self.failUnless(browsers.podcasts) self.failUnless(browsers.albums) self.failUnless(browsers.playlists) self.failUnless(browsers.filesystem) def test_get(self): self.failUnless(browsers.get("SearchBar") is browsers.tracks.TrackList) self.failUnless( browsers.get("FileSystem") is browsers.filesystem.FileSystem) self.assertEqual(browsers.get("Paned"), browsers.paned.PanedBrowser) self.assertEqual(browsers.get("paned"), browsers.paned.PanedBrowser) self.assertEqual(browsers.get("panedbrowser"), browsers.paned.PanedBrowser) def test_get_podcasts_aka_feeds(self): cls = browsers.podcasts.Podcasts assert browsers.get("Podcasts") == cls assert browsers.get("audiofeeds") == cls, "Legacy name unsupported" def test_default(self): self.assertEqual(browsers.default, browsers.tracks.TrackList) def test_name(self): self.assertEqual(browsers.name(browsers.tracks.TrackList), "SearchBar") def test_get_invalid(self): self.assertRaises(ValueError, browsers.get, "DoesNotExist") def test_index(self): self.assertEqual( browsers.browsers[browsers.index("SearchBar")], browsers.tracks.TrackList) self.assertEqual( browsers.browsers[browsers.index("FileSystem")], browsers.filesystem.FileSystem) def test_index_invalid(self): self.assertRaises(ValueError, browsers.index, "DoesNotExist") def test_migrate(self): self.failUnless( sys.modules["browsers.audiofeeds"] is browsers.podcasts) self.failUnless( sys.modules["browsers.iradio"] is browsers.iradio) def test_old_names(self): self.assertEqual(browsers.get("PanedBrowser"), browsers.get("Paned")) self.assertEqual(browsers.get("PlaylistsBrowser"), browsers.get("Playlists")) �����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661071236.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers__base.py��������������������������������������������������������0000644�0001750�0001750�00000017471�14300367604�017772� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2013 Christoph Reiter # 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk from quodlibet.browsers._base import FakeDisplayItem as FDI, \ DisplayPatternMixin, FakeDisplayItem from quodlibet.util.cover import CoverManager from tests import TestCase, init_fake_app, destroy_fake_app, mkstemp, run_gtk_loop from .helper import realized, dummy_path from quodlibet import browsers, app from quodlibet.formats import AudioFile from quodlibet import config from quodlibet.browsers import Browser from quodlibet.library import SongFileLibrary, SongLibrarian SONGS = [ AudioFile({ "title": "one", "artist": "piman", "~filename": dummy_path(u"/dev/null"), }), AudioFile({ "title": "two", "artist": "mu", "~filename": dummy_path(u"/dev/zero"), }), AudioFile({ "title": "three", "artist": "boris", "~filename": dummy_path(u"/bin/ls"), }) ] SONGS.sort() for song in SONGS: song.sanitize() class TBrowser(TestCase): def setUp(self): self.browser = Browser() def test_can_filter(self): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: self.failIf(self.browser.can_filter(key)) def test_defaults(self): self.failUnless(self.browser.background) self.failIf(self.browser.can_reorder) self.failIf(self.browser.headers) def test_status_bar(self): self.assertEqual(self.browser.status_text(1, "21s"), "1 song (21s)") self.assertEqual(self.browser.status_text(101, "2:03"), "101 songs (2:03)") def tearDown(self): self.browser = None class TBrowserBase(TestCase): Kind = None def setUp(self): config.init() init_fake_app() app.cover_manager = CoverManager() self.library = library = SongFileLibrary() library.librarian = SongLibrarian() library.add(SONGS) self.Kind.init(library) self.b = self.Kind(library) def tearDown(self): self.b.destroy() self.library.librarian = None self.library.destroy() config.quit() destroy_fake_app() class TBrowserMixin: def test_menu(self): # FIXME: the playlist browser accesses the song list directly if self.b.name == "Playlists": return menu = self.b.Menu([], self.library, []) self.assertTrue(isinstance(menu, Gtk.Menu)) def test_key(self): self.assertEqual(browsers.get(browsers.name(self.Kind)), self.Kind) def test_pack_unpack(self): to_pack = Gtk.Button() container = self.b.pack(to_pack) self.b.unpack(container, to_pack) def test_pack_noshow_songpane(self): to_pack = Gtk.Button() to_pack.hide() container = self.b.pack(to_pack) self.assertFalse(to_pack.get_visible()) self.b.unpack(container, to_pack) self.assertFalse(to_pack.get_visible()) def test_name(self): self.failIf("_" in self.b.name) self.failUnless("_" in self.b.accelerated_name) def test_init(self): self.Kind.init(self.library) def test_active_filter(self): with realized(self.b): if self.b.active_filter is not None: self.b.active_filter(SONGS[0]) def test_save_restore(self): self.b.restore() self.b.finalize(True) try: self.b.save() except NotImplementedError: pass def test_msic(self): with realized(self.b): self.b.activate() self.b.status_text(1000) self.b.status_text(1) song = AudioFile({"~filename": dummy_path(u"/fake")}) song.sanitize() self.b.scroll(song) def test_filters_caps(self): with realized(self.b): self.failUnless(isinstance(self.b.can_filter_tag("foo"), bool)) self.failUnless(isinstance(self.b.can_filter_text(), bool)) self.failUnless(isinstance(self.b.can_filter("foo"), bool)) def test_filter_text(self): with realized(self.b): if self.b.can_filter_tag("foo"): self.b.filter("foo", ["bar"]) if self.b.can_filter_tag("(((((##!!!!))),"): self.b.filter("(((((##!!!!))),", ["(((((##!!!!))),"]) if self.b.can_filter_text(): self.b.filter_text("foo") self.b.filter_text("(((((##!!!!))),,,==") def test_get_filter_text(self): with realized(self.b): if self.b.can_filter_text(): self.assertEqual(self.b.get_filter_text(), u"") self.assertTrue( isinstance(self.b.get_filter_text(), str)) self.b.filter_text(u"foo") self.assertEqual(self.b.get_filter_text(), u"foo") self.assertTrue( isinstance(self.b.get_filter_text(), str)) def test_filter_albums(self): with realized(self.b): if self.b.can_filter_albums(): self.b.filter_albums([]) self.b.filter_albums([object]) self.b.filter_albums(self.library.albums.values()) def test_filter_other(self): with realized(self.b): self.b.unfilter() def test_cover_art_changed(self): # See #4110 app.cover_manager.emit("cover-changed", SONGS[2:3]) run_gtk_loop() # No (generic) assertions, but ensure coverage class TFakeDisplayItem(TestCase): def test_call(self): self.assertEqual(FDI()("title"), "Title") self.assertEqual(FDI()("~title~artist"), "Title - Artist") self.assertEqual(FDI(title="foo")("title"), "foo") self.assertEqual(FDI(title="f")("~title~artist"), "f - Artist") self.assertEqual(FDI()("~#rating"), "Rating") self.assertEqual(FDI({"~#rating": 0.5})("~#rating"), 0.5) self.assertEqual(FDI()("~#rating:max"), "Rating<max>") def test_get(self): self.assertEqual(FDI().get("title"), "Title") def test_comma(self): self.assertEqual(FDI().comma("title"), "Title") self.assertEqual(FDI({"~#rating": 0.5}).comma("~#rating"), 0.5) self.assertEqual(FDI(title="a\nb").comma("title"), "a, b") class DummyDPM(DisplayPatternMixin): fd, _PATTERN_FN = mkstemp() os.close(fd) class TDisplayPatternMixin(TestCase): TEST_PATTERN = u"<~name>: <artist|<artist>|?> [b]<~length>[/b]" def setUp(self): with open(DummyDPM._PATTERN_FN, "wb") as f: f.write(self.TEST_PATTERN.encode("utf-8") + b"\n") @classmethod def tearDownClass(cls): os.unlink(DummyDPM._PATTERN_FN) def test_loading_pattern(self): dpm = DummyDPM() dpm.load_pattern() self.failUnlessEqual(dpm.display_pattern_text, self.TEST_PATTERN) def test_updating_pattern(self): dpm = DummyDPM() dpm.load_pattern() dpm.update_pattern("static") self.failUnlessEqual( dpm.display_pattern % FakeDisplayItem(), "static") def test_markup(self): dpm = DummyDPM() dpm.load_pattern() item = FakeDisplayItem({"~length": "2:34"}) self.failUnlessEqual(dpm.display_pattern % item, "Name: Artist <b>2:34</b>") browsers.init() # create a new test class for each browser for browser in browsers.browsers: cls = TBrowserBase name = "TB" + browser.__name__ new_test = type(name, (TBrowserBase, TBrowserMixin), {}) new_test.Kind = browser globals()[name] = new_test �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1659562070.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_albums.py�������������������������������������������������������0000644�0001750�0001750�00000017442�14272564126�020210� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2014 Christoph Reiter # 2016-22 Nick Boultbee # 2019 Ruud van Asseldonk # # 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 2 of the License, or # (at your option) any later version. from functools import cmp_to_key from gi.repository import Gtk from senf import fsnative from quodlibet.browsers._base import DisplayPatternMixin from . import TestCase, run_gtk_loop from .helper import realized from quodlibet import config from quodlibet.browsers.albums import AlbumList from quodlibet.browsers.albums.models import AlbumItem from quodlibet.browsers.albums.prefs import Preferences, DEFAULT_PATTERN_TEXT from quodlibet.browsers.albums.main import (compare_title, compare_people, compare_genre, compare_rating, compare_date, compare_original_date) from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary, SongLibrarian from quodlibet.util.collection import Album SONGS = [ AudioFile({ "album": "one", "artist": "piman", "~filename": fsnative(u"/dev/null"), }), AudioFile({ "album": "two", "artist": "mu", "~filename": fsnative(u"/dev/zero"), }), AudioFile({ "album": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls"), }), AudioFile({ "album": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls2"), }), ] SONGS.sort() class TAlbumPrefs(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_main(self): class Browser(Gtk.Box, DisplayPatternMixin): _DEFAULT_PATTERN_TEXT = "" widget = Preferences(Browser()) widget.destroy() class TAlbumSort(TestCase): def _get_album(self, dict_): song = AudioFile(dict_) album = Album(song) album.songs.add(song) return AlbumItem(album) def assertOrder(self, func, list_): key = cmp_to_key(func) # sort twice for full line coverage of the compare function reversed_ = list(sorted(list_, key=key, reverse=True)) sorted_ = list(sorted(list_, key=key)) self.assertEqual(reversed_[::-1], sorted_) self.assertEqual(list_, sorted_) def test_sort_title(self): a = self._get_album({"album": "a"}) b = self._get_album({"album": "b"}) n = self._get_album({"album": ""}) self.assertOrder(compare_title, [AlbumItem(None), a, b, n]) def test_sort_artist(self): a = self._get_album({"album": "b", "artist": "x"}) b = self._get_album({"album": "a", "artist": "y"}) c = self._get_album({"album": "a", "artist": ""}) n = self._get_album({"album": ""}) self.assertOrder(compare_people, [AlbumItem(None), a, b, c, n]) def test_sort_genre(self): a = self._get_album({"album": "b", "genre": "x"}) b = self._get_album({"album": "a", "genre": "y"}) c = self._get_album({"album": "a", "genre": ""}) n = self._get_album({"album": ""}) self.assertOrder(compare_genre, [AlbumItem(None), a, b, c, n]) def test_sort_date(self): a = self._get_album({"album": "b", "date": "1970"}) b = self._get_album({"album": "a", "date": "2038"}) c = self._get_album({"album": "a", "date": ""}) n = self._get_album({"album": ""}) self.assertOrder(compare_date, [AlbumItem(None), a, b, c, n]) def test_sort_original_date(self): a = self._get_album({"album": "b", "date": "1970"}) b = self._get_album({"album": "a", "date": "2038", "originaldate": "1967"}) c = self._get_album({"album": "a", "date": ""}) d = self._get_album({"album": "b", "originaldate": "1971"}) n = self._get_album({"album": ""}) self.assertOrder(compare_original_date, [AlbumItem(None), b, a, d, c, n]) def test_sort_rating(self): a = self._get_album({"album": "b", "~#rating": 0.5}) b = self._get_album({"album": "a", "~#rating": 0.25}) c = self._get_album({"album": "x", "~#rating": 0.0}) n = self._get_album({"album": "", "~#rating": 0.25}) self.assertOrder(compare_rating, [AlbumItem(None), a, b, c, n]) class TAlbumBrowser(TestCase): def setUp(self): config.init() library = SongLibrary() library.librarian = SongLibrarian() AlbumList.init(library) for af in SONGS: af.sanitize() library.add(SONGS) self.bar = AlbumList(library) self._id = self.bar.connect("songs-selected", self._selected) self._id2 = self.bar.connect("songs-activated", self._activated) with realized(self.bar): self.bar.filter_text("") self._wait() self.songs = [] self.activated = False def _activated(self, albumlist): self.activated = True def _selected(self, albumlist, songs, *args): self.songs = songs def _wait(self): run_gtk_loop() def test_activated(self): with realized(self.bar): view = self.bar.view view.row_activated(Gtk.TreePath((0,)), view.get_column(0)) self.failUnless(self.activated) def test_can_filter(self): with realized(self.bar): self.failUnless(self.bar.can_filter(None)) self.failUnless(self.bar.can_filter("album")) self.failUnless(self.bar.can_filter("foobar")) self.failIf(self.bar.can_filter("~#length")) self.failIf(self.bar.can_filter("title")) def test_set_text(self): with realized(self.bar): self.bar.filter_text("artist=piman") self._wait() self.failUnlessEqual(len(self.songs), 1) self.bar.filter_text("") self._wait() self.failUnlessEqual(set(self.songs), set(SONGS)) def test_filter_album(self): with realized(self.bar): self.bar.filter_text("dsagfsag") self._wait() self.failUnlessEqual(len(self.songs), 0) self.bar.filter_text("") self._wait() self.bar.filter("album", ["one", "three"]) self._wait() self.failUnlessEqual(len(self.songs), 3) def test_filter_artist(self): with realized(self.bar): self.bar.filter("artist", ["piman"]) self._wait() self.failUnlessEqual(len(self.songs), 1) self.failUnlessEqual(self.songs[0]("artist"), "piman") def test_header(self): self.failIf(self.bar.headers) def test_list(self): albums = self.bar.list_albums() self.failUnlessEqual(set(albums), {s.album_key for s in SONGS}) self.bar.filter_albums([SONGS[0].album_key]) self._wait() self.failUnlessEqual({s.album_key for s in self.songs}, {SONGS[0].album_key}) def test_active_filter(self): with realized(self.bar): self.bar.filter("artist", ["piman"]) self._wait() self.failUnless(self.bar.active_filter(self.songs[0])) for s in SONGS: if s is not self.songs[0]: self.failIf(self.bar.active_filter(s)) def test_default_display_pattern(self): pattern_text = self.bar.display_pattern_text self.failUnlessEqual(pattern_text, DEFAULT_PATTERN_TEXT) self.failUnless("<album>" in pattern_text) def tearDown(self): self.bar.disconnect(self._id) self.bar.disconnect(self._id2) self.bar.destroy() del self.bar config.quit() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_collection.py���������������������������������������������������0000664�0001750�0001750�00000007156�14035600052�021045� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet import config from quodlibet.browsers.collection import CollectionBrowser from quodlibet.browsers.collection.models import UnknownNode, \ CollectionTreeStore, build_tree, MultiNode from quodlibet.browsers.collection.prefs import save_headers, get_headers, \ PatternEditor from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary SONGS = [ AudioFile({"album": "one", "artist": "piman", "~filename": "/dev/null"}), AudioFile({"album": "two", "artist": "mu\nboris", "~filename": "/dev/zero"}), AudioFile({"album": "three", "artist": "boris", "~filename": "/bin/ls"}), AudioFile({"album": "three", "artist": "boris", "~filename": "/bin/ls2"}), AudioFile({"album": "four", "~filename": "/bin/ls3"}), ] SONGS.sort() class TCollectionPreferences(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_headers(self): value = [("foobar", 0), ("~people", 1)] save_headers(value) self.failUnlessEqual(get_headers(), value) def test_pref_dialog(self): d = PatternEditor() d.destroy() class TCollectionAlbums(TestCase): def setUp(self): l = SongLibrary() l.add(SONGS) l.albums.load() self.albums = l.albums def tearDown(self): del self.albums def test_build_tree(self): tags = [("~people", 0)] tree = build_tree(tags, self.albums) self.failUnless("mu" in tree) self.failUnless("boris" in tree) self.failUnless("piman" in tree) self.failUnless(UnknownNode in tree) self.failUnlessEqual(len(tree), 4) def test_build_tree_merge(self): tags = [("~people", 1)] tree = build_tree(tags, self.albums) self.failUnless(MultiNode in tree) self.failUnless(UnknownNode in tree) self.failUnless("boris" in tree) self.failUnless("piman" in tree) self.failUnlessEqual(len(tree), 4) def test_model(self): model = CollectionTreeStore() model.set_albums([("~people", 0)], self.albums) self.failUnlessEqual(len(model), 4) model.change_albums(self.albums) self.failUnlessEqual(len(model), 4) model.remove_albums(self.albums) self.failUnlessEqual(len(model), 0) def test_utils(self): model = CollectionTreeStore() model.set_albums([("~people", 0)], self.albums) a = list(self.albums.values()) a.sort(key=lambda x: x.key) path = model.get_path_for_album(a[0]) albums = model.get_albums_for_path(path) self.failUnless(a[0] in albums) albums = model.get_albums_for_iter(model.get_iter(path)) self.failUnless(a[0] in albums) x = model.get_album(model.get_iter_first()) self.failIf(x) x = model.get_album(model.get_iter(path)) self.failUnlessEqual(x, a[0]) for r in model: self.failUnless(model.get_markup(model.tags, r.iter)) x = list(model.iter_albums(None)) self.assertEqual(set(x), set(a)) class TCollectionBrowser(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_init(self): library = SongLibrary() x = CollectionBrowser(library) x.destroy() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660895633.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_covergrid.py����������������������������������������������������0000644�0001750�0001750�00000011113�14277640621�020676� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2014 Christoph Reiter # 2016 Nick Boultbee # 2019 Ruud van Asseldonk # # 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 2 of the License, or # (at your option) any later version. from quodlibet.browsers.covergrid.main import CoverGrid from senf import fsnative from . import TestCase, run_gtk_loop from .helper import realized from quodlibet import config from quodlibet.browsers.albums.prefs import DEFAULT_PATTERN_TEXT from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary, SongLibrarian SONGS = [ AudioFile({ "album": "one", "artist": "piman", "~filename": fsnative(u"/dev/null"), }), AudioFile({ "album": "two", "artist": "mu", "~filename": fsnative(u"/dev/zero"), }), AudioFile({ "album": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls"), }), AudioFile({ "album": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls2"), }), ] SONGS.sort() class TCoverGridBrowser(TestCase): def setUp(self): config.init() library = SongLibrary() library.librarian = SongLibrarian() CoverGrid.init(library) for af in SONGS: af.sanitize() library.add(SONGS) self.bar = CoverGrid(library) self._id = self.bar.connect("songs-selected", self._selected) self._id2 = self.bar.connect("songs-activated", self._activated) with realized(self.bar): self.bar.filter_text("") self._wait() self.songs = [] self.activated = False def tearDown(self): self.bar.disconnect(self._id) self.bar.disconnect(self._id2) self.bar.destroy() del self.bar config.quit() def _activated(self, albumlist): self.activated = True def _selected(self, albumlist, songs, *args): self.songs = songs def _wait(self): run_gtk_loop() def test_activated(self): with realized(self.bar): view = self.bar.view child = view.get_child_at_index(0) child.emit('activate') self._wait() self.failUnless(self.activated) def test_can_filter(self): with realized(self.bar): self.failUnless(self.bar.can_filter(None)) self.failUnless(self.bar.can_filter("album")) self.failUnless(self.bar.can_filter("foobar")) self.failIf(self.bar.can_filter("~#length")) self.failIf(self.bar.can_filter("title")) def test_set_text(self): with realized(self.bar): self.bar.filter_text("artist=piman") self._wait() self.failUnlessEqual(len(self.songs), 1) self.bar.filter_text("") self._wait() self.failUnlessEqual(set(self.songs), set(SONGS)) def test_filter_album(self): with realized(self.bar): self.bar.filter_text("dsagfsag") self._wait() self.failUnlessEqual(len(self.songs), 0) self.bar.filter_text("") self._wait() self.bar.filter("album", ["one", "three"]) self._wait() self.failUnlessEqual(len(self.songs), 3) def test_filter_artist(self): with realized(self.bar): self.bar.filter("artist", ["piman"]) self._wait() self.failUnlessEqual(len(self.songs), 1) self.failUnlessEqual(self.songs[0]("artist"), "piman") def test_header(self): self.failIf(self.bar.headers) def test_list(self): albums = self.bar.list_albums() self.failUnlessEqual(set(albums), {s.album_key for s in SONGS}) self.bar.filter_albums([SONGS[0].album_key]) self._wait() self.failUnlessEqual({s.album_key for s in self.songs}, {SONGS[0].album_key}) def test_active_filter(self): with realized(self.bar): self.bar.filter("artist", ["piman"]) self._wait() self.failUnless(self.bar.active_filter(self.songs[0])) for s in SONGS: if s is not self.songs[0]: self.failIf(self.bar.active_filter(s)) def test_default_display_pattern(self): pattern_text = self.bar.display_pattern_text self.failUnlessEqual(pattern_text, DEFAULT_PATTERN_TEXT) self.failUnless("<album>" in pattern_text) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656314886.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_filesystem.py���������������������������������������������������0000664�0001750�0001750�00000001462�14256256006�021103� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from typing import Generator import pytest import quodlibet.config from quodlibet.browsers.filesystem import FileSystem from quodlibet.library import SongLibrary @pytest.fixture def bar() -> Generator[FileSystem, None, None]: quodlibet.config.init() bar = FileSystem(SongLibrary()) yield bar bar.destroy() quodlibet.config.quit() class TestFileSystem: def test_can_filter(self, bar): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: assert not bar.can_filter(key) assert bar.can_filter("~dirname") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1661801479.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_iradio.py�������������������������������������������������������0000644�0001750�0001750�00000014224�14303212007�020146� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import io from bz2 import BZ2Compressor from http.server import HTTPServer, BaseHTTPRequestHandler from threading import Thread from typing import Generator import pytest import quodlibet.config from quodlibet.browsers.iradio import (InternetRadio, IRFile, QuestionBar, parse_taglist, parse_pls, parse_m3u, download_taglist) from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary from quodlibet.util import is_windows, is_osx from tests import TestCase, skipIf, run_gtk_loop quodlibet.config.RATINGS = quodlibet.config.HardCodedRatingsPrefs() FAKE_URLS = ["http://example.com", "https://quodlibet.readthedocs.io"] def test_parse_taglist(): parse_taglist(b"") stations = parse_taglist(b"""\ uri=http://foo.bar artist=foo artist=bar ~listenerpeak=42 """) assert len(stations) == 1 assert stations[0]["~#listenerpeak"] == 42 assert stations[0].list("artist") == ["foo", "bar"] class FakeTask: def __init__(self): self.pulsed = 0 def pulse(self): self.pulsed += 1 def test_parse_pls(): f = io.BytesIO(b"""\ [playlist] Title1=Here enter name of the station File1=http://stream2.streamq.net:8020/ NumberOfEntries=1 """) r = parse_pls(f) assert len(r) == 1 assert r[0]("~uri") == "http://stream2.streamq.net:8020/" assert r[0]("title") == "Here enter name of the station" def test_parse_m3u(): f = io.BytesIO(b"""\ #EXTM3U #EXTINF:123, Sample artist - Sample title http://stream2.streamq.net:8020/ """) r = parse_m3u(f) assert len(r) == 1 assert r[0]("~uri") == "http://stream2.streamq.net:8020/" class TQuestionBar(TestCase): def test_main(self): b = QuestionBar() self.assertFalse(b.get_visible()) class TInternetRadio(TestCase): def setUp(self): quodlibet.config.init() self.bar = InternetRadio(SongLibrary()) def test_can_filter(self): self.assertTrue(self.bar.can_filter("foo")) self.assertTrue(self.bar.can_filter_text()) def test_status_bar_text(self): self.assertEqual(self.bar.status_text(1), "1 station") self.assertEqual(self.bar.status_text(101, 123), "101 stations") @skipIf(is_windows() or is_osx(), "Don't need to test downloads all the time") def test_click_add_station(self): self.bar._update_button.emit('clicked') assert not self.bar.has_stations # Run the actual download from real URL run_gtk_loop() assert self.bar.has_stations def tearDown(self): self.bar.destroy() quodlibet.config.quit() class TIRFile(TestCase): def setUp(self): self.s = IRFile("http://foo.bar") def test_website(self): self.s["website"] = "abc" self.assertEqual(self.s.get("artist"), "abc") self.assertEqual(self.s("artist"), "abc") self.assertEqual(self.s.list("artist"), ["abc"]) def test_organisation(self): self.s["organization"] = "foo" self.assertEqual(self.s("title"), "foo") self.assertEqual(self.s.get("title"), "foo") def test_title_split_stream(self): self.assertFalse(self.s("artist")) self.s["title"] = "artist - title" self.s.multisong = False self.assertEqual(self.s("title"), "title") self.assertEqual(self.s.get("title"), "title") self.assertEqual(self.s("artist"), "artist") self.assertEqual(self.s.get("artist"), "artist") def test_title_split(self): self.assertTrue(self.s.multisong) self.s["title"] = "artist - title" self.assertEqual(self.s("title"), self.s["title"]) def test_format(self): self.assertEqual(self.s("~format"), self.s.format) self.s["audio-codec"] = "SomeCodec" self.assertTrue("SomeCodec" in self.s("~format")) self.assertTrue(self.s.format in self.s("~format")) def test_people(self): self.s["title"] = "artist - title" self.s.multisong = False self.assertEqual(self.s("~people"), "artist") self.assertEqual(self.s("~~people~foo"), "artist") def testcan_write(self): self.failUnless(self.s.can_change("title")) self.s.streamsong = True self.failIf(self.s.can_change("title")) def test_dump_to_file(self): self.s["title"] = "artist - title" self.s.multisong = False dump = self.s.to_dump() new = AudioFile() new.from_dump(dump) self.assertEqual(new["title"], "title") self.assertEqual(new["artist"], "artist") del self.s["title"] dump = self.s.to_dump() new = AudioFile() new.from_dump(dump) self.assertTrue("title" not in new) self.assertTrue("artist" not in new) class Bzip2GetHandler(BaseHTTPRequestHandler): # Not thread-safe, but won't be an issue here compressor = BZ2Compressor() def do_GET(self) -> None: uris = [f"uri={url}" for url in FAKE_URLS] content = "\n".join(uris).encode("utf-8") self.compressor.compress(content) bz2 = self.compressor.flush() self.send_response(200) self.send_header("Content-Length", str(len(bz2))) self.send_header("Content-type", "application/x-bzip2") self.end_headers() self.wfile.write(bz2) @pytest.fixture def test_server() -> Generator[HTTPServer, None, None]: server = HTTPServer(("localhost", 0), Bzip2GetHandler) Thread(target=server.serve_forever, daemon=True).start() yield server server.shutdown() def test_download_tags(test_server): received = [] host, port = test_server.server_address url = f"http://{host}:{port:d}" ret = list(download_taglist(url, received.extend, None)) run_gtk_loop() assert len(ret), "No stations" assert all(ret), "Got some falsey stations" assert received, f"No stations received from {url}" assert {s("~filename") for s in received} == set(FAKE_URLS) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_paned.py��������������������������������������������������������0000664�0001750�0001750�00000042325�14231604332�020001� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, run_gtk_loop from .helper import realized from gi.repository import Gtk from senf import fsnative from quodlibet import config from quodlibet.browsers.paned import PanedBrowser from quodlibet.browsers.paned.util import PaneConfig from quodlibet.browsers.paned.util import get_headers from quodlibet.browsers.paned.models import AllEntry, UnknownEntry, SongsEntry from quodlibet.browsers.paned.models import PaneModel from quodlibet.browsers.paned.prefs import PatternEditor, Preferences from quodlibet.browsers.paned.prefs import PreferencesButton, ColumnMode from quodlibet.browsers.paned.pane import Pane from quodlibet.formats import AudioFile from quodlibet.util.collection import Collection from quodlibet.util.string.date import format_date from quodlibet.library import SongLibrary, SongLibrarian SONGS = [ AudioFile({ "title": "three", "artist": "boris", "genre": "Rock", "~filename": fsnative(u"/bin/ls"), "foo": "bar"}), AudioFile({ "title": "two", "artist": "mu", "genre": "Rock", "~filename": fsnative(u"/dev/zero"), "foo": "bar"}), AudioFile({ "title": "four", "artist": "piman", "genre": "J-Pop", "~filename": fsnative(u"/dev/null"), "foo": "bar\nquux"}), AudioFile({ "title": "one", "artist": "piman", "genre": "J-Pop", "~filename": fsnative(u"/bin/foo"), "foo": "bar\nnope"}), AudioFile({ "title": "xxx", "~filename": fsnative(u"/bin/bar"), "foo": "bar"}), ] UNKNOWN_ARTIST = AudioFile(dict(SONGS[0])) del UNKNOWN_ARTIST["artist"] ALBUM = Collection() ALBUM.songs = SONGS class TPanedBrowser(TestCase): Bar = PanedBrowser def setUp(self): config.init() config.set("browsers", "panes", "artist") library = SongLibrary() library.librarian = SongLibrarian() PanedBrowser.init(library) for af in SONGS: af.sanitize() library.add(SONGS) self.bar = self.Bar(library) self.last = None self.emit_count = 0 def selected_cb(browser, songs, *args): self.last = list(songs) self.emit_count += 1 self.bar.connect("songs-selected", selected_cb) def test_get_set_headers(self): config.set("browsers", "panes", "~people album") self.assertEqual(get_headers(), ["~people", "album"]) def test_pack(self): to_pack = Gtk.Button() container = self.bar.pack(to_pack) self.bar.unpack(container, to_pack) def test_can_filter(self): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: self.failIf(self.bar.can_filter_tag(key)) self.failUnless(self.bar.can_filter("artist")) self.failUnless(self.bar.can_filter_text()) def test_filter_text(self): self.bar.activate() self.bar.filter_text("artist=nope") run_gtk_loop() self.failUnlessEqual(set(self.last), set()) self.bar.filter_text("artist=!boris") run_gtk_loop() self.failUnlessEqual(set(self.last), set(SONGS[1:])) def test_filter_value(self): self.bar.activate() expected = [SONGS[0]] self.bar.filter("artist", ["boris"]) run_gtk_loop() self.failUnlessEqual(self.last, expected) def test_filter_notvalue(self): self.bar.activate() expected = SONGS[1:4] self.bar.filter("artist", ["notvalue", "mu", "piman"]) run_gtk_loop() self.failUnlessEqual(set(self.last), set(expected)) def test_restore(self): config.set("browsers", "query_text", "foo") self.bar.restore() self.failUnlessEqual(self.bar._get_text(), "foo") self.bar.finalize(True) run_gtk_loop() self.failUnlessEqual(self.emit_count, 0) def test_numeric_config_search(self): config.set("browsers", "panes", "~#track") self.bar.refresh_panes() self.bar.filter_text("foobar") def test_restore_entry_text(self): self.bar.filter_text("foobar") self.bar.save() self.bar._set_text("nope") self.bar.restore() self.failUnlessEqual(self.bar._get_text(), "foobar") run_gtk_loop() self.failUnlessEqual(self.emit_count, 1) def test_restore_selection(self): self.bar.activate() self.bar.filter("artist", [u"piman"]) self.bar.save() self.bar.unfilter() self.bar.restore() self.bar.activate() run_gtk_loop() for song in self.last: self.assertTrue(u"piman" in song.list("artist")) def test_set_all_panes(self): self.bar.activate() self.bar.set_all_panes() def test_restore_pane_width(self): config.set("browsers", "panes", "artist\talbum") self.bar.set_all_panes() paned = self.bar.multi_paned.get_paned() paned.set_relative(0.8) self.bar.set_all_panes() self.failUnlessAlmostEqual(paned.get_relative(), 0.8) def test_make_pane_widths_equal(self): config.set("browsers", "panes", "artist\talbum\t~year\t~#track") self.bar.set_all_panes() self.bar.make_pane_widths_equal() paneds = self.bar.multi_paned._get_paneds() self.failUnlessAlmostEqual(paneds[0].get_relative(), 1.0 / 4.0) self.failUnlessAlmostEqual(paneds[1].get_relative(), 1.0 / 3.0) self.failUnlessAlmostEqual(paneds[2].get_relative(), 1.0 / 2.0) def test_column_mode(self): self.bar.set_all_column_mode(ColumnMode.SMALL) self.bar.set_all_column_mode(ColumnMode.WIDE) self.bar.set_all_column_mode(ColumnMode.COLUMNAR) def tearDown(self): self.bar.destroy() config.quit() class TPaneConfig(TestCase): def test_tag(self): p = PaneConfig("title") self.failUnlessEqual(p.title, "Title") self.failUnlessEqual(p.tags, {"title"}) self.failUnlessEqual(p.format(SONGS[0]), [("three", "three")]) self.failUnless(str(len(ALBUM.songs)) in p.format_display(ALBUM)) self.failIf(p.has_markup) def test_numeric(self): a_date_format = "%Y-%m-%d" config.set("settings", "datecolumn_timestamp_format", a_date_format) p = PaneConfig("~#lastplayed") self.failUnlessEqual(p.title, "Last Played") self.failUnlessEqual(p.tags, {"~#lastplayed"}) zero_date = format_date(0, a_date_format) self.failUnlessEqual(p.format(SONGS[0]), [(zero_date, zero_date)]) self.failIf(p.has_markup) def test_tied(self): p = PaneConfig("~title~artist") self.failUnlessEqual(p.title, "Title / Artist") self.failUnlessEqual(p.tags, {"title", "artist"}) self.failUnlessEqual(p.format(SONGS[0]), [("three", "three"), ("boris", "boris")]) self.failIf(p.has_markup) def test_pattern(self): p = PaneConfig("<foo>") self.failUnlessEqual(p.title, "Foo") self.failUnlessEqual(p.tags, {"foo"}) self.failUnless(p.has_markup) def test_condition(self): p = PaneConfig("<foo|a <bar>|quux>") self.failUnlessEqual(p.title, "a Bar") self.failUnlessEqual(p.tags, {"bar"}) self.failUnless(p.has_markup) def test_group(self): p = PaneConfig(r"a\:b:<title>") self.failUnlessEqual(p.title, "A:B") self.failUnlessEqual(set(p.format_display(ALBUM).split(", ")), {"one", "two", "three", "four", "xxx"}) p = PaneConfig("foo:~#lastplayed") self.failUnlessEqual(p.format_display(ALBUM), "0") p = PaneConfig("foo:title") self.failUnlessEqual(set(p.format_display(ALBUM).split(", ")), {"one", "two", "three", "four", "xxx"}) class TPaneEntry(TestCase): def test_all_have(self): sel = SongsEntry("foo", "foo", SONGS) self.assertFalse(sel.all_have("artist", "one")) self.assertFalse(sel.all_have("~#mtime", 4)) self.assertTrue(sel.all_have("foo", "bar")) def test_all(self): entry = AllEntry() conf = PaneConfig("title:artist") self.assertFalse(entry.get_count_text(conf)) entry.get_text(conf) self.assertEqual(list(entry.songs), []) self.assertFalse(entry.contains_text("")) repr(entry) def test_unknown(self): entry = UnknownEntry(SONGS) conf = PaneConfig("title:artist") self.assertEqual(entry.songs, set(SONGS)) self.assertEqual(entry.key, "") self.assertFalse(entry.contains_text("")) self.assertTrue(SONGS[0]("artist") in entry.get_count_text(conf)) entry.get_text(conf) repr(entry) def test_songs(self): entry = SongsEntry("key", "key", SONGS) self.assertEqual(entry.key, "key") conf = PaneConfig("title:artist") self.assertTrue("boris" in entry.get_count_text(conf)) self.assertEqual(entry.get_text(conf), (False, "key")) self.assertTrue(entry.contains_text("key")) repr(entry) def test_songs_markup(self): entry = SongsEntry("key", "key", SONGS) conf = PaneConfig("<title>") self.assertEqual(entry.get_text(conf), (True, "key")) class TPane(TestCase): def setUp(self): config.init() lib = SongLibrary() self.pane = Pane(lib, "artist") def tearDown(self): self.pane.destroy() del self.pane config.quit() def test_init(self): repr(self.pane) self.assertEqual(self.pane.tags, {"artist"}) def test_add_remove_and_show(self): with realized(self.pane): self.pane.add(SONGS) with realized(self.pane): self.pane.remove(SONGS) self.assertFalse(self.pane.list("arist")) def test_matches(self): self.assertTrue(self.pane.matches(SONGS[0])) self.pane.fill(SONGS) selection = self.pane.get_selection() selection.unselect_all() selection.select_path(Gtk.TreePath(3)) self.assertFalse(self.pane.matches(SONGS[1])) def test_fill(self): self.pane.fill(SONGS) def test_fill_selection(self): self.pane.fill(SONGS) model, paths = self.pane.get_selection().get_selected_rows() self.assertEqual(len(paths), 1) self.assertEqual(paths[0], Gtk.TreePath((0,))) def test_set_selected(self): self.pane.fill(SONGS) self.pane.set_selected([]) self.assertEqual(self.pane.get_selected(), {None}) self.pane.set_selected([], force_any=False) self.assertEqual(self.pane.get_selected(), set()) keys = self.pane.list("artist") self.pane.set_selected(keys) self.assertEqual(self.pane.get_selected(), keys) def test_restore_string(self): self.pane.fill(SONGS) keys = self.pane.list("artist") self.pane.set_selected(keys) to_restore = self.pane.get_restore_string() self.pane.remove(SONGS) self.pane.parse_restore_string(to_restore) self.pane.fill(SONGS) self.assertEqual(self.pane.get_selected(), keys) class TMultiPane(TestCase): def setUp(self): config.init() lib = SongLibrary() self.p2 = Pane(lib, "artist", self) self.p1 = Pane(lib, "genre", self.p2) self.last = None self.count = 0 def fill(self, songs): # this class is the final pane self.last = songs self.count += 1 def test_inhibit(self): self.p2.inhibit() self.p1.fill(SONGS) self.p2.uninhibit() self.assertEqual(self.count, 0) def test_pipe_through(self): self.p1.fill(SONGS) self.assertEqual(self.last, set(SONGS)) self.assertEqual(self.count, 1) def test_filter_first(self): VALUE = "J-Pop" self.p1.fill(SONGS) keys = self.p1.list("genre") self.assertTrue(VALUE in keys) self.p1.set_selected([VALUE], force_any=False) self.assertTrue(self.last) for song in self.last: self.assertEqual(song("genre"), VALUE) self.assertEqual(self.count, 2) def tearDown(self): self.p1.destroy() self.p2.destroy() del self.p1 del self.p2 config.quit() class TPaneModel(TestCase): def _verify_model(self, model): if len(model) == 1: self.assertFalse(isinstance(model[0][0], AllEntry)) elif len(model) > 1: self.assertTrue(isinstance(model[0][0], AllEntry)) for row in list(model)[1:-1]: self.assertTrue(isinstance(row[0], SongsEntry)) self.assertTrue( isinstance(model[-1][0], (SongsEntry, UnknownEntry))) def test_add_songs(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self.assertTrue(isinstance(m[0][0], AllEntry)) self.assertTrue(isinstance(m[-1][0], UnknownEntry)) self.assertEqual(len(m), len(SONGS) + 1 - 1) m.add_songs([]) self._verify_model(m) m2 = PaneModel(conf) for song in SONGS: m2.add_songs([song]) self._verify_model(m) self.assertEqual(len(m), len(m2)) for e1, e2 in zip(m.itervalues(), m2.itervalues()): self.assertEqual(e1.key, e2.key) m3 = PaneModel(conf) for song in reversed(SONGS): m3.add_songs([song]) self._verify_model(m) self.assertEqual(len(m), len(m3)) for e1, e2 in zip(m.itervalues(), m3.itervalues()): self.assertEqual(e1.key, e2.key) def test_add_unknown_first(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs([UNKNOWN_ARTIST]) self._verify_model(m) m.add_songs(SONGS) self._verify_model(m) def test_add_songs_double(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self._verify_model(m) m.add_songs(SONGS) self._verify_model(m) self.assertEqual(len(m), len(SONGS) + 1 - 1) def test_get_songs(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) # get none self.assertEqual(m.get_songs([]), set()) # get all self.assertEqual(len(m.get_songs([0])), len(SONGS)) self.assertEqual(len(m.get_songs([0, 1])), len(SONGS)) # get one self.assertEqual(m.get_songs([1]), {SONGS[0]}) def test_get_keys_by_tag(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self.assertEqual(m.get_keys_by_tag("title", ["three"]), ["boris"]) self.assertEqual(m.get_keys_by_tag("nope", ["foo", ""]), [""]) self.assertEqual( m.get_keys_by_tag("artist", ["piman", "foo"]), ["piman"]) def test_list(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self.assertEqual(m.list("artist"), {"boris", "mu", "piman", ""}) conf = PaneConfig("<artist><foo>") m = PaneModel(conf) m.add_songs(SONGS) self.assertEqual(m.list("artist"), {"boris", "mu", "piman"}) self.assertEqual(set(m.list("foo")), {'nope', 'bar', 'quux'}) def test_get_keys(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self.assertFalse(m.get_keys([])) self.assertEqual(m.get_keys([0, 1]), {None, "boris"}) def test_remove_songs_keep_rows(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) length = len(m) m.remove_songs(SONGS, False) self._verify_model(m) self.assertEqual(length, len(m)) self.assertFalse(m.get_songs([r.path for r in m])) def test_remove_songs_remove_rows(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) length = len(m) m.remove_songs(SONGS, True) self._verify_model(m) self.assertNotEqual(length, len(m)) self.assertEqual(len(m), 0) def test_remove_steps(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) for song in SONGS: m.remove_songs([song], True) self._verify_model(m) def test_matches(self): conf = PaneConfig("artist") m = PaneModel(conf) m.add_songs(SONGS) self.assertFalse(m.matches([], SONGS[0])) self.assertTrue(m.matches([0], SONGS[0])) self.assertTrue(m.matches([1], SONGS[0])) self.assertFalse(m.matches([2], SONGS[0])) m.add_songs([UNKNOWN_ARTIST]) self._verify_model(m) self.assertTrue(m.matches([len(m) - 1], UNKNOWN_ARTIST)) class TPanedPreferences(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_editor(self): x = PatternEditor() x.headers = x.headers x.destroy() x.destroy() def test_button(self): PreferencesButton(None).destroy() def test_dialog(self): Preferences(None).destroy() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1666295010.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_playlists.py����������������������������������������������������0000644�0001750�0001750�00000040317�14324322342�020734� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from pathlib import Path import pytest from gi.repository import Gdk, Gtk import quodlibet.config from quodlibet import app from quodlibet import qltk from quodlibet.browsers._base import BrowserError from quodlibet.browsers.playlists import PlaylistsBrowser from quodlibet.browsers.playlists.prefs import DEFAULT_PATTERN_TEXT from quodlibet.browsers.playlists.util import (parse_m3u, parse_pls, _name_for) from quodlibet.library.file import FileLibrary from quodlibet.library.playlist import _DEFAULT_PLAYLIST_DIR, PlaylistLibrary from quodlibet.formats import AudioFile from quodlibet.library import SongFileLibrary from quodlibet.library.librarians import SongLibrarian from quodlibet.qltk.songlist import DND_QL from quodlibet.util.collection import FileBackedPlaylist, XSPFBackedPlaylist from quodlibet.util.path import mkdir from senf import fsnative, fsn2uri, fsn2bytes from tests import (TestCase, get_data_path, mkdtemp, _TEMP_DIR, init_fake_app, destroy_fake_app, run_gtk_loop) from tests.gtk_helpers import MockSelData from tests.test_browsers_search import SONGS from .helper import dummy_path, __, temp_filename class ConfigSetupMixin: def setUp(self): quodlibet.config.init() def tearDown(self): quodlibet.config.quit() class TParsePlaylistMixin: def test_parse_empty(self): with temp_filename() as name: with open(name) as f: pl = self.Parse(f, name, pl_lib=self.pl_lib) self.failIf(pl) pl.delete() def test_parse_onesong(self): with temp_filename() as name: with open(name, "wb") as af: target = self.prefix target += fsn2bytes(get_data_path("silence-44-s.ogg"), "utf-8") af.write(target) with open(name, "rb") as f: pl = self.Parse(f, name, pl_lib=self.pl_lib) self.failUnlessEqual(len(pl), 1) self.failUnlessEqual(pl[0]("title"), "Silence") pl.delete() def test_parse_onesong_uri(self): target = get_data_path("silence-44-s.ogg") target = fsn2uri(target).encode("ascii") target = self.prefix + target with temp_filename() as name: with open(name, "wb") as f: f.write(target) with open(name, "rb") as f: pl = self.Parse(f, name, pl_lib=self.pl_lib) self.failUnlessEqual(len(pl), 1) self.failUnlessEqual(pl[0]("title"), "Silence") pl.delete() class TParseM3U(TestCase, ConfigSetupMixin, TParsePlaylistMixin): Parse = staticmethod(parse_m3u) prefix = b"" def setUp(self): self.pl_lib = PlaylistLibrary(SongFileLibrary()) class TParsePLS(TestCase, ConfigSetupMixin, TParsePlaylistMixin): Parse = staticmethod(parse_pls) prefix = b"File1=" def setUp(self): self.pl_lib = PlaylistLibrary(SongFileLibrary()) class TPlaylistIntegration(TestCase): DUPLICATES = 1 SONG = AudioFile({ "title": "two", "artist": "mu", "~filename": dummy_path(u"/dev/zero")}) SONGS = [ AudioFile({ "title": "one", "artist": "piman", "~filename": dummy_path(u"/dev/null")}), SONG, AudioFile({ "title": "three", "artist": "boris", "~filename": dummy_path(u"/bin/ls")}), AudioFile({ "title": "four", "artist": "random", "album": "don't stop", "labelid": "65432-1", "~filename": dummy_path(u"/dev/random")}), SONG, ] def setUp(self): quodlibet.config.init() self.lib = quodlibet.browsers.tracks.library = SongFileLibrary() quodlibet.browsers.tracks.library.librarian = SongLibrarian() for af in self.SONGS: af.sanitize() self.lib.add(self.SONGS) self._dir = mkdtemp() self.pl = FileBackedPlaylist.new(self._dir, "Foobar", self.lib, self.lib.playlists) self.pl.extend(self.SONGS) def tearDown(self): self.pl.delete() self.lib.destroy() self.lib.librarian.destroy() quodlibet.config.quit() shutil.rmtree(self._dir) def test_remove_song(self): # Check: library should have one song fewer (the duplicate) self.failUnlessEqual(len(self.lib), len(self.SONGS) - self.DUPLICATES) self.failUnlessEqual(len(self.pl), len(self.SONGS)) # Remove an unduplicated song self.pl.remove_songs([self.SONGS[0]]) self.failUnlessEqual(len(self.pl), len(self.SONGS) - 1) def test_remove_duplicated_song(self): self.failUnlessEqual(self.SONGS[1], self.SONGS[4]) self.pl.remove_songs([self.SONGS[1]]) self.failUnlessEqual(len(self.pl), len(self.SONGS) - 2) def test_remove_multi_duplicated_song(self): self.pl.extend([self.SONG, self.SONG]) self.failUnlessEqual(len(self.pl), 7) self.pl.remove_songs([self.SONG], False) self.failUnlessEqual(len(self.pl), 7 - 2 - 2) def test_remove_duplicated_song_leave_dupes(self): self.pl.remove_songs([self.SONGS[1]], True) self.failUnlessEqual(len(self.pl), len(self.SONGS) - 1) def test_remove_no_lib(self): pl = FileBackedPlaylist.new(self._dir, "Foobar") pl.extend(self.SONGS) self.assertTrue(len(pl)) pl.remove_songs(self.SONGS, False) self.assertFalse(len(pl)) class TPlaylistsBrowser(TestCase): Bar = PlaylistsBrowser ANOTHER_SONG = AudioFile({ "title": "lonely", "artist": "new artist", "~filename": dummy_path(u"/dev/urandom")}) ALL_SONGS = SONGS + [ANOTHER_SONG] def setUp(self): self.success = False # Testing locally is VERY dangerous without this... self.assertTrue(_TEMP_DIR in _DEFAULT_PLAYLIST_DIR or os.name == "nt", msg="Failing, don't want to delete %s" % _DEFAULT_PLAYLIST_DIR) try: shutil.rmtree(_DEFAULT_PLAYLIST_DIR) except OSError: pass mkdir(_DEFAULT_PLAYLIST_DIR) init_fake_app() self.lib = quodlibet.browsers.playlists.library = SongFileLibrary() self.lib.librarian = SongLibrarian() for af in self.ALL_SONGS: af.sanitize() self.lib.add(self.ALL_SONGS) self.big = pl = FileBackedPlaylist.new(_DEFAULT_PLAYLIST_DIR, "Big", self.lib, self.lib.playlists) pl.extend(SONGS) pl.write() self.small = pl = XSPFBackedPlaylist.new(_DEFAULT_PLAYLIST_DIR, "Small", self.lib, self.lib.playlists) pl.extend([self.ANOTHER_SONG]) pl.write() PlaylistsBrowser.init(self.lib) self.bar = PlaylistsBrowser(self.lib, self.MockConfirmerAccepting) self.bar.connect('songs-selected', self._expected) self.bar._select_playlist(self.bar.playlists()[0]) self.expected = None # Uses the declining confirmer. self.bar_decline = PlaylistsBrowser(self.lib, self.MockConfirmerDeclining) self.bar_decline.connect('songs-selected', self._expected_decline) self.bar_decline._select_playlist(self.bar_decline.playlists()[0]) # Note that _do() uses self.expected, but _do() is not called by the # testcase for declining the prompt. Tests fail with a shared expected. self.expected_decline = None def tearDown(self): self.small.delete() self.big.delete() self.bar.destroy() self.lib.destroy() shutil.rmtree(_DEFAULT_PLAYLIST_DIR) destroy_fake_app() def _expected(self, bar, songs, sort): songs.sort() if self.expected is not None: self.failUnlessEqual(self.expected, songs) self.success = True def _expected_decline(self, bar, songs, sort): songs.sort() if self.expected_decline is not None: self.failUnlessEqual(self.expected_decline, songs) self.success = True def _do(self): run_gtk_loop() self.failUnless(self.success or self.expected is None) def test_saverestore(self): # Flush previous signals, etc. Hmm. self.expected = None self._do() self.expected = [SONGS[0]] self.bar.filter_text("title = %s" % SONGS[0]["title"]) self.bar._select_playlist(self.bar.playlists()[0]) self.expected = [SONGS[0]] self._do() self.bar.save() self.bar.filter_text("") self.expected = list(sorted(SONGS)) self._do() self.bar.restore() self.bar.activate() self.expected = [SONGS[0]] self._do() def test_active_filter_playlists(self): self.bar._select_playlist(self.bar.playlists()[1]) # Second playlist should not have any of `SONGS` self.assertFalse(self.bar.active_filter(SONGS[0])) # But it should have `ANOTHER_SONG` self.assertTrue(self.bar.active_filter(self.ANOTHER_SONG), msg="Couldn't find song from second playlist") # ... and setting a reasonable filter on that song should match still self.bar.filter_text("lonely") self.assertTrue(self.bar.active_filter(self.ANOTHER_SONG), msg="Couldn't find song from second playlist with " "filter of 'lonely'") # ...unless it doesn't match that song self.bar.filter_text("piman") self.assertFalse(self.bar.active_filter(self.ANOTHER_SONG), msg="Shouldn't have matched 'piman' on second list") def test_rename(self): self.assertEquals(self.bar.playlists()[1], self.small) assert self.bar._rename(0, "zBig") self.assertEquals(self.bar.playlists()[0], self.small) self.assertEquals(self.bar.playlists()[1].name, "zBig") def test_rename_empty(self): assert not self.bar._rename(0, "", show_error=False) def test_default_display_pattern(self): pattern_text = self.bar.display_pattern_text self.failUnlessEqual(pattern_text, DEFAULT_PATTERN_TEXT) self.failUnless("<~name>" in pattern_text) def test_drag_data_get(self): b = self.bar song = AudioFile() song["~filename"] = fsnative(u"foo") sel = MockSelData() qltk.selection_set_songs(sel, [song]) b._drag_data_get(None, None, sel, DND_QL, None) def test_playlist_drag_data_extend_accept(self): b = self.bar song1 = AudioFile() song2 = AudioFile() song3 = AudioFile() song1["~filename"] = fsnative(u"foo1") song2["~filename"] = fsnative(u"foo2") song3["~filename"] = fsnative(u"foo3") sel = MockSelData() qltk.selection_set_songs(sel, [song1, song2, song3]) filenames = qltk.selection_get_filenames(sel) first_pl = b.playlists()[0] original_length = len(first_pl) # This is usually called by __drag_data_received, but that is heavily # dependent on gtk-views, so is more conveniently called manually. b._add_drag_data_tracks_to_playlist(first_pl, filenames) self.failUnlessEqual(len(first_pl), original_length + 3) def test_playlist_drag_data_extend_decline(self): b = self.bar_decline song1 = AudioFile() song2 = AudioFile() song3 = AudioFile() song1["~filename"] = fsnative(u"foo1") song2["~filename"] = fsnative(u"foo2") song3["~filename"] = fsnative(u"foo3") sel = MockSelData() qltk.selection_set_songs(sel, [song1, song2, song3]) filenames = qltk.selection_get_filenames(sel) first_pl = b.playlists()[0] original_length = len(first_pl) b._add_drag_data_tracks_to_playlist(first_pl, filenames) self.failUnlessEqual(len(first_pl), original_length) def test_songs_deletion(self): b = self.bar self._fake_browser_pack(b) event = self.a_delete_event() # This is selected in setUp() first_pl = b.playlists()[0] app.window.songlist.set_songs(first_pl) app.window.songlist.select_by_func(lambda x: True, scroll=False, one=True) original_length = len(first_pl) ret = b.key_pressed(event) self.failUnless(ret, msg="Didn't simulate a delete keypress") self.failUnlessEqual(len(first_pl), original_length - 1) def test_playlist_deletion_ACCEPT(self): b = self.bar orig_length = len(b.playlists()) event = self.a_delete_event() first_pl = b.playlists()[0] second_pl = b.playlists()[1] b._select_playlist(first_pl) ret = b._PlaylistsBrowser__key_pressed(b, event) self.failUnless(ret, msg="Didn't simulate a delete keypress") self.failUnlessEqual(len(b.playlists()), orig_length - 1) self.failUnlessEqual(b.playlists()[0], second_pl) def test_playlist_deletion_CANCEL(self): b = self.bar_decline orig_length = len(b.playlists()) event = self.a_delete_event() first_pl = b.playlists()[0] second_pl = b.playlists()[1] b._select_playlist(first_pl) ret = b._PlaylistsBrowser__key_pressed(b, event) self.failUnless(ret, msg="Didn't simulate a delete keypress") self.failUnlessEqual(len(b.playlists()), orig_length) self.failUnlessEqual(b.playlists()[0], first_pl) self.failUnlessEqual(b.playlists()[1], second_pl) def test_import(self): def fns(songs): return [song('~filename') for song in songs] pl_lib = self.bar.pl_lib assert len(self.bar.playlists()) == 2, "Should start with two playlists" assert len(pl_lib) == 2, f"Started with {pl_lib.keys()}" pl_name = "_€3 œufs à Noël" pl_path = Path(_TEMP_DIR) / (pl_name + ".m3u") with open(pl_path, "wb") as f: for fn in fns(SONGS): f.write(fsn2bytes(fn, "utf-8") + b"\n") pls_added, songs_added = self.bar._import_playlists([str(pl_path)]) assert pls_added == 1, f"Failed to add {pl_path}" assert len(self.bar.songs_lib) == len(self.ALL_SONGS) assert songs_added == 0, "Why did we add existing songs?" assert len(pl_lib) == 3, f"Got PLs: \n{', '.join(str(pl) for pl in pl_lib)}" pls = self.bar.playlists() assert len(pls) == 3, f"Got PL rows: {', '.join(str(pl) for pl in pls)}" # Leading underscore makes it always the last entry imported = pls[-1] self.failUnlessEqual(fns(imported.songs), fns(SONGS)) def test_no_pl_lib(self): """Probably not possible in real runtime situations""" with pytest.raises(BrowserError): assert PlaylistsBrowser(FileLibrary("no-playlists")) @staticmethod def a_delete_event(): ev = Gdk.Event() ev.type = Gdk.EventType.KEY_PRESS ev.keyval, accel_mod = Gtk.accelerator_parse("Delete") ev.state = Gtk.accelerator_get_default_mod_mask() & accel_mod return ev @staticmethod def _fake_browser_pack(b): app.window.get_child().pack_start(b, True, True, 0) class MockConfirmerAccepting: RESPONSE_INVOKE = Gtk.ResponseType.YES def __init__(self, *args): pass def run(self, *args): return self.RESPONSE_INVOKE class MockConfirmerDeclining: RESPONSE_INVOKE = Gtk.ResponseType.YES def __init__(self, *args): pass def run(self, *args): return Gtk.ResponseType.CANCEL class TPlaylistUtils(TestCase): def test_naming(self): self.failUnlessEqual(_name_for('/foo/bar.m3u'), 'bar') self.failUnlessEqual(_name_for('/foo/Will.I.Am.m3u'), 'Will.I.Am') def test_naming_default(self): self.failUnlessEqual(_name_for(''), __('New Playlist')) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_podcasts.py�����������������������������������������������������0000644�0001750�0001750�00000004705�14327505043�020535� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from _pytest.fixtures import fixture from gi.repository import Gtk import quodlibet.config from quodlibet.browsers.podcasts import Podcasts, AddFeedDialog, Feed from quodlibet.library import SongLibrary from quodlibet.util.config import Config from senf import fsn2uri from tests import TestCase, get_data_path TEST_URL = u"https://a@b:foo.example.com?bar=baz&quxx#anchor" class TAudioFeeds(TestCase): def setUp(self): quodlibet.config.init() self.library = SongLibrary() self.bar = Podcasts(self.library) def test_can_filter(self): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: self.failIf(self.bar.can_filter(key)) def tearDown(self): self.bar.destroy() self.library.destroy() quodlibet.config.quit() class TAddFeedDialog(TestCase): def setUp(self): quodlibet.config.init() def test_add_feed_takes_uri(self): parent = Gtk.Window() ret = AddFeedDialog(parent).run(text=TEST_URL, test=True) self.failUnlessEqual(ret.uri, TEST_URL) def tearDown(self): quodlibet.config.quit() class TFeed(TestCase): def setUp(self): quodlibet.config.init() def test_feed(self): fn = get_data_path('valid_podcast.xml') feed = Feed(fsn2uri(fn)) result = feed.parse() # Assume en_US / en_GB locale here in tests self.failIfEqual(feed.name, "Unknown", msg="Didn't find feed name") # Do this after the above, as many exceptions can be swallowed self.failUnless(result) self.failUnlessEqual(len(feed), 2) self.failUnlessEqual(feed[0]('title'), 'Full Episode: Tuesday, November 28, 2017') def tearDown(self): quodlibet.config.quit() @fixture def config(): quodlibet.config.init() yield quodlibet.config quodlibet.config.quit() @fixture def podcasts(): library = SongLibrary() return Podcasts(library) def test_menu_items_can_be_clicked(config: Config, podcasts: Podcasts): view = podcasts._view view.popup_menu = lambda *args: True menu = podcasts._popup_menu(None) assert menu for item in menu.get_children(): item.emit('activate') �����������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_search.py�������������������������������������������������������0000664�0001750�0001750�00000011415�14231604332�020153� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import quodlibet.browsers.tracks import quodlibet.config from quodlibet.browsers.tracks import TrackList from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary, SongLibrarian from quodlibet.qltk.songlist import SongList from senf import fsnative from tests import TestCase, run_gtk_loop # Don't sort yet, album_key makes it complicated... SONGS = [AudioFile({ "title": "one", "artist": "piman", "~filename": fsnative(u"/dev/null")}), AudioFile({ "title": "two", "artist": "mu", "~#length": 234, "~filename": fsnative(u"/dev/zero")}), AudioFile({ "title": "three", "artist": "boris", "~filename": fsnative(u"/bin/ls")}), AudioFile({ "title": "four", "artist": "random", "album": "don't stop", "labelid": "65432-1", "~filename": fsnative(u"/dev/random")}), AudioFile({ "title": "five € and a £", "artist": "shell", "album": "don't stop", "labelid": "12345-6", "~filename": fsnative(u"/tmp/five € and £!")})] class TSearchBar(TestCase): Bar = TrackList def setUp(self): quodlibet.config.init() quodlibet.browsers.tracks.library = SongLibrary() quodlibet.browsers.tracks.library.librarian = SongLibrarian() for af in SONGS: af.sanitize() quodlibet.browsers.tracks.library.add(SONGS) self.bar = self.Bar(quodlibet.browsers.tracks.library) self._sid = self.bar.connect('songs-selected', self._expected) self.success = False def _expected(self, bar, songs, sort): songs.sort() self.failUnlessEqual(self.expected, songs) self.success = True def _do(self): run_gtk_loop() self.failUnless(self.success or self.expected is None) def test_can_filter(self): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: self.failUnless(self.bar.can_filter(key)) def test_empty_is_all(self): self.bar.filter_text("") self.expected = list(sorted(SONGS)) self._do() def test_active_filter(self): self.assertTrue(self.bar.active_filter(SONGS[0])) self.bar.filter_text("this does not match any song") self.expected = [] self.assertFalse(self.bar.active_filter(SONGS[0])) self._do() def test_filter(self): self.expected = [SONGS[1]] self.bar.filter("title", ["two"]) self._do() def test_filter_again(self): self.expected = sorted(SONGS[3:5]) self.bar.filter("album", ["don't stop"]) self._do() def test_filter_notvalue(self): self.expected = sorted(SONGS[0:2]) self.bar.filter("artist", ["notvalue", "mu", "piman"]) self._do() def test_filter_none(self): self.expected = [] self.bar.filter("title", ["not a value"]) self._do() def test_filter_album_by_labelid(self): self.expected = [SONGS[3]] self.bar.filter("labelid", [("65432-1")]) self._do() def test_filter_numeric(self): self.expected = sorted([SONGS[0]] + SONGS[2:]) self.bar.filter("~#length", [0]) self._do() def test_search_text_artist(self): self.bar._set_text("boris") self.expected = [SONGS[2]] self.bar._sb_box.changed() self._do() def test_search_text_custom_star(self): old = SongList.star SongList.star = ["artist", "labelid"] self.bar._set_text("65432-1") self.expected = [SONGS[3]] self.bar._sb_box.changed() try: self._do() finally: SongList.star = old def test_saverestore(self): self.bar.filter_text("title = %s" % SONGS[0]["title"]) self.expected = [SONGS[0]] self._do() self.bar.save() self.bar.filter_text("") self.expected = list(sorted(SONGS)) self._do() self.bar.restore() self.bar.activate() self.expected = [SONGS[0]] self._do() def tearDown(self): for song in SONGS: try: os.unlink(song("~filename")) except OSError: pass self.bar.disconnect(self._sid) self.bar.destroy() quodlibet.browsers.tracks.library.destroy() quodlibet.config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660723675.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_browsers_soundcloud.py���������������������������������������������������0000644�0001750�0001750�00000006630�14277120733�021076� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import time from unittest import TestCase from gi.repository import Gtk from quodlibet import config from quodlibet import const from quodlibet.browsers.soundcloud import SoundcloudBrowser from quodlibet.browsers.soundcloud.api import SoundcloudApiClient from quodlibet.browsers.soundcloud.query import SoundcloudQuery, convert_time from quodlibet.query import QueryType from quodlibet.util.dprint import print_d from tests.test_browsers__base import TBrowserBase NONE = set([]) class TestExtract(TestCase): @classmethod def setUpClass(cls): const.DEBUG = True @classmethod def tearDownClass(cls): const.DEBUG = False def test_extract_single_tag(self): self.verify("artist=jay z", {"jay z"}) def test_extract_unsupported(self): self.failUnlessEqual(SoundcloudQuery("musicbrainz_discid=12345").type, QueryType.INVALID) def test_extract_composite_text(self): self.verify("&(foo, bar)", {"foo", "bar"}) self.verify("|(either, or)", {"either", "or"}) def test_numeric_simple(self): self.verify("#(length=180)", {'180000'}, term='duration') def test_extract_date(self): now = int(time.time()) terms = SoundcloudQuery("#(date>today)", clock=lambda: now).terms self.failUnlessEqual(terms['created_at[from]'].pop(), convert_time(now - 86400)) def test_numeric_relative(self): self.verify("#(length>180)", {'180000'}, term='duration[from]') self.verify("#(180<=length)", {'180000'}, term='duration[from]') self.verify("#(length<360)", {'360000'}, term='duration[to]') self.verify("#(360>=length)", {'360000'}, term='duration[to]') def test_extract_tag_inter(self): self.verify("genre=&(jazz, funk)", {'jazz', 'funk'}) def test_extract_tag_union(self): self.verify("genre=|(jazz, funk)", {'jazz', 'funk'}) def test_extract_complex(self): self.verify("&(artist='foo', genre=|(rock, metal))", {'foo', 'rock', 'metal'}) def verify(self, text, expected, term='q'): print_d("Trying '%s'..." % text) terms = SoundcloudQuery(text).terms self.failUnlessEqual(terms[term], expected, msg="terms[%s] wasn't %r. Full terms: %r" % (term, expected, terms)) class TestMenu(TBrowserBase): Kind = SoundcloudBrowser def test_songsmenu_has_information_but_no_edit(self): menu = self.b.Menu([], self.library, []) assert menu items = [item.get_label() for item in menu.get_children() if type(item) is not Gtk.SeparatorMenuItem] # We're always in en_US assert "_Rating" in items assert "_Information" in items, "Should have included Information" assert "Edit _Tags" not in items, "Shouldn't have included edit" class TestHttpsDefault(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_setup_default(self): self.failUnless(SoundcloudApiClient().root.startswith('https://'), msg="API client should use HTTPS") ��������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1630745765.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_cli.py�������������������������������������������������������������������0000664�0001750�0001750�00000001476�14114632245�015541� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from .helper import capture_output from quodlibet import cli from tests import TestCase class Tcli(TestCase): def test_process_no_arguments_works(self): with capture_output() as (out, err): cli.process_arguments(["myprog"]) self.assertFalse(out.getvalue()) self.assertFalse(err.getvalue()) def test_process_arguments_errors_on_invalid_opt(self): with self.assertRaises(SystemExit): with capture_output(): cli.process_arguments(["myprog", "--wrong-thing"]) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689589142.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_commands.py��������������������������������������������������������������0000644�0001750�0001750�00000013637�14455212626�016600� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from senf import fsnative from quodlibet.formats import AudioFile from tests import TestCase, init_fake_app, destroy_fake_app from .helper import capture_output from gi.repository import Gtk from quodlibet import config from quodlibet import app from quodlibet.commands import registry class TCommandBase(TestCase): def setUp(self): config.init() init_fake_app() def tearDown(self): destroy_fake_app() config.quit() def _send(self, command): command = fsnative(str(command)) return registry.handle_line(app, command) class TCommands(TCommandBase): def test_query(self): self._send(u"query foo") self.assertEqual(self._send("print-query-text"), u"foo\n") def test_print_playing_elapsed(self): app.player.info = AudioFile( {"album": "foo", "~filename": fsnative("/dev/null")}) app.player.seek(123 * 1000) assert self._send("print-playing <album~~elapsed>") == "foo - 2:03\n" def test_print_playing_elapsed_numeric(self): app.player.info = AudioFile( {"album": "foo", "~filename": fsnative("/dev/null")}) app.player.seek(234.56 * 1000) assert self._send("print-playing <~#elapsed>") == "234.56\n" def test_player(self): self._send("previous") self._send("force-previous") self._send("next") self._send("pause") self._send("play-pause") self._send("play") self._send("print-playing <album~~elapsed>") self._send("stop") self._send("volume +1000") self._send("volume 40") self._send("volume -10") self._send("volume +4.2") self._send("seek -10") self._send("seek +10") self._send("seek 0") def test_misc(self): with capture_output(): self._send("play-file /dev/null") self._send("dump-playlist") self._send("dump-queue") self._send("enqueue /dev/null") self._send("enqueue-files /dev/null") self._send("filter album=test") self._send("query '/foobar/'") self._send("focus") self._send("hide-window") self._send("dump-browsers") self._send("open-browser SearchBar") from quodlibet.qltk.browser import LibraryBrowser for window in Gtk.Window.list_toplevels(): if isinstance(window, LibraryBrowser): window.destroy() self._send("properties") self._send("queue 1") self._send("quit") self._send("random album") self._send("refresh") self._send("repeat 0") self._send("show-window") self._send("song-list 1") self._send("stop-after 1") self._send("status") self._send("toggle-window") self._send("unqueue /dev/null") def test_set_browser(self): self._send("set-browser 1") def test_enqueue_files(self): songs = [AudioFile({"~filename": fn, "title": fn}) for fn in ["one", "two, please", "slash\\.mp3", "four"]] app.library.add(songs) self.assertFalse(app.window.playlist.q.get()) self._send("enqueue-files " "one,two\\, please,slash\\\\.mp3,four") self.assertEquals(app.window.playlist.q.get(), songs) def test_rating(self): app.player.song = AudioFile( {"album": "foo", "~filename": fsnative("/dev/null")}) self._send("rating +") self.assertAlmostEqual(app.player.song['~#rating'], 0.75) self._send("rating 0.4") self.assertAlmostEqual(app.player.song['~#rating'], 0.4) self._send("rating +0.01") self.assertAlmostEqual(app.player.song['~#rating'], 0.41) self._send("rating -10") self.assertEquals(app.player.song['~#rating'], 0) class TCommandWithPattern(TCommandBase): def setUp(self): super().setUp() songs = [AudioFile({"~filename": fn, "title": fn.upper()}) for fn in ["one", "two, please", "slash\\.mp3", "4.0-four"]] app.library.add(songs) self.assertFalse(app.window.playlist.q.get()) self._send("enqueue-files " "one,two\\, please,slash\\\\.mp3,4.0-four") def test_old_syntax(self): assert self._send("print-query two ") == "two, please\n" def test_old_syntax_that_is_a_valid_json(self): assert self._send("print-query \"one\"") == "one\n" assert self._send("print-query 4.0") == "4.0-four\n" assert self._send("print-query true") == "\n" def test_new_syntax(self): assert self._send( "print-query {\"query\": \"two\", \"pattern\": null}" ) == "two, please\n" assert self._send( "print-query {\"query\": \"two\", \"pattern\": \"asdf\"}" ) == "asdf\n" assert self._send( "print-query {\"query\": \"slash\", \"pattern\": \"<title>\"}" ) == "SLASH\\.MP3\n" def test_query_is_valid_json(self): assert self._send( "print-query {\"query\": \"\\\"one\\\"\", \"pattern\": \"<title>\"}" ) == "ONE\n" assert self._send( "print-query {\"query\": \"4.0\", \"pattern\": \"<title>\"}" ) == "4.0-FOUR\n" def test_query_is_not_a_string(self): # Query is valid json, but not came from the CLI. (It's not a string.) assert self._send( "print-query {\"query\": 4.0, \"pattern\": \"<title>\"}" ) == "\n" assert self._send( "print-query {\"query\": true, \"pattern\": \"<title>\"}" ) == "\n" def test_invalid_args(self): assert self._send( "print-query {\"query\": \"slash\", \"unknown\": \"<title>\"}" ) == "\n" �������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_config.py����������������������������������������������������������������0000664�0001750�0001750�00000005114�14035600052�016221� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from quodlibet.config import RatingsPrefs from tests import TestCase, mkstemp from quodlibet import config class Tconfig(TestCase): def setUp(self): config.init() def test_init_garbage_file(self): config.quit() garbage = b"\xf1=\xab\xac" fd, filename = mkstemp() os.close(fd) with open(filename, "wb") as f: f.write(garbage) config.init(filename) self.assertTrue(config.options("player")) invalid_filename = filename + ".not-valid" self.assertTrue(os.path.exists(invalid_filename)) with open(invalid_filename, "rb") as f: self.assertEqual(f.read(), garbage) os.remove(filename) os.remove(invalid_filename) def tearDown(self): config.quit() class TRatingsPrefs(TestCase): initial_number = int(config.INITIAL["settings"]["ratings"]) def setUp(self): config.init() self.prefs = RatingsPrefs() def test_getters(self): # A little pointless, and brittle, but still. self.failUnlessEqual(self.prefs.number, self.initial_number) self.failUnlessEqual(self.prefs.precision, 1.0 / self.initial_number) symbol_full = config.INITIAL["settings"]["rating_symbol_full"] self.failUnlessEqual(self.prefs.full_symbol, symbol_full) symbol_blank = config.INITIAL["settings"]["rating_symbol_blank"] self.failUnlessEqual(self.prefs.blank_symbol, symbol_blank) def test_caching(self): self.failUnlessEqual(self.prefs.number, self.initial_number) self.prefs.number = 10 self.prefs.default = 0.1 # Read it back, and it's fine self.failUnlessEqual(self.prefs.number, 10) self.failUnlessEqual(self.prefs.default, 0.1) # .. but modify behind the scenes (unsupported)... config.reset("settings", "ratings") config.reset("settings", "default_rating") # ...and caching will return the old one self.failUnlessEqual(self.prefs.number, 10) self.failUnlessEqual(self.prefs.default, 0.1) def test_all(self): self.prefs.number = 5 # Remember zero is a possible rating too self.failUnlessEqual(len(self.prefs.all), 6) self.failUnlessEqual(self.prefs.all, [0, 0.2, 0.4, 0.6, 0.8, 1.0]) def tearDown(self): config.quit() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_desktop_files.py���������������������������������������������������������0000664�0001750�0001750�00000003441�14035600052�017610� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import subprocess from tests import TestCase, mkstemp from quodlibet import util QLDATA_DIR = os.path.join(os.path.dirname(util.get_module_dir()), "data") class _TDesktopFileMixin: PATH = None def test_filename(self): self.assertTrue(self.PATH.endswith(".desktop.in")) def test_validate(self): with open(self.PATH, "rb") as template: desktop_data = template.read() # copy to a temp file and strip "_ from translatable entries fd, name = mkstemp(suffix=".desktop") os.close(fd) with open(name, "wb") as temp: new_lines = [] for l in desktop_data.splitlines(): if l.startswith(b"_"): l = l[1:] new_lines.append(l) temp.write(b"\n".join(new_lines)) # pass to desktop-file-validate try: output = subprocess.check_output( ["desktop-file-validate", name], stderr=subprocess.STDOUT) except OSError: # desktop-file-validate not available return except subprocess.CalledProcessError as e: output = e.output finally: os.remove(name) if output: raise Exception(output) class TQLDesktopFile(TestCase, _TDesktopFileMixin): PATH = os.path.join(QLDATA_DIR, "io.github.quodlibet.QuodLibet.desktop.in") class TEFDesktopFile(TestCase, _TDesktopFileMixin): PATH = os.path.join(QLDATA_DIR, "io.github.quodlibet.ExFalso.desktop.in") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_errorreport.py�����������������������������������������������������������0000664�0001750�0001750�00000006324�14035600052�017345� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys import os import shutil from gi.repository import Gtk from quodlibet.errorreport import faulthandling, enable_errorhook, errorhook from quodlibet.errorreport.faulthandling import FaultHandlerCrash from quodlibet.errorreport.logdump import dump_to_disk from quodlibet.errorreport.ui import ErrorDialog, SubmitErrorDialog from quodlibet.errorreport.main import get_sentry from quodlibet.errorreport.sentrywrapper import SentryError, CapturedException from . import TestCase, mkdtemp from .helper import temp_filename class Tfaulthandling(TestCase): def test_basic(self): with temp_filename() as filename: faulthandling.enable(filename) faulthandling.raise_and_clear_error() faulthandling.disable() def test_error(self): with temp_filename() as filename: with open(filename, "wb") as h: h.write(b"something") faulthandling.enable(filename) with self.assertRaises(FaultHandlerCrash): faulthandling.raise_and_clear_error() faulthandling.disable() def test_stacktrace_grouping(self): stack1 = 'File "%s", line 486 in string_at' % ( os.path.join("foo", "bar", "quux.py"),) stack2 = 'File "%s", line 350 in string_at' % ( os.path.join("baz", "bar", "quux.py"),) stack3 = 'File "%s", line 350 in other' % ( os.path.join("baz", "bar", "quux.py"),) key1 = FaultHandlerCrash(stack1).get_grouping_key() key2 = FaultHandlerCrash(stack2).get_grouping_key() key3 = FaultHandlerCrash(stack3).get_grouping_key() assert key1 and key2 and key3 assert key1 == key2 != key3 class Tlogdump(TestCase): def test_main(self): temp_dir = mkdtemp() try: dump_dir = os.path.join(temp_dir, "dump") try: raise Exception("foo") except Exception: dump_to_disk(dump_dir, sys.exc_info()) assert len(os.listdir(dump_dir)) == 1 finally: shutil.rmtree(temp_dir) class Terrorui(TestCase): def test_main(self): w = Gtk.Window() ErrorDialog(w, u"foo").destroy() ErrorDialog(w, u"foo").destroy() SubmitErrorDialog(w, u"foo").destroy() class Terrorreport(TestCase): def test_enable(self): enable_errorhook(True) enable_errorhook(False) try: raise Exception except Exception: errorhook() class Tsentrywrapper(TestCase): def test_main(self): sentry = get_sentry() try: raise Exception except Exception: exc_info = sys.exc_info() try: err = sentry.capture(exc_info) except SentryError: return assert isinstance(err, CapturedException) assert isinstance(err.get_report(), str) err.set_comment(u"foo") err.set_comment(u"bar") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats___init__.py������������������������������������������������������0000664�0001750�0001750�00000013546�14035600052�020256� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from senf import fsnative from tests import TestCase, get_data_path from .helper import capture_output from quodlibet import formats from quodlibet.formats import AudioFile, load_audio_files, dump_audio_files, \ SerializationError from quodlibet.util.picklehelper import pickle_dumps from quodlibet import config class TFormats(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_presence(self): self.failUnless(formats.aac) self.failUnless(formats.aiff) self.failUnless(formats.midi) self.failUnless(formats.mod) self.failUnless(formats.monkeysaudio) self.failUnless(formats.mp3) self.failUnless(formats.mp4) self.failUnless(formats.mpc) self.failUnless(formats.spc) self.failUnless(formats.trueaudio) self.failUnless(formats.vgm) self.failUnless(formats.wav) self.failUnless(formats.wavpack) self.failUnless(formats.wma) self.failUnless(formats.xiph) def test_loaders(self): self.failUnless(formats.loaders[".mp3"] is formats.mp3.MP3File) def test_migration(self): self.failUnless(formats.mp3 is sys.modules["quodlibet.formats.mp3"]) self.failUnless(formats.mp3 is sys.modules["quodlibet/formats/mp3"]) self.failUnless(formats.mp3 is sys.modules["formats.mp3"]) self.failUnless(formats.xiph is sys.modules["formats.flac"]) self.failUnless(formats.xiph is sys.modules["formats.oggvorbis"]) def test_filter(self): self.assertTrue(formats.filter("foo.mp3")) self.assertFalse(formats.filter("foo.doc")) self.assertFalse(formats.filter("foomp3")) def test_music_file(self): path = get_data_path('silence-44-s.mp3') self.assertTrue(formats.MusicFile(path)) # non existing with capture_output() as (stdout, stderr): song = formats.MusicFile(get_data_path("nope.mp3")) self.assertFalse(song) self.assertTrue(stderr.getvalue()) # unknown extension with capture_output() as (stdout, stderr): song = formats.MusicFile(get_data_path("nope.xxx")) self.assertFalse(song) self.assertFalse(stderr.getvalue()) class TPickle(TestCase): def setUp(self): types = formats.types instances = [] for t in types: i = AudioFile.__new__(t) # we want to pickle/unpickle everything, since historically # these things ended up in the file dict.__init__( i, {b"foo": u"bar", u"quux": b"baz", "a": "b", u"b": 42, "c": 0.25}) instances.append(i) self.instances = instances def test_load_audio_files(self): for protocol in [0, 1, 2]: data = pickle_dumps(self.instances, protocol) items = load_audio_files(data) assert len(items) == len(formats.types) assert all(isinstance(i, AudioFile) for i in items) def test_sanitized_py3(self): i = AudioFile.__new__(list(formats.types)[0]) # this is something that old py2 versions could pickle dict.__init__(i, { b"bytes": b"bytes", u"unicode": u"unicode", b"~filename": b"somefile", u"~mountpoint": u"somemount", u"int": 42, b"float": 1.25, }) data = pickle_dumps([i], 1) items = load_audio_files(data, process=True) i = items[0] assert i["bytes"] == "bytes" assert i["unicode"] == "unicode" assert isinstance(i["~filename"], fsnative) assert isinstance(i["~mountpoint"], fsnative) assert i["int"] == 42 assert i["float"] == 1.25 def test_dump_audio_files(self): data = dump_audio_files(self.instances, process=False) items = load_audio_files(data, process=False) assert len(items) == len(self.instances) for a, b in zip(items, self.instances): a = dict(a) b = dict(b) for key in a: assert b[key] == a[key] for key in b: assert b[key] == a[key] def test_save_ascii_keys_as_bytes_on_py3(self): i = AudioFile.__new__(list(formats.types)[0]) dict.__setitem__(i, u"foo", u"bar") data = dump_audio_files([i], process=True) items = load_audio_files(data, process=False) assert isinstance(list(items[0].keys())[0], bytes) def test_dump_empty(self): data = dump_audio_files([]) assert load_audio_files(data) == [] def test_load_audio_files_missing_class(self): for protocol in [0, 1, 2]: data = pickle_dumps(self.instances, protocol) items = load_audio_files(data) self.assertEqual(len(items), len(formats.types)) assert all(isinstance(i, AudioFile) for i in items) broken = data.replace(b"SPCFile", b"FooFile") items = load_audio_files(broken) self.assertEqual(len(items), len(formats.types) - 1) assert all(isinstance(i, AudioFile) for i in items) broken = data.replace(b"formats.spc", b"formats.foo") items = load_audio_files(broken) self.assertEqual(len(items), len(formats.types) - 1) assert all(isinstance(i, AudioFile) for i in items) def test_unpickle_random_class(self): for protocol in [0, 1, 2]: data = pickle_dumps([42], protocol) with self.assertRaises(SerializationError): load_audio_files(data) ����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1677753347.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats__audio.py��������������������������������������������������������0000644�0001750�0001750�00000131037�14400076003�017750� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import io import os import shutil import time from contextlib import contextmanager from tempfile import mkstemp, mkdtemp from quodlibet import config, app from quodlibet.formats import AudioFile, types as format_types, AudioFileError from quodlibet.formats import decode_value, MusicFile, FILESYSTEM_TAGS from quodlibet.formats._audio import NUMERIC_ZERO_DEFAULT, TIME_TAGS from quodlibet.util.environment import is_windows from quodlibet.util.path import (normalize_path, mkdir, get_home_dir, unquote, escape_filename, RootPathFile) from quodlibet.util.string.date import format_date from quodlibet.util.tags import _TAGS as TAGS from senf import fsnative, fsn2text, bytes2fsn from tests import TestCase, get_data_path, init_fake_app, destroy_fake_app from .helper import temp_filename bar_1_1 = AudioFile({ "~filename": fsnative(u"/fakepath/1"), "title": "A song", "discnumber": "1/2", "tracknumber": "1/3", "artist": "Foo", "album": "Bar"}) bar_1_2 = AudioFile({ "~filename": fsnative(u"/fakepath/2"), "title": "Perhaps another", "titlesort": "Titles don't sort", "discnumber": "1", "tracknumber": "2/3", "artist": "Lali-ho!", "album": "Bar", "date": "2004-12-12", "originaldate": "2005-01-01", "~#filesize": 1024 ** 2, "~#bitrate": 128}) bar_2_1 = AudioFile({ "~filename": fsnative(u"/does not/exist"), "title": "more songs", "discnumber": "2/2", "tracknumber": "1", "artist": "Foo\nI have two artists", "artistsort": "Foosort\n\nThird artist", "album": "Bar", "lyricist": "Foo", "composer": "Foo", "performer": "I have two artists"}) bar_va = AudioFile({ "~filename": "/fakepath/3", "title": "latest", "artist": "Foo\nI have two artists", "album": "Bar", "language": "de\neng", "albumartist": "Various Artists", "performer": "Jay-Z"}) num_call = AudioFile({"custom": "0.3"}) ANOTHER_RATING = 0.2 SOME_RATING = 0.8 class TAudioFile(TestCase): def setUp(self): # Need the playlists library now init_fake_app() config.RATINGS = config.HardCodedRatingsPrefs() fd, filename = mkstemp() os.close(fd) self.quux = AudioFile({ "~filename": normalize_path(filename, True), "album": u"Quuxly" }) def tearDown(self): destroy_fake_app() try: os.unlink(self.quux["~filename"]) except EnvironmentError: pass def test_format_type(self): for t in format_types: i = AudioFile.__new__(t) assert isinstance(i("~format"), str) def test_tag_strs(self): for t in format_types: i = AudioFile.__new__(t) i["~filename"] = fsnative(u"foo") for tag in TAGS.values(): name = tag.name # brute force variants = [ name, "~" + name, name + "sort", "~" + name + "sort", name + ":role", "~" + name + ":role", "~" + name + "sort:role", name + "sort:role", ] for name in variants: if name in FILESYSTEM_TAGS: assert isinstance(i(name, fsnative()), fsnative) else: assert isinstance(i(name), str) def test_sort(self): l = [self.quux, bar_1_2, bar_2_1, bar_1_1] l.sort() self.assertEqual(l, [bar_1_1, bar_1_2, bar_2_1, self.quux]) self.assertEqual(self.quux, self.quux) self.assertEqual(bar_1_1, bar_1_1) self.assertNotEqual(bar_2_1, bar_1_2) def test_realkeys(self): self.failIf("artist" in self.quux.realkeys()) self.failIf("~filename" in self.quux.realkeys()) self.failUnless("album" in self.quux.realkeys()) def test_iterrealitems(self): af = AudioFile({ "~filename": fsnative(u"foo"), "album": u"Quuxly" }) assert list(af.iterrealitems()) == [('album', u'Quuxly')] def test_language(self): self.assertEqual(bar_va("~language"), "German\nEnglish") self.assertEqual(bar_va.list("~language"), ['German', 'English']) self.assertEqual(bar_1_1("~language", default="foo"), "foo") self.assertEqual(bar_1_1.list("~language"), []) def test_trackdisc(self): self.failUnlessEqual(bar_1_1("~#track"), 1) self.failUnlessEqual(bar_1_1("~#disc"), 1) self.failUnlessEqual(bar_1_1("~#tracks"), 3) self.failUnlessEqual(bar_1_1("~#discs"), 2) self.failIf(bar_1_2("~#discs")) self.failIf(bar_2_1("~#tracks")) def test_setitem_keys(self): af = AudioFile() af[u"foo"] = u"bar" assert "foo" in af assert isinstance(list(af.keys())[0], str) af.clear() af[u"öäü"] = u"bar" assert u"öäü" in af assert isinstance(list(af.keys())[0], str) with self.assertRaises(TypeError): af[42] = u"foo" with self.assertRaises(TypeError): af[b"foo"] = u"bar" def test_call(self): # real keys should lookup the same for key in bar_1_1.realkeys(): self.failUnlessEqual(bar_1_1[key], bar_1_1(key)) # fake/generated key checks af = AudioFile() self.failIf(af("not a key")) self.failUnlessEqual(af("not a key", "foo"), "foo") self.failUnlessEqual(af("artist"), "") assert self.quux("~basename") assert self.quux("~dirname") == os.path.dirname(self.quux("~filename")) assert self.quux("title") == \ "%s [untitled Unknown Audio File]" % fsn2text(self.quux("~basename")) self.failUnlessEqual(bar_1_1("~#disc"), 1) self.failUnlessEqual(bar_1_2("~#disc"), 1) self.failUnlessEqual(bar_2_1("~#disc"), 2) self.failUnlessEqual(bar_1_1("~#track"), 1) self.failUnlessEqual(bar_1_2("~#track"), 2) self.failUnlessEqual(bar_2_1("~#track"), 1) def test_year(self): self.failUnlessEqual(bar_1_2("~year"), "2004") self.failUnlessEqual(bar_1_2("~#year"), 2004) self.failUnlessEqual(bar_1_1("~#year", 1999), 1999) def test_filesize(self): self.failUnlessEqual(bar_1_2("~filesize"), "1.00 MB") self.failUnlessEqual(bar_1_2("~#filesize"), 1024 ** 2) assert isinstance(bar_1_2("~filesize"), str) def test_bitrate(self): self.assertEqual(bar_1_2("~#bitrate"), 128) self.assertEqual(bar_1_2("~bitrate"), "128 kbps") def test_originalyear(self): self.failUnlessEqual(bar_1_2("~originalyear"), "2005") self.failUnlessEqual(bar_1_2("~#originalyear"), 2005) self.failUnlessEqual(bar_1_1("~#originalyear", 1999), 1999) def test_call_people(self): af = AudioFile() self.failUnlessEqual(af("~people"), "") self.failUnlessEqual(bar_1_1("~people"), "Foo") self.failUnlessEqual(bar_1_2("~people"), "Lali-ho!") self.failUnlessEqual(bar_2_1("~people"), "Foo\nI have two artists") # See Issue 1034 self.failUnlessEqual(bar_va("~people"), "Foo\nI have two artists\nVarious Artists\nJay-Z") def test_call_multiple(self): for song in [self.quux, bar_1_1, bar_2_1]: self.failUnlessEqual(song("~~people"), song("~people")) self.failUnlessEqual(song("~title~people"), song("title")) self.failUnlessEqual( song("~title~~people"), song("~title~artist")) def test_tied_filename_numeric(self): self.assertEqual( bar_1_2("~~filename~~#originalyear"), u'/fakepath/2 - 2005') def test_call_numeric(self): self.failUnlessAlmostEqual(num_call("~#custom"), 0.3) self.failUnlessEqual(num_call("~#blah~foo", 0), 0) def test_list(self): for key in bar_1_1.realkeys(): self.failUnlessEqual(bar_1_1.list(key), [bar_1_1(key)]) af = AudioFile({"~filename": fsnative(u"foo")}) self.failUnlessEqual(af.list("artist"), []) self.failUnlessEqual(af.list("title"), [af("title")]) self.failUnlessEqual(af.list("not a key"), []) self.failUnlessEqual(len(bar_2_1.list("artist")), 2) self.failUnlessEqual(bar_2_1.list("artist"), bar_2_1["artist"].split("\n")) def test_list_tied_tags(self): expected = ["%s - %s" % (bar_1_1("artist"), bar_1_1("title"))] self.failUnlessEqual(bar_1_1.list("~artist~title"), expected) def test_list_multiple_tied_tags(self): expected = ["%s - %s" % (bar_2_1.comma("artist"), bar_2_1("title"))] self.failUnlessEqual(bar_2_1.list("~artist~title"), expected) def test_list_sort(self): self.failUnlessEqual(bar_1_1.list_sort("title"), [("A song", "A song")]) self.failUnlessEqual(bar_1_1.list_sort("artist"), [("Foo", "Foo")]) af = AudioFile({"~filename": fsnative(u"foo")}) self.failUnlessEqual(af.list_sort("artist"), []) self.failUnlessEqual(af.list_sort("title"), [(af("title"), af("title"))]) self.failUnlessEqual(af.list_sort("not a key"), []) self.failUnlessEqual(bar_1_2.list_sort("title"), [("Perhaps another", "Perhaps another")]) self.failUnlessEqual(bar_2_1.list_sort("artist"), [("Foo", "Foosort"), ("I have two artists", "I have two artists")]) self.failUnlessEqual(bar_2_1.list_sort("~#track"), [('1', '1')]) def test_list_sort_empty_sort(self): # we don't want to care about empty sort values, make sure we ignore # them s = AudioFile({"artist": "x\ny\nz", "artistsort": "c\n\nd"}) self.assertEqual( s.list_sort("artist"), [("x", "c"), ("y", "y"), ("z", "d")]) def test_list_sort_noexist(self): self.failUnlessEqual(bar_1_1.list_sort("nopenopenope"), []) def test_list_separate_noexist(self): self.failUnlessEqual(bar_1_1.list_separate("nopenopenope"), []) def test_list_sort_length_diff(self): s = AudioFile({"artist": "a\nb", "artistsort": "c"}) self.assertEqual(s.list_sort("artist"), [("a", "c"), ("b", "b")]) s = AudioFile({"artist": "a\nb", "artistsort": "c\nd\ne"}) self.assertEqual(s.list_sort("artist"), [("a", "c"), ("b", "d")]) s = AudioFile({"artistsort": "c\nd\ne"}) self.assertEqual(s.list_sort("artist"), []) s = AudioFile({"artist": "a\nb"}) self.assertEqual(s.list_sort("artist"), [("a", "a"), ("b", "b")]) s = AudioFile({}) self.assertEqual(s.list_sort("artist"), []) def test_list_separate(self): self.failUnlessEqual(bar_1_1.list_separate("title"), [("A song", "A song")]) self.failUnlessEqual(bar_1_1.list_separate("artist"), [("Foo", "Foo")]) self.failUnlessEqual(bar_2_1.list_separate("~artist~album"), [('Foo', 'Foosort'), ('I have two artists', 'I have two artists'), ('Bar', 'Bar')]) self.failUnlessEqual(bar_2_1.list_separate("~artist~~#track"), [('Foo', 'Foosort'), ('I have two artists', 'I have two artists'), ('1', '1')]) def test_list_list_separate_types(self): res = bar_2_1.list_separate("~~#track~artist~~filename") self.assertEqual(res, [(u'1', u'1'), (u'Foo', u'Foosort'), (u'I have two artists', u'I have two artists'), (u'/does not/exist', u'/does not/exist')]) def test_list_numeric(self): self.assertEqual(bar_1_2.list('~#bitrate'), [128]) def test_comma(self): for key in bar_1_1.realkeys(): self.failUnlessEqual(bar_1_1.comma(key), bar_1_1(key)) self.failUnless(", " in bar_2_1.comma("artist")) def test_comma_filename(self): self.assertTrue(isinstance(bar_1_1.comma("~filename"), str)) def test_comma_mountpoint(self): assert not bar_1_1("~mountpoint") assert isinstance(bar_1_1.comma("~mountpoint"), str) assert bar_1_1.comma("~mountpoint") == u"" def test_exist(self): self.failIf(bar_2_1.exists()) self.failUnless(self.quux.exists()) def test_valid(self): self.failIf(bar_2_1.valid()) quux = self.quux quux["~#mtime"] = 0 self.failIf(quux.valid()) quux["~#mtime"] = os.path.getmtime(quux["~filename"]) self.failUnless(quux.valid()) os.utime(quux["~filename"], (quux["~#mtime"], quux["~#mtime"] - 1)) self.failIf(quux.valid()) quux["~#mtime"] = os.path.getmtime(quux["~filename"]) self.failUnless(quux.valid()) os.utime(quux["~filename"], (quux["~#mtime"], quux["~#mtime"] - 1)) quux.sanitize() self.failUnless(quux.valid()) def test_can_change(self): af = AudioFile() self.failIf(af.can_change("~foobar")) self.failIf(af.can_change("=foobar")) self.failIf(af.can_change("foo=bar")) self.failIf(af.can_change("")) self.failUnless(af.can_change("foo bar")) def test_is_writable(self): fn = self.quux["~filename"] os.chmod(fn, 0o444) assert not self.quux.is_writable(), f"{fn!r} is writeable ({os.stat(fn)})" os.chmod(fn, 0o644) assert self.quux.is_writable(), f"{fn!r} is unwriteable ({os.stat(fn)})" def test_can_multiple_values(self): af = AudioFile() self.assertEqual(af.can_multiple_values(), True) self.assertTrue(af.can_multiple_values("artist")) def test_rename(self): old_fn = self.quux["~filename"] fd, new_fn = mkstemp() os.close(fd) os.unlink(new_fn) assert self.quux.exists() self.quux.rename(new_fn) assert not os.path.exists(old_fn) assert self.quux.exists() self.quux.rename(old_fn) assert not os.path.exists(new_fn) assert self.quux.exists() def test_rename_other_dir(self): old_fn = self.quux["~filename"] new_dir = mkdtemp() self.quux.rename(os.path.join(new_dir, "foo")) assert not os.path.exists(old_fn) assert self.quux.exists() self.quux.rename(old_fn) assert self.quux.exists() os.rmdir(new_dir) def test_rename_to_existing(self): self.quux.rename(self.quux("~filename")) if os.name != "nt": self.failUnlessRaises( ValueError, self.quux.rename, fsnative(u"/dev/null")) with temp_filename() as new_file: with self.assertRaises(ValueError): self.quux.rename(new_file) def test_playlists_tag(self): songs_lib = app.library pl_name = "playlist 123!" songs_lib.add([bar_1_1, bar_1_2, self.quux]) pl_lib = songs_lib.playlists pl = pl_lib.create(pl_name) pl.extend([self.quux, bar_1_1]) assert pl, "Nothing added to playlist" for song in pl: assert song("~playlists") == pl_name assert not bar_1_2("~playlists") def test_lyric_filename(self): song = AudioFile() song["~filename"] = fsnative(u"filename") self.assertTrue(isinstance(song.lyric_filename, fsnative)) song["title"] = u"Title" song["artist"] = u"Artist" self.assertTrue(isinstance(song.lyric_filename, fsnative)) song["lyricist"] = u"Lyricist" self.assertTrue(isinstance(song.lyric_filename, fsnative)) def lyric_filename_search_test_song(self, pathfile): s = AudioFile() s.sanitize(pathfile) s['artist'] = "SpongeBob SquarePants" s['title'] = "Theme Tune" return s @contextmanager def lyric_filename_test_setup(self, no_config=False): with temp_filename() as filename: s = self.lyric_filename_search_test_song(filename) root = os.path.dirname(filename) if not no_config: config.set("memory", "lyric_filenames", "<artist>.-.<title>,<artist> - <title>.lyrics_mod") config.set("memory", "lyric_rootpaths", root) s.root = root yield s if not no_config: self.lyric_filename_search_clean_config() def lyric_filename_search_clean_config(self): """reset config to ensure other tests aren't affected""" config.remove_option("memory", "lyric_rootpaths") config.remove_option("memory", "lyric_filenames") def test_lyric_filename_search_builtin_default(self): """test built-in default""" with self.lyric_filename_test_setup(no_config=True) as ts: fp = os.path.join(ts.root, ts["artist"], ts["title"] + ".lyric") p = os.path.dirname(fp) mkdir(p) with io.open(fp, "w", encoding='utf-8') as f: f.write(u"") search = unquote(ts.lyric_filename) os.remove(fp) os.rmdir(p) self.assertEqual(search, fp) def test_lyric_filename_search_builtin_default_local_path(self): """test built-in default local path""" with self.lyric_filename_test_setup(no_config=True) as ts: fp = os.path.join(ts.root, ts["artist"] + " - " + ts["title"] + ".lyric") with io.open(fp, "w", encoding='utf-8') as f: f.write(u"") search = ts.lyric_filename os.remove(fp) if is_windows(): fp = fp.lower() # account for 'os.path.normcase' santisatation search = search.lower() # compensate for the above self.assertEqual(search, fp) def test_lyric_filename_search_file_not_found(self): """test default file not found fallback""" with self.lyric_filename_test_setup() as ts: fp = os.path.join(ts.root, ts["artist"] + ".-." + ts["title"]) search = unquote(ts.lyric_filename) self.assertEqual(search, fp) def test_lyric_filename_search_custom_path(self): """test custom lyrics file location / naming""" with self.lyric_filename_test_setup() as ts: fp = os.path.join(ts.root, ts["artist"] + " - " + ts["title"] + ".lyric") with io.open(fp, "w", encoding='utf-8') as f: f.write(u"") search = ts.lyric_filename os.remove(fp) self.assertEqual(search, fp) def test_lyric_filename_search_order_priority(self): """test custom lyrics order priority""" with self.lyric_filename_test_setup() as ts: root2 = os.path.join(get_home_dir(), ".lyrics") # built-in default fp2 = os.path.join(root2, ts["artist"] + " - " + ts["title"] + ".lyric") p2 = os.path.dirname(fp2) mkdir(p2) with io.open(fp2, "w", encoding='utf-8') as f: f.write(u"") fp = os.path.join(ts.root, ts["artist"] + " - " + ts["title"] + ".lyric") with io.open(fp, "w", encoding='utf-8') as f: f.write(u"") mkdir(p2) search = ts.lyric_filename os.remove(fp2) os.rmdir(p2) os.remove(fp) self.assertEqual(search, fp) def test_lyric_filename_search_modified_extension_fallback(self): """test modified extension fallback search""" with self.lyric_filename_test_setup() as ts: fp = os.path.join(ts.root, ts["artist"] + " - " + ts["title"] + ".txt") with io.open(fp, "w", encoding='utf-8') as f: f.write(u"") search = ts.lyric_filename os.remove(fp) self.assertEqual(search, fp) def test_lyric_filename_search_special_characters(self): """test '<' and/or '>' in name (not parsed (transparent to test))""" with self.lyric_filename_test_setup(no_config=True) as ts: path_variants = ['<oldskool>'] \ if is_windows() else [r'\<artist\>', r'\<artist>', r'<artist\>'] for path_variant in path_variants: ts['artist'] = path_variant + " SpongeBob SquarePants" parts = [ts.root, ts["artist"] + " - " + ts["title"] + ".lyric"] rpf = RootPathFile(ts.root, os.path.sep.join(parts)) if not rpf.valid: rpf = RootPathFile(rpf.root, rpf.pathfile_escaped) self.assertTrue(rpf.valid, "even escaped target file is not valid") with io.open(rpf.pathfile, "w", encoding='utf-8') as f: f.write(u"") search = ts.lyric_filename os.remove(rpf.pathfile) fp = rpf.pathfile if is_windows(): # account for 'os.path.normcase' santisatation fp = fp.lower() search = search.lower() # compensate for the above self.assertEqual(search, fp) def test_lyric_filename_search_special_characters_across_path(self): """test '<' and/or '>' in name across path separator (not parsed (transparent to test))""" with self.lyric_filename_test_setup(no_config=True) as ts: # test '<' and '>' in name across path # (not parsed (transparent to test)) ts['artist'] = "a < b" ts['title'] = "b > a" parts = [ts.root, ts["artist"], ts["title"] + ".lyric"] rpf = RootPathFile(ts.root, os.path.sep.join(parts)) rootp = ts.root rmdirs = [] # ensure valid dir existence for p in rpf.end.split(os.path.sep)[:-1]: rootp = os.path.sep.join([ts.root, p]) if not RootPathFile(ts.root, rootp).valid: rootp = os.path.sep.join([ts.root, escape_filename(p)]) self.assertTrue(RootPathFile(ts.root, rootp).valid, "even escaped target dir part is not valid!") if not os.path.exists(rootp): mkdir(rootp) rmdirs.append(rootp) if not rpf.valid: rpf = RootPathFile(rpf.root, rpf.pathfile_escaped) with io.open(rpf.pathfile, "w", encoding='utf-8') as f: f.write(u"") # search for lyric file search = ts.lyric_filename # clean up test lyric file / path os.remove(rpf.pathfile) for p in rmdirs: os.rmdir(p) # test whether the 'found' file is the test lyric file fp = rpf.pathfile if is_windows(): fp = fp.lower() # account for 'os.path.normcase' santisatation search = search.lower() # compensate for the above self.assertEqual(search, fp) def test_lyrics_from_file(self): with temp_filename() as filename: af = AudioFile(artist='Motörhead', title='this: again') af.sanitize(filename) lyrics = "blah!\nblasé 😬\n" lyrics_dir = os.path.dirname(af.lyric_filename) mkdir(lyrics_dir) with io.open(af.lyric_filename, "w", encoding='utf-8') as lf: lf.write(str(lyrics)) self.failUnlessEqual(af("~lyrics").splitlines(), lyrics.splitlines()) os.remove(af.lyric_filename) os.rmdir(lyrics_dir) def test_lyrics_mp3_is_not_a_valid_lyrics_file(self): # https://github.com/quodlibet/quodlibet/issues/3395 fn = get_data_path('silence-44-s.mp3') with temp_filename() as filename: af = AudioFile(artist='bar', title='foo') af.sanitize(filename) lyrics_dir = os.path.dirname(af.lyric_filename) mkdir(lyrics_dir) try: with open(af.lyric_filename, "wb") as target: with open(fn, "rb") as source: target.write(source.read()) assert "\0" not in af("~lyrics") finally: shutil.rmtree(lyrics_dir) def test_unsynced_lyrics(self): song = AudioFile() song["unsyncedlyrics"] = "lala" assert song("~lyrics") == "lala" assert song("unsyncedlyrics") == "lala" assert song("lyrics") != "lala" def test_mountpoint(self): song = AudioFile() song["~filename"] = fsnative(u"filename") song.sanitize() assert isinstance(song["~mountpoint"], fsnative) assert isinstance(song.comma("~mointpoint"), str) def test_sanitize(self): q = AudioFile(self.quux) b = AudioFile(bar_1_1) q.sanitize() b.pop('~filename') self.failUnlessRaises(ValueError, b.sanitize) n = AudioFile({"artist": u"foo\0bar", "title": u"baz\0", "~filename": fsnative(u"whatever")}) n.sanitize() self.failUnlessEqual(n["artist"], "foo\nbar") self.failUnlessEqual(n["title"], "baz") def test_performers(self): q = AudioFile([("performer:vocals", "A"), ("performer:guitar", "B"), ("performer", "C")]) self.failUnlessEqual(set(q.list("~performers")), {"A", "B", "C"}) self.failUnlessEqual(set(q.list("~performers:roles")), {"A (Vocals)", "B (Guitar)", "C"}) def test_performers_multi_value(self): q = AudioFile([ ("performer:vocals", "X\nA\nY"), ("performer:guitar", "Y\nB\nA"), ("performer", "C\nB\nA"), ]) self.failUnlessEqual( set(q.list("~performer")), {"A", "B", "C", "X", "Y"}) self.failUnlessEqual( set(q.list("~performer:roles")), { "A (Guitar, Vocals)", "C", "B (Guitar)", "X (Vocals)", "Y (Guitar, Vocals)", }) def test_people(self): q = AudioFile([("performer:vocals", "A"), ("performer:guitar", "B"), ("performer", "C"), ("arranger", "A"), ("albumartist", "B"), ("artist", "C")]) self.failUnlessEqual(q.list("~people"), ["C", "B", "A"]) self.failUnlessEqual(q.list("~people:roles"), ["C (Performance)", "B (Guitar)", "A (Arrangement, Vocals)"]) def test_people_mix(self): q = AudioFile([ ("performer:arrangement", "A"), ("arranger", "A"), ("performer", "A"), ("performer:foo", "A"), ]) self.failUnlessEqual(q.list("~people"), ["A"]) self.failUnlessEqual(q.list("~people:roles"), ["A (Arrangement, Arrangement, Foo, Performance)"]) def test_people_multi_value(self): q = AudioFile([ ("arranger", "A\nX"), ("performer", "A\nY"), ("performer:foo", "A\nX"), ]) self.failUnlessEqual(q.list("~people"), ["A", "Y", "X"]) self.failUnlessEqual(q.list("~people:roles"), ["A (Arrangement, Foo, Performance)", "Y (Performance)", "X (Arrangement, Foo)"]) def test_people_individuals(self): q = AudioFile({"artist": "A\nX", "albumartist": "Various Artists"}) self.failUnlessEqual(q.list("~people:real"), ["A", "X"]) lonely = AudioFile({"artist": "various artists", "title": "blah"}) self.failUnlessEqual(lonely.list("~people:real"), ["various artists"]) lots = AudioFile({"artist": "Various Artists", "albumartist": "V.A."}) self.failUnlessEqual(lots.list("~people:real"), ["Various Artists"]) def test_peoplesort(self): q = AudioFile([("performer:vocals", "The A"), ("performersort:vocals", "A, The"), ("performer:guitar", "The B"), ("performersort:guitar", "B, The"), ("performer", "The C"), ("performersort", "C, The"), ("albumartist", "The B"), ("albumartistsort", "B, The")]) self.failUnlessEqual(q.list("~peoplesort"), ["B, The", "C, The", "A, The"]) self.failUnlessEqual(q.list("~peoplesort:roles"), ["B, The (Guitar)", "C, The (Performance)", "A, The (Vocals)"]) def test_blank_tag_handling_comma(self): q = AudioFile([("title", "A\n"), ("artists", "A\n\nB\n")]) self.failUnlessEqual(q.comma("artists"), "A, B") self.failUnlessEqual(q.comma("~title~version"), "A") def test_blank_tag_handling_list(self): q = AudioFile([("artist", "A\n\nB\n"), ("performer", ""), ("albumartist", "C")]) self.failUnlessEqual(q.list("performer"), []) self.failUnlessEqual(q.list("~people"), ["A", "B", "C"]) def test_blank_tag_handling_list_sort(self): q = AudioFile([("artist", "A\n\nB"), ("artistsort", "\n\nY")]) self.failUnlessEqual(q.list_sort("artist"), [("A", "A"), ("B", "Y")]) q = AudioFile([("artist", "A\n\nB"), ("artistsort", "X\nY")]) self.failUnlessEqual(q.list_sort("artist"), [("A", "X"), ("B", "B")]) def test_to_dump(self): dump = bar_1_1.to_dump() num = len(set(bar_1_1.keys()) | NUMERIC_ZERO_DEFAULT) self.failUnlessEqual(dump.count(b"\n"), num + 2) for key, value in bar_1_1.items(): self.failUnless(key.encode("utf-8") in dump) self.failUnless(value.encode("utf-8") in dump) for key in NUMERIC_ZERO_DEFAULT: self.failUnless(key.encode("utf-8") in dump) n = AudioFile() n.from_dump(dump) self.failUnless( set(dump.split(b"\n")) == set(n.to_dump().split(b"\n"))) def test_to_dump_unicode(self): b = AudioFile(bar_1_1) b[u"öäü"] = u"öäü" dump = b.to_dump() n = AudioFile() n.from_dump(dump) self.assertEqual(n[u"öäü"], u"öäü") def test_add(self): song = AudioFile() self.failIf("foo" in song) song.add("foo", "bar") self.failUnlessEqual(song["foo"], "bar") song.add("foo", "another") self.failUnlessEqual(song.list("foo"), ["bar", "another"]) def test_remove(self): song = AudioFile() song.add("foo", "bar") song.add("foo", "another") song.add("foo", "one more") song.remove("foo", "another") self.failUnlessEqual(song.list("foo"), ["bar", "one more"]) song.remove("foo", "bar") self.failUnlessEqual(song.list("foo"), ["one more"]) song.remove("foo", "one more") self.failIf("foo" in song) def test_remove_unknown(self): song = AudioFile() song.add("foo", "bar") song.remove("foo", "not in list") song.remove("nope") self.failUnlessEqual(song.list("foo"), ["bar"]) def test_remove_all(self): song = AudioFile() song.add("foo", "bar") song.add("foo", "another") song.add("foo", "one more") song.remove("foo") self.assertFalse("foo" in song) def test_remove_empty(self): song = AudioFile() song.add("foo", u"") song.remove("foo", u"") self.assertFalse("foo" in song) def test_change(self): song = AudioFile() song.add("foo", "bar") song.add("foo", "another") song.change("foo", "bar", "one more") self.failUnlessEqual(song.list("foo"), ["one more", "another"]) song.change("foo", "does not exist", "finally") self.failUnlessEqual(song["foo"], "finally") song.change("foo", "finally", "we're done") self.failUnlessEqual(song["foo"], "we're done") def test_bookmarks_none(self): self.failUnlessEqual([], AudioFile().bookmarks) def test_bookmarks_simple(self): af = AudioFile({"~bookmark": "1:20 Mark 1"}) self.failUnlessEqual([(80, "Mark 1")], af.bookmarks) def test_bookmarks_two(self): af = AudioFile({"~bookmark": "1:40 Mark 2\n1:20 Mark 1"}) self.failUnlessEqual([(80, "Mark 1"), (100, "Mark 2")], af.bookmarks) def test_bookmark_invalid(self): af = AudioFile({"~bookmark": ("Not Valid\n1:40 Mark 2\n" "-20 Not Valid 2\n1:20 Mark 1")}) self.failUnlessEqual( [(80, "Mark 1"), (100, "Mark 2"), (-1, "Not Valid"), (-1, "-20 Not Valid 2")], af.bookmarks) def test_set_bookmarks_none(self): af = AudioFile({"bookmark": "foo"}) af.bookmarks = [] self.failUnlessEqual([], AudioFile().bookmarks) self.failIf("~bookmark" in af) def test_set_bookmarks_simple(self): af = AudioFile() af.bookmarks = [(120, "A mark"), (140, "Mark twain")] self.failUnlessEqual(af["~bookmark"], "2:00 A mark\n2:20 Mark twain") def test_set_bookmarks_invalid_value(self): self.failUnlessRaises( ValueError, setattr, AudioFile(), 'bookmarks', "huh?") def test_set_bookmarks_invalid_time(self): self.failUnlessRaises( TypeError, setattr, AudioFile(), 'bookmarks', [("notint", "!")]) def test_set_bookmarks_unrealistic_time(self): self.failUnlessRaises( ValueError, setattr, AudioFile(), 'bookmarks', [(-1, "!")]) def test_has_rating(self): song = AudioFile() self.assertFalse(song.has_rating) song["~#rating"] = 0.5 self.assertTrue(song.has_rating) song.remove_rating() self.assertFalse(song.has_rating) def test_remove_rating(self): song = AudioFile() self.assertFalse(song.has_rating) song.remove_rating() self.assertFalse(song.has_rating) song["~#rating"] = 0.5 self.assertTrue(song.has_rating) song.remove_rating() self.assertFalse(song.has_rating) def test_album_key(self): album_key_tests = [ ({}, ('', (), ())), ({'album': 'foo'}, ('', ('foo',), ())), ({'labelid': 'foo'}, ('foo', (), ())), ({'musicbrainz_albumid': 'foo'}, ('foo', (), ())), ({'album': 'foo', 'labelid': 'bar'}, ('bar', ('foo',), ())), ({'album': 'foo', 'labelid': 'bar', 'musicbrainz_albumid': 'quux'}, ('bar', ('foo',), ())), ({'albumartist': 'a'}, ('', (), ('a',))), ] for tags, expected in album_key_tests: afile = AudioFile(**tags) afile.sanitize(fsnative(u'/dir/fn')) self.failUnlessEqual(afile.album_key, expected) def test_eq_ne(self): self.failIf(AudioFile({"a": "b"}) == AudioFile({"a": "b"})) self.failUnless(AudioFile({"a": "b"}) != AudioFile({"a": "b"})) def test_invalid_fs_encoding(self): # issue 798 a = AudioFile() if os.name != "nt": a["~filename"] = "/\xf6\xe4\xfc/\xf6\xe4\xfc.ogg" # latin 1 encoded a.sort_by_func("~filename")(a) a.sort_by_func("~basename")(a) else: # windows a["~filename"] = \ b"/\xf6\xe4\xfc/\xf6\xe4\xfc.ogg".decode("latin-1") a.sort_by_func("~filename")(a) a.sort_by_func("~basename")(a) a.sort_by_func("~dirname")(a) def test_sort_key_defaults(self): AF = AudioFile assert AF().sort_key == AF({"tracknumber": "0"}).sort_key assert AF().sort_key != AF({"tracknumber": "1/1"}).sort_key assert AF().sort_key < AF({"tracknumber": "2/2"}).sort_key assert AF().sort_key == AF({"discnumber": "0"}).sort_key assert AF().sort_key != AF({"discnumber": "1/1"}).sort_key assert AF().sort_key < AF({"discnumber": "2/2"}).sort_key def test_sort_cache(self): copy = AudioFile(bar_1_1) sort_1 = tuple(copy.sort_key) copy["title"] = copy["title"] + "something" sort_2 = tuple(copy.sort_key) self.failIfEqual(sort_1, sort_2) album_sort_1 = tuple(copy.album_key) copy["album"] = copy["album"] + "something" sort_3 = tuple(copy.sort_key) self.failIfEqual(sort_2, sort_3) album_sort_2 = tuple(copy.album_key) self.failIfEqual(album_sort_1, album_sort_2) def test_cache_attributes(self): x = AudioFile() x.multisong = not x.multisong x["a"] = "b" # clears cache # attribute should be unchanged self.failIfEqual(AudioFile().multisong, x.multisong) def test_sort_func(self): tags = [lambda s: s("foo"), "artistsort", "albumsort", "~filename", "~format", "discnumber", "~#track"] for tag in tags: f = AudioFile.sort_by_func(tag) f(bar_1_1) f(bar_1_2) f(bar_2_1) def test_sort_func_custom_numeric(self): func = AudioFile.sort_by_func("~#year") files = [AudioFile({"year": "nope"}), AudioFile({"date": "2038"})] assert sorted(files, key=func) == files def test_uri(self): # On windows where we have unicode paths (windows encoding is utf-16) # we need to encode to utf-8 first, then escape. # On linux we take the byte stream and escape it. # see g_filename_to_uri if os.name == "nt": f = AudioFile({"~filename": u"/\xf6\xe4.mp3", "title": "win"}) self.failUnlessEqual(f("~uri"), "file:///%C3%B6%C3%A4.mp3") else: f = AudioFile({ "~filename": bytes2fsn(b"/\x87\x12.mp3", None), "title": "linux", }) self.failUnlessEqual(f("~uri"), "file:///%87%12.mp3") def test_reload(self): audio = MusicFile(get_data_path('silence-44-s.mp3')) audio["title"] = u"foo" audio.reload() self.assertNotEqual(audio.get("title"), u"foo") def test_reload_externally_modified(self): config.set("editing", "save_to_songs", True) fn = self.quux("~filename") + ".mp3" shutil.copy(get_data_path('silence-44-s.mp3'), fn) orig = MusicFile(fn) copy = MusicFile(fn) orig["~#rating"] = SOME_RATING copy["~#rating"] = ANOTHER_RATING orig.write() orig.reload() copy.reload() # should pick up the change to the file assert orig("~#rating") == SOME_RATING, "reloading failed" assert copy("~#rating") == SOME_RATING, "should have picked up external change" def test_reload_fail(self): audio = MusicFile(get_data_path('silence-44-s.mp3')) audio["title"] = u"foo" audio.sanitize(fsnative(u"/dev/null")) self.assertRaises(AudioFileError, audio.reload) self.assertEqual(audio["title"], u"foo") class TAudioFormats(TestCase): def setUp(self): with temp_filename() as filename: self.filename = filename def test_load_non_exist(self): for t in format_types: if not t.is_file: continue self.assertRaises(AudioFileError, t, self.filename) def test_write_non_existing(self): for t in format_types: if not t.is_file: continue instance = AudioFile.__new__(t) instance.sanitize(self.filename) try: instance.write() except AudioFileError: pass def test_reload_non_existing(self): for t in format_types: if not t.is_file: continue instance = AudioFile.__new__(t) instance.sanitize(self.filename) try: instance.reload() except AudioFileError: pass class Tdecode_value(TestCase): def test_main(self): self.assertEqual(decode_value("~#foo", 0.25), u"0.25") self.assertEqual(decode_value("~#foo", 4), u"4") self.assertEqual(decode_value("~#foo", "bar"), u"bar") self.assertTrue(isinstance(decode_value("~#foo", "bar"), str)) path = fsnative(u"/foobar") self.assertEqual(decode_value("~filename", path), fsn2text(path)) def test_path(self): try: path = bytes2fsn(b"\xff\xff", "utf-8") except ValueError: return assert decode_value("~filename", path) == fsn2text(path) class Treplay_gain(TestCase): # -6dB is approximately equal to half magnitude minus_6db = 0.501187234 def setUp(self): self.rg_data = {"replaygain_album_gain": "-1.00 dB", "replaygain_album_peak": "1.1", "replaygain_track_gain": "+1.0000001 dB", "replaygain_track_peak": "0.9"} self.song = AudioFile(self.rg_data) self.no_rg_song = AudioFile() def test_large(self): rg_data = {"replaygain_track_gain": "9999999 dB"} song = AudioFile(rg_data) assert song.replay_gain(["track"], 0, 0) == 1.0 assert song.replay_gain([], 0, 99999999999) == 1.0 def test_no_rg_song(self): scale = self.no_rg_song.replay_gain(["track"], 0, -6.0) self.failUnlessAlmostEqual(scale, self.minus_6db) scale = self.no_rg_song.replay_gain(["track"], +10, +10) self.failUnlessEqual(scale, 1.0) scale = self.no_rg_song.replay_gain(["track"], -16.0, +10) self.failUnlessAlmostEqual(scale, self.minus_6db) def test_nogain(self): self.failUnlessEqual(self.song.replay_gain(["none", "track"]), 1) def test_fallback_track(self): del(self.song["replaygain_track_gain"]) self.failUnlessAlmostEqual( self.song.replay_gain(["track"], 0, -6.0), self.minus_6db) def test_fallback_album(self): del(self.song["replaygain_album_gain"]) self.failUnlessAlmostEqual( self.song.replay_gain(["album"], 0, -6.0), self.minus_6db) def test_fallback_and_preamp(self): del(self.song["replaygain_track_gain"]) self.failUnlessEqual(self.song.replay_gain(["track"], 9, -9), 1) def test_preamp_track(self): self.failUnlessAlmostEqual( self.song.replay_gain(["track"], -7.0, 0), self.minus_6db) def test_preamp_album(self): self.failUnlessAlmostEqual( self.song.replay_gain(["album"], -5.0, 0), self.minus_6db) def test_preamp_clip(self): # Make sure excess pre-amp won't clip a track (with peak data) self.failUnlessAlmostEqual( self.song.replay_gain(["track"], 12.0, 0), 1.0 / 0.9) def test_trackgain(self): self.failUnless(self.song.replay_gain(["track"]) > 1) def test_albumgain(self): self.failUnless(self.song.replay_gain(["album"]) < 1) def test_invalid(self): self.song["replaygain_album_gain"] = "fdsodgbdf" self.failUnlessEqual(self.song.replay_gain(["album"]), 1) def test_track_fallback(self): radio_rg = self.song.replay_gain(["track"]) del(self.song["replaygain_album_gain"]) del(self.song["replaygain_album_peak"]) # verify defaulting to track when album is present self.failUnlessAlmostEqual( self.song.replay_gain(["album", "track"]), radio_rg) def test_numeric_rg_tags(self): """Tests fully-numeric (ie no "db") RG tags. See Issue 865""" self.failUnless(self.song("replaygain_album_gain"), "-1.00 db") for key, exp in self.rg_data.items(): # Hack the nasties off and produce the "real" expected value exp = float(exp.split(" ")[0]) # Compare as floats. Seems fairer. album_rg = self.song("~#%s" % key) try: val = float(album_rg) except ValueError: self.fail("Invalid %s returned: %s" % (key, album_rg)) self.failUnlessAlmostEqual( val, exp, places=5, msg="%s should be %s not %s" % (key, exp, val)) def test_human_time_tags(self): now = int(time.time()) tags = {t: now for t in TIME_TAGS} tags["~filename"] = "/dev/null" af = AudioFile(tags) for t in TIME_TAGS: assert af(t) == now, "Numeric dates broken" assert af(t.replace("~#", "~")) == format_date(now), "Human date broken" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats__id3.py����������������������������������������������������������0000664�0001750�0001750�00000061407�14231604332�017337� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path import os from io import BytesIO from quodlibet import const from quodlibet.formats._image import EmbeddedImage from quodlibet.formats.mp3 import MP3File from quodlibet.formats.aiff import AIFFFile import mutagen from .helper import get_temp_copy class TID3ImagesBase(TestCase): KIND = None PATH = None def setUp(self): self.filename = get_temp_copy(self.PATH) def tearDown(self): os.remove(self.filename) class TID3ImagesMixin: def test_can_change_images(self): self.failUnless(self.KIND(self.filename).can_change_images) def test_get_primary_image(self): self.failIf(self.KIND(self.filename).has_images) f = mutagen.File(self.filename) apic = mutagen.id3.APIC(encoding=3, mime="image/jpeg", type=4, desc="foo", data=b"bar") f.tags.add(apic) f.save() song = self.KIND(self.filename) self.failUnless(song.has_images) image = song.get_primary_image() self.assertEqual(image.mime_type, "image/jpeg") fn = image.file self.failUnlessEqual(fn.read(), b"bar") apic = mutagen.id3.APIC(encoding=3, mime="image/jpeg", type=3, desc="xx", data=b"bar2") f.tags.add(apic) f.save() song = self.KIND(self.filename) self.failUnless(song.has_images) image = song.get_primary_image() self.failUnlessEqual(image.read(), b"bar2") # get_images() images = song.get_images() self.assertTrue(images and len(images) == 2) self.assertEqual(images[0].type, 3) self.assertEqual(images[1].type, 4) def test_clear_images(self): f = mutagen.File(self.filename) apic = mutagen.id3.APIC(encoding=3, mime="image/jpeg", type=4, desc="foo", data=b"bar") f.tags.add(apic) f.save() song = self.KIND(self.filename) self.failUnless(song.has_images) song.clear_images() song = self.KIND(self.filename) self.assertFalse(song.has_images) def test_set_image(self): fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) song = self.KIND(self.filename) self.failIf(song.has_images) song.set_image(image) self.assertTrue(song.has_images) song = self.KIND(self.filename) self.assertTrue(song.has_images) self.assertEqual(song.get_primary_image().mime_type, "image/jpeg") def test_set_image_no_tag(self): f = mutagen.File(self.filename) f.delete() song = self.KIND(self.filename) fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) song.set_image(image) song = self.KIND(self.filename) self.assertTrue(song.has_images) class TID3ImagesMP3(TID3ImagesBase, TID3ImagesMixin): KIND = MP3File PATH = get_data_path('silence-44-s.mp3') class TID3ImagesAIFF(TID3ImagesBase, TID3ImagesMixin): KIND = AIFFFile PATH = get_data_path('test.aiff') class TID3FileBase(TestCase): KIND = None PATH = None def setUp(self): self.filename = get_temp_copy(self.PATH) def tearDown(self): os.unlink(self.filename) class TID3FileMixin: def test_optional_POPM_count(self): # https://github.com/quodlibet/quodlibet/issues/364 f = mutagen.File(self.filename) f.tags.add(mutagen.id3.POPM(const.EMAIL, 42)) try: f.save() except TypeError: # https://github.com/quodlibet/quodlibet/issues/33 pass else: self.KIND(self.filename) def test_write_empty_replaygain_track_gain(self): f = self.KIND(self.filename) f["replaygain_track_gain"] = "" f.write() f.reload() assert f.replay_gain(["track"]) == 1.0 def test_TXXX_DATE(self): # https://github.com/quodlibet/quodlibet/issues/220 f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TXXX(encoding=3, desc=u'DATE', text=u'2010-01-13')) f.tags.add(mutagen.id3.TDRC(encoding=3, text=u'2010-01-14')) f.save() self.assertEquals(self.KIND(self.filename)['date'], '2010-01-14') f.tags.delall('TDRC') f.save() self.assertEquals(self.KIND(self.filename)['date'], '2010-01-13') f.delete() self.KIND(self.filename) def test_USLT(self): """Tests reading and writing of lyrics in USLT""" f = mutagen.File(self.filename) f.tags.add(mutagen.id3.USLT(encoding=3, desc=u'', lang='\x00\x00\x00', text=u'lyrics')) f.tags.add(mutagen.id3.USLT(encoding=3, desc=u'desc', lang='\x00\x00\x00', text=u'lyrics with non-empty desc')) f.tags.add(mutagen.id3.USLT(encoding=3, desc=u'', lang='xyz', text=u'lyrics with non-empty lang')) f.save() f = mutagen.File(self.filename) self.failUnlessEqual(f.tags[u'USLT::\x00\x00\x00'], u'lyrics') self.failUnlessEqual(f.tags[u'USLT:desc:\x00\x00\x00'], u'lyrics with non-empty desc') self.failUnlessEqual(f.tags[u'USLT::xyz'], u'lyrics with non-empty lang') f = self.KIND(self.filename) self.failUnlessEqual(sorted(f['lyrics'].split('\n')), sorted([u'lyrics', u'lyrics with non-empty lang', u'lyrics with non-empty desc'])) # multiple USLT tags are not supported so the behavior seems random self.assertIn(f['~lyricsdescription'], [u'desc', u'']) self.assertIn(f['~lyricslanguage'], [u'xyz', u'']) f['lyrics'] = u'modified lyrics' f['~lyricsdescription'] = u'' f.write() f = self.KIND(self.filename) self.assertEqual(f['lyrics'], u'modified lyrics') self.assertEqual(f['~lyricsdescription'], u'') # languages were invalid regarding ISO_639_2 → *und*efined is written self.assertEqual(f['~lyricslanguage'], u'und') f['lyrics'] = u'modified lyrics\nwith two lines' f['~lyricsdescription'] = u'desc' f['~lyricslanguage'] = u'eng' f.write() f = self.KIND(self.filename) self.assertEqual(f['lyrics'], u'modified lyrics\nwith two lines') self.assertEqual(f['~lyricsdescription'], u'desc') self.assertEqual(f['~lyricslanguage'], u'eng') del f['lyrics'] f.write() f = mutagen.File(self.filename) self.failIf('USLT' in f.tags, 'There should be no USLT tag when lyrics were deleted') f = self.KIND(self.filename) self.failIf('lyrics' in f, 'There should be no lyrics key when there is no USLT') def test_lang_read(self): """Tests reading of language from TXXX""" # https://github.com/quodlibet/quodlibet/issues/439 f = mutagen.File(self.filename) try: lang = u'free-text' f.tags.add( mutagen.id3.TXXX(encoding=3, desc=u'QuodLibet::language', text=lang)) f.save() self.assertEquals(self.KIND(self.filename)['language'], lang) finally: f.delete() def test_lang_read_TLAN(self): """Tests reading language from TLAN""" f = mutagen.File(self.filename) lang = u'eng' try: f.tags.add(mutagen.id3.TLAN(encoding=3, text=lang)) f.save() self.assertEquals(self.KIND(self.filename)['language'], lang) finally: f.delete() def test_lang_read_multiple_TLAN(self): """Tests reading multiple language from TLAN""" f = mutagen.File(self.filename) # Include an invalid one; current behaviour is to load anyway lang = u'eng\0der\0fra\0fooooo' exp = u'eng\nder\nfra\nfooooo' try: f.tags.add(mutagen.id3.TLAN(encoding=3, text=lang)) f.save() self.assertEquals(self.KIND(self.filename)['language'], exp) finally: f.delete() def test_write_lang_freetext(self): """Tests that if you don't use an ISO 639-2 code, TXXX gets populated """ af = self.KIND(self.filename) for val in ["free-text", "foo", "de", "en"]: af["language"] = val # Just checking... self.failUnlessEqual(af("language"), val) af.write() tags = mutagen.File(self.filename).tags self.failUnlessEqual(tags[u'TXXX:QuodLibet::language'], val) self.failIf("TLAN" in tags) def test_write_lang_iso(self): """Tests that if you use an ISO 639-2 code, TLAN gets populated""" for iso_lang in ['eng', 'ger', 'zho']: af = self.KIND(self.filename) af["language"] = iso_lang self.failUnlessEqual(af("language"), iso_lang) af.write() tags = mutagen.File(self.filename).tags self.failIf(u'TXXX:QuodLibet::language' in tags, "Should have used TLAN tag for '%s'" % iso_lang) self.failUnlessEqual(tags[u'TLAN'], iso_lang) af.clear() def test_write_multiple_lang_iso(self): """Tests using multiple ISO 639-2 codes""" iso_langs = ['eng', 'ger', 'zho'] iso_langs_str = "\n".join(iso_langs) af = self.KIND(self.filename) af["language"] = iso_langs_str self.failUnlessEqual(af("language"), iso_langs_str) af.write() tags = mutagen.File(self.filename).tags self.failIf(u'TXXX:QuodLibet::language' in tags, "Should have used TLAN for %s" % iso_langs) self.failUnlessEqual(tags[u'TLAN'], iso_langs, msg="Wrong tags: %s" % tags) af.clear() def test_ignore_tlen(self): f = mutagen.File(self.filename) f.tags.delall("TLEN") f.save() length = self.KIND(self.filename)("~#length") for value in ["20000", "0", "x"]: f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TLEN(encoding=0, text=[value])) f.save() self.assertAlmostEqual( self.KIND(self.filename)("~#length"), length, 2) def test_load_tcon(self): # check if the mutagen preprocessing is used f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TCON(encoding=3, text=["4", "5"])) f.save() genres = set(self.KIND(self.filename).list("genre")) self.failUnlessEqual(genres, {"Funk", "Disco"}) def test_mb_track_id(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.UFID(owner="http://musicbrainz.org", data=b"x")) f.save() song = self.KIND(self.filename) self.failUnlessEqual(song("musicbrainz_trackid"), "x") song["musicbrainz_trackid"] = "y" song.write() f = mutagen.File(self.filename) self.failUnlessEqual(f.tags["UFID:http://musicbrainz.org"].data, b"y") del song["musicbrainz_trackid"] song.write() f = mutagen.File(self.filename) self.failIf(f.tags.get("UFID:http://musicbrainz.org")) def test_mb_release_track_id(self): f = mutagen.File(self.filename) f.tags.add( mutagen.id3.TXXX(encoding=3, desc=u"MusicBrainz Release Track Id", text=["bla"])) f.save() song = self.KIND(self.filename) self.assertEqual(song["musicbrainz_releasetrackid"], u"bla") song["musicbrainz_releasetrackid"] = u"foo" song.write() f = mutagen.File(self.filename) frames = f.tags.getall("TXXX:MusicBrainz Release Track Id") self.assertTrue(frames) self.assertEqual(frames[0].text, [u"foo"]) def test_load_comment(self): # comm with empty descriptions => comment f = mutagen.File(self.filename) f.tags.add(mutagen.id3.COMM(encoding=3, lang="aar", desc="", text=["foo", "bar"])) f.save() comments = set(self.KIND(self.filename).list("comment")) self.failUnlessEqual(comments, {"bar", "foo"}) def test_foobar2k_replaygain(self): # foobar2k saved gain there f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="replaygain_track_gain", text=["-6 db"])) f.save() song = self.KIND(self.filename) self.failIfAlmostEqual(song.replay_gain(["track"]), 1.0, 1) # check if all keys are str for k in self.KIND(self.filename).keys(): self.failUnless(isinstance(k, str)) # remove value, save, reload and check if still gone del song["replaygain_track_gain"] song.write() song.reload() self.failUnlessAlmostEqual(song.replay_gain(["track"]), 1.0, 1) def test_foobar2k_replaygain_read_new(self): # Others don't like RVA2, so we have to read/write foobar style # https://github.com/quodlibet/quodlibet/issues/1027 f = mutagen.File(self.filename) # use RVA2 in case it's the only one f.tags.add(mutagen.id3.RVA2(desc="track", channel=1, gain=-9, peak=1.0)) f.save() song = self.KIND(self.filename) self.failUnlessAlmostEqual(song.replay_gain(["track"]), 0.35, 1) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="replaygain_track_gain", text=["-6 db"])) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="replaygain_track_peak", text=["0.9"])) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="replaygain_album_gain", text=["3 db"])) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="replaygain_album_peak", text=["0.8"])) f.save() song = self.KIND(self.filename) self.failUnlessEqual(song("replaygain_track_gain"), "-6 db") self.failUnlessEqual(song("replaygain_track_peak"), "0.9") self.failUnlessEqual(song("replaygain_album_gain"), "3 db") self.failUnlessEqual(song("replaygain_album_peak"), "0.8") def test_foobar2k_replaygain_write_new(self): # Others don't like RVA2, so we have to read/write foobar style # https://github.com/quodlibet/quodlibet/issues/1027 song = self.KIND(self.filename) song["replaygain_track_gain"] = "-6 db" song["replaygain_track_peak"] = "0.9" song["replaygain_album_gain"] = "3 db" song["replaygain_album_peak"] = "0.8" song.write() f = mutagen.File(self.filename) for k in ["track_peak", "track_gain", "album_peak", "album_gain"]: self.failUnless(f[f"TXXX:REPLAYGAIN_{k.upper()}"]) def test_foobar2k_rg_caseinsensitive(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="REPLAYGAIN_TRACK_GAIN", text=["-6 db"])) f.save() song = self.KIND(self.filename) self.failUnlessEqual(song("replaygain_track_gain"), "-6 db") song.write() f = mutagen.File(self.filename) frames = f.tags.getall("TXXX:REPLAYGAIN_TRACK_GAIN") self.assertTrue(frames) self.assertEqual(frames[0].desc, "REPLAYGAIN_TRACK_GAIN") del song["replaygain_track_gain"] song.write() f = mutagen.File(self.filename) self.assertFalse(f.tags.getall("TXXX:REPLAYGAIN_TRACK_GAIN")) def test_quodlibet_txxx_inval(self): # This shouldn't happen in our namespace, but check anyway since # we might open the whole TXXX namespace sometime f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="QuodLibet::valid", text=["quux"])) f.tags.add(mutagen.id3.TXXX(encoding=3, desc="QuodLibet::foo=", text=["quux", "bar"])) f.tags.add(mutagen.id3.COMM(encoding=3, desc=u"QuodLibet::öäü", text=["quux", "bar"], lang="aar")) f.tags.add(mutagen.id3.COMM(encoding=3, desc=u"", text=["a"], lang="aar")) f.tags.add(mutagen.id3.COMM(encoding=3, desc=u"", text=["b"], lang="foo")) f.save() # check if all keys are valid for k in self.KIND(self.filename).keys(): self.failUnless(isinstance(k, str)) song = self.KIND(self.filename) self.failIf("foo=" in song) self.failIf(u"öäü" in song) self.failUnlessEqual(set(song.list("comment")), {"a", "b"}) self.failUnlessEqual(song("valid"), "quux") del song["valid"] song.write() f = mutagen.File(self.filename) self.failUnless(f.tags.getall("TXXX:QuodLibet::foo=")) self.failIf(f.tags.getall("TXXX:QuodLibet::valid")) self.failUnlessEqual(len(f.tags.getall("COMM")), 2) self.failUnlessEqual(len(f.tags.getall("COMM:")), 1) def test_old_comm_to_txxx(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.COMM(encoding=3, desc=u"QuodLibet::foo", text=["a"], lang="aar")) f.save() song = self.KIND(self.filename) self.failUnlessEqual(song("foo"), "a") song.write() f = mutagen.File(self.filename) self.failUnlessEqual(f["TXXX:QuodLibet::foo"].text, ["a"]) def test_txxx_others(self): f = mutagen.File(self.filename) t1 = mutagen.id3.TXXX(encoding=3, desc="FooBar::invalid", text="quux") t2 = mutagen.id3.TXXX(encoding=3, desc="FooBar::öäü", text="bar") f.tags.add(t1) f.tags.add(t2) f.save() song = self.KIND(self.filename) self.failIf("invalid" in song) self.failIf(u"öäü" in song) song.write() f = mutagen.File(self.filename) self.failUnless(f[t1.HashKey]) self.failUnless(f[t2.HashKey]) def test_woar(self): f = mutagen.File(self.filename) t1 = mutagen.id3.WOAR(url="http://this.is.a.test") f.tags.add(t1) f.save() song = self.KIND(self.filename) self.failUnlessEqual(song("website"), t1.url) song["website"] = "http://another.test\nhttp://omg.another.one" song.write() f = mutagen.File(self.filename) self.failUnlessEqual(len(f.tags.getall("WOAR")), 2) def test_unhandled(self): f = mutagen.File(self.filename) t1 = mutagen.id3.AENC(owner="x", preview_start=1, preview_length=3) f.tags.add(t1) f.save() self.KIND(self.filename) def test_encoding(self): song = self.KIND(self.filename) song["foo"] = u"öäü" song["bar"] = u"abc" song["comment"] = u"öäü" song["artist"] = u"xyz" song["album"] = u"öäü" song["tracknumber"] = u"ö" song["discnumber"] = u"9" song.write() f = mutagen.File(self.filename) self.failUnlessEqual(f.tags["TXXX:QuodLibet::foo"].encoding, 1) self.failUnlessEqual(f.tags["TXXX:QuodLibet::bar"].encoding, 3) self.failUnlessEqual(f.tags["TPE1"].encoding, 3) self.failUnlessEqual(f.tags["TALB"].encoding, 1) self.failUnlessEqual(f.tags["TPE1"].encoding, 3) # FIXME: we shouldn't write invalid TRCK... self.failUnlessEqual(f.tags["TRCK"].encoding, 1) self.failUnlessEqual(f.tags["TPOS"].encoding, 3) def test_tcon(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TMCL(encoding=3, people=[["foo", "bar"]])) f.save() song = self.KIND(self.filename) self.failUnless("performer:foo" in song) self.failUnlessEqual(song("performer:foo"), "bar") def test_nonascii_unsup_tcon(self): people = [["a=", "a"], ["b~", "b"], [u"äöü", "u"], ["quux", "x"]] f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TMCL(encoding=3, people=people)) f.save() # we only support one of them self.failUnlessEqual( len(self.KIND(self.filename).list("~performer")), 1) # but after writing they should still be there song = self.KIND(self.filename) song.write() f = mutagen.File(self.filename) self.failUnlessEqual(len(f.tags["TMCL"].people), 4) self.failUnlessEqual(f.tags["TMCL"].people, people) # also change something.. song["performer:quux"] = "foo" song.write() f = mutagen.File(self.filename) self.failUnlessEqual(dict(f.tags["TMCL"].people)["quux"], "foo") def test_rva_large(self): song = self.KIND(self.filename) song["replaygain_track_peak"] = "3" song["replaygain_track_gain"] = "100" song.write() song["replaygain_track_peak"] = "-1" song["replaygain_track_gain"] = "-100" song.write() def test_rva(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.RVA2(desc="track", channel=1, gain=-3, peak=1.0)) f.tags.add(mutagen.id3.RVA2(desc="album", channel=1, gain=-6, peak=1.0)) f.save() song = self.KIND(self.filename) self.failUnlessAlmostEqual(song.replay_gain(["track"]), 0.7, 1) self.failUnlessAlmostEqual(song.replay_gain(["album"]), 0.5, 1) song.write() f = mutagen.File(self.filename) self.failUnlessEqual(len(f.tags.getall("RVA2")), 2) def test_rva_unknown(self): f = mutagen.File(self.filename) f.tags.add(mutagen.id3.RVA2(desc="track", channel=2, gain=-6, peak=1.0)) f.tags.add(mutagen.id3.RVA2(desc="foo", channel=1, gain=-3, peak=1.0)) f.save() # we use foo as track if nothing else is there song = self.KIND(self.filename) self.failUnlessAlmostEqual(song.replay_gain(["track"]), 0.7, 1) song.write() # and we write that over track.. f = mutagen.File(self.filename) self.failUnlessAlmostEqual(f.tags["RVA2:track"].gain, -3.0, 1) # now that one is there, ignore foo f = mutagen.File(self.filename) f.tags.add(mutagen.id3.RVA2(desc="foo", channel=1, gain=0, peak=1.0)) f.save() song = self.KIND(self.filename) self.failUnlessAlmostEqual(song.replay_gain(["track"]), 0.7, 1) def test_rva_inval(self): song = self.KIND(self.filename) song["replaygain_track_peak"] = u"0.1afasf" song["replaygain_track_gain"] = u"0.1afasf" song.write() def test_without_id3_tag(self): f = mutagen.File(self.filename) f.delete() f.save() song = self.KIND(self.filename) song.get_primary_image() song.write() def test_distrust_latin1(self): x = u"Å" # abuse mutagen a bit, and get some utf-8 in with the wrong encoding f = mutagen.File(self.filename) f.tags.add(mutagen.id3.TPE1( encoding=0, text=x.encode("utf-8").decode("latin-1"))) f.save() # back to utf-8 song = self.KIND(self.filename) self.failUnlessEqual(song("artist"), x) song.write() # because it's not ascii, saved as utf-16 f = mutagen.File(self.filename) self.failUnlessEqual(f.tags["TPE1"].encoding, 1) # and now latin-1 that is not decodable using utf-8/16 x = u"äöü".encode("ibm1026").decode("latin-1") f.tags.add(mutagen.id3.TPE1(encoding=0, text=x)) f.save() self.failUnlessEqual(self.KIND(self.filename)("artist"), x) def test_handled_txxx_encoding(self): song = self.KIND(self.filename) song['albumartistsort'] = u'Dvo\u0159\xe1k, Anton\xedn' song["replaygain_track_peak"] = u'Dvo\u0159\xe1k, Anton\xedn' song.write() def test_albumartistsort(self): song = self.KIND(self.filename) song['albumartistsort'] = u"foo" song.write() song = self.KIND(self.filename) self.assertEqual(song['albumartistsort'], u"foo") class TID3FileMP3(TID3FileBase, TID3FileMixin): KIND = MP3File PATH = get_data_path('silence-44-s.mp3') class TID3FileAIFF(TID3FileBase, TID3FileMixin): KIND = AIFFFile PATH = get_data_path('test.aiff') ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats__image.py��������������������������������������������������������0000664�0001750�0001750�00000005551�14035600052�017735� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path, mkstemp import os from quodlibet.formats import AudioFile, EmbeddedImage, APICType class TAPICType(TestCase): def test_basic(self): self.assertEqual(APICType.COVER_FRONT, 3) def test_sort_key(self): values = [ APICType.OTHER, APICType.COVER_FRONT, APICType.FILE_ICON, APICType.ARTIST, APICType.PUBLISHER_LOGOTYPE ] values.sort(key=APICType.sort_key, reverse=True) wanted = [ APICType.OTHER, APICType.FILE_ICON, APICType.PUBLISHER_LOGOTYPE, APICType.ARTIST, APICType.COVER_FRONT ] self.assertEqual(values, wanted) class TImageContainer(TestCase): def setUp(self): self.a = AudioFile() def test_default_get(self): self.assertFalse(self.a.get_primary_image()) def test_has_image(self): self.assertFalse(self.a.has_images) self.a["~picture"] = "y" self.assertTrue(self.a.has_images) self.a.has_images = False self.assertFalse(self.a.has_images) def test_default_can_change(self): self.assertFalse(self.a.can_change_images) class TEmbeddedImages(TestCase): def setUp(self): from gi.repository import GdkPixbuf h, self.filename = mkstemp() os.close(h) pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) pb.savev(self.filename, "png", [], []) def tearDown(self): os.remove(self.filename) def test_repr(self): image = EmbeddedImage.from_path(self.filename) repr(image) def test_from_path(self): image = EmbeddedImage.from_path(self.filename) self.assertTrue(image) self.assertEqual(image.file.name, self.filename) self.assertEqual(image.mime_type, "image/png") self.assertEqual(image.width, 150) self.assertEqual(image.height, 10) self.assertEqual(image.color_depth, 8) def test_from_path_bogus(self): image = EmbeddedImage.from_path(self.filename + "nope") self.assertFalse(image) def test_not_an_image(self): path = get_data_path('test-2.wma') image = EmbeddedImage.from_path(path) self.assertFalse(image) def test_get_extensions(self): image = EmbeddedImage.from_path(self.filename) self.assertTrue("png" in image.extensions) def test_from_path_empty(self): h, empty = mkstemp() os.close(h) try: image = EmbeddedImage.from_path(empty) self.assertFalse(image) finally: os.remove(empty) �������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_aac.py�����������������������������������������������������������0000664�0001750�0001750�00000004632�14035600052�017237� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from mutagen.aac import AAC from quodlibet.formats.aac import AACFile from . import TestCase, get_data_path, skipUnless from .helper import get_temp_copy class _TAACFile(TestCase): NAME = None def setUp(self): self.f = get_temp_copy(get_data_path(self.NAME)) self.song = AACFile(self.f) def tearDown(self): os.unlink(self.f) class _TAACFileMixin: def test_basic(self): self.song["title"] = u"SomeTestValue" self.song.write() self.song.reload() self.assertEqual(self.song("title"), u"SomeTestValue") def test_write(self): self.song.write() def test_can_change(self): self.assertTrue(self.song.can_change("title")) self.assertFalse(self.song.can_change("foobar")) self.assertTrue("title" in self.song.can_change()) def test_can_multiple_values(self): self.assertEqual(self.song.can_multiple_values(), True) self.assertTrue(self.song.can_multiple_values("title")) def test_invalid(self): path = get_data_path('empty.xm') self.assertTrue(os.path.exists(path)) self.assertRaises(Exception, AACFile, path) def test_format_codec(self): self.assertEqual(self.song("~format"), "AAC") self.assertEqual(self.song("~codec"), "AAC") self.assertEqual(self.song("~encoding"), "") def test_channels(self): assert self.song("~#channels") == 2 @skipUnless(AAC, "too old mutagen") class TADTSFile(_TAACFile, _TAACFileMixin): NAME = "empty.aac" def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.7, 2) def test_bitrate(self): self.assertEqual(self.song("~#bitrate"), 3) def test_samplerate(self): assert self.song("~#samplerate") == 44100 @skipUnless(AAC, "too old mutagen") class TADIFFile(_TAACFile, _TAACFileMixin): NAME = "adif.aac" def test_length(self): self.assertAlmostEqual(self.song("~#length"), 0.25, 2) def test_bitrate(self): self.assertEqual(self.song("~#bitrate"), 128) def test_samplerate(self): assert self.song("~#samplerate") == 48000 ������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_aiff.py����������������������������������������������������������0000664�0001750�0001750�00000002074�14035600052�017416� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path from quodlibet.formats.aiff import AIFFFile class TAIFFFile(TestCase): def setUp(self): self.song = AIFFFile(get_data_path('test.aiff')) def test_length(self): self.assertAlmostEqual(self.song("~#length"), 1.0, 1) def test_bitrate(self): self.failUnlessEqual(self.song("~#bitrate"), 128) def test_format(self): self.assertEqual(self.song("~format"), "AIFF") def test_tags(self): self.assertEqual(self.song("artist"), "artist") self.assertEqual(self.song("album"), "album") self.assertEqual(self.song("genre"), "genre") def test_channels(self): assert self.song("~#channels") == 1 def test_samplerate(self): assert self.song("~#samplerate") == 8000 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_all.py�����������������������������������������������������������0000664�0001750�0001750�00000004652�14035600052�017265� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, get_data_path from quodlibet.formats import MusicFile, AudioFileError, EmbeddedImage from .helper import get_temp_copy FILES = [ get_data_path("empty.ogg"), get_data_path("empty.flac"), get_data_path("silence-44-s.mp3"), get_data_path("silence-44-s.mpc"), get_data_path("test.wma"), get_data_path("coverart.wv"), get_data_path("test.m4a"), get_data_path("empty.opus"), get_data_path("silence-44-s.tta"), get_data_path("empty.aac"), get_data_path("test.mid"), get_data_path("test.wav"), get_data_path("silence-44-s.ape"), get_data_path("test.vgm"), get_data_path("silence-44-s.spx"), get_data_path("test.spc"), ] class TAudioFileAllBase: FILE = None def setUp(self): self.filename = get_temp_copy(self.FILE) self.song = MusicFile(self.filename) def tearDown(self): try: os.remove(self.filename) except OSError: pass def test_clear_images_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, self.song.clear_images) def test_set_image_noent(self): os.remove(self.filename) image = EmbeddedImage(None, "image/png") self.assertRaises(AudioFileError, self.song.set_image, image) def test_get_primary_image_noent(self): os.remove(self.filename) self.assertTrue(self.song.get_primary_image() is None) def test_get_images_noent(self): os.remove(self.filename) self.assertEqual(self.song.get_images(), []) def test_write_noent(self): os.remove(self.filename) try: self.song.write() except AudioFileError: pass def test_load_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, type(self.song), self.filename) @classmethod def create_tests(cls): for i, file_ in enumerate(FILES): new_type = type(cls.__name__ + str(i), (cls, TestCase), {"FILE": file_}) assert new_type.__name__ not in globals() globals()[new_type.__name__] = new_type TAudioFileAllBase.create_tests() ��������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_apev2.py���������������������������������������������������������0000664�0001750�0001750�00000015464�14035600052�017535� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path import os from io import BytesIO import mutagen from mutagen.apev2 import BINARY, APEValue from quodlibet.formats.monkeysaudio import MonkeysAudioFile from quodlibet.formats.mpc import MPCFile from quodlibet.formats.wavpack import WavpackFile from quodlibet.formats._image import APICType, EmbeddedImage from .helper import get_temp_copy class TAPEv2FileMixin: def test_can_change(self): self.failUnlessEqual(self.s.can_change(), True) self.failUnlessEqual(self.s.can_change("~"), False) self.failUnlessEqual(self.s.can_change("a"), False) self.failUnlessEqual(self.s.can_change("OggS"), True) self.failUnlessEqual(self.s.can_change("\xc3\xa4\xc3\xb6"), False) self.failUnlessEqual(self.s.can_change("sUbtitle"), False) self.failUnlessEqual(self.s.can_change("indeX"), False) self.failUnlessEqual(self.s.can_change("yEar"), False) def test_trans_keys(self): self.s["date"] = "2010" self.s.write() m = mutagen.apev2.APEv2(self.f) self.failUnlessEqual(m["Year"], "2010") m["yEar"] = "2011" m.save() self.s.reload() self.failUnlessEqual(self.s["date"], "2011") def test_ignore(self): for tag in ["inDex", "index"]: m = mutagen.apev2.APEv2(self.f) m[tag] = "foobar" m.save() self.s.reload() self.failUnlessEqual(self.s.get(tag), None) m = mutagen.apev2.APEv2(self.f) self.failUnlessEqual(m[tag], "foobar") def test_multi_case(self): self.s["AA"] = "B" self.s["aa"] = "C" self.s["BB"] = "D" self.s["Aa"] = "E" self.s.write() self.s.reload() self.failUnlessEqual(set(self.s["aa"].split()), {"C", "B", "E"}) def test_binary_ignore(self): m = mutagen.apev2.APEv2(self.f) m["foo"] = APEValue(b"bar", BINARY) m.save() self.s.reload() self.failUnlessEqual(self.s.get("foo"), None) self.s.write() m = mutagen.apev2.APEv2(self.f) self.failUnless("foo" in m) def test_titlecase(self): self.s["isRc"] = "1234" self.s["fOoBaR"] = "5678" self.s.write() self.s.reload() self.failUnless("isrc" in self.s) self.failUnless("foobar" in self.s) m = mutagen.apev2.APEv2(self.f) self.failUnless("ISRC" in m) self.failUnless("Foobar" in m) def test_disc_mapping(self): m = mutagen.apev2.APEv2(self.f) m["disc"] = "99/102" m.save() self.s.reload() self.failUnlessEqual(self.s("~#disc"), 99) self.failUnlessEqual(self.s("discnumber"), "99/102") self.s["discnumber"] = "77/88" self.s.write() m = mutagen.apev2.APEv2(self.f) self.failUnlessEqual(m["disc"], "77/88") def test_track_mapping(self): m = mutagen.apev2.APEv2(self.f) m["track"] = "99/102" m.save() self.s.reload() self.failUnlessEqual(self.s("~#track"), 99) self.failUnlessEqual(self.s("tracknumber"), "99/102") self.s["tracknumber"] = "77/88" self.s.write() m = mutagen.apev2.APEv2(self.f) self.failUnlessEqual(m["track"], "77/88") class TMPCFileAPEv2(TestCase, TAPEv2FileMixin): def setUp(self): self.f = get_temp_copy(get_data_path('silence-44-s.mpc')) self.s = MPCFile(self.f) def tearDown(self): os.unlink(self.f) class TMAFile(TestCase, TAPEv2FileMixin): def setUp(self): self.f = get_temp_copy(get_data_path('silence-44-s.ape')) self.s = MonkeysAudioFile(self.f) def tearDown(self): os.unlink(self.f) def test_format_codec(self): self.assertEqual(self.s("~format"), "Monkey's Audio") self.assertEqual(self.s("~codec"), "Monkey's Audio") self.assertEqual(self.s("~encoding"), "") def test_channels(self): assert self.s("~#channels") == 2 def test_samplerate(self): assert self.s("~#samplerate") == 44100 def test_bitdepth(self): assert self.s("~#bitdepth") == 16 def test_ma_file_old(): s = MonkeysAudioFile(get_data_path('mac-396.ape')) assert s("~format") == "Monkey's Audio" assert s("~codec") == "Monkey's Audio" assert s("~encoding") == "" assert s("~#channels") == 2 assert s("~#samplerate") == 44100 # depends on the mutagen version assert s("~#bitdepth", 0) in (0, 16) class TWavpackFileAPEv2(TestCase, TAPEv2FileMixin): def setUp(self): self.f = get_temp_copy(get_data_path('silence-44-s.wv')) self.s = WavpackFile(self.f) def tearDown(self): os.unlink(self.f) def test_format_codec(self): self.assertEqual(self.s("~format"), "WavPack") self.assertEqual(self.s("~codec"), "WavPack") self.assertEqual(self.s("~encoding"), "") class TWvCoverArt(TestCase): def setUp(self): self.f = get_temp_copy(get_data_path('coverart.wv')) self.s = WavpackFile(self.f) def tearDown(self): os.unlink(self.f) def test_get_primary_image(self): cover = self.s.get_primary_image() self.assertTrue(cover) self.assertEqual(cover.type, APICType.COVER_FRONT) def test_get_images(self): covers = self.s.get_images() self.assertEqual(len(covers), 2) types = [c.type for c in covers] self.assertEqual(types, [APICType.COVER_FRONT, APICType.COVER_BACK]) def test_can_change_images(self): self.assertTrue(self.s.can_change_images) def test_clear_images(self): # cover case image = self.s.get_primary_image() self.assertTrue(image) self.s.clear_images() self.assertFalse(self.s.has_images) self.s.reload() image = self.s.get_primary_image() self.assertFalse(image) # no cover case self.s.clear_images() def test_set_image(self): fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) self.s.set_image(image) self.assertTrue(self.s.has_images) images = self.s.get_images() self.assertEqual(len(images), 1) self.assertEqual(images[0].mime_type, "image/") self.assertEqual(images[0].read(), b"foo") def test_set_image_no_tag(self): m = mutagen.apev2.APEv2(self.f) m.delete() fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) self.s.set_image(image) images = self.s.get_images() self.assertEqual(len(images), 1) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_dsf.py�����������������������������������������������������������0000664�0001750�0001750�00000004135�14035600052�017265� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path, skipUnless from quodlibet.formats.dsf import DSFFile, extensions @skipUnless(extensions, "too old mutagen") class TDSFFile(TestCase): def setUp(self): self.song1 = DSFFile(get_data_path("with-id3.dsf")) self.song2 = DSFFile(get_data_path("without-id3.dsf")) self.song3 = DSFFile(get_data_path("2822400-1ch-0s-silence.dsf")) self.song4 = DSFFile(get_data_path("5644800-2ch-s01-silence.dsf")) def test_length(self): self.assertAlmostEqual(self.song1("~#length"), 0.0, 1) self.assertAlmostEqual(self.song2("~#length"), 0.0, 1) self.assertAlmostEqual(self.song3("~#length"), 0.0, 1) self.assertAlmostEqual(self.song4("~#length"), 0.01, 2) def test_bitrate(self): self.failUnlessEqual(self.song1("~#bitrate"), 2822) self.failUnlessEqual(self.song2("~#bitrate"), 2822) self.failUnlessEqual(self.song3("~#bitrate"), 2822) self.failUnlessEqual(self.song4("~#bitrate"), 11289) def test_format(self): self.assertEqual(self.song1("~format"), "DSF") def test_tags(self): self.assertEqual(self.song1("title"), "DSF title") def test_channels(self): assert self.song1("~#channels") == 1 assert self.song2("~#channels") == 1 assert self.song3("~#channels") == 1 assert self.song4("~#channels") == 2 def test_samplerate(self): assert self.song1("~#samplerate") == 2822400 assert self.song2("~#samplerate") == 2822400 assert self.song3("~#samplerate") == 2822400 assert self.song4("~#samplerate") == 5644800 def test_bitdepth(self): assert self.song1("~#bitdepth") == 1 assert self.song2("~#bitdepth") == 1 assert self.song3("~#bitdepth") == 1 assert self.song4("~#bitdepth") == 1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_midi.py����������������������������������������������������������0000664�0001750�0001750�00000002427�14035600052�017435� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path from quodlibet.formats.midi import MidiFile class TMidiFile(TestCase): def setUp(self): self.song = MidiFile(get_data_path('test.mid')) def test_length(self): self.failUnlessAlmostEqual(87, self.song("~#length", 0), 0) def test_reload(self): self.song["title"] = "foobar" self.song.reload() self.failUnlessEqual(self.song("title"), "foobar") def test_write(self): self.song.write() def test_can_change(self): self.failUnlessEqual(self.song.can_change(), ["title"]) self.failUnless(self.song.can_change("title")) self.failIf(self.song.can_change("album")) def test_invalid(self): path = get_data_path('empty.xm') self.failUnlessRaises(Exception, MidiFile, path) def test_format_codec(self): self.assertEqual(self.song("~format"), "MIDI") self.assertEqual(self.song("~codec"), "MIDI") self.assertEqual(self.song("~encoding"), "") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_mod.py�����������������������������������������������������������0000664�0001750�0001750�00000001566�14035600052�017275� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, skipUnless, get_data_path from quodlibet.formats.mod import ModFile, extensions @skipUnless(extensions, "ModPlug missing") class TModFile(TestCase): def setUp(self): self.song = ModFile(get_data_path('empty.xm')) def test_length(self): self.failUnlessEqual(self.song("~#length", 0), 0) def test_title(self): self.failUnlessEqual(self.song["title"], "test song") def test_format_codec(self): self.assertEqual(self.song("~format"), "MOD/XM/IT") self.assertEqual(self.song("~codec"), "MOD/XM/IT") self.assertEqual(self.song("~encoding"), "") ������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_mp3.py�����������������������������������������������������������0000664�0001750�0001750�00000003737�14035600052�017217� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path from quodlibet.formats.mp3 import MP3File class TMP3File(TestCase): def setUp(self): self.song = MP3File(get_data_path('silence-44-s.mp3')) self.song2 = MP3File(get_data_path('test.mp2')) self.song3 = MP3File(get_data_path('lame.mp3')) def test_channels(self): assert self.song("~#channels") == 2 assert self.song2("~#channels") == 1 assert self.song3("~#channels") == 2 def test_samplerate(self): assert self.song("~#samplerate") == 44100 assert self.song2("~#samplerate") == 32000 assert self.song3("~#samplerate") == 44100 def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.77, 2) self.assertAlmostEqual(self.song2("~#length"), 1.764, 3) self.assertAlmostEqual(self.song3("~#length"), 0.0616, 3) def test_bitrate(self): self.failUnlessEqual(self.song("~#bitrate"), 32) self.failUnlessEqual(self.song2("~#bitrate"), 32) # 127 with mutagen 1.39+ assert self.song3("~#bitrate") in [127, 270] def test_format(self): self.assertEqual(self.song("~format"), "MP3") self.assertEqual(self.song2("~format"), "MP2") self.assertEqual(self.song3("~format"), "MP3") def test_codec(self): self.assertEqual(self.song("~codec"), "MP3") self.assertEqual(self.song2("~codec"), "MP2") self.assertEqual(self.song3("~codec"), "MP3") def test_encoding(self): self.assertEqual(self.song("~encoding"), "") self.assertEqual(self.song2("~encoding"), "") assert self.song3("~encoding") in [ "LAME 3.99.1+\nVBR", "LAME 3.99.1+\nVBR\n-V 2"] ���������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_mp4.py�����������������������������������������������������������0000664�0001750�0001750�00000013442�14231604332�017215� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import shutil from io import BytesIO import mutagen from tests import TestCase, get_data_path, mkstemp from quodlibet.formats.mp4 import MP4File from quodlibet.formats._image import EmbeddedImage import mutagen.mp4 from .helper import get_temp_copy class TMP4File(TestCase): def setUp(self): self.f = get_temp_copy(get_data_path('test.m4a')) self.song = MP4File(self.f) def tearDown(self): os.unlink(self.f) def _assert_tag_supported(self, tag, value="SomeTestValue"): self.song[tag] = value self.song.write() self.song.reload() self.assertEqual(self.song(tag), value) def test_format(self): self.assertEqual(self.song("~format"), "MPEG-4") def test_codec(self): self.assertEqual(self.song("~codec"), "AAC LC") def test_encoding(self): self.assertEqual(self.song("~encoding"), "FAAC 1.24") def test_mb_release_track_id(self): tag = mutagen.mp4.MP4(self.f) tag["----:com.apple.iTunes:MusicBrainz Release Track Id"] = [b"foo"] tag.save() song = MP4File(self.f) self.assertEqual(song("musicbrainz_releasetrackid"), u"foo") song["musicbrainz_releasetrackid"] = u"bla" song.write() tag = mutagen.mp4.MP4(self.f) self.assertEqual( tag["----:com.apple.iTunes:MusicBrainz Release Track Id"], [b"bla"]) def test_basic(self): self._assert_tag_supported("title") self._assert_tag_supported("artist") self._assert_tag_supported("albumartist") self._assert_tag_supported("album") self._assert_tag_supported("genre") self._assert_tag_supported("date") def test_basic_numeric(self): self._assert_tag_supported("tracknumber", "12") self._assert_tag_supported("discnumber", "1") self._assert_tag_supported("bpm", "132") def test_less_common_tags(self): self._assert_tag_supported("discsubtitle") self._assert_tag_supported("mood") self._assert_tag_supported("conductor") self._assert_tag_supported("description") def test_replaygain_tags(self): self._assert_tag_supported('replaygain_album_gain', '-5.67 dB') self._assert_tag_supported('replaygain_album_peak', '1.0') self._assert_tag_supported('replaygain_track_gain', '-5.67 dB') self._assert_tag_supported('replaygain_track_peak', '1.0') self._assert_tag_supported('replaygain_reference_loudness', '89 dB') def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.7079, 3) def test_bitrate(self): self.assertEqual(self.song("~#bitrate"), 2) def test_channels(self): assert self.song("~#channels") == 2 def test_samplerate(self): assert self.song("~#samplerate") == 44100 def test_bitdepth(self): assert self.song("~#bitdepth") == 16 def test_bpm_rounds(self): self.song["bpm"] = "98.76" self.song.write() self.song.reload() self.assertEqual(self.song("bpm"), "99") self.assertEqual(self.song("~#bpm"), 99) def test_empty_disk_trkn(self): for key in ["trkn", "disk"]: tag = mutagen.mp4.MP4(self.f) tag[key] = [] tag.save() tag = mutagen.mp4.MP4(self.f) assert tag[key] == [] self.song.reload() def test_write(self): self.song.write() def test_can_change(self): self.assertTrue(self.song.can_change("title")) self.assertFalse(self.song.can_change("foobar")) self.assertTrue("albumartist" in self.song.can_change()) def test_invalid(self): path = get_data_path('empty.xm') self.assertTrue(os.path.exists(path)) self.assertRaises(Exception, MP4File, path) def test_get_image(self): image = self.song.get_primary_image() self.assertTrue(image) self.assertEqual(image.mime_type, "image/png") def test_get_images(self): images = self.song.get_images() self.assertTrue(images and len(images) == 2) def test_get_image_non(self): tag = mutagen.mp4.MP4(self.f) tag.pop("covr", None) tag.save() self.song.reload() self.assertFalse(self.song.get_primary_image()) def test_clear_images(self): self.assertTrue(self.song.valid()) self.assertTrue(self.song.has_images) self.song.clear_images() self.assertFalse(self.song.has_images) self.assertFalse(self.song.get_primary_image()) tag = mutagen.mp4.MP4(self.f) self.assertFalse("covr" in tag) def test_set_image(self): self.assertTrue(self.song.has_images) fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) self.song.set_image(image) image = self.song.get_primary_image() self.assertTrue(image) self.assertEqual(image.read(), b"foo") self.assertTrue(self.song.has_images) def test_can_change_images(self): self.assertTrue(self.song.can_change_images) def test_can_multiple_values(self): self.assertEqual(self.song.can_multiple_values(), []) self.assertFalse(self.song.can_multiple_values("artist")) def test_m4b_support(self): path = get_data_path('test.m4a') fd, filename = mkstemp(suffix='m4b') os.close(fd) shutil.copy(path, filename) self.song = MP4File(filename) assert self.song("~format") == "MPEG-4" self._assert_tag_supported("title") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_mpc.py�����������������������������������������������������������0000664�0001750�0001750�00000003300�14035600052�017261� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, get_data_path from quodlibet.formats.mpc import MPCFile class TMPCFile(TestCase): def setUp(self): self.song = MPCFile(get_data_path('silence-44-s.mpc')) self.song2 = MPCFile(get_data_path('silence-44-s.sv8.mpc')) def test_length(self): self.assertAlmostEqual(self.song("~#length"), 0.065306, 3) self.assertAlmostEqual(self.song2("~#length"), 3.684716, 3) def test_channels(self): assert self.song("~#channels") == 2 assert self.song2("~#channels") == 2 def test_samplerate(self): assert self.song("~#samplerate") == 44100 assert self.song2("~#samplerate") == 44100 def test_bitrate(self): self.failUnlessEqual(self.song("~#bitrate"), 239) self.failUnlessEqual(self.song2("~#bitrate"), 1) def test_invalid(self): path = get_data_path('empty.xm') self.failUnless(os.path.exists(path)) self.failUnlessRaises(Exception, MPCFile, path) def test_format(self): self.assertEqual(self.song("~format"), "Musepack") self.assertEqual(self.song2("~format"), "Musepack") def test_codec(self): self.assertEqual(self.song("~codec"), "Musepack SV7") self.assertEqual(self.song2("~codec"), "Musepack SV8") def test_encoding(self): self.assertEqual(self.song("~encoding"), "") self.assertEqual(self.song2("~encoding"), "") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_remote.py��������������������������������������������������������0000664�0001750�0001750�00000001634�14035600052�020005� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests import TestCase from quodlibet.formats.remote import RemoteFile class TRemoteFile(TestCase): def test_path_types(self): f = RemoteFile("http://example.com") self.assertTrue(isinstance(f["~mountpoint"], fsnative)) self.assertTrue(isinstance(f["~filename"], fsnative)) def test_fix_old_types(self): f = RemoteFile("http://example.com") dict.__setitem__(f, "~filename", b"foo") self.assertTrue(isinstance(f["~filename"], fsnative)) dict.__setitem__(f, "~filename", u"foo") self.assertTrue(isinstance(f["~filename"], fsnative)) ����������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_spc.py�����������������������������������������������������������0000664�0001750�0001750�00000002532�14035600052�017275� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, get_data_path from quodlibet.formats.spc import SPCFile class TSPCFile(TestCase): def setUp(self): self.song = SPCFile(get_data_path('test.spc')) def test_tags(self): tags = { "title": "Game Select", "artist": "Koji Kondo", "album": "Super Mario All-Stars", "dumper": "Datschge", } for k, v in tags.items(): self.failUnlessEqual(self.song[k], v) def test_length(self): self.failUnlessEqual(self.song("~#length"), 25) def test_write(self): self.song.write() def test_can_change(self): self.failUnless(self.song.can_change("title")) def test_invalid(self): path = get_data_path('empty.xm') self.failUnless(os.path.exists(path)) self.failUnlessRaises(Exception, SPCFile, path) def test_format_codec(self): self.assertEqual(self.song("~format"), "SPC700") self.assertEqual(self.song("~codec"), "SPC700") self.assertEqual(self.song("~encoding"), "") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_trueaudio.py�����������������������������������������������������0000664�0001750�0001750�00000001603�14035600052�020507� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import pytest from tests import TestCase, get_data_path from quodlibet.formats.trueaudio import TrueAudioFile class TTrueAudioFile(TestCase): def setUp(self): self.song = TrueAudioFile(get_data_path('silence-44-s.tta')) def test_length(self): assert self.song("~#length") == pytest.approx(3.684, abs=1e-3) def test_audio_props(self): assert self.song("~#samplerate") == 44100 def test_format_codec(self): assert self.song("~format") == "True Audio" assert self.song("~codec") == "True Audio" assert self.song("~encoding") == "" assert self.song("~codec") == "True Audio" �����������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_vgm.py�����������������������������������������������������������0000664�0001750�0001750�00000003311�14035600052�017275� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path from quodlibet.formats.vgm import VgmFile class TVgmFile(TestCase): def setUp(self): self.song = VgmFile(get_data_path('test.vgm')) def test_length(self): self.failUnlessAlmostEqual(2.81, self.song("~#length", 0), 1) def test_reload(self): self.song["title"] = "foobar" self.song.reload() self.failUnlessEqual(self.song("title"), "Chaos Emerald") def test_gd3_tags(self): expected_tags = { "title": "Chaos Emerald", "album": "Sonic the Hedgehog\nソニック・ザ・ヘッジホッグ", "console": "Sega Mega Drive\nセガメガドライブ", "artist": "Masato Nakamura\n中村正人", "date": "1991" } for k, v in expected_tags.items(): self.failUnlessEqual(self.song[k], v) def test_write(self): self.song.write() def test_can_change(self): self.failUnlessEqual(self.song.can_change(), ["title"]) self.failUnless(self.song.can_change("title")) self.failIf(self.song.can_change("album")) def test_invalid(self): path = get_data_path('empty.xm') self.failUnlessRaises(Exception, VgmFile, path) def test_format_codec(self): self.assertEqual(self.song("~format"), "VGM") self.assertEqual(self.song("~codec"), "VGM") self.assertEqual(self.song("~encoding"), "") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_wav.py�����������������������������������������������������������0000664�0001750�0001750�00000002675�14035600052�017315� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, get_data_path from quodlibet.formats.wav import WAVEFile class TWAVEFile(TestCase): def setUp(self): self.song = WAVEFile(get_data_path('test.wav')) def test_title_tag(self): self.assertEqual(self.song["title"], "test") self.assertTrue(isinstance(self.song["title"], str)) def test_length(self): self.failUnlessAlmostEqual(self.song("~#length"), 0.227, 2) def test_channels(self): assert self.song("~#channels") == 1 def test_samplerate(self): assert self.song("~#samplerate") == 11025 def test_bitdepth(self): assert self.song("~#bitdepth") == 8 def test_write(self): self.song.write() def test_can_change(self): self.failUnless(self.song.can_change("artist")) def test_invalid(self): path = get_data_path('empty.xm') self.failUnless(os.path.exists(path)) self.failUnlessRaises(Exception, WAVEFile, path) def test_format_codec(self): self.assertEqual(self.song("~format"), "WAVE") self.assertEqual(self.song("~codec"), "WAVE") self.assertEqual(self.song("~encoding"), "") �������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_wavpack.py�������������������������������������������������������0000664�0001750�0001750�00000002013�14035600052�020136� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, get_data_path from quodlibet.formats.wavpack import WavpackFile class TWavpackFile(TestCase): def setUp(self): self.song = WavpackFile(get_data_path('silence-44-s.wv')) def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.68471, 3) def test_channels(self): assert self.song("~#channels") == 2 def test_samplerate(self): assert self.song("~#samplerate") == 44100 def test_bitrate(self): self.failUnlessEqual(self.song("~#bitrate"), 76) def test_format_codec(self): self.assertEqual(self.song("~format"), "WavPack") self.assertEqual(self.song("~codec"), "WavPack") self.assertEqual(self.song("~encoding"), "") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_wma.py�����������������������������������������������������������0000664�0001750�0001750�00000015521�14035600052�017276� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from io import BytesIO from mutagen import asf from tests import TestCase, get_data_path from quodlibet.formats.wma import WMAFile, unpack_image, pack_image from quodlibet.formats._image import APICType, EmbeddedImage from .helper import get_temp_copy class TWMAFile(TestCase): def setUp(self): self.f = get_temp_copy(get_data_path('test.wma')) self.song = WMAFile(self.f) self.f2 = get_temp_copy(get_data_path('test-2.wma')) self.song2 = WMAFile(self.f2) self.f3 = get_temp_copy(get_data_path('test.asf')) self.song3 = WMAFile(self.f3) def tearDown(self): os.unlink(self.f) os.unlink(self.f2) os.unlink(self.f3) def test_basic(self): self.song["title"] = u"SomeTestValue" self.song.write() self.song.reload() self.assertEqual(self.song("title"), u"SomeTestValue") def test_multi(self): self.song["genre"] = u"Rock\nPop" self.song.write() self.song.reload() # XXX: mutagen doesn't preserve order.. fix it! self.assertEqual(set(self.song.list("genre")), {u"Rock", u"Pop"}) def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.7120, 3) self.assertAlmostEqual(self.song2("~#length"), 3.684, 3) self.assertAlmostEqual(self.song3("~#length"), 11.38, 2) def test_channels(self): assert self.song("~#channels") == 2 assert self.song2("~#channels") == 2 assert self.song3("~#channels") == 1 def test_bitrate(self): self.assertEqual(self.song("~#bitrate"), 64) self.assertEqual(self.song2("~#bitrate"), 38) self.assertEqual(self.song3("~#bitrate"), 5) def test_sample_rate(self): assert self.song("~#samplerate") == 48000 assert self.song2("~#samplerate") == 44100 assert self.song3("~#samplerate") == 8000 def test_write(self): self.song.write() self.song2.write() self.song3.write() def test_can_change(self): self.assertTrue(self.song.can_change("title")) self.assertFalse(self.song.can_change("foobar")) self.assertTrue("albumartist" in self.song.can_change()) def test_format(self): self.assertEqual(self.song("~format"), "ASF") self.assertEqual(self.song2("~format"), "ASF") self.assertEqual(self.song3("~format"), "ASF") def test_codec(self): self.assertEqual(self.song("~codec"), u"Windows Media Audio 9 Standard") self.assertEqual(self.song2("~codec"), u"Windows Media Audio 9 Professional") self.assertEqual(self.song3("~codec"), u"Intel G.723") def test_encoding(self): self.assertEqual( self.song("~encoding"), u"Windows Media Audio 9.1\n64 kbps, 48 kHz, stereo 2-pass CBR") self.assertEqual( self.song2("~encoding"), (u"Windows Media Audio 9.1 Professional\n192 kbps, 44 kHz, " "2 channel 24 bit 2-pass VBR")) self.assertEqual(self.song3("~encoding"), u"Microsoft G.723.1\n8 kHz Mono, 5333 Bit/s") def test_mb_release_track_id(self): tag = asf.ASF(self.f) tag["MusicBrainz/Release Track Id"] = [u"foo"] tag.save() song = WMAFile(self.f) self.assertEqual(song("musicbrainz_releasetrackid"), u"foo") song["musicbrainz_releasetrackid"] = u"bla" song.write() tag = asf.ASF(self.f) self.assertEqual(tag["MusicBrainz/Release Track Id"], [u"bla"]) def test_invalid(self): path = get_data_path('empty.xm') self.assertTrue(os.path.exists(path)) self.assertRaises(Exception, WMAFile, path) def test_get_images(self): tag = asf.ASF(self.f2) tag["WM/Picture"] = [tag["WM/Picture"][0], tag["WM/Picture"][0]] tag.save() self.song2.reload() images = self.song2.get_images() self.assertTrue(images and len(images) == 2) def test_get_image(self): self.assertFalse(self.song.get_primary_image()) image = self.song2.get_primary_image() self.assertTrue(image) self.assertEqual(image.mime_type, "image/jpeg") self.assertTrue(image.read()) def test_get_image_invalid_data(self): tag = asf.ASF(self.f) tag["WM/Picture"] = [asf.ASFValue(b"nope", asf.BYTEARRAY)] tag.save() self.assertFalse(self.song.has_images) self.song.reload() self.assertTrue(self.song.has_images) image = self.song.get_primary_image() self.assertFalse(image) def test_unpack_image_min(self): data = b"\x03" + b"\x00" * 4 + b"\x00" * 4 mime, desc, data, type_ = unpack_image(data) self.assertEqual(mime, u"") self.assertEqual(desc, u"") self.assertEqual(data, b"") self.assertEqual(type_, 3) def test_unpack_image_invalid(self): self.assertRaises(ValueError, unpack_image, b"") self.assertRaises(ValueError, unpack_image, b"\x00" * 6) self.assertRaises(ValueError, unpack_image, b"\x00" * 8) self.assertRaises(ValueError, unpack_image, b"\x00" * 100) def test_pack_image(self): d = pack_image( u"image/jpeg", u"Description", b"foo", APICType.COVER_FRONT) mime, desc, data, type_ = unpack_image(d) self.assertEqual(mime, u"image/jpeg") self.assertEqual(desc, u"Description") self.assertEqual(data, b"foo") self.assertEqual(type_, APICType.COVER_FRONT) def test_clear_images(self): # cover case image = self.song2.get_primary_image() self.assertTrue(image) self.song2.clear_images() self.assertFalse(self.song2.has_images) self.song2.reload() image = self.song2.get_primary_image() self.assertFalse(image) # no cover case self.song.clear_images() def test_set_image(self): fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) self.assertFalse(self.song.has_images) self.song.set_image(image) self.assertTrue(self.song.has_images) image = self.song.get_primary_image() self.assertEqual(image.mime_type, "image/jpeg") self.assertEqual(image.read(), b"foo") def test_can_change_images(self): self.assertTrue(self.song.can_change_images) def test_can_multiple_values(self): self.assertTrue("artist" in self.song.can_multiple_values()) self.assertTrue(self.song.can_multiple_values("genre")) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_formats_xiph.py����������������������������������������������������������0000664�0001750�0001750�00000047176�14035600052�017475� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.config import RATINGS from tests import get_data_path, skipUnless, mkstemp, TestCase import os import sys import base64 from io import BytesIO from quodlibet import config, const, formats from quodlibet.formats.xiph import OggFile, FLACFile, OggOpusFile, OggOpus from quodlibet.formats._image import EmbeddedImage, APICType from mutagen.flac import FLAC, Picture from mutagen.id3 import ID3, TIT2, ID3NoHeaderError from mutagen.oggvorbis import OggVorbis from .helper import get_temp_copy def _get_jpeg(size=5): from gi.repository import GdkPixbuf pb = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, False, 8, size, size) fd, fn = mkstemp() pb.savev(fn, "jpeg", [], []) with os.fdopen(fd, "rb") as h: data = h.read() os.unlink(fn) return data class TXiphPickle(TestCase): # make sure the classes are available at the old paths # so unpickling old libraries works. def test_modules_flac(self): self.failUnless("formats.flac" in sys.modules) mod = sys.modules["formats.flac"] self.failUnless(mod.FLACFile is FLACFile) def test_modules_vorbis(self): self.failUnless("formats.oggvorbis" in sys.modules) mod = sys.modules["formats.oggvorbis"] self.failUnless(mod.OggFile is OggFile) class TVCFile(TestCase): # Mixin to test Vorbis writing features def setUp(self): config.init() config.set("editing", "save_email", "") config.set("editing", "save_to_songs", "1") class TVCFileMixin: def test_rating(self): self.song["~#rating"] = 0.2 self.song.write() song = type(self.song)(self.filename) self.failUnlessEqual(song["~#rating"], 0.2) def test_channels(self): assert self.song("~#channels") == 2 def test_deletes_rating(self): config.set("editing", "save_email", "foo@Bar.org") self.song["~#rating"] = 0.2 self.song.write() self.song["~#rating"] = RATINGS.default self.song.write() song = type(self.song)(self.filename) config.set("editing", "save_email", const.EMAIL) self.failUnlessEqual(song("~#rating"), RATINGS.default) def test_new_email_rating(self): config.set("editing", "save_email", "foo@Bar.org") self.song["~#rating"] = 0.2 self.song.write() song = type(self.song)(self.filename) config.set("editing", "save_email", const.EMAIL) self.failUnlessEqual(song["~#rating"], 0.2) def test_default_email_rating(self): self.song["~#rating"] = 0.2 self.song.write() song = type(self.song)(self.filename) config.set("editing", "save_email", "foo@Bar.org") config.set("editing", "save_email", const.EMAIL) self.failUnlessEqual(song["~#rating"], 0.2) def test_different_email_rating(self): config.set("editing", "save_email", "foo@Bar.org") self.song["~#rating"] = 0.2 self.song.write() config.set("editing", "save_email", const.EMAIL) song = type(self.song)(self.filename) self.failUnlessEqual(song("~#rating"), RATINGS.default) song.write() config.set("editing", "save_email", "foo@Bar.org") song = type(self.song)(self.filename) config.set("editing", "save_email", const.EMAIL) self.failUnlessEqual(song["~#rating"], 0.2) def test_huge_playcount(self): count = 1000000000000000 self.song["~#playcount"] = count self.song.write() song = type(self.song)(self.filename) self.failUnlessEqual(song["~#playcount"], count) def test_parameter(self): for bad in ["rating", "playcount", "rating:foo", "playcount:bar"]: self.failIf(self.song.can_change(bad)) def test_parameter_ci(self): for bad in ["ratinG", "plaYcount", "raTing:foo", "playCount:bar"]: self.failIf(self.song.can_change(bad)) def test_case_insensitive(self): self.song["foo"] = "1" self.song["FOO"] = "1" self.song.write() self.song.reload() self.failUnlessEqual(self.song.list("foo"), ["1", "1"]) def test_case_insensitive_total(self): self.song["TRacKNUMBER"] = "1/10" self.song.write() self.song.reload() self.failUnlessEqual(self.song["tracknumber"], "1/10") def test_dont_save(self): config.set("editing", "save_to_songs", "false") self.song["~#rating"] = 1.0 self.song.write() song = type(self.song)(self.filename) config.set("editing", "save_to_songs", "true") self.failUnlessEqual(song("~#rating"), RATINGS.default) def test_can_change(self): self.failUnless(self.song.can_change()) class TTotalTagsBase(TestCase): """Test conversation between the tracknumber/totaltracks/tracktotal format and the tracknumber="x/y" format. """ MAIN = None FALLBACK = None SINGLE = None def setUp(self): config.init() self.filename = get_temp_copy(get_data_path('empty.ogg')) def tearDown(self): os.unlink(self.filename) config.quit() class TTotalTagsMixin: def __load_tags(self, tags, expected): m = OggVorbis(self.filename) for key, value in tags.items(): m.tags[key] = value m.save() song = OggFile(self.filename) for key, value in expected.items(): self.failUnlessEqual(song(key), value) if self.MAIN not in expected: self.failIf(self.MAIN in song) if self.SINGLE not in expected: self.failIf(self.SINGLE in song) if self.FALLBACK not in expected: self.failIf(self.FALLBACK in song) def test_load_old_single(self): self.__load_tags( {self.SINGLE: "1/42"}, {self.SINGLE: "1/42"}) def test_load_main(self): self.__load_tags( {self.SINGLE: "3", self.MAIN: "10"}, {self.SINGLE: "3/10"}) def test_load_fallback(self): self.__load_tags( {self.SINGLE: "3", self.FALLBACK: "10"}, {self.SINGLE: "3/10"}) def test_load_all(self): self.__load_tags( {self.SINGLE: "3", self.FALLBACK: "10", self.MAIN: "5"}, {self.SINGLE: "3/5", self.FALLBACK: "10"}) def test_load_main_no_single(self): self.__load_tags( {self.MAIN: "5"}, {self.SINGLE: "/5"}) def test_load_fallback_no_single(self): self.__load_tags( {self.FALLBACK: "6"}, {self.SINGLE: "/6"}) def test_load_both_no_single(self): self.__load_tags( {self.FALLBACK: "6", self.MAIN: "5"}, {self.FALLBACK: "6", self.SINGLE: "/5"}) def __save_tags(self, tags, expected): #return song = OggFile(self.filename) for key, value in tags.items(): song[key] = value song.write() m = OggVorbis(self.filename) # test if all values ended up where we wanted for key, value in expected.items(): self.failUnless(key in m.tags) self.failUnlessEqual(m.tags[key], [value]) # test if not specified are not there if self.MAIN not in expected: self.failIf(self.MAIN in m.tags) if self.FALLBACK not in expected: self.failIf(self.FALLBACK in m.tags) if self.SINGLE not in expected: self.failIf(self.SINGLE in m.tags) def test_save_single(self): self.__save_tags( {self.SINGLE: "1/2"}, {self.SINGLE: "1", self.MAIN: "2"}) def test_save_main(self): self.__save_tags( {self.MAIN: "3"}, {self.MAIN: "3"}) def test_save_fallback(self): self.__save_tags( {self.FALLBACK: "3"}, {self.MAIN: "3"}) def test_save_single_and_main(self): # not clear what to do here... self.__save_tags( {self.SINGLE: "1/2", self.MAIN: "3"}, {self.SINGLE: "1", self.MAIN: "3"}) def test_save_single_and_fallback(self): self.__save_tags( {self.SINGLE: "1/2", self.FALLBACK: "3"}, {self.SINGLE: "1", self.MAIN: "2", self.FALLBACK: "3"}) def test_save_all(self): # not clear what to do here... self.__save_tags( {self.SINGLE: "1/2", self.MAIN: "4", self.FALLBACK: "3"}, {self.SINGLE: "1", self.MAIN: "4", self.FALLBACK: "3"}) class TTrackTotal(TTotalTagsBase, TTotalTagsMixin): MAIN = "tracktotal" FALLBACK = "totaltracks" SINGLE = "tracknumber" class TDiscTotal(TTotalTagsBase, TTotalTagsMixin): MAIN = "disctotal" FALLBACK = "totaldiscs" SINGLE = "discnumber" class TFLACFile(TVCFile, TVCFileMixin): def setUp(self): TVCFile.setUp(self) self.filename = get_temp_copy(get_data_path('empty.flac')) self.song = FLACFile(self.filename) def test_format_codec(self): self.assertEqual(self.song("~format"), "FLAC") self.assertEqual(self.song("~codec"), "FLAC") self.assertEqual(self.song("~encoding"), "") def test_audio_props(self): assert self.song("~#channels") == 2 assert self.song("~#samplerate") == 44100 assert self.song("~#bitdepth") == 16 def test_mime(self): self.failUnless(self.song.mimes) def test_save_empty(self): self.song.write() flac = FLAC(self.filename) self.failIf(flac.tags) self.failIf(flac.tags is None) def test_strip_id3(self): self.song["title"] = "Test" self.song.write() id3 = ID3() id3.add(TIT2(encoding=2, text=u"Test but differently")) id3.save(filename=self.filename) song2 = formats.MusicFile(self.filename) self.failUnlessEqual(type(self.song), type(song2)) self.failUnlessEqual(self.song["title"], song2["title"]) song2.write() self.assertRaises(ID3NoHeaderError, ID3, self.filename) def tearDown(self): os.unlink(self.filename) config.quit() class TVCCover(TestCase): def setUp(self): config.init() def tearDown(self): os.unlink(self.filename) config.quit() class TVCCoverMixin: def test_can_change_images(self): song = self.QLType(self.filename) self.assertTrue(song.can_change_images) def test_no_cover(self): song = self.QLType(self.filename) self.failIf(song("~picture")) self.failIf(song.get_primary_image()) def test_get_images(self): # coverart + coverartmime data = _get_jpeg() song = self.MutagenType(self.filename) song["coverart"] = base64.b64encode(data).decode("ascii") song["coverartmime"] = u"image/jpeg" song.save() song = self.QLType(self.filename) self.assertEqual(len(song.get_images()), 1) self.assertEqual(song.get_images()[0].mime_type, "image/jpeg") # metadata_block_picture pic = Picture() pic.data = _get_jpeg() pic.type = APICType.COVER_FRONT b64pic_cover = base64.b64encode(pic.write()).decode("ascii") song = self.MutagenType(self.filename) song["metadata_block_picture"] = [b64pic_cover] song.save() song = self.QLType(self.filename) self.assertEqual(len(song.get_images()), 2) self.assertEqual(song.get_images()[0].type, APICType.COVER_FRONT) def test_handle_old_coverart(self): data = _get_jpeg() song = self.MutagenType(self.filename) song["coverart"] = base64.b64encode(data).decode("ascii") song["coverartmime"] = "image/jpeg" song.save() song = self.QLType(self.filename) self.failUnlessEqual(song("~picture"), "y") self.failIf(song("coverart")) self.failIf(song("coverartmime")) song.write() self.assertEqual(song.get_primary_image().mime_type, "image/jpeg") fn = song.get_primary_image().file cov_data = fn.read() self.failUnlessEqual(data, cov_data) song = self.MutagenType(self.filename) self.failUnlessEqual(base64.b64decode(song["coverart"][0]), data) self.failUnlessEqual(song["coverartmime"][0], "image/jpeg") def test_handle_invalid_coverart(self): crap = u".-a,a.f,afa-,.-" song = self.MutagenType(self.filename) song["coverart"] = crap song.save() song = self.QLType(self.filename) self.failUnlessEqual(song("~picture"), "y") self.failIf(song("coverart")) self.failIf(song.get_primary_image()) self.failIf(song("~picture")) song.write() song = self.MutagenType(self.filename) self.failUnlessEqual(song["coverart"][0], crap) def test_handle_picture_block(self): pic = Picture() pic.data = _get_jpeg() pic.type = APICType.COVER_FRONT b64pic_cover = base64.b64encode(pic.write()).decode("ascii") pic2 = Picture() pic2.data = _get_jpeg(size=6) pic2.type = APICType.COVER_BACK b64pic_other = base64.b64encode(pic2.write()).decode("ascii") song = self.MutagenType(self.filename) song["metadata_block_picture"] = [b64pic_other, b64pic_cover] song.save() song = self.QLType(self.filename) self.failUnlessEqual(song("~picture"), "y") fn = song.get_primary_image().file self.failUnlessEqual(pic.data, fn.read()) song.write() song = self.MutagenType(self.filename) self.failUnless(b64pic_other in song["metadata_block_picture"]) self.failUnless(b64pic_cover in song["metadata_block_picture"]) song["metadata_block_picture"] = [b64pic_other] song.save() song = self.QLType(self.filename) fn = song.get_primary_image().file self.failUnlessEqual(pic2.data, fn.read()) def test_handle_invalid_picture_block(self): crap = ".-a,a.f,afa-,.-" song = self.MutagenType(self.filename) song["metadata_block_picture"] = crap song.save() song = self.QLType(self.filename) self.failUnlessEqual(song("~picture"), "y") self.failIf(song("metadata_block_picture")) self.failIf(song.get_primary_image()) self.failIf(song("~picture")) song.write() song = self.MutagenType(self.filename) self.failUnlessEqual(song["metadata_block_picture"][0], crap) def test_handle_invalid_flac_picture(self): crap = b".-a,a.f,afa-,.-" song = self.MutagenType(self.filename) song["metadata_block_picture"] = base64.b64encode(crap).decode("ascii") song.save() song = self.QLType(self.filename) self.failIf(song.get_primary_image()) self.failIf(song.get_images()) def test_set_image(self): data = _get_jpeg() song = self.MutagenType(self.filename) song["coverart"] = base64.b64encode(data).decode("ascii") song["coverartmime"] = "image/jpeg" song.save() fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) song = self.QLType(self.filename) self.assertTrue(song.has_images) self.assertTrue(song.get_primary_image()) self.assertTrue(song.has_images) song.set_image(image) self.assertTrue(song.has_images) self.assertEqual(song.get_primary_image().width, 10) song = self.MutagenType(self.filename) self.assertTrue("coverart" not in song) self.assertTrue("coverartmime" not in song) class TVCCoverOgg(TVCCover, TVCCoverMixin): def setUp(self): TVCCover.setUp(self) self.filename = get_temp_copy(get_data_path('empty.ogg')) self.MutagenType = OggVorbis self.QLType = OggFile class TVCCoverFlac(TVCCover, TVCCoverMixin): def setUp(self): TVCCover.setUp(self) self.filename = get_temp_copy(get_data_path('empty.flac')) self.MutagenType = FLAC self.QLType = FLACFile class TFlacPicture(TestCase): def setUp(self): config.init() self.filename = get_temp_copy(get_data_path('empty.flac')) def test_get_images(self): pic = Picture() pic.data = _get_jpeg() pic.type = APICType.COVER_FRONT b64pic_cover = base64.b64encode(pic.write()).decode("ascii") # metadata_block_picture song = FLAC(self.filename) song["metadata_block_picture"] = [b64pic_cover] song.save() song = FLACFile(self.filename) self.assertEqual(len(song.get_images()), 1) self.assertEqual(song.get_images()[0].type, APICType.COVER_FRONT) # flac Picture song = FLAC(self.filename) pic = Picture() pic.data = _get_jpeg() pic.type = APICType.COVER_BACK song.add_picture(pic) song.save() song = FLACFile(self.filename) self.assertEqual(len(song.get_images()), 2) self.assertEqual(song.get_images()[-1].type, APICType.COVER_BACK) def test_get_image(self): data = b"abc" song = FLAC(self.filename) pic = Picture() pic.data = data song.add_picture(pic) song.save() song = FLACFile(self.filename) self.failUnless(song("~picture")) fn = song.get_primary_image().file self.failUnlessEqual(fn.read(), pic.data) def test_clear_images(self): data = b"abc" song = FLAC(self.filename) pic = Picture() pic.data = data song.add_picture(pic) song.save() song = FLACFile(self.filename) self.assertTrue(song.get_primary_image()) song.clear_images() song.clear_images() song = FLACFile(self.filename) self.assertFalse(song.get_primary_image()) def test_set_image(self): fileobj = BytesIO(b"foo") image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) song = FLACFile(self.filename) self.assertFalse(song.get_primary_image()) song.set_image(image) self.assertEqual(song.get_primary_image().width, 10) def tearDown(self): os.unlink(self.filename) config.quit() class TOggFile(TVCFile, TVCFileMixin): def setUp(self): TVCFile.setUp(self) self.filename = get_temp_copy(get_data_path('empty.ogg')) self.song = OggFile(self.filename) def tearDown(self): os.unlink(self.filename) config.quit() def test_audio_props(self): assert self.song("~#samplerate") == 44100 def test_format_codec(self): self.assertEqual(self.song("~format"), "Ogg Vorbis") self.assertEqual(self.song("~codec"), "Ogg Vorbis") self.assertEqual(self.song("~encoding"), "") @skipUnless(OggOpus, "Ogg Opus mutagen support missing") class TOggOpusFile(TVCFile, TVCFileMixin): def setUp(self): TVCFile.setUp(self) self.filename = get_temp_copy(get_data_path('empty.opus')) self.song = OggOpusFile(self.filename) def test_length(self): self.assertAlmostEqual(self.song("~#length"), 3.6847, 3) self.failUnless("opusenc" in self.song("encoder")) def test_channels(self): assert self.song("~#channels") == 2 def test_sample_rate(self): assert self.song("~#samplerate") == 48000 def test_format_codec(self): self.assertEqual(self.song("~format"), "Ogg Opus") self.assertEqual(self.song("~codec"), "Ogg Opus") self.assertEqual(self.song("~encoding"), "libopus 0.9.14") def tearDown(self): os.unlink(self.filename) config.quit() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656278102.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_gio.py�������������������������������������������������������������������0000664�0001750�0001750�00000005760�14256146126�015555� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import shutil from pathlib import Path from time import sleep, time from typing import Optional, Set from _pytest.fixtures import fixture from gi.repository import Gio from quodlibet import print_d from quodlibet.library.file import Event from quodlibet.util.path import normalize_path from tests import mkdtemp, run_gtk_loop from tests.helper import temp_filename SLEEP_SECS = 0.2 """Enough for OS events / caches to filter through to GIO etc""" @fixture def temp_dir() -> Path: out_path = Path(mkdtemp()) yield out_path shutil.rmtree(out_path) class BasicMonitor: def __init__(self, path: Path): self.changed = [] f = Gio.File.new_for_path(str(path)) monitor = f.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, None) handler_id = monitor.connect("changed", self._file_changed) self._monitors = {path: (monitor, handler_id)} print_d(f"Monitoring {path!s}") def _file_changed(self, _monitor, main_file: Gio.File, other_file: Optional[Gio.File], event_type: Gio.FileMonitorEvent) -> None: file_path = main_file.get_path() other_path = (Path(normalize_path(other_file.get_path(), True)) if other_file else None) print_d(f"Got event {event_type} on {file_path}->{other_path}") self.changed.append((event_type, file_path)) @property def event_types(self) -> Set[Event]: return {changed[0] for changed in self.changed} class TestFileMonitor: def test_create_delete(self, temp_dir: Path): path = temp_dir monitor = BasicMonitor(path) some_file = (path / "foo.txt") some_file.write_text("test") sleep(SLEEP_SECS) run_gtk_loop() assert monitor.changed, "No events after creation" # assert monitor.event_types >= {EventType.CHANGED, EventType.CREATED} assert monitor.event_types >= {Event.CREATED} monitor.changed.clear() some_file.unlink() sleep(SLEEP_SECS) run_gtk_loop() assert monitor.changed, "No events after deletion" assert monitor.event_types >= {Event.DELETED} def test_move(self, temp_dir: Path): monitor = BasicMonitor(temp_dir) with temp_filename(dir=temp_dir, suffix=".txt", as_path=True) as path: path.write_text("test\n") sleep(SLEEP_SECS) run_gtk_loop() assert monitor.changed, "No events after creation" monitor.changed.clear() new_name = f"new-{time()}.txt" path.rename(path.parent / new_name) sleep(SLEEP_SECS) run_gtk_loop() assert monitor.changed assert monitor.event_types >= {Event.RENAMED}, f"Got {monitor.changed}" ����������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_https.py�����������������������������������������������������������������0000644�0001750�0001750�00000004734�14455205526�016140� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # 2023 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import pytest from gi.repository import Gio, Soup, GLib from urllib.request import urlopen, build_opener from tests import TestCase, skipIf from quodlibet.util import is_linux, get_ca_file @pytest.mark.network # See https://stackoverflow.com/questions/75274925 @skipIf(is_linux() and not os.environ.get("container"), "Only on Flatpak linux") class Thttps(TestCase): """For Windows/OSX/Flatpak to check if we can create a TLS connection using both openssl and whatever backend soup/gio uses. """ GOOD = ["https://sha256.badssl.com/"] BAD = [ "https://expired.badssl.com/", "https://wrong.host.badssl.com/", "https://self-signed.badssl.com/", ] def test_urllib(self): for url in self.GOOD: urlopen(url, cafile=get_ca_file()).close() for url in self.BAD: with self.assertRaises(Exception): urlopen(url, cafile=get_ca_file()).close() def test_urllib_default(self): for url in self.GOOD: urlopen(url).close() for url in self.BAD: with self.assertRaises(Exception): urlopen(url).close() def test_urllib_build_opener(self): for url in self.GOOD: build_opener().open(url).close() for url in self.BAD: with self.assertRaises(Exception): build_opener().open(url).close() def test_gio(self): for url in self.GOOD: client = Gio.SocketClient() client.set_tls(True) client.connect_to_uri(url, 443, None).close() for url in self.BAD: with self.assertRaises(GLib.GError): client = Gio.SocketClient() client.set_tls(True) client.connect_to_uri(url, 443, None).close() def test_soup(self): for url in self.GOOD: session = Soup.Session() msg = Soup.Message.new("GET", url) session.send_and_read(msg) for url in self.BAD: with self.assertRaises(GLib.GError): session = Soup.Session() msg = Soup.Message.new("GET", url) session.send_and_read(msg) ������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_icons.py�����������������������������������������������������������������0000664�0001750�0001750�00000001331�14035600052�016064� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from tests import TestCase import quodlibet class TIconTheme(TestCase): def test_icon_theme(self): theme = Gtk.IconTheme.get_default() theme.append_search_path(quodlibet.get_image_dir()) for i in [ "io.github.quodlibet.QuodLibet", "io.github.quodlibet.ExFalso", "quodlibet-missing-cover" ]: self.failUnless(theme.has_icon(i)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_image_support.py���������������������������������������������������������0000664�0001750�0001750�00000002126�14035600052�017632� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import GdkPixbuf, Gdk from tests import TestCase, get_data_path class Timage_support(TestCase): """Mostly targeted at Windows/OSX, to make sure we package all the image decoders correctly """ IMAGES = [ "image.svg", "image.bmp", "image.png", "image.gif", "image.jpg", ] def test_create_pixbuf(self): for name in self.IMAGES: file_path = get_data_path(name) pb = GdkPixbuf.Pixbuf.new_from_file(file_path) assert pb assert pb.get_width() == 16 assert pb.get_height() == 16 def test_cursors(self): # make sure cursor images are packaged right cursor = Gdk.Cursor.new_from_name(Gdk.Display.get_default(), "default") assert cursor.get_surface() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_album.py���������������������������������������������������������0000664�0001750�0001750�00000012250�14231604507�017606� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.library import SongLibrary from quodlibet.library.album import AlbumLibrary from quodlibet.library.base import Library from quodlibet.util import connect_obj from tests import TestCase from tests.test_library_libraries import FakeSong, ASrange, AlbumSong class TAlbumLibrary(TestCase): Fake = FakeSong Frange = staticmethod(ASrange) UnderlyingLibrary = Library def setUp(self): self.underlying = self.UnderlyingLibrary() self.added = [] self.changed = [] self.removed = [] self._sigs = [ connect_obj(self.underlying, 'added', list.extend, self.added), connect_obj(self.underlying, 'changed', list.extend, self.changed), connect_obj(self.underlying, 'removed', list.extend, self.removed), ] self.library = AlbumLibrary(self.underlying) # Populate for every test self.underlying.add(self.Frange(12)) def tearDown(self): for s in self._sigs: self.underlying.disconnect(s) self.underlying.destroy() self.library.destroy() def test_get(self): key = self.underlying.get("file_1.mp3").album_key self.failUnlessEqual(self.library.get(key).title, "Album 1") album = self.library.get(key) self.failUnlessEqual(album.key, key) self.failUnlessEqual(len(album.songs), 4) key = self.underlying.get("file_2.mp3").album_key self.failUnlessEqual(self.library.get(key).title, "Album 2") def test_getitem(self): key = self.underlying.get("file_4.mp3").album_key self.failUnlessEqual(self.library[key].key, key) def test_keys(self): self.failUnless(len(self.library.keys()), 3) def test_has_key(self): key = self.underlying.get("file_1.mp3").album_key self.failUnless(self.library.has_key(key)) def test_misc_collection(self): self.failUnless(self.library.values()) def test_items(self): self.failUnlessEqual(len(self.library.items()), 3) def test_items_2(self): albums = self.library.values() self.failUnlessEqual(len(albums), 3) songs = self.underlying._contents.values() # Make sure "all the songs' albums" == "all the albums", roughly self.failUnlessEqual({a.key for a in albums}, {s.album_key for s in songs}) def test_remove(self): key = self.underlying.get("file_1.mp3").album_key songs = self.underlying._contents # Remove all songs in Album 1 for i in range(1, 12, 3): song = songs["file_%d.mp3" % i] self.underlying.remove([song]) # Album 1 is all gone... self.failUnlessEqual(self.library.get(key), None) # ...but Album 2 is fine key = self.underlying.get("file_2.mp3").album_key album2 = self.library[key] self.failUnlessEqual(album2.key, key) self.failUnlessEqual(len(album2.songs), 4) def test_misc(self): # It shouldn't implement FileLibrary etc self.failIf(getattr(self.library, "filename", None)) class TAlbumLibrarySignals(TestCase): def setUp(self): lib = SongLibrary() received = [] def listen(name, items): received.append(name) self._sigs = [ connect_obj(lib, 'added', listen, 'added'), connect_obj(lib, 'changed', listen, 'changed'), connect_obj(lib, 'removed', listen, 'removed'), ] albums = lib.albums self._asigs = [ connect_obj(albums, 'added', listen, 'a_added'), connect_obj(albums, 'changed', listen, 'a_changed'), connect_obj(albums, 'removed', listen, 'a_removed'), ] self.lib = lib self.albums = albums self.received = received def test_add_one(self): self.lib.add([AlbumSong(1)]) self.failUnlessEqual(self.received, ["added", "a_added"]) def test_add_two_same(self): self.lib.add([AlbumSong(1, "a1")]) self.lib.add([AlbumSong(5, "a1")]) self.failUnlessEqual(self.received, ["added", "a_added", "added", "a_changed"]) def test_remove(self): songs = [AlbumSong(1, "a1"), AlbumSong(2, "a1"), AlbumSong(4, "a2")] self.lib.add(songs) self.lib.remove(songs[:2]) self.failUnlessEqual(self.received, ["added", "a_added", "removed", "a_removed"]) def test_change(self): songs = [AlbumSong(1, "a1"), AlbumSong(2, "a1"), AlbumSong(4, "a2")] self.lib.add(songs) self.lib.changed(songs) self.failUnlessEqual(self.received, ["added", "a_added", "changed", "a_changed"]) def tearDown(self): for s in self._asigs: self.albums.disconnect(s) for s in self._sigs: self.lib.disconnect(s) self.lib.destroy() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_file.py����������������������������������������������������������0000644�0001750�0001750�00000026062�14266344767�017452� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from pathlib import Path from time import sleep import pytest as pytest from quodlibet import config, app, print_d from quodlibet.library import SongFileLibrary from quodlibet.library.file import FileLibrary from quodlibet.util.library import get_exclude_dirs from quodlibet.util.path import normalize_path from senf import text2fsn from tests import (mkdtemp, get_data_path, run_gtk_loop, _TEMP_DIR, init_fake_app, destroy_fake_app) from tests.helper import temp_filename from tests.test_library_libraries import TLibrary, FakeSongFile, FakeAudioFile class TFileLibrary(TLibrary): Fake = FakeSongFile Library = FileLibrary def test_mask_invalid_mount_point(self): new = self.Fake(1) self.library.add([new]) self.failIf(self.library.masked_mount_points) self.failUnless(len(self.library)) self.library.mask("/adsadsafaf") self.failIf(self.library.masked_mount_points) self.library.unmask("/adsadsafaf") self.failIf(self.library.masked_mount_points) self.failUnless(len(self.library)) def test_mask_basic(self): new = self.Fake(1) self.library.add([new]) self.failIf(self.library.masked_mount_points) self.library.mask(new.mountpoint) self.failUnlessEqual(self.library.masked_mount_points, [new.mountpoint]) self.failIf(len(self.library)) self.failUnlessEqual(self.library.get_masked(new.mountpoint), [new]) self.failUnless(self.library.masked(new)) self.library.unmask(new.mountpoint) self.failUnless(len(self.library)) self.failUnlessEqual(self.library.get_masked(new.mountpoint), []) def test_remove_masked(self): new = self.Fake(1) self.library.add([new]) self.library.mask(new.mountpoint) self.failUnless(self.library.masked_mount_points) self.library.remove_masked(new.mountpoint) self.failIf(self.library.masked_mount_points) def test_content_masked(self): new = self.Fake(100) new._mounted = False self.failIf(self.library.get_content()) self.library._load_init([new]) self.failUnless(self.library.masked(new)) self.failUnless(self.library.get_content()) def test_init_masked(self): new = self.Fake(100) new._mounted = False self.library._load_init([new]) self.failIf(self.library.items()) self.failUnless(self.library.masked(new)) def test_load_init_nonmasked(self): new = self.Fake(200) new._mounted = True self.library._load_init([new]) self.failUnlessEqual(list(self.library.values()), [new]) def test_reload(self): new = self.Fake(200) self.library.add([new]) changed = set() removed = set() self.library.reload(new, changed=changed, removed=removed) self.assertTrue(new in changed) self.assertFalse(removed) def test_move_root(self): # TODO: mountpoint tests too self.library.filename = "moving" root = Path(normalize_path(mkdtemp(), True)) other_root = Path(normalize_path(mkdtemp(), True)) new_root = Path(normalize_path(mkdtemp(), True)) in_song = FakeAudioFile(str(root / "in file.mp3")) out_song = FakeAudioFile(str(other_root / "out file.mp3")) # Make sure they exist in_song.sanitize() out_song.sanitize() assert Path(in_song("~dirname")) == root, "test setup wrong" assert Path(out_song("~dirname")) == other_root, "test setup wrong" self.library.add([out_song, in_song]) # Run it by draining the generator list(self.library.move_root(root, str(new_root))) msg = f"Dir wasn't updated in {root!r} -> {new_root!r} for {in_song.key}" assert Path(in_song("~dirname")) == new_root, msg assert Path(in_song("~filename")) == (new_root / "in file.mp3") assert Path(out_song("~dirname")) == other_root, f"{out_song} was wrongly moved" assert in_song._written, "Song wasn't written to disk" assert not out_song._written, "Excluded songs was written!" def test_move_root_gone_source_dir(self): # See #3967 self.library.filename = "moving" gone_root = Path(normalize_path("/gone", True)) new_root = Path(normalize_path(mkdtemp(), True)) song = FakeAudioFile(str(gone_root / "in file.mp3")) assert Path(song("~dirname")) == gone_root, "test setup wrong" self.library.add([song]) # Run it by draining the generator list(self.library.move_root(gone_root, str(new_root))) assert Path(song("~dirname")) == new_root assert song._written, "Song wasn't written to disk" def test_remove_roots(self): self.library.filename = "removing" root = Path(normalize_path(mkdtemp(), True)) other_root = Path(normalize_path(mkdtemp(), True)) out_song = FakeAudioFile(str(other_root / "out file.mp3")) in_song = FakeAudioFile(str(root / "in file.mp3")) in_song.sanitize() out_song.sanitize() self.library.add([in_song, out_song]) assert in_song in self.library, "test seems broken" # Run it by draining the generator list(self.library.remove_roots([root])) assert in_song not in self.library assert out_song in self.library, "removed too many files" assert self.removed == [in_song], "didn't signal the song removal" assert not self.changed, "shouldn't have changed any tracks" class TWatchedFileLibrary(TLibrary): Fake = FakeSongFile temp_path = Path(normalize_path(os.path.expanduser(_TEMP_DIR), True)).resolve() def setUp(self): init_fake_app() config.set("library", "watch", True) super().setUp() # Replace global one with this one librarian = app.library.librarian app.library.destroy() self.library.librarian = librarian app.library = self.library self.library.filename = "watching" librarian.register(self.library, "main") assert self.library.librarian.libraries def test_test_setup(self): assert self.temp_path.is_dir() assert self.temp_path.is_absolute() assert not self.temp_path.is_symlink(), "Symlinks cause trouble in these tests" assert not get_exclude_dirs() def tearDown(self): destroy_fake_app() def Library(self): lib = SongFileLibrary(watch_dirs=[text2fsn(str(self.temp_path))]) # Setup needs copools run_gtk_loop() return lib def test_monitors(self): monitors = self.library._monitors assert monitors, "Not monitoring any dirs" temp_path = Path(self.temp_path) assert temp_path in monitors, f"Not monitoring {temp_path} (but {monitors})" @pytest.mark.flaky(max_runs=3, min_passes=2) def test_watched_adding_removing(self): with temp_filename(dir=self.temp_path, suffix=".mp3", as_path=True) as path: shutil.copy(Path(get_data_path("silence-44-s.mp3")), path) sleep(0.5) run_gtk_loop() assert path.exists() assert str(path) in self.library, f"{path} should be in [{self.fns}] now" assert not path.exists(), "Failed to delete test file" sleep(0.5) # Deletion now run_gtk_loop() assert self.removed, "Nothing was automatically removed" assert self.added, "Nothing was automatically added" assert {Path(af("~filename")) for af in self.added} == {path} assert {Path(af("~filename")) for af in self.removed} == {path} assert str(path) not in self.library, f"{path} shouldn't be in the library now" def test_watched_adding(self): with temp_filename(dir=self.temp_path, suffix=".mp3", as_path=True) as path: shutil.copy(Path(get_data_path("silence-44-s.mp3")), path) assert self.temp_path in path.parents, "Copied test file incorrectly" watch_dirs = self.library._monitors.keys() assert path.parent in watch_dirs, "Not monitoring directory of new file" run_gtk_loop() assert self.library, f"Nothing in library despite watches on {watch_dirs}" assert str(path) in self.library, (f"{path!s} should have been added to " f"library [{self.fns}]") assert str(path) in {af("~filename") for af in self.added} def test_watched_moving_song(self): with temp_filename(dir=self.temp_path, suffix=".flac", as_path=True) as path: shutil.copy(Path(get_data_path("silence-44-s.flac")), path) sleep(0.2) assert path.exists() run_gtk_loop() assert str(path) in self.library, f"New path {path!s} didn't get added" assert len(self.added) == 1 assert self.added[0]("~basename") == path.name self.added.clear() # Now move it... new_path = path.parent / f"moved-{path.name}" path.rename(new_path) sleep(0.2) assert not path.exists(), "test should have removed old file" assert new_path.exists(), "test should have renamed file" print_d(f"New test file at {new_path}") run_gtk_loop() p = normalize_path(str(new_path), True) assert p in self.library, f"New path {new_path} not in library [{self.fns}]" msg = "Inconsistent events: should be (added and removed) or nothing at all" assert not (bool(self.added) ^ bool(self.removed)), msg def test_watched_moving_dir(self): temp_dir = self.temp_path / "old" temp_dir.mkdir(exist_ok=False) sleep(0.2) run_gtk_loop() assert temp_dir in self.library._monitors with temp_filename(dir=temp_dir, suffix=".flac", as_path=True) as path: shutil.copy(Path(get_data_path("silence-44-s.flac")), path) sleep(0.2) assert path.exists() run_gtk_loop() assert str(path) in self.library, f"New path {path!s} didn't get added" assert len(self.added) == 1 self.added.clear() assert self.library # Now move the directory... new_dir = path.parent.parent / "new" temp_dir.rename(new_dir) assert new_dir.is_dir(), "test should have moved to new dir" sleep(0.2) run_gtk_loop() new_path = new_dir / path.name assert new_path.is_file() msg = f"New path {new_path} not in library [{self.fns}]. Did move_root run?" assert str(new_path) in self.library, msg assert not self.removed, "A file was removed" @property def fns(self) -> str: return ", ".join(s("~filename") for s in self.library) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_librarians.py����������������������������������������������������0000664�0001750�0001750�00000014750�14231604332�020637� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, run_gtk_loop from quodlibet.util import connect_obj from quodlibet.library import SongLibrarian, SongFileLibrary from quodlibet.library.base import Library from quodlibet.library.librarians import Librarian from tests.test_library_libraries import Fake, Frange, FakeSongFile, FSrange class TLibrarian(TestCase): Fake = Fake Frange = staticmethod(Frange) Librarian = Librarian Library = Library def setUp(self): self.librarian = self.Librarian() self.Library.librarian = self.librarian self.lib1 = self.Library("One") self.lib2 = self.Library("Two") self.added_1 = [] self.changed_1 = [] self.removed_1 = [] self.added_2 = [] self.changed_2 = [] self.removed_2 = [] self.added = [] self.changed = [] self.removed = [] connect_obj(self.lib1, 'added', list.extend, self.added_1) connect_obj(self.lib1, 'changed', list.extend, self.changed_1) connect_obj(self.lib1, 'removed', list.extend, self.removed_1) connect_obj(self.lib2, 'added', list.extend, self.added_2) connect_obj(self.lib2, 'changed', list.extend, self.changed_2) connect_obj(self.lib2, 'removed', list.extend, self.removed_2) connect_obj(self.librarian, 'added', list.extend, self.added) connect_obj(self.librarian, 'changed', list.extend, self.changed) connect_obj(self.librarian, 'removed', list.extend, self.removed) def test_libraries(self): self.failUnlessEqual(len(self.librarian.libraries), 2) self.failUnless(self.lib1 in self.librarian.libraries.values()) self.failUnless(self.lib2 in self.librarian.libraries.values()) def test_register_at_instantiation(self): try: lib = self.Library("Three") self.failUnlessEqual(len(self.librarian.libraries), 3) finally: lib.destroy() def test_register_later(self): try: lib = self.Library() self.failUnlessEqual(len(self.librarian.libraries), 2) self.librarian.register(lib, "Three") self.failUnlessEqual(len(self.librarian.libraries), 3) finally: lib.destroy() def test_register_exists(self): self.failUnlessRaises(ValueError, self.Library, "Two") def test_unregister(self): self.lib2.destroy() self.failUnlessEqual(len(self.librarian.libraries), 1) self.failUnless(self.lib1 in self.librarian.libraries.values()) self.failIf(self.lib2 in self.librarian.libraries.values()) self.lib1.destroy() self.failUnlessEqual(len(self.librarian.libraries), 0) def test_added(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) self.failUnlessEqual(sorted(self.added), self.Frange(24)) def test_removed(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) self.lib1.remove([self.Fake(9)]) self.lib2.remove([self.Fake(16)]) self.failUnlessEqual(self.removed, [self.Fake(9), self.Fake(16)]) def test_changed(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) self.librarian.changed(self.Frange(6, 18)) run_gtk_loop() self.failUnlessEqual(sorted(self.changed), self.Frange(6, 18)) self.failUnlessEqual(self.changed_1, self.Frange(6, 12)) self.failUnlessEqual(self.changed_2, self.Frange(12, 18)) def test___getitem__(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) self.failUnlessEqual(self.librarian[10], 10) new = self.Fake(100) new.key = 200 self.lib2.add([new]) self.failUnlessEqual(self.librarian[200], new) def test___getitem___not_present(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) self.lib2.remove([self.Fake(16)]) self.failUnlessRaises(KeyError, self.librarian.__getitem__, 16) self.failUnlessRaises(KeyError, self.librarian.__getitem__, 99) def test___contains__(self): self.lib1.add(self.Frange(12)) self.lib2.add(self.Frange(12, 24)) new = self.Fake(100) new.key = 200 self.lib1.add([new]) for value in [1, 2, 15, 22, 200, new]: self.failUnless(value in self.librarian, "didn't find %d" % value) for value in [-1, 25, 50, 100]: self.failIf(value in self.librarian, "found %d" % value) def tearDown(self): self.Library.librarian = None self.lib1.destroy() self.lib2.destroy() self.librarian.destroy() class TSongLibrarian(TLibrarian): Fake = FakeSongFile Frange = staticmethod(FSrange) Library = SongFileLibrary Librarian = SongLibrarian def test_tag_values(self): self.lib1.add(self.Frange(0, 30, 2)) self.lib2.add(self.Frange(1, 30, 2)) del(self.added[:]) self.failUnlessEqual( sorted(self.librarian.tag_values(20)), list(range(20))) self.failUnlessEqual(sorted(self.librarian.tag_values(0)), []) self.failIf(self.changed or self.added or self.removed) def test_rename(self): new = self.Fake(10) new.key = 30 self.lib1.add([new]) self.lib2.add([new]) self.librarian.rename(new, 20) run_gtk_loop() self.failUnlessEqual(new.key, 20) self.failUnless(new in self.lib1) self.failUnless(new in self.lib2) self.failUnless(new.key in self.lib1) self.failUnless(new.key in self.lib2) self.failUnlessEqual(self.changed_1, [new]) self.failUnlessEqual(self.changed_2, [new]) self.failUnless(new in self.changed) def test_rename_changed(self): new = self.Fake(10) self.lib1.add([new]) changed = set() self.librarian.rename(new, 20, changed=changed) self.assertEqual(len(changed), 1) self.assertTrue(new in changed) def test_reload(self): new = self.Fake(10) self.lib1.add([new]) changed = set() removed = set() self.librarian.reload(new, changed=changed, removed=removed) self.assertTrue(new in changed) self.assertFalse(removed) ������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656278102.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_libraries.py�����������������������������������������������������0000664�0001750�0001750�00000026244�14256146126�020477� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from quodlibet.formats import AudioFile from quodlibet.library.base import (Library, iter_paths, PicklingMixin) from quodlibet.util import connect_obj, is_windows from senf import fsnative from tests import TestCase, mkstemp, mkdtemp, skipIf, run_gtk_loop class Fake(int): def __init__(self, _): self.key = int(self) def keys(self): return [] def get(self, tag, default=None): return default def Frange(*args): return list(map(Fake, range(*args))) class FakeSong(Fake): def list(self, tag): # Turn tag_values into a less-than query, for testing. if tag <= self: return [] else: return [int(self)] def rename(self, newname): self.key = newname class AlbumSong(AudioFile): """A mock AudioFile belong to one of three albums, based on a single number""" def __init__(self, num, album=None): super().__init__() self["~filename"] = fsnative(u"file_%d.mp3" % (num + 1)) self["title"] = "Song %d" % (num + 1) self["artist"] = "Fakeman" if album is None: self["album"] = "Album %d" % (num % 3 + 1) else: self["album"] = album self["labelid"] = self["album"] class FakeSongFile(FakeSong): _valid = True _exists = True _mounted = True @property def mountpoint(self): return "/" if self._mounted else "/FAKE" def valid(self): return self._valid def exists(self): return self._exists def reload(self): if self._exists: self._valid = True else: raise IOError("doesn't exist") def mounted(self): return self._mounted # Custom range functions, to generate lists of song-like objects def FSFrange(*args): return list(map(FakeSongFile, range(*args))) def FSrange(*args): return list(map(FakeSong, range(*args))) def ASrange(*args): return list(map(AlbumSong, range(*args))) class TLibrary(TestCase): Fake = Fake Frange = staticmethod(Frange) Library = Library def setUp(self): self.library = self.Library() self.added = [] self.changed = [] self.removed = [] connect_obj(self.library, 'added', list.extend, self.added) connect_obj(self.library, 'changed', list.extend, self.changed) connect_obj(self.library, 'removed', list.extend, self.removed) def test_add(self): self.library.add(self.Frange(12)) self.failUnlessEqual(self.added, self.Frange(12)) del self.added[:] self.library.add(self.Frange(12, 24)) self.failUnlessEqual(self.added, self.Frange(12, 24)) def test_remove(self): self.library.add(self.Frange(10)) self.assertTrue(self.library.remove(self.Frange(3, 6))) self.failUnlessEqual(self.removed, self.Frange(3, 6)) # Neither the objects nor their keys should be present. self.failIf(self.Fake(3) in self.library) self.failUnless(self.Fake(6) in self.library) self.failIf(3 in self.library) self.failUnless(6 in self.library) def test_remove_when_not_present(self): self.assertFalse(self.library.remove([self.Fake(12)])) def test_changed(self): self.library.add(self.Frange(10)) self.library.changed(self.Frange(5)) run_gtk_loop() self.failUnlessEqual(self.changed, self.Frange(5)) def test_changed_not_present(self): self.library.add(self.Frange(10)) self.library.changed(self.Frange(2, 20, 3)) run_gtk_loop() self.failUnlessEqual(set(self.changed), {2, 5, 8}) def test_changed_none_present(self): self.library.changed(self.Frange(5)) run_gtk_loop() def test___iter__(self): self.library.add(self.Frange(10)) self.failUnlessEqual(sorted(list(self.library)), self.Frange(10)) def test___iter___empty(self): self.failIf(list(self.library)) def test___len__(self): self.failUnlessEqual(len(self.library), 0) self.library.add(self.Frange(10)) self.failUnlessEqual(len(self.library), 10) self.library.remove(self.Frange(3)) self.failUnlessEqual(len(self.library), 7) def test___getitem__(self): self.library.add(self.Frange(10)) self.failUnlessEqual(self.library[5], Fake(5)) new = self.Fake(12) new.key = 100 self.library.add([new]) self.failUnlessEqual(self.library[100], new) self.failIf(12 in self.library) def test___getitem___not_present(self): self.library.add(self.Frange(10)) self.failUnlessRaises(KeyError, self.library.__getitem__, 12) def test___contains__(self): self.library.add(self.Frange(10)) new = self.Fake(12) new.key = 100 self.library.add([new]) for value in [0, 1, 2, 6, 9, 100, new]: # 0, 1, 2, 6, 9: all added by self.Frange # 100: key for new # new: is itself present self.failUnless(value in self.library, "didn't find %s" % value) for value in [-1, 10, 12, 101]: # -1, 10, 101: boundary values # 12: equal but non-key-equal to new self.failIf(value in self.library, "found %d" % value) def test_get(self): self.failUnless(self.library.get(12) is None) self.failUnless(self.library.get(12, "foo") == "foo") new = self.Fake(12) new.key = 100 self.library.add([new]) self.failUnless(self.library.get(12) is None) self.failUnless(self.library.get(100) is new) def test_keys(self): items = [] for i in range(20): items.append(self.Fake(i)) items[-1].key = i + 100 self.library.add(items) self.failUnlessEqual( sorted(self.library.keys()), list(range(100, 120))) def test_values(self): items = [] for i in range(20): items.append(self.Fake(i)) items[-1].key = i + 100 self.library.add(items) self.failUnlessEqual(sorted(self.library.values()), list(self.Frange(20))) def test_items(self): items = [] for i in range(20): items.append(self.Fake(i)) items[-1].key = i + 100 self.library.add(items) expected = list(zip(range(100, 120), range(20))) self.failUnlessEqual(sorted(self.library.items()), expected) def test_has_key(self): self.failIf(self.library.has_key(10)) new = self.Fake(10) new.key = 20 self.library.add([new]) self.failIf(self.library.has_key(10)) self.failUnless(self.library.has_key(20)) def tearDown(self): self.library.destroy() class FakeAudioFile(AudioFile): def __init__(self, key): self._written = [] self["~filename"] = fsnative(str(key)) def write(self): self._written.append(self("~filename")) def FakeAudioFileRange(*args): return list(map(FakeAudioFile, range(*args))) class TPicklingMixin(TestCase): class PicklingMockLibrary(PicklingMixin, Library): """A library-like class that implements enough to test PicklingMixin""" def __init__(self): super().__init__(name="Mock") self._contents = {} # set up just enough of the library interface to work self.values = self._contents.values self.items = self._contents.items def add(self, items): for item in items: self._contents[item.key] = item Library = PicklingMockLibrary Frange = staticmethod(FakeAudioFileRange) def setUp(self): self.library = self.Library() def test_load_noexist(self): fd, filename = mkstemp() os.close(fd) os.unlink(filename) library = self.Library() library.load(filename) assert len(library) == 0 def test_load_invalid(self): fd, filename = mkstemp() os.write(fd, b"nope") os.close(fd) try: library = self.Library() library.load(filename) assert len(library) == 0 finally: os.unlink(filename) def test_save_load(self): fd, filename = mkstemp() os.close(fd) try: self.library.add(self.Frange(30)) self.library.save(filename) library = self.Library() library.load(filename) for (k, v), (k2, v2) in zip( sorted(self.library.items()), sorted(library.items())): assert k == k2 assert v.key == v2.key finally: os.unlink(filename) class Titer_paths(TestCase): def setUp(self): # on osx the temp folder returned is a symlink self.root = os.path.realpath(mkdtemp()) def tearDown(self): shutil.rmtree(self.root) def test_empty(self): assert list(iter_paths(self.root)) == [] def test_one_file(self): fd, name = mkstemp(dir=self.root) os.close(fd) assert list(iter_paths(self.root)) == [name] def test_one_file_exclude(self): fd, name = mkstemp(dir=self.root) os.close(fd) assert list(iter_paths(self.root, exclude=[self.root])) == [] assert list(iter_paths(self.root, exclude=[os.path.dirname(self.root)])) == [] assert list(iter_paths(self.root, exclude=[name])) == [] assert list(iter_paths(self.root, exclude=[name + "a"])) == [name] @skipIf(is_windows(), "no symlink") def test_with_dir_symlink(self): child = mkdtemp(dir=self.root) link = os.path.join(self.root, "foo") os.symlink(child, link) fd, name = mkstemp(dir=link) os.close(fd) assert name not in list(iter_paths(self.root)) assert list(iter_paths(link)) == list(iter_paths(child)) assert list(iter_paths(link, exclude=[link])) == [] assert list(iter_paths(child, exclude=[child])) == [] assert list(iter_paths(link, exclude=[child])) == [] @skipIf(is_windows(), "no symlink") def test_with_file(self): fd, name = mkstemp(dir=self.root) os.close(fd) link = os.path.join(self.root, "foo") os.symlink(name, link) assert list(iter_paths(self.root)) == [name, name] assert list(iter_paths(self.root, exclude=[link])) == [name] assert list(iter_paths(self.root, exclude=[name])) == [] def test_hidden_dir(self): child = mkdtemp(dir=self.root, prefix=".") fd, name = mkstemp(dir=child) os.close(fd) assert list(iter_paths(child)) == [] assert list(iter_paths(child, skip_hidden=False)) == [name] assert list(iter_paths(self.root)) == [] assert list(iter_paths(self.root, skip_hidden=False)) == [name] def test_hidden_file(self): fd, name = mkstemp(dir=self.root, prefix=".") os.close(fd) assert list(iter_paths(self.root)) == [] ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_playlist.py������������������������������������������������������0000664�0001750�0001750�00000016744�14231604507�020363� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from pathlib import Path from quodlibet import app from quodlibet.formats import AudioFile from quodlibet.library import SongFileLibrary from quodlibet.util import connect_obj from quodlibet.util.collection import Playlist, FileBackedPlaylist from tests import TestCase, _TEMP_DIR from tests.test_library_libraries import FakeSong from quodlibet.library.playlist import _DEFAULT_PLAYLIST_DIR def AFrange(*args): songs = [ AudioFile({"~filename": f"/tmp/{i}.mp3", "artist": "Foo", "title": f"track-{i}"}) for i in range(*args)] # Need a mountpoint, or everything goes wrong... for song in songs: song.sanitize() return songs PL_NAME = "The Only" class TPlaylistLibrary(TestCase): Fake = FakeSong Frange = staticmethod(AFrange) UnderlyingLibrary = SongFileLibrary def setUp(self): self.underlying = self.UnderlyingLibrary() # Need this for ~playlists app.library = self.underlying self.added = [] self.changed = [] self.removed = [] self._sigs = [ connect_obj(self.underlying, 'changed', list.extend, self.changed), connect_obj(self.underlying, 'removed', list.extend, self.removed), ] for song in self.underlying: song.sanitize() # Populate for every test self.underlying.add(self.Frange(12)) pl_dir = Path(_TEMP_DIR) / _DEFAULT_PLAYLIST_DIR self.create_playlist_file(pl_dir) self.add_ignored_file(pl_dir) # Creates the library self.library = self.underlying.playlists def create_playlist_file(self, pl_dir) -> None: # Won't exist, we haven't started the library yet temp_path = Path(_TEMP_DIR).absolute() parents = {path.absolute() for path in pl_dir.parents} assert temp_path in parents or os.environ.get('CI', False), "Dangerous test!" shutil.rmtree(pl_dir, ignore_errors=True) os.makedirs(pl_dir) fn = FileBackedPlaylist.filename_for(PL_NAME) # No PL library given - rely on import self.pl = pl = FileBackedPlaylist(str(pl_dir), fn, self.underlying, None) pl.extend(list(sorted(self.underlying))[-3:]) assert len(pl) == 3, "Should have only the three songs just added" diff = set(self.underlying) - set(pl) assert all(song in self.underlying for song in pl), f"Missing from lib: {diff}" pl.finalize() pl.write() @staticmethod def add_ignored_file(pl_dir): # See #3639 with open(pl_dir / ".gitignore", "w") as f: f.write(".backup\n") def tearDown(self): for pl in list(self.library.values()): pl.delete() for s in self._sigs: self.underlying.disconnect(s) self.underlying.destroy() # Don't destroy self.library, it's a reference which is gone app.library = None def test_migrate(self): pl_path = Path(self.library.pl_dir) path = pl_path / f"{PL_NAME}.xspf" assert path.exists(), f"New playlist not found - got {os.listdir(pl_path)}" def test_old_playlist_removed(self): pl_path = Path(self.library.pl_dir) fn = FileBackedPlaylist.filename_for(PL_NAME) old_path = pl_path / fn assert not old_path.exists(), "Didn't remove old playlist" assert len(self.library) == 1 def test_save_with_name(self): song = AudioFile({"~filename": "/dev/null", "title": "Hello, World"}) pl = self.library.create_from_songs([song], title="moondance!") assert pl.name == "moondance!" def test_backup(self): pl_path = Path(self.library.pl_dir) fn = FileBackedPlaylist.filename_for(PL_NAME) backup = (pl_path / ".backup" / fn) assert backup.exists(), "Didn't backup" with open(backup) as f: lines = f.readlines() assert len(lines) == 3 def test_dotfiles_ignored(self): pl_path = Path(self.library.pl_dir) ignore_path = pl_path / ".gitignore" assert ignore_path.exists(), "Shouldn't have removed hidden file" assert not any("gitignore" in pl.name for pl in self.library) def test_get(self): pl = self.library.get(PL_NAME) assert pl, f"Not found - got {self.library.items()}" assert pl.name == PL_NAME assert pl.key == PL_NAME assert len(pl.songs) == 3 assert not self.underlying.get("Another") def test_keys(self): assert list(self.library.keys()) == [PL_NAME] def test_has_key(self): assert self.library.has_key(PL_NAME) def test_misc_collection(self): self.failUnless(self.library.values()) def test_items(self): assert self.library.items() == [(PL_NAME, self.pl)] def test_remove_songs(self): pl = self.library[PL_NAME] all_contents = list(self.underlying.values()) assert all(song in self.underlying for song in pl), "Not all songs are in lib" removed = self.underlying.remove(all_contents) assert set(removed) == set(all_contents), "Not everything removed from lib" assert not pl, f"PL should be empty, has: {list(pl)}" def test_misc(self): # It shouldn't implement FileLibrary etc self.failIf(getattr(self.library, "filename", None)) class TPlaylistLibrarySignals(TestCase): def setUp(self): self.lib = lib = SongFileLibrary() self.received = [] def listen(name, items): self.received.append(name) self._sigs = [ connect_obj(lib, 'added', listen, 'added'), connect_obj(lib, 'changed', listen, 'changed'), connect_obj(lib, 'removed', listen, 'removed'), ] self.playlists = lib.playlists self._asigs = [ connect_obj(self.playlists, 'added', listen, 'pl_added'), connect_obj(self.playlists, 'changed', listen, 'pl_changed'), connect_obj(self.playlists, 'removed', listen, 'pl_removed'), ] songs = AFrange(3) self.lib.add(songs) def test_add_remove(self): pl = Playlist("only", self.lib, self.playlists) assert self.received == ["added", "pl_added"] self.received.clear() # Update playlist, should trigger changes in files too pl.extend(self.lib._contents.values()) # Changing files then does trigger another change, # annoying but seems impossible to avoid if we want to save metadata, ~playlists assert self.received == ["pl_changed", "changed", "pl_changed"] self.received.clear() # Remove some songs and watch the playlist change songs = list(self.lib._contents.values()) self.lib.remove(songs[:2]) assert self.received == ["removed", "pl_changed", "changed", "pl_changed"] self.received.clear() pl.delete() assert self.received == ["pl_removed"] def test_songs_changes_have_no_effect(self): self.received.clear() self.lib.changed(list(self.lib)[0:1]) assert self.received == ["changed"] def tearDown(self): for s in self._asigs: self.playlists.disconnect(s) for s in self._sigs: self.lib.disconnect(s) self.lib.destroy() ����������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_library_song.py����������������������������������������������������������0000664�0001750�0001750�00000015016�14231604507�017457� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from quodlibet import config from quodlibet.formats import AudioFileError from quodlibet.library import SongLibrary, SongFileLibrary from tests import get_data_path, run_gtk_loop from tests.helper import get_temp_copy, capture_output from tests.test_library_libraries import (TLibrary, FakeSong, FSrange, FakeSongFile, FSFrange) from tests.test_util_collection import NUMERIC_SONGS class TSongLibrary(TLibrary): Fake = FakeSong Frange = staticmethod(FSrange) Library = SongLibrary def test_rename_dirty(self): self.library.dirty = False song = self.Fake(10) self.library.add([song]) self.failUnless(self.library.dirty) self.library.dirty = False self.library.rename(song, 20) self.failUnless(self.library.dirty) def test_rename(self): song = self.Fake(10) self.library.add([song]) self.library.rename(song, 20) run_gtk_loop() self.failUnless(song in self.changed) self.failUnless(song in self.library) self.failUnless(song.key in self.library) self.failUnlessEqual(song.key, 20) def test_rename_changed(self): song = self.Fake(10) self.library.add([song]) changed = set() self.library.rename(song, 20, changed=changed) self.assertEqual(len(changed), 1) self.assertTrue(song in changed) def test_tag_values(self): self.library.add(self.Frange(30)) del self.added[:] self.failUnlessEqual( sorted(self.library.tag_values(10)), list(range(10))) self.failUnlessEqual(sorted(self.library.tag_values(0)), []) self.failIf(self.changed or self.added or self.removed) class TSongFileLibrary(TSongLibrary): Fake = FakeSongFile Frange = staticmethod(FSFrange) Library = SongFileLibrary def test__load_exists_invalid(self): new = self.Fake(100) new._valid = False changed, removed = self.library._load_item(new) self.failIf(removed) self.failUnless(changed) self.failUnless(new._valid) self.failUnless(new in self.library) def test__load_not_exists(self): new = self.Fake(100) new._valid = False new._exists = False changed, removed = self.library._load_item(new) self.failIf(removed) self.failIf(changed) self.failIf(new._valid) self.failIf(new in self.library) def test__load_error_during_reload(self): try: from quodlibet import util print_exc = util.print_exc util.print_exc = lambda *args, **kwargs: None new = self.Fake(100) def error(): raise AudioFileError new.reload = error new._valid = False changed, removed = self.library._load_item(new) self.failUnless(removed) self.failIf(changed) self.failIf(new._valid) self.failIf(new in self.library) finally: util.print_exc = print_exc def test__load_not_mounted(self): new = self.Fake(100) new._valid = False new._exists = False new._mounted = False changed, removed = self.library._load_item(new) self.failIf(removed) self.failIf(changed) self.failIf(new._valid) self.failIf(new in self.library) self.failUnless(self.library.masked(new)) def __get_file(self): return get_temp_copy(get_data_path('empty.flac')) def test_add_filename(self): config.init() try: filename = self.__get_file() ret = self.library.add_filename(filename) self.failUnless(ret) self.failUnlessEqual(len(self.library), 1) self.failUnlessEqual(len(self.added), 1) ret = self.library.add_filename(filename) self.failUnless(ret) self.failUnlessEqual(len(self.added), 1) os.unlink(filename) filename = self.__get_file() ret = self.library.add_filename(filename, add=False) self.failUnless(ret) self.failIf(ret in self.library) self.failUnlessEqual(len(self.added), 1) self.library.add([ret]) self.failUnless(ret in self.library) self.failUnlessEqual(len(self.added), 2) self.failUnlessEqual(2, len(self.library)) os.unlink(filename) with capture_output(): ret = self.library.add_filename("") self.failIf(ret) self.failUnlessEqual(len(self.added), 2) self.failUnlessEqual(len(self.library), 2) finally: config.quit() def test_contains_filename(self): filename = self.__get_file() try: assert not self.library.contains_filename(filename) assert self.library.add_filename(filename, add=False) assert not self.library.contains_filename(filename) assert self.library.add_filename(filename) assert self.library.contains_filename(filename) finally: os.unlink(filename) def test_add_filename_normalize_path(self): if not os.name == "nt": return config.init() filename = self.__get_file() # create a equivalent path different from the original one if filename.upper() == filename: other = filename.lower() else: other = filename.upper() song = self.library.add_filename(filename) other_song = self.library.add_filename(other) self.assertTrue(song is other_song) os.unlink(filename) config.quit() def test_playlists_featuring(self): pl_lib = self.library.playlists pl = pl_lib.create("playlist1") pl.extend(NUMERIC_SONGS) playlists = pl_lib.playlists_featuring(NUMERIC_SONGS[0]) assert set(playlists) == {pl} # Now add a second one, check that instance tracking works pl2 = pl_lib.create("playlist2") pl2.append(NUMERIC_SONGS[0]) playlists = pl_lib.playlists_featuring(NUMERIC_SONGS[0]) assert set(playlists) == {pl, pl2}, "didn't register playlist2" assert set(pl_lib.playlists_featuring(NUMERIC_SONGS[1])) == {pl} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_metadata.py��������������������������������������������������������������0000664�0001750�0001750�00000007703�14035600052�016542� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import mkstemp, TestCase, get_data_path import os from quodlibet import formats from quodlibet import config from shutil import copyfileobj class TestMetaDataBase(TestCase): base = get_data_path("silence-44-s") def setUp(self): """Copy the base silent file to a temp name/location and load it""" config.init() fd, self.filename = mkstemp(suffix=self.ext, text=False) dst = os.fdopen(fd, 'wb') src = open(self.base + self.ext, 'rb') copyfileobj(src, dst) dst.close() self.song = formats.MusicFile(self.filename) def tearDown(self): """Delete the temp file""" os.remove(self.filename) del self.filename del self.song config.quit() class _TestMetaDataMixin: def test_base_data(self): self.failUnlessEqual(self.song['artist'], 'piman\njzig') self.failUnlessEqual(self.song['album'], 'Quod Libet Test Data') self.failUnlessEqual(self.song['title'], 'Silence') def test_mutability(self): self.failIf(self.song.can_change('=foo')) self.failIf(self.song.can_change('foo~bar')) self.failUnless(self.song.can_change('artist')) self.failUnless(self.song.can_change('title')) self.failUnless(self.song.can_change('tracknumber')) self.failUnless(self.song.can_change('somebadtag')) self.failUnless(self.song.can_change('some%punctuated:tag.')) def _test_tag(self, tag, values, remove=True): self.failUnless(self.song.can_change(tag)) for value in values: self.song[tag] = value self.song.write() written = formats.MusicFile(self.filename) self.failUnlessEqual(written[tag], value) if remove: del self.song[tag] self.song.write() deleted = formats.MusicFile(self.filename) self.failIf(tag in deleted) def test_artist(self): # a normalish tag self._test_tag('artist', [u'me', u'you\nme', u'\u6d5c\u5d0e\u3042\u3086\u307f']) def test_date(self): # unusual special handling for mp3s self._test_tag('date', [u'2004', u'2005', u'2005-06-12'], False) def test_genre(self): # unusual special handling for mp3s self._test_tag('genre', [u'Pop', u'Rock\nClassical', u'Big Bird', u'\u30a2\u30cb\u30e1\u30b5\u30f3\u30c8\u30e9']) def test_odd_performer(self): values = [u"A Person", u"Another"] self._test_tag("performer:vocals", values) self._test_tag("performer:guitar", values) def test_wackjob(self): # undefined tag self._test_tag('wackjob', [u'Jelly\nDanish', u'Muppet', u'\u30cf\u30f3\u30d0\u30fc\u30ac\u30fc']) tags = ['album', 'arranger', 'artist', 'author', 'comment', 'composer', 'conductor', 'copyright', 'discnumber', 'encodedby', 'genre', 'isrc', 'language', 'license', 'lyricist', 'organization', 'performer', 'title', 'tracknumber', 'version', 'xyzzy_undefined_tag', 'musicbrainz_trackid', 'releasecountry'] for ext in formats.loaders.keys(): if os.path.exists(TestMetaDataBase.base + ext): extra_tests = {} for tag in tags: if tag in ['artist', 'date', 'genre']: continue def _test_tag(self, tag=tag): self._test_tag(tag, [u'a']) extra_tests['test_tag_' + tag] = _test_tag def _test_tags(self, tag=tag): self._test_tag(tag, [u'b\nc']) extra_tests['test_tags_' + tag] = _test_tags name = 'MetaData' + ext testcase = type( name, (TestMetaDataBase, _TestMetaDataMixin), extra_tests) testcase.ext = ext globals()[name] = testcase �������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_mmkeys.py����������������������������������������������������������������0000664�0001750�0001750�00000001531�14035600052�016260� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, init_fake_app, destroy_fake_app from quodlibet import app from quodlibet.mmkeys import MMKeysHandler, iter_backends class TMmKeys(TestCase): def setUp(self): init_fake_app() def tearDown(self): destroy_fake_app() def test_handler(self): handler = MMKeysHandler(app) handler.quit() def test_backends(self): for backend in iter_backends(): backend.is_active() instance = backend("Foo", lambda action: None) instance.grab() instance.cancel() instance.cancel() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658680115.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_operon.py����������������������������������������������������������������0000644�0001750�0001750�00000056420�14267271463�016303� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import sys from quodlibet.util import is_osx, is_windows from senf import fsnative, path2fsn from tests import TestCase, get_data_path, mkstemp, skipIf from .helper import capture_output, get_temp_copy from quodlibet import config from quodlibet.formats import MusicFile from quodlibet.operon.main import main as operon_main def call(args): args = [path2fsn(a) for a in args] with capture_output() as (out, err): try: return_code = operon_main([path2fsn("operon.py")] + args) except SystemExit as e: return_code = e.code return (return_code, out.getvalue(), err.getvalue()) class TOperonBase(TestCase): def setUp(self): config.init() self.f = get_temp_copy(get_data_path('silence-44-s.ogg')) self.f2 = get_temp_copy(get_data_path('silence-44-s.mp3')) self.s = MusicFile(self.f) self.s2 = MusicFile(self.f2) fd, self.f3 = mkstemp(".mp3") os.write(fd, b"garbage") os.close(fd) def tearDown(self): os.unlink(self.f) os.unlink(self.f2) os.unlink(self.f3) config.quit() def check_true(self, args, stdout_not_empty, stderr_not_empty, **kwargs): """Assert success status code""" return self._check(args, True, stdout_not_empty, stderr_not_empty, **kwargs) def check_false(self, args, stdout_not_empty, stderr_not_empty, **kwargs): """Assert error status code""" return self._check(args, False, stdout_not_empty, stderr_not_empty, **kwargs) def _check(self, args, command_succeeds, stdout_not_empty, stderr_not_empty): s, o, e = call(args) assert (s == 0) == command_succeeds, repr((s, o, e)) assert bool(o) == stdout_not_empty, repr(o) assert bool(e) == stderr_not_empty, repr(e) return o, e class TOperonMain(TOperonBase): # [--version] [--help] [--verbose] <command> [<args>] def test_main(self): self.check_false([], False, True) self.check_true(["help"], True, False) self.check_false(["help", "foobar"], False, True) # TODO: "image-extract", "rename", "fill", "fill-tracknumber", "edit" # "load" for sub in ["help", "copy", "set", "clear", "remove", "add", "list", "print", "info", "tags"]: self.check_true(["help", sub], True, False) self.check_true(["help", "-h"], True, False) self.check_true(["help", "--help"], True, False) self.check_false(["help", "--foobar"], False, True) self.check_true(["--verbose", "help", "help"], True, False) self.check_true(["-v", "help", "help"], True, False) self.check_false(["--foobar", "help", "help"], False, True) self.check_true(["--version"], True, False) class TOperonAdd(TOperonBase): # add <tag> <value> <file> [<files>] def test_add_misc(self): self.check_false(["add"], False, True) self.check_false(["add", "tag"], False, True) self.check_false(["add", "tag", "value"], False, True) self.check_true(["add", "tag", "value", self.f], False, False) self.check_true(["add", "tag", "value", self.f, self.f], False, False) def test_add_check(self): keys = list(self.s.keys()) self.check_true(["add", "foo", "bar", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s["foo"], "bar") self.failUnlessEqual(len(keys) + 1, len(self.s.keys())) self.check_true(["-v", "add", "foo", "bar2", self.f], False, True) self.s.reload() self.failUnlessEqual(set(self.s.list("foo")), {"bar", "bar2"}) def test_add_backlisted(self): self.check_false(["add", "playcount", "bar", self.f], False, True) def test_permissions(self): try: os.chmod(self.f, 0o000) self.check_false(["add", "foo", "bar", self.f, self.f], False, True) os.chmod(self.f, 0o444) self.check_false(["add", "foo", "bar", self.f, self.f], False, True) finally: os.chmod(self.f, 0o666) class TOperonPrint(TOperonBase): # [-p <pattern>] <file> [<files>] def test_print(self): self.check_false(["print"], False, True) o, e = self.check_true(["print", self.f], True, False) self.failUnlessEqual(o.splitlines()[0], "piman, jzig - Quod Libet Test Data - 02/10 - Silence") o, e = self.check_true(["print", "-p", "<title>", self.f], True, False) self.failUnlessEqual(o.splitlines()[0], "Silence") o, e = self.check_true(["print", "-p", "<title>", self.f, self.f], True, False) self.failUnlessEqual(o.splitlines(), ["Silence", "Silence"]) def test_print_invalid(self): # passing a song which can't be loaded results in fail self.check_false(["print", self.f3], False, True) # in case some fail and some don't, print the error messages for # the failed ones, the patterns for the working ones and return # an error status o, e = self.check_false(["print", self.f3, self.f2], True, True) self.assertTrue("Quod Libet Test Data" in o) @skipIf(is_windows(), "doesn't prevent reading under wine...") def test_permissions(self): os.chmod(self.f, 0o000) self.check_false(["print", "-p", "<title>", self.f], False, True) class TOperonRemove(TOperonBase): # [--dry-run] <tag> [-e <pattern> | <value>] <file> [<files>] def test_error(self): self.check_false(["remove"], False, True) self.check_false(["remove", "tag", "value"], False, True) def test_remove(self): self.s["test"] = "foo\nbar\nfoo" self.s.write() self.check_true(["remove", "tag", "value", self.f], False, False) self.check_true(["remove", "test", "foo", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s["test"], "bar") self.check_true(["-v", "remove", "test", "xxx", self.f, self.f], False, True) self.s.reload() self.failUnlessEqual(self.s["test"], "bar") def test_dry_run(self): self.s["test"] = "foo\nbar\nfoo" self.s.write() self.check_true(["remove", "--dry-run", "test", "foo", self.f], False, True) self.s.reload() self.failUnlessEqual(len(self.s.list("test")), 3) def test_pattern(self): self.s["test"] = "fao\nbar\nfoo" self.s.write() self.check_true(["remove", "test", "-e", "f[ao]o", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s.list("test"), ["bar"]) self.check_true(["-v", "remove", "test", "-e", ".*", self.f], False, True) self.s.reload() self.failIf(self.s.list("test")) class TOperonClear(TOperonBase): # [--dry-run] [-a | -e <pattern> | <tag>] <file> [<files>] def test_misc(self): self.check_false(["clear"], False, True) self.check_false(["clear", self.f], False, True) self.check_true(["clear", "-a", self.f], False, False) self.check_false(["-v", "clear", "-e", self.f], False, True) self.check_true(["-v", "clear", "-e", "xx", self.f], False, True) self.check_true(["clear", "-e", "xx", self.f], False, False) self.check_false(["clear", "-e", "x", "-a", self.f], False, True) def _test_all(self): self.check(["clear", "-a", self.f], True, output=False) self.s.reload() self.failIf(self.s.realkeys()) self.check(["clear", "-a", self.f, self.f], True, output=False) def _test_all_dry_run(self): old_len = len(self.s.realkeys()) self.failUnless(old_len) self.check(["clear", "-a", "--dry-run", self.f], True) self.s.reload() self.failUnlessEqual(len(self.s.realkeys()), old_len) def _test_pattern(self): old_len = len(self.s.realkeys()) self.check(["clear", "-e", "a.*", self.f], True, output=False) self.s.reload() self.failUnlessEqual(len(self.s.realkeys()), old_len - 2) def _test_simple(self): old_len = len(self.s.realkeys()) self.check(["clear", "a.*", self.f], True, output=False) self.s.reload() self.failUnlessEqual(len(self.s.realkeys()), old_len) self.check(["clear", "--dry-run", "artist", self.f], True) self.s.reload() self.failUnlessEqual(len(self.s.realkeys()), old_len) self.check(["clear", "artist", self.f], True, output=False) self.s.reload() self.failUnlessEqual(len(self.s.realkeys()), old_len - 1) class TOperonSet(TOperonBase): # [--dry-run] <tag> <value> <file> [<files>] def test_misc(self): self.check_false(["set"], False, True) self.check_true(["set", "-h"], True, False) self.check_false(["set", "tag", "value"], False, True) self.check_true(["set", "tag", "value", self.f], False, False) self.check_true(["set", "tag", "value", self.f, self.f], False, False) self.check_true(["set", "--dry-run", "tag", "value", self.f], False, False) def test_simple(self): self.check_true(["set", "foo", "bar", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s["foo"], "bar") self.check_true(["set", "--dry-run", "foo", "x", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s["foo"], "bar") def test_replace(self): self.failIfEqual(self.s["artist"], "foobar") self.check_true(["set", "artist", "foobar", self.f], False, False) self.s.reload() self.failUnlessEqual(self.s["artist"], "foobar") class TOperonCopy(TOperonBase): # [--dry-run] [--ignore-errors] <source> <dest> def test_misc(self): self.check_false(["copy"], False, True) self.check_true(["copy", "-h"], True, False) self.check_false(["copy", "foo"], False, True) self.check_true(["copy", self.f, self.f2], False, False) self.check_true(["-v", "copy", self.f, self.f2], False, True) def test_simple(self): for key in self.s2.realkeys(): del self.s2[key] self.s2.write() self.s2.reload() self.failIf(self.s2.realkeys()) self.check_true(["copy", self.f, self.f2], False, False) self.s2.reload() self.failUnless(self.s2.realkeys()) def test_not_changable(self): self.s2["rating"] = "foo" self.s2.write() self.check_false(["copy", self.f2, self.f], False, True) self.check_true(["copy", "--ignore-errors", self.f2, self.f], False, False) def test_add(self): self.failUnlessEqual(len(self.s2.list("genre")), 1) self.check_true(["copy", self.f, self.f2], False, False) self.s2.reload() self.failUnlessEqual(len(self.s2.list("genre")), 2) def test_dry_run(self): for key in self.s2.realkeys(): del self.s2[key] self.s2.write() self.s2.reload() self.check_true(["copy", "--dry-run", self.f, self.f2], False, True) self.s2.reload() self.failIf(self.s2.realkeys()) class TOperonEdit(TOperonBase): # [--dry-run] <file> def test_misc(self): self.check_false(["edit"], False, True) self.check_true(["edit", "-h"], True, False) self.check_false(["edit", "foo", "bar"], False, True) def test_nonexist_editor(self): editor = fsnative(u"/this/path/does/not/exist/hopefully") os.environ["VISUAL"] = editor e = self.check_false(["edit", self.f], False, True)[1] self.assertTrue(editor in e) def test_no_edit(self): if os.name == "nt": return os.environ["VISUAL"] = "touch -t 197001010101" realitems = lambda s: [(k, s[k]) for k in s.realkeys()] old_items = realitems(self.s) self.check_true(["edit", self.f], False, False) self.s.reload() self.assertEqual(sorted(old_items), sorted(realitems(self.s))) def test_mtime(self): if os.name == "nt": return os.environ["VISUAL"] = "true" self.check_false(["edit", self.f], False, True) os.environ["VISUAL"] = "false" self.check_false(["edit", self.f], False, True) def test_dry_run(self): if os.name == "nt" or sys.platform == "darwin": return realitems = lambda s: [(k, s[k]) for k in s.realkeys()] os.environ["VISUAL"] = "truncate -s 0" old_items = realitems(self.s) os.utime(self.f, (42, 42)) e = self.check_true(["edit", "--dry-run", self.f], False, True)[1] # log all removals for key in self.s.realkeys(): self.assertTrue(key in e) # nothing should have changed self.s.reload() self.assertEqual(sorted(old_items), sorted(realitems(self.s))) @skipIf(is_windows() or is_osx(), "Linux only, uses truncate") def test_remove_all(self): os.environ["VISUAL"] = "truncate -s 0" os.utime(self.f, (42, 42)) self.check_true(["edit", self.f], False, False) # all should be gone self.s.reload() assert not self.s.realkeys() class TOperonInfo(TOperonBase): # [-t] [-c <c1>,<c2>...] <file> def test_misc(self): self.check_false(["info"], False, True) self.check_true(["info", self.f], True, False) self.check_false(["info", self.f, self.f2], False, True) self.check_true(["info", "-h"], True, False) def test_normal(self): self.check_true(["info", "-cdesc", self.f], True, False) self.check_true(["info", "-cvalue", self.f], True, False) self.check_true(["info", "-cdesc,value", self.f], True, False) self.check_true(["info", "-cvalue, desc", self.f], True, False) self.check_false(["info", "-cfoo", self.f], False, True) def test_terse(self): self.check_true(["info", "-t", self.f], True, False) self.check_true(["info", "-t", "-cdesc", self.f], True, False) self.check_true(["info", "-t", "-cvalue", self.f], True, False) self.check_true(["info", "-t", "-cdesc,value", self.f], True, False) self.check_true(["info", "-t", "-cvalue, desc", self.f], True, False) self.check_false(["info", "-t", "-cfoo", self.f], False, True) class TOperonList(TOperonBase): # [-t] [-c <c1>,<c2>...] <file> def test_misc(self): self.check_true(["list", "-h"], True, False) self.check_false(["list"], False, True) self.check_true(["list", self.f], True, False) self.check_false(["list", self.f, self.f2], False, True) def test_normal(self): self.check_true(["list", "-cdesc", self.f], True, False) self.check_true(["list", "-cvalue,tag", self.f], True, False) self.check_true(["list", "-cdesc,value", self.f], True, False) self.check_true(["list", "-cvalue, desc", self.f], True, False) self.check_false(["list", "-cfoo", self.f], False, True) def test_terse(self): self.check_true(["list", "-t", self.f], True, False) self.check_true(["list", "-t", "-cdesc", self.f], True, False) self.check_true(["list", "-t", "-cvalue,tag", self.f], True, False) self.check_true(["list", "-t", "-cdesc,value", self.f], True, False) self.check_true(["list", "-t", "-cvalue, desc", self.f], True, False) self.check_false(["list", "-t", "-cfoo", self.f], False, True) def test_terse_escape(self): self.s["foobar"] = "a:bc\\:" self.s.write() d = self.check_true(["list", "-t", "-cvalue", self.f], True, False)[0] lines = d.splitlines() self.assertTrue("a\\:bc\\\\\\:" in lines) class TOperonTags(TOperonBase): # [-t] [-c <c1>,<c2>...] def test_misc(self): self.check_true(["tags", "-h"], True, False) self.check_false(["tags", self.f], False, True) self.check_false(["tags", self.f, self.f2], False, True) def test_normal(self): self.check_true(["tags", "-cdesc"], True, False) self.check_true(["tags", "-ctag"], True, False) self.check_true(["tags", "-ctag, desc"], True, False) self.check_false(["tags", "-cfoo"], False, True) def test_terse(self): self.check_true(["tags", "-t"], True, False) self.check_true(["tags", "-t", "-cdesc"], True, False) self.check_true(["tags", "-t", "-cdesc,tag"], True, False) self.check_true(["tags", "-t", "-ctag, desc"], True, False) self.check_false(["tags", "-t", "-cfoo"], False, True) def test_output(self): o, e = self.check_true(["tags"], True, False) assert not e assert "tracknumber" in o assert "replaygain_album_gain" not in o o, e = self.check_true(["tags", "-a"], True, False) assert not e assert "tracknumber" in o assert "replaygain_album_gain" in o class TOperonImageExtract(TOperonBase): # [--dry-run] [--primary] [-d <destination>] <file> [<files>] def setUp(self): super().setUp() self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) super().tearDown() def test_misc(self): self.check_true(["image-extract", "-h"], True, False) self.check_true(["image-extract", self.f], False, False) self.check_true(["image-extract", self.f, self.f2], False, False) self.check_false(["image-extract"], False, True) def test_extract_all(self): target_dir = os.path.dirname(self.fcover) self.check_true(["image-extract", "-d", target_dir, self.fcover], False, False) self.assertEqual(len(self.cover.get_images()), 1) image = self.cover.get_primary_image() name = os.path.splitext(os.path.basename(self.fcover))[0] expected = "%s-00.%s" % (name, image.extensions[0]) expected_path = os.path.join(target_dir, expected) self.assertTrue(os.path.exists(expected_path)) with open(expected_path, "rb") as h: self.assertEqual(h.read(), image.read()) def test_extract_primary(self): target_dir = os.path.dirname(self.fcover) self.check_true( ["image-extract", "-d", target_dir, "--primary", self.fcover], False, False) self.assertEqual(len(self.cover.get_images()), 1) image = self.cover.get_primary_image() name = os.path.splitext(os.path.basename(self.fcover))[0] expected = "%s.%s" % (name, image.extensions[0]) expected_path = os.path.join(target_dir, expected) self.assertTrue(os.path.exists(expected_path)) with open(expected_path, "rb") as h: self.assertEqual(h.read(), image.read()) class TOperonImageSet(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super().setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) self.fcover2 = get_temp_copy(get_data_path('test-2.wma')) self.cover2 = MusicFile(self.fcover2) def tearDown(self): os.unlink(self.fcover) os.unlink(self.filename) super().tearDown() def test_misc(self): self.check_true(["image-set", "-h"], True, False) self.check_false(["image-set", self.fcover], False, True) self.check_false(["image-set"], False, True) self.check_false(["image-set", self.filename], False, True) def test_not_supported(self): path = get_data_path('test.mid') out, err = self.check_false( ["image-set", self.filename, path], False, True) self.assertTrue("supported" in err) def test_set(self): self.check_true(["image-set", self.filename, self.fcover], False, False) self.check_true(["-v", "image-set", self.filename, self.fcover], False, True) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 1) with open(self.filename, "rb") as h: self.assertEqual(h.read(), images[0].read()) def test_set_two(self): self.check_true( ["image-set", self.filename, self.fcover, self.fcover2], False, False) with open(self.filename, "rb") as h: image_data = h.read() for audio in [self.cover, self.cover2]: audio.reload() image = audio.get_images()[0] self.assertEqual(image.read(), image_data) class TOperonImageClear(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super().setUp() self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) super().tearDown() def test_misc(self): self.check_true(["image-clear", "-h"], True, False) self.check_true(["image-clear", self.fcover], False, False) self.check_false(["image-clear"], False, True) def test_not_supported(self): path = get_data_path('test.mid') out, err = self.check_false(["image-clear", path], False, True) self.assertTrue("supported" in err) def test_clear(self): images = self.cover.get_images() self.assertEqual(len(images), 1) self.check_true(["image-clear", self.fcover], False, False) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 0) class TOperonFill(TOperonBase): # [--dry-run] <pattern> <file> [<files>] def test_misc(self): self.check_true(["fill", "-h"], True, False) self.check_false(["fill", self.f], False, True) self.check_true(["fill", "foo", self.f2], False, False) self.check_true(["fill", "foo", self.f, self.f2], False, False) def test_apply(self): basename = self.s("~basename") self.check_true(["fill", "<title>", self.f], False, False) self.s.reload() self.assertEqual(self.s("title"), os.path.splitext(basename)[0]) def test_apply_no_match(self): old_title = self.s("title") self.check_true( ["fill", "<tracknumber>. <title>", self.f], False, False) self.s.reload() self.assertEqual(self.s("title"), old_title) def test_preview(self): o, e = self.check_true( ["fill", "--dry-run", "<title>", self.f], True, False) self.assertTrue("title" in o) self.assertTrue(self.s("~basename") in o) def test_preview_no_match(self): o, e = self.check_true( ["fill", "--dry-run", "<tracknumber>. <title>", self.f], True, False) self.assertTrue("title" in o) self.assertTrue(self.s("~basename") in o) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618435529.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_order.py�����������������������������������������������������������������0000664�0001750�0001750�00000003764�14035656711�016115� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from collections import defaultdict from quodlibet.formats import AudioFile from quodlibet.order import OrderInOrder from quodlibet.order.reorder import OrderWeighted, OrderShuffle from quodlibet.order.repeat import OneSong from quodlibet.qltk.songmodel import PlaylistModel from tests import TestCase r0 = AudioFile({'~#rating': 0}) r1 = AudioFile({'~#rating': 0.33}) r2 = AudioFile({'~#rating': 0.66}) r3 = AudioFile({'~#rating': 1.0}) class TOrderWeighted(TestCase): def test_weighted(self): pl = PlaylistModel() pl.set([r3, r1, r2, r0]) order = OrderWeighted() scores = defaultdict(int) for i in range(500): order.reset(pl) cur = pl.current_iter for j in range(3, -1, -1): cur = order.next_explicit(pl, cur) scores[pl[cur][0]] += j self.failUnless(scores[r1] > scores[r0]) self.failUnless(scores[r2] > scores[r1]) self.failUnless(scores[r3] > scores[r2]) class TOrderShuffle(TestCase): def test_remaining(self): order = OrderShuffle() pl = PlaylistModel() songs = [r3, r1, r2, r0] pl.set(songs) cur = pl.current_iter for i in range(4, 0, -1): cur = order.next_explicit(pl, cur) self.failUnlessEqual(len(order.remaining(pl)), i) # The playlist should reset after the last song cur = order.next_explicit(pl, cur) self.failUnlessEqual(len(order.remaining(pl)), len(songs)) class TOrderOneSong(TestCase): def test_remaining(self): order = OneSong(OrderInOrder()) pl = PlaylistModel(OrderInOrder) pl.set([r0, r1]) for i in range(2): self.failUnlessEqual(order.next(pl, pl.current_iter), None) ������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1670230195.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_pattern.py���������������������������������������������������������������0000644�0001750�0001750�00000057324�14343330263�016447� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from senf import fsnative from tests import TestCase from quodlibet.formats import AudioFile from quodlibet.pattern import (FileFromPattern, XMLFromPattern, Pattern, XMLFromMarkupPattern, ArbitraryExtensionFileFromPattern) class _TPattern(TestCase): def setUp(self): s1 = {'tracknumber': u'5/6', 'artist': u'Artist', 'title': u'Title5', '~filename': '/path/to/a.mp3', 'xmltest': u"<&>"} s2 = {'tracknumber': u'6', 'artist': u'Artist', 'title': u'Title6', '~filename': '/path/to/b.ogg', 'discnumber': u'2', 'unislash': u"foo\uff0fbar"} s3 = {'title': u'test/subdir', 'genre': u'/\n/', '~filename': '/one/more/a.flac', 'version': u'Instrumental'} s4 = {'performer': u'a\nb', 'artist': u'foo\nbar'} s5 = {'tracknumber': u'7/1234', 'artist': u'Artist', 'title': u'Title7', '~filename': '/path/to/e.mp3'} s6 = {'artist': u'Foo', 'albumartist': u'foo.bar', 'album': u'Best Of', '~filename': '/path/to/f.mp3', 'title': u'The.Final.Word'} s7 = {'artist': u'un élève français', '~filename': '/path/to/g.mp3', 'albumartist': u'Lee "Scratch" Perry', 'album': u"The 'only' way!", 'comment': u'Trouble|Strife'} s8 = {'tracknumber': u'7/8', 'artist': u'Artist1\n\nArtist3', 'artistsort': u'SortA1\nSortA2', 'album': u'Album5', 'albumsort': u'SortAlbum5', '~filename': '/path/to/g.mp3', 'xmltest': u"<&>"} if os.name == "nt": s1["~filename"] = u"C:\\path\\to\\a.mp3" s2["~filename"] = u"C:\\path\\to\\b.ogg" s3["~filename"] = u"C:\\one\\more\\a.flac" s4["~filename"] = u"C:\\path\\to\\a.mp3" s5["~filename"] = u"C:\\path\\to\\a.mp3" s6["~filename"] = u"C:\\path\\to\\f.mp3" s7["~filename"] = u"C:\\path\\to\\g.mp3" s8["~filename"] = u"C:\\path\\to\\h.mp3" self.a = AudioFile(s1) self.b = AudioFile(s2) self.c = AudioFile(s3) self.d = AudioFile(s4) self.e = AudioFile(s5) self.f = AudioFile(s6) self.g = AudioFile(s7) self.h = AudioFile(s8) class TPattern(_TPattern): from quodlibet.formats import AudioFile AudioFile def test_numeric(self): pat = Pattern("<~#rating>") self.assertEqual(pat.format(self.a), "0.50") def test_space(self): pat = Pattern("a ") self.assertEqual(pat.format(self.a), "a ") pat = Pattern(" a") self.assertEqual(pat.format(self.a), " a") pat = Pattern("a\n\n") self.assertEqual(pat.format(self.a), "a\n\n") def test_escape(self): pat = Pattern("a \\<foo\\|bla\\>") self.assertEqual(pat.format(self.a), "a <foo|bla>") pat = Pattern(r"a\\<foo>") self.assertEqual(pat.format(self.a), "a\\") def test_query_like_tag(self): pat = Pattern("<t=v>") self.assertEqual(pat.format(AudioFile({"t=v": "foo"})), "foo") def test_conditional_number_dot_title(s): pat = Pattern('<tracknumber|<tracknumber>. ><title>') s.assertEquals(pat.format(s.a), '5/6. Title5') s.assertEquals(pat.format(s.b), '6. Title6') s.assertEquals(pat.format(s.c), 'test/subdir') def test_conditional_other_number_dot_title(s): pat = Pattern('<tracknumber|<tracknumber>|00>. <title>') s.assertEquals(pat.format(s.a), '5/6. Title5') s.assertEquals(pat.format(s.b), '6. Title6') s.assertEquals(pat.format(s.c), '00. test/subdir') def test_conditional_other_other(s): # FIXME: was <tracknumber|a|b|c>.. but we can't put <>| in the format # string since it would break the XML pattern formatter. s.assertEqual(Pattern('<tracknumber|a|b|c>').format(s.a), "") def test_conditional_genre(s): pat = Pattern('<genre|<genre>|music>') s.assertEquals(pat.format(s.a), 'music') s.assertEquals(pat.format(s.b), 'music') s.assertEquals(pat.format(s.c), '/, /') def test_conditional_unknown(s): pat = Pattern('<album|foo|bar>') s.assertEquals(pat.format(s.a), 'bar') def test_conditional_equals(s): pat = Pattern('<artist=Artist|matched|not matched>') s.assertEquals(pat.format(s.a), 'matched') pat = Pattern('<artist=Artistic|matched|not matched>') s.assertEquals(pat.format(s.a), 'not matched') def test_conditional_equals_unicode(s): pat = Pattern(u'<artist=Artist|matched|not matched>') s.assertEquals(pat.format(s.g), 'not matched') pat = Pattern(u'<artist=un élève français|matched|not matched>') s.assertEquals(pat.format(s.g), 'matched') def test_duplicate_query(self): pat = Pattern('<u=yes|<u=yes|x|y>|<u=yes|q|z>>') self.assertEqual(pat.format(AudioFile({"u": u"yes"})), "x") self.assertEqual(pat.format(AudioFile({"u": u"no"})), "z") def test_tag_query_escaping(s): pat = Pattern('<albumartist=Lee "Scratch" Perry|matched|not matched>') s.assertEquals(pat.format(s.g), 'matched') def test_tag_query_escaped_pipe(s): pat = Pattern(r'<albumartist=/Lee\|Bob/|matched|not matched>') s.assertEquals(pat.format(s.g), 'matched') pat = Pattern(r'<albumartist=\||matched|not matched>') s.assertEquals(pat.format(s.g), 'not matched') pat = Pattern(r'<comment=/Trouble\|Strife/|matched|not matched>') s.assertEquals(pat.format(s.g), 'matched') def test_tag_query_quoting(s): pat = Pattern('<album=The only way|matched|not matched>') s.assertEquals(pat.format(s.g), 'not matched') pat = Pattern("<album=\"The 'only' way!\"|matched|not matched>") s.assertEquals(pat.format(s.g), 'matched') def test_tag_query_regex(s): pat = Pattern("<album=/'only'/|matched|not matched>") s.assertEquals(pat.format(s.g), 'matched') pat = Pattern("<album=/The .+ way/|matched|not matched>") s.assertEquals(pat.format(s.g), 'matched') pat = Pattern("</The .+ way/|matched|not matched>") s.assertEquals(pat.format(s.g), 'not matched') def test_tag_internal(self): if os.name != "nt": pat = Pattern("<~filename='/path/to/a.mp3'|matched|not matched>") self.assertEquals(pat.format(self.a), 'matched') pat = Pattern( "<~filename=/\\/path\\/to\\/a.mp3/|matched|not matched>") self.assertEquals(pat.format(self.a), 'matched') else: pat = Pattern( r"<~filename='C:\\\path\\\to\\\a.mp3'|matched|not matched>") self.assertEquals(pat.format(self.a), 'matched') def test_tag_query_disallowed_free_text(s): pat = Pattern("<The only way|matched|not matched>") s.assertEquals(pat.format(s.g), 'not matched') def test_query_scope(self): pat = Pattern("<foo|<artist=Foo|x|y>|<artist=Foo|z|q>>") self.assertEqual(pat.format(self.f), "z") def test_query_numeric(self): pat = Pattern("<#(foo=42)|42|other>") self.assertEqual(pat.format(AudioFile()), "other") self.assertEqual(pat.format(AudioFile({"foo": "42"})), "42") def test_conditional_notfile(s): pat = Pattern('<tracknumber|<tracknumber>|00>') s.assertEquals(pat.format(s.a), '5/6') s.assertEquals(pat.format(s.b), '6') s.assertEquals(pat.format(s.c), '00') def test_conditional_subdir(s): pat = Pattern('/a<genre|/<genre>>/<title>') s.assertEquals(pat.format(s.a), '/a/Title5') s.assertEquals(pat.format(s.b), '/a/Title6') s.assertEquals(pat.format(s.c), '/a//, //test/subdir') def test_number_dot_title(s): pat = Pattern('<tracknumber>. <title>') s.assertEquals(pat.format(s.a), '5/6. Title5') s.assertEquals(pat.format(s.b), '6. Title6') s.assertEquals(pat.format(s.c), '. test/subdir') def test_recnumber_dot_title(s): pat = Pattern(r'\<<tracknumber>\>. <title>') s.assertEquals(pat.format(s.a), '<5/6>. Title5') s.assertEquals(pat.format(s.b), '<6>. Title6') s.assertEquals(pat.format(s.c), '<>. test/subdir') def test_generated(s): pat = Pattern('<~basename>') s.assertEquals(pat.format(s.a), os.path.basename(s.a["~filename"])) def test_generated_and_not_generated(s): pat = Pattern('<~basename> <title>') res = pat.format(s.a) s.assertEquals( res, os.path.basename(s.a["~filename"]) + " " + s.a["title"]) def test_number_dot_title_dot(s): pat = Pattern('<tracknumber>. <title>.') s.assertEquals(pat.format(s.a), '5/6. Title5.') s.assertEquals(pat.format(s.b), '6. Title6.') s.assertEquals(pat.format(s.c), '. test/subdir.') def test_number_dot_genre(s): pat = Pattern('<tracknumber>. <genre>') s.assertEquals(pat.format(s.a), '5/6. ') s.assertEquals(pat.format(s.b), '6. ') s.assertEquals(pat.format(s.c), '. /, /') def test_unicode_with_int(s): song = AudioFile({"tracknumber": "5/6", "title": b"\xe3\x81\x99\xe3\x81\xbf\xe3\x82\x8c".decode('utf-8')}) pat = Pattern('<~#track>. <title>') s.assertEquals(pat.format(song), b"5. \xe3\x81\x99\xe3\x81\xbf\xe3\x82\x8c".decode('utf-8')) def test_json(s): pat = Pattern('<~json>') if os.name != "nt": s.assertEquals(pat.format(s.a), '{"artist": "Artist", "title": "Title5", "tracknumber": "5/6",' ' "xmltest": "<&>", "~filename": "/path/to/a.mp3"}') else: s.assertEquals(pat.format(s.a), '{"artist": "Artist", "title": "Title5", "tracknumber": "5/6",' ' "xmltest": "<&>", "~filename": "C:\\\\path\\\\to\\\\a.mp3"}') class _TFileFromPattern(_TPattern): def _create(self, string): return FileFromPattern(string) def test_escape_slash(s): fpat = s._create('<~filename>') s.assertTrue(fpat.format(s.a).endswith("_path_to_a.mp3")) pat = Pattern('<~filename>') if os.name != "nt": s.assertTrue(pat.format(s.a).startswith("/path/to/a")) else: s.assertTrue(pat.format(s.a).startswith("C:\\path\\to\\a")) if os.name != "nt": wpat = s._create(r'\\<artist>\\ "<title>') s.assertTrue( wpat.format(s.a).startswith(r'\Artist\ "Title5')) else: # FIXME.. pass def test_directory_rooting(s): if os.name == "nt": s.assertRaises(ValueError, FileFromPattern, 'a\\<b>') s.assertRaises(ValueError, FileFromPattern, '<a>\\<b>') s._create('C:\\<a>\\<b>') else: s.assertRaises(ValueError, FileFromPattern, 'a/<b>') s.assertRaises(ValueError, FileFromPattern, '<a>/<b>') s._create('/<a>/<b>') def test_backslash_conversion_win32(s): if os.name == 'nt': pat = s._create(r'Z:\<artist>\<title>') s.assertTrue(pat.format(s.a).startswith(r'Z:\Artist\Title5')) def test_raw_slash_preservation(s): if os.name == "nt": pat = s._create('C:\\a\\b\\<genre>') s.assertTrue(pat.format(s.a).startswith('C:\\a\\b\\')) s.assertTrue(pat.format(s.b).startswith('C:\\a\\b\\')) s.assertTrue(pat.format(s.c).startswith('C:\\a\\b\\_, _')) else: pat = s._create('/a/b/<genre>') s.assertTrue(pat.format(s.a).startswith('/a/b/')) s.assertTrue(pat.format(s.b).startswith('/a/b/')) s.assertTrue(pat.format(s.c).startswith('/a/b/_, _')) def test_specialcase_anti_ext(s): p1 = s._create('<~filename>') p2 = s._create('<~dirname>_<~basename>') s.assertEquals(p1.format(s.a), p2.format(s.a)) s.assertTrue(p1.format(s.a).endswith('_path_to_a.mp3')) s.assertEquals(p1.format(s.b), p2.format(s.b)) s.assertTrue(p1.format(s.b).endswith('_path_to_b.ogg')) s.assertEquals(p1.format(s.c), p2.format(s.c)) s.assertTrue(p1.format(s.c).endswith('_one_more_a.flac')) def test_long_filename(s): if os.name == "nt": a = AudioFile({"title": "x" * 300, "~filename": u"C:\\f.mp3"}) path = s._create(u'C:\\foobar\\ä<title>\\<title>').format(a) assert isinstance(path, fsnative) s.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255) path = s._create(u'äüö<title><title>').format(a) assert isinstance(path, fsnative) s.failUnlessEqual(len(path), 255) else: a = AudioFile({"title": "x" * 300, "~filename": "/f.mp3"}) path = s._create(u'/foobar/ä<title>/<title>').format(a) assert isinstance(path, fsnative) s.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255) path = s._create(u'äüö<title><title>').format(a) assert isinstance(path, fsnative) s.failUnlessEqual(len(path), 255) class TFileFromPattern(_TFileFromPattern): def _create(self, string): return FileFromPattern(string) def test_type(self): pat = self._create('') self.assertTrue(isinstance(pat.format(self.a), fsnative)) pat = self._create('<title>') self.assertTrue(isinstance(pat.format(self.a), fsnative)) def test_number_dot_title_dot(s): pat = s._create('<tracknumber>. <title>.') s.assertEquals(pat.format(s.a), '05. Title5..mp3') s.assertEquals(pat.format(s.b), '06. Title6..ogg') s.assertEquals(pat.format(s.c), '. test_subdir..flac') def test_tracknumber_decimals(s): pat = s._create('<tracknumber>. <title>') s.assertEquals(pat.format(s.a), '05. Title5.mp3') s.assertEquals(pat.format(s.e), '0007. Title7.mp3') def test_ext_case_preservation(s): x = AudioFile({'~filename': fsnative(u'/tmp/Xx.Flac'), 'title': 'Xx'}) # If pattern has a particular ext, preserve case of ext p1 = s._create('<~basename>') s.assertEquals(p1.format(x), 'Xx.Flac') p2 = s._create('<title>.FLAC') s.assertEquals(p2.format(x), 'Xx.FLAC') # If pattern doesn't have a particular ext, lowercase ext p3 = s._create('<title>') s.assertEquals(p3.format(x), 'Xx.flac') class TArbitraryExtensionFileFromPattern(_TFileFromPattern): def _create(self, string): return ArbitraryExtensionFileFromPattern(string) def test_number_dot_title_dot(s): pat = s._create('<tracknumber>. <title>.') if os.name == 'nt': # Can't have Windows names ending with dot s.assertEquals(pat.format(s.a), '05. Title5_') s.assertEquals(pat.format(s.b), '06. Title6_') s.assertEquals(pat.format(s.c), '. test_subdir_') else: s.assertEquals(pat.format(s.a), '05. Title5.') s.assertEquals(pat.format(s.b), '06. Title6.') s.assertEquals(pat.format(s.c), '. test_subdir.') def test_tracknumber_decimals(s): pat = s._create('<tracknumber>. <title>') s.assertEquals(pat.format(s.a), '05. Title5') s.assertEquals(pat.format(s.e), '0007. Title7') def test_constant_albumart_example(s): pat = s._create("folder.jpg") s.assertEquals(pat.format(s.a), 'folder.jpg') def test_extra_dots(s): pat = s._create("<artist~album>.png") s.assertEquals(pat.format(s.f), 'Foo - Best Of.png') pat = s._create("<albumartist~title>.png") s.assertEquals(pat.format(s.f), 'foo.bar - The.Final.Word.png') class TXMLFromPattern(_TPattern): def test_markup_passthrough(s): pat = XMLFromPattern(r'\<b\><<title>>\</b\>') s.assertEquals(pat.format(s.a), '<b><Title5></b>') s.assertEquals(pat.format(s.b), '<b><Title6></b>') s.assertEquals(pat.format(s.c), '<b><test/subdir></b>') def test_escape(s): pat = XMLFromPattern(r'\<b\><<xmltest>>\</b\>') s.assertEquals(pat.format(s.a), '<b><<&>></b>') def test_cond_markup(s): pat = XMLFromPattern(r'<title|\<b\><title> woo\</b\>>') s.assertEquals(pat.format(s.a), '<b>Title5 woo</b>') class TXMLFromMarkupPattern(_TPattern): def _test_markup(self, text): from gi.repository import Pango Pango.parse_markup(text, -1, "\x00") def test_convenience(s): pat = XMLFromMarkupPattern(r'[b]foo[/b]') s.assertEquals(pat.format(s.a), '<b>foo</b>') s._test_markup(pat.format(s.a)) pat = XMLFromMarkupPattern('[small ]foo[/small \t]') s.assertEquals(pat.format(s.a), '<small >foo</small \t>') s._test_markup(pat.format(s.a)) def test_link(s): pat = XMLFromMarkupPattern(r'[a href=""]foo[/a]') s.assertEquals(pat.format(s.a), '<a href="">foo</a>') def test_convenience_invalid(s): pat = XMLFromMarkupPattern(r'[b foo="1"]') s.assertEquals(pat.format(s.a), '[b foo="1"]') s._test_markup(pat.format(s.a)) def test_span(s): pat = XMLFromMarkupPattern(r'[span]foo[/span]') s.assertEquals(pat.format(s.a), '<span>foo</span>') s._test_markup(pat.format(s.a)) pat = XMLFromMarkupPattern(r'[span weight="bold"]foo[/span]') s.assertEquals(pat.format(s.a), '<span weight="bold">foo</span>') s._test_markup(pat.format(s.a)) def test_escape(s): pat = XMLFromMarkupPattern(r'\[b]') s.assertEquals(pat.format(s.a), '[b]') s._test_markup(pat.format(s.a)) pat = XMLFromMarkupPattern(r'\\\\[b]\\\\[/b]') s.assertEquals(pat.format(s.a), r'\\<b>\\</b>') s._test_markup(pat.format(s.a)) class TRealTags(TestCase): def test_empty(self): self.failUnlessEqual(Pattern("").tags, []) def test_both(self): pat = "<foo|<~bar~fuu> - <fa>|<bar>>" self.failUnlessEqual(Pattern(pat).tags, ["bar", "fuu", "fa"]) pat = "<foo|<~bar~fuu> - <fa>|<quux>>" self.failUnlessEqual(Pattern(pat).tags, ["bar", "fuu", "fa", "quux"]) class TPatternFormatList(_TPattern): def test_numeric(self): pat = Pattern("<~#rating>") self.assertEqual(pat.format_list(self.a), {("0.50", "0.50")}) def test_empty(self): pat = Pattern("<nopenope>") self.assertEqual(pat.format_list(self.a), {("", "")}) def test_same(s): pat = Pattern('<~basename> <title>') s.failUnlessEqual(pat.format_list(s.a), {(pat.format(s.a), pat.format(s.a))}) pat = Pattern('/a<genre|/<genre>>/<title>') s.failUnlessEqual(pat.format_list(s.a), {(pat.format(s.a), pat.format(s.a))}) def test_same2(s): fpat = FileFromPattern('<~filename>') pat = Pattern('<~filename>') s.assertEquals(fpat.format_list(s.a), {(fpat.format(s.a), fpat.format(s.a))}) s.assertEquals(pat.format_list(s.a), {(pat.format(s.a), pat.format(s.a))}) def test_tied(s): pat = Pattern('<genre>') s.failUnlessEqual(pat.format_list(s.c), {('/', '/')}) pat = Pattern('<performer>') s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b')}) pat = Pattern('<performer><performer>') s.failUnlessEqual(set(pat.format_list(s.d)), {('aa', 'aa'), ('ab', 'ab'), ('ba', 'ba'), ('bb', 'bb')}) pat = Pattern('<~performer~artist>') s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b'), ('bar', 'bar'), ('foo', 'foo')}) pat = Pattern('<performer~artist>') s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b'), ('bar', 'bar'), ('foo', 'foo')}) pat = Pattern('<artist|<artist>.|<performer>>') s.failUnlessEqual(pat.format_list(s.d), {('foo.', 'foo.'), ('bar.', 'bar.')}) pat = Pattern('<artist|<artist|<artist>.|<performer>>>') s.failUnlessEqual(pat.format_list(s.d), {('foo.', 'foo.'), ('bar.', 'bar.')}) def test_sort(s): pat = Pattern('<album>') s.failUnlessEqual(pat.format_list(s.f), {(u'Best Of', u'Best Of')}) pat = Pattern('<album>') s.failUnlessEqual(pat.format_list(s.h), {(u'Album5', u'SortAlbum5')}) pat = Pattern('<artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'Artist3', u'Artist3')}) pat = Pattern('<artist> x') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1 x', u'SortA1 x'), (u'Artist3 x', u'Artist3 x')}) def test_sort_tied(s): pat = Pattern('<~artist~album>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'Artist3', u'Artist3'), (u'Album5', u'SortAlbum5')}) pat = Pattern('<~album~artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'Artist3', u'Artist3'), (u'Album5', u'SortAlbum5')}) pat = Pattern('<~artist~artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'Artist3', u'Artist3')}) def test_sort_combine(s): pat = Pattern('<album> <artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Album5 Artist1', u'SortAlbum5 SortA1'), (u'Album5 Artist3', u'SortAlbum5 Artist3')}) pat = Pattern('x <artist> <album>') s.failUnlessEqual(pat.format_list(s.h), {(u'x Artist1 Album5', u'x SortA1 SortAlbum5'), (u'x Artist3 Album5', u'x Artist3 SortAlbum5')}) pat = Pattern(' <artist> <album> xx') s.failUnlessEqual(pat.format_list(s.h), {(u' Artist1 Album5 xx', u' SortA1 SortAlbum5 xx'), (u' Artist3 Album5 xx', u' Artist3 SortAlbum5 xx')}) pat = Pattern('<album> <tracknumber> <artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Album5 7/8 Artist1', u'SortAlbum5 7/8 SortA1'), (u'Album5 7/8 Artist3', u'SortAlbum5 7/8 Artist3')}) pat = Pattern('<tracknumber> <album> <artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'7/8 Album5 Artist1', u'7/8 SortAlbum5 SortA1'), (u'7/8 Album5 Artist3', u'7/8 SortAlbum5 Artist3')}) def test_sort_multiply(s): pat = Pattern('<artist> <artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1 Artist1', u'SortA1 SortA1'), (u'Artist3 Artist1', u'Artist3 SortA1'), (u'Artist1 Artist3', u'SortA1 Artist3'), (u'Artist3 Artist3', u'Artist3 Artist3')}) def test_missing_value(self): pat = Pattern('<genre> - <artist>') self.assertEqual(pat.format_list(self.a), {(" - Artist", " - Artist")}) pat = Pattern('') self.assertEqual(pat.format_list(self.a), {("", "")}) def test_string(s): pat = Pattern('display') s.assertEqual(pat.format_list(s.a), {("display", "display")}) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618435529.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_player.py����������������������������������������������������������������0000664�0001750�0001750�00000031706�14035656711�016273� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests import TestCase, skipUnless, get_data_path from quodlibet import player from quodlibet import library from quodlibet import config from quodlibet.util import connect_obj from quodlibet.player.nullbe import NullPlayer from quodlibet.formats import AudioFile from quodlibet.qltk.songmodel import PlaylistModel from quodlibet.qltk.controls import Volume FILES = [ AudioFile({"~filename": fsnative(u"/foo/bar1"), "title": "1"}), AudioFile({"~filename": fsnative(u"/foo/bar2"), "title": "2"}), AudioFile({"~filename": fsnative(u"/foo/bar3"), "title": "3"}), ] for file_ in FILES: file_.sanitize() UNKNOWN_FILE = FILES.pop(-1) REAL_FILE = AudioFile({"~filename": get_data_path("empty.ogg")}) REAL_FILE.sanitize() class TPlayer(TestCase): NAME = None def setUp(self): config.init() config.set("player", "gst_pipeline", "fakesink") config.set("settings", "xine_driver", "none") module = player.init_backend(self.NAME) lib = library.init() self.player = module.init(lib.librarian) source = PlaylistModel() source.set(FILES) self.events = [] def start_end_handler(player, song, *args): self.events.append((args[-1], song)) self.player.connect("song-started", start_end_handler, "started") self.player.connect("song-ended", start_end_handler, "ended") self.player.setup(source, None, 0) self.signals = [] def handler(type_, *args): self.signals.append(type_) connect_obj(self.player, "unpaused", handler, "unpaused") connect_obj(self.player, "paused", handler, "paused") def _check_events(self): # make sure song-started and song-ended match up stack = [] old = self.events[:] for type_, song in self.events: if type_ == "started": stack.append(song) elif type_ == "ended": self.assertTrue(stack.pop(-1) is song, msg=old) self.assertFalse(stack, msg=old) def tearDown(self): self.player.destroy() self._check_events() del self.events del self.signals config.quit() class TPlayerMixin: def _can_sync(self): # TODO: make this work with xinebe return not isinstance(self, TXinePlayer) def test_seek_signal(self): if not self._can_sync(): return events = [] during_events = [] def on_seek(player, song, pos): events.append(pos) during_events.append(player.get_position()) self.player.connect("seek", on_seek) self.player.go_to(REAL_FILE) self.player.sync(10) assert self.player.get_position() == 0 self.player.seek(100) assert self.player.get_position() == 100 self.player.sync(10) assert self.player.get_position() == 100 self.player.seek(150) assert self.player.get_position() == 150 self.player.seek(50) assert self.player.get_position() == 50 self.player.sync(10) assert self.player.get_position() == 50 # some backends merge requests and only emit once assert events in ([100, 150, 50], [100, 50]) assert events == during_events def test_seek_in_song_started(self): if not self._can_sync(): return from gi.repository import Gst # doesn't work on debian 8, maybe a GStreamer bug if Gst.version()[:2] < (1, 6): return def on_started(player, song): assert player.get_position() == 0 player.seek(100) self.player.connect("song-started", on_started) self.player.go_to(REAL_FILE) self.player.sync(10) assert self.player.get_position() == 100 def test_song_start(self): self.assertFalse(self.player.song) self.assertFalse(self.player.info) def test_paused(self): self.assertTrue(self.player.paused) self.player.paused = False self.assertFalse(self.player.paused) self.assertTrue(self.signals, ["unpaused"]) def test_volume(self): self.assertEqual(self.player.volume, 1.0) self.player.volume = 1000 self.assertEqual(self.player.volume, 1.0) self.player.volume = -1000 self.assertEqual(self.player.volume, 0.0) self.player.volume = 0.5 self.assertEqual(self.player.volume, 0.5) def test_volume_cubic(self): self.player.volume = 1 assert self.player.props.volume == 1 self.player.volume = 0 assert self.player.props.volume == 0 self.player.volume = 0.5 assert self.player.props.volume == 0.125 def test_remove(self): self.player.remove(None) self.player.go_to(FILES[0]) self.assertEqual(self.player.song, FILES[0]) self.player.remove(FILES[0]) self.assertEqual(self.player.song, FILES[1]) self.player.remove(None) self.assertEqual(self.player.song, FILES[1]) def test_next(self): self.assertFalse(self.player.song) self.player.next() self.assertEqual(self.player.song, FILES[0]) self.player.next() self.assertEqual(self.player.song, FILES[1]) self.player.next() self.assertFalse(self.player.song) def test_previous(self): self.player.next() self.player.next() self.assertEqual(self.player.song, FILES[1]) self.player.previous() self.assertEqual(self.player.song, FILES[0]) def test_goto(self): self.assertTrue(self.player.paused) self.player.go_to(FILES[1]) self.assertEqual(self.player.song, FILES[1]) self.assertTrue(self.player.paused) self.player.go_to(FILES[0], explicit=True) self.assertEqual(self.player.song, FILES[0]) def test_goto_unknown(self): self.assertTrue(self.player.paused) self.player.go_to(UNKNOWN_FILE, True) self.assertIs(self.player.song, UNKNOWN_FILE) self.assertTrue(self.player.paused) self.player.go_to(None) self.assertIs(self.player.song, None) def test_reset(self): self.player.go_to(None) self.player._reset() self.assertEqual(self.player.song, FILES[0]) self.player.next() self.player._reset() self.assertEqual(self.player.song, FILES[0]) def test_equalizer(self): self.player.eq_bands self.player.eq_values self.player.eq_values = [1, 2, 3, 4] self.player.next() def test_unpause_while_no_song(self): self.assertTrue(self.player.paused) self.player.go_to(None) self.player.paused = False self.player.next() self.assertTrue(self.signals, ["unpaused"]) self.player.go_to(None) self.assertTrue(self.signals, ["unpaused", "paused"]) def test_replaygain(self): self.player.replaygain_profiles[0] = "track" self.player.next() config.set("player", "replaygain", True) self.assertEqual(self.player.calc_replaygain_volume(1.0), 1.0) config.set("player", "fallback_gain", -5.0) self.assertAlmostEqual( self.player.calc_replaygain_volume(1.0), 0.562, 3) config.set("player", "pre_amp_gain", 10.0) self.assertEqual(self.player.calc_replaygain_volume(1.0), 1.0) def test_seekable(self): self.assertFalse(self.player.seekable) self.player.next() self.assertTrue(self.player.seekable) calls = [] def on_change(*args): calls.append(args) self.player.connect("notify::seekable", on_change) self.player.go_to(None) self.assertTrue(calls) self.assertFalse(self.player.seekable) def test_pause_on_goto_none(self): # When we got to None, pause after song-started # Not that that's the right thing to do, but it should be consistent # between backends and the random album plugin expects it atm. assert self.player.song is None self.player.play() event = [] def on_started(player, song): event.append((song, player.paused)) self.player.connect("song-started", on_started) self.player.go_to(None) assert event[0] == (None, False) def test_mute(self): self.assertFalse(self.player.mute) self.player.next() self.assertFalse(self.player.mute) # backend don't have to support it, but shouldn't fail on set/get self.player.mute = not self.player.mute def test_preserve_volume(self): self.player.next() self.player.volume = 0.5 self.player.next() self.assertEqual(self.player.volume, 0.5) def test_play(self): assert self.player.song is None assert self.player.paused self.player.play() assert not self.player.paused song = self.player.song assert song is not None self.player.play() assert not self.player.paused assert self.player.song is song def test_playpause(self): assert self.player.song is None assert self.player.paused self.player.playpause() assert not self.player.paused song = self.player.song assert song is not None self.player.playpause() assert self.player.paused assert self.player.song is song class TNullPlayer(TPlayer, TPlayerMixin): NAME = "nullbe" def test_previous_seek(self): self.player.next() self.player.next() self.assertEqual(self.player.song, FILES[1]) self.player.seek(10000) self.assertEqual(self.player.get_position(), 10000) self.player.previous() self.assertEqual(self.player.get_position(), 0) self.assertEqual(self.player.song, FILES[1]) def test_previous_force(self): self.player.next() self.player.next() self.assertEqual(self.player.song, FILES[1]) self.player.seek(10000) self.assertEqual(self.player.get_position(), 10000) self.player.previous(force=True) self.assertEqual(self.player.get_position(), 0) self.assertEqual(self.player.song, FILES[0]) def test_previous_skip(self): self.player.next() self.player.next() self.assertEqual(self.player.song, FILES[1]) self.player.seek(10) self.assertEqual(self.player.get_position(), 10) self.player.previous() self.assertEqual(self.player.get_position(), 0) self.assertEqual(self.player.song, FILES[0]) def test_stop(self): self.player.next() self.player.seek(10000) self.assertEqual(self.player.get_position(), 10000) self.player.stop() self.assertEqual(self.player.get_position(), 0) def test_can_play_uri_null(self): self.assertTrue(self.player.can_play_uri("")) self.assertTrue(self.player.can_play_uri("file://")) self.assertTrue(self.player.can_play_uri("fake://")) has_xine = True try: player.init_backend("xinebe") except player.PlayerError: has_xine = False @skipUnless(has_xine, "couldn't load/test xinebe") class TXinePlayer(TPlayer, TPlayerMixin): NAME = "xinebe" def test_can_play_uri_xine(self): self.assertFalse(self.player.can_play_uri("")) self.assertTrue(self.player.can_play_uri("file://")) self.assertFalse(self.player.can_play_uri("fake://")) has_gstbe = True try: player.init_backend("gstbe") except player.PlayerError: has_gstbe = False @skipUnless(has_gstbe, "couldn't load/test gstbe") class TGstPlayer(TPlayer, TPlayerMixin): NAME = "gstbe" def test_can_play_uri_gst(self): self.assertFalse(self.player.can_play_uri("")) self.assertTrue(self.player.can_play_uri("file://")) self.assertFalse(self.player.can_play_uri("fake://")) class TVolume(TestCase): def setUp(self): self.p = NullPlayer() self.v = Volume(self.p) def test_setget(self): for i in [0.0, 1.2, 0.24, 1.0, 0.9]: self.v.set_value(i) self.failUnlessAlmostEqual(self.p.volume, self.v.get_value()) def test_add(self): self.v.set_value(0.5) self.v += 0.1 self.failUnlessAlmostEqual(self.p.volume, 0.6) def test_sub(self): self.v.set_value(0.5) self.v -= 0.1 self.failUnlessAlmostEqual(self.p.volume, 0.4) def test_add_boundry(self): self.v.set_value(0.95) self.v += 0.1 self.failUnlessAlmostEqual(self.p.volume, 1.0) def test_sub_boundry(self): self.v.set_value(0.05) self.v -= 0.1 self.failUnlessAlmostEqual(self.p.volume, 0.0) def tearDown(self): self.p.destroy() self.v.destroy() ����������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_player_gst.py������������������������������������������������������������0000644�0001750�0001750�00000021614�14455205526�017143� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import sys import contextlib try: from gi.repository import Gst except ImportError: Gst = None from tests import TestCase, skipUnless, get_data_path try: from quodlibet.player.gstbe.util import GStreamerSink as Sink from quodlibet.player.gstbe.util import parse_gstreamer_taglist from quodlibet.player.gstbe.util import find_audio_sink from quodlibet.player.gstbe.prefs import GstPlayerPreferences except ImportError: pass from quodlibet.player import PlayerError from quodlibet.util import sanitize_tags, is_flatpak, matches_flatpak_runtime, is_osx from quodlibet.formats import MusicFile from quodlibet import config @contextlib.contextmanager def ignore_gst_errors(): old = Gst.debug_get_default_threshold() Gst.debug_set_default_threshold(Gst.DebugLevel.NONE) yield Gst.debug_set_default_threshold(old) @skipUnless(Gst, "GStreamer missing") class TGstPlayerPrefs(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_main(self): widget = GstPlayerPreferences(None, True) widget.destroy() @skipUnless(Gst, "GStreamer missing") class TGStreamerSink(TestCase): def test_simple(self): sinks = ["gconfaudiosink", "alsasink"] for n in filter(Gst.ElementFactory.find, sinks): obj, name = Sink(n) self.failUnless(obj) self.failUnlessEqual(name, n) def test_invalid(self): with ignore_gst_errors(): self.assertRaises(PlayerError, Sink, "notarealsink") def test_fallback(self): obj, name = Sink("") self.failUnless(obj) if os.name == "nt": self.failUnlessEqual(name, "directsoundsink") else: self.failUnlessEqual(name, find_audio_sink()[1]) def test_append_sink(self): obj, name = Sink("volume") self.failUnless(obj) self.failUnlessEqual(name.split("!")[-1].strip(), Sink("")[1]) @skipUnless(Gst, "GStreamer missing") class TGstreamerTagList(TestCase): def test_parse(self): # gst.TagList can't be filled using pyGtk... so use a dict instead l = {} l["extended-comment"] = u"foo=bar" self.failUnless("foo" in parse_gstreamer_taglist(l)) l["extended-comment"] = [u"foo=bar", u"bar=foo", u"bar=foo2"] self.failUnless("foo" in parse_gstreamer_taglist(l)) self.failUnless("bar" in parse_gstreamer_taglist(l)) self.failUnlessEqual(parse_gstreamer_taglist(l)["bar"], "foo\nfoo2") # date is abstract, so define our own # (might work with pygobject now) class Foo: def to_iso8601_string(self): return "3000-10-2" l["date"] = Foo() date = Gst.DateTime Gst.DateTime = Foo self.failUnlessEqual(parse_gstreamer_taglist(l)["date"], "3000-10-2") Gst.DateTime = date l["foo"] = u"äöü" parsed = parse_gstreamer_taglist(l) self.assertTrue(isinstance(parsed["foo"], str)) self.assertTrue(u"äöü" in parsed["foo"].split("\n")) l["foo"] = u"äöü".encode("utf-8") parsed = parse_gstreamer_taglist(l) self.assertTrue(isinstance(parsed["foo"], str)) self.assertTrue(u"äöü" in parsed["foo"].split("\n")) l["bar"] = 1.2 self.failUnlessEqual(parse_gstreamer_taglist(l)["bar"], 1.2) l["bar"] = 9 self.failUnlessEqual(parse_gstreamer_taglist(l)["bar"], 9) l["bar"] = Gst.TagList() # some random gst instance self.failUnless( isinstance(parse_gstreamer_taglist(l)["bar"], str)) self.failUnless("GstTagList" in parse_gstreamer_taglist(l)["bar"]) def test_sanitize(self): l = sanitize_tags({"location": u"http://foo"}) self.failUnless("website" in l) l = sanitize_tags({"channel-mode": u"joint-stereo"}) self.failUnlessEqual(l["channel-mode"], "stereo") l = sanitize_tags({"channel-mode": u"dual"}) self.failUnlessEqual(l["channel-mode"], "stereo") l = sanitize_tags({"audio-codec": u"mp3"}) self.failUnlessEqual(l["audio-codec"], "MP3") l = sanitize_tags({"audio-codec": u"Advanced Audio Coding"}) self.failUnlessEqual(l["audio-codec"], "MPEG-4 AAC") l = sanitize_tags({"audio-codec": u"vorbis"}) self.failUnlessEqual(l["audio-codec"], "Ogg Vorbis") l = {"a": u"http://www.shoutcast.com", "b": u"default genre"} l = sanitize_tags(l) self.failIf(l) l = sanitize_tags({"duration": 1000 * 42}, stream=True) self.failUnlessEqual(l["~#length"], 42) l = sanitize_tags({"duration": 1000 * 42}) self.failIf(l) l = sanitize_tags({"duration": u"bla"}, stream=True) self.failUnlessEqual(l["duration"], u"bla") l = sanitize_tags({"bitrate": 1000 * 42}, stream=True) self.failUnlessEqual(l["~#bitrate"], 42) l = sanitize_tags({"bitrate": 1000 * 42}) self.failIf(l) l = sanitize_tags({"bitrate": u"bla"}) self.failUnlessEqual(l["bitrate"], u"bla") l = sanitize_tags({"nominal-bitrate": 1000 * 42}) self.failUnlessEqual(l["~#bitrate"], 42) l = sanitize_tags({"nominal-bitrate": 1000 * 42}, stream=True) self.failIf(l) l = sanitize_tags({"nominal-bitrate": u"bla"}) self.failUnlessEqual(l["nominal-bitrate"], u"bla") l = {"emphasis": u"something"} self.failIf(sanitize_tags(l)) self.failIf(sanitize_tags(l)) l = {"title": u"something"} self.failIf(sanitize_tags(l)) self.failUnless(sanitize_tags(l, stream=True)) l = {"artist": u"something"} self.failIf(sanitize_tags(l)) self.failUnless(sanitize_tags(l, stream=True)) l = {"~#foo": 42, "bar": 42, "~#bla": u"42"} self.failUnless("~#foo" in sanitize_tags(l)) self.failUnless("~#bar" in sanitize_tags(l)) self.failUnless("bla" in sanitize_tags(l)) l = {} l["extended-comment"] = [u"location=1", u"website=2", u"website=3"] l = parse_gstreamer_taglist(l) l = sanitize_tags(l)["website"].split("\n") self.failUnless("1" in l) self.failUnless("2" in l) self.failUnless("3" in l) @skipUnless(Gst, "GStreamer missing") @skipUnless(sys.platform == "darwin" or os.name == "nt" or is_flatpak(), "no control over gst") class TGStreamerCodecs(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def _check(self, song): old_threshold = Gst.debug_get_default_threshold() Gst.debug_set_default_threshold(Gst.DebugLevel.NONE) pipeline = Gst.parse_launch( "uridecodebin uri=%s ! fakesink" % song("~uri")) bus = pipeline.get_bus() pipeline.set_state(Gst.State.PLAYING) error = None try: while 1: message = bus.timed_pop(Gst.SECOND * 40) if not message or message.type == Gst.MessageType.ERROR: if message: error = message.parse_error()[0].message else: error = "timed out" break if message.type == Gst.MessageType.EOS: break finally: pipeline.set_state(Gst.State.NULL) Gst.debug_set_default_threshold(old_threshold) return error def test_decode_all(self): """Decode all kinds of formats using Gstreamer, to check if they all work and to notify us if a plugin is missing on platforms where we control the packaging. """ files = [ "coverart.wv", "empty.aac", "empty.flac", "empty.ogg", "empty.opus", "silence-44-s.mpc", "silence-44-s.tta", # "test.mid", "test.spc", "test.vgm", "test.wma", "empty.xm", "h264_aac.mp4", "h265_aac.mp4" ] if not matches_flatpak_runtime("*org.gnome.*/3.32"): # https://gitlab.com/freedesktop-sdk/freedesktop-sdk/issues/809 files.append("silence-44-s.spx") if not is_osx(): # gstlibav gets stuck decoding this.. not sure files.append("silence-44-s.sv8.mpc") errors = [] for file_ in files: path = get_data_path(file_) song = MusicFile(path) if song is not None: error = self._check(song) if error: errors.append((song("~format"), error)) if errors: raise Exception("Decoding failed %r" % errors) ��������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653776644.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_player_xine.py�����������������������������������������������������������0000664�0001750�0001750�00000001766�14244520404�017310� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet.library import SongLibrarian from quodlibet.player import PlayerError try: from quodlibet.player.xinebe.player import XinePlaylistPlayer except ImportError: XinePlaylistPlayer = None from . import TestCase, skipUnless @skipUnless(XinePlaylistPlayer is not None, "no xinebe") class TXinePlaylistPlayer(TestCase): def test_init(self): try: player = XinePlaylistPlayer(None, SongLibrarian()) except PlayerError: # travis has no output pass else: player.destroy() def test_init_device_non_existing(self): with self.assertRaises(PlayerError): XinePlaylistPlayer(b"this is not a device", SongLibrarian()) ����������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_playlist_menu.py���������������������������������������������������������0000664�0001750�0001750�00000004332�14231604332�017645� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017-21 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os import quodlibet from quodlibet import qltk from quodlibet.browsers.playlists.menu import PlaylistMenu from quodlibet.library.playlist import _DEFAULT_PLAYLIST_DIR, PlaylistLibrary from quodlibet.formats import AudioFile from quodlibet.library import SongLibrarian, SongFileLibrary from quodlibet.library.file import FileLibrary from tests.helper import dummy_path from tests import TestCase, _TEMP_DIR FIXED_NAME = "_foobar" class StubbedPlaylistMenu(PlaylistMenu): def _get_new_name(self, parent, title): return FIXED_NAME class TPlaylistMenu(TestCase): SONG = AudioFile({ "title": "two", "artist": "mu", "~filename": dummy_path(u"/dev/zero")}) SONGS = [ AudioFile({ "title": "one", "artist": "piman", "~filename": dummy_path(u"/dev/null")}), SONG, ] def setUp(self): # Testing locally is VERY dangerous without this... self.assertTrue(_TEMP_DIR in _DEFAULT_PLAYLIST_DIR or os.name == "nt", msg="Failing, don't want to delete %s" % _DEFAULT_PLAYLIST_DIR) try: os.mkdir(_DEFAULT_PLAYLIST_DIR) except EnvironmentError: pass quodlibet.config.init() self.lib = FileLibrary() self.lib.librarian = SongLibrarian() for af in self.SONGS: af.sanitize() self.lib.add(self.SONGS) def tearDown(self): self.lib.destroy() self.lib.librarian.destroy() quodlibet.config.quit() def test__on_new_playlist_activate(self): main = qltk.MenuItem('Menu') menu = StubbedPlaylistMenu(self.SONGS, PlaylistLibrary(SongFileLibrary())) main.set_submenu(menu) # Run it (with stubbed dialog) pl = menu._on_new_playlist_activate(main, self.SONGS) assert pl, "No playlists added" assert pl.name == FIXED_NAME, "Wrong name used" assert pl.songs == self.SONGS ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_playlist_util.py���������������������������������������������������������0000664�0001750�0001750�00000006271�14244626671�017700� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2022 TheMelmacian # # 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 2 of the License, or # (at your option) any later version. import os from io import BufferedReader from urllib.response import addinfourl from quodlibet.browsers.playlists.util import _dir_for, parse_m3u from quodlibet.library import SongFileLibrary from quodlibet.library.playlist import PlaylistLibrary from quodlibet.util.collection import Playlist from quodlibet.util.urllib import urlopen from tests import TestCase, get_data_path class TPlaylistUtil(TestCase): PLAYLIST_FILE_PATH = get_data_path('test.m3u8') sfLib: SongFileLibrary = None plLib: PlaylistLibrary = None def setUp(self): self.sfLib = SongFileLibrary() self.plLib = PlaylistLibrary(self.sfLib) def tearDown(self): self.plLib.destroy() self.sfLib.destroy() def test_dir_for(self): # uri format of files added via drag and drop or add button # (Gtk.SelectionData.get_uris()): file:///path/to/file.ext url_based_file: addinfourl = urlopen("file:///" + self.PLAYLIST_FILE_PATH) reader_based_file: BufferedReader = open(self.PLAYLIST_FILE_PATH, "rb") try: dir_of_url_based_file: str = _dir_for(url_based_file) self.assertEqual( os.path.realpath(os.path.dirname(self.PLAYLIST_FILE_PATH)), os.path.realpath(dir_of_url_based_file), "determining the directory of url based files" " should result in a correct path" ) dir_of_reader_based_file: str = _dir_for(reader_based_file) self.assertEqual( os.path.realpath(os.path.dirname(self.PLAYLIST_FILE_PATH)), os.path.realpath(dir_of_reader_based_file,), "determining the directory of reader based files" " should result in a correct path" ) finally: url_based_file.close() reader_based_file.close() def test_parse_m3u8(self): fileName = os.path.basename(self.PLAYLIST_FILE_PATH) playlist: Playlist = None with open(self.PLAYLIST_FILE_PATH, "rb") as file: try: playlist = parse_m3u(file, fileName, self.sfLib, self.plLib) except: assert False, ("parsing m3u8 playlists in correct format" " should not cause errors") self.assertIsNotNone(playlist, ("parsing an m3u8 playlist in the correct format" " should result in a playlist")) # the test.m3u8 contains: # - 3 existing and supported audio files from the tests/data folder: # lame.mp3, test.wav, sine-110hz.flac # - 1 non existing file: non_existing_audio_file.mp3 # - 1 not supported file: test.jpg # parsing the file correctly should result in a playlist with 3 entries self.assertEqual( 3, len(playlist), "only existing files should be added to the playlist" ) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_plugins___init__.py������������������������������������������������������0000664�0001750�0001750�00000012436�14035600052�020261� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, mkstemp import os from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.util.songwrapper import SongWrapper, ListWrapper from quodlibet.plugins import PluginConfig class TSongWrapper(TestCase): psong = AudioFile({ "~filename": "does not/exist", "title": "more songs", "discnumber": "2/2", "tracknumber": "1", "artist": "Foo\nI have two artists", "album": "Bar", "~bookmark": "2:10 A bookmark"}) pwrap = SongWrapper(psong) def setUp(self): fd, self.filename = mkstemp() os.close(fd) config.init() self.wrap = SongWrapper(AudioFile( {"title": "woo", "~filename": self.filename})) def tearDown(self): os.unlink(self.filename) config.quit() def test_slots(self): def breakme(): self.wrap.woo = 1 self.failUnlessRaises(AttributeError, breakme) def test_cmp(self): songs = [SongWrapper(AudioFile({"tracknumber": str(i)})) for i in range(10)] songs.reverse() songs.sort() self.failUnlessEqual([s("~#track") for s in songs], list(range(10))) def test_needs_write_yes(self): self.failIf(self.wrap._needs_write) self.wrap["woo"] = "bar" self.failUnless(self.wrap._needs_write) def test_needs_write_no(self): self.failIf(self.wrap._needs_write) self.wrap["~woo"] = "bar" self.failIf(self.wrap._needs_write) def test_pop(self): self.failIf(self.wrap._needs_write) self.wrap.pop("artist", None) self.failUnless(self.wrap._needs_write) def test_getitem(self): self.failUnlessEqual(self.wrap["title"], "woo") def test_get(self): self.failUnlessEqual(self.wrap.get("title"), "woo") self.failUnlessEqual(self.wrap.get("dne"), None) self.failUnlessEqual(self.wrap.get("dne", "huh"), "huh") def test_delitem(self): self.failUnless("title" in self.wrap) del(self.wrap["title"]) self.failIf("title" in self.wrap) self.failUnless(self.wrap._needs_write) def test_realkeys(self): self.failUnlessEqual(self.pwrap.realkeys(), self.psong.realkeys()) def test_can_change(self): for key in ["~foo", "title", "whee", "a test", "foo=bar", ""]: self.failUnlessEqual( self.pwrap.can_change(key), self.psong.can_change(key)) def test_comma(self): for key in ["title", "artist", "album", "notexist", "~length"]: self.failUnlessEqual(self.pwrap.comma(key), self.psong.comma(key)) def test_list(self): for key in ["title", "artist", "album", "notexist", "~length"]: self.failUnlessEqual(self.pwrap.list(key), self.psong.list(key)) def test_dicty(self): self.failUnlessEqual(self.pwrap.keys(), self.psong.keys()) self.failUnlessEqual( list(self.pwrap.values()), list(self.psong.values())) self.failUnlessEqual(self.pwrap.items(), self.psong.items()) def test_mtime(self): self.wrap._song.sanitize() self.failUnless(self.wrap.valid()) self.wrap["~#mtime"] = os.path.getmtime(self.filename) - 2 self.wrap._updated = False self.failIf(self.wrap.valid()) def test_setitem(self): self.failIf(self.wrap._was_updated()) self.wrap["title"] = "bar" self.failUnless(self.wrap._was_updated()) self.failUnlessEqual(self.wrap["title"], "bar") def test_not_really_updated(self): self.failIf(self.wrap._was_updated()) self.wrap["title"] = "woo" self.failIf(self.wrap._was_updated()) self.wrap["title"] = "quux" self.failUnless(self.wrap._was_updated()) def test_new_tag(self): self.failIf(self.wrap._was_updated()) self.wrap["version"] = "bar" self.failUnless(self.wrap._was_updated()) def test_bookmark(self): self.failUnlessEqual(self.psong.bookmarks, self.pwrap.bookmarks) self.pwrap.bookmarks = [(43, "another mark")] self.failUnlessEqual(self.psong["~bookmark"], "0:43 another mark") self.failUnlessEqual(self.psong.bookmarks, self.pwrap.bookmarks) class TListWrapper(TestCase): def test_empty(self): wrapped = ListWrapper([]) self.failUnlessEqual(wrapped, []) def test_empty_song(self): wrapped = ListWrapper([{}]) self.failUnless(len(wrapped) == 1) self.failIf(isinstance(wrapped[0], dict)) def test_none(self): wrapped = ListWrapper([None, None]) self.failUnless(len(wrapped) == 2) self.failUnlessEqual(wrapped, [None, None]) class TPluginConfig(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_mapping(self): c = PluginConfig("some") c.set("foo", "bar") self.assertEqual(config.get("plugins", "some_foo"), "bar") def test_defaults(self): c = PluginConfig("some") c.defaults.set("hm", "mh") self.assertEqual(c.get("hm"), "mh") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_plugins_cover.py���������������������������������������������������������0000664�0001750�0001750�00000030061�14231604332�017635� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import io import os import shutil from gi.repository import GdkPixbuf from quodlibet.util.cover.http import ApiCoverSourcePlugin from quodlibet.util.thread import Cancellable from tests import TestCase, mkdtemp, mkstemp, get_data_path, run_gtk_loop from quodlibet import config from quodlibet.plugins import Plugin from quodlibet.formats.mp3 import MP3File from quodlibet.formats import AudioFile, EmbeddedImage from quodlibet.plugins.cover import CoverSourcePlugin from quodlibet.util.cover.manager import CoverPluginHandler, CoverManager from quodlibet.util.path import path_equal from .helper import get_temp_copy DUMMY_COVER = io.StringIO() class DummyCoverSource1(CoverSourcePlugin): @staticmethod def priority(): return 0.95 @property def cover(self): DummyCoverSource1.cover_call = True return None class DummyCoverSource2(CoverSourcePlugin): @staticmethod def priority(): return 0.5 @property def cover(self): DummyCoverSource2.cover_call = True return DUMMY_COVER def fetch_cover(self): DummyCoverSource2.fetch_call = True return self.emit('fetch-success', self.cover) class DummyCoverSource3(ApiCoverSourcePlugin): @staticmethod def priority(): return 0.3 @property def cover(self): DummyCoverSource3.cover_call = True return None def search(self): return self.emit('search-complete', [{'cover': DUMMY_COVER}]) def fetch_cover(self): DummyCoverSource3.fetch_call = True return self.emit('fetch-success', DUMMY_COVER) dummy_sources = [Plugin(s) for s in (DummyCoverSource1, DummyCoverSource2, DummyCoverSource3)] class TCoverManager(TestCase): built_in_count = 2 def setUp(self): self.manager = CoverManager() def test_has_builtin_covers(self): self.assertEqual(len(list(self.manager.sources)), self.built_in_count) manager = CoverPluginHandler(use_built_in=False) self.assertEqual(len(list(manager.sources)), 0) def test_only_enabled(self): for source in dummy_sources: self.manager.plugin_handler.plugin_handle(source) self.assertEqual(len(list(self.manager.sources)), self.built_in_count) for source in dummy_sources: self.manager.plugin_handler.plugin_enable(source) self.assertEqual(len(list(self.manager.sources)), self.built_in_count + len(dummy_sources)) for k, source in enumerate(dummy_sources): self.manager.plugin_handler.plugin_disable(source) self.assertEqual(len(list(self.manager.sources)), self.built_in_count + len(dummy_sources) - k - 1) def test_sources_sorted(self): for source in dummy_sources: self.manager.plugin_handler.plugin_handle(source) self.manager.plugin_handler.plugin_enable(source) priorities = [p.priority() for p in self.manager.sources] self.assertSequenceEqual(priorities, sorted(priorities, reverse=True)) # Test that sources are sorted even after removing some of the sources for source in dummy_sources: self.manager.plugin_handler.plugin_disable(source) ps = [p.priority() for p in self.manager.sources] self.assertSequenceEqual(ps, sorted(ps, reverse=True)) def test_acquire_cover_sync(self): song = AudioFile({"~filename": "/dev/null"}) manager = CoverManager(use_built_in=False) handler = manager.plugin_handler for source in dummy_sources: handler.plugin_handle(source) handler.plugin_enable(dummy_sources[0]) self.assertIs(manager.acquire_cover_sync(song), None) handler.plugin_enable(dummy_sources[1]) self.assertIs(manager.acquire_cover_sync(song), DUMMY_COVER) handler.plugin_enable(dummy_sources[2]) self.assertIs(manager.acquire_cover_sync(song), DUMMY_COVER) handler.plugin_disable(dummy_sources[1]) self.assertIs(manager.acquire_cover_sync(song), None) def test_acquire_cover(self): manager = CoverManager(use_built_in=False) handler = manager.plugin_handler for source in dummy_sources: handler.plugin_handle(source) handler.plugin_enable(dummy_sources[0]) found = [] result = [] def done(_found, _result): found.append(_found) result.append(_result) manager.acquire_cover(done, None, None) run_gtk_loop() self.assertFalse(found[0]) handler.plugin_enable(dummy_sources[1]) manager.acquire_cover(done, None, None) run_gtk_loop() self.assertTrue(found[1]) self.assertIs(result[1], DUMMY_COVER) handler.plugin_disable(dummy_sources[1]) handler.plugin_enable(dummy_sources[2]) manager.acquire_cover(done, None, None) run_gtk_loop() self.assertTrue(found[2]) self.assertIs(result[2], DUMMY_COVER) def test_acquire_cover_calls(self): # * fetch_cover shouldn't get called if source provides the cover # synchronously # * First cover source should fail providing the cover both # synchronously and asynchronously and only then the next source # should be used manager = CoverManager(use_built_in=False) handler = manager.plugin_handler found = [] result = [] for source in dummy_sources: handler.plugin_handle(source) handler.plugin_enable(source) source.cls.cover_call = False source.cls.fetch_call = False def done(_found, _result): found.append(_found) result.append(_result) manager.acquire_cover(done, None, None) run_gtk_loop() self.assertTrue(found[0]) self.assertIs(result[0], DUMMY_COVER) self.assertTrue(dummy_sources[0].cls.cover_call) self.assertTrue(dummy_sources[1].cls.cover_call) self.assertFalse(dummy_sources[2].cls.cover_call) self.assertFalse(dummy_sources[0].cls.fetch_call) self.assertFalse(dummy_sources[1].cls.fetch_call) self.assertFalse(dummy_sources[2].cls.fetch_call) for source in dummy_sources: source.cls.cover_call = False source.cls.fetch_call = False handler.plugin_disable(dummy_sources[1]) manager.acquire_cover(done, None, None) run_gtk_loop() self.assertTrue(found[1]) self.assertIs(result[1], DUMMY_COVER) self.assertTrue(dummy_sources[0].cls.cover_call) self.assertFalse(dummy_sources[1].cls.cover_call) self.assertTrue(dummy_sources[2].cls.cover_call) self.assertFalse(dummy_sources[0].cls.fetch_call) self.assertFalse(dummy_sources[1].cls.fetch_call) self.assertTrue(dummy_sources[2].cls.fetch_call) def test_search(self): manager = CoverManager(use_built_in=False) handler = manager.plugin_handler for source in dummy_sources: handler.plugin_handle(source) handler.plugin_enable(source) source.cls.cover_call = False source.cls.fetch_call = False song = AudioFile({ "~filename": os.path.join("/tmp/asong.ogg"), "album": "Abbey Road", "artist": "The Beatles" }) songs = [song] results = [] def done(manager, provider, result): self.failUnless(result, msg="Shouldn't succeed with no results") results.append(result) def finished(manager, songs): print("Finished!") manager.connect('covers-found', done) manager.search_cover(Cancellable(), songs) manager.connect('searches-complete', finished) run_gtk_loop() self.failUnlessEqual(len(results), 1) def tearDown(self): pass class TCoverManagerBuiltin(TestCase): def setUp(self): config.init() self.main = mkdtemp() self.dir1 = mkdtemp(dir=self.main) self.dir2 = mkdtemp(dir=self.main) h, self.cover1 = mkstemp(".png", dir=self.main) os.close(h) pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 10, 10) pb.savev(self.cover1, "png", [], []) h, self.cover2 = mkstemp(".png", dir=self.main) os.close(h) pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 20, 20) pb.savev(self.cover2, "png", [], []) self.file1 = get_temp_copy(get_data_path('silence-44-s.mp3')) self.file2 = get_temp_copy(get_data_path('silence-44-s.mp3')) self.manager = CoverManager() def tearDown(self): shutil.rmtree(self.main) config.quit() def test_connect_cover_changed(self): called_with = [] def sig_handler(*args): called_with.extend(args) obj = object() self.manager.connect("cover-changed", sig_handler) self.manager.cover_changed([obj]) self.assertEqual(called_with, [self.manager, [obj]]) def test_get_primary_image(self): self.assertFalse(MP3File(self.file1).has_images) self.assertFalse(MP3File(self.file1).has_images) def test_manager(self): self.assertEqual(len(list(self.manager.sources)), 2) def test_get_cover_many_prefer_embedded(self): # embed one cover, move one to the other dir MP3File(self.file1).set_image(EmbeddedImage.from_path(self.cover1)) os.unlink(self.cover1) self.external_cover = os.path.join(self.dir2, "cover.png") shutil.move(self.cover2, self.external_cover) # move one audio file in each dir shutil.move(self.file1, self.dir1) self.file1 = os.path.join(self.dir1, os.path.basename(self.file1)) shutil.move(self.file2, self.dir2) self.file2 = os.path.join(self.dir2, os.path.basename(self.file2)) song1 = MP3File(self.file1) song2 = MP3File(self.file2) # each should find a cover self.failUnless(self.is_embedded(self.manager.get_cover(song1))) self.failIf(self.is_embedded(self.manager.get_cover(song2))) cover_for = self.manager.get_cover_many # both settings should search both songs before giving up config.set("albumart", "prefer_embedded", True) self.failUnless(self.is_embedded(cover_for([song1, song2]))) self.failUnless(self.is_embedded(cover_for([song2, song1]))) config.set("albumart", "prefer_embedded", False) self.failIf(self.is_embedded(cover_for([song1, song2]))) self.failIf(self.is_embedded(cover_for([song2, song1]))) def is_embedded(self, fileobj): return not path_equal(fileobj.name, self.external_cover, True) def test_acquire_prefer_embedded(self): # embed one cover... MP3File(self.file1).set_image(EmbeddedImage.from_path(self.cover1)) os.unlink(self.cover1) self.external_cover = os.path.join(self.dir1, "cover.png") # ...and save a different cover externally shutil.copy(self.cover2, self.external_cover) shutil.move(self.file1, self.dir1) self.file1 = os.path.join(self.dir1, os.path.basename(self.file1)) both_song = MP3File(self.file1) results = [] def acquire(song): def cb(source, result): results.append(result) self.manager.acquire_cover(cb, None, song) def result_was_embedded(): return self.is_embedded(results.pop()) config.set("albumart", "prefer_embedded", True) acquire(both_song) self.failUnless(result_was_embedded(), "Embedded image expected due to prefs") config.set("albumart", "prefer_embedded", False) acquire(both_song) self.failIf(result_was_embedded(), "Got an embedded image despite prefs") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_plugins_events.py��������������������������������������������������������0000664�0001750�0001750�00000006612�14035600052�020025� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, mkstemp, mkdtemp import os import sys import shutil from quodlibet import player from quodlibet.library import SongLibrarian, SongLibrary from quodlibet.plugins import PluginManager from quodlibet.plugins.events import EventPluginHandler from quodlibet.qltk.songlist import SongList class TEventPlugins(TestCase): def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.lib = SongLibrarian() lib = SongLibrary() lib.librarian = self.lib self.songlist = SongList(library=lib) self.player = player.init_player("nullbe", self.lib) self.handler = EventPluginHandler( librarian=self.lib, player=self.player, songlist=self.songlist) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, []) def tearDown(self): self.pm.quit() shutil.rmtree(self.tempdir) def create_plugin(self, name='', funcs=None): fd, fn = mkstemp(suffix='.py', text=True, dir=self.tempdir) file = os.fdopen(fd, 'w') file.write("from quodlibet.plugins.events import EventPlugin\n") file.write("log = []\n") file.write("class %s(EventPlugin):\n" % name) indent = ' ' file.write("%spass\n" % indent) if name: file.write("%sPLUGIN_ID = %r\n" % (indent, name)) file.write("%sPLUGIN_NAME = %r\n" % (indent, name)) for f in (funcs or []): file.write("%sdef %s(s, *args): log.append((%r, args))\n" % (indent, f, f)) file.flush() file.close() def _get_calls(self, plugin): mod = sys.modules[plugin.cls.__module__] return mod.log def test_found(self): self.create_plugin(name='Name') self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_player_paused(self): self.create_plugin(name='Name', funcs=["plugin_on_paused"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.player.emit("paused") self.failUnlessEqual([("plugin_on_paused", tuple())], self._get_calls(plugin)) def test_lib_changed(self): self.create_plugin(name='Name', funcs=["plugin_on_changed"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.lib.emit("changed", [None]) self.failUnlessEqual([("plugin_on_changed", ([None],))], self._get_calls(plugin)) def test_songs_selected(self): self.create_plugin(name='Name', funcs=["plugin_on_songs_selected"]) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) plugin = self.pm.plugins[0] self.pm.enable(plugin, True) self.songlist.emit("selection-changed", self.songlist.get_selection()) self.failUnlessEqual(self._get_calls(plugin), [("plugin_on_songs_selected", ([], ))]) ����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_plugins_playlist.py������������������������������������������������������0000664�0001750�0001750�00000015540�14035600052�020362� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. """TODO: Share better with, i.e. test MenuItemPlugin directly""" import os import shutil from gi.repository import Gtk from quodlibet.browsers import Browser from quodlibet.library import SongLibrary from quodlibet.plugins.playlist import PlaylistPlugin, PlaylistPluginHandler from quodlibet.util.collection import Playlist from tests import TestCase, mkstemp, mkdtemp from quodlibet.plugins import PluginManager, Plugin from tests.helper import capture_output MAX_PLAYLISTS = 50 TEST_PLAYLIST = Playlist("foo") def generate_playlists(n): return [Playlist("Playlist %d" % x) for x in range(n)] class TPlaylistPlugins(TestCase): class MockBrowser(Browser): def __init__(self): super().__init__() self.activated = False def activate(self): self.activated = True def get_toplevel(self): return self def is_toplevel(self): return True def _confirmer(self, *args): self.confirmed = True def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.confirmed = False self.mock_browser = self.MockBrowser() self.handler = PlaylistPluginHandler(self._confirmer) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, []) self.library = SongLibrary('foo') def tearDown(self): self.library.destroy() self.pm.quit() shutil.rmtree(self.tempdir) def create_plugin(self, id='', name='', desc='', icon='', funcs=None, mod=False): fd, fn = mkstemp(suffix='.py', text=True, dir=self.tempdir) file = os.fdopen(fd, 'w') if mod: indent = '' else: file.write( "from quodlibet.plugins.playlist import PlaylistPlugin\n") file.write("class %s(PlaylistPlugin):\n" % name) indent = ' ' file.write("%spass\n" % indent) if name: file.write("%sPLUGIN_ID = %r\n" % (indent, name)) if name: file.write("%sPLUGIN_NAME = %r\n" % (indent, name)) if desc: file.write("%sPLUGIN_DESC = %r\n" % (indent, desc)) if icon: file.write("%sPLUGIN_ICON = %r\n" % (indent, icon)) for f in (funcs or []): if f in ["__init__"]: file.write("%sdef %s(self, *args): super().__init__(" "*args); raise Exception(\"as expected.\")\n" % (indent, f)) else: file.write("%sdef %s(*args): return args\n" % (indent, f)) file.flush() file.close() def test_empty_has_no_plugins(self): self.pm.rescan() self.assertEquals(self.pm.plugins, []) def test_name_and_desc_plus_func_is_one(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_playlist']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_additional_functions_still_only_one(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_playlist', 'plugin_playlists']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_two_plugins_are_two(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_playlist']) self.create_plugin(name='Name2', desc='Desc2', funcs=['plugin_albums']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 2) def test_disables_plugin(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_playlist']) self.pm.rescan() self.failIf(self.pm.enabled(self.pm.plugins[0])) def test_enabledisable_plugin(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_playlist']) self.pm.rescan() plug = self.pm.plugins[0] self.pm.enable(plug, True) self.failUnless(self.pm.enabled(plug)) self.pm.enable(plug, False) self.failIf(self.pm.enabled(plug)) def test_ignores_broken_plugin(self): self.create_plugin(name="Broken", desc="Desc", funcs=["__init__", "plugin_playlist"]) self.pm.rescan() plug = self.pm.plugins[0] self.pm.enable(plug, True) menu = Gtk.Menu() with capture_output(): self.handler.populate_menu(menu, None, self.mock_browser, [TEST_PLAYLIST]) self.failUnlessEqual(len(menu.get_children()), 0, msg="Shouldn't have enabled a broken plugin") def test_populate_menu(self): plugin = Plugin(FakePlaylistPlugin) self.handler.plugin_enable(plugin) menu = Gtk.Menu() self.handler.populate_menu(menu, None, self.mock_browser, [TEST_PLAYLIST]) # Don't forget the separator num = len(menu.get_children()) - 1 self.failUnlessEqual(num, 1, msg="Need 1 plugin not %d" % num) def test_handling_playlists_without_confirmation(self): plugin = Plugin(FakePlaylistPlugin) self.handler.plugin_enable(plugin) playlists = generate_playlists(MAX_PLAYLISTS) self.handler.handle(plugin.id, self.library, self.mock_browser, playlists) self.failUnless("Didn't execute plugin", FakePlaylistPlugin.total > 0) self.failIf(self.confirmed, ("Wasn't expecting a confirmation for %d" " invocations" % len(playlists))) def test_handling_lots_of_songs_with_confirmation(self): plugin = Plugin(FakePlaylistPlugin) self.handler.plugin_enable(plugin) playlists = generate_playlists(MAX_PLAYLISTS + 1) self.handler.handle(plugin.id, self.library, self.mock_browser, playlists) self.failUnless(self.confirmed, ("Should have confirmed %d invocations (Max=%d)." % (len(playlists), MAX_PLAYLISTS))) class FakePlaylistPlugin(PlaylistPlugin): PLUGIN_NAME = "Fake Playlist Plugin" PLUGIN_ID = "PlaylistMunger" MAX_INVOCATIONS = MAX_PLAYLISTS total = 0 def __init__(self, playlists, library): super().__init__(playlists, library) self.total = 0 def plugin_playlist(self, _): self.total += 1 if self.total > self.MAX_INVOCATIONS: raise ValueError("Shouldn't have called me on this many songs" " (%d > %d)" % (self.total, self.MAX_INVOCATIONS)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_plugins_songsmenu.py�����������������������������������������������������0000664�0001750�0001750�00000016074�14035600052�020542� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import shutil from quodlibet.library import SongLibrary from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import any_song, each_song from tests import TestCase, mkstemp, mkdtemp import os from quodlibet.formats import AudioFile from quodlibet.plugins import PluginManager, Plugin from quodlibet.qltk.songsmenu import SongsMenuPluginHandler from tests.helper import capture_output from tests.test_library_libraries import FakeSong class TSongsMenuPlugins(TestCase): def _confirmer(self, *args): self.confirmed = True def setUp(self): self.tempdir = mkdtemp() self.pm = PluginManager(folders=[self.tempdir]) self.confirmed = False self.handler = SongsMenuPluginHandler(self._confirmer, self._confirmer) self.pm.register_handler(self.handler) self.pm.rescan() self.assertEquals(self.pm.plugins, []) self.library = SongLibrary('foo') def tearDown(self): self.library.destroy() self.pm.quit() shutil.rmtree(self.tempdir) def create_plugin(self, id='', name='', desc='', icon='', funcs=None, mod=False): fd, fn = mkstemp(suffix='.py', text=True, dir=self.tempdir) file = os.fdopen(fd, 'w') if mod: indent = '' else: file.write( "from quodlibet.plugins.songsmenu import SongsMenuPlugin\n") file.write("class %s(SongsMenuPlugin):\n" % name) indent = ' ' file.write("%spass\n" % indent) if name: file.write("%sPLUGIN_ID = %r\n" % (indent, name)) if name: file.write("%sPLUGIN_NAME = %r\n" % (indent, name)) if desc: file.write("%sPLUGIN_DESC = %r\n" % (indent, desc)) if icon: file.write("%sPLUGIN_ICON = %r\n" % (indent, icon)) for f in (funcs or []): if f in ["__init__"]: file.write("%sdef %s(self, *args): super().__init__(" "*args); raise Exception(\"as expected\")\n" % (indent, f)) else: file.write("%sdef %s(*args): return args\n" % (indent, f)) file.flush() file.close() def test_empty_has_no_plugins(self): self.pm.rescan() self.assertEquals(self.pm.plugins, []) def test_name_and_desc_plus_func_is_one(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_additional_functions_still_only_one(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song', 'plugin_songs']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 1) def test_two_plugins_are_two(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.create_plugin(name='Name2', desc='Desc2', funcs=['plugin_albums']) self.pm.rescan() self.assertEquals(len(self.pm.plugins), 2) def test_disables_plugin(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.pm.rescan() self.failIf(self.pm.enabled(self.pm.plugins[0])) def test_enabledisable_plugin(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.pm.rescan() plug = self.pm.plugins[0] self.pm.enable(plug, True) self.failUnless(self.pm.enabled(plug)) self.pm.enable(plug, False) self.failIf(self.pm.enabled(plug)) def test_ignores_broken_plugin(self): self.create_plugin(name="Broken", desc="Desc", funcs=["__init__", "plugin_song"]) self.pm.rescan() plug = self.pm.plugins[0] self.pm.enable(plug, True) with capture_output(): menu = self.handler.Menu(None, [AudioFile()]) self.failIf(menu and menu.get_children()) def test_Menu(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.handler.Menu(None, [AudioFile()]) def test_handling_songs_without_confirmation(self): plugin = Plugin(FakeSongsMenuPlugin) self.handler.plugin_enable(plugin) MAX = FakeSongsMenuPlugin.MAX_INVOCATIONS songs = [AudioFile({'~filename': "/tmp/%s" % x, 'artist': 'foo'}) for x in range(MAX)] self.handler.handle(plugin.id, self.library, None, songs) self.failIf(self.confirmed, ("Wasn't expecting a confirmation for %d" " invocations" % len(songs))) def test_handling_lots_of_songs_with_confirmation(self): plugin = Plugin(FakeSongsMenuPlugin) self.handler.plugin_enable(plugin) MAX = FakeSongsMenuPlugin.MAX_INVOCATIONS songs = [AudioFile({'~filename': "/tmp/%s" % x, 'artist': 'foo'}) for x in range(MAX + 1)] self.handler.handle(plugin.id, self.library, None, songs) self.failUnless(self.confirmed, ("Should have confirmed %d invocations (Max=%d)." % (len(songs), MAX))) def even(i): return i % 2 == 0 def never(_): return False class Tsongsmenu(TestCase): songs = [FakeSong(1), FakeSong(2)] def test_any_song(self): FakeSongsMenuPlugin.plugin_handles = any_song(even) p = FakeSongsMenuPlugin(self.songs, None) self.failUnless(p.plugin_handles(self.songs)) self.failIf(p.plugin_handles(self.songs[:1])) def test_any_song_multiple(self): FakeSongsMenuPlugin.plugin_handles = any_song(even, never) p = FakeSongsMenuPlugin(self.songs, None) self.failIf(p.plugin_handles(self.songs)) self.failIf(p.plugin_handles(self.songs[:1])) def test_each_song(self): FakeSongsMenuPlugin.plugin_handles = each_song(even) p = FakeSongsMenuPlugin(self.songs, None) self.failIf(p.plugin_handles(self.songs)) self.failUnless(p.plugin_handles(self.songs[1:])) def test_each_song_multiple(self): FakeSongsMenuPlugin.plugin_handles = each_song(even, never) p = FakeSongsMenuPlugin(self.songs, None) self.failIf(p.plugin_handles(self.songs)) self.failIf(p.plugin_handles(self.songs[:1])) class FakeSongsMenuPlugin(SongsMenuPlugin): PLUGIN_NAME = "Fake Songs Menu Plugin" PLUGIN_ID = "SongsMunger" MAX_INVOCATIONS = 50 def __init__(self, songs, library): super().__init__(songs, library) self.total = 0 def plugin_song(self, song): self.total += 1 if self.total > self.MAX_INVOCATIONS: raise ValueError("Shouldn't have called me on this many songs" " (%d > %d)" % (self.total, self.MAX_INVOCATIONS)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_po.py��������������������������������������������������������������������0000664�0001750�0001750�00000025722�14231604332�015404� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import re from pathlib import Path import pytest from tests import TestCase, skipUnless from tests.helper import ListWithUnused as L ACCEPTABLE_STOCK = [ b'media-next', b'media-previous', b'media-play', b'media-pause'] try: import polib except ImportError: polib = None from quodlibet.util.string.titlecase import human_title from gdist import gettextutil # Don't use get_module_dir(), as venvs can arrange things differently QL_BASE_PATH = Path(__file__).parent.parent PO_PATH = QL_BASE_PATH / "po" def has_gettext_util(): try: gettextutil.check_version() except gettextutil.GettextError: return False return True class MissingTranslationsException(Exception): def __init__(self, missing): super().__init__("No reference in POTFILES.in to: " + ", ".join(missing)) @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_potfile_format(): with gettextutil.create_pot(PO_PATH) as pot_path: gettextutil.check_pot(pot_path) class TPOTFILESIN(TestCase): def test_no_extra_entries(self): """Works without polib installed...""" with open(PO_PATH / "POTFILES.in") as f: for fn in f: path = QL_BASE_PATH / fn.strip() assert path.is_file(), f"Can't read {path!r} from POTFILES.in" @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_missing(self): results = gettextutil.get_missing(PO_PATH) if results: raise MissingTranslationsException(results) @skipUnless(polib, "polib not found") @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") class TPot(TestCase): @classmethod def setUpClass(cls): with gettextutil.create_pot(PO_PATH) as pot_path: cls.pot = polib.pofile(pot_path) def conclude(self, fails, reason): if fails: def format_occurrences(e): return ', '.join('%s:%s' % o for o in e.occurrences) msg = "\n".join(f"{e.msgid!r} ({format_occurrences(e)})" for e in fails) self.fail(f"One or more messages did not pass ({reason}):\n{msg}") def test_multiple_format_placeholders(self): fails = [] reg = re.compile(r"((?<!%)%[sbcdoxXneEfFgG]|\{\})") for entry in self.pot: if len(reg.findall(entry.msgid)) > 1: fails.append(entry) self.conclude(fails, "uses multiple non-named format placeholders") def test_label_capitals(self): """ Check that various input labels (strings ending with a ':') are written with proper capitalization. Examples: Dough amount: - ok Salt: - ok Channel eggs through the Internet: - ok All Caps: - title case can't be used for labels Caveats: The test doesn't yet know which words are usually capitalized, so: Send to Kitchen: - will erroneously pass the test """ fails = [] ok_labels = L('Local _IP:', 'Songs with MBIDs:') for entry in self.pot: if not entry.msgid.endswith(':'): continue if ' ' not in entry.msgid.strip(): continue if entry.msgid == human_title(entry.msgid): if entry.msgid not in ok_labels: fails.append(entry) ok_labels.check_unused() self.conclude(fails, "title case used for a label") def test_whitespace(self): """ Check that there are no more than 1 space character ' ' in a row. Examples: "Quod Libet" - ok "Quod Libet" - extra whitespace "Traceback:\n <snip>" - ok Caveats: linebreaks and presumably other special characters in the messages are stored as literals, so when matching them with regular expressions, don't forget to use double backslash. """ fails = [] regex = re.compile(r'[^\\n] {2,}') for entry in self.pot: if regex.findall(entry.msgid): fails.append(entry) self.conclude(fails, "extra whitespace") def test_punctuation(self): """ Check that punctuation marks are used properly. Examples: Hello! - ok Hello ! - extra whitespace HH:MM:SS - ok example.com - ok Open .tags file - ok Hello,world - missing whitespace """ fails = [] regex = re.compile(r'\s[.,:;!?](?![a-z])|' r'[a-z](?<!people)[,:;][a-zA-Z]') for entry in self.pot: if regex.findall(entry.msgid): fails.append(entry) self.conclude(fails, "check punctuation") def test_ellipsis(self): # https://wiki.gnome.org/Initiatives/GnomeGoals/UnicodeUsage for entry in self.pot: self.assertFalse( "..." in entry.msgid, msg=u"%s should use '…' (ELLIPSIS) instead of '...'" % entry) def test_markup(self): # https://wiki.gnome.org/Initiatives/GnomeGoals/RemoveMarkupInMessages fails = [] for entry in self.pot: # This only checks strings starting and ending with a tag. # TODO: fix for all cases by adding a translator comment # and insert if re.match("<.*?>.*</.*?>", entry.msgid): fails.append(entry) self.conclude(fails, "contains markup, remove it!") def test_terms_letter_case(self): """ Check that some words are always written with a specific combination of lower and upper case letters. Examples: MusicBrainz - ok musicbrainz - lower case letters musicbrainz_track_id - ok musicbrainz.org - ok @(musicbrainz - ok """ terms = ( 'AcoustID', 'D-Bus', 'Ex Falso', 'GNOME', 'GStreamer', 'Internet', 'iPod', 'Last.fm', 'MusicBrainz', 'Python', 'Quod Libet', 'Replay Gain', 'ReplayGain', 'Squeezebox', 'Wikipedia') ok_prefixes = ('@(') ok_suffixes = ('_', '.org') fails = [] for entry in self.pot: msg = entry.msgid for term in terms: if term.lower() not in msg.lower(): continue i = msg.lower().find(term.lower()) if (msg[:i].endswith(ok_prefixes) or msg[i + len(term):].startswith(ok_suffixes)): continue if term not in msg: fails.append(entry) self.conclude(fails, "incorrect letter case for a term") def test_terms_spelling(self): """ Check if some words are misspelled. Some of the words are already checked in test_terms_letter_case, but some misspellings include not only letter case. Examples: Last.fm - ok LastFM - common misspelling """ incorrect_terms = ('Acoustid.org', 'ExFalso', 'LastFM', 'QuodLibet') fails = [] for entry in self.pot: for term in incorrect_terms: if term in entry.msgid: fails.append(entry) self.conclude(fails, "incorrect spelling for a term") def test_leading_and_trailing_spaces(self): fails = [] for entry in self.pot: if entry.msgid.strip() != entry.msgid: fails.append(entry) self.conclude(fails, "leading or trailing spaces") class POMixin: lang: str @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_pos(self): po_path = gettextutil.get_po_path(PO_PATH, self.lang) gettextutil.check_po(po_path) def test_gtranslator_breakage(self): with open(self.current_po_path(), "rb") as h: for line in h: if line.strip().startswith(b"#"): continue assert b"\xc2\xb7" not in line, \ f"Broken GTranslator copy/paste in {self.lang}:\n{line!r}" def test_gtk_stock_items(self): with open(self.current_po_path(), "rb") as h: for line in h: if line.strip().startswith(b'msgstr "gtk-'): parts = line.strip().split() value = parts[1].strip('"')[4:] self.failIf(value and value not in ACCEPTABLE_STOCK, f"Invalid stock translation in {self.lang}\n{line}") def conclude(self, fails, reason): if fails: def format_occurrences(e): occurences = [(self.lang + ".po", e.linenum)] occurences += e.occurrences return ', '.join('%s:%s' % o for o in occurences) message = "\n".join(f"{e.msgid!r} - {e.msgstr!r} ({format_occurrences(e)})" for e in fails) self.fail(f"One or more messages did not pass ({reason}).\n{message}") def test_original_punctuation_present(self): if polib is None: return LANGUAGES_TO_CHECK = ('ru', 'de') if self.lang not in LANGUAGES_TO_CHECK: return fails = [] # In some languages, for example Chinese and Japanese, it's usual to # put accelerators separately, on the end of the string in parentheses, # so the test needs to strip that part before checking the endings. par = re.compile(r' ?\(_\w\)$') for entry in polib.pofile(str(self.current_po_path())): if not entry.msgstr or entry.obsolete or 'fuzzy' in entry.flags: continue # Possible endings for the strings. Make sure to put longer # endings before shorter ones, for example: '...', '.' # otherwise this pair: 'a...', 'b..' will pass the test. ends = [(':', u':'), u'…', '...', ('.', u'。'), ' '] # First find the appropriate ending of msgid for end in ends: if entry.msgid.endswith(end): break else: continue # ... then check that msgstr ends with it as as well if not entry.msgstr.endswith(end): matches = par.findall(entry.msgstr) if matches and entry.msgstr[:-len(matches[0])].endswith(end): pass else: fails.append(entry) self.conclude(fails, "ending punctuation missing") def current_po_path(self) -> Path: return PO_PATH / f"{self.lang}.po" for lang in gettextutil.list_languages(PO_PATH): testcase = type('PO.' + str(lang), (TestCase, POMixin), {}) testcase.lang = lang globals()['PO.' + lang] = testcase ����������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1655124508.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk___init__.py���������������������������������������������������������0000664�0001750�0001750�00000011231�14251631034�017547� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from gi.repository import Gtk, Gdk from senf import fsnative, fsn2bytes from quodlibet.formats import AudioFile from quodlibet import qltk from quodlibet.qltk.pluginwin import PluginWindow from quodlibet import util from quodlibet.plugins import PluginManager from tests.gtk_helpers import MockSelData def test_is_instance_of_gtype_name(): assert qltk.is_instance_of_gtype_name(Gtk.Button(), "GtkButton") assert qltk.is_instance_of_gtype_name(Gtk.Button(), "GtkWidget") assert not qltk.is_instance_of_gtype_name(Gtk.Button(), "GtkLabel") assert not qltk.is_instance_of_gtype_name(Gtk.Button(), "NopeNopeNope") class TQltk(TestCase): def test_none(self): self.failUnless(qltk.get_top_parent(None) is None) def test_get_fg_highlight_color(self): widget = Gtk.Button() color = qltk.get_fg_highlight_color(widget) assert color is not None assert isinstance(color, Gdk.RGBA) def test_gtp(self): w = Gtk.Window() l = Gtk.Label() self.failUnlessEqual(qltk.get_top_parent(w), w) self.failUnlessEqual(qltk.get_top_parent(l), None) w.destroy() l.destroy() def test_gtp_packed(self): w = Gtk.Window() l = Gtk.Label() w.add(l) self.failUnlessEqual(qltk.get_top_parent(w), w) self.failUnlessEqual(qltk.get_top_parent(l), w) w.destroy() l.destroy() def test_is_accel(self): e = Gdk.Event.new(Gdk.EventType.KEY_RELEASE) self.failIf(qltk.is_accel(e, "a")) e = Gdk.Event.new(Gdk.EventType.KEY_PRESS) e.keyval = Gdk.KEY_Return e.state = Gdk.ModifierType.CONTROL_MASK self.failUnless(qltk.is_accel(e, "<ctrl>Return")) e = Gdk.Event.new(Gdk.EventType.KEY_PRESS) e.keyval = Gdk.KEY_Return e.state = Gdk.ModifierType.CONTROL_MASK self.failUnless(qltk.is_accel(e, "a", "<ctrl>Return")) self.failUnless(qltk.is_accel(e, "<ctrl>Return", "b")) self.failIf(qltk.is_accel(e, "a", "b")) def test_is_accel_invalid(self): e = Gdk.Event.new(Gdk.EventType.KEY_PRESS) with self.assertRaises(ValueError): qltk.is_accel(e, "NOPE") def test_is_accel_primary(self): e = Gdk.Event.new(Gdk.EventType.KEY_PRESS) e.keyval = Gdk.KEY_Return e.state = Gdk.ModifierType.CONTROL_MASK if not util.is_osx(): self.assertTrue(qltk.is_accel(e, "<Primary>Return")) def test_popup_menu_under_widget(self): w = Gtk.Window() l = Gtk.Label() w.add(l) m = Gtk.Menu() m.attach_to_widget(l, None) w.show_all() qltk.popup_menu_under_widget(m, l, 1, 0) w.destroy() m.destroy() def test_redraw_all(self): qltk.redraw_all_toplevels() def test_get_menu_item_top_parent(self): item = Gtk.MenuItem() menu = Gtk.Menu() menu.append(item) window = Gtk.Window() menu.attach_to_widget(window, None) self.assertEqual(qltk.get_menu_item_top_parent(item), window) def test_get_menu_item_top_parent_sub(self): item = Gtk.MenuItem() menu = Gtk.Menu() menu.append(item) window = Gtk.Window() menu.attach_to_widget(window, None) sub = Gtk.Menu() sub_item = Gtk.MenuItem() sub.append(sub_item) item.set_submenu(sub) self.assertEqual(qltk.get_menu_item_top_parent(sub_item), window) def test_get_menu_item_top_parent_unattached(self): item = Gtk.MenuItem() menu = Gtk.Menu() menu.append(item) self.assertTrue(qltk.get_menu_item_top_parent(item) is None) def test_show_uri_with_existing_window(self): PluginManager.instance = PluginManager() # Force an instance win = PluginWindow() qltk.show_uri("foo", "quodlibet:///prefs/plugins/Squeezebox Output") # TODO: proper assertions, etc win.destroy() def test_get_font_backend_name(self): name = qltk.get_font_backend_name() assert isinstance(name, str) class Tselection_data(TestCase): def test_selection_set_songs(self): song = AudioFile() song["~filename"] = fsnative(u"foo") sel = MockSelData() qltk.selection_set_songs(sel, [song]) assert sel.data == fsn2bytes(fsnative(u"foo"), "utf-8") assert qltk.selection_get_filenames(sel) == [fsnative(u"foo")] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk__editutils.py�������������������������������������������������������0000664�0001750�0001750�00000003523�14035600052�020156� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.formats import DUMMY_SONG from quodlibet.qltk._editutils import FilterCheckButton, \ OverwriteWarning, WriteFailedError, FilterPluginBox, EditingPluginHandler class FCB(FilterCheckButton): _section = _key = _label = "foo" class FCB2(FCB): _order = 1.0 class FCB3(FCB): _order = 1.2 class FCB4(FCB): _order = 1.3 class FCB5(FCB): _order = 1.3 class FCB1(FCB): _order = 1.4 class TFilterCheckButton(TestCase): def setUp(self): self.fcb1 = FCB1() self.fcb2 = FCB2() self.fcb3 = FCB3() self.fcb4 = FCB4() self.fcb5 = FCB5() def test_filter(self): self.failUnlessRaises(NotImplementedError, self.fcb1.filter, "", "") def test_filter_list(self): self.failUnlessRaises( NotImplementedError, self.fcb1.filter_list, [""], [""]) def test_cmp(self): l = [self.fcb1, self.fcb2, self.fcb3, self.fcb4, self.fcb5] l.sort() self.failUnlessEqual( l, [self.fcb2, self.fcb3, self.fcb4, self.fcb5, self.fcb1]) def tearDown(self): for cb in [self.fcb1, self.fcb2, self.fcb3, self.fcb4, self.fcb5]: cb.destroy() class TEditDialogs(TestCase): def test_overwrite(self): OverwriteWarning(None, DUMMY_SONG).destroy() def test_write_failed(self): WriteFailedError(None, DUMMY_SONG).destroy() class TFilterPluginBox(TestCase): def test_main(self): handler = EditingPluginHandler() x = FilterPluginBox(handler) self.assertEqual(x.filters, []) x.destroy() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_about.py������������������������������������������������������������0000664�0001750�0001750�00000001100�14035600052�017110� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet import app from quodlibet.qltk.about import AboutDialog from tests import TestCase, init_fake_app, destroy_fake_app class TAboutDialog(TestCase): def setUp(self): init_fake_app() def tearDown(self): destroy_fake_app() def test_ctr(self): AboutDialog(None, app).destroy() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_bookmarks.py��������������������������������������������������������0000664�0001750�0001750�00000003127�14035600052�020001� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2017 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests import TestCase from quodlibet.qltk.bookmarks import EditBookmarks, MenuItems, \ EditBookmarksPane from quodlibet.player.nullbe import NullPlayer from quodlibet.library import SongLibrary from quodlibet.formats import AudioFile from quodlibet import config class TBookmarks(TestCase): def setUp(self): config.init() player = NullPlayer() song = AudioFile() song.bookmarks = [(10, "bla")] song.sanitize(fsnative(u"/")) player.song = song self.player = player self.library = SongLibrary() def tearDown(self): self.player.destroy() config.quit() def test_edit_window(self): EditBookmarks(None, self.library, self.player).destroy() def test_menu_items(self): MenuItems(self.player.song.bookmarks, self.player, False) def test_add_bookmark_directly(self): song = self.player.song pane = EditBookmarksPane(self.library, song, close=True) model = [(31, "thirty-one seconds"), (180, "three minutes".encode('utf-8'))] pane._set_bookmarks(model, None, None, self.library, song) self.failUnlessEqual(len(song.bookmarks), 2) self.failUnlessEqual(song.bookmarks[1], (180, "three minutes")) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689624639.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_browser.py����������������������������������������������������������0000664�0001750�0001750�00000002327�14455320077�017511� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import quodlibet.config from quodlibet.browsers.albums import AlbumList from quodlibet.browsers.tracks import TrackList from quodlibet.library import SongLibrarian, SongLibrary from quodlibet.player.nullbe import NullPlayer from quodlibet.qltk.browser import LibraryBrowser from tests import TestCase class TLibraryBrowser(TestCase): def setUp(self): quodlibet.config.init() self.library = SongLibrary() def test_ctr(self): win = LibraryBrowser(AlbumList, self.library, NullPlayer()) win.browser.emit("songs-selected", [], False) win.songlist.get_selection().emit("changed") win.destroy() def test_open(self): self.library.librarian = SongLibrarian() widget = LibraryBrowser.open(TrackList, self.library, NullPlayer()) self.assertTrue(widget) self.assertTrue(widget.get_visible()) widget.destroy() def tearDown(self): self.library.destroy() quodlibet.config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_cbes.py�������������������������������������������������������������0000664�0001750�0001750�00000010607�14035600052�016726� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, mkstemp import os from quodlibet.qltk.cbes import ComboBoxEntrySave, StandaloneEditor import quodlibet.config class TComboBoxEntrySave(TestCase): memory = "pattern 1\npattern 2\n" saved = "pattern text\npattern name\n" def setUp(self): quodlibet.config.init() h, self.fname = mkstemp() os.close(h) with open(self.fname, "w") as f: f.write(self.memory) with open(self.fname + ".saved", "w") as f: f.write(self.saved) self.cbes = ComboBoxEntrySave(self.fname, count=2) self.cbes2 = ComboBoxEntrySave(self.fname, count=2) def test_equivalence(self): model1 = self.cbes.get_model() model2 = self.cbes2.get_model() self.failUnlessEqual(model1, model2) rows1 = list(model1) rows2 = list(model2) for row1, row2 in zip(rows1, rows2): self.failUnlessEqual(row1[0], row2[0]) self.failUnlessEqual(row1[1], row2[1]) self.failUnlessEqual(row1[2], row2[2]) def test_text_changed_signal(self): called = [0] def cb(*args): called[0] += 1 def get_count(): c = called[0] called[0] = 0 return c self.cbes.connect("text-changed", cb) entry = self.cbes.get_child() entry.set_text("foo") self.failUnlessEqual(get_count(), 1) self.cbes.prepend_text("bar") # in case the model got changed but the entry is still the same # the text-changed signal should not be triggered self.failUnlessEqual(entry.get_text(), "foo") self.failUnlessEqual(get_count(), 0) def test_shared_model(self): self.cbes.prepend_text("a test") self.test_equivalence() def test_initial_size(self): # 1 saved, Edit, separator, 2 remembered self.failUnlessEqual(len(self.cbes.get_model()), 5) def test_prepend_text(self): self.cbes.prepend_text("pattern 3") self.memory = "pattern 3\npattern 1\n" self.test_save() def test_save(self): self.cbes.write() self.failUnlessEqual(self.memory, open(self.fname).read()) self.failUnlessEqual(self.saved, open(self.fname + ".saved").read()) def test_set_text_then_prepend(self): self.cbes.get_child().set_text("foobar") self.cbes.prepend_text("foobar") self.memory = "foobar\npattern 1\n" self.test_save() def tearDown(self): self.cbes.destroy() self.cbes2.destroy() os.unlink(self.fname) os.unlink(self.fname + ".saved") quodlibet.config.quit() class TStandaloneEditor(TestCase): TEST_KV_DATA = [ ("Search Foo", "https://foo.com/search?q=<artist>-<title>")] def setUp(self): quodlibet.config.init() h, self.fname = mkstemp() os.close(h) with open(self.fname + ".saved", "w") as f: f.write( "%s\n%s\n" % (self.TEST_KV_DATA[0][1], self.TEST_KV_DATA[0][0])) self.sae = StandaloneEditor(self.fname, "test", None, None) def test_constructor(self): self.failUnless(self.sae.model) data = [(row[1], row[0]) for row in self.sae.model] self.failUnlessEqual(data, self.TEST_KV_DATA) def test_load_values(self): values = StandaloneEditor.load_values(self.fname + ".saved") self.failUnlessEqual(self.TEST_KV_DATA, values) def test_defaults(self): defaults = [("Dot-com Dream", "http://<artist>.com")] try: os.unlink(self.fname) except OSError: pass # Now create a new SAE without saved results and use defaults self.fname = "foo" self.sae.destroy() self.sae = StandaloneEditor(self.fname, "test2", defaults, None) self.sae.write() data = [(row[1], row[0]) for row in self.sae.model] self.failUnlessEqual(defaults, data) def tearDown(self): self.sae.destroy() try: os.unlink(self.fname) os.unlink(self.fname + ".saved") except OSError: pass quodlibet.config.quit() �������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_ccb.py��������������������������������������������������������������0000664�0001750�0001750�00000004324�14231604332�016543� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, run_gtk_loop from quodlibet import config from quodlibet.qltk.ccb import ConfigCheckButton, ConfigCheckMenuItem class TConfigCheckButton(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_toggle(self): config.set("memory", "bar", "on") c = ConfigCheckButton("dummy", "memory", "bar") c.set_active(True) self.failUnless(config.getboolean("memory", "bar") and c.get_active()) c.set_active(False) run_gtk_loop() self.failIf(config.getboolean("memory", "bar") or c.get_active()) def test_populate(self): # Assert that active state works config.set("memory", "bar", "on") c = ConfigCheckButton("dummy", "memory", "bar", populate=True) run_gtk_loop() self.failUnless(c.get_active()) # ...and inactive config.set("memory", "bar", "off") c = ConfigCheckButton("dummy", "memory", "bar", populate=True) run_gtk_loop() self.failIf(c.get_active()) class TConfigCheckMenuItem(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_toggle(self): config.set("memory", "bar", "on") c = ConfigCheckMenuItem("dummy", "memory", "bar") c.set_active(True) self.failUnless(config.getboolean("memory", "bar") and c.get_active()) c.set_active(False) run_gtk_loop() self.failIf(config.getboolean("memory", "bar") or c.get_active()) def test_populate(self): # Assert that active state works config.set("memory", "bar", "on") c = ConfigCheckMenuItem("dummy", "memory", "bar", populate=True) run_gtk_loop() self.failUnless(c.get_active()) # ...and inactive config.set("memory", "bar", "off") c = ConfigCheckMenuItem("dummy", "memory", "bar", populate=True) run_gtk_loop() self.failIf(c.get_active()) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_chooser.py����������������������������������������������������������0000644�0001750�0001750�00000004544�14266344767�017505� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk from senf import fsnative from quodlibet.qltk.chooser import choose_files, get_current_dir, \ set_current_dir, choose_folders, create_chooser_filter, \ choose_target_file, choose_target_folder, with_response from quodlibet.qltk import gtk_version from quodlibet.util import is_osx, is_wine from . import TestCase, skipIf @skipIf(is_wine(), "hangs under wine") @skipIf(gtk_version < (3, 16, 0) or is_osx(), "crashy on older gtk+ and macOS") class Tchooser(TestCase): def test_choose_files(self): w = Gtk.Window() with with_response(Gtk.ResponseType.CANCEL): assert choose_files(w, u"title", u"action") == [] def test_choose_folders(self): w = Gtk.Window() with with_response(Gtk.ResponseType.CANCEL): assert choose_folders(w, u"title", u"action") == [] def test_choose_filter(self): cf = create_chooser_filter(u"filter", ["*.txt"]) assert isinstance(cf, Gtk.FileFilter) assert cf.get_name() == u"filter" w = Gtk.Window() with with_response(Gtk.ResponseType.CANCEL): assert choose_files(w, u"title", u"action", cf) == [] def test_choose_target_file(self): w = Gtk.Window() with with_response(Gtk.ResponseType.CANCEL): assert choose_target_file(w, u"title", u"action") is None with with_response(Gtk.ResponseType.CANCEL): assert choose_target_file( w, u"title", u"action", u"example") is None def test_choose_target_folder(self): w = Gtk.Window() with with_response(Gtk.ResponseType.CANCEL): assert choose_target_folder(w, u"title", u"action") is None with with_response(Gtk.ResponseType.CANCEL): assert choose_target_folder( w, u"title", u"action", u"example") is None def test_get_current_dir(self): path = get_current_dir() assert isinstance(path, fsnative) def test_set_current_dir(self): set_current_dir(fsnative(u".")) assert get_current_dir() == os.getcwd() ������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_completion.py�������������������������������������������������������0000664�0001750�0001750�00000002666�14035600052�020171� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from gi.repository import Gtk from quodlibet import config from quodlibet.library import SongLibrary from quodlibet.qltk.completion import EntryWordCompletion, LibraryTagCompletion from quodlibet.qltk.completion import LibraryValueCompletion class TEntryWordCompletion(TestCase): def test_ctr(self): w = EntryWordCompletion() e = Gtk.Entry() e.set_completion(w) self.failUnlessEqual(w.get_entry(), e) self.failUnlessEqual(e.get_completion(), w) e.destroy() class TLibraryTagCompletion(TestCase): def test_ctr(self): w = LibraryTagCompletion(SongLibrary()) e = Gtk.Entry() e.set_completion(w) self.failUnlessEqual(w.get_entry(), e) self.failUnlessEqual(e.get_completion(), w) e.destroy() class TLibraryValueCompletion(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_ctr(self): w = LibraryValueCompletion("artist", SongLibrary()) e = Gtk.Entry() e.set_completion(w) self.failUnlessEqual(w.get_entry(), e) self.failUnlessEqual(e.get_completion(), w) e.destroy() ��������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_controls.py���������������������������������������������������������0000664�0001750�0001750�00000001704�14035600052�017653� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk.controls import PlayControls, VolumeMenu from quodlibet.qltk.controls import Volume from quodlibet.library import SongLibrary from quodlibet.player.nullbe import NullPlayer from quodlibet import config class TControls(TestCase): def setUp(self): config.init() self.p = NullPlayer() self.l = SongLibrary() def tearDown(self): config.quit() def test_controls(self): w = PlayControls(self.p, self.l) w.destroy() def test_volumemenu(self): w = VolumeMenu(self.p) w.destroy() def test_volume(self): w = Volume(self.p) w.destroy() ������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1655124512.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_cover.py������������������������������������������������������������0000664�0001750�0001750�00000003340�14251631040�017125� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from gi.repository import Gtk, GdkPixbuf, Gdk from tests import TestCase, mkstemp, init_fake_app, destroy_fake_app from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.qltk.cover import (CoverImage, BigCenteredImage, ResizeImage, get_no_cover_pixbuf) class TCoverImage(TestCase): def setUp(self): config.init() init_fake_app() fd, self.fn = mkstemp() os.close(fd) pb = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) pb.savev(self.fn, "png", [], []) def tearDown(self): destroy_fake_app() config.quit() os.remove(self.fn) def test_set_song(self): c = CoverImage() c.set_song(AudioFile({"~filename": "woo"})) event = Gdk.Event.new(Gdk.EventType.BUTTON_PRESS) event.type.button = 1 c.emit("button-press-event", event) c.destroy() def test_big_window(self): parent = Gtk.Window() w = BigCenteredImage("foobar", open(self.fn, "rb"), parent) w.destroy() def test_resize(self): w = ResizeImage(False) w.set_file(open(self.fn, "rb")) w.set_file(None) w.destroy() def test_no_cover(self): pb = get_no_cover_pixbuf(5, 10) self.assertEqual(pb.get_width(), 5) self.assertEqual(pb.get_height(), 5) pb = get_no_cover_pixbuf(10, 5) self.assertEqual(pb.get_width(), 5) self.assertEqual(pb.get_height(), 5) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_data_editors.py�����������������������������������������������������0000644�0001750�0001750�00000001537�14266344767�020504� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet import config from tests import TestCase from quodlibet.qltk.data_editors import TagListEditor class TTagListEditor(TestCase): def setUp(self): config.init() def test_no_strings(self): mse = TagListEditor("title") self.failUnlessEqual(mse.tags, []) self.failUnlessEqual(mse.get_title(), "title") mse.destroy() def test_defaulting(self): defaults = ["one", "two three"] mse = TagListEditor("title", defaults) self.failUnlessEqual(mse.tags, defaults) mse.destroy() def tearDown(self): config.quit() �����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_delete.py�����������������������������������������������������������0000664�0001750�0001750�00000003332�14035600052�017251� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from senf import fsnative from tests import TestCase from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.qltk.delete import DeleteDialog, TrashDialog, TrashMenuItem SONG = AudioFile({"~filename": fsnative(u"/dev/null")}) SONG.sanitize() class TDeleteDialog(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_delete_songs(self): dialog = DeleteDialog.for_songs(None, []) dialog.destroy() def test_delete_files(self): dialog = DeleteDialog.for_files(None, []) dialog.destroy() def test_trash_songs(self): dialog = TrashDialog.for_songs(None, []) dialog.destroy() def test_trash_files(self): dialog = TrashDialog.for_files(None, []) dialog.destroy() def test_delete_songs_full(self): w = Gtk.Window() dialog = DeleteDialog.for_songs(w, [SONG]) dialog.destroy() def test_delete_files_full(self): w = Gtk.Window() dialog = DeleteDialog.for_files(w, [SONG("~filename")]) dialog.destroy() def test_trash_songs_full(self): w = Gtk.Window() dialog = TrashDialog.for_songs(w, [SONG]) dialog.destroy() def test_trash_files_full(self): w = Gtk.Window() dialog = TrashDialog.for_files(w, [SONG("~filename")]) dialog.destroy() def test_menu_item(self): TrashMenuItem().destroy() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_download.py���������������������������������������������������������0000664�0001750�0001750�00000001665�14244626671�017646� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.formats.remote import RemoteFile from quodlibet.qltk.download import DownloadProgress from tests import TestCase, mkdtemp, run_gtk_loop def an_rf(i: int) -> AudioFile: return RemoteFile(f"https://github.com/quodlibet/quodlibet/{i}.mp3") class TDownloadProgress(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_download_fails_for_non_existent(self): songs = [an_rf(i) for i in range(3)] d = DownloadProgress(songs) for _ in d.download_songs(mkdtemp()): run_gtk_loop() assert d.failed == set(songs) ���������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_edittags.py���������������������������������������������������������0000664�0001750�0001750�00000011273�14035600052�017616� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter # 2020 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from unittest.mock import Mock import quodlibet.config from quodlibet import app from quodlibet.formats import AudioFile from quodlibet.plugins.editing import EditTagsPlugin from quodlibet.qltk.edittags import (SplitValues, SplitDisc, SplitTitle, SplitArranger, AddTagDialog, AudioFileGroup, EditTags, ListEntry, Comment, EditTagsPluginHandler) from quodlibet.qltk.properties import SongProperties from tests import TestCase, init_fake_app, destroy_fake_app class DummyEditPlugin(EditTagsPlugin): activations = [] def activated(self, tag, value): self.activations.append((tag, value)) return super().activated(tag, value) class TEditTags(TestCase): def setUp(self): init_fake_app() quodlibet.config.init() def tearDown(self): quodlibet.config.quit() destroy_fake_app() def test_items(self): SplitValues("foo", "bar").destroy() SplitDisc("foo", "bar").destroy() SplitTitle("foo", "bar").destroy() SplitArranger("foo", "bar").destroy() def test_addtag_dialog(self): AddTagDialog(None, ["artist"], app.library).destroy() def test_edit_tags_starts(self): props = SongProperties(app.library, [], quodlibet.app.window) EditTags(props, app.library) def test_edit_tags_popup_menu(self): song = AudioFile({"~filename": "/dev/null", "artist": "Person", "album": "Dj Bars of FOO"}) props = SongProperties(app.library, [song], app.window) box = EditTags(props, app.library) # Add a fake plugin plugin_cls = DummyEditPlugin box.handler = Mock(EditTagsPluginHandler) box.handler.plugins = [plugin_cls] model = box._view.get_model() # Make sure there's a row tag, value = "artist", song("artist") entry = ListEntry(tag, Comment(value)) model.append(row=[entry]) box._group_info = AudioFileGroup([song]) box._view.select_by_func(lambda _: True) # Prevent weird mouse stuff failing in tests box._view.ensure_popup_selection = lambda: False box._popup_menu(box._view, props) box.show() assert plugin_cls.activations == [(tag, value)] class GroupSong(AudioFile): def __init__(self, can_multiple=True, can_change=True, cant_change=[]): self._can_multiple = can_multiple self._can_change = can_change self._cant_change = cant_change def can_multiple_values(self, key=None): if key is None: return self._can_multiple if self._can_multiple is True: return True return key in self._can_multiple def can_change(self, key=None): if key is None: return self._can_change if self._can_change is True: return key not in self._cant_change return key in self._can_change class TAudioFileGroup(TestCase): def test_multiple_values(self): group = AudioFileGroup([GroupSong(True), GroupSong(True)]) self.assertTrue(group.can_multiple_values() is True) self.assertTrue(group.can_multiple_values("foo") is True) group = AudioFileGroup([GroupSong(["ha"]), GroupSong(True)]) self.assertEqual(group.can_multiple_values(), {"ha"}) self.assertFalse(group.can_multiple_values("foo")) self.assertTrue(group.can_multiple_values("ha")) group = AudioFileGroup([GroupSong(["foo", "ha"]), GroupSong(["ha"])]) self.assertEqual(group.can_multiple_values(), {"ha"}) self.assertFalse(group.can_multiple_values("foo")) self.assertTrue(group.can_multiple_values("ha")) def test_can_change(self): group = AudioFileGroup( [GroupSong(can_change=True), GroupSong(can_change=True)]) self.assertTrue(group.can_change() is True) self.assertTrue(group.can_change("foo") is True) group = AudioFileGroup( [GroupSong(can_change=["foo", "ha"]), GroupSong(can_change=["ha"])]) self.assertEqual(group.can_change(), {"ha"}) self.assertFalse(group.can_change("foo")) self.assertTrue(group.can_change("ha")) group = AudioFileGroup([GroupSong(), GroupSong(cant_change=["baz"])]) self.assertTrue(group.can_change()) self.assertFalse(group.can_change("baz")) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_entry.py������������������������������������������������������������0000664�0001750�0001750�00000010402�14035600052�017144� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from .helper import visible from quodlibet.qltk.entry import ValidatingEntry, UndoEntry, Entry from quodlibet.query._query import Query import quodlibet.config class TEntry(TestCase): def test_set_max_width_chars(self): with visible(Entry()) as e: e.set_max_width_chars(4) nat1 = e.get_preferred_width()[1] e.set_max_width_chars(40) nat2 = e.get_preferred_width()[1] self.assertTrue(nat1 < nat2) class TValidatingEntry(TestCase): def setUp(self): quodlibet.config.init() self.entry = ValidatingEntry(Query.validator) def test_changed_simple(self): self.entry.set_text("valid") def test_changed_valid(self): self.entry.set_text("search = 'valid'") def test_changed_invalid(self): self.entry.set_text("=#invalid") def test_custom_validator(self): x = [] def valid(text): x.append(text) return text entry = ValidatingEntry(valid) entry.set_text("foo") self.assertEqual(x, [u"foo"]) self.assertTrue(isinstance(x[0], str)) def tearDown(self): self.entry.destroy() quodlibet.config.quit() class TUndoEntry(TestCase): def setUp(self): self.entry = UndoEntry() def __equal(self, value): entry_val = self.entry.get_text() self.failUnlessEqual(value, entry_val) def __insert(self, text, pos): self.entry.insert_text(text, position=pos) self.entry.set_position(pos + len(text)) def __delete_left(self, start, end): self.entry.set_position(start) self.entry.delete_text(start, end) self.entry.set_position(start) def __delete_right(self, start, end): self.entry.set_position(end) self.entry.delete_text(start, end) self.entry.set_position(start) def test_undo_reset(self): entry = self.entry self.__insert("foo", 0) self.__insert("bar", 0) entry.reset_undo() entry.undo() entry.undo() entry.undo() self.__equal("barfoo") def test_undo_norm(self): entry = self.entry self.__insert("foo", 0) entry.undo() self.__equal("") entry.redo() self.__equal("foo") def test_undo_space(self): entry = self.entry self.__insert("f", 0) self.__insert(" ", 1) self.__insert("o", 2) entry.undo() self.__equal("f ") entry.undo() self.__equal("") def test_undo_insert_end(self): entry = self.entry self.__insert("f", 0) self.__insert("o", 1) self.__insert("o", 2) entry.undo() self.__equal("") entry.redo() self.__equal("foo") def test_undo_insert_end_2(self): entry = self.entry self.__insert("f", 0) self.__insert("o", 1) self.__insert("o", 2) self.__insert("bar", 3) entry.undo() self.__equal("foo") entry.redo() self.__equal("foobar") def test_undo_insert_middle(self): entry = self.entry self.__insert("foo", 0) self.__insert("b", 1) self.__equal("fboo") entry.undo() self.__equal("foo") entry.undo() self.__equal("") def test_undo_delete(self): entry = self.entry self.__insert("foobar", 0) self.__delete_left(3, 4) self.__equal("fooar") self.__delete_right(1, 3) self.__equal("far") entry.undo() self.__equal("fooar") entry.undo() self.__equal("foobar") def test_undo_delete_space(self): entry = self.entry self.__insert("foob ar", 0) self.__delete_right(6, 7) self.__equal("foob a") self.__delete_right(5, 6) self.__delete_right(4, 5) self.__delete_right(3, 4) self.__delete_right(2, 3) entry.undo() self.__equal("foob") def tearDown(self): self.entry.destroy() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_exfalso.py����������������������������������������������������������0000664�0001750�0001750�00000002161�14231604332�017452� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.qltk import exfalsowindow from tests import TestCase from quodlibet.qltk.exfalsowindow import ExFalsoWindow from quodlibet.library import SongLibrary import quodlibet.config class TExFalsoWindow(TestCase): def setUp(self): quodlibet.config.init() self.ef = ExFalsoWindow(SongLibrary()) def test_nothing(self): self.failUnless(self.ef.get_child()) def tearDown(self): self.ef.destroy() quodlibet.config.quit() def test_prefs(self): self.prefs = exfalsowindow.PreferencesWindow(None) self.prefs.present() assert self.prefs.get_title() == "Ex Falso Preferences" assert self.prefs.get_child(), "No window contents" pages = [type(p) for p in self.prefs.get_child().get_children()] assert pages == [self.prefs.Tagging], "Wrong prefs pages" self.prefs.destroy() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_filesel.py����������������������������������������������������������0000664�0001750�0001750�00000013126�14035600052�017434� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, mkdtemp from tests.helper import __ import os import sys sys.modules['dircache'] = os # cheat the dircache effects from senf import fsnative from quodlibet.qltk.filesel import DirectoryTree, FileSelector, get_drives, \ MainDirectoryTree, MainFileSelector, get_gtk_bookmarks, parse_gtk_bookmarks from quodlibet.util.path import get_home_dir import quodlibet.config from quodlibet.util import is_windows class Tget_gtk_bookmarks(TestCase): def test_main(self): paths = get_gtk_bookmarks() assert all(isinstance(p, fsnative) for p in paths) def test_parse(self): if is_windows(): return data = (b'file:///foo/bar\nfile:///home/user\n' b'file:///home/user/Downloads Downloads\n') paths = parse_gtk_bookmarks(data) assert all(isinstance(p, fsnative) for p in paths) class TDirectoryTree(TestCase): if os.name == "nt": ROOTS = [get_home_dir(), u"C:\\"] else: ROOTS = [get_home_dir(), "/"] def setUp(self): quodlibet.config.init() def tearDown(self): quodlibet.config.quit() def test_initial(self): if os.name == "nt": paths = [u"C:\\", get_home_dir()] else: paths = ["/", get_home_dir()] for path in paths: dirlist = DirectoryTree(path, folders=self.ROOTS) model, rows = dirlist.get_selection().get_selected_rows() selected = [model[row][0] for row in rows] dirlist.destroy() self.failUnlessEqual([os.path.normpath(path)], selected) def test_bad_initial(self): invalid = os.path.join("bin", "file", "does", "not", "exist") for path in self.ROOTS: newpath = os.path.join(path, invalid) dirlist = DirectoryTree(newpath, folders=self.ROOTS) selected = dirlist.get_selected_paths() dirlist.destroy() # select the last valid parent directory self.assertEqual(len(selected), 1) self.assertTrue(selected[0].startswith(path)) def test_bad_go_to(self): newpath = fsnative(u"/woooooo/bar/fun/broken") dirlist = DirectoryTree(fsnative(u"/"), folders=self.ROOTS) dirlist.go_to(newpath) dirlist.destroy() def test_main(self): folders = ["/"] if os.name == "nt": folders = [u"C:\\"] main = MainDirectoryTree(folders=folders) self.assertTrue(len(main.get_model())) main = MainDirectoryTree() self.assertTrue(len(main.get_model())) def test_get_drives(self): for path in get_drives(): self.assertTrue(isinstance(path, fsnative)) def test_popup(self): dt = DirectoryTree(None, folders=self.ROOTS) menu = dt._create_menu() dt._popup_menu(menu) children = menu.get_children() self.failUnlessEqual(len(children), 4) delete = children[1] self.failUnlessEqual(delete.get_label(), __("_Delete")) self.failUnless(delete.get_sensitive()) def test_multiple_selections(self): dt = DirectoryTree(None, folders=self.ROOTS) menu = dt._create_menu() dt._popup_menu(menu) children = menu.get_children() select_sub = children[3] self.failUnless("sub-folders" in select_sub.get_label().lower()) self.failUnless(select_sub.get_sensitive()) sel = dt.get_selection() model = dt.get_model() for it, pth in model.iterrows(None): sel.select_iter(it) self.failUnless(select_sub.get_sensitive(), msg="Select All should work for multiple") self.failIf(children[0].get_sensitive(), msg="New Folder should be disabled for multiple") self.failUnless(children[3].get_sensitive(), msg="Refresh should be enabled for multiple") class TFileSelector(TestCase): def setUp(self): quodlibet.config.init() self.ROOTS = [mkdtemp(), mkdtemp()] self.INITIAL = self.ROOTS[0] self.PATHS = [ os.path.join(self.ROOTS[0], "a"), os.path.join(self.ROOTS[0], "b"), ] for path in self.PATHS: open(path, "wb").close() self.fs = FileSelector( initial=self.INITIAL, filter=(lambda s: s in self.PATHS), folders=self.ROOTS) self.fs.connect('changed', self._changed) self.files = None self.fs.rescan() def tearDown(self): self.fs.destroy() quodlibet.config.quit() for file_ in self.PATHS: os.unlink(file_) for dir_ in self.ROOTS: os.rmdir(dir_) def _changed(self, fs, selection): self.selection = selection self.files = fs.get_selected_paths() self.files.sort() def test_select(self): expected = self.PATHS expected.sort() self.selection.select_all() self.assertEqual(self.files, expected) def test_select_rescan(self): expected = self.PATHS expected.sort() self.selection.select_all() self.assertEqual(self.files, expected) files_prev = self.fs.get_selected_paths() self.fs.rescan() self.assertEqual(self.files, expected) self.assertEqual(self.files, files_prev) def test_main(self): MainFileSelector() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_getstring.py��������������������������������������������������������0000664�0001750�0001750�00000002731�14035600052�020017� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk, Gdk from tests import TestCase, skipIf from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk import is_wayland class _ClipboadTestClass(GetStringDialog): _OK = True def _verify_clipboard(self, text): if self._OK: return text @skipIf(is_wayland(), "blocks under wayland for some reason") class TGetStringDialog(TestCase): def setUp(self): parent = Gtk.Window() self.gsd1 = GetStringDialog(parent, "title", "enter a string") self.gsd2 = _ClipboadTestClass(parent, "title", "enter a string") def test_getstring(self): ret = self.gsd1.run(text="foobar", test=True) self.failUnlessEqual(ret, "foobar") def test_tooltip(self): foo = GetStringDialog(Gtk.Window(), "title", "", tooltip="foo bar") self.failUnlessEqual(foo._val.get_tooltip_text(), "foo bar") def test_clipboard(self): clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard.set_text("42", -1) ret = self.gsd2.run(text="24", clipboard=True, test=True) self.failUnlessEqual(ret, "42") clipboard.clear() def tearDown(self): self.gsd1.destroy() self.gsd2.destroy() ���������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_image.py������������������������������������������������������������0000664�0001750�0001750�00000005137�14035600052�017076� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase import cairo from gi.repository import Gtk, GdkPixbuf, Gdk from quodlibet.qltk.image import get_surface_extents, get_surface_for_pixbuf, \ scale, calc_scale_size, add_border, add_border_widget class TImageUtils(TestCase): def setUp(self): self.small = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 10, 20) self.wide = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) self.high = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 10, 100) def test_get_surface_for_pixbuf(self): w = Gtk.Button() rgb = GdkPixbuf.Colorspace.RGB newpb = GdkPixbuf.Pixbuf.new(rgb, True, 8, 10, 10) surface = get_surface_for_pixbuf(w, newpb) self.assertTrue(isinstance(surface, cairo.Surface)) def test_scale(s): nw = scale(s.wide, (50, 30)) s.failUnlessEqual((nw.get_width(), nw.get_height()), (50, 3)) nh = scale(s.high, (100, 20)) s.failUnlessEqual((nh.get_width(), nh.get_height()), (2, 20)) ns = scale(s.small, (500, 300)) s.failUnlessEqual((ns.get_width(), ns.get_height()), (150, 300)) ns = scale(s.small, (500, 300), scale_up=False) s.failUnlessEqual((ns.get_width(), ns.get_height()), (10, 20)) def test_calc_scale_size(self): self.assertRaises(ValueError, calc_scale_size, (1, 1), (1, 0)) res = calc_scale_size((100, 100), (500, 100)) self.assertEqual(res, (100, 20)) def test_add_border(self): color = Gdk.RGBA() w, h = self.small.get_width(), self.small.get_height() res = add_border(self.small, color) self.assertEqual(res.get_width(), w + 2) self.assertEqual(res.get_height(), h + 2) res = add_border(self.small, color) self.assertEqual(res.get_width(), w + 2) self.assertEqual(res.get_height(), h + 2) res = add_border(self.small, color, width=2) self.assertEqual(res.get_width(), w + 4) self.assertEqual(res.get_height(), h + 4) def test_add_border_widget(self): widget = Gtk.Button() add_border_widget(self.small, widget) def test_get_surface_extents(self): sf = cairo.ImageSurface(cairo.FORMAT_RGB24, 10, 11) self.assertEqual(get_surface_extents(sf), (0, 0, 10, 11)) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_info.py�������������������������������������������������������������0000644�0001750�0001750�00000002316�14266344767�016771� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import tempfile from quodlibet import app from tests import TestCase, destroy_fake_app, init_fake_app from quodlibet.player.nullbe import NullPlayer from quodlibet.qltk.info import SongInfo from quodlibet.library import SongLibrary SOME_PATTERN = "foo\n[big]<title>[/big] - <artist>" class FakePatternEdit: @property def text(self): return SOME_PATTERN class TSongInfo(TestCase): def setUp(self): init_fake_app() fd, self.filename = tempfile.mkstemp() os.close(fd) self.info = SongInfo(SongLibrary(), NullPlayer(), self.filename) def test_save(self): fake_edit = FakePatternEdit() self.info._on_set_pattern(None, fake_edit, app.player) with open(self.filename, "r") as f: contents = f.read() self.failUnlessEqual(contents, SOME_PATTERN + "\n") def tearDown(self): destroy_fake_app() self.info.destroy() os.unlink(self.filename) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_information.py������������������������������������������������������0000664�0001750�0001750�00000006754�14035600052�020347� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from senf import fsnative from tests import TestCase, init_fake_app, destroy_fake_app from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary from quodlibet.qltk.information import Information, OneArtist, OneAlbum, \ ManySongs, OneSong, TitleLabel, _sort_albums import quodlibet.config def AF(*args, **kwargs): a = AudioFile(*args, **kwargs) a.sanitize() return a class TInformation(TestCase): def setUp(self): quodlibet.config.init() init_fake_app() self.inf = None self.library = SongLibrary() def tearDown(self): destroy_fake_app() self.library.destroy() quodlibet.config.quit() if self.inf: self.inf.destroy() def test_none(self): Information(self.library, []).destroy() def test_one(self): f = AF({"~filename": fsnative(u"/dev/null")}) self.inf = Information(self.library, [f]) self.assert_child_is(OneSong) def test_two(self): f = AF({"~filename": fsnative(u"/dev/null")}) f2 = AF({"~filename": fsnative(u"/dev/null2")}) self.inf = Information(self.library, [f, f2]) self.assert_child_is(ManySongs) def test_album(self): f = AF({"~filename": fsnative(u"/dev/null"), "album": "woo"}) f2 = AF({"~filename": fsnative(u"/dev/null2"), "album": "woo"}) self.inf = Information(self.library, [f, f2]) self.assert_child_is(OneAlbum) def test_album_special_chars(self): f = AF({"~filename": fsnative(u"/dev/null"), "album": "woo & hoo"}) f2 = AF({"~filename": fsnative(u"/dev/null2"), "album": "woo & hoo"}) self.inf = Information(self.library, [f, f2]) self.assert_child_is(OneAlbum) def test_artist(self): f = AF({"~filename": fsnative(u"/dev/null"), "artist": "woo"}) f2 = AF({"~filename": fsnative(u"/dev/null2"), "artist": "woo"}) self.inf = Information(self.library, [f, f2]) self.assert_child_is(OneArtist) def test_performer_roles(self): f = AF({"~filename": fsnative(u"/dev/null"), "performer:piano": "woo"}) self.inf = Information(self.library, [f]) self.assert_child_is(OneSong) def test_remove_song(self): f = AF({"~filename": fsnative(u"/dev/null"), "artist": "woo"}) f2 = AF({"~filename": fsnative(u"/dev/null2"), "artist": "woo"}) self.library.add([f, f2]) self.inf = Information(self.library, [f, f2]) self.library.remove([f]) def assert_child_is(self, cls): self.failUnless(isinstance(self.inf.get_child(), cls)) class TUtils(TestCase): def test_sort_albums(self): # Make sure we have more than one album, one having a null date f = AF({"~filename": fsnative(u"/1"), "album": "one"}) f2 = AF({"~filename": fsnative(u"/2"), "album": "one"}) f3 = AF({"~filename": fsnative(u"/3"), "album": "two", "date": "2009"}) f4 = AF({"~filename": fsnative(u"/4")}) albums, count = _sort_albums([f, f2, f3, f4]) self.failUnlessEqual(count, 1) self.failUnlessEqual(len(albums), 2) class TTitleLabel(TestCase): def test_foo(self): label = TitleLabel("foo & bar") self.failUnlessEqual(label.get_text(), "foo & bar") ��������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_lyrics.py�����������������������������������������������������������0000664�0001750�0001750�00000004153�14035600052�017316� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from senf import fsnative import quodlibet.config from quodlibet.formats import AudioFile from quodlibet.formats.mp3 import MP3File from quodlibet.library import SongLibrary from quodlibet.qltk.lyrics import LyricsPane from tests import TestCase, init_fake_app, destroy_fake_app, get_data_path from tests.helper import get_temp_copy LYRICS = "foobär...\nMore cowbell!©" def AF(*args, **kwargs): a = AudioFile(*args, **kwargs) a.sanitize() return a class TLyricsPane(TestCase): def setUp(self): quodlibet.config.init() init_fake_app() self.pane = None self.library = SongLibrary() def tearDown(self): destroy_fake_app() self.library.destroy() quodlibet.config.quit() if self.pane: self.pane.destroy() def test_construction(self): af = AF({"~filename": fsnative(u"/dev/null")}) self.pane = LyricsPane(af) def test_save_lyrics(self): af = self.temp_mp3() self.pane = LyricsPane(af) self.pane._save_lyrics(af, LYRICS) self.failUnlessEqual(af("~lyrics"), LYRICS) def test_save_encoded_lyrics(self): af = self.temp_mp3() self.pane = LyricsPane(af) self.pane._save_lyrics(af, LYRICS) self.failUnlessEqual(af("~lyrics"), LYRICS) def test_save_lyrics_deletes_lyric_file(self): af = self.temp_mp3() lf_name = af.lyric_filename os.makedirs(os.path.dirname(lf_name)) with open(lf_name, "wb") as f: f.write(LYRICS.encode("utf-8")) self.failUnless(os.path.exists(lf_name)) self.pane = LyricsPane(af) self.pane._save_lyrics(af, LYRICS) self.failIf(os.path.exists(lf_name)) def temp_mp3(self): name = get_temp_copy(get_data_path('silence-44-s.mp3')) af = MP3File(name) af.sanitize() return af ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_maskedbox.py��������������������������������������������������������0000664�0001750�0001750�00000001135�14035600052�017763� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet import config from quodlibet.qltk.maskedbox import MaskedBox from quodlibet.library import SongFileLibrary class TMaskedBox(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test(self): lib = SongFileLibrary() MaskedBox(lib).destroy() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_models.py�����������������������������������������������������������0000664�0001750�0001750�00000035155�14035600052�017302� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from gi.repository import Gtk from quodlibet.qltk.models import ObjectStore, ObjectModelFilter from quodlibet.qltk.models import ObjectModelSort, ObjectTreeStore from quodlibet.util import cmp class _TObjectStoreMixin: Store = None def test_append(self): m = self.Store() for i in range(10): m.append(row=[i]) self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_column_count(self): m = self.Store() self.failUnlessEqual(m.get_n_columns(), 1) def test_insert(self): m = self.Store() for i in reversed(range(10)): m.insert(0, row=[i]) self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_prepend(self): m = self.Store() for i in reversed(range(10)): m.prepend(row=[i]) self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_insert_before(self): m = self.Store() iter_ = m.append(row=[1]) new_iter = m.insert_before(iter_, [2]) self.failUnlessEqual(m.get_value(new_iter, 0), 2) self.failUnlessEqual([2, 1], [r[0] for r in m]) def test_insert_before_noiter(self): m = self.Store() m.append(row=[1]) m.insert_before(None, [2]) self.failUnlessEqual([r[0] for r in m], [1, 2]) def test_insert_after(self): m = self.Store() iter_ = m.append(row=[1]) new_iter = m.insert_after(iter_, [2]) self.failUnlessEqual(m.get_value(new_iter, 0), 2) self.failUnlessEqual([1, 2], [r[0] for r in m]) def test_insert_after_noiter(self): m = self.Store() m.append(row=[1]) m.insert_after(None, [2]) self.failUnlessEqual([r[0] for r in m], [2, 1]) def test_allow_nonatomic(self): m = self.Store() m.ATOMIC = False self.failUnless(m.insert(0)) self.failUnless(m.prepend()) self.failUnless(m.append()) self.failUnless(m.insert_before(None)) self.failUnless(m.insert_after(None)) class TOrigObjectStore(TestCase, _TObjectStoreMixin): Store = lambda *x: Gtk.ListStore(object) class TObjectStore(TestCase, _TObjectStoreMixin): Store = ObjectStore def test_validate(self): self.failUnlessRaises(ValueError, ObjectStore, int) ObjectStore() ObjectStore(object) self.failUnlessRaises(ValueError, ObjectStore, object, object) def test_iter_path_changed(self): m = ObjectStore() def handler(model, path, iter_, result): result[0] += 1 result = [0] m.connect("row-changed", handler, result) m.append([object()]) iter_ = m.get_iter_first() m.iter_changed(iter_) self.assertEqual(result[0], 1) m.path_changed(m.get_path(iter_)) self.assertEqual(result[0], 2) def test_append_many(self): m = ObjectStore() m.append_many(range(10)) self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_append_many_set(self): m = ObjectStore() m.append_many(set()) m.append_many(set(range(10))) self.failUnlessEqual({r[0] for r in m}, set(range(10))) def test_iter_append_many(self): m = ObjectStore() iters = list(m.iter_append_many(range(10))) self.failUnlessEqual([r[0] for r in m], list(range(10))) values = [m.get_value(i) for i in iters] self.failUnlessEqual(values, list(range(10))) def test_iter_append_many_iterable_int(self): m = ObjectStore() for x in m.iter_append_many((i for i in range(10))): pass self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_iter_append_many_iterable_object(self): objects = [object() for i in range(10)] m = ObjectStore() for x in m.iter_append_many((i for i in objects)): pass self.failUnlessEqual([r[0] for r in m], objects) def test_iter_append_many_empty(self): m = ObjectStore() for x in m.iter_append_many([]): pass for x in m.iter_append_many(iter([])): pass def test_insert_many(self): m = ObjectStore() m.append(row=[42]) m.append(row=[24]) m.insert_many(1, range(10)) self.failUnlessEqual([r[0] for r in m], [42] + list(range(10)) + [24]) def test_insert_many_append(self): m = ObjectStore() m.insert_many(-1, range(10)) self.failUnlessEqual([r[0] for r in m], list(range(10))) m = ObjectStore() m.insert_many(99, range(10)) self.failUnlessEqual([r[0] for r in m], list(range(10))) def test_itervalues(self): m = ObjectStore() m.insert_many(0, range(10)) self.failUnlessEqual(list(range(10)), list(m.itervalues())) def test_itervalues_empty(self): m = ObjectStore() self.assertEqual(list(m.itervalues()), []) def test_iterrows(self): m = ObjectStore() m.insert_many(0, range(10)) for iter_, value in m.iterrows(): self.failUnlessEqual(m.get_value(iter_), value) def test_iterrows_empty(self): m = ObjectStore() self.assertEqual(list(m.iterrows()), []) def test_is_empty(self): m = ObjectStore() self.assertTrue(m.is_empty()) iter_ = m.append(row=[1]) self.assertFalse(m.is_empty()) m.remove(iter_) self.assertTrue(m.is_empty()) def test_nonatomic(self): m = ObjectStore() self.assertRaises(AssertionError, m.append) self.assertRaises(AssertionError, m.insert, 0) self.assertRaises(AssertionError, m.prepend) self.assertRaises(AssertionError, m.insert_before, None) self.assertRaises(AssertionError, m.insert_after, None) def test_signal_count(self): m = ObjectStore() def handler(model, path, iter_, result): result[0] += 1 inserted = [0] m.connect("row-inserted", handler, inserted) changed = [0] m.connect("row-changed", handler, changed) m.append([1]) m.prepend([8]) m.insert(0, [1]) m.insert_before(None, [1]) m.insert_after(None, [1]) m.insert_many(0, [1, 2, 3]) m.append_many([1, 2, 3]) list(m.iter_append_many([1, 2, 3])) list(m.iter_append_many(range(3))) self.assertEqual(changed[0], 0) self.assertEqual(inserted[0], len(m)) def test__sort_on_value(self): m = ObjectStore() iterBob = m.append(row=["bob"]) iterAlice = m.append(row=["alice"]) m.append(row=["charlie"]) result = ObjectStore._sort_on_value(m, iterAlice, iterBob, None) self.assertEqual(result, cmp("alice", "bob")) class _TObjectTreeStoreMixin: Store = None def test_column_count(self): m = self.Store() self.failUnlessEqual(m.get_n_columns(), 1) def test_append_int(self): m = self.Store() m.append(None, row=[1]) m.append(None, row=[2]) self.failUnlessEqual([r[0] for r in m], [1, 2]) def test_append_obj(self): m = self.Store() obj = object() obj2 = object() m.append(None, row=[obj]) m.append(None, row=[obj2]) self.failUnlessEqual([r[0] for r in m], [obj, obj2]) def test_insert_after(self): m = self.Store() iter_ = m.append(None, row=[1]) new_iter = m.insert_after(None, iter_, [2]) self.failUnlessEqual(m.get_value(new_iter, 0), 2) self.failUnlessEqual([1, 2], [r[0] for r in m]) def test_insert_after_noroot(self): m = self.Store() iter_ = m.append(None, row=[1]) iter2_ = m.append(iter_, row=[2]) new_iter = m.insert_after(iter_, iter2_, [3]) self.failUnlessEqual(m.get_value(new_iter, 0), 3) self.failUnlessEqual([1], [r[0] for r in m]) self.failUnlessEqual([2, 3], list(r[0] for r in m[0].iterchildren())) def test_insert_after_noiter(self): m = self.Store() m.append(None, row=[1]) m.insert_after(None, None, [2]) self.failUnlessEqual([r[0] for r in m], [2, 1]) def test_insert_before(self): m = self.Store() iter_ = m.append(None, row=[1]) new_iter = m.insert_before(None, iter_, [2]) self.failUnlessEqual(m.get_value(new_iter, 0), 2) self.failUnlessEqual([2, 1], [r[0] for r in m]) def test_insert_before_noroot(self): m = self.Store() iter_ = m.append(None, row=[1]) iter2_ = m.append(iter_, row=[2]) new_iter = m.insert_before(iter_, iter2_, [3]) self.failUnlessEqual(m.get_value(new_iter, 0), 3) self.failUnlessEqual([1], [r[0] for r in m]) self.failUnlessEqual([3, 2], list(r[0] for r in m[0].iterchildren())) def test_insert_before_noiter(self): m = self.Store() m.append(None, row=[1]) m.insert_before(None, None, [2]) self.failUnlessEqual([r[0] for r in m], [1, 2]) def test_allow_nonatomic(self): m = self.Store() m.ATOMIC = False self.failUnless(m.insert(None, 0)) self.failUnless(m.prepend(None)) self.failUnless(m.append(None)) self.failUnless(m.insert_before(None, None)) self.failUnless(m.insert_after(None, None)) class TOrigTreeStore(TestCase, _TObjectTreeStoreMixin): Store = lambda *x: Gtk.TreeStore(object) class TObjectTreeStore(TestCase, _TObjectTreeStoreMixin): Store = ObjectTreeStore def test_validate(self): self.failUnlessRaises(ValueError, ObjectTreeStore, int) ObjectTreeStore() ObjectTreeStore(object) self.failUnlessRaises(ValueError, ObjectTreeStore, object, object) def test_iter_path_changed(self): m = ObjectTreeStore() def handler(model, path, iter_, result): result[0] += 1 result = [0] m.connect("row-changed", handler, result) m.append(None, [object()]) iter_ = m.get_iter_first() m.iter_changed(iter_) self.assertEqual(result[0], 1) m.path_changed(m.get_path(iter_)) self.assertEqual(result[0], 2) def test_itervalues(self): m = ObjectTreeStore() obj = object() obj2 = object() it = m.append(None, row=[obj]) m.append(it, row=[obj2]) self.assertEqual(list(m.itervalues(None)), [obj]) self.assertEqual(list(m.itervalues(it)), [obj2]) def test_iterrows(self): m = ObjectTreeStore() obj = object() obj2 = object() it = m.append(None, row=[obj]) m.append(it, row=[obj2]) self.assertEqual(list(m.iterrows(None))[0][1], obj) self.assertEqual(list(m.iterrows(it))[0][1], obj2) def test_nonatomic(self): m = ObjectTreeStore() self.assertRaises(AssertionError, m.append, None) self.assertRaises(AssertionError, m.insert, None, 0) self.assertRaises(AssertionError, m.prepend, None) self.assertRaises(AssertionError, m.insert_before, None, None) self.assertRaises(AssertionError, m.insert_after, None, None) def test_signal_count(self): m = ObjectTreeStore() def handler(model, path, iter_, result): result[0] += 1 inserted = [0] m.connect("row-inserted", handler, inserted) changed = [0] m.connect("row-changed", handler, changed) m.append(None, [1]) m.insert(None, 0, [1]) m.prepend(None, [1]) m.insert_before(None, None, [1]) m.insert_after(None, None, [1]) self.assertEqual(changed[0], 0) self.assertEqual(inserted[0], len(m)) def test_tree_store_insert_before_none(self): store = ObjectTreeStore() root = store.append(None, [42]) sub = store.append(root, [24]) iter_ = store.insert_before(None, None, [1]) assert store.get_path(iter_).get_indices() == [1] iter_ = store.insert_before(root, None, [1]) assert store.get_path(iter_).get_indices() == [0, 1] iter_ = store.insert_before(sub, None, [1]) assert store.get_path(iter_).get_indices() == [0, 0, 0] iter_ = store.insert_before(None, root, [1]) assert store.get_path(iter_).get_indices() == [0] iter_ = store.insert_before(None, sub, [1]) assert store.get_path(iter_).get_indices() == [1, 0] def test_tree_store_insert_after_none(self): store = ObjectTreeStore() root = store.append(None, [42]) sub = store.append(root, [24]) iter_ = store.insert_after(None, None, [1]) assert store.get_path(iter_).get_indices() == [0] iter_ = store.insert_after(root, None, [1]) assert store.get_path(iter_).get_indices() == [1, 0] iter_ = store.insert_after(sub, None, [1]) assert store.get_path(iter_).get_indices() == [1, 1, 0] iter_ = store.insert_after(None, root, [1]) assert store.get_path(iter_).get_indices() == [2] iter_ = store.insert_after(None, sub, [1]) assert store.get_path(iter_).get_indices() == [1, 2] class TObjectModelFilter(TestCase): def test_iter_values(self): m = ObjectStore() f = ObjectModelFilter(child_model=m) m.insert_many(0, range(10)) self.failUnlessEqual(list(range(10)), list(f.itervalues())) def test_filter(self): m = ObjectStore() f = ObjectModelFilter(child_model=m) m.insert_many(0, range(10)) def filter_func(model, iter_, data): if model.get_value(iter_) % 2 == 0: return True return False f.set_visible_func(filter_func) f.refilter() self.failUnlessEqual(list(range(0, 10, 2)), list(f.itervalues())) class TObjectModelSort(TestCase): def test_iter_values(self): m = ObjectStore() f = ObjectModelSort(model=m) m.insert_many(0, range(10)) self.failUnlessEqual(list(range(10)), list(f.itervalues())) def test_sort(self): m = ObjectStore() f = ObjectModelSort(model=m) m.insert_many(0, range(10)) def sort_func(model, iter_a, iter_b, data): a = model.get_value(iter_a, 0) b = model.get_value(iter_b, 0) return -cmp(a, b) f.set_default_sort_func(sort_func) self.failUnlessEqual(sorted(range(10), reverse=True), list(f.itervalues())) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_msg.py��������������������������������������������������������������0000664�0001750�0001750�00000001755�14035600052�016604� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk.msg import WarningMessage, ErrorMessage, \ CancelRevertSave, ConfirmFileReplace class TWarningMessage(TestCase): def test_ctr(self): WarningMessage(None, "title", "description").destroy() class TErrorMessage(TestCase): def test_ctr(self): ErrorMessage(None, "title", "description").destroy() class TCancelRevertSave(TestCase): def setUp(self): self.win = CancelRevertSave(None) def test_ctr(self): pass def tearDown(self): self.win.destroy() class TFileReplace(TestCase): def setUp(self): self.win = ConfirmFileReplace(None, "") def test_ctr(self): pass def tearDown(self): self.win.destroy() �������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_notif.py������������������������������������������������������������0000664�0001750�0001750�00000003111�14035600052�017121� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet import _ from quodlibet.qltk.notif import Task, TaskController class FakeStatusBar: def __init__(self): self.count = 0 def update(self): self.count += 1 class TTaskController(TestCase): def setUp(self): self.c = TaskController() self.f = FakeStatusBar() self.c.parent = self.f def test_reparent(self): def set_parent(p): self.c.parent = p set_parent(None) set_parent(FakeStatusBar()) self.assertRaises(ValueError, set_parent, FakeStatusBar()) def test_multiple_tasks(self): self.assertEquals(self.c.active_tasks, []) self.assertNotEqual(self.c.source, "") t1 = Task("src", "desc", controller=self.c) self.assertEquals(self.c.source, "src") self.assertEquals(self.c.active_tasks, [t1]) t1.update(0.5) self.assertEquals(self.c.frac, 0.5) t2 = Task("src2", "desc2", controller=self.c) self.assertEquals(self.c.source, _("Active tasks")) self.assertEquals(self.c.frac, 0.25) Task("src3", "desc3", controller=self.c, known_length=False) self.assertAlmostEqual(self.c.frac, 0.5 / 3) t1.finish() t2.finish() self.assertEquals(self.c.desc, "desc3") self.assertEquals(self.c.frac, None) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_paned.py������������������������������������������������������������0000664�0001750�0001750�00000013345�14035600052�017103� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.qltk.paned import RVPaned, RHPaned, ConfigRVPaned, \ MultiRVPaned, MultiRHPaned, ConfigMultiRVPaned, ConfigMultiRHPaned from quodlibet import config from . import TestCase from .helper import visible class TRPaned: Kind = None def test_ctr(self): self.Kind().destroy() def test_pre_alloc(self): p = self.Kind() p.set_relative(0.25) self.failUnlessEqual(p.get_relative(), 0.25) self.assertRaises(ValueError, p.set_relative, 2.0) self.assertRaises(ValueError, p.set_relative, -2.0) def test_visible_no_setup(self): p = self.Kind() with visible(p): pass def test_visible_pre_setup_children(self): p = self.Kind() p.pack1(Gtk.Button()) p.pack2(Gtk.Button()) p.set_relative(0.75) self.failUnlessAlmostEqual(p.get_relative(), 0.75) with visible(p, width=200, height=200) as p: self.failUnlessAlmostEqual(p.get_relative(), 0.75, 2) def test_visible_pre_setup_empty(self): p = self.Kind() p.set_relative(0.75) self.failUnlessEqual(p.get_relative(), 0.75) with visible(p) as p: self.failUnlessAlmostEqual(p.get_relative(), 0.75, 2) def test_min_size_child(self): p = self.Kind() p.set_size_request(200, 200) p.pack1(Gtk.Label(), True, False) b2 = Gtk.Button() b2.set_size_request(50, 50) p.pack2(b2, True, False) p.set_relative(0.5) with visible(p) as p: self.assertEqual(p.get_position(), 100) class RHPaned(TestCase, TRPaned): Kind = RHPaned class RVPaned(TestCase, TRPaned): Kind = RVPaned class TConfigRPaned(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_basic(self): self.failUnless(config.get("memory", "foobar", None) is None) p = ConfigRVPaned("memory", "foobar", 0.75) p.pack1(Gtk.Button()) p.pack2(Gtk.Button()) with visible(p, width=200, height=200) as p: self.failUnlessAlmostEqual(p.get_relative(), 0.75, 2) p.props.position = 20 self.failUnlessAlmostEqual(p.get_relative(), 0.10, 2) config_value = config.getfloat("memory", "foobar") self.failUnlessAlmostEqual(config_value, 0.10, 2) class TMultiRPaned: Kind = None def test_set_widgets(self): """Test if widgets are properly set and in the correct order.""" p = self.Kind() # 0 widgets p.set_widgets([]) paned = p.get_paned() self.assertIsNotNone(paned) self.assertIsNone(paned.get_child1()) self.assertIsNone(paned.get_child2()) # 1 widget sw = Gtk.ScrolledWindow() p.set_widgets([sw]) paned = p.get_paned() children = [paned.get_child1(), paned.get_child2()] self.assertIn(sw, children) # 2 widgets sws = [Gtk.ScrolledWindow() for _ in range(2)] p.set_widgets(sws) paned = p.get_paned() self.assertIs(sws[0], paned.get_child1()) self.assertIs(sws[1], paned.get_child2()) # 3 wigets sws = [Gtk.ScrolledWindow() for _ in range(3)] p.set_widgets(sws) root_paned = p.get_paned() self.assertIs(sws[0], root_paned.get_child1()) sub_paned = root_paned.get_child2() self.assertIs(sws[1], sub_paned.get_child1()) self.assertIs(sws[2], sub_paned.get_child2()) def test_make_pane_widths_equal(self): p = self.Kind() sws = [Gtk.ScrolledWindow() for _ in range(4)] p.set_widgets(sws) p.make_pane_widths_equal() paneds = p._get_paneds() self.failUnlessAlmostEqual(paneds[0].get_relative(), 1.0 / 4.0) self.failUnlessAlmostEqual(paneds[1].get_relative(), 1.0 / 3.0) self.failUnlessAlmostEqual(paneds[2].get_relative(), 1.0 / 2.0) def test_change_orientation(self): p = self.Kind() p.set_widgets([Gtk.ScrolledWindow()]) opposite = Gtk.Orientation.HORIZONTAL horizontal_opposite = True if p.get_paned().props.orientation is Gtk.Orientation.HORIZONTAL: opposite = Gtk.Orientation.VERTICAL horizontal_opposite = False p.change_orientation(horizontal=horizontal_opposite) for paned in p._get_paneds(): self.assertIs(paned.props.orientation, opposite) def test_destroy(self): self.Kind().destroy() class TMultiRHPaned(TestCase, TMultiRPaned): Kind = MultiRHPaned class TMultiRVPaned(TestCase, TMultiRPaned): Kind = MultiRVPaned class TConfigMultiRPaned: def setUp(self): config.init() def tearDown(self): config.quit() def test_basic(self): self.assertTrue(config.get("memory", "pane_widths", None) is None) p = self.Kind("memory", "pane_widths") sws = [Gtk.ScrolledWindow() for _ in range(3)] p.set_widgets(sws) paneds = p._get_paneds() paneds[0].set_relative(0.4) paneds[1].set_relative(0.6) p.save_widths() widths = config.getstringlist("memory", "pane_widths") self.assertAlmostEqual(float(widths[0]), 0.4) self.assertAlmostEqual(float(widths[1]), 0.6) config.remove_option("memory", "pane_widths") class TConfigMultiRHPaned(TestCase, TConfigMultiRPaned): Kind = ConfigMultiRHPaned class TConfigMultiRVPaned(TestCase, TConfigMultiRPaned): Kind = ConfigMultiRVPaned �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1665307309.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_playorder.py��������������������������������������������������������0000644�0001750�0001750�00000007313�14320511255�020014� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import quodlibet.config import quodlibet.plugins from quodlibet.qltk import Icons from quodlibet.qltk.playorder import OrderShuffle, OrderWeighted, \ ToggledPlayOrderMenu, Orders, Order, OrderInOrder from quodlibet.qltk.playorder import PlayOrderWidget from tests import TestCase class TPlayOrderWidget(TestCase): def setUp(self): quodlibet.config.init() self.order = None self.volume = 0 self.replaygain_profiles = [None, None, None] self.reset_replaygain = lambda: None self.po = PlayOrderWidget(self, self) def tearDown(self): self.po.destroy() # quodlibet.plugins.quit() quodlibet.config.quit() def test_initial(self): self.failIf(self.po.repeated) self.failIf(self.po.shuffled) self.failUnless(isinstance(self.po.order, OrderInOrder)) self.failUnless(self.replaygain_profiles[2], ["album", "track"]) def test_replay_gain(self): self.po.shuffled = True self.po.shuffler = OrderWeighted self.failUnlessEqual(self.replaygain_profiles[2], ["track"]) self.po.shuffled = False self.failUnlessEqual(self.replaygain_profiles[2], ["album", "track"]) def test_get_name(self): orders = [OrderShuffle, OrderWeighted] for order in orders: self.po.shuffler = order self.failUnlessEqual(self.po.shuffler, order) def test_shuffle(self): self.failIf(self.po.repeated) self.po.shuffled = True self.assertTrue(self.po.shuffled) self.assertEqual(self.po.shuffler, OrderShuffle) self.failUnless(isinstance(self.order, OrderShuffle)) def test_shuffle_defaults_to_inorder(self): self.po.shuffler = OrderWeighted self.po.shuffled = False self.failUnlessEqual(type(self.po.order), OrderInOrder) self.po.shuffled = True self.assertEqual(self.po.shuffler, OrderWeighted) self.failUnlessEqual(type(self.po.order), OrderWeighted) class FakeOrder(Order): name = "fake" class TToggledPlayOrderMenu(TestCase): def setUp(self): self.orders = Orders([OrderShuffle, OrderWeighted, FakeOrder]) self.tpom = ToggledPlayOrderMenu(Icons.AUDIO_X_GENERIC, orders=self.orders, current_order=OrderShuffle, enabled=True) def tearDown(self): self.tpom.destroy() def test_enabled_initially(self): self.failUnless(self.tpom.enabled) def test_setting_enabled(self): self.tpom.enabled = False self.failIf(self.tpom.enabled) self.tpom.enabled = True self.failUnless(self.tpom.enabled) def test_initial(self): self.failUnlessEqual(self.tpom.current, OrderShuffle) def test_unknown_name(self): self.assertRaises(ValueError, self.tpom.set_active_by_name, "foobar") def test_set_by_name(self): self.tpom.set_active_by_name("fake") self.failUnlessEqual(self.tpom.current.name, "fake") def test_get_name(self): for order in self.orders: self.tpom.current = order self.failUnlessEqual(self.tpom.current, order) def test_set_orders(self): self.tpom.set_orders([]) self.failIf(self.tpom.current) def test_playorder_disables_when_order_disappears(self): self.tpom.orders = Orders([OrderWeighted, FakeOrder]) self.failIf(self.tpom.enabled) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618773137.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_pluginwin.py��������������������������������������������������������0000664�0001750�0001750�00000004574�14037102221�020031� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from tests.helper import realized from quodlibet import plugins from quodlibet import config from quodlibet.plugins import Plugin from quodlibet.qltk.models import ObjectStore from quodlibet.qltk.pluginwin import PluginWindow, PluginErrorWindow, \ PluginListView, PluginEnabledFilterCombo, PluginPreferencesContainer, \ EnabledType, PluginTypeFilterCombo class FakePlugin: PLUGIN_ID = "fo<o" PLUGIN_NAME = "b>ar" PLUGIN_DESC = "quux" @classmethod def PluginPreferences(cls, parent): return PluginEnabledFilterCombo() class FakePlugin2(FakePlugin): @classmethod def PluginPreferences(cls, parent): return PluginWindow() PLUGIN = Plugin(FakePlugin) PLUGIN2 = Plugin(FakePlugin2) class TPluginWindow(TestCase): def setUp(self): plugins.init() config.init() def test_plugin_win(self): win = PluginWindow() win.destroy() def test_plugin_error_window(self): win = PluginErrorWindow(None, {"foo": ["bar", "quux"]}) win.destroy() def test_plugin_list(self): model = ObjectStore() model.append([PLUGIN]) plist = PluginListView() plist.set_model(model) with realized(plist): plist.select_by_plugin_id("foobar") plist.destroy() def test_enabled_filter_combo(self): combo = PluginEnabledFilterCombo() combo.refill(["a", "b", "c"], True) self.assertEqual(combo.get_active_row()[1], EnabledType.ALL) combo.destroy() def test_type_filter_combo(self): combo = PluginTypeFilterCombo() # The ALL item should be first. assert combo.get_active_type() == object # Check we have a few types (including separator) combo.set_active(5) assert combo.get_active_type() combo.destroy() def test_plugin_prefs(self): cont = PluginPreferencesContainer() cont.set_no_plugins() cont.set_plugin(PLUGIN) cont.set_plugin(None) cont.set_plugin(PLUGIN) cont.set_plugin(PLUGIN2) def tearDown(self): plugins.quit() config.quit() ������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_prefs.py������������������������������������������������������������0000664�0001750�0001750�00000001467�14035600052�017135� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, init_fake_app, destroy_fake_app from quodlibet.qltk.prefs import PreferencesWindow from quodlibet.qltk.songlist import set_columns from quodlibet import config class TPreferencesWindow(TestCase): def setUp(self): config.init() init_fake_app() # Avoid warnings when running with empty config set_columns(["artist", "title"]) self.win = PreferencesWindow(None) def test_ctr(self): pass def tearDown(self): destroy_fake_app() self.win.destroy() config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_properties.py�������������������������������������������������������0000664�0001750�0001750�00000003465�14231604332�020215� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, run_gtk_loop from senf import fsnative from quodlibet.formats import AudioFile from quodlibet.qltk.properties import SongProperties from quodlibet.library import SongLibrary from quodlibet import config class DummyPlugins: def rescan(self): pass def find_subclasses(self, *args): return [] def TagsFromPathPlugins(self): return [] def RenamePlugins(self): return [] def EditTagsPlugins(self): return [] class TSongProperties(TestCase): af1 = AudioFile({"title": "woo"}) af1.sanitize(fsnative(u"invalid")) af2 = AudioFile({"title": "bar", "album": "quux"}) af2.sanitize(fsnative(u"alsoinvalid")) def setUp(self): SongProperties.plugins = DummyPlugins() config.init() self.library = SongLibrary() def test_onesong(self): self.window = SongProperties(self.library, [self.af1]) def test_twosong(self): self.window = SongProperties(self.library, [self.af2, self.af1]) def test_changed(self): self.test_twosong() self.window.hide() self.library.emit('changed', [self.af2]) run_gtk_loop() def test_removed(self): self.test_twosong() self.window.hide() self.library.emit('removed', [self.af2]) run_gtk_loop() def tearDown(self): try: self.window.destroy() except AttributeError: pass else: del(self.window) self.library.destroy() del(SongProperties.plugins) config.quit() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_queue.py������������������������������������������������������������0000664�0001750�0001750�00000005732�14231604332�017144� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from time import sleep from typing import List from quodlibet.order.reorder import OrderShuffle from senf import bytes2fsn from tests import TestCase, run_gtk_loop from quodlibet.player.nullbe import NullPlayer from quodlibet.formats import DUMMY_SONG from quodlibet.qltk.queue import QueueExpander, PlaybackStatusIcon, \ PlayQueue, QUEUE from quodlibet.library import SongLibrary import quodlibet.config class TPlayQueue(TestCase): def setUp(self): self.player = NullPlayer() self.lib = SongLibrary() self.lib.librarian = None self.lib.add([DUMMY_SONG]) try: os.unlink(QUEUE) except OSError: pass def test_save_restore(self): q = PlayQueue(self.lib, self.player) q.get_model().append(row=[DUMMY_SONG]) q.destroy() q = PlayQueue(self.lib, self.player) model = q.get_model() assert model.values()[0] is DUMMY_SONG def test_autosave(self): q = PlayQueue(self.lib, self.player, autosave_interval_secs=1) assert q._tid q.get_model().append(row=[DUMMY_SONG]) sleep(1.1) run_gtk_loop() assert self.get_queue() == [DUMMY_SONG("~filename")] q.destroy() # Doesn't prove much but still assert not q._tid def get_queue(self) -> List[str]: try: with open(QUEUE, "rb") as f: return [bytes2fsn(line.strip(), "utf-8") for line in f.readlines()] except FileNotFoundError: return [] def test_autosave_batched(self): q = PlayQueue(self.lib, self.player, autosave_interval_secs=None) model = q.get_model() model.append(row=[DUMMY_SONG]) run_gtk_loop() assert not self.get_queue() for i in range(PlayQueue._MAX_PENDING + 1): model.append(row=[DUMMY_SONG]) run_gtk_loop() assert len(self.get_queue()) == PlayQueue._MAX_PENDING + 1 class TQueueExpander(TestCase): def setUp(self): quodlibet.config.init() player = NullPlayer() self.queue = QueueExpander(SongLibrary(), player) def test_ctr(self): pass def test_status_icon(self): widget = PlaybackStatusIcon() widget.play() widget.stop() widget.pause() widget.pause() def test_random_at_startup(self): self.failIf(isinstance(self.queue.model.order, OrderShuffle)) quodlibet.config.set("memory", "shufflequeue", True) self.queue = self.queue = QueueExpander(SongLibrary(), NullPlayer()) # See issue #2411 self.failUnless(isinstance(self.queue.model.order, OrderShuffle)) def tearDown(self): self.queue.destroy() quodlibet.config.quit() ��������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_quodlibetwindow.py��������������������������������������������������0000664�0001750�0001750�00000002637�14231604332�021241� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from quodlibet.library import SongFileLibrary, SongLibrarian from quodlibet.qltk.notif import TaskController from tests import TestCase, init_fake_app from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlaybackErrorDialog from quodlibet import player from quodlibet import config class TQuodLibetWindow(TestCase): def setUp(self): init_fake_app() # Ugh TaskController.default_instance = TaskController() config.init() def tearDown(self): # Avoid leaking to other tests if SongFileLibrary.librarian: SongFileLibrary.librarian.destroy() SongFileLibrary.librarian = None QuodLibetWindow.windows.clear() config.quit() def test_window(self): lib = SongFileLibrary() lib.librarian = SongLibrarian() pl = player.init_player("nullbe", lib.librarian) window = QuodLibetWindow(lib, pl, headless=True) assert window in window.windows window.destroy() def test_playback_error_dialog(self): error = player.PlayerError(u'\xf6\xe4\xfc', u'\xf6\xe4\xfc') PlaybackErrorDialog(None, error) �������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_ratingsmenu.py������������������������������������������������������0000664�0001750�0001750�00000004201�14035600052�020337� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012,2013 Christoph Reiter # 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from senf import fsnative from tests import TestCase from quodlibet import config from quodlibet.qltk.ratingsmenu import RatingsMenuItem from quodlibet.library import SongLibrary, SongLibrarian from quodlibet.formats import AudioFile NUM_RATINGS = 4 class TRatingsMenuItem(TestCase): def setUp(self): config.RATINGS = config.HardCodedRatingsPrefs() self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS) self.library = SongLibrary() self.library.librarian = SongLibrarian() self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0}) self.af.sanitize() self.rmi = RatingsMenuItem([self.af], self.library) def tearDown(self): self.rmi.destroy() self.library.destroy() self.library.librarian.destroy() def test_menuitem_children(self): children = [mi for mi in self.rmi.get_submenu().get_children() if isinstance(mi, Gtk.CheckMenuItem)] self.failUnlessEqual(len(children), NUM_RATINGS + 1) highest = children[-1] self.failUnlessEqual(highest.get_active(), True) self.failUnlessEqual(children[1].get_active(), False) def test_no_rating(self): af = AudioFile({"~filename": fsnative(u"/foobar"), 'artist': 'foo'}) rmi = RatingsMenuItem([af], self.library) children = [mi for mi in rmi.get_submenu().get_children() if isinstance(mi, Gtk.CheckMenuItem)] self.failIf(any([c.get_active() for c in children])) def test_set_remove_rating(self): self.rmi.set_rating(0.5, [self.af], self.library) self.failUnless(self.af.has_rating) self.failUnlessEqual(self.af('~#rating'), 0.5) self.rmi.remove_rating([self.af], self.library) self.failIf(self.af.has_rating) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_renamefiles.py������������������������������������������������������0000664�0001750�0001750�00000030531�14231604332�020305� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import glob from typing import Text from gi.repository import Gtk, GObject from tests import TestCase, mkdtemp from senf import fsnative from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.qltk.renamefiles import (StripDiacriticals, StripNonASCII, Lowercase, SpacesToUnderscores, StripWindowsIncompat, RenameFiles, ReplaceColons) class TFilter(TestCase): def setUp(self): self.c = self.Kind() def tearDown(self): self.c.destroy() class TFilterMixin: def test_mix_empty(self): empty = fsnative(u"") v = self.c.filter(empty, u"") self.failUnlessEqual(v, u"") self.failUnless(isinstance(v, str)) def test_mix_safe(self): empty = fsnative(u"") safe = u"safe" self.failUnlessEqual(self.c.filter(empty, safe), safe) class TSpacesToUnderscores(TFilter, TFilterMixin): Kind = SpacesToUnderscores def test_conv(self): self.failUnlessEqual(self.c.filter("", "foo bar "), "foo_bar_") class TStripWindowsIncompat(TFilter, TFilterMixin): Kind = StripWindowsIncompat def test_conv(self): if os.name == "nt": self.failUnlessEqual( self.c.filter(u"", u'foo\\:*?;"<>|/'), u"foo\\_________") else: self.failUnlessEqual( self.c.filter("", 'foo\\:*?;"<>|/'), "foo_________/") def test_type(self): empty = fsnative(u"") self.assertTrue(isinstance(self.c.filter(empty, empty), fsnative)) def test_ends_with_dots_or_spaces(self): empty = fsnative(u"") v = self.c.filter(empty, fsnative(u'foo. . ')) self.failUnlessEqual(v, fsnative(u"foo. ._")) self.assertTrue(isinstance(v, fsnative)) if os.name == "nt": self.failUnlessEqual( self.c.filter(empty, u'foo. \\bar .'), u"foo._\\bar _") else: self.failUnlessEqual( self.c.filter(empty, u'foo. /bar .'), "foo._/bar _") class TReplaceColons(TFilter, TFilterMixin): Kind = ReplaceColons def test_leaves_colons_without_space(self): assert self.unaffected("Nu:Tone & others - mix.flac") assert self.unaffected("Elastica - 2:1.mp3") def test_replaces_colons_as_delimiters(self): assert self.conv("ii: allegro") == "ii - allegro" def test_replaces_semicolons_as_delimiters(self): assert (self.conv("Mozart; Requiem in D minor") == "Mozart - Requiem in D minor") def test_replaces_colons_with_lots_of_spaces(self): assert (self.conv("Cello Suite No 1 : Prelude") == self.conv("Cello Suite No 1 - Prelude")) def test_replaces_colons_with_non_word(self): assert (self.conv('No. 1 "Minute": Molto vivace') == self.conv('No. 1 "Minute" - Molto vivace')) def test_type(self): empty = fsnative(u"") self.assertTrue(isinstance(self.c.filter(empty, empty), fsnative)) def conv(self, s: Text): return self.c.filter(fsnative(""), s) def unaffected(self, s: Text) -> bool: return self.conv(s) == s class TStripDiacriticals(TFilter, TFilterMixin): Kind = StripDiacriticals def test_conv(self): empty = fsnative(u"") test = u"\u00c1 test" out = u"A test" v = self.c.filter(empty, test) self.failUnlessEqual(v, out) self.failUnless(isinstance(v, str)) class TStripNonASCII(TFilter, TFilterMixin): Kind = StripNonASCII def test_conv(self): empty = fsnative(u"") in_ = u"foo \u00c1 \u1234" out = u"foo _ _" v = self.c.filter(empty, in_) self.failUnlessEqual(v, out) self.failUnless(isinstance(v, str)) class TLowercase(TFilter, TFilterMixin): Kind = Lowercase def test_conv(self): empty = fsnative(u"") v = self.c.filter(empty, fsnative(u"foobar baz")) self.failUnlessEqual(v, fsnative(u"foobar baz")) self.failUnless(isinstance(v, fsnative)) v = self.c.filter(empty, fsnative(u"Foobar.BAZ")) self.failUnlessEqual(v, fsnative(u"foobar.baz")) self.failUnless(isinstance(v, fsnative)) class Renamer(Gtk.EventBox): __gsignals__ = { 'changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self, *args, **kwargs): super().__init__() from quodlibet.library import SongLibrary self.library = SongLibrary() box = Gtk.EventBox() self.renamer = RenameFiles(self.library, box) box.add(self.renamer) self.renamer.test_mode = True def add_songs(self, songs): self.library.add(songs) def rename(self, pattern, songs): self.renamer.combo.get_child().set_text(pattern) self.renamer._preview(songs) self.renamer._rename(self.library) class Song(AudioFile): """A mock AudioFile belong to one of three albums, based on a single number""" def __init__(self, target, num): super().__init__() self["title"] = "title_%d" % (num + 1) self["artist"] = "artist" self["album"] = "album" self["labelid"] = self["album"] self["~filename"] = \ fsnative(os.path.join(target, self["title"] + ".mp3")) class TMoveArt(TestCase): Kind = Renamer def setUp(self): self.renamer = self.Kind() def tearDown(self): self.renamer.destroy() def reset_environment(self): config.init() self.root_path = mkdtemp() self.filenames = \ ['cover.jpg', 'info.jpg', 'title.jpg', 'title2.jpg'] def generate_songs(self, path, quantity): return [Song(path, num) for num in range(quantity)] def generate_files(self, path, filenames): pathfiles = [] for f in filenames: pathfile = os.path.join(path, f) if not os.path.isdir(os.path.dirname(pathfile)): os.makedirs(os.path.dirname(pathfile)) with open(pathfile, "w") as fh: fh.write(f) pathfiles.append(pathfile) return pathfiles def art_set(self, path): return self.generate_files(path, self.filenames) def song_set(self, path): songs = self.generate_songs(path, 1) files = self.generate_files(path, [os.path.basename(song['~filename']) for song in songs]) return files, songs def source_target(self, root_path, album, artist): return (os.path.join(root_path, album, artist), os.path.join(root_path + "_2", album, artist)) def moveart_set(self, artist='artist', album='album', source=None, target=None, file_pattern="<title>"): source2, target2 = \ self.source_target(self.root_path, artist, album) if not source: source = source2 if not target: target = target2 self.art_set(source) song_files, songs = self.song_set(source) self.renamer.add_songs(songs) pattern = os.path.join(target, file_pattern) self.renamer.rename(pattern, songs) return (source, target) def test_no_move(self): self.reset_environment() # move art not set, no art files should move count_expected = 0 source, target = self.moveart_set() target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_move_defaults(self): self.reset_environment() config.set("rename", "move_art", True) # single match for default search_filenames # "cover.jpg,folder.jpg,.folder.jpg" count_expected = 1 source, target = self.moveart_set() target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_move_all_wildcard(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "*.jpg") # wildcard added to search_filenames for catchall" count_expected = 4 source, target = self.moveart_set() target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_move_escape_glob_characters(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "*.jpg") self.filenames = ['artist_[x].jpg'] # test whether we cope with non-escaped special glob characters" count_expected = 1 source, target = self.moveart_set() target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_relative_pattern(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "*.jpg") # should be a no-op" count_expected = 4 source, target = self.moveart_set(target='') target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_selective_pattern(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "<artist>.jpg") self.filenames = ['cover.jpg', 'artist.jpg'] # should be a no-op count_expected = 1 source, target = self.moveart_set(target='') target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_overwrite(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "*.jpg") self.filenames = ['art.jpg'] # move set source, target = self.moveart_set() # fail as target audio already exists self.assertRaises(Exception, self.moveart_set()) # remove audio os.remove(os.path.join(target, 'title_1.mp3')) # move exising target art to .orig suffix count_expected = 2 self.moveart_set() target_files = glob.glob(os.path.join(target, '*jpg*')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) # remove audio os.remove(os.path.join(target, 'title_1.mp3')) os.remove(os.path.join(target, 'art.jpg.orig')) config.set("rename", "move_art_overwrite", True) # overwrite existing target arg count_expected = 1 self.moveart_set() target_files = glob.glob(os.path.join(target, '*jpg*')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) def test_multi_source(self): self.reset_environment() config.set("rename", "move_art", True) config.set("albumart", "search_filenames", "*.jpg") source, target = \ self.source_target(self.root_path, 'artist', 'album') source2, target2 = \ self.source_target(self.root_path, 'artist', 'album2') self.filenames = ['art.jpg'] self.art_set(source) self.filenames = ['art2.jpg'] self.art_set(source2) song_files, songs = self.song_set(source) song_files2, songs2 = self.song_set(source2) self.renamer.add_songs(songs + songs2) # avoid audio file clashes pattern = os.path.join(target, '[<album>] artist - <title>') self.renamer.rename(pattern, songs + songs2) # album art sets merged count_expected = 2 self.moveart_set() target_files = glob.glob(os.path.join(target, '*.jpg')) count_target = len(target_files) self.failUnlessEqual(count_target, count_expected) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_scanbox.py����������������������������������������������������������0000664�0001750�0001750�00000000616�14035600052�017446� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.qltk.scanbox import ScanBox from . import TestCase class TScanBox(TestCase): def test_main(self): ScanBox().destroy() ������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_searchbar.py��������������������������������������������������������0000664�0001750�0001750�00000002047�14035600052�017743� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.qltk.searchbar import SearchBarBox from quodlibet.query import Query from . import TestCase class TSearchBarBox(TestCase): def test_get_query(self): sbb = SearchBarBox() self.failIf(sbb.get_query(None)) a_star = ["artist", "date", "custom"] sbb.set_text("foobar") expected = Query("foobar", star=a_star) self.failUnlessEqual(sbb.get_query(a_star), expected) def test_get_query_override_star(self): sbb = SearchBarBox(star=["initial"]) text = "foobar" sbb.set_text(text) self.failUnlessEqual(sbb.get_query(), Query(text, star=["initial"])) another_star = ["another", "star"] self.failUnlessEqual(sbb.get_query(star=another_star), Query(text, star=another_star)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_seekbutton.py�������������������������������������������������������0000664�0001750�0001750�00000002310�14035600052�020165� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from tests import TestCase from quodlibet.qltk.seekbutton import HSlider, SeekButton, TimeLabel from quodlibet.library import SongLibrary from quodlibet.player.nullbe import NullPlayer class TSlider(TestCase): def test_basics(self): s = HSlider() s.set_slider_disabled(True) s.set_slider_disabled(False) s.set_slider_length(100) s.set_slider_widget(Gtk.Button()) s.destroy() class TTimeLabel(TestCase): def test_time_label(self): l = TimeLabel() l.set_time(42) time_text = l.get_text() l.set_disabled(True) disabled_text = l.get_text() self.assertNotEqual(time_text, disabled_text) l.set_disabled(False) self.assertEqual(l.get_text(), time_text) class TSeekButton(TestCase): def test_seekbutton(self): w = SeekButton(NullPlayer(), SongLibrary()) w.destroy() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692646566.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_songlist.py���������������������������������������������������������0000644�0001750�0001750�00000025203�14470736246�017672� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from typing import List, Set from gi.repository import Gtk from quodlibet import config from quodlibet.browsers.tracks import TrackList from quodlibet.formats import AudioFile from quodlibet.library import SongFileLibrary, SongLibrarian from quodlibet.qltk.songlist import (SongList, set_columns, get_columns, header_tag_split, get_sort_tag) from quodlibet.qltk.songlistcolumns import SongListColumn from senf import fsnative from tests import TestCase, run_gtk_loop class TSongList(TestCase): HEADERS = ["acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track"] def setUp(self): config.init() self.lib = SongFileLibrary() self.songlist = SongList(self.lib) assert not self.lib.librarian, "not expecting a librarian - leaky test?" self.orders_changed = 0 self.songs_removed: List[Set] = [] def orders_changed_cb(*args): self.orders_changed += 1 def orders_removed_cb(songlist, removed): self.songs_removed.append(removed) self.__sigs = [ self.songlist.connect("orders-changed", orders_changed_cb), self.songlist.connect("songs-removed", orders_removed_cb) ] def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_orders([(key, order)]) self.failUnlessEqual( self.songlist.get_sort_orders(), [(key, order)]) self.songlist.toggle_column_sort(self.songlist.get_columns()[-1]) self.failUnlessEqual( self.songlist.get_sort_orders(), [("three", True)]) def test_sort_orders(self): s = self.songlist s.set_column_headers(["foo", "quux", "bar"]) values = [("foo", True), ("bar", False)] s.set_sort_orders(values) self.assertEqual(s.get_sort_orders(), values) s.toggle_column_sort(s.get_columns()[1], replace=False) self.assertEqual(s.get_sort_orders(), values + [("quux", False)]) s.toggle_column_sort(s.get_columns()[1], replace=True) self.assertEqual(s.get_sort_orders(), [("quux", False)]) def test_toggle_sort(self): s = self.songlist s.set_column_headers(["foo"]) self.assertEqual(self.orders_changed, 1) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 2) self.assertEqual(s.get_sort_orders(), [("foo", False)]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 3) self.assertEqual(s.get_sort_orders(), [("foo", True)]) def test_clear_sort(self): s = self.songlist s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertTrue(s.get_sort_orders()) s.clear_sort() self.assertFalse(s.get_sort_orders()) def test_not_sortable(self): config.set("song_list", "always_allow_sorting", False) s = self.songlist s.sortable = False s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) assert self.orders_changed == 0 assert not s.get_sort_orders() def test_sortable_if_config_overrides(self): config.set("song_list", "always_allow_sorting", True) s = self.songlist s.sortable = False assert s.sortable s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) assert s.get_sort_orders() def test_find_default_sort_column(self): s = self.songlist self.assertTrue(s.find_default_sort_column() is None) s.set_column_headers(["~#track"]) self.assertTrue(s.find_default_sort_column()) def test_inline_search_state(self): self.assertEqual(self.songlist.get_search_column(), 0) self.assertTrue(self.songlist.get_enable_search()) def test_set_songs(self): self.songlist.set_songs([], sorted=True) self.songlist.set_songs([], sorted=False) self.songlist.set_songs([], scroll_select=True) self.songlist.set_songs([], scroll_select=False) self.songlist.set_songs([], scroll=True) self.songlist.set_songs([], scroll=False) def test_set_songs_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), [song]) song2 = AudioFile({"~filename": "/dev/null"}) self.songlist.set_songs([song2], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_set_songs_no_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) model = self.songlist.get_model() model.go_to(song) self.assertIs(model.current, song) # only restore if there was a selected one self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_get_selected_songs(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.assertEqual(self.songlist.get_selected_songs(), [song]) self.assertEqual(self.songlist.get_first_selected_song(), song) sel.unselect_all() self.assertEqual(self.songlist.get_selected_songs(), []) self.assertIs(self.songlist.get_first_selected_song(), None) def test_add_songs(self): song = AudioFile({"~filename": "/dev/null"}) # unsorted self.songlist.add_songs([song]) self.songlist.add_songs([song]) # sorted self.songlist.set_column_headers(["foo"]) self.songlist.toggle_column_sort(self.songlist.get_columns()[0]) self.songlist.add_songs([]) self.songlist.add_songs([song]) self.songlist.add_songs([song]) self.assertEqual(self.songlist.get_songs(), [song] * 4) def test_remove_songs(self): song = AudioFile({"~filename": "/dev/null"}) song.sanitize() self.lib.add([song]) assert song in self.lib, "Broken library?" self.songlist.add_songs([song]) assert set(self.songlist.get_songs()) == {song} self.lib.remove([song]) assert not list(self.lib), "Didn't get removed" run_gtk_loop() assert self.songs_removed == [{song}], f"Signal not emitted: {self.__sigs}" def test_header_menu(self): song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() self.songlist.set_songs([song]) library = self.lib librarian = SongLibrarian() librarian.register(self.lib, "test") self.lib.librarian = librarian browser = TrackList(library) self.songlist.set_column_headers(["foo"]) self.assertFalse(self.songlist.Menu("foo", browser, library)) sel = self.songlist.get_selection() sel.select_all() self.assertTrue(self.songlist.Menu("foo", browser, library)) librarian.destroy() self.lib.librarian = None def test_get_columns_migrated(self): self.failIf(config.get("settings", "headers", None)) columns = "~album,~#replaygain_track_gain,foobar" config.set("settings", "columns", columns) self.failUnlessEqual(get_columns(), ["~album", "~#replaygain_track_gain", "foobar"]) self.failIf(config.get("settings", "headers", None)) def test_get_set_columns(self): self.failIf(config.get("settings", "headers", None)) self.failIf(config.get("settings", "columns", None)) columns = ["first", "won't", "two words", "4"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) columns += ["~~another~one"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) self.failIf(config.get("settings", "headers", None)) def test_header_tag_split(self): self.assertEqual(header_tag_split("foo"), ["foo"]) self.assertEqual(header_tag_split("~foo~bar"), ["foo", "bar"]) self.assertEqual(header_tag_split("<foo>"), ["foo"]) self.assertEqual(header_tag_split("<~foo~bar>"), ["foo", "bar"]) self.assertEqual(header_tag_split("pattern <~foo~bar>"), ["foo", "bar"]) def test_get_sort_tag(self): self.assertEqual(get_sort_tag("~#track"), "") self.assertEqual(get_sort_tag("artist"), "artistsort") self.assertEqual(get_sort_tag("date"), "date") self.assertEqual(get_sort_tag("~artist~date"), "~artistsort~date") self.assertEqual(get_sort_tag("~date~artist"), "~date~artistsort") self.assertEqual(get_sort_tag("composer"), "composersort") self.assertEqual(get_sort_tag("originalartist"), "originalartistsort") def test_check_sensible_menu_items(self): col = SongListColumn("title") menu = self.songlist._menu(col) submenus = [item.get_submenu() for item in menu.get_children()] names = {item.get_label() for child in submenus if child and not isinstance(child, Gtk.SeparatorMenuItem) for item in child.get_children()} assert {"Title", "Genre", "Comment", "Artist"} < names def tearDown(self): for sig in self.__sigs: self.songlist.disconnect(sig) self.songlist.destroy() self.lib.destroy() config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1667140131.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_songlistcolumns.py��������������������������������������������������0000644�0001750�0001750�00000010174�14327505043�021262� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase from .helper import visible from gi.repository import Gtk from quodlibet.qltk.songlistcolumns import create_songlist_column from quodlibet.qltk.songmodel import PlaylistModel from quodlibet.formats import AudioFile import quodlibet.config import datetime import time A_DATETIME = datetime.datetime(year=1999, month=5, day=1, hour=23, minute=11, second=59) class TSongListColumns(TestCase): def setUp(self): quodlibet.config.init() self.model = object() def tearDown(self): quodlibet.config.quit() def _create_col(self, t): return create_songlist_column(self.model, t) def _render_column(self, column, **kwargs): view = Gtk.TreeView() model = PlaylistModel() view.set_model(model) song = AudioFile({"~filename": os.devnull, "~#rating": 0.6666}) song.update(kwargs) model.append(row=[song]) view.append_column(column) if column.get_resizable(): column.set_expand(True) with visible(view): view.columns_autosize() text = column.get_cells()[0].get_property("text") self.assertIsNot(text, None) return text def test_date(self): column = self._create_col("~#added") self._render_column(column) # column reuse triggers warning somwhow column = self._create_col("~#added") self._render_column(column, **{"~#added": 100}) def test_length(self): column = self._create_col("~length") self._render_column(column) def test_filesize(self): column = self._create_col("~#filesize") self._render_column(column) def test_rating(self): column = self._create_col("~rating") text = self._render_column(column) self.assertNotEqual(text, "0.67") column = self._create_col("~#rating") text = self._render_column(column) self.assertEqual(text, "0.67") def test_bitrate(self): column = self._create_col("~#bitrate") self._render_column(column) def test_basename(self): column = self._create_col("~basename") self._render_column(column) def test_pattern(self): column = self._create_col("<artist>-<album>") self._render_column(column) def test_artist(self): column = self._create_col("artist") self._render_column(column) def test_people(self): column = self._create_col("~people") self._render_column(column) def test_bpm(self): column = self._create_col("bpm") text = self._render_column(column, **{"bpm": "123"}) self.assertEqual(text, "123") def test_initialkey(self): column = self._create_col("initialkey") text = self._render_column(column, **{"initialkey": "F"}) self.assertEqual(text, "F") def test_custom_datecol_format(self): format = "%Y%m%d %H:%M:%S PLAINTEXT" quodlibet.config.settext("settings", "datecolumn_timestamp_format", format) stamp = int(time.mktime(A_DATETIME.timetuple())) column = self._create_col("~#added") text = self._render_column(column, **{"~#added": stamp}) self.assertEqual(text, "19990501 23:11:59 PLAINTEXT") def test_nonconfigured_datecol_format(self): # make sure config option is unset by default text = quodlibet.config.gettext("settings", "datecolumn_timestamp_format") self.assertEqual(text, "") # make sure unset config option does not result in the # behaviour for testcase for set option above stamp = int(time.mktime(A_DATETIME.timetuple())) column = self._create_col("~#added") text = self._render_column(column, **{"~#added": stamp}) self.assertNotEqual(text, "19990501 23:11:59 PLAINTEXT") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1675520037.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_songmodel.py��������������������������������������������������������0000644�0001750�0001750�00000041537�14367464045�020027� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from random import Random from quodlibet.qltk.queue import QueueModel from tests import TestCase from gi.repository import Gtk from quodlibet.player.nullbe import NullPlayer from quodlibet.qltk.songmodel import PlaylistModel, PlaylistMux from quodlibet.qltk.playorder import Order, OrderShuffle, OrderInOrder, \ RepeatSongForever, RepeatListForever import quodlibet.config def do_events(): while Gtk.events_pending(): Gtk.main_iteration() class TPlaylistModel(TestCase): def setUp(self): self.pl = PlaylistModel() self.pl.set(range(10)) do_events() self.failUnless(self.pl.current is None) def test_current_recover(self): self.pl.set(range(10)) self.pl.next() self.failUnlessEqual(self.pl.current, 0) self.pl.set(range(20, 30)) self.failUnless(self.pl.current is None) self.pl.current_iter = self.pl.current_iter self.failUnless(self.pl.current is None) self.pl.set(range(10)) self.failUnlessEqual(self.pl.current, 0) def test_current_recover_unknown(self): self.pl.set([1, 2, 3, 4]) self.assertIs(self.pl.go_to(5), None) self.pl.set([1, 2, 3, 4, 5]) self.assertEqual(self.pl.current, 5) self.assertIsNot(self.pl.go_to(4), None) self.assertEqual(self.pl.current, 4) def test_isempty(self): self.failIf(self.pl.is_empty()) self.pl.clear() self.failUnless(self.pl.is_empty()) def test_get(self): self.assertEqual(self.pl.get(), list(range(10))) self.pl.set(range(12)) Gtk.main_iteration_do(False) self.assertEqual(self.pl.get(), list(range(12))) def test_next(self): self.pl.next() self.failUnlessEqual(self.pl.current, 0) self.pl.next() self.failUnlessEqual(self.pl.current, 1) self.pl.go_to(9) self.failUnlessEqual(self.pl.current, 9) self.pl.next() self.failUnless(self.pl.current is None) def test_find(self): self.failUnlessEqual(self.pl[self.pl.find(8)][0], 8) def test_find_not_there(self): self.failUnless(self.pl.find(22) is None) def test_find_all(self): to_find = [1, 4, 5, 8, 9] iters = self.pl.find_all(to_find) for i, v in zip(iters, to_find): self.failUnlessEqual(self.pl[i][0], v) def test_find_all_duplicates(self): # ignore duplicates in parameters self.assertTrue(len(self.pl.find_all([1, 1])), 1) # but find duplicates self.pl.set([1, 1]) self.assertTrue(len(self.pl.find_all([1])), 2) def test_find_all_some_missing(self): to_find = [1, 4, 18, 5, 8, 9, -1] iters = self.pl.find_all(to_find) to_find.remove(18) to_find.remove(-1) for i, v in zip(iters, to_find): self.failUnlessEqual(self.pl[i][0], v) def test_find_all_empty(self): to_find = [100, 200, -11] iters = self.pl.find_all(to_find) self.failUnlessEqual(iters, []) def test_contains(self): self.failUnless(1 in self.pl) self.failUnless(8 in self.pl) self.failIf(22 in self.pl) def test_removal(self): self.pl.go_to(8) for i in range(3, 8): self.pl.remove(self.pl.find(i)) self.pl.next() self.failUnlessEqual(self.pl.current, 9) def test_next_at_end_finishes(self): self.pl.go_to(9) self.pl.next() self.assertEqual(self.pl.current, None) def test_shuffle(self): self.pl.order = OrderShuffle() for i in range(5): history = [self.pl.current for _ in range(10) if self.pl.next() or True] self.assertNotEqual(history, list(range(10))) self.assertEqual(sorted(history), list(range(10))) self.pl.next() self.assertEqual(self.pl.current, None) self.pl.order.reset(self.pl) def test_shuffle_previous_after_reorder(self): rand = Random(7) self.pl.order = OrderShuffle() history = [self.pl.current for _ in range(10) if self.pl.next() or True] order = list(range(10)) for i in reversed(range(10)): values = list(self.pl.itervalues()) rand.shuffle(order) self.pl.reorder(order) self.assertNotEqual(values, list(self.pl.itervalues())) self.failUnlessEqual(self.pl.current, history[i], f"expected different item at index {i}") self.pl.previous() def test_shuffle_repeat_forever(self): self.pl.order = RepeatSongForever(OrderShuffle()) old = self.pl.current for i in range(5): self.pl.next_ended() self.assertEqual(self.pl.current, old) def test_shuffle_repeat(self): self.pl.order = RepeatListForever(OrderShuffle()) numbers = [self.pl.current for _ in range(30) if self.pl.next_ended() or True] allnums = sorted(list(range(10)) * 3) self.assertNotEqual(numbers, allnums) numbers.sort() self.assertEqual(numbers, allnums) def test_repeat_song_repeats_on_end(self): self.pl.order = RepeatSongForever(OrderInOrder()) self.pl.go_to(3) self.failUnlessEqual(self.pl.current, 3) self.pl.next_ended() self.failUnlessEqual(self.pl.current, 3) def test_repeat_song_uses_underlying_on_explicit(self): self.pl.order = RepeatSongForever(OrderInOrder()) self.pl.go_to(3) self.pl.next() self.failUnlessEqual(self.pl.current, 4) def test_repeat_all_cycles_playlist(self): self.pl.go_to(3) self.pl.order = RepeatListForever(OrderInOrder()) self.failUnlessEqual(self.pl.current, 3) self.pl.next() self.failUnlessEqual(self.pl.current, 4) for i in range(9): self.pl.next_ended() self.failUnlessEqual(self.pl.current, 3) def test_previous(self): self.pl.go_to(2) self.failUnlessEqual(self.pl.current, 2) self.pl.previous() self.failUnlessEqual(self.pl.current, 1) self.pl.previous() self.failUnlessEqual(self.pl.current, 0) self.pl.previous() self.failUnlessEqual(self.pl.current, 0) def test_go_to_saves_current(self): self.pl.go_to(5) self.failUnlessEqual(self.pl.current, 5) self.pl.set([5, 10, 15, 20]) Gtk.main_iteration_do(False) self.pl.next() self.failUnlessEqual(self.pl.current, 10) def test_go_to_order(self): self.pl.order = OrderShuffle() for i in range(5): self.pl.go_to(5) self.failUnlessEqual(self.pl.current, 5) self.pl.go_to(1) self.failUnlessEqual(self.pl.current, 1) def test_go_to(self): class SetOrder(Order): # most orders don't change iter here, # so make sure this gets handled right def set_explicit(self, playlist, iter): return playlist.iter_next(iter) def set_implicit(self, playlist, iter): return playlist.iter_next(playlist.iter_next(iter)) self.pl.order = SetOrder() self.failUnlessEqual(self.pl[self.pl.go_to(5, True)][0], 6) self.failUnlessEqual(self.pl[self.pl.go_to(5, False)][0], 7) def test_go_to_none(self): for i in range(5): self.pl.go_to(None) self.failUnlessEqual(self.pl.current, None) self.pl.next() self.failUnlessEqual(self.pl.current, 0) def test_reset(self): self.pl.go_to(5) self.failUnlessEqual(self.pl.current, 5) self.pl.reset() self.failUnlessEqual(self.pl.current, 0) def test_reset_order(self): self.pl.order = OrderInOrder() self.pl.go_to(5) self.failUnlessEqual(self.pl.current, 5) self.pl.reset() self.failUnlessEqual(self.pl.current, 0) def test_restart(self): self.pl.go_to(1) self.pl.set([101, 102, 103, 104]) Gtk.main_iteration_do(False) self.pl.next() self.failUnlessEqual(self.pl.current, 101) def test_next_nosong_536(self): self.pl.go_to(1) self.pl.order = OrderShuffle() self.pl.set([]) Gtk.main_iteration_do(False) self.pl.next() def test_clear_current(self): self.pl.go_to(1) self.pl.clear() self.pl.go_to(None) def shutDown(self): self.pl.destroy() class TPlaylistMux(TestCase): def setUp(self): self.q = QueueModel() self.pl = PlaylistModel() self.p = NullPlayer() self.mux = PlaylistMux(self.p, self.q, self.pl) self.p.setup(self.mux, None, 0) self.failUnless(self.pl.current is None) quodlibet.config.init() def test_destroy(self): self.mux.destroy() def test_only_pl(self): self.pl.set(range(10)) do_events() self.failUnless(self.mux.current is None) songs = [self.next() for i in range(10)] self.failUnlessEqual(songs, list(range(10))) self.next() self.failUnless(self.mux.current is None) def test_only_q(self): self.q.set(range(10)) do_events() self.failUnless(self.mux.current is None) songs = [self.next() for i in range(10)] self.failUnlessEqual(songs, list(range(10))) self.next() self.failUnless(self.mux.current is None) def test_mixed(self): self.q.set(range(5)) self.pl.set(range(5, 10)) do_events() self.failUnless(self.mux.current is None) songs = [self.next() for i in range(10)] self.failUnlessEqual(songs, list(range(10))) self.next() self.failUnless(self.mux.current is None) def test_newplaylist(self): self.pl.set(range(5, 10)) do_events() self.failUnless(self.mux.current is None) self.mux.go_to(7) self.failUnlessEqual(self.mux.current, 7) self.pl.set([3, 5, 12, 11]) do_events() self.failUnlessEqual(self.mux.current, None) self.pl.set([19, 8, 12, 3]) do_events() self.failUnlessEqual(self.mux.current, None) self.pl.set([3, 7, 9, 11]) do_events() self.mux.next() self.failUnlessEqual(self.mux.current, 9) def test_halfway(self): self.pl.set(range(10)) do_events() self.failUnless(self.mux.current is None) songs = [self.next() for i in range(5)] self.q.set(range(100, 105)) do_events() songs.extend([self.next() for i in range(10)]) self.failUnlessEqual( songs, [0, 1, 2, 3, 4, 100, 101, 102, 103, 104, 5, 6, 7, 8, 9]) self.next() self.failUnless(self.mux.current is None) def test_removal(self): self.pl.set(range(0, 5)) self.q.set(range(10, 15)) do_events() songs = [self.next() for i in range(3)] self.q.remove(self.q.find(14)) self.q.remove(self.q.find(13)) songs.extend([self.next() for i in range(5)]) self.failUnlessEqual(songs, [10, 11, 12, 0, 1, 2, 3, 4]) def next(self): self.mux.next() song = self.mux.current self.p.emit('song-started', self.mux.current) do_events() return song def previous(self): self.mux.previous() song = self.mux.current self.p.emit('song-started', self.mux.current) do_events() return song def test_previous(self): self.pl.set(range(10)) self.mux.go_to(0) self.next() self.previous() self.assertEqual(self.mux.current, 0) def test_previous_shuffle(self): self.pl.set(range(10)) self.pl.order = OrderShuffle() self.mux.go_to(0) self.next() self.previous() self.assertEqual(self.mux.current, 0) def test_goto(self): self.pl.set(range(10)) self.q.set(range(10, 20)) do_events() self.failUnless(self.mux.current is None) self.mux.go_to(5) self.failUnlessEqual(self.mux.current, 5) self.mux.go_to(2) self.failUnlessEqual(self.mux.current, 2) self.failUnlessEqual(self.next(), 10) self.mux.go_to(7) self.failUnlessEqual(self.mux.current, 7) self.failUnlessEqual(self.next(), 11) def test_random_queue_666(self): for i in range(5): self.mux.go_to(None) self.pl.set([1]) do_events() self.failUnless(self.mux.current is None) self.q.order = OrderShuffle() self.failUnless(self.next() == 1) self.q.set([10, 11]) do_events() value = self.next() self.failUnless( value in [10, 11], "got %r, expected 10 or 11" % value) if value == 10: next = 11 else: next = 10 self.failUnlessEqual(self.next(), next) def test_sourced(self): self.pl.set(range(10)) self.q.set(range(10)) self.mux.go_to(None) self.failUnless(self.pl.sourced) self.q.go_to(1) self.p.next() self.failIf(self.pl.sourced) def test_unqueue(self): self.q.set(range(100)) self.mux.unqueue(range(100)) self.failIf(len(self.q)) def test_queue(self): self.mux.enqueue(range(40)) self.failUnlessEqual(list(self.q.itervalues()), list(range(40))) def test_queue_move_entry(self): self.q.set(range(10)) self.p.next() self.assertEqual(self.p.song, 0) self.q.move_after(self.q[-1].iter, None) self.p.next() self.assertEqual(self.p.song, 9) def test_goto_queue(self): self.pl.set(range(20, 30)) self.q.set(range(10)) self.mux.go_to(self.q[-1].iter, source=self.q) self.assertTrue(self.q.sourced) self.assertEqual(self.mux.current, self.q[-1][0]) def test_queue_disable(self): self.pl.set(range(10)) self.q.set(range(10)) quodlibet.config.set("memory", "queue_disable", True) self.next() self.failUnlessEqual(len(self.pl.get()), len(range(10))) self.failUnlessEqual(len(self.q.get()), len(range(10))) self.assertTrue(self.pl.sourced) quodlibet.config.set("memory", "queue_disable", False) self.next() self.failUnlessEqual(len(self.pl.get()), len(range(10))) self.failUnlessEqual(len(self.q.get()), len(range(10)) - 1) self.assertTrue(self.q.sourced) def test_queue_disable_next(self): self.pl.set(range(10)) self.q.set(range(10)) self.mux.go_to(self.q[0].iter, source=self.q) quodlibet.config.set("memory", "queue_disable", True) self.next() self.assertTrue(self.pl.sourced) def test_queue_disable_prev(self): self.pl.set(range(10)) self.q.set(range(10)) self.mux.go_to(self.q[0].iter, source=self.q) quodlibet.config.set("memory", "queue_disable", True) self.previous() self.assertTrue(self.pl.sourced) def test_queue_keep_songs(self): self.q.set(range(10)) quodlibet.config.set("memory", "queue_keep_songs", True) self.next() self.failUnlessEqual(len(self.q.get()), len(range(10))) self.failUnlessEqual(self.q.current, None) self.mux.go_to(self.q[0].iter, source=self.q) self.failUnlessEqual(self.q.current, 0) self.next() self.failUnlessEqual(len(self.q.get()), len(range(10))) self.failUnlessEqual(self.q.current, 1) quodlibet.config.set("memory", "queue_keep_songs", False) self.next() self.failUnlessEqual(len(self.q.get()), len(range(10)) - 1) self.failUnless(self.q.current is None) def test_queue_disable_and_keep_songs(self): self.pl.set(range(10)) self.q.set(range(10)) self.mux.go_to(self.q[0].iter, source=self.q) quodlibet.config.set("memory", "queue_disable", True) quodlibet.config.set("memory", "queue_keep_songs", True) self.next() self.assertTrue(self.pl.sourced) def test_queue_preserved_when_setexplicit_rejected(self): class TestOrder(Order): def set_explicit(self, playlist, iter): return None self.pl.set(range(10, 20)) self.pl.order = TestOrder() self.q.set(range(10)) self.mux.go_to(self.q[0].iter, source=self.q) self.assertTrue(self.q.sourced) self.mux.go_to(self.pl[0].iter, explicit=True, source=self.pl) self.assertTrue(self.q.sourced) self.assertEqual(self.mux.current, self.q[0][0]) def tearDown(self): self.p.destroy() �����������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1660723675.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_songsmenu.py��������������������������������������������������������0000644�0001750�0001750�00000012574�14277120733�020046� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import quodlibet.player from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.formats.remote import RemoteFile from quodlibet.library import SongFileLibrary from quodlibet.qltk.songsmenu import SongsMenu from senf import fsnative from tests import TestCase, mkdtemp def an_af(i: int) -> AudioFile: return AudioFile({"~filename": "/dev/null", "title": "http://example.com/%0d" % i}) def an_rf(i: int) -> AudioFile: return RemoteFile(f"https://example.com/{i}.mp3") class TSongsMenu(TestCase): def _confirmer(self, *args): self.confirmed = True return False def setUp(self): config.init() self.library = SongFileLibrary() backend = quodlibet.player.init_backend("nullbe") self.device = backend.init(self.library) self.songs = [AudioFile({"title": x}) for x in ["song1", "song2", "song3"]] for song in self.songs: song.sanitize(fsnative(str(song["title"]))) self.confirmed = False def test_empty(self): self.menu = self.empty_menu_with() self.failIf(len(self.menu)) def test_simple(self): self.menu = SongsMenu(self.library, self.songs, plugins=False) def test_playlists(self): self.menu = self.empty_menu_with(playlists=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].can_add = False self.menu = self.empty_menu_with(playlists=True) self.failUnlessEqual(len(self.menu), 1) self.failIf(self.menu.get_children()[0].props.sensitive) def test_queue(self): self.menu = self.empty_menu_with(queue=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].can_add = False self.menu = self.empty_menu_with(queue=True) self.failUnlessEqual(len(self.menu), 1) self.failIf(self.menu.get_children()[0].props.sensitive) def test_remove(self): self.menu = self.empty_menu_with(remove=True, removal_confirmer=self._confirmer) self.failUnlessEqual(len(self.menu), 1) item = self.menu.get_children()[0] self.failIf(item.props.sensitive) item.activate() self.failUnless(self.confirmed, "Should have confirmed song removal") def test_remove_sensitive(self): self.library.add(self.songs) self.menu = self.empty_menu_with(remove=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) def test_delete(self): self.menu = self.empty_menu_with(delete=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].is_file = False self.menu = self.empty_menu_with(delete=True) self.failIf(self.menu.get_children()[0].props.sensitive) def test_show_files(self): self.menu = self.empty_menu_with(show_files=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) item = self.menu.get_children()[0] self.failUnless(item.props.sensitive) def test_show_files_remote_songs(self): self.songs = self.library.songs = [an_rf(1)] self.menu = self.empty_menu_with(show_files=True) self.failIf(len(self.menu)) def test_show_files_too_many_songs(self): self.songs = self.library.songs = [an_af(i) for i in range(50)] self.menu = self.empty_menu_with(show_files=True) item = self.menu.get_children()[0] self.failIf(item.props.sensitive, msg="Should have disabled show files for 50 files") def test_download(self): def choose(*args, **kwargs): return [mkdtemp()] self.songs = self.library.songs = [an_rf(i) for i in range(3)] self.menu = self.empty_menu_with(download=True, folder_chooser=choose) last = self.menu.get_children()[-1] assert last.props.sensitive, "should have enabled download for remotes" # TODO: some useful assertions, without needing a UI def empty_menu_with(self, plugins=False, playlists=False, queue=False, remove=False, delete=False, edit=False, info=False, ratings=False, show_files=False, download=False, removal_confirmer=None, folder_chooser=None): return SongsMenu(self.library, self.songs, plugins=plugins, playlists=playlists, queue=queue, remove=remove, delete=delete, edit=edit, info=info, ratings=ratings, show_files=show_files, removal_confirmer=removal_confirmer, download=download, folder_chooser=folder_chooser) def tearDown(self): self.device.destroy() self.library.destroy() try: self.menu.destroy() except AttributeError: pass else: del(self.menu) config.quit() ������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_tagscombobox.py�����������������������������������������������������0000664�0001750�0001750�00000002716�14035600052�020503� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, skipIf from quodlibet.util.tags import USER_TAGS from quodlibet.qltk import is_wayland class TagsCombo(TestCase): def setUp(self): self.all = self.Kind() self.some = self.Kind(["artist", "album", "~people", "foobar"]) def tearDown(self): self.all.destroy() self.some.destroy() class TagsComboMixin: def test_none(self): self.failUnlessRaises(ValueError, self.Kind, []) def test_some(self): self.some.set_active(2) self.failUnlessEqual(self.some.tag, "foobar") def test_all(self): tags = list(USER_TAGS) tags.sort() for i, value in enumerate(tags): self.all.set_active(i) self.failUnlessEqual(self.all.tag, value) @skipIf(is_wayland(), "crashes..") class TTagsComboBox(TagsCombo, TagsComboMixin): from quodlibet.qltk.tagscombobox import TagsComboBox as Kind Kind @skipIf(is_wayland(), "crashes..") class TTagsComboBoxEntry(TagsCombo, TagsComboMixin): from quodlibet.qltk.tagscombobox import TagsComboBoxEntry as Kind Kind def test_custom(self): self.all.get_child().set_text("a new tag") self.failUnlessEqual(self.all.tag, "a new tag") ��������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_tagsfrompath.py�����������������������������������������������������0000664�0001750�0001750�00000002244�14035600052�020507� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk.tagsfrompath import (TitleCase, SplitTag, UnderscoresToSpaces) import quodlibet.config class FilterTestCase(TestCase): def setUp(self): quodlibet.config.init() self.c = self.Kind() def tearDown(self): self.c.destroy() quodlibet.config.quit() class TTitleCase(FilterTestCase): Kind = TitleCase def test_simple(self): self.failUnlessEqual(self.c.filter("title", "foo bar"), "Foo Bar") def test_apostrophe(self): self.failUnlessEqual(self.c.filter("title", "IT's"), "IT's") class TSplitTag(FilterTestCase): Kind = SplitTag def test_simple(self): self.failUnlessEqual(self.c.filter("title", "foo & bar"), "foo\nbar") class TUnderscoresToSpaces(FilterTestCase): Kind = UnderscoresToSpaces def test_simple(self): self.failUnlessEqual(self.c.filter("titke", "foo_bar"), "foo bar") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_textedit.py���������������������������������������������������������0000664�0001750�0001750�00000003606�14035600052�017645� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk.textedit import TextEditBox, TextEdit, \ validate_markup_pattern class TTextEditBox(TestCase): def setUp(self): self.box = TextEditBox() def test_empty(self): self.failUnlessEqual(self.box.text, "") def test_set(self): self.box.text = "bazquux" self.failUnlessEqual(self.box.text, "bazquux") def test_clicked(self): self.box.apply.clicked() def tearDown(self): self.box.destroy() class TTextEdit(TTextEditBox): def setUp(self): self.box = TextEdit(None) class TTextEditBox2(TestCase): def setUp(self): self.foobar = TextEditBox("foobar") def test_revert(self): self.foobar.revert.clicked() self.failUnless(self.foobar.text, "foobar") def tearDown(self): self.foobar.destroy() class TTextEdit2(TTextEditBox2): def setUp(self): self.foobar = TextEdit(None, "foobar") class Tvalidate_markup_pattern(TestCase): def test_valid(self): for t in [u"", u"<foo>", u"\\<b\\><foo>bar\\</b\\>", u"[b]"]: validate_markup_pattern(t, False, False) for t in [u"[b][/b]"]: validate_markup_pattern(t, True, False) for t in [u"[a href=''][/a]", u"\\<a href=''\\>\\</a\\>"]: validate_markup_pattern(t, True, True) def test_invalid(self): for t in [u"\\<", u"\\<a href=''\\>\\</a\\>"]: self.assertRaises( ValueError, validate_markup_pattern, t, False, False) for t in [u"[b]"]: self.assertRaises( ValueError, validate_markup_pattern, t, True, False) ��������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_tracker.py����������������������������������������������������������0000664�0001750�0001750�00000010041�14231604332�017440� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary from quodlibet.library.file import FileLibrary from quodlibet.player.nullbe import NullPlayer from quodlibet.qltk.tracker import SongTracker, FSInterface from tests import TestCase, mkdtemp, run_gtk_loop A_PATH = "/dev/null" class TSongTracker(TestCase): def setUp(self): config.init() self.p = NullPlayer() self.w = SongLibrary() self.s1 = AudioFile( {"~#playcount": 0, "~#skipcount": 0, "~#lastplayed": 10, "~filename": "foo", "~#length": 1.5}) self.s2 = AudioFile( {"~#playcount": 0, "~#skipcount": 0, "~#lastplayed": 10, "~filename": "foo", "~#length": 1.5}) self.cm = SongTracker(self.w, self.p, self) self.current = None def test_destroy(self): self.cm.destroy() def test_play(self): import time # Allow at least 2 second to elapse to simulate playing self.p.song = self.s1 self.p.paused = False time.sleep(2) run_gtk_loop() self.p.emit('song-ended', self.s1, False) run_gtk_loop() t = time.time() self.assertEquals(self.s1["~#playcount"], 1) self.assertEquals(self.s1["~#skipcount"], 0) self.failUnless(t - self.s1["~#lastplayed"] <= 1) def test_skip(self): self.p.emit('song-ended', self.s1, True) run_gtk_loop() self.assertEquals(self.s1["~#playcount"], 0) self.assertEquals(self.s1["~#skipcount"], 1) self.failUnless(self.s1["~#lastplayed"], 10) def test_error(self): self.current = self.p.song = self.s1 self.p._error('Test error') run_gtk_loop() self.assertEquals(self.s1["~#playcount"], 0) self.assertEquals(self.s1["~#skipcount"], 0) self.failUnless(self.s1["~#lastplayed"], 10) def test_restart(self): self.current = self.s1 self.p.emit('song-ended', self.s1, True) run_gtk_loop() self.assertEquals(self.s1["~#playcount"], 0) self.assertEquals(self.s1["~#skipcount"], 0) def tearDown(self): self.w.destroy() config.quit() class TFSInterface(TestCase): def setUp(self): self.p = NullPlayer() self.dir = mkdtemp() self.lib = FileLibrary() self.song = AudioFile({"~filename": A_PATH, "title": "bar", "~#length": 10}) self.lib.add([self.song]) self.filename = os.path.join(self.dir, "foo") self.fs = FSInterface(self.filename, self.p, self.lib) def tearDown(self): self.p.destroy() self.lib.destroy() shutil.rmtree(self.dir) def test_init(self): run_gtk_loop() self.failIf(os.path.exists(self.filename)) def test_start(self): self.p.emit('song_started', self.song) run_gtk_loop() with open(self.filename, "rb") as h: self.failUnless(b"title=bar\n" in h.read()) def test_song_ended(self): self.p.emit('song-started', self.song) run_gtk_loop() self.p.emit('song-ended', {}, False) run_gtk_loop() self.failIf(os.path.exists(self.filename)) def test_elapsed(self): self.p.seek(123456) self.p.emit('song-started', AudioFile({"~#length": 10})) run_gtk_loop() with open(self.filename, "rb") as h: contents = h.read() assert b"~#elapsed=123.456" in contents assert b"~elapsed=2:03\n" in contents def test_current_song_changed(self): self.p.song = self.song self.song["title"] = "new!" self.lib.changed([self.song]) run_gtk_loop() with open(self.filename, "rb") as h: contents = h.read() assert b"title=new!\n" in contents �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_unity.py������������������������������������������������������������0000664�0001750�0001750�00000000641�14035600052�017157� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk import unity class TUnityQuickList(TestCase): def test_init(self): unity.init("quodlibet.desktop", None) �����������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_util.py�������������������������������������������������������������0000664�0001750�0001750�00000001333�14035600052�016763� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from tests import TestCase from .helper import realized from quodlibet.qltk.util import position_window_beside_widget class Tposition_window_beside_widget(TestCase): def test_main(self): button = Gtk.Button() window = Gtk.Window() with realized(button): position_window_beside_widget(window, button, True) position_window_beside_widget(window, button, False) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_views.py������������������������������������������������������������0000664�0001750�0001750�00000021316�14035600052�017146� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.qltk.views import AllTreeView, BaseView, TreeViewColumn, \ DragScroll, MultiDragTreeView, RCMTreeView, DragIconTreeView import quodlibet.config from quodlibet.util import is_windows from gi.repository import Gtk, Gdk from . import skipIf from .helper import send_key_click, visible, send_button_click, realized def _fill_view(view): """Adds a model with 100 text rows and a column to display them. Returns the model. """ model = Gtk.ListStore(str) column = Gtk.TreeViewColumn("foo") title = Gtk.CellRendererText() column.pack_start(title, True) column.add_attribute(title, "text", 0) view.append_column(column) for x in range(100): model.append(row=["foo"]) view.set_model(model) return model class THintedTreeView(TestCase): def setUp(self): quodlibet.config.init() self.c = AllTreeView() def test_exists(self): self.failUnless(self.c) def tearDown(self): self.c.destroy() quodlibet.config.quit() class TBaseView(TestCase): def setUp(self): self.m = Gtk.ListStore(str) self.c = BaseView(model=self.m) def test_selection_changed(self): events = [] def on_selection_changed(*args): events.append(args) self.c.connect("selection-changed", on_selection_changed) self.m.append(row=["foo"]) self.c.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.c.get_selection().select_all() self.assertTrue(events) def test_remove(self): self.m.append(row=["foo"]) self.c.remove_iters([self.m[0].iter]) self.failIf(len(self.m)) self.m.append(row=["foo"]) self.c.remove_iters([]) self.failUnless(len(self.m)) self.c.remove_paths([self.m[0].path]) self.failIf(len(self.m)) def test_key_events(self): with visible(self.c): send_key_click(self.c, "<Primary>Right") send_key_click(self.c, "<Primary>Left") def test_select_func(self): self.m.append(row=["foo"]) self.m.append(row=["bar"]) self.failUnless(self.c.select_by_func(lambda r: True)) self.failIf(self.c.select_by_func(lambda r: False)) self.c.select_by_func(lambda r: False, scroll=False, one=True) def test_iter_select_func(self): # empty self.assertFalse(self.c.iter_select_by_func(lambda r: False)) self.assertFalse(self.c.iter_select_by_func(lambda r: True)) self.m.append(row=["foo"]) self.m.append(row=["bar"]) self.m.append(row=["foo"]) self.c.remove_selection() self.assertTrue(self.c.iter_select_by_func(lambda r: r[0] == "foo")) selection = self.c.get_selection() model, iter_ = selection.get_selected() self.assertEqual(model.get_path(iter_)[:], [0]) self.assertTrue(self.c.iter_select_by_func(lambda r: r[0] == "foo")) model, iter_ = selection.get_selected() self.assertEqual(model.get_path(iter_)[:], [2]) self.assertTrue(self.c.iter_select_by_func(lambda r: r[0] == "foo")) model, iter_ = selection.get_selected() self.assertEqual(model.get_path(iter_)[:], [0]) self.assertTrue(self.c.iter_select_by_func(lambda r: r[0] == "bar")) model, iter_ = selection.get_selected() self.assertEqual(model.get_path(iter_)[:], [1]) self.assertFalse(self.c.iter_select_by_func(lambda r: r[0] == "bar")) def test_remove_select_single(self): # empty self.c.remove_selection() model = _fill_view(self.c) # select first and remove selection = self.c.get_selection() length = len(model) selection.select_path(model[0].path) self.c.remove_selection() self.assertEqual(len(model), length - 1) model, iter_ = selection.get_selected() # afterwards the first is selected self.assertEqual(model[iter_].path, model[0].path) def test_remove_select_multiple(self): selection = self.c.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) # empty self.c.remove_selection() model = _fill_view(self.c) # select first two and remove selection = self.c.get_selection() length = len(model) selection.select_range(model[0].path, model[1].path) self.c.remove_selection() self.assertEqual(len(model), length - 2) # afterwards the first is selected model, paths = selection.get_selected_rows() self.assertEqual(paths, [model[0].path]) def test_without_model(self): column = TreeViewColumn() self.c.append_column(column) column = self.c.get_columns()[0] column.set_sort_indicator(True) self.c.set_search_column(0) with self.c.without_model() as model: self.assertEqual(model, self.m) self.assertTrue(self.c.get_model() is None) self.assertEqual(self.c.get_search_column(), 0) column = self.c.get_columns()[0] self.assertTrue(column.get_sort_indicator()) def test_set_drag_dest(self): x, y = self.c.convert_bin_window_to_widget_coords(0, 0) # empty model self.c.unset_rows_drag_dest() self.c.set_drag_dest(x, y) path, pos = self.c.get_drag_dest_row() self.assertTrue(path is None) # filled model but not realized, fall back to last path model = _fill_view(self.c) self.c.set_drag_dest(x, y) path, pos = self.c.get_drag_dest_row() self.assertEqual(model[-1].path, path) # realized now, so the first path with realized(self.c): x, y = self.c.convert_bin_window_to_widget_coords(0, 0) self.c.unset_rows_drag_dest() self.c.set_drag_dest(x, y, into_only=False) path, pos = self.c.get_drag_dest_row() self.assertEqual(model[0].path, path) self.assertEqual(pos, Gtk.TreeViewDropPosition.BEFORE) self.c.unset_rows_drag_dest() self.c.set_drag_dest(x, y, into_only=True) path, pos = self.c.get_drag_dest_row() self.assertEqual(model[0].path, path) self.assertEqual(pos, Gtk.TreeViewDropPosition.INTO_OR_BEFORE) def tearDown(self): self.c.destroy() class TMultiDragTreeView(TestCase): def setUp(self): self.c = MultiDragTreeView() _fill_view(self.c) def test_click(self): with visible(self.c): send_button_click(self.c, Gdk.BUTTON_PRIMARY) send_button_click(self.c, Gdk.BUTTON_PRIMARY, primary=True) class TRCMTreeView(TestCase): def setUp(self): self.c = RCMTreeView() _fill_view(self.c) def test_right_click(self): with visible(self.c): send_button_click(self.c, Gdk.BUTTON_SECONDARY) send_button_click(self.c, Gdk.BUTTON_SECONDARY, primary=True) def test_popup(self): menu = Gtk.Menu() selection = self.c.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) with visible(self.c): # the popup only shows if the underlying row is selected, # so select all first selection.select_all() self.assertTrue(self.c.popup_menu(menu, Gdk.BUTTON_SECONDARY, 0)) class TDragIconTreeView(TestCase): def setUp(self): self.c = DragIconTreeView() _fill_view(self.c) def test_create_drag_icon(self): model = self.c.get_model() all_paths = [row.path for row in model] self.assertFalse(self.c.create_multi_row_drag_icon(all_paths, 1)) with visible(self.c): self.assertTrue(self.c.create_multi_row_drag_icon(all_paths, 1)) self.assertFalse(self.c.create_multi_row_drag_icon([], 1)) self.assertTrue( self.c.create_multi_row_drag_icon([all_paths[0]], 10)) class TDragScroll(TestCase): def setUp(self): class ScrollClass(BaseView, DragScroll): pass self.c = ScrollClass() _fill_view(self.c) @skipIf(is_windows(), "fixme") def test_basic(self): self.c.scroll_motion(0, 0) self.c.scroll_motion(42, 42) self.c.scroll_motion(999, 999) self.c.scroll_disable() class TTreeViewColumn(TestCase): def test_main(self): TreeViewColumn(title="foo") area = Gtk.CellAreaBox() tvc = TreeViewColumn(cell_area=area) self.assertEqual(tvc.get_area(), area) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_window.py�����������������������������������������������������������0000664�0001750�0001750�00000004564�14231604332�017331� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase, skipIf from quodlibet.qltk.window import Window, on_first_map, Dialog from quodlibet.util import InstanceTracker, is_osx from .helper import realized class TWindow(TestCase): def test_on_first_map(self): w = Window() calls = [] def foo(*args): calls.append(args) on_first_map(w, foo, 1) w.show() self.assertEqual(calls, [(1,)]) on_first_map(w, foo, 2) self.assertEqual(calls, [(1,), (2,)]) w.destroy() def test_ctr(self): Window().destroy() def test_instance_tracking(self): class SomeWindow(Window, InstanceTracker): def __init__(self): super().__init__() self._register_instance() self.assertFalse(SomeWindow.windows) other = Window() a = SomeWindow() self.assertTrue(a in SomeWindow.windows) self.assertTrue(a in SomeWindow.instances()) a.destroy() self.assertFalse(SomeWindow.instances()) self.assertTrue(SomeWindow.windows) other.destroy() self.assertFalse(SomeWindow.windows) def test_show_maybe(self): Window.prevent_inital_show(True) w = Window() w.show_maybe() self.assertFalse(w.get_visible()) Window.prevent_inital_show(False) w.show_maybe() self.assertTrue(w.get_visible()) w.destroy() def test_use_header_bar(self): w = Window(title="foo") w.use_header_bar() self.assertEqual(w.get_title(), "foo") w.destroy() w = Window() w.use_header_bar() self.assertEqual(w.get_title(), None) w.destroy() @skipIf(is_osx(), "crashes on 10.13") def test_toggle_fullscreen(self): w = Window(title="foo") w.toggle_fullscreen() with realized(w): w.toggle_fullscreen() w.toggle_fullscreen() w.destroy() class TDialog(TestCase): def test_add_icon_button(self): d = Dialog() w = d.add_icon_button("foo", "bar", 100) self.assertEqual(d.get_widget_for_response(100), w) ��������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_wlw.py��������������������������������������������������������������0000664�0001750�0001750�00000003713�14035600052�016623� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from .helper import locale_numeric_conv from gi.repository import Gtk from quodlibet.qltk.wlw import WaitLoadWindow class TWaitLoadWindow(TestCase): class DummyConnector(Gtk.Window): count = 0 def connect(self, *args): self.count += 1 def disconnect(self, *args): self.count -= 1 class Eater: def set_cursor(*args): pass window = Eater() def setUp(self): self.parent = self.DummyConnector() self.wlw = WaitLoadWindow(self.parent, 5, "a test") def test_none(self): wlw = WaitLoadWindow(None, 5, "a test") wlw.step() wlw.destroy() def test_plurals(self): with locale_numeric_conv(): wlw = WaitLoadWindow(None, 1234, "At %(current)d of %(total)d") self.failUnlessEqual(wlw._label.get_text(), "At 0 of 1,234") while wlw.current < 1000: wlw.step() self.failUnlessEqual(wlw._label.get_text(), "At 1,000 of 1,234") def test_connect(self): self.failUnlessEqual(self.parent.count, 2) self.wlw.destroy() self.failUnlessEqual(self.parent.count, 0) def test_start(self): self.failUnlessEqual(self.wlw.current, 0) self.failUnlessEqual(self.wlw.count, 5) def test_step(self): self.failIf(self.wlw.step()) self.failUnlessEqual(self.wlw.current, 1) self.failIf(self.wlw.step()) self.failIf(self.wlw.step()) self.failUnlessEqual(self.wlw.current, 3) def test_destroy(self): self.wlw.destroy() self.failUnlessEqual(self.parent.count, 0) def tearDown(self): self.wlw.destroy() �����������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_qltk_x.py����������������������������������������������������������������0000664�0001750�0001750�00000004211�14035600052�016253� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.qltk import x from quodlibet.qltk import Icons from . import TestCase from .helper import visible class Notebook(TestCase): def test_widget_str(self): n = x.Notebook() c = Gtk.VBox() n.append_page(c, "A Test") self.failUnlessEqual(n.get_tab_label(c).get_text(), "A Test") n.destroy() def test_widget_label(self): l = Gtk.Label(label="A Test") n = x.Notebook() c = Gtk.VBox() n.append_page(c, l) self.failUnless(l is n.get_tab_label(c)) c.destroy() def test_widget_error(self): n = x.Notebook() w = Gtk.VBox() self.failUnlessRaises(TypeError, n.append_page, w) w.destroy() n.destroy() class Frame(TestCase): def test_label(self): self.failUnlessEqual( x.Frame("foo").get_label_widget().get_text(), "foo") class MenuItem(TestCase): def test_ctr(self): self.failUnless(x.MenuItem("foo", Icons.EDIT_FIND)) class Button(TestCase): def test_ctr(self): self.failUnless(x.Button("foo", Icons.EDIT_FIND)) class TAlign(TestCase): def test_ctr(self): button = Gtk.Button() a = x.Align(button, left=2, right=4, top=5, bottom=-2, border=2) self.assertEqual(a.get_margin_top(), 7) self.assertEqual(a.get_margin_bottom(), 0) self.assertEqual(a.get_margin_left(), 4) self.assertEqual(a.get_margin_right(), 6) self.failUnless(a.get_child() is button) a.destroy() class TScrolledWindow(TestCase): def test_ctr(self): w = x.ScrolledWindow() w.destroy() class THighlightToggleButton(TestCase): def test_main(self): w = x.HighlightToggleButton() w.set_active(True) with visible(w): pass w.set_active(False) with visible(w): pass w.destroy() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692647462.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_query.py�����������������������������������������������������������������0000644�0001750�0001750�00000052525�14470740046�016142� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import time import pytest from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.plugins import Plugin from quodlibet.plugins.query import QueryPlugin, QUERY_HANDLER from quodlibet.query import Query, QueryType from quodlibet.query import _match as match from senf import fsnative from tests import TestCase, skip class TestQuery_is_valid: def test_re(self): assert Query('t = /an re/').valid assert Query('t = /an re/c').valid assert Query('t = /an\\/re/').valid assert not Query('t = /an/re/').valid assert Query('t = /aaa/lsic').valid assert not Query('t = /aaa/icslx').valid def test_str(self): assert Query('t = "a str"').valid assert Query('t = "a str"c').valid assert Query('t = "a\\"str"').valid # there's no equivalent failure for strings since 'str"' would be # read as a set of modifiers def test_tag(self): assert Query('t = tag').valid assert Query('t = !tag').valid assert Query('t = |(tag, bar)').valid assert Query('t = a"tag"').valid assert not Query('t = a, tag').valid assert Query('tag with spaces = tag').valid def test_empty(self): assert Query('').valid assert Query('').is_parsable assert Query('') def test_emptylist(self): assert not Query("a = &()").valid assert not Query("a = |()").valid assert not Query("|()").valid assert not Query("&()").valid def test_nonsense(self): assert not Query('a string').valid assert not Query('t = #(a > b)').valid assert not Query("=a= = /b/").valid assert not Query("a = &(/b//").valid assert not Query("(a = &(/b//)").valid def test_trailing(self): assert not Query('t = /an re/)').valid assert not Query('|(a, b = /a/, c, d = /q/) woo').valid def test_not(self): assert Query('t = !/a/').valid assert Query('t = !!/a/').valid assert Query('!t = "a"').valid assert Query('!!t = "a"').valid assert Query('t = !|(/a/, !"b")').valid assert Query('t = !!|(/a/, !"b")').valid assert Query('!|(t = /a/)').valid def test_taglist(self): assert Query('a, b = /a/').valid assert Query('a, b, c = |(/a/)').valid assert Query('|(a, b = /a/, c, d = /q/)').valid assert not Query('a = /a/, b').valid def test_andor(self): assert Query('a = |(/a/, /b/)').valid assert Query('a = |(/b/)').valid assert Query('|(a = /b/, c = /d/)').valid assert Query('a = &(/a/, /b/)').valid assert Query('a = &(/b/)').valid assert Query('&(a = /b/, c = /d/)').valid def test_numcmp(self): assert Query("#(t < 3)").valid assert Query("#(t <= 3)").valid assert Query("#(t > 3)").valid assert Query("#(t >= 3)").valid assert Query("#(t = 3)").valid assert Query("#(t != 3)").valid assert not Query("#(t !> 3)").valid assert not Query("#(t >> 3)").valid def test_numcmp_func(self): assert Query("#(t:min < 3)").valid assert Query("&(#(playcount:min = 0), #(added < 1 month ago))").valid def test_trinary(self): assert Query("#(2 < t < 3)").valid assert Query("#(2 >= t > 3)").valid # useless, but valid assert Query("#(5 > t = 2)").valid def test_list(self): assert Query("#(t < 3, t > 9)").valid assert Query("t = &(/a/, /b/)").valid assert Query("s, t = |(/a/, /b/)").valid assert Query("|(t = /a/, s = /b/)").valid def test_nesting(self): assert Query("|(s, t = &(/a/, /b/),!#(2 > q > 3))").valid class FakeQueryPlugin(QueryPlugin): PLUGIN_NAME = "name" def search(self, song, body): return body and "DIE" not in body.upper() def test_extension(self): plugin = Plugin(self.FakeQueryPlugin) QUERY_HANDLER.plugin_enable(plugin) try: assert Query("@(name)").valid assert not Query("@(name: DIE)").search("foo") assert Query("@(name: extension body)").valid assert Query("@(name: body (with (nested) parens))").valid assert Query(r"@(name: body \\ with \) escapes)").valid finally: QUERY_HANDLER.plugin_disable(plugin) def test_extension_search(self): plugin = Plugin(self.FakeQueryPlugin) QUERY_HANDLER.plugin_enable(plugin) song = AudioFile({"~filename": "/dev/null"}) try: assert Query("@(name: LIVE)").search(song) assert not Query("@(name: DIE)").search(song) finally: QUERY_HANDLER.plugin_disable(plugin) def test_invalid_extension(self): assert not Query("@(name)").valid, "Unregistered plugin is valid" assert not Query("@()").valid assert not Query(r"@(invalid %name!\\)").valid assert not Query("@(name: mismatched ( parenthesis)").valid assert not Query(r"@(\()").valid assert not Query("@(name:unclosed body").valid assert not Query("@ )").valid def test_numexpr(self): assert Query("#(t < 3*4)").valid assert Query("#(t * (1+r) < 7)").valid assert Query("#(0 = t)").valid assert Query("#(t < r < 9)").valid assert Query("#((t-9)*r < -(6*2) = g*g-1)").valid assert Query("#(t + 1 + 2 + -4 * 9 > g*(r/4 + 6))").valid assert Query("#(date < 2010-4)").valid assert Query("#(date < 2010 - 4)").valid assert Query("#(date > 0000)").valid assert Query("#(date > 00004)").valid assert Query("#(added > today)").valid assert Query("#(length < 5:00)").valid assert Query("#(filesize > 5M)").valid assert Query("#(added < 7 days ago)").valid def test_numexpr_failures(self): assert not Query("#(3*4)").valid assert not Query("#(t = 3 + )").valid assert not Query("#(t = -)").valid assert not Query("#(-4 <)").valid assert not Query("#(t < ()").valid assert not Query("#((t +) - 1 > 8)").valid assert not Query("#(t += 8)").valid def test_numexpr_fails_for_wrong_units(self): assert not Query("#(t > 3 minutes)").valid assert not Query("#(size < 3 minutes)").valid assert not Query("#(date = 3 GB)").valid class TQuery(TestCase): def setUp(self): config.init() self.s1 = AudioFile( {"album": u"I Hate: Tests", "artist": u"piman", "title": u"Quuxly", "version": u"cake mix", "~filename": fsnative(u"/dir1/foobar.ogg"), "~#length": 224, "~#skipcount": 13, "~#playcount": 24, "date": u"2007-05-24", "~#samplerate": 44100}) self.s2 = AudioFile( {"album": u"Foo the Bar", "artist": u"mu", "title": u"Rockin' Out", "~filename": fsnative(u"/dir2/something.mp3"), "tracknumber": u"12/15"}) self.s3 = AudioFile({ "artist": u"piman\nmu", "~filename": fsnative(u"/test/\xf6\xe4\xfc/fo\xfc.ogg"), "~mountpoint": fsnative(u"/bla/\xf6\xe4\xfc/fo\xfc"), }) self.s4 = AudioFile({"title": u"Ångström", "utf8": u"Ångström"}) self.s5 = AudioFile({"title": u"oh&blahhh", "artist": u"!ohno"}) def tearDown(self): config.quit() def test_basic_tag(self): assert Query("album=foo").search(self.s2) assert not Query("album=.").search(self.s2) assert Query("album=/./").search(self.s2) def test_inequality(self): assert Query("album!=foo").search(self.s1) assert not Query("album!=foo").search(self.s2) @skip("Enable for basic benchmarking of Query") def test_inequality_performance(self): t = time.time() for i in range(500): # Native assert is a bit lighter... assert Query("album!=foo the bar").search(self.s1) assert Query("album=foo the bar").search(self.s2) assert Query("foo the bar").search(self.s2) assert not Query("foo the bar").search(self.s1) us = (time.time() - t) * 1000000 / ((i + 1) * 4) print("Blended Query searches average %.0f μs" % us) @skip("Enable for basic benchmarking of Query") def test_inequality_equalish_performance(self): t0 = time.time() repeats = 2000 for i in range(repeats): assert Query("album!=foo the bar").search(self.s1) ineq_time = (time.time() - t0) t1 = time.time() for i in range(repeats): assert Query("album=!foo the bar").search(self.s1) not_val_time = (time.time() - t1) assert ineq_time == pytest.approx(not_val_time, abs=0.1) def test_repr(self): query = Query("foo = bar", []) r = repr(query).replace("u'", "'") assert r == "<Query string='foo = bar' type=VALID star=[]>" query = Query("bar", ["foo"]) r = repr(query).replace("u'", "'") assert r == "<Query string='&(/bar/d)' type=TEXT star=['foo']>" def test_2007_07_27_synth_search(self): song = AudioFile({"~filename": fsnative(u"foo/64K/bar.ogg")}) query = Query("~dirname = !64K") assert not query.search(song), "%r, %r" % (query, song) def test_empty(self): assert not Query("foobar = /./").search(self.s1) def test_gte(self): assert Query("#(track >= 11)").search(self.s2) def test_re(self): for s in ["album = /i hate/", "artist = /pi*/", "title = /x.y/"]: assert Query(s).search(self.s1) assert not Query(s).search(self.s2) f = Query("artist = /mu|piman/").search assert f(self.s1) assert f(self.s2) def test_re_escape(self): af = AudioFile({"foo": "\""}) assert Query('foo="\\""').search(af) af = AudioFile({"foo": "/"}) assert Query('foo=/\\//').search(af) def test_not(self): for s in ["album = !hate", "artist = !pi"]: assert not Query(s).search(self.s1) assert Query(s).search(self.s2) def test_abbrs(self): for s in ["b = /i hate/", "a = /pi*/", "t = /x.y/"]: assert Query(s).search(self.s1) assert not Query(s).search(self.s2) def test_str(self): for k in self.s2.keys(): v = self.s2[k] assert Query('%s = "%s"' % (k, v)).search(self.s2) assert not Query('%s = !"%s"' % (k, v)).search(self.s2) def test_numcmp(self): assert not Query("#(track = 0)").search(self.s1) assert not Query("#(notatag = 0)").search(self.s1) assert Query("#(track = 12)").search(self.s2) def test_trinary(self): assert Query("#(11 < track < 13)").search(self.s2) assert Query("#(11 < track <= 12)").search(self.s2) assert Query("#(12 <= track <= 12)").search(self.s2) assert Query("#(12 <= track < 13)").search(self.s2) assert Query("#(13 > track > 11)").search(self.s2) assert Query("#(20 > track < 20)").search(self.s2) def test_not_2(self): for s in ["album = !/i hate/", "artist = !/pi*/", "title = !/x.y/"]: assert Query(s).search(self.s2) assert not Query(s).search(self.s1) def test_case(self): assert Query("album = /i hate/").search(self.s1) assert Query("album = /I Hate/").search(self.s1) assert Query("album = /i Hate/").search(self.s1) assert Query("album = /i Hate/i").search(self.s1) assert Query(u"title = /ångström/").search(self.s4) assert not Query("album = /i hate/c").search(self.s1) assert not Query(u"title = /ångström/c").search(self.s4) def test_re_and(self): assert Query("album = &(/ate/,/est/)").search(self.s1) assert not Query("album = &(/ate/, /ets/)").search(self.s1) assert not Query("album = &(/tate/, /ets/)").search(self.s1) def test_re_or(self): assert Query("album = |(/ate/,/est/)").search(self.s1) assert Query("album = |(/ate/,/ets/)").search(self.s1) assert not Query("album = |(/tate/, /ets/)").search(self.s1) def test_newlines(self): assert Query("a = /\n/").search(self.s3) assert Query("a = /\\n/").search(self.s3) assert not Query("a = /\n/").search(self.s2) assert not Query("a = /\\n/").search(self.s2) def test_exp_and(self): assert Query("&(album = ate, artist = man)").search(self.s1) assert not Query("&(album = ate, artist = nam)").search(self.s1) assert not Query("&(album = tea, artist = nam)").search(self.s1) def test_exp_or(self): assert Query("|(album = ate, artist = man)").search(self.s1) assert Query("|(album = ate, artist = nam)").search(self.s1) assert not Query("&(album = tea, artist = nam)").search(self.s1) def test_dumb_search(self): assert Query("ate man").search(self.s1) assert Query("Ate man").search(self.s1) assert not Query("woo man").search(self.s1) assert not Query("not crazy").search(self.s1) def test_dumb_search_value(self): assert Query("|(ate, foobar)").search(self.s1) assert Query("!!|(ate, foobar)").search(self.s1) assert Query("&(ate, te)").search(self.s1) assert not Query("|(foo, bar)").search(self.s1) assert not Query("&(ate, foobar)").search(self.s1) assert not Query("! !&(ate, foobar)").search(self.s1) assert not Query("&blah").search(self.s1) assert Query("&blah oh").search(self.s5) assert Query("!oh no").search(self.s5) assert not Query("|blah").search(self.s1) # https://github.com/quodlibet/quodlibet/issues/1056 assert Query("&(ate, piman)").search(self.s1) def test_dumb_search_value_negate(self): assert Query("!xyz").search(self.s1) assert Query("!!!xyz").search(self.s1) assert Query(" !!!&(xyz, zyx)").search(self.s1) assert not Query("!man").search(self.s1) assert Query("&(tests,piman)").search(self.s1) assert Query("&(tests,!nope)").search(self.s1) assert not Query("&(tests,!!nope)").search(self.s1) assert not Query("&(tests,!piman)").search(self.s1) assert Query("&(tests,|(foo,&(pi,!nope)))").search(self.s1) def test_dumb_search_regexp(self): assert Query("/(x|H)ate/").search(self.s1) assert Query("'PiMan'").search(self.s1) assert not Query("'PiMan'c").search(self.s1) assert Query("!'PiMan'c").search(self.s1) assert not Query("!/(x|H)ate/").search(self.s1) def test_unslashed_search(self): assert Query("artist=piman").search(self.s1) assert Query(u"title=ång").search(self.s4) assert not Query("artist=mu").search(self.s1) assert not Query(u"title=äng").search(self.s4) def test_synth_search(self): assert Query("~dirname=/dir1/").search(self.s1) assert Query("~dirname=/dir2/").search(self.s2) assert not Query("~dirname=/dirty/").search(self.s1) assert not Query("~dirname=/dirty/").search(self.s2) def test_search_almostequal(self): a, b = AudioFile({"~#rating": 0.771}), AudioFile({"~#rating": 0.769}) assert Query("#(rating = 0.77)").search(a) assert Query("#(rating = 0.77)").search(b) def test_and_or_neg_operator(self): union = Query("|(foo=bar,bar=foo)") inter = Query("&(foo=bar,bar=foo)") neg = Query("!foo=bar") numcmp = Query("#(bar = 0)") tag = Query("foo=bar") tests = [inter | tag, tag | tag, neg | neg, tag | inter, neg | union, union | union, inter | inter, numcmp | numcmp, numcmp | union] assert not [x for x in tests if not isinstance(x, match.Union)] tests = [inter & tag, tag & tag, neg & neg, tag & inter, neg & union, union & union, inter & inter, numcmp & numcmp, numcmp & inter] assert not [x for x in tests if not isinstance(x, match.Inter)] assert isinstance(-neg, match.Tag) true = Query("") assert isinstance(true | inter, match.True_) assert isinstance(inter | true, match.True_) assert isinstance(true & inter, match.Inter) assert isinstance(inter & true, match.Inter) assert isinstance(true & true, match.True_) assert isinstance(true | true, match.True_) assert isinstance(-true, match.Neg) def test_filter(self): q = Query("artist=piman") assert q.filter([self.s1, self.s2]) == [self.s1] assert q.filter(iter([self.s1, self.s2])) == [self.s1] q = Query("") assert q.filter([self.s1, self.s2]), [self.s1 == self.s2] assert q.filter(iter([self.s1, self.s2])), [self.s1 == self.s2] def test_match_all(self): assert Query("").matches_all assert Query(" ").matches_all assert not Query("foo").matches_all def test_utf8(self): # also handle undecoded values assert Query(u"utf8=Ångström").search(self.s4) def test_fs_utf8(self): assert Query(u"~filename=foü.ogg").search(self.s3) assert Query(u"~filename=öä").search(self.s3) assert Query(u"~dirname=öäü").search(self.s3) assert Query(u"~basename=ü.ogg").search(self.s3) def test_filename_utf8_fallback(self): assert Query(u"filename=foü.ogg").search(self.s3) assert Query(u"filename=öä").search(self.s3) def test_mountpoint_utf8_fallback(self): assert Query(u"mountpoint=foü").search(self.s3) assert Query(u"mountpoint=öä").search(self.s3) def test_mountpoint_no_value(self): af = AudioFile({"~filename": fsnative(u"foo")}) assert not Query(u"~mountpoint=bla").search(af) def test_star_numeric(self): with pytest.raises(ValueError): Query(u"foobar", star=["~#mtime"]) def test_match_diacriticals_explcit(self): assert Query(u'title=angstrom').search(self.s4) assert not Query(u'title="Ångstrom"').search(self.s4) assert Query(u'title="Ångstrom"d').search(self.s4) assert Query(u'title=Ångström').search(self.s4) assert Query(u'title="Ångström"').search(self.s4) assert Query(u'title=/Ångström/').search(self.s4) assert Query(u'title="Ångstrom"d').search(self.s4) assert Query(u'title=/Angstrom/d').search(self.s4) assert Query(u'""d').search(self.s4) def test_match_diacriticals_dumb(self): assert Query(u'Angstrom').search(self.s4) assert Query(u'Ångström').search(self.s4) assert Query(u'Ångstrom').search(self.s4) assert not Query(u'Ängström').search(self.s4) def test_match_diacriticals_invalid_or_unsupported(self): # these fall back to test dumb searches: # invalid regex Query(u'/Sigur [r-zos/d') # group refs unsupported for diacritic matching Query(u'/(<)?(\\w+@\\w+(?:\\.\\w+)+)(?(1)>)/d') def test_numexpr(self): assert Query("#(length = 224)").search(self.s1) assert Query("#(length = 3:44)").search(self.s1) assert Query("#(length = 3 minutes + 44 seconds)").search(self.s1) assert Query("#(playcount > skipcount)").search(self.s1) assert Query("#(playcount < 2 * skipcount)").search(self.s1) assert Query("#(length > 3 minutes)").search(self.s1) assert Query("#(3:00 < length < 4:00)").search(self.s1) assert Query("#(40 seconds < length/5 < 1 minute)").search(self.s1) assert Query("#(2+3 * 5 = 17)").search(self.s1) assert Query("#(playcount / 0 > 0)").search(self.s1) assert not Query("#(track + 1 != 13)").search(self.s2) def test_numexpr_date(self): assert Query("#(length < 2005-07-19)").search(self.s1) assert Query("#(date > 2005-07-19)").search(self.s1) assert Query("#(2005-11-24 < 2005-07-19)").search(self.s1) assert Query("#(date = (2007-05-19) + 5 days)").search(self.s1) assert Query("#(date - 5 days = 2007-05-19)").search(self.s1) assert Query("#(2010-02-18 > date)").search(self.s1) assert Query("#(2010 > date)").search(self.s1) assert Query("#(date > 4)").search(self.s1) assert Query("#(date > 0004)").search(self.s1) assert Query("#(date > 0000)").search(self.s1) def test_large_numbers(self): assert Query("#(playcount = 00024)").search(self.s1) assert Query("#(samplerate = 44100)").search(self.s1) def test_ignore_characters(self): try: config.set("browsers", "ignored_characters", "-") assert Query("Foo the Bar - mu").search(self.s2) config.set("browsers", "ignored_characters", "1234") assert Query("4Fo13o 2th2e3 4Bar4").search(self.s2) finally: config.reset("browsers", "ignored_characters") class TestQuery_get_type: def test_red(self): for p in ["a = /w", "|(sa#"]: assert Query(p).type == QueryType.INVALID def test_black(self): for p in ["a test", "more test hooray"]: assert Query(p).type == QueryType.TEXT def test_green(self): for p in ["a = /b/", "&(a = b, c = d)", "/abc/", "!x", "!&(abc, def)"]: assert Query(p).type == QueryType.VALID ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1692647462.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_query__match.py����������������������������������������������������������0000644�0001750�0001750�00000010015�14470740046�017441� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import pytest from quodlibet.formats import AudioFile from quodlibet.query._match import NumexprNow, numexprTagOrSpecial, Inter, True_, Neg from quodlibet.query._match import numexprUnit, ParseError, NumexprTag, Numcmp from quodlibet.util import parse_date from quodlibet.util.collection import Collection from tests import TestCase class TQueryInter(TestCase): def test_main(self): q = Inter([]) assert q.filter([1]) == [1] q = Inter([True_()]) assert q.filter([1]) == [1] q = Inter([True_(), True_()]) assert q.filter([1]) == [1] q = Inter([True_(), Neg(True_())]) assert q.filter([1]) == [] q = Inter([Neg(True_()), True_()]) assert q.filter([1]) == [] q = Inter([Neg(True_())]) assert q.filter([1]) == [] class TQueryMatch(TestCase): def test_numexpr_unit(self): assert numexprUnit(10, 'seconds').evaluate(None, 0, True) == 10 assert numexprUnit(10, 'minutes').evaluate(None, 0, True) == 10 * 60 assert numexprUnit(1, 'year').evaluate(None, 0, True) == 365 * 24 * 60 * 60 assert numexprUnit(3, 'k').evaluate(None, 0, True) == 3 * 1024 assert numexprUnit(3, 'megabytes').evaluate(None, 0, True) == 3 * 1024 ** 2 def test_numexpr_raises_for_invalid_units(self): with pytest.raises(ParseError): numexprUnit(7, 'invalid unit') def test_time_tag(self): time = 424242 song = AudioFile({'~#added': 400000, '~#mtime': 410000, '~#length': 315}) added_value = NumexprTag('added').evaluate(song, time, True) assert added_value == 24242 assert NumexprTag('length').evaluate(song, time, True) == 315 assert NumexprTag('date').evaluate(song, time, True) is None assert added_value > NumexprTag('mtime').evaluate(song, time, True) def test_date_tag(self): time = 424242 song = AudioFile({'date': '2012-11-09'}) date_value = NumexprTag('date').evaluate(song, 0, True) assert date_value == parse_date('2012-11-09') assert NumexprTag('date').evaluate(song, time, True) == parse_date('2012-11-09') assert date_value > parse_date('2012-11-08') assert date_value < parse_date('2012-11-10') def test_numexpr_func(self): time = 424242 col = Collection() col.songs = (AudioFile({'~#added': 400000, '~#length': 315}), AudioFile({'~#added': 405000, '~#length': 225})) assert NumexprTag('length:avg').evaluate(col, time, True) == 270 assert NumexprTag('added:max').evaluate(col, time, True) == 19242 def test_numcmp_with_aggregate_and_units(self): col = Collection() col.songs = (AudioFile({'~#length': 30}), AudioFile({'~#length': 210})) min_length = NumexprTag('length:min') max_length = NumexprTag('length:max') avg_length = NumexprTag('length:avg') assert Numcmp(min_length, ">", numexprUnit(10, "seconds")) assert Numcmp(min_length, "<", numexprUnit(2, "minutes")) assert Numcmp(max_length, "<", numexprUnit(1, "hour")) assert Numcmp(max_length, ">=", numexprUnit(30, "seconds")) assert Numcmp(avg_length, "=", numexprUnit(2, "minutes")) def test_numexpr_now(self): time = 424242 day = 24 * 60 * 60 now_none = NumexprNow().evaluate(None, time, True) assert now_none == time today_none = NumexprNow(day).evaluate(None, time, True) assert today_none == time - day assert now_none == numexprTagOrSpecial('now').evaluate(None, time, True) assert today_none == numexprTagOrSpecial('today').evaluate(None, time, True) assert repr(NumexprNow()) == repr(numexprTagOrSpecial('now')) assert repr(NumexprTag('genre')) == repr(numexprTagOrSpecial('genre')) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_remote.py����������������������������������������������������������������0000664�0001750�0001750�00000012213�14231604332�016250� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import sys from pathlib import Path from unittest import mock import pytest from gi.repository import GLib, Gio from senf import fsn2bytes, bytes2fsn from . import TestCase, skipIf from .helper import temp_filename import quodlibet from quodlibet.remote import QuodLibetUnixRemote from quodlibet.util import is_windows QLPATH = str(Path(quodlibet.__file__).resolve().parent.parent) class Mock: def __init__(self, resp=None): self.lines = [] self.resp = resp def handle_line(self, app, line): self.lines.append(line) return self.resp @skipIf(is_windows(), "unix only") class TUnixRemote(TestCase): def test_fifo(self): mock = Mock() remote = QuodLibetUnixRemote(None, mock) remote._callback(b"foo\n") remote._callback(b"bar\nbaz") self.assertEqual( mock.lines, [bytes2fsn(b, None) for b in [b"foo", b"bar", b"baz"]]) def test_response(self): with temp_filename() as fn: mock = Mock(resp=bytes2fsn(b"resp", None)) remote = QuodLibetUnixRemote(None, mock) remote._callback(b"\x00foo\x00" + fsn2bytes(fn, None) + b"\x00") self.assertEqual(mock.lines, [bytes2fsn(b"foo", None)]) with open(fn, "rb") as h: self.assertEqual(h.read(), b"resp") @skipIf(is_windows(), "unix only") class TUnixRemoteFifoFullCycle(TestCase): @pytest.fixture(autouse=True) def tmp_fifo_path(self, tmp_path): self.registry = Mock(resp=bytes2fsn(b"response", None)) self.tmp_path = tmp_path with mock.patch.object(QuodLibetUnixRemote, "_PATH", str(tmp_path / "control")): yield def _send_message_remote_proc(self, msg, callback): """Execute QuodLibetUnixRemote.send_message() in a child process""" # Using a child process is the only way to execute send_message, as it # can only be run on the main thread, and blocks waiting for the # response. It can't be run in a separate thread, because it uses # signals to handle timeouts and we can't run the GLib mainloop in a # thread as Gtk has already been initialised on the Python main thread. # Attempting to use the loop in a thread leads to segfaults. temp_script = self.tmp_path / "send_message.py" with temp_script.open("w") as fpy: fpy.write( f"""\ import sys import traceback from quodlibet.remote import QuodLibetUnixRemote QuodLibetUnixRemote._PATH = {QuodLibetUnixRemote._PATH!r} msg = sys.stdin.read() try: result = QuodLibetUnixRemote.send_message(msg) except Exception: traceback.print_exc(file=sys.stderr) else: sys.stdout.buffer.write(result) sys.stdout.flush() """ ) def finished(proc, result): try: success, stdout, stderr = proc.communicate_finish(result) except GLib.Error as ex: callback(None, ex) else: if not success: return if stderr.get_size(): callback(None, stderr.get_data().decode()) callback(stdout.get_data(), None) try: launcher = Gio.SubprocessLauncher.new( Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE | Gio.SubprocessFlags.STDIN_PIPE ) path = [QLPATH] if "PYTHONPATH" in os.environ: path.append(os.environ["PYTHONPATH"]) launcher.setenv("PYTHONPATH", ":".join(path), True) proc = launcher.spawnv([sys.executable, str(temp_script)]) input = GLib.Bytes.new(msg) proc.communicate_async(input, None, finished) except Exception as ex: callback(None, ex) def send_message(self, msg: str) -> bytes: """Send a message to a remote Runs the GLib main loop, with the QuodLibetUnixRemote listener active, sends it a message and waits for the response. """ result = error = None remote = None loop = GLib.MainLoop() def proc_callback(*res): nonlocal result, error result, error = res remote.stop() loop.quit() def run_receiver_and_remote(): nonlocal remote remote = QuodLibetUnixRemote(None, self.registry) remote.start() GLib.idle_add(self._send_message_remote_proc, msg, proc_callback) GLib.idle_add(run_receiver_and_remote) loop.run() if error is not None: if isinstance(error, str): pytest.fail(error, pytrace=False) raise error return result def test_remote_send_message(self): response = self.send_message(b"foo 42") self.assertEqual(self.registry.lines, [bytes2fsn(b"foo 42", None)]) self.assertEqual(response, b"response") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_session.py���������������������������������������������������������������0000664�0001750�0001750�00000001671�14035600052�016443� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, init_fake_app, destroy_fake_app from quodlibet import app from quodlibet import session from quodlibet.session import SessionError, iter_backends class TSession(TestCase): def setUp(self): init_fake_app() def tearDown(self): destroy_fake_app() def test_session(self): client = session.init(app) client.close() def test_all(self): for backend in iter_backends(): client = backend() try: client.open(app) except SessionError: pass else: client.close() client.close() �����������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1653812665.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_setup.py�����������������������������������������������������������������0000664�0001750�0001750�00000006333�14244626671�016141� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import shutil from pathlib import Path from tempfile import mkdtemp import pytest from _pytest.fixtures import fixture import quodlibet from gdist import (create_po, GDistribution, create_pot, update_po, po_stats, build_po, build_mo, install_mo) from quodlibet.util import get_module_dir from tests.test_po import has_gettext_util SRC_FILE = Path(get_module_dir(quodlibet)).parent / "quodlibet.py" @fixture def dist(temp_po_dir) -> GDistribution: dist = GDistribution() dist.packages = [] dist.po_directory = str(temp_po_dir) return dist @fixture def temp_po_dir() -> Path: out_path = Path(mkdtemp()) po_path = out_path / "po" po_path.mkdir() with open(po_path / "POTFILES.in", "w") as f: f.write(f"{SRC_FILE.name}\n") shutil.copy(SRC_FILE, out_path / SRC_FILE.name) yield po_path shutil.rmtree(po_path) @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") class TestPoCommands: def test_create_po_command(self, dist): cmd = create_po(dist) cmd.lang = "fr_FR" cmd.run() def test_create_pot_command(self, dist): cmd = create_pot(dist) cmd.run() def test_update_po_command(self, dist, temp_po_dir): (temp_po_dir / "en_GB.po").touch() cmd = update_po(dist) cmd.lang = "en_GB" cmd.run() def test_po_stats_command(self, dist, temp_po_dir): cmd = po_stats(dist) cmd.lang = "en_GB" cmd.run() def test_build_po(self, dist): cmd = build_po(dist) cmd.run() def test_build_mo(self, dist, temp_po_dir): cmd = build_mo(dist) # Probably should create another dir, but this will do for now cmd.build_base = str(temp_po_dir) cmd.po_build_dir = str(temp_po_dir) cmd.run() def test_install_mo(self, dist, temp_po_dir): cmd = install_mo(dist) cmd.build_base = str(temp_po_dir) out = mkdtemp() # These need to exist for the command to succeed (Path(out) / "share" / "locale").mkdir(parents=True) (temp_po_dir / "share" / "locale").mkdir(parents=True) cmd.install_dir = out cmd.run() shutil.rmtree(out) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_soundcloudFile.py��������������������������������������������������������0000664�0001750�0001750�00000004526�14231604332�017744� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016-22 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from collections import defaultdict from quodlibet import config from quodlibet.browsers.soundcloud.api import SoundcloudApiClient from quodlibet.browsers.soundcloud.library import SoundcloudLibrary, SoundcloudFile from tests import TestCase TRACK_ID = 1234 class TSoundcloudFile(TestCase): class FakeClient(SoundcloudApiClient): def __init__(self): super().__init__() self.access_token = "abc" self.favoritings = defaultdict(int) self.unfavoritings = defaultdict(int) def _on_favorited(self, json, _data): super()._on_favorited(json) def save_favorite(self, track_id): self.favoritings[track_id] += 1 def remove_favorite(self, track_id): self.unfavoritings[track_id] += 1 @classmethod def setUpClass(cls): config.RATINGS = config.HardCodedRatingsPrefs() def setUp(self): SoundcloudLibrary.librarian = None self.client = self.FakeClient() def test_favoriting(self): client = self.client song = SoundcloudFile("http://uri", TRACK_ID, client, favorite=False) self.failIf(song.has_rating) song['~#rating'] = 1.0 self.failUnless(song.has_rating) self.failUnlessEqual(song("~#rating"), 1.0) song.write() self.failUnless(song.favorite) self.failUnlessEqual(client.favoritings[TRACK_ID], 1) self.failUnlessEqual(client.unfavoritings[TRACK_ID], 0) song.write() self.failUnlessEqual(client.favoritings[TRACK_ID], 1) def test_unfavoriting(self): client = self.client song = SoundcloudFile("http://uri", TRACK_ID, client, favorite=True) self.failUnless(song.has_rating) self.failUnlessEqual(song("~#rating"), 1.0) song['~#rating'] = 0.2 song.write() self.failIf(song.favorite) self.failUnlessEqual(client.unfavoritings[TRACK_ID], 1) self.failUnlessEqual(client.favoritings[TRACK_ID], 0) song.write() self.failUnlessEqual(client.unfavoritings[TRACK_ID], 1) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_soundcloudLibrary.py�����������������������������������������������������0000664�0001750�0001750�00000004521�14231604332�020464� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import json from pathlib import Path from quodlibet import config from quodlibet.browsers.soundcloud.api import SoundcloudApiClient from quodlibet.browsers.soundcloud.library import SoundcloudLibrary from quodlibet.browsers.soundcloud.query import SoundcloudQuery from tests import TestCase PERMALINK = "https://soundcloud.com/" "kerstineden/banging-techno-sets-098-kerstin-eden-02-2015" AVATAR_URL = u'https://i1.sndcdn.com/avatars-000127864033-q70sz6-large.jpg' TEST_DATA_PATH = Path(__file__).parent.parent / "tests" / "data" class TSoundcloudLibrary(TestCase): class FakeClient(SoundcloudApiClient): def get_tracks(self, query): self._on_track_data(None, [self._track], None) def __init__(self): super().__init__() with open(TEST_DATA_PATH / "soundcloud_track_response.json") as f: self._track = json.load(f) def authenticate_user(self): pass def setUp(self): SoundcloudLibrary.librarian = None self.lib = SoundcloudLibrary(self.FakeClient()) def tearDown(self): self.lib.destroy() @classmethod def setUpClass(cls): config.RATINGS = config.HardCodedRatingsPrefs() def test_parse(self): lib = self.lib lib.query_with_refresh(SoundcloudQuery("dummy search")) songs = list(lib._contents.values()) assert len(songs) == 1 s = songs[0] assert s("artist") == "ANDY C ram" assert s("date") == "2015-06-29" assert s("~year") == "2015" assert s("~#download_count") == 0 assert s("~#playback_count") == 363310 assert s("~#favoritings_count") == 10061 assert s("~#rating") == 1.0 assert s("~#playcount") == 4 assert int(s("~#bitrate")) == 128 def test_artwork_url(self): lib = SoundcloudLibrary(self.FakeClient()) lib.query_with_refresh(SoundcloudQuery("")) s = list(lib._contents.values())[0] url = s("artwork_url") assert url == "https://i1.sndcdn.com/artworks-000121689963-0b0pdr-t500x500.jpg" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_unisearch.py�������������������������������������������������������������0000664�0001750�0001750�00000015357�14035600052�016747� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import re import unicodedata from tests import TestCase from quodlibet.unisearch import compile from quodlibet.unisearch.db import diacritic_for_letters from quodlibet.unisearch.parser import re_replace_literals, re_add_variants class TUniSearch(TestCase): def test_mapping(self): cache = diacritic_for_letters(False) new = diacritic_for_letters(True) self.assertEqual(sorted(cache.items()), sorted(new.items())) def test_normalize_input(self): assert re.match( re_add_variants(unicodedata.normalize("NFD", u"ö")), u"ö") def test_re_replace(self): r = re_add_variants(u"aa") self.assertTrue(u"[" in r and u"]" in r and r.count(u"ä") == 2) def test_re_replace_multi(self): r = re_add_variants(u"ae") self.assertEqual(r, u"(?:[aàáâãäåāăąǎǟǡǻȁȃȧḁạảấầẩẫậắằẳẵặ]" u"[eèéêëēĕėęěȅȇȩḕḗḙḛḝẹẻẽếềểễệ]|[æǣǽ])") r = re_add_variants(u"SS") self.assertEqual(r, u"(?:[SŚŜŞŠȘṠṢṤṦṨꞄ][SŚŜŞŠȘṠṢṤṦṨꞄ]|ẞ)") r = re_add_variants(u"ss") self.assertEqual(r, u"(?:[sśŝşšșṡṣṥṧṩꞅ][sśŝşšșṡṣṥṧṩꞅ]|ß)") def test_punct(self): r = re_add_variants(u"'") assert "`" in r assert "'" in r r = re_add_variants(u"''") assert "\"" in r r = re_add_variants(u'"') assert "”" in r assert "“" in r r = re_add_variants(u'\\*') assert re.match(r, "*") def test_re_replace_multi_fixme(self): # we don't handler overlapping sequences, so this doesn't match "LỺ" r = re_add_variants(u"LLL") self.assertEqual(r, u"(?:[LĹĻĽḶḸḺḼŁ][LĹĻĽḶḸḺḼŁ]|Ỻ)[LĹĻĽḶḸḺḼŁ]") def test_re_replace_multi_nested(self): r = re_add_variants(u"(եւ)") self.assertEqual(r, u"((?:եւ|և))") r = re_add_variants(u"(եւ)+") self.assertEqual(r, u"((?:եւ|և))+") def test_re_replace_escape(self): r = re_add_variants(u"n\\n") self.assertEqual(r, u"[nñńņňǹṅṇṉṋʼn]\n") def test_construct_regexp(self): res = [ (u"\\.", None), (u"..", None), (u"\\.", None), (u"^a\aa[ha-z]k{1,3}h*h+h?(x|yy)(a+b|cd)$", None), (u"(?=Asimov)", None), (u"(?!Asimov)", None), (u"(?<=abc)def", None), (u"(?<!foo)", None), (u"(?#foo)", u""), (u"(.+) \1", None), (u"\\A\\b\\B\\d\\D\\s\\S\\w\\W\\Z\a", u"\\A\\b\\B[\\d][\\D][\\s][\\S][\\w][\\W]\\Z\a"), (u"a{3,5}?a+?a*?a??", None), (u"^foo$", None), (u"[-+]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?", u"[\\-\\+]?([\\d]+(\\.[\\d]*)?|\\.[\\d]+)([eE][\\-\\+]?[\\d]+)?"), (u"(\\$\\d*)", u"(\\$[\\d]*)"), (u"\\$\\.\\^\\[\\]\\:\\-\\+\\?\\\\", None), (u"[^a][^ab]", None), (u"[ab][abc]", None), (u"[.]", u"\\."), (u"[^a-z]", None), (u"[^a-z\\w]", None), ("(x|yy)", None), ] for r, o in res: if o is None: o = r self.assertEqual(re_replace_literals(r, {}), o) def test_construct_regexp_37_change(self): # Starting with 3.7 the parser throws out some subpattern # nodes. We try to recover them or test against the old and new result. res = [ (u"(?:foo)", ("(?:foo)", "foo")), (u"(?:foo)x", ("(?:foo)x", "foox")), (u"(?:foo)(?:bar)", ("(?:foo)(?:bar)", "foobar")), (u"(?:foo|bla)", None), (u"(?:foo|bla)x", None), ] for r, o in res: out = re_replace_literals(r, {}) if o is None: o = r if isinstance(o, tuple): assert out in o else: assert out == o def test_construct_regexp_broken(self): self.assertRaises(re.error, re_replace_literals, u"[", {}) self.assertRaises(NotImplementedError, re_replace_literals, u"(?P<quote>['\"]).*?(?P=quote)", {}) def test_seq(self): assert re_add_variants(u"[x-y]") == u"[ẋẍýÿŷȳẏẙỳỵỷỹx-y]" assert re_add_variants(u"[f-gm]") == u"[ḟꝼĝğġģǧǵḡᵹf-gmḿṁṃ]" assert re_add_variants(u"[^m]") == u"[^mḿṁṃ]" assert re_add_variants(u"[^m-m\\w]") == u"[^ḿṁṃm-m\\w]" assert re_add_variants(u"[^m-m]") == "[^ḿṁṃm-m]" assert re_add_variants(u"[^ö]") == u"[^ö]" assert re_add_variants(u"[LLL]") == u"[LĹĻĽḶḸḺḼŁ]" def test_literal(self): assert re_add_variants(u"f") == u"[fḟꝼ]" assert u"ø" in re_add_variants(u"o") assert u"Ø" in re_add_variants(u"O") assert re_add_variants(u"[^f]") == u"[^fḟꝼ]" class TCompileMatch(TestCase): def test_basics_default(self): assert compile(u"foo")(u"foo") assert compile(u"foo")(u"fooo") assert not compile(u"foo")(u"fo") def test_ignore_case(self): assert compile(u"foo", ignore_case=True)(u"Foo") assert not compile(u"foo", ignore_case=False)(u"Foo") def test_assert_dot_all(self): assert compile(u"a.b", dot_all=True)(u"a\nb") assert not compile(u"a.b", dot_all=False)(u"a\nb") assert compile(u"a.b", dot_all=False)(u"a b") def test_unicode_equivalence(self): assert compile(u"\u212B")(u"\u00C5") assert compile(u"\u00C5")(u"\u212B") assert compile(u"A\u030a")(u"\u00C5") assert compile(u"A\u030a")(u"\u212B") assert compile(u"o\u0308")(u"o\u0308") assert compile(u"o\u0308")(u"\xf6") assert compile(u"\xf6")(u"o\u0308") def test_assert_asym(self): assert compile(u"o", asym=True)(u"ö") assert not compile(u"o", asym=False)(u"ö") def test_assert_asym_unicode_equivalence(self): assert compile(u"A", asym=True)(u"\u00C5") assert compile(u"A\u030a", asym=True)(u"\u212B") assert compile(u"\u00C5", asym=True)(u"\u212B") assert compile(u"\u212B", asym=True)(u"\u00C5") def test_invalid(self): with self.assertRaises(ValueError): compile(u"(F", asym=False) with self.assertRaises(ValueError): compile(u"(F", asym=True) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_update.py����������������������������������������������������������������0000664�0001750�0001750�00000000637�14035600052�016243� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.update import UpdateDialog class TUpdateDialog(TestCase): def test_main(self): UpdateDialog(None).destroy() �������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684252533.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util.py������������������������������������������������������������������0000644�0001750�0001750�00000111611�14430723565�015745� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import uuid import tempfile import os import sys import threading import traceback import time import logging from pathlib import Path from senf import fsnative, fsn2bytes, bytes2fsn from quodlibet import _ from quodlibet.config import HardCodedRatingsPrefs, DurationFormat from quodlibet import config from quodlibet import util from quodlibet.util.dprint import print_exc, format_exception, extract_tb, \ PrintHandler from quodlibet.util import format_time_long as f_t_l, format_time_preferred, \ format_time_display, format_time_seconds from quodlibet.util import re_escape from quodlibet.util.library import set_scan_dirs, get_scan_dirs from quodlibet.util.path import \ parse_xdg_user_dirs, xdg_get_system_data_dirs, escape_filename, \ strip_win32_incompat_from_path, xdg_get_cache_home, \ xdg_get_data_home, unexpand, xdg_get_user_dirs, \ xdg_get_config_home, get_temp_cover_file, mkdir, mtime from quodlibet.util.string import decode, encode, split_escape, join_escape from quodlibet.util.environment import is_osx from . import TestCase, skipIf from .helper import capture_output, locale_numeric_conv, temp_filename is_win = os.name == "nt" class Tmkdir(TestCase): def test_exists(self): mkdir(".") def test_notdirectory(self): self.failUnlessRaises(OSError, mkdir, __file__) def test_manydeep(self): self.failUnless(not os.path.isdir("nonext")) t = tempfile.mkdtemp() path = os.path.join(t, "nonext", "test", "test2", "test3") mkdir(path) try: self.failUnless(os.path.isdir(path)) finally: os.rmdir(path) path = os.path.dirname(path) os.rmdir(path) path = os.path.dirname(path) os.rmdir(path) path = os.path.dirname(path) os.rmdir(path) os.rmdir(t) class Tgetcwd(TestCase): def test_Tgetcwd(self): self.assertTrue(isinstance(os.getcwd(), fsnative)) class Tmtime(TestCase): def test_equal(self): self.failUnlessEqual(mtime("."), os.path.getmtime(".")) def test_bad(self): self.failIf(os.path.exists("/dev/doesnotexist")) self.failUnlessEqual(mtime("/dev/doesnotexist"), 0) class Tformat_locale(TestCase): def test_format_int_locale(self): assert isinstance(util.format_int_locale(1024), str) def test_format_float_locale(self): assert isinstance(util.format_float_locale(1024.1024), str) def test_format_time_seconds(self): assert isinstance(util.format_time_seconds(1024), str) with locale_numeric_conv(): assert format_time_seconds(1024) == "1,024 seconds" assert format_time_seconds(1) == "1 second" class Tunexpand(TestCase): d = os.path.expanduser("~") u = unexpand(d) def test_base(self): path = unexpand(self.d) if is_win: self.failUnlessEqual(path, "%USERPROFILE%") else: self.failUnlessEqual(path, "~") def test_only_profile_case(self): assert isinstance(unexpand(os.path.expanduser(fsnative(u"~"))), fsnative) def test_base_trailing(self): path = unexpand(self.d + os.path.sep) self.failUnlessEqual(path, self.u + os.path.sep) def test_noprefix(self): path = unexpand(self.d + "foobar" + os.path.sep) self.failUnlessEqual(path, self.d + "foobar" + os.path.sep) def test_subfile(self): path = unexpand(os.path.join(self.d, "la", "la")) self.failUnlessEqual(path, os.path.join(self.u, "la", "la")) def test_case_insensitive_win(self): if is_win: assert unexpand(self.d.lower()) == "%USERPROFILE%" assert unexpand(self.d.upper()) == "%USERPROFILE%" class Tformat_rating(TestCase): def setUp(self): self.r = config.RATINGS = HardCodedRatingsPrefs() def test_empty(self): self.failUnlessEqual(util.format_rating(0, blank=False), "") def test_full(self): self.failUnlessEqual( len(util.format_rating(1, blank=False)), int(1 / self.r.precision)) def test_rating_length(self): config.RATINGS.number = 4 for i in range(0, int(1 / self.r.precision + 1)): self.failUnlessEqual( i, len(util.format_rating(i * self.r.precision, blank=False))) def test_bogus(self): max_length = int(1 / self.r.precision) self.failUnlessEqual(len(util.format_rating(2 ** 32 - 1, blank=False)), max_length) self.failUnlessEqual(len(util.format_rating(-4.2, blank=False)), 0) def test_blank_lengths(self): """Check that there are no unsuspected edge-cases for various rating precisions""" for self.r.number in [1, 5, 4, 3, 2]: steps = self.r.number self.failUnlessEqual(len(util.format_rating(1)), steps) self.failUnlessEqual(len(util.format_rating(0)), steps) self.failUnlessEqual(len(util.format_rating(0.5)), steps) self.failUnlessEqual(len(util.format_rating(1 / 3.0)), steps) def test_blank_values(self): self.r.number = 5 self.r.blank_symbol = "0" self.r.full_symbol = "1" # Easy ones first self.failUnlessEqual(util.format_rating(0.0), "00000") self.failUnlessEqual(util.format_rating(0.2), "10000") self.failUnlessEqual(util.format_rating(0.8), "11110") self.failUnlessEqual(util.format_rating(1.0), "11111") # A bit arbitrary, but standard behaviour self.failUnlessEqual(util.format_rating(0.51), "11100") # Test rounding down... self.failUnlessEqual(util.format_rating(0.6), "11100") # Test rounding up... self.failUnlessEqual(util.format_rating(0.91), "11111") # You never know... self.failUnlessEqual(util.format_rating(3.0), "11111") self.failUnlessEqual(util.format_rating(-0.5), "00000") class Tpango(TestCase): def test_escape_empty(self): self.failUnlessEqual(util.escape(""), "") def test_roundtrip(self): for s in ["foo&", "<&>", "&", "&", "<&testing&>amp;"]: esc = util.escape(s) self.failIfEqual(s, esc) self.failUnlessEqual(s, util.unescape(esc)) def test_unescape_empty(self): self.failUnlessEqual(util.unescape(""), "") def test_format(self): self.assertEqual(util.bold("foo"), "<b>foo</b>") self.assertEqual(util.italic("foo"), "<i>foo</i>") self.assertEqual(util.monospace("foo"), "<tt>foo</tt>") def test_format_escape(self): assert util.bold("foo & bar") == "<b>foo & bar</b>" assert util.italic("foo & bar") == "<i>foo & bar</i>" assert util.monospace("foo & bar") == "<tt>foo & bar</tt>" assert util.bold_italic("foo & bar") == "<b><i>foo & bar</i></b>" class Tre_esc(TestCase): def test_empty(self): self.failUnlessEqual(re_escape(b""), b"") self.assertTrue(isinstance(re_escape(b""), bytes)) def test_empty_unicode(self): self.failUnlessEqual(re_escape(u""), u"") self.assertTrue(isinstance(re_escape(u""), str)) def test_safe(self): self.failUnlessEqual(re_escape("fo o"), "fo o") def test_unsafe(self): self.failUnlessEqual(re_escape("!bar"), r"\!bar") def test_many_unsafe(self): self.failUnlessEqual( re_escape("*quux#argh?woo"), r"\*quux\#argh\?woo") class Tdecode(TestCase): def test_empty(self): self.failUnlessEqual(decode(b""), "") def test_safe(self): self.failUnlessEqual(decode(b"foo!"), "foo!") def test_invalid(self): self.failUnlessEqual( decode(b"fo\xde"), u'fo\ufffd [Invalid Encoding]') class Tencode(TestCase): def test_empty(self): self.failUnlessEqual(encode(""), b"") def test_unicode(self): self.failUnlessEqual(encode(u"abcde"), b"abcde") class Tcapitalize(TestCase): def test_empty(self): self.failUnlessEqual(util.capitalize(""), "") def test_firstword(self): self.failUnlessEqual(util.capitalize("aa b"), "Aa b") def test_preserve(self): self.failUnlessEqual(util.capitalize("aa B"), "Aa B") def test_nonalphabet(self): self.failUnlessEqual(util.capitalize("!aa B"), "!aa B") class Thuman_sort(TestCase): def smaller(self, x, y): return util.human_sort_key(x) < util.human_sort_key(y) def equal(self, x, y): return util.human_sort_key(x) == util.human_sort_key(y) def test_human(self): self.failUnlessEqual(self.smaller(u"2", u"15"), True) self.failUnlessEqual(self.smaller(u" 2", u"15 "), True) self.failUnlessEqual(self.smaller(u"a2 g", u"a 2z"), True) self.failUnlessEqual(self.smaller(u"a2zz", u"a2.1z"), True) self.failUnlessEqual(self.smaller(u"42o", u"42\xf6"), True) self.failUnlessEqual(self.smaller(u"42\xf6", u"42p"), True) self.failUnlessEqual(self.smaller(u"bbb", u"zzz3"), True) self.assertTrue(self.equal(" foo", "foo")) self.assertTrue(self.equal(" ", "")) self.assertTrue(self.smaller("", ".")) self.assertTrue(self.smaller("a", "b")) self.assertTrue(self.smaller("A", "b")) def test_false(self): # album browser needs that to sort albums without artist/title # to the bottom self.failIf(util.human_sort_key("")) def test_white(self): self.failUnlessEqual( util.human_sort_key(u" 3foo bar6 42.8"), util.human_sort_key(u"3 foo bar6 42.8 ")) self.failUnless(64.0 in util.human_sort_key(u"64. 8")) class Tformat_time(TestCase): def test_seconds(self): self.failUnlessEqual(util.format_time(0), "0:00") self.failUnlessEqual(util.format_time(59), "0:59") def test_minutes(self): self.failUnlessEqual(util.format_time(60), "1:00") self.failUnlessEqual(util.format_time(60 * 59 + 59), "59:59") def test_hourss(self): self.failUnlessEqual(util.format_time(60 * 60), "1:00:00") self.failUnlessEqual( util.format_time(60 * 60 + 60 * 59 + 59), "1:59:59") def test_negative(self): self.failUnlessEqual(util.format_time(-124), "-2:04") class Tparse_time(TestCase): def test_invalid(self): self.failUnlessEqual(util.parse_time("not a time"), 0) def test_except(self): self.failUnlessRaises(ValueError, util.parse_time, "not a time", None) def test_empty(self): self.failUnlessEqual(util.parse_time(""), 0) def test_roundtrip(self): # The values are the ones tested for Tformat_time, so we know they # will be formatted correctly. They're also representative of # all the major patterns. for i in [0, 59, 60, 60 * 59 + 59, 60 * 60, 60 * 60 + 60 * 59 + 59]: self.failUnlessEqual(util.parse_time(util.format_time(i)), i) def test_negative(self): self.failUnlessEqual(util.parse_time("-2:04"), -124) class Tparse_date(TestCase): def test_invalid(self): self.assertRaises(ValueError, util.parse_date, "not a date") self.assertRaises(ValueError, util.parse_date, "0") self.assertRaises(ValueError, util.parse_date, "2000-13") self.assertRaises(ValueError, util.parse_date, "2000-01-32") self.assertRaises(ValueError, util.parse_date, "2000-01-0") self.assertRaises(ValueError, util.parse_date, "2000-0-01") def test_valid(self): ref = time.mktime(time.strptime("2004", "%Y")) self.assertEqual(util.parse_date("2004"), ref) self.assertEqual(util.parse_date("2004-01-01"), ref) self.assertEqual(util.parse_date("2004-1-1"), ref) self.assertTrue( util.parse_date("2004-01-01") < util.parse_date("2004-01-02")) class Tdate_key(TestCase): def test_compare(self): date_key = util.date_key self.assertTrue(date_key("2004") == date_key("2004-01-01")) self.assertTrue(date_key("2004") == date_key("2004-01")) self.assertTrue(date_key("2004") < date_key("2004-01-02")) self.assertTrue(date_key("2099-02-02") < date_key("2099-03-30")) self.assertTrue(date_key("2004-01-foo") == date_key("2004-01")) def test_validate(self): validate = util.validate_query_date for valid in ["2004", "2005-01", "3000-3-4"]: self.assertTrue(validate(valid)) for invalid in ["", "-", "3000-", "9-0", "8-1-0", "1-13-1", "1-1-32", "1-1-1-1-1", "a", "1-a", "1-1-a"]: self.assertFalse(validate(invalid)) class Tformat_size(TestCase): def t_dict(self, d): for key, value in d.items(): formatted = util.format_size(key) self.failUnlessEqual(formatted, value) assert isinstance(formatted, str) def test_bytes(self): self.t_dict({0: "0 B", 1: "1 B", 1023: "1023 B"}) def test_kbytes(self): self.t_dict({ 1024: "1.00 KB", 1536: "1.50 KB", 10240: "10 KB", 15360: "15 KB" }) def test_mbytes(self): self.t_dict({ 1024 * 1024: "1.00 MB", 1024 * 1536: "1.50 MB", 1024 * 10240: "10.0 MB", 1024 * 15360: "15.0 MB", 123456 * 1024: "121 MB", 765432 * 1024: "747 MB"}) def test_gbytes(self): self.t_dict({ 1024 * 1024 * 1024: "1.0 GB", 1024 * 1024 * 1536: "1.5 GB", 1024 * 1024 * 10240: "10.0 GB", 1024 * 1024 * 15360: "15.0 GB" }) class Ttag(TestCase): def test_empty(self): self.failUnlessEqual(util.tag(""), "Invalid tag") def test_basic(self): self.failUnlessEqual(util.tag("title"), "Title") def test_basic_nocap(self): self.failUnlessEqual(util.tag("title", False), "title") def test_internal(self): self.failUnlessEqual(util.tag("~year"), "Year") def test_numeric(self): self.failUnlessEqual(util.tag("~#year"), "Year") def test_two(self): self.failUnlessEqual(util.tag("title~version"), "Title / Version") def test_two_nocap(self): self.failUnlessEqual( util.tag("title~version", False), "title / version") def test_precap_handling(self): self.failUnlessEqual(util.tag("labelid"), "Label ID") self.failUnlessEqual(util.tag("labelid", False), "label ID") class Ttagsplit(TestCase): def test_single_tag(self): self.failUnlessEqual(util.tagsplit("foo"), ["foo"]) def test_synth_tag(self): self.failUnlessEqual(util.tagsplit("~foo"), ["~foo"]) def test_two_tags(self): self.failUnlessEqual(util.tagsplit("foo~bar"), ["foo", "bar"]) def test_two_prefix(self): self.failUnlessEqual(util.tagsplit("~foo~bar"), ["foo", "bar"]) def test_synth(self): self.failUnlessEqual(util.tagsplit("~foo~~bar"), ["foo", "~bar"]) def test_numeric(self): self.failUnlessEqual(util.tagsplit("~#bar"), ["~#bar"]) def test_two_numeric(self): self.failUnlessEqual(util.tagsplit("~#foo~~#bar"), ["~#foo", "~#bar"]) def test_two_synth_start(self): self.failUnlessEqual( util.tagsplit("~~people~album"), ["~people", "album"]) class Tpattern(TestCase): def test_empty(self): self.failUnlessEqual(util.pattern(""), "") def test_basic(self): self.failUnlessEqual(util.pattern("<title>"), "Title") def test_basic_nocap(self): self.failUnlessEqual(util.pattern("<title>", False), "title") def test_internal(self): self.failUnlessEqual(util.pattern("<~plays>"), "Plays") def test_tied(self): self.failUnlessEqual(util.pattern("<~title~album>"), "Title - Album") def test_unknown(self): self.failUnlessEqual(util.pattern("<foobarbaz>"), "Foobarbaz") def test_condition(self): self.failUnlessEqual(util.pattern("<~year|<~year> - <album>|<album>>"), "Year - Album") def test_escape(self): self.failUnlessEqual(util.pattern(r"\<i\><&>\</i\>", esc=True), "<i>&</i>") def test_invalid(self): self.failUnlessEqual(util.pattern("<date"), "") util.pattern("<d\\") def test_complex_condition(self): self.assertEqual(util.pattern(r"<#(bitrate \> 150)|HQ|LQ>"), "LQ") def test_escape_condition(self): self.assertEqual( util.pattern(r"<~filename=/\/adsad\/sadads/|BLA|BLU>"), "BLU") class Tformat_time_long(TestCase): def test_second(s): s.assertEquals(f_t_l(1).split(", ")[0], _("1 second")) def test_seconds(s): s.assertEquals(f_t_l(2).split(", ")[0], _("%d seconds") % 2) def test_notminutes(s): s.assertEquals(f_t_l(59).split(", ")[0], _("%d seconds") % 59) def test_minute(s): s.assertEquals(f_t_l(60), _("1 minute")) def test_minutes(s): s.assertEquals(f_t_l(120).split(", ")[0], _("%d minutes") % 2) def test_nothours(s): s.assertEquals(f_t_l(3599).split(", ")[0], _("%d minutes") % 59) def test_hour(s): s.assertEquals(f_t_l(3600), _("1 hour")) def test_hours(s): s.assertEquals(f_t_l(7200), _("%d hours") % 2) def test_notdays(s): s.assertEquals(f_t_l(86399).split(", ")[0], _("%d hours") % 23) def test_seconds_dropped(s): s.assertEquals(len(f_t_l(3601).split(", ")), 2) def test_day(s): s.assertEquals(f_t_l(86400), _("1 day")) def test_days(s): s.assertEquals(f_t_l(172800).split(", ")[0], _("%d days") % 2) def test_notyears(s): s.assertEquals(f_t_l(31535999).split(", ")[0], _("%d days") % 364) def test_year(s): s.assertEquals(f_t_l(31536000), _("1 year")) def test_years(s): s.assertEquals(f_t_l(63072000).split(", ")[0], _("%d years") % 2) def test_drop_zero(s): s.assertEquals(f_t_l(3601), ", ".join([_("1 hour"), _("1 second")])) def test_limit_zero(s): s.assertEquals(f_t_l(1, limit=0), _("1 second")) def test_limit(s): s.assertEquals(len(f_t_l(2 ** 31).split(", ")), 2) class TFormatTimePreferred(TestCase): def test_default_setting_is_standard(s): s.assertEquals(config.DURATION.format, DurationFormat.STANDARD) def test_raw_config_is_standard(s): s.assertEquals(config.get('display', 'duration_format'), DurationFormat.STANDARD) def test_acts_like_long(s): s._fuzz_loop(format_time_preferred, f_t_l) def _fuzz_loop(s, f, f2): x = 1 while x < 100000000: s.assertEquals(f(x), f2(x)) x = x * 3 / 2 + 1 def test_acts_like_display(s): def fmt_numeric(x): return format_time_preferred(x, DurationFormat.NUMERIC) s._fuzz_loop(fmt_numeric, format_time_display) def test_seconds(s): def fmt_seconds(x): return format_time_preferred(x, DurationFormat.SECONDS) s._fuzz_loop(fmt_seconds, format_time_seconds) class Tspawn(TestCase): def test_simple(self): if is_win: return self.failUnless(util.spawn(["ls", "."], stdout=True)) def test_invalid(self): from gi.repository import GLib self.failUnlessRaises(GLib.GError, util.spawn, ["not a command"]) def test_get_output(self): if is_win: return fileobj = util.spawn(["echo", "'$1'", '"$2"', ">3"], stdout=True) self.failUnlessEqual(fileobj.read().split(), ["'$1'", '"$2"', ">3"]) class Txdg_dirs(TestCase): def test_system_data_dirs_posix(self): if is_win: return os.environ["XDG_DATA_DIRS"] = "/xyz" self.failUnlessEqual(xdg_get_system_data_dirs()[0], "/xyz") del os.environ["XDG_DATA_DIRS"] dirs = xdg_get_system_data_dirs() self.failUnlessEqual(dirs[0], "/usr/local/share/") self.failUnlessEqual(dirs[1], "/usr/share/") def test_data_home(self): if is_win: return os.environ["XDG_DATA_HOME"] = "/xyz" self.failUnlessEqual(xdg_get_data_home(), "/xyz") del os.environ["XDG_DATA_HOME"] should = os.path.join(os.path.expanduser("~"), ".local", "share") self.failUnlessEqual(xdg_get_data_home(), should) def test_get_user_dirs(self): xdg_get_user_dirs() def test_parse_xdg_user_dirs(self): data = b'# foo\nBLA="$HOME/blah"\n' vars_ = parse_xdg_user_dirs(data) self.assertTrue(b"BLA" in vars_) expected = os.path.join(os.environ.get("HOME", ""), "blah") self.assertEqual(vars_[b"BLA"], expected) vars_ = parse_xdg_user_dirs(b'BLA="$HOME/"') self.assertTrue(b"BLA" in vars_) self.assertEqual(vars_[b"BLA"], os.environ.get("HOME", "")) # some invalid self.assertFalse(parse_xdg_user_dirs(b"foo")) self.assertFalse(parse_xdg_user_dirs(b"foo=foo bar")) self.assertFalse(parse_xdg_user_dirs(b"foo='foo")) def test_on_windows(self): self.assertTrue(xdg_get_system_data_dirs()) self.assertTrue(xdg_get_cache_home()) self.assertTrue(xdg_get_data_home()) self.assertTrue(xdg_get_config_home()) class Tlibrary(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_basic(self): self.failIf(get_scan_dirs()) if os.name == "nt": set_scan_dirs([u"C:\\foo", u"D:\\bar", u""]) self.failUnlessEqual(get_scan_dirs(), [u"C:\\foo", u"D:\\bar"]) else: set_scan_dirs(["foo", "bar", ""]) self.failUnlessEqual(get_scan_dirs(), ["foo", "bar"]) class TNormalizePath(TestCase): def test_default(self): from quodlibet.util.path import normalize_path as norm name = norm(tempfile.mkdtemp()) try: self.failUnlessEqual(norm(name), name) self.failUnlessEqual(norm(os.path.join(name, "foo", "..")), name) finally: os.rmdir(name) def test_types(self): from quodlibet.util.path import normalize_path assert isinstance(normalize_path(fsnative(u"foo"), False), fsnative) assert isinstance(normalize_path("foo", False), fsnative) assert isinstance(normalize_path(fsnative(u"foo"), True), fsnative) assert isinstance(normalize_path("foo", True), fsnative) def test_canonicalise(self): from quodlibet.util.path import normalize_path as norm f, path = tempfile.mkstemp() path = os.path.realpath(path) # on osx tmp is a symlink os.close(f) path = norm(path) link_dir = tempfile.mkdtemp() link = None if not is_win: link = os.path.join(link_dir, str(uuid.uuid4())) os.symlink(path, link) try: self.failUnlessEqual(norm(path, canonicalise=True), path) self.failUnlessEqual(norm(os.path.join(path, "foo", ".."), True), path) if link: self.failUnlessEqual(norm(link, True), path) # A symlink shouldn't be resolved unless asked for self.failIfEqual(norm(link, False), path) # And the other behaviour should also work unnormalised_path = os.path.join(link, "foo", "..") self.failUnlessEqual(norm(unnormalised_path, True), path) finally: if link: os.remove(link) os.remove(path) os.rmdir(link_dir) def test_pathlib_is_equivalent(self): from quodlibet.util.path import normalize_path with temp_filename() as fn: assert normalize_path(Path(fn)) == normalize_path(fn) with temp_filename() as fn: path = Path(fn) assert normalize_path(path / "./..") == normalize_path(fn + "./..") assert normalize_path(path / ".." / path.name) == normalize_path(path) class Tescape_filename(TestCase): def test_str(self): result = escape_filename("\x00\x01") self.assertEqual(result, "%00%01") self.assertTrue(isinstance(result, fsnative)) def test_unicode(self): result = escape_filename(u'abc\xe4') self.assertEqual(result, "abc%C3%A4") self.assertTrue(isinstance(result, fsnative)) def test_safe_chars(self): result = escape_filename('1, 2, and -3', safe=' -') self.assertEqual(result, "1%2C 2%2C and -3") self.assertTrue(isinstance(result, fsnative)) @skipIf(is_win, "not on Windows") class Tload_library(TestCase): # This started breaking on newer osx in CI # I suspect it is https://bugs.python.org/issue44689 # so could be re-tried with newer Python @skipIf(is_osx(), "broken on osx") def test_libc(self): lib, name = util.load_library(["c"]) self.assertEqual(name, "c") lib2, name = util.load_library(["c"]) self.assertTrue(lib is lib2) lib3, name = util.load_library(["c"], shared=False) self.assertTrue(lib2 is not lib3) def test_glib(self): if sys.platform == "darwin": fn = "libglib-2.0.0.dylib" else: fn = "libglib-2.0.so.0" lib, name = util.load_library([fn]) self.assertEqual(name, fn) self.assertTrue(lib) class Tstrip_win32_incompat_from_path(TestCase): def test_types(self): v = strip_win32_incompat_from_path(fsnative(u"")) self.assertTrue(isinstance(v, fsnative)) v = strip_win32_incompat_from_path(fsnative(u"foo")) self.assertTrue(isinstance(v, fsnative)) v = strip_win32_incompat_from_path(u"") self.assertTrue(isinstance(v, str)) v = strip_win32_incompat_from_path(u"foo") self.assertTrue(isinstance(v, str)) def test_basic(self): if is_win: v = strip_win32_incompat_from_path(u"C:\\foo\\<>/a") self.assertEqual(v, u"C:\\foo\\___a") else: v = strip_win32_incompat_from_path("/foo/<>a") self.assertEqual(v, "/foo/__a") class TPathHandling(TestCase): def test_main(self): v = fsnative(u"foo") self.assertTrue(isinstance(v, fsnative)) v3 = bytes2fsn(fsn2bytes(v, "utf-8"), "utf-8") self.assertTrue(isinstance(v3, fsnative)) self.assertEqual(v, v3) class Tget_temp_cover_file(TestCase): def test_main(self): fobj = get_temp_cover_file(b"foobar") try: self.assertTrue(isinstance(fobj.name, fsnative)) finally: fobj.close() class Tsplit_escape(TestCase): def test_split_escape(self): # from mutagen inout = [ (("", ":"), [""]), ((":", ":"), ["", ""]), ((":", ":", 0), [":"]), ((":b:c:", ":", 0), [":b:c:"]), ((":b:c:", ":", 1), ["", "b:c:"]), ((":b:c:", ":", 2), ["", "b", "c:"]), ((":b:c:", ":", 3), ["", "b", "c", ""]), (("a\\:b:c", ":"), ["a:b", "c"]), (("a\\\\:b:c", ":"), ["a\\", "b", "c"]), (("a\\\\\\:b:c\\:", ":"), ["a\\:b", "c:"]), (("\\", ":"), [""]), (("\\\\", ":"), ["\\"]), (("\\\\a\\b", ":"), ["\\a\\b"]), ] for inargs, out in inout: self.assertEqual(split_escape(*inargs), out) def test_types(self): parts = split_escape(b"\xff:\xff", b":") self.assertEqual(parts, [b"\xff", b"\xff"]) self.assertTrue(isinstance(parts[0], bytes)) parts = split_escape(u"a:b", u":") self.assertEqual(parts, [u"a", u"b"]) self.assertTrue(all(isinstance(p, str) for p in parts)) parts = split_escape(u"", u":") self.assertEqual(parts, [u""]) self.assertTrue(all(isinstance(p, str) for p in parts)) parts = split_escape(u":", u":") self.assertEqual(parts, [u"", u""]) self.assertTrue(all(isinstance(p, str) for p in parts)) def test_join_escape_types(self): self.assertEqual(join_escape([], b":"), b"") self.assertTrue(isinstance(join_escape([], b":"), bytes)) self.assertTrue(isinstance(join_escape([], u":"), str)) self.assertEqual(join_escape([b"\xff", b"\xff"], b":"), b"\xff:\xff") self.assertEqual(join_escape([u'\xe4', u'\xe4'], ":"), u'\xe4:\xe4') def test_join_escape(self): self.assertEqual(join_escape([b":"], b":"), b"\\:") self.assertEqual(join_escape([b"\\:", b":"], b":"), b"\\\\\\::\\:") def test_roundtrip(self): values = [b"\\:", b":"] joined = join_escape(values, b":") self.assertEqual(split_escape(joined, b":"), values) class TMainRunner(TestCase): def test_abort_before_call(self): runner = util.MainRunner() def worker(): self.assertRaises( util.MainRunnerAbortedError, runner.call, lambda: None) thread = threading.Thread(target=worker) runner.abort() thread.start() thread.join() def test_timeout(self): runner = util.MainRunner() def worker(): self.assertRaises( util.MainRunnerTimeoutError, runner.call, lambda: None, timeout=0.00001) for i in range(3): thread = threading.Thread(target=worker) thread.start() thread.join() runner.abort() def test_call_exception(self): from gi.repository import GLib runner = util.MainRunner() loop = GLib.MainLoop() def func(): raise KeyError def worker(): try: self.assertRaises(util.MainRunnerError, runner.call, func) finally: loop.quit() thread = threading.Thread(target=worker) thread.start() loop.run() runner.abort() thread.join() def test_from_main_loop(self): from gi.repository import GLib runner = util.MainRunner() loop = GLib.MainLoop() def in_main_loop(): try: self.assertRaises( util.MainRunnerError, runner.call, lambda: None, foo=0) self.assertEqual( runner.call(lambda i: i + 1, 42, priority=0), 43) self.assertEqual(runner.call(lambda i: i - 1, 42), 41) finally: loop.quit() GLib.idle_add(in_main_loop) loop.run() def test_ok(self): from gi.repository import GLib runner = util.MainRunner() loop = GLib.MainLoop() def func(i): self.assertTrue(util.is_main_thread()) return i + 1 def worker(): try: self.assertEqual(runner.call(func, 42), 43) finally: loop.quit() thread = threading.Thread(target=worker) thread.start() loop.run() thread.join() runner.abort() def test_multi_abort(self): runner = util.MainRunner() runner.abort() runner.abort() def worker(): self.assertRaises(util.MainRunnerError, runner.call, lambda: None) thread = threading.Thread(target=worker) thread.start() thread.join() class Tconnect_destroy(TestCase): def test_main(self): from gi.repository import Gtk b = Gtk.Button() class A(Gtk.Button): def foo(self): pass a = A() ref = sys.getrefcount(a) util.connect_destroy(b, "clicked", a.foo) self.assertEqual(sys.getrefcount(a), ref + 1) a.destroy() self.assertEqual(sys.getrefcount(a), ref) class Tcached_property(TestCase): def test_main(self): class A: @util.cached_property def foo(self): return object() a = A() first = a.foo self.assertTrue(first is a.foo) del a.__dict__["foo"] self.assertFalse(first is a.foo) def test_dunder(self): def define_class(): class A: @util.cached_property def __foo_(self): return object() self.assertRaises(AssertionError, define_class) @util.enum class Foo(str): FOO = "blah" BAR = "not foo" BAZ = "baz!" class Tenum(TestCase): def test_main(self): @util.enum class IntFoo(int): FOO = 0 BAR = 1 self.assertTrue(issubclass(IntFoo, int)) self.assertTrue(isinstance(IntFoo.BAR, IntFoo)) self.assertTrue(isinstance(IntFoo.FOO, IntFoo)) self.assertEqual(IntFoo.FOO, 0) self.assertEqual(IntFoo.BAR, 1) def test_str(self): self.assertTrue(issubclass(Foo, str)) self.assertTrue(isinstance(Foo.BAR, Foo)) self.assertEqual(Foo.FOO, "blah") self.assertEqual(repr(Foo.BAR), "Foo.BAR") def test_values(self): self.assertEqual(Foo.values, {Foo.FOO, Foo.BAR, Foo.BAZ}) def test_value_of(self): self.assertEqual(Foo.value_of("blah"), Foo.FOO) self.assertEqual(Foo.value_of("baz!"), Foo.BAZ) def test_value_of_raises_for_unknown(self): self.assertRaises(ValueError, Foo.value_of, "??") def test_value_of_uses_default(self): self.assertEquals(Foo.value_of("??", "default"), "default") class Tlist_unique(TestCase): def test_main(self): self.assertEqual(util.list_unique([]), []) self.assertEqual(util.list_unique(iter([])), []) self.assertEqual(util.list_unique([1, 2, 3]), [1, 2, 3]) self.assertEqual(util.list_unique([1, 2, 1, 4]), [1, 2, 4]) self.assertEqual(util.list_unique([1, 1, 1, 2]), [1, 2]) class Treraise(TestCase): def test_reraise(self): try: try: raise ValueError("foo") except Exception as e: util.reraise(TypeError, e) except Exception as e: self.assertTrue(isinstance(e, TypeError)) self.assertTrue("ValueError" in traceback.format_exc()) else: self.assertTrue(False) class Tenviron(TestCase): def test_main(self): for v in os.environ.values(): if os.name == "nt": self.assertTrue(isinstance(v, str)) else: self.assertTrue(isinstance(v, str)) class Tget_module_dir(TestCase): def test_self(self): path = util.get_module_dir() self.assertTrue(isinstance(path, fsnative)) self.assertTrue(os.path.exists(path)) def test_other(self): path = util.get_module_dir(util) self.assertTrue(isinstance(path, fsnative)) self.assertTrue(os.path.exists(path)) class Tget_ca_file(TestCase): def test_main(self): path = util.get_ca_file() if path is not None: self.assertTrue(isinstance(path, fsnative)) self.assertTrue(os.path.exists(path)) class Tprint_exc(TestCase): def test_main(self): try: 1 / 0 except: with capture_output(): print_exc() def test_pass_exc_info(self): try: 1 / 0 except: with capture_output(): print_exc(exc_info=sys.exc_info(), context="foo") class TPrintHandler(TestCase): def test_main(self): handler = PrintHandler() for level in range(0, 70, 10): record = logging.LogRecord( "foo", level, "a.py", 45, "bar", None, None) with capture_output(): handler.handle(record) class Tformat_exception(TestCase): def test_main(self): try: 1 / 0 except: result = format_exception(*sys.exc_info()) self.assertTrue(isinstance(result, list)) self.assertTrue(all([isinstance(l, str) for l in result])) class Textract_tb(TestCase): def test_main(self): try: 1 / 0 except: result = extract_tb(sys.exc_info()[2]) self.assertTrue(isinstance(result, list)) for fn, l, fu, text in result: self.assertTrue(isinstance(fn, fsnative)) self.assertTrue(isinstance(l, int)) self.assertTrue(isinstance(fu, str)) self.assertTrue(isinstance(text, str)) def test_capture_output(): with capture_output() as (o, e): sys.stdout.write("foo") sys.stderr.write("bar") assert o.getvalue() == "foo" assert e.getvalue() == "bar" # also make sure sys.stdout.buffer exists and works, # for completeness with capture_output() as (o, e): sys.stdout.write("foo") sys.stdout.buffer.write(b"bar") sys.stderr.write("baz") sys.stderr.buffer.write(b"quux") assert o.getvalue() == "foobar" assert e.getvalue() == "bazquux" # newlines are preserved as is with capture_output() as (o, e): sys.stdout.write("a\nb\r\nc\rd") assert o.getvalue() == "a\nb\r\nc\rd" �����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_atomic.py�����������������������������������������������������������0000664�0001750�0001750�00000004737�14035600052�017277� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os import stat import shutil from tests import TestCase, mkdtemp from quodlibet.util.atomic import atomic_save class Tatomic_save(TestCase): def setUp(self): self.dir = mkdtemp() def tearDown(self): shutil.rmtree(self.dir) def test_basic(self): filename = os.path.join(self.dir, "foo.txt") with open(filename, "wb") as fobj: fobj.write(b"nope") with atomic_save(filename, "wb") as fobj: fobj.write(b"foo") temp_name = fobj.name with open(filename, "rb") as fobj: self.assertEqual(fobj.read(), b"foo") self.assertFalse(os.path.exists(temp_name)) self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) def test_non_exist(self): filename = os.path.join(self.dir, "foo.txt") with atomic_save(filename, "wb") as fobj: fobj.write(b"foo") temp_name = fobj.name with open(filename, "rb") as fobj: self.assertEqual(fobj.read(), b"foo") self.assertFalse(os.path.exists(temp_name)) self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) def test_readonly(self): filename = os.path.join(self.dir, "foo.txt") with open(filename, "wb") as fobj: fobj.write(b"nope") dir_mode = os.stat(self.dir).st_mode file_mode = os.stat(filename).st_mode # setting directory permissions doesn't work under Windows, so make # the file read only, so the rename fails. On the other hand marking # the file read only doesn't make rename fail on unix, so make the # directory read only as well. os.chmod(filename, stat.S_IREAD) os.chmod(self.dir, stat.S_IREAD) try: with self.assertRaises(OSError): with atomic_save(filename, "wb") as fobj: fobj.write(b"foo") finally: # restore permissions os.chmod(self.dir, dir_mode) os.chmod(filename, file_mode) with open(filename, "rb") as fobj: self.assertEqual(fobj.read(), b"nope") self.assertEqual(os.listdir(self.dir), [os.path.basename(filename)]) ���������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1656357949.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_collection.py�������������������������������������������������������0000664�0001750�0001750�00000061050�14256402075�020157� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil from collections import defaultdict from os.path import exists from pathlib import Path from xml.etree.ElementTree import ElementTree import pytest from quodlibet import config, app from quodlibet.formats import AudioFile as Fakesong from quodlibet.formats._audio import NUMERIC_ZERO_DEFAULT, PEOPLE, AudioFile from quodlibet.library.file import FileLibrary from quodlibet.library.playlist import PlaylistLibrary from quodlibet.util import format_rating from quodlibet.util.collection import (Album, Playlist, avg, bayesian_average, FileBackedPlaylist, XSPFBackedPlaylist, XSPF_NS) from senf import fsnative, uri2fsn from tests import TestCase, mkdtemp config.RATINGS = config.HardCodedRatingsPrefs() NUMERIC_SONGS = [ Fakesong({"~filename": fsnative("fake1-\xf0.mp3"), "~#length": 4, "~#added": 5, "~#lastplayed": 1, "~#bitrate": 200, "date": "100", "~#rating": 0.1, "originaldate": "2004-01-01", "~#filesize": 101}), Fakesong({"~filename": fsnative("fake2.mp3"), "~#length": 7, "~#added": 7, "~#lastplayed": 88, "~#bitrate": 220, "date": "99", "~#rating": 0.3, "originaldate": "2002-01-01", "~#filesize": 202}), Fakesong({"~filename": fsnative("fake3.mp3"), "~#length": 1, "~#added": 3, "~#lastplayed": 43, "~#bitrate": 60, "date": "33", "~#rating": 0.5, "tracknumber": "4/6", "discnumber": "1/2"}) ] AMAZING_SONG = Fakesong({"~#length": 123, "~#rating": 1.0}) class TAlbum(TestCase): def setUp(self): config.init() def test_people_sort(s): songs = [ Fakesong({"albumartist": "aa", "artist": "b\na"}), Fakesong({"albumartist": "aa", "artist": "a\na"}) ] album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.comma("~people"), "aa, a, b") def test_peoplesort_sort(s): songs = [ Fakesong({"albumartistsort": "aa", "artist": "b\na"}), Fakesong({"albumartist": "aa", "artistsort": "a\na"}) ] album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.comma("~peoplesort"), "aa, a, b") def test_tied_tags(s): songs = [ Fakesong({"artist": "a", "title": "c"}), Fakesong({"artist": "a", "dummy": "d\ne"}) ] album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.comma("~artist~dummy"), "a - d, e") def test_tied_num_tags(s): songs = [ Fakesong({"~#length": 5, "title": "c", "~#rating": 0.4}), Fakesong({"~#length": 7, "dummy": "d\ne", "~#rating": 0.6}), Fakesong({"~#length": 0, "dummy2": 5, "~#rating": 0.5}) ] album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.comma("~foo~~s~~~"), "") s.failUnlessEqual(album.comma("~#length~dummy"), "12 - d, e") s.failUnlessEqual(album.comma("~#rating~dummy"), "0.50 - d, e") s.failUnlessEqual(album.comma("~#length:sum~dummy"), "12 - d, e") s.failUnlessEqual(album.comma("~#dummy2"), 5) s.failUnlessEqual(album.comma("~#dummy3"), "") def test_internal_tags(s): songs = [ Fakesong({"~#length": 5, "discnumber": "1", "date": "2038"}), Fakesong({"~#length": 7, "dummy": "d\ne", "discnumber": "2"}) ] album = Album(songs[0]) album.songs = set(songs) s.failIfEqual(album.comma("~long-length"), "") s.failIfEqual(album.comma("~tracks"), "") s.failIfEqual(album.comma("~discs"), "") s.failUnlessEqual(album.comma("~foo"), "") s.failUnlessEqual(album.comma(""), "") s.failUnlessEqual(album.comma("~"), "") s.failUnlessEqual(album.get("~#"), "") def test_numeric_ops(s): songs = NUMERIC_SONGS album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.get("~#length"), 12) s.failUnlessEqual(album.get("~#length:sum"), 12) s.failUnlessEqual(album.get("~#length:max"), 7) s.failUnlessEqual(album.get("~#length:min"), 1) s.failUnlessEqual(album.get("~#length:avg"), 4) s.failUnlessEqual(album.get("~#length:foo"), 0) s.failUnlessEqual(album.get("~#added"), 7) s.failUnlessEqual(album.get("~#lastplayed"), 88) s.failUnlessEqual(album.get("~#bitrate"), 200) s.failUnlessEqual(album.get("~#year"), 33) s.failUnlessEqual(album.get("~#rating"), 0.3) s.failUnlessEqual(album.get("~#originalyear"), 2002) def test_numeric_comma(self): songs = [Fakesong({ "~#added": 1, "~#rating": 0.5, "~#bitrate": 42, "~#length": 1, })] album = Album(songs[0]) album.songs = set(songs) self.assertEqual(album.comma("~#added"), 1) self.assertEqual(album.comma("~#rating"), 0.5) self.assertEqual(album.comma("~#bitrate"), 42) def test_numeric_funcs_text(self): songs = NUMERIC_SONGS album = Album(songs[0]) album.songs = set(songs) self.assertEqual(album("~length:sum"), "0:12") self.assertEqual(album("~length:min"), "0:01") self.assertEqual(album("~long-length:min"), "1 second") self.assertEqual(album("~tracks:min"), "6 tracks") self.assertEqual(album("~discs:min"), "2 discs") self.assertEqual(album("~rating:min"), format_rating(0.1)) self.assertEqual(album("~filesize:min"), "0 B") def test_single_rating(s): songs = [Fakesong({"~#rating": 0.75})] album = Album(songs[0]) album.songs = set(songs) # One song should average to its own rating s.failUnlessEqual(album.get("~#rating:avg"), songs[0]("~#rating")) # BAV should now be default for rating s.failUnlessEqual(album.get("~#rating:bav"), album.get("~#rating:avg")) def test_multiple_ratings(s): r1, r2 = 1.0, 0.5 songs = [Fakesong({"~#rating": r1}), Fakesong({"~#rating": r2})] album = Album(songs[0]) album.songs = set(songs) # Standard averaging still available s.failUnlessEqual(album("~#rating:avg"), avg([r1, r2])) # C = 0.0 => emulate arithmetic mean config.set("settings", "bayesian_rating_factor", 0.0) s.failUnlessEqual(album("~#rating:bav"), album("~#rating:avg")) def test_bayesian_multiple_ratings(s): # separated from above to avoid caching c, r1, r2 = 5, 1.0, 0.5 songs = [Fakesong({"~#rating": r1}), Fakesong({"~#rating": r2})] album = Album(songs[0]) album.songs = set(songs) config.set("settings", "bayesian_rating_factor", float(c)) s.failUnlessEqual( config.getfloat("settings", "bayesian_rating_factor"), float(c)) expected = avg(c * [config.RATINGS.default] + [r1, r2]) s.failUnlessEqual(album("~#rating:bav"), expected) s.failUnlessEqual(album("~#rating"), expected) def test_bayesian_average(s): bav = bayesian_average l = [1, 2, 3, 4] a = avg(l) # c=0 => this becomes a mean regardless of m s.failUnlessEqual(bav(l, 0, 0), a) s.failUnlessEqual(bav(l, 0, 999), a) # c=1, m = a (i.e. just adding another mean score) => no effect s.failUnlessEqual(bav(l, 1, a), a) # Harder ones s.failUnlessEqual(bav(l, 5, 2), 20.0 / 9) expected = 40.0 / 14 s.failUnlessEqual(bav(l, 10, 3), expected) # Also check another iterable s.failUnlessEqual(bav(tuple(l), 10, 3), expected) def test_defaults(s): failUnlessEq = s.failUnlessEqual song = Fakesong({}) album = Album(song) failUnlessEq(album("foo", "x"), "x") album.songs.add(song) failUnlessEq(album("~#length", "x"), song("~#length", "x")) failUnlessEq(album("~#bitrate", "x"), song("~#bitrate", "x")) failUnlessEq(album("~#rating", "x"), song("~#rating", "x")) failUnlessEq(album("~#playcount", "x"), song("~#playcount", "x")) failUnlessEq(album("~#mtime", "x"), song("~#mtime", "x")) failUnlessEq(album("~#year", "x"), song("~#year", "x")) failUnlessEq(album("~#foo", "x"), song("~#foo", "x")) failUnlessEq(album("foo", "x"), song("foo", "x")) failUnlessEq(album("~foo", "x"), song("~foo", "x")) failUnlessEq(album("~people", "x"), song("~people", "x")) failUnlessEq(album("~peoplesort", "x"), song("~peoplesort", "x")) failUnlessEq(album("~performer", "x"), song("~performer", "x")) failUnlessEq(album("~performersort", "x"), song("~performersort", "x")) failUnlessEq(album("~rating", "x"), song("~rating", "x")) for p in PEOPLE: failUnlessEq(album(p, "x"), song(p, "x")) for p in NUMERIC_ZERO_DEFAULT: failUnlessEq(album(p, "x"), song(p, "x")) def test_methods(s): songs = [ Fakesong({"b": "bb4\nbb1\nbb1", "c": "cc1\ncc3\ncc3", "#d": 0.1}), Fakesong({"b": "bb1\nbb1\nbb4", "c": "cc3\ncc1\ncc3", "#d": 0.2}) ] album = Album(songs[0]) album.songs = set(songs) s.failUnlessEqual(album.list("c"), ["cc3", "cc1"]) s.failUnlessEqual(album.list("~c~b"), ["cc3", "cc1", "bb1", "bb4"]) s.failUnlessEqual(album.list("#d"), ["0.1", "0.2"]) s.failUnlessEqual(album.comma("c"), "cc3, cc1") s.failUnlessEqual(album.comma("~c~b"), "cc3, cc1 - bb1, bb4") def tearDown(self): config.quit() class PlaylistResource: def __init__(self, pl: Playlist): self.pl = pl def __enter__(self): return self.pl def __exit__(self, *exc_info): self.pl.delete() class TPlaylist(TestCase): TWO_SONGS = [ Fakesong({"~#length": 5, "discnumber": "1", "date": "2038"}), Fakesong({"~#length": 7, "dummy": "d\ne", "discnumber": "2"}) ] class FakeLib: def __init__(self): self.reset() def emit(self, name, songs): self.emitted[name].extend(songs) def masked(self, songs): return False def reset(self): self.emitted = defaultdict(list) @property def changed(self): return self.emitted.get('changed', []) @property def playlists(self): return PlaylistLibrary(self) FAKE_LIB = FakeLib() def setUp(self): self.FAKE_LIB.reset() app.library = self.FAKE_LIB def pl(self, name, lib=None) -> Playlist: return Playlist(name, lib) def wrap(self, name, lib=FAKE_LIB): return PlaylistResource(self.pl(name, lib)) def test_equality(s): pl = s.pl("playlist") pl2 = s.pl("playlist") pl3 = s.pl("playlist") s.failUnlessEqual(pl, pl2) # Debatable s.failUnlessEqual(pl, pl3) pl4 = s.pl("foobar") s.failIfEqual(pl, pl4) pl.delete() pl2.delete() pl3.delete() pl4.delete() def test_index(s): with s.wrap("playlist") as pl: songs = s.TWO_SONGS pl.extend(songs) # Just a sanity check... s.failUnlessEqual(songs.index(songs[1]), 1) # And now the happy paths.. s.failUnlessEqual(pl.index(songs[0]), 0) s.failUnlessEqual(pl.index(songs[1]), 1) # ValueError is what we want here try: pl.index(Fakesong({})) s.fail() except ValueError: pass def test_name_tag(s): with s.wrap("a playlist") as pl: s.failUnlessEqual(pl("~name"), "a playlist") s.failUnlessEqual(pl.get("~name"), "a playlist") def test_internal_tags(s): with s.wrap("playlist") as pl: pl.extend(s.TWO_SONGS) s.failIfEqual(pl.comma("~long-length"), "") s.failIfEqual(pl.comma("~tracks"), "") s.failIfEqual(pl.comma("~discs"), "") s.failUnlessEqual(pl.comma("~foo"), "") s.failUnlessEqual(pl.comma(""), "") s.failUnlessEqual(pl.comma("~"), "") s.failUnlessEqual(pl.get("~#"), "") def test_numeric_ops(s): songs = NUMERIC_SONGS with s.wrap("playlist") as pl: pl.extend(songs) s.failUnlessEqual(pl.get("~#length"), 12) s.failUnlessEqual(pl.get("~#length:sum"), 12) s.failUnlessEqual(pl.get("~#length:max"), 7) s.failUnlessEqual(pl.get("~#length:min"), 1) s.failUnlessEqual(pl.get("~#length:avg"), 4) s.failUnlessEqual(pl.get("~#length:foo"), 0) s.failUnlessEqual(pl.get("~#rating:avg"), avg([0.1, 0.3, 0.5])) s.failUnlessEqual(pl.get("~#filesize"), 303) s.failUnlessEqual(pl.get("~#added"), 7) s.failUnlessEqual(pl.get("~#lastplayed"), 88) s.failUnlessEqual(pl.get("~#bitrate"), 200) s.failUnlessEqual(pl.get("~#year"), 33) s.failUnlessEqual(pl.get("~#rating"), 0.3) s.failUnlessEqual(pl.get("~#originalyear"), 2002) def test_updating_aggregates_extend(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) old_length = pl.get("~#length") old_size = pl.get("~#filesize") # Double the playlist pl.extend(NUMERIC_SONGS) new_length = pl.get("~#length") new_size = pl.get("~#filesize") s.failUnless(new_length > old_length, msg="Ooops, %d <= %d" % (new_length, old_length)) s.failUnless(new_size > old_size, msg="Ooops, %d <= %d" % (new_size, old_size)) def test_updating_aggregates_append(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) old_rating = pl.get("~#rating") pl.append(AMAZING_SONG) new_rating = pl.get("~#filesize") s.failUnless(new_rating > old_rating) def test_updating_aggregates_clear(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) s.failUnless(pl.get("~#length")) pl.clear() s.failIf(pl.get("~#length")) def test_updating_aggregates_remove_songs(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) s.failUnless(pl.get("~#length")) pl.remove_songs(NUMERIC_SONGS) s.failIf(pl.get("~#length")) def test_listlike(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) s.failUnlessEqual(NUMERIC_SONGS[0], pl[0]) s.failUnlessEqual(NUMERIC_SONGS[1:2], pl[1:2]) s.failUnless(NUMERIC_SONGS[1] in pl) def test_extend_signals(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) s.failUnlessEqual(s.FAKE_LIB.changed, NUMERIC_SONGS) def test_append_signals(s): with s.wrap("playlist") as pl: song = NUMERIC_SONGS[0] pl.append(song) s.failUnlessEqual(s.FAKE_LIB.changed, [song]) def test_clear_signals(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) pl.clear() s.failUnlessEqual(s.FAKE_LIB.changed, NUMERIC_SONGS * 2) def test_make(self): with self.wrap("Does not exist") as pl: self.failIf(len(pl)) self.failUnlessEqual(pl.name, "Does not exist") def test_rename_working(self): with self.wrap("Foobar") as pl: assert pl.name == "Foobar" pl.rename("Foo Quuxly") assert pl.name == "Foo Quuxly" # Rename should not fire signals self.failIf(self.FAKE_LIB.changed) def test_rename_nothing(self): with self.wrap("Foobar") as pl: self.failUnlessRaises(ValueError, pl.rename, "") def test_no_op_rename(self): with self.wrap("playlist") as pl: pl.rename("playlist") self.failUnlessEqual(pl.name, "playlist") def test_duplicates_single_item(self): with self.wrap("playlist") as pl: pl.append(self.TWO_SONGS[0]) self.failIf(pl.has_duplicates) pl.append(self.TWO_SONGS[0]) self.failUnless(pl.has_duplicates) def test_duplicates(self): with self.wrap("playlist") as pl: pl.extend(self.TWO_SONGS) pl.extend(self.TWO_SONGS) self.failUnlessEqual(len(pl), 4) self.failUnless(pl.has_duplicates, ("Playlist has un-detected duplicates: %s " % "\n".join([str(s) for s in pl._list]))) def test_remove_leaving_duplicates(self): with self.wrap("playlist") as pl: pl.extend(self.TWO_SONGS) [first, second] = self.TWO_SONGS pl.extend(NUMERIC_SONGS + self.TWO_SONGS) self.failUnlessEqual(len(self.FAKE_LIB.changed), 7) self.FAKE_LIB.reset() pl.remove_songs(self.TWO_SONGS, leave_dupes=True) self.failUnless(first in pl) self.failUnless(second in pl) self.failIf(len(self.FAKE_LIB.changed)) def test_remove_fully(self): with self.wrap("playlist") as pl: pl.extend(self.TWO_SONGS * 2) self.FAKE_LIB.reset() pl.remove_songs(self.TWO_SONGS, leave_dupes=False) self.failIf(len(pl)) self.failUnlessEqual(self.FAKE_LIB.changed, self.TWO_SONGS) class TFileBackedPlaylist(TPlaylist): Playlist = FileBackedPlaylist def setUp(self): super().setUp() self.temp = mkdtemp() self.temp2 = mkdtemp() def tearDown(self): shutil.rmtree(self.temp) shutil.rmtree(self.temp2) def pl(self, name, lib=None): fn = self.Playlist.filename_for(name) return self.Playlist(self.temp, fn, lib) def new_pl(self, name, lib=None): return self.Playlist.new(self.temp, name, lib) def test_from_songs(self): pl = self.Playlist.from_songs(self.temp, NUMERIC_SONGS) self.failUnlessEqual(pl.songs, NUMERIC_SONGS) pl.delete() def test_read(self): lib = FileLibrary("foobar") lib.add(NUMERIC_SONGS) with self.wrap("playlist", lib) as pl: pl.extend(NUMERIC_SONGS) pl.write() self.assertEqual(len(pl), len(NUMERIC_SONGS)) def test_write(self): with self.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) pl.extend([fsnative(u"xf0xf0")]) pl.write() with open(pl.path, "rb") as h: self.assertEqual(len(h.read().splitlines()), len(NUMERIC_SONGS) + 1) def test_difficult_names(self): lib = FileLibrary("foobar") tempdir = mkdtemp() self.add_songs_in_temp_dir(lib, tempdir, NUMERIC_SONGS) name = "c:?\"problem?\" / foo* / 100% ə! COM" with self.wrap(name, lib) as pl: pl.extend(NUMERIC_SONGS) pl.write() assert pl.songs == NUMERIC_SONGS with self.wrap(name, lib) as pl2: assert pl2.songs == NUMERIC_SONGS def add_songs_in_temp_dir(self, lib, tempdir, songs): for l in songs: l["~filename"] = os.path.join(tempdir, l["~filename"]) l.sanitize() lib.add([l]) def test_symmetric(self): P = self.Playlist for name in ("bar & foo?", "100% cool.now 😀", "COM:", "a/b"): new_name = P.name_for(P.filename_for(name)) assert new_name == name def test_make_dup(self): p1 = self.new_pl("Does not exist") p2 = self.new_pl("Does not exist") self.failUnlessEqual(p1.name, "Does not exist") self.failUnless(p2.name.startswith("Does not exist")) self.failIfEqual(p1.name, p2.name) p1.delete() p2.delete() def test_rename_removes(self): with self.wrap("foo") as pl: pl.rename("bar") self.failUnless(exists(self.path_for('bar'))) self.failIf(exists(self.path_for('foo'))) def path_for(self, name: str): return os.path.join(self.temp, self.Playlist.filename_for(name)) def test_rename_fails_if_file_exists(self): with self.wrap("foo") as foo: with self.wrap("bar"): with pytest.raises(ValueError): foo.rename("bar") def test_masked_handling(self): if os.name == "nt": # FIXME: masking isn't properly implemented on Windows return # playlists can contain songs and paths for masked handling.. lib = FileLibrary("foobar") with self.wrap("playlist", lib) as pl: song = Fakesong({"date": "2038", "~filename": fsnative(u"/fake")}) song.sanitize() lib.add([song]) # mask and update lib.mask("/") pl.append(song) pl.remove_songs([song]) self.failUnless("/fake" in pl) pl.extend(self.TWO_SONGS) # check if collections can handle the mix self.failUnlessEqual(pl("date"), "2038") # unmask and update lib.unmask("/") pl.add_songs(["/fake"], lib) self.failUnless(song in pl) lib.destroy() def test_delete_emits_no_signals(self): lib = self.FakeLib() with self.wrap("playlist", lib=lib) as pl: pl.extend(self.TWO_SONGS) # We don't care about changed signals on extend... lib.reset() pl.delete() assert not lib.emitted, "Deleting caused library signals" # Second time, just in case assert not lib.emitted, "Deleting again caused library signals" class TXSPFBackedPlaylist(TFileBackedPlaylist): Playlist = XSPFBackedPlaylist def setUp(self): super().setUp() self.temp = mkdtemp() self.temp2 = mkdtemp() def tearDown(self): shutil.rmtree(self.temp) shutil.rmtree(self.temp2) def path_for(self, name: str): return os.path.join(self.temp, f"{name}.xspf") def test_write(self): with self.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) some_path = fsnative(os.path.join(self.temp, "xf0xf0")) pl.extend([some_path]) pl.write() assert exists(pl.path), "File doesn't exist" root = ElementTree().parse(pl.path) assert root.tag == "{http://xspf.org/ns/0/}playlist" tracks = root.findall(".//track", namespaces={"": XSPF_NS}) assert len(tracks) == len(NUMERIC_SONGS) + 1, f"Hmm found {tracks}" # Should now write compliant local URLs last_location = tracks[-1].find("location", namespaces={"": XSPF_NS}).text assert uri2fsn(last_location) == some_path def test_writes_multiple_line_files(self): with self.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) pl.write() with open(pl.path) as f: lines = f.readlines() assert len(lines) >= 1 + 2 + len(pl), "Was expecting a semi-pretty-file" def test_load_legacy_format_to_xspf(self): playlist_fn = "old" songs_lib = FileLibrary() songs_lib.add(NUMERIC_SONGS) old_pl = FileBackedPlaylist(self.temp, playlist_fn) old_pl.extend(NUMERIC_SONGS) pl = XSPFBackedPlaylist.from_playlist(old_pl, songs_lib=songs_lib, pl_lib=None) expected_filenames = {s("~filename") for s in NUMERIC_SONGS} assert {s("~filename") for s in pl.songs} == expected_filenames def test_v1_load_non_compliant_xspf(self): """See #3983""" songs_lib = FileLibrary() test_filename = ("/music/Funk & Disco/" "Average White Band - Pickin' Up The Pieces/" "Average White Band - Your Love Is a Miracle.flac") songs_lib.add([AudioFile({"~filename": test_filename})]) playlist_fn = "non-compliant.xspf" path = str(Path(__file__).parent / "data") pl = XSPFBackedPlaylist(path, playlist_fn, songs_lib=songs_lib, pl_lib=None) assert {s("~filename") for s in pl.songs}, set(test_filename) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_collections.py������������������������������������������������������0000664�0001750�0001750�00000010772�14035600052�020335� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.collections import HashedList, DictProxy class TDictMixin(TestCase): uses_mmap = False def setUp(self): self.fdict = DictProxy() self.rdict = {} self.fdict["foo"] = self.rdict["foo"] = "bar" def test_getsetitem(self): self.failUnlessEqual(self.fdict["foo"], "bar") self.failUnlessRaises(KeyError, self.fdict.__getitem__, "bar") def test_has_key_contains(self): self.failUnless("foo" in self.fdict) self.failIf("bar" in self.fdict) self.failUnless(self.fdict.has_key("foo")) self.failIf(self.fdict.has_key("bar")) def test_iter(self): self.failUnlessEqual(list(iter(self.fdict)), ["foo"]) def test_clear(self): self.fdict.clear() self.rdict.clear() self.failIf(self.fdict) def test_keys(self): self.failUnlessEqual(list(self.fdict.keys()), list(self.rdict.keys())) def test_values(self): self.failUnlessEqual( list(self.fdict.values()), list(self.rdict.values())) def test_items(self): self.failUnlessEqual( list(self.fdict.items()), list(self.rdict.items())) def test_pop(self): self.failUnlessEqual(self.fdict.pop("foo"), self.rdict.pop("foo")) self.failUnlessRaises(KeyError, self.fdict.pop, "woo") def test_pop_bad(self): self.failUnlessRaises(TypeError, self.fdict.pop, "foo", 1, 2) def test_popitem(self): self.failUnlessEqual(self.fdict.popitem(), self.rdict.popitem()) self.failUnlessRaises(KeyError, self.fdict.popitem) def test_update_other(self): other = {"a": 1, "b": 2} self.fdict.update(other) self.rdict.update(other) def test_update_other_is_list(self): other = [("a", 1), ("b", 2)] self.fdict.update(other) self.rdict.update(dict(other)) def test_update_kwargs(self): self.fdict.update(a=1, b=2) other = {"a": 1, "b": 2} self.rdict.update(other) def test_setdefault(self): self.fdict.setdefault("foo", "baz") self.rdict.setdefault("foo", "baz") self.fdict.setdefault("bar", "baz") self.rdict.setdefault("bar", "baz") def test_get(self): self.failUnlessEqual(self.rdict.get("a"), self.fdict.get("a")) self.failUnlessEqual( self.rdict.get("a", "b"), self.fdict.get("a", "b")) self.failUnlessEqual(self.rdict.get("foo"), self.fdict.get("foo")) def test_repr(self): self.failUnlessEqual(repr(self.rdict), repr(self.fdict)) def test_len(self): self.failUnlessEqual(len(self.rdict), len(self.fdict)) def tearDown(self): self.failUnlessEqual(self.fdict, self.rdict) self.failUnlessEqual(self.rdict, self.fdict) class THashedList(TestCase): def test_init(self): l = HashedList([1, 2, 3]) self.failUnless(1 in l) l = HashedList() self.failIf(1 in l) def test_length(self): l = HashedList([1, 2, 3, 3]) self.failUnlessEqual(len(l), 4) def test_insert(self): l = HashedList([1, 2, 3, 3]) l.insert(0, 3) self.failUnlessEqual(len(l), 5) def test_delete(self): l = HashedList([2, 2]) self.failUnless(2 in l) del l[0] self.failUnless(2 in l) del l[0] self.failIf(2 in l) def test_iter(self): l = HashedList([1, 2, 3, 3]) new = [a for a in l] self.failUnlessEqual(new, [1, 2, 3, 3]) def test_del_slice(self): l = HashedList([1, 2, 3, 3]) del l[1:3] self.failUnlessEqual(len(l), 2) self.failUnless(1 in l) self.failUnless(3 in l) self.failIf(2 in l) def test_set_slice(self): l = HashedList([1, 2, 3, 3]) l[:3] = [4] self.failUnless(4 in l) self.failUnless(3 in l) self.failIf(2 in l) def test_extend(self): l = HashedList() l.extend([1, 1, 2]) self.failUnless(1 in l) self.failUnlessEqual(len(l), 3) def test_duplicates(self): l = HashedList() self.failIf(l.has_duplicates()) l = HashedList(range(10)) self.failIf(l.has_duplicates()) l.append(5) self.failUnless(l.has_duplicates()) ������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_config.py�����������������������������������������������������������0000664�0001750�0001750�00000027153�14035600052�017265� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, mkstemp from .helper import temp_filename from quodlibet.util.config import Config, Error, ConfigProxy class TConfig(TestCase): def test_set_default_only(self): conf = Config() self.assertRaises(Error, conf.set, "foo", "bar", 1) conf.defaults.add_section("foo") conf.set("foo", "bar", 1) def test_options(self): conf = Config() self.assertRaises(Error, conf.options, "foo") conf.defaults.add_section("foo") self.assertEqual(conf.options("foo"), []) conf.defaults.set("foo", "bar", 1) conf.defaults.set("foo", "blah", 1) conf.set("foo", "blah", 1) conf.set("foo", "quux", 1) self.assertEqual(conf.options("foo"), ['blah', 'quux', 'bar']) conf.defaults.clear() def test_options_no_default(self): conf = Config() conf.add_section("foo") self.assertEqual(conf.options("foo"), []) def test_has_section(self): conf = Config() self.assertFalse(conf.has_section("foo")) conf.defaults.add_section("foo") self.assertTrue(conf.has_section("foo")) conf.add_section("foo") conf.defaults.clear() self.assertTrue(conf.has_section("foo")) conf.clear() self.assertFalse(conf.has_section("foo")) def test_read_garbage_file(self): conf = Config() garbage = b"\xf1=\xab\xac" fd, filename = mkstemp() os.close(fd) with open(filename, "wb") as f: f.write(garbage) self.assertRaises(Error, conf.read, filename) os.remove(filename) def test_set(self): conf = Config() conf.add_section("foo") conf.set("foo", "bar", 1) self.failUnlessEqual(conf.get("foo", "bar"), "1") self.failUnlessEqual(conf.getint("foo", "bar"), 1) def test_setbytes(self): conf = Config() conf.add_section("foo") conf.setbytes("foo", "bar", b"\xff\xff") assert conf.getbytes("foo", "bar") == b"\xff\xff" def test_getbytes(self): conf = Config() assert conf.getbytes("foo", "bar", b"\xff") == b"\xff" def test_reset(self): conf = Config() conf.defaults.add_section("player") conf.defaults.set("player", "backend", "blah") conf.set("player", "backend", "foo") self.assertEqual(conf.get("player", "backend"), "foo") conf.reset("player", "backend") conf.defaults.set("player", "backend", "blah_new") self.assertEqual(conf.get("player", "backend"), "blah_new") def test_reset_no_section(self): conf = Config() conf.defaults.add_section("player") conf.defaults.set("player", "backend", "blah") conf.reset("player", "backend") assert conf.get("player", "backend") == "blah" def test_initial_after_set(self): conf = Config() conf.add_section("player") conf.set("player", "backend", "orig") conf.defaults.add_section("player") conf.defaults.set("player", "backend", "initial") self.assertEqual(conf.get("player", "backend"), "orig") self.assertEqual(conf.defaults.get("player", "backend"), "initial") conf.reset("player", "backend") self.assertEqual(conf.get("player", "backend"), "initial") def test_get_fallback_default(self): conf = Config() conf.defaults.add_section("get") self.assertRaises(Error, conf.get, "get", "bar") conf.defaults.set("get", "bar", 1) self.assertEqual(conf.get("get", "bar"), "1") conf.defaults.add_section("getboolean") self.assertRaises(Error, conf.getboolean, "getboolean", "bar") conf.defaults.set("getboolean", "bar", True) self.assertEqual(conf.getboolean("getboolean", "bar"), True) conf.defaults.add_section("getfloat") self.assertRaises(Error, conf.getfloat, "getfloat", "bar") conf.defaults.set("getfloat", "bar", 1.0) self.assertEqual(conf.getfloat("getfloat", "bar"), 1.0) conf.defaults.add_section("getint") self.assertRaises(Error, conf.getint, "getint", "bar") conf.defaults.set("getint", "bar", 42) self.assertEqual(conf.getint("getint", "bar"), 42) conf.defaults.add_section("getlist") self.assertRaises(Error, conf.getlist, "getlist", "bar") conf.defaults.setlist("getlist", "bar", [1, 2, 3]) self.assertEqual(conf.getlist("getlist", "bar"), ["1", "2", "3"]) def test_get(self): conf = Config() conf.add_section("foo") conf.set("foo", "int", "1") conf.set("foo", "float", "1.25") conf.set("foo", "str", "foobar") conf.set("foo", "bool", "True") self.failUnlessEqual(conf.getint("foo", "int"), 1) self.failUnlessEqual(conf.getfloat("foo", "float"), 1.25) self.failUnlessEqual(conf.get("foo", "str"), "foobar") self.failUnlessEqual(conf.getboolean("foo", "bool"), True) def test_get_invalid_data(self): conf = Config() conf.add_section("foo") conf.set("foo", "bla", "xx;,,;\n\n\naa") self.assertTrue(conf.getboolean("foo", "bla", True)) self.assertEqual(conf.getint("foo", "bla", 42), 42) self.assertEqual(conf.getfloat("foo", "bla", 1.5), 1.5) self.assertEqual(conf.getstringlist("foo", "bla", ["baz"]), ["baz"]) def test_getint_float(self): conf = Config() conf.add_section("foo") conf.set("foo", "float", "1.25") self.assertEqual(conf.getint("foo", "float"), 1) def test_get_default(self): conf = Config() conf.add_section("foo") self.failUnlessEqual(conf.getboolean("foo", "nothing", True), True) self.failUnlessEqual(conf.getint("foo", "nothing", 42), 42) self.failUnlessEqual(conf.getfloat("foo", "nothing", 42.42), 42.42) self.failUnlessEqual(conf.get("foo", "nothing", "foo"), "foo") def test_stringlist_simple(self): conf = Config() conf.add_section("foo") self.failIf(conf.get("foo", "bar", None)) vals = ["one", "two", "three"] conf.setstringlist("foo", "bar", vals) self.failUnlessEqual(conf.getstringlist("foo", "bar"), vals) def test_stringlist_mixed(self): conf = Config() conf.add_section("foo") self.failIf(conf.get("foo", "bar", None)) conf.setstringlist("foo", "bar", ["one", 2]) self.failUnlessEqual(conf.getstringlist("foo", "bar"), ["one", "2"]) def test_stringlist_quoting(self): conf = Config() conf.add_section("foo") self.failIf(conf.get("foo", "bar", None)) vals = ["foo's gold", "bar, \"best\" 'ever'", u"le goût d'œufs à Noël"] conf.setstringlist("foo", "bar", vals) self.failUnlessEqual(conf.getstringlist("foo", "bar"), vals) def test_stringlist_spaces(self): conf = Config() conf.add_section("foo") vals = [" ", " ", " \t ", " \n \n"] conf.setstringlist("foo", "bar", vals) self.failUnlessEqual(conf.getstringlist("foo", "bar"), vals) def test_stringlist_invalid_encoding(self): conf = Config() conf.add_section("foo") conf.setbytes("foo", "bar", b"\xff\xff\xff\xff\xff\xff") def test_getlist(self): conf = Config() conf.add_section("foo") self.assertEqual(conf.getlist("foo", "bar", ["arg"]), ["arg"]) conf.set("foo", "bar", "abc,fo:o\\,bar") self.assertEqual(conf.getlist("foo", "bar"), ["abc", "fo:o,bar"]) self.assertEqual(conf.getlist("foo", "bar", sep=":"), ["abc,fo", "o\\,bar"]) conf.set("foo", "bar", "") self.assertEqual(conf.getlist("foo", "bar"), [""]) def test_setlist(self): conf = Config() conf.add_section("foo") conf.setlist("foo", "bar", [" a", ",", "c"]) self.assertEqual(conf.getlist("foo", "bar"), [" a", ",", "c"]) self.assertEqual(conf.get("foo", "bar"), " a,\\,,c") conf.setlist("foo", "bar", [" a", ",", "c"], sep=":") self.assertEqual(conf.get("foo", "bar"), " a:,:c") def test_versioning_disabled(self): # we don't pass a version, so versioning is disabled conf = Config() self.assertRaises(Error, conf.get_version) with temp_filename() as filename: conf.read(filename) self.assertRaises(Error, conf.register_upgrade_function, lambda: None) def test_versioning_upgrade_func(self): called = [] with temp_filename() as filename: conf = Config(version=0) def func(*args): called.append(args) conf.register_upgrade_function(func) self.assertRaises(Error, conf.get_version) conf.read(filename) self.assertEqual(conf.get_version(), -1) conf.register_upgrade_function(func) self.assertEqual([(conf, -1, 0), (conf, -1, 0)], called) def test_versioning(self): with temp_filename() as filename: conf = Config(version=41) conf.add_section("foo") conf.set("foo", "bar", "quux") conf.write(filename) self.assertRaises(Error, conf.get_version) # old was 41, we have 42, so upgrade def func(config, old, new): if old < 42: config.set("foo", "bar", "nope") conf = Config(version=42) conf.register_upgrade_function(func) conf.read(filename) self.assertEqual(conf.get_version(), 41) self.assertEqual(conf.get("foo", "bar"), "nope") # write doesn't change version conf.write(filename) self.assertEqual(conf.get_version(), 41) # but if we load again, it does conf.read(filename) self.assertEqual(conf.get_version(), 42) def test_upgrade_first_read(self): # don't run upgrade funcs if there is no config file yet with temp_filename() as filename: pass conf = Config(version=41) def func(*args): self.assertTrue(False) conf.register_upgrade_function(func) conf.read(filename) class TConfigProxy(TestCase): def setUp(self): conf = Config() conf.defaults.add_section("somesection") self.proxy = ConfigProxy(conf, "somesection") def test_getters_setters(self): self.proxy.set("foo", "bar") self.assertEqual(self.proxy.get("foo"), "bar") self.proxy.set("foo", 1.5) self.assertEqual(self.proxy.getfloat("foo"), 1.5) self.proxy.set("foo", 15) self.assertEqual(self.proxy.getint("foo"), 15) self.proxy.set("foo", False) self.assertEqual(self.proxy.getboolean("foo"), False) self.proxy.setbytes("foo", b"\xff") assert self.proxy.getbytes("foo") == b"\xff" def test_default(self): self.assertEqual(self.proxy.get("foo", "quux"), "quux") def test_get_initial(self): self.proxy.defaults.set("a", 3.0) self.assertEqual(self.proxy.defaults.get("a"), "3.0") def test_initial_and_reset(self): self.proxy.defaults.set("bla", "baz") self.assertEqual(self.proxy.get("bla"), "baz") self.proxy.set("bla", "nope") self.assertEqual(self.proxy.get("bla"), "nope") self.proxy.reset("bla") self.assertEqual(self.proxy.get("bla"), "baz") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_copool.py�����������������������������������������������������������0000664�0001750�0001750�00000006575�14231604332�017323� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import pytest from tests import TestCase, run_gtk_loop from gi.repository import Gtk from quodlibet.util import copool @pytest.mark.flaky(max_runs=3, min_passes=2) class Tcopool(TestCase): def setUp(self): self.buffer = None self.go = True def tearDown(self): copool.remove_all() def __set_buffer(self): while self.go: self.buffer = True yield None def _assert_eventually(self, value): while Gtk.events_pending(): Gtk.main_iteration() if self.buffer is value: return assert self.buffer is value def _assert_never(self, value): run_gtk_loop() assert self.buffer is not value def test_add_remove(self): copool.add(self.__set_buffer) self._assert_eventually(True) copool.remove(self.__set_buffer) self.buffer = None self._assert_eventually(None) def test_add_remove_with_funcid(self): copool.add(self.__set_buffer, funcid="test") self._assert_eventually(True) copool.remove("test") self.buffer = None self._assert_eventually(None) def test_pause_resume(self): copool.add(self.__set_buffer) self._assert_eventually(True) copool.pause(self.__set_buffer) self.buffer = None self._assert_never(True) copool.resume(self.__set_buffer) self._assert_eventually(True) copool.remove(self.__set_buffer) self.buffer = None self._assert_never(True) def test_pause_resume_with_funcid(self): self.buffer = None copool.add(self.__set_buffer, funcid="test") self._assert_eventually(True) copool.pause("test") self.buffer = None self._assert_never(True) copool.resume("test") copool.resume("test") self._assert_eventually(True) copool.remove("test") self.buffer = None self._assert_never(True) def test_pause_restart_pause(self): self.buffer = None copool.add(self.__set_buffer, funcid="test") self._assert_eventually(True) copool.pause("test") self.buffer = None self._assert_never(True) copool.add(self.__set_buffer, funcid="test") self._assert_eventually(True) copool.pause("test") self.buffer = None self._assert_never(True) def test_pause_all(self): self.buffer = None copool.add(self.__set_buffer, funcid="test") self._assert_eventually(True) copool.pause_all() self.buffer = None self._assert_never(True) def test_step(self): copool.add(self.__set_buffer, funcid="test") copool.pause("test") assert copool.step("test") self.go = False assert not copool.step("test") with pytest.raises(ValueError): copool.step("test") def test_timeout(self): copool.add(self.__set_buffer, funcid="test", timeout=100) copool.pause("test") copool.resume("test") copool.remove("test") with pytest.raises(ValueError): copool.step("test") �����������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1689586518.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_cover.py������������������������������������������������������������0000644�0001750�0001750�00000021664�14455205526�017152� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # 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 2 of the License, or # (at your option) any later version. import glob import os import shutil from os.path import basename from gi.repository import Gio from senf import fsnative from quodlibet import config from quodlibet.ext.covers.artwork_url import ArtworkUrlCover from quodlibet.formats import AudioFile from quodlibet.plugins import Plugin from quodlibet.util.cover.http import escape_query_value from quodlibet.util.cover.manager import CoverManager from quodlibet.util.path import normalize_path, path_equal, mkdir from tests import TestCase, mkdtemp bar_2_1 = AudioFile({ "~filename": fsnative(u"does not/exist"), "title": "more songs", "discnumber": "2/2", "tracknumber": "1", "artist": "Foo\nI have two artists", "album": "Bar", "lyricist": "Foo", "composer": "Foo", "performer": "I have two artists", }) class TCoverManager(TestCase): def setUp(self): config.init() self.manager = CoverManager() self.dir = mkdtemp() self.song = self.an_album_song() # Safety check self.failIf(glob.glob(os.path.join(self.dir + "*.jpg"))) files = [self.full_path("12345.jpg"), self.full_path("nothing.jpg")] for f in files: open(f, "w").close() def an_album_song(self, fn="asong.ogg"): return AudioFile({ "~filename": os.path.join(self.dir, fn), "album": u"Quuxly", "artist": u"Some One", }) def tearDown(self): shutil.rmtree(self.dir) config.quit() def _find_cover(self, song): return self.manager.get_cover(song) def full_path(self, path): return os.path.join(self.dir, path) def test_dir_not_exist(self): self.failIf(self._find_cover(bar_2_1)) def test_nothing(self): self.failIf(self._find_cover(self.song)) def test_labelid(self): self.song["labelid"] = "12345" assert path_equal(os.path.abspath(self._find_cover(self.song).name), self.full_path("12345.jpg")) del(self.song["labelid"]) def test_regular(self): for fn in ["cover.png", "folder.jpg", "Quuxly - front.png", "Quuxly_front_folder_cover.gif"]: f = self.add_file(fn) cover = self._find_cover(self.song) assert cover, f"No cover found after adding {fn}" assert path_equal(os.path.abspath(cover.name), f) self.test_labelid() # labelid must work with other files present def test_file_encoding(self): f = self.add_file(fsnative(u"öäü - Quuxly - cover.jpg")) self.assertTrue(isinstance(self.song("album"), str)) h = self._find_cover(self.song) assert h, "Nothing found" self.assertEqual(normalize_path(h.name), normalize_path(f)) def test_glob(self): config.set("albumart", "force_filename", str(True)) config.set("albumart", "filename", "foo.*") for fn in ["foo.jpg", "foo.png"]: f = self.add_file(fn) assert path_equal( os.path.abspath(self._find_cover(self.song).name), f) def test_invalid_glob(self): config.set("albumart", "force_filename", str(True)) config.set("albumart", "filename", "[a-2].jpg") # Invalid glob range, should not match anything self.add_file("a.jpg") assert self._find_cover(self.song) is None def test_invalid_glob_path(self): config.set("albumart", "force_filename", str(True)) config.set("albumart", "filename", "*.jpg") # Make a dir which contains an invalid glob path = os.path.join(self.full_path("[a-2]"), "cover.jpg") mkdir(os.path.dirname(path)) f = self.add_file(path) # Change the song's path to contain the invalid glob old_song_path = self.song['~filename'] new_song_path = os.path.join(os.path.dirname(path), os.path.basename(old_song_path)) self.song['~filename'] = new_song_path # The glob in the dirname should be ignored, while the # glob in the filename/basename is honored assert path_equal( os.path.abspath(self._find_cover(self.song).name), f) self.song['~filename'] = old_song_path def test_multiple_entries(self): config.set("albumart", "force_filename", str(True)) # the order of these is important, since bar should be # preferred to both 'foo' files # the spaces after the comma and last name are intentional config.set("albumart", "filename", "bar*,foo.png, foo.jpg ") for fn in ["foo.jpg", "foo.png", "bar.jpg"]: f = self.add_file(fn) assert path_equal( os.path.abspath(self._find_cover(self.song).name), f) def test_intelligent(self): song = self.song song["artist"] = "Q-Man" song["title"] = "First Q falls hardest" fns = ["Quuxly - back.jpg", "Quuxly.jpg", "q-man - quxxly.jpg", "folder.jpeg", "Q-man - Quuxly (FRONT).jpg"] for fn in fns: f = self.add_file(fn) cover = self._find_cover(song) if cover: actual = os.path.abspath(cover.name) assert path_equal(actual, f) else: # Here, no cover is better than the back... assert path_equal(f, self.full_path("Quuxly - back.jpg")) def test_embedded_special_cover_words(self): """Tests that words incidentally containing embedded "special" words album keywords (e.g. cover, disc, back) don't trigger See Issue 818""" song = AudioFile({ "~filename": fsnative(os.path.join(self.dir, u"asong.ogg")), "album": "foobar", "title": "Ode to Baz", "artist": "Q-Man", }) data = [('back.jpg', False), ('discovery.jpg', False), ("Pharell - frontin'.jpg", False), ('nickelback - Curb.jpg', False), ('foobar.jpg', True), ('folder.jpg', True), # Though this order is debatable ('Q-Man - foobar.jpg', True), ('Q-man - foobar (cover).jpg', True)] for fn, should_find in data: f = self.add_file(fn) cover = self._find_cover(song) if cover: actual = os.path.abspath(cover.name) assert path_equal(actual, f), \ f"{basename(f)!r} should trump {basename(actual)!r}" else: self.failIf(should_find, msg="Couldn't find %s for %s" % (f, song("~filename"))) def add_file(self, fn): f = self.full_path(fn) open(f, "wb").close() return f def test_multiple_people(self): song = AudioFile({ "~filename": os.path.join(self.dir, "asong.ogg"), "album": "foobar", "title": "Ode to Baz", "performer": "The Performer", "artist": "The Composer\nThe Conductor", "composer": "The Composer", }) for fn in ["foobar.jpg", "The Performer - foobar.jpg", "The Composer - The Performer - foobar.jpg", "The Composer - The Conductor, The Performer - foobar.jpg"]: f = self.add_file(fn) cover = self._find_cover(song) self.failUnless(cover) actual = os.path.abspath(cover.name) cover.close() assert path_equal( actual, f, "\"%s\" should trump \"%s\"" % (f, actual)) def test_get_thumbnail(self): self.assertTrue(self.manager.get_pixbuf(self.song, 10, 10) is None) self.assertTrue( self.manager.get_pixbuf_many([self.song], 10, 10) is None) def test_get_many(self): songs = [AudioFile({"~filename": os.path.join(self.dir, "song.ogg"), "title": "Ode to Baz"}), self.an_album_song()] plugin = Plugin(ArtworkUrlCover) self.manager.plugin_handler.plugin_enable(plugin) self.add_file('cover.jpg') cover = self.manager.get_cover_many(songs) assert cover def test_search_missing_artist(self): titled_album_song = self.an_album_song('z.ogg') titled_album_song["artist"] = "foo" album_songs = [self.an_album_song('x.ogg'), titled_album_song, self.an_album_song()] self.manager.search_cover(Gio.Cancellable(), album_songs) class THttp(TestCase): def test_escape(self): assert escape_query_value("foo bar") == "foo%20bar" assert escape_query_value("foo?") == "foo%3F" assert escape_query_value("foo&bar") == "foo%26bar" assert escape_query_value("¿fübàr?") == "¿fübàr%3F" ����������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_dbusutils.py��������������������������������������������������������0000664�0001750�0001750�00000011170�14035600052�020026� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012 Christoph Reiter <reiter.christoph@gmail.com> # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase, skipUnless try: import dbus except ImportError: dbus = None else: from quodlibet.util.dbusutils import apply_signature, list_spec_properties from quodlibet.util.dbusutils import filter_property_spec, DBusProperty from quodlibet.util.dbusutils import dbus_unicode_validate ANN1 = """ <property name="Position" type="s" access="read"> <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" \ value="false"/> </property> <property name="MinimumRate" type="s" access="read"/> """ ANN2 = """ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" \ value="false"/> <property name="Foobar" type="s" access="read"> <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" \ value="invalidates"/> </property> <property name="XXX" type="s" access="read"/> """ @skipUnless(dbus, "dbus missing") class TDbusUtils(TestCase): def test_prop_sig(self): value = apply_signature(2, "u") self.failUnless(isinstance(value, dbus.UInt32)) value = apply_signature({"a": "b"}, "a{ss}") self.failUnlessEqual(value.signature, "ss") self.failUnless(isinstance(value, dbus.Dictionary)) value = apply_signature(("a",), "a(s)") self.failUnlessEqual(value.signature, "s") self.failUnless(isinstance(value, dbus.Struct)) value = apply_signature(("a", "b"), "as") self.failUnlessEqual(value.signature, "s") self.failUnless(isinstance(value, dbus.Array)) self.failUnlessRaises(TypeError, apply_signature, 2, "a(s)") text = b'\xc3\xb6\xc3\xa4\xc3\xbc' value = apply_signature(text, "s", utf8_strings=True) self.failUnless(isinstance(value, str)) value = apply_signature(text, "s") self.failUnless(isinstance(value, str)) text = u"öäü" value = apply_signature(text, "s", utf8_strings=True) self.failUnless(isinstance(value, str)) value = apply_signature(text, "s") self.failUnless(isinstance(value, str)) def test_list_props(self): props = list_spec_properties(ANN1) self.failUnlessEqual(props["Position"]["access"], "read") self.failUnlessEqual(props["Position"]["emit"], "false") self.failUnlessEqual(props["Position"]["type"], "s") self.failUnlessEqual(props["MinimumRate"]["emit"], "true") props = list_spec_properties(ANN2) self.failUnlessEqual(props["Foobar"]["emit"], "invalidates") self.failUnlessEqual(props["XXX"]["emit"], "false") def test_filter_props(self): spec = filter_property_spec(ANN1, wl=["Position"]) self.failUnlessEqual( list(list_spec_properties(spec).keys()), ["Position"]) props = list_spec_properties(spec) self.failUnlessEqual(props["Position"]["emit"], "false") spec = filter_property_spec(ANN1, bl=["Position"]) self.failUnlessEqual(list(list_spec_properties(spec).keys()), ["MinimumRate"]) spec = filter_property_spec(ANN1) self.failUnlessEqual(len(list_spec_properties(spec).keys()), 2) def test_validate_utf8(self): self.failUnlessEqual(dbus_unicode_validate(u'X\ufffeX'), u"X\ufffdX") self.failUnlessEqual(dbus_unicode_validate(b'X\xef\xbf\xbeX'), u"X\ufffdX") def test_property_mixin(self): class X(DBusProperty): SUPPORTS_MULTIPLE_OBJECT_PATHS = False def set_introspection(self, *args): pass def get_property(self, interface, name): return interface def set_property(self, interface, name, value): pass x = X() x.set_properties("a1", ANN1) x.set_properties("a2", ANN2) x.implement_interface("a1", "a2") props = x.get_properties("a1") self.failUnless(("a1", "Position") in props) self.failUnless(("a2", "XXX") in props) props = x.get_properties("a2") self.failIf(("a1", "Position") in props) self.failUnlessEqual(x.get_interface("a2", "XXX"), "a2") self.failUnlessEqual(x.get_interface("a1", "XXX"), "a2") self.failUnlessEqual(x.get_value("a2", "XXX"), "a2") self.failUnlessEqual(x.get_value("a1", "XXX"), "a2") self.failUnlessEqual(x.get_value("a1", "Position"), "a1") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_dprint.py�����������������������������������������������������������0000664�0001750�0001750�00000002112�14035600052�017304� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import sys from tests import TestCase from .helper import capture_output from quodlibet.util.dprint import print_e, format_exception_only, print_exc class Tdprint(TestCase): def test_basics(self): with capture_output() as (stdout, stderr): print_e(u"foo") assert u"foo" in stderr.getvalue() def test_any_object(self): with capture_output() as (stdout, stderr): print_e(42) assert u"42" in stderr.getvalue() def test_format_exception_only(self): try: raise Exception except Exception: result = format_exception_only(*sys.exc_info()[:2]) assert all(isinstance(l, str) for l in result) def test_no_stack(self): with capture_output(): print_exc((None, None, None)) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_environment.py������������������������������������������������������0000664�0001750�0001750�00000001361�14035600052�020355� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util import is_unity, is_windows, is_osx class TUtilEnvironment(TestCase): def test_all(self): self.assertTrue(isinstance(is_unity(), bool)) self.assertTrue(isinstance(is_windows(), bool)) self.assertTrue(isinstance(is_osx(), bool)) def test_constrains(self): if is_windows(): self.assertFalse(is_osx()) if is_osx(): self.assertFalse(is_windows()) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919642.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_fifo.py�������������������������������������������������������������0000664�0001750�0001750�00000007541�14231604332�016745� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from unittest import mock from gi.repository import GLib from quodlibet import print_d from quodlibet.util import is_windows from tests import TestCase, skipIf from quodlibet.util.fifo import FIFOError, split_message, FIFO, fifo_exists, write_fifo from tests.helper import temp_filename class Tsplit_message(TestCase): def test_main(self): func = lambda d: list(split_message(d)) # no response format self.assertEqual(func(b""), []) self.assertEqual(func(b"foo"), [(b"foo", None)]) self.assertEqual(func(b"foo\nbar"), [(b"foo", None), (b"bar", None)]) # response format self.assertEqual(func(b"\x00a\x00/dev/null\x00"), [(b"a", b"/dev/null")]) self.assertEqual(func(b"\x00a\x00/dev/null\x00\x00b\x00/dev/foo\x00"), [(b"a", b"/dev/null"), (b"b", b"/dev/foo")]) # mixed self.assertEqual(func(b"foo\x00a\x00/dev\x00"), [(b"foo", None), (b"a", b"/dev")]) self.assertEqual(func(b"\x00a\x00/dev\x00foo"), [(b"a", b"/dev"), (b"foo", None)]) self.assertEqual(func(b"\x00a\x00/dev\x00foo\x00b\x00/arg\x00bla"), [(b"a", b"/dev"), (b"foo", None), (b"b", b"/arg"), (b"bla", None)]) # inval self.assertRaises(ValueError, func, b"foo\x00bar") @skipIf(is_windows(), "not on Windows") class TFIFO(TestCase): def test_creation_destruction(self): def cb(bs, _): print_d(bs) with temp_filename() as fn: fifo = FIFO(fn, cb) self.failIf(fifo_exists(fifo._path)) fifo.open() self.failUnless(fifo_exists(fifo._path)) # Should *not* error if file is gone fifo.destroy() def test_unwriteable_location(self): fifo = FIFO("/dev/not-here", None) fifo.open() with self.assertRaises(FIFOError): write_fifo(fifo._path, "foobar".encode()) fifo.destroy() def test_empty_read(self): result = [] with temp_filename() as f, mock.patch.object(FIFO, "open") as m_open: fifo = FIFO(f, result.append) source = mock.Mock() source.read.return_value = b"" assert fifo._process(source, GLib.IO_IN) is False assert m_open.mock_calls == [mock.call(ignore_lock=True)] assert result == [] def test_glib_err_read(self): result = [] with temp_filename() as f, mock.patch.object(FIFO, "open") as m_open: fifo = FIFO(f, result.append) source = mock.Mock() assert fifo._process(source, GLib.IO_ERR) is False assert m_open.mock_calls == [mock.call(ignore_lock=True)] assert result == [] def test_oserror_read(self): result = [] with temp_filename() as f, mock.patch.object(FIFO, "open") as m_open: fifo = FIFO(f, result.append) source = mock.Mock() source.read.side_effect = OSError assert fifo._process(source, GLib.IO_IN) is False assert m_open.mock_calls == [mock.call(ignore_lock=True)] assert result == [] def test_successful_read(self): result = [] with temp_filename() as f, mock.patch.object(FIFO, "open") as m_open: fifo = FIFO(f, result.append) source = mock.Mock() source.read.return_value = b"foo" assert fifo._process(source, GLib.IO_IN) is True assert m_open.mock_calls == [] assert result == [b"foo"] ���������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_i18n.py�������������������������������������������������������������0000644�0001750�0001750�00000013367�14266344767�016627� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import contextlib import os from tests import TestCase from .helper import preserve_environ, locale_numeric_conv from quodlibet.util import i18n from quodlibet.util.i18n import GlibTranslations, bcp47_to_language, \ set_i18n_envvars, fixup_i18n_envvars, osx_locale_id_to_lang, \ numeric_phrase, get_available_languages, iter_locale_dirs @contextlib.contextmanager def use_dummy_ngettext(exp_singular, exp_plural, ret_singular, ret_plural): """Replace ngettext with a dummy implementation that returns predefined translations if given source text equals expected value and otherwise the source text unchanged. """ original_ngettext = i18n.ngettext try: def dummy_ngettext(singular, plural, n): if n == 1 and singular == exp_singular: return ret_singular elif n != 1 and plural == exp_plural: return ret_plural else: return (singular if n == 1 else plural) i18n.ngettext = dummy_ngettext yield finally: i18n.ngettext = original_ngettext class TGlibTranslations(TestCase): def setUp(self): self.t = GlibTranslations() def test_ugettext(self): t = self.t.ugettext("foo") self.assertEqual(t, "foo") self.assertTrue(isinstance(t, str)) def test_ungettext(self): t = self.t.ungettext("foo", "bar", 1) self.assertEqual(t, "foo") self.assertTrue(isinstance(t, str)) t = self.t.ungettext("foo", "bar", 2) self.assertEqual(t, "bar") self.assertTrue(isinstance(t, str)) def test_upgettext(self): t = self.t.upgettext("ctx", "foo") self.assertEqual(t, "foo") self.assertTrue(isinstance(t, str)) def test_unpgettext(self): t = self.t.unpgettext("ctx", "foo", "bar", 1) self.assertEqual(t, "foo") self.assertTrue(isinstance(t, str)) t = self.t.unpgettext("ctx", "foo", "bar", 2) self.assertEqual(t, "bar") self.assertTrue(isinstance(t, str)) class Tgettext(TestCase): def test_iter_locale_dirs(self): for dir_ in iter_locale_dirs(): assert isinstance(dir_, str) dirs = list(iter_locale_dirs()) assert len(dirs) == len(set(dirs)) def test_get_languages(self): assert isinstance(get_available_languages("quodlibet"), set) assert isinstance(get_available_languages("quodlibet_nope"), set) def test_bcp47(self): self.assertEqual(bcp47_to_language("zh-Hans"), "zh_CN") self.assertEqual(bcp47_to_language("pt-PT"), "pt_PT") self.assertEqual(bcp47_to_language("de"), "de") # ignore script self.assertEqual(bcp47_to_language("sr-Latn-CS"), "sr_CS") # unsupported, support something at least self.assertEqual(bcp47_to_language("zh-guoyu"), "zh") def test_set_envvars(self): with preserve_environ(): set_i18n_envvars() def test_osx_locale_id_to_lang(self): self.assertEqual(osx_locale_id_to_lang("de_DE"), "de_DE") self.assertEqual(osx_locale_id_to_lang("zh-Hans_TW"), "zh_TW") self.assertEqual(osx_locale_id_to_lang("zh-foo-bar_AT"), "zh_AT") def test_fixup_i18n_envvars(self): with preserve_environ(): os.environ["LANGUAGE"] = "en:de:en_FOO:nl" fixup_i18n_envvars() self.assertEqual(os.environ["LANGUAGE"], "en:C:de:en_FOO:C:nl") def test_numeric_phrase(self): actual = numeric_phrase("%d green bottle", "%d green bottles", 1) self.failUnlessEqual(actual, "1 green bottle") with locale_numeric_conv(): actual = numeric_phrase( "%d green bottle", "%d green bottles", 1234) self.failUnlessEqual(actual, "1,234 green bottles") def test_numeric_phrase_locales(self): with locale_numeric_conv(thousands_sep=" "): actual = numeric_phrase("%(bottles)d green bottle", "%(bottles)d green bottles", 1234, "bottles") self.failUnlessEqual(actual, "1 234 green bottles") def test_numeric_phrase_templated(self): actual = numeric_phrase("%(bottles)d green bottle", "%(bottles)d green bottles", 1, "bottles") self.failUnlessEqual(actual, "1 green bottle") with locale_numeric_conv(): actual = numeric_phrase("%(bottles)d green bottle", "%(bottles)d green bottles", 1234, "bottles") self.failUnlessEqual(actual, "1,234 green bottles") def test_numeric_phrase_translation(self): # See issue 2166 with use_dummy_ngettext("%d text", "%d texts", "%d translation", "%d translations"): actual = numeric_phrase("%d text", "%d texts", 1) self.failUnlessEqual(actual, "1 translation") actual = numeric_phrase("%d text", "%d texts", 2) self.failUnlessEqual(actual, "2 translations") def test_numeric_phrase_translation_templated(self): # See issue 2166 with use_dummy_ngettext("%(n)d text", "%(n)d texts", "%(n)d translation", "%(n)d translations"): actual = numeric_phrase("%(n)d text", "%(n)d texts", 1, "n") self.failUnlessEqual(actual, "1 translation") actual = numeric_phrase("%(n)d text", "%(n)d texts", 2, "n") self.failUnlessEqual(actual, "2 translations") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_json_data.py��������������������������������������������������������0000664�0001750�0001750�00000007365�14035600052�017765� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import json import os from quodlibet.util.json_data import JSONObjectDict, JSONObject from . import TestCase, mkstemp from .helper import capture_output Field = JSONObject.Field class TJsonData(TestCase): class WibbleData(JSONObject): """Test subclass""" FIELDS = {"name": Field("h name", "name"), "pattern": Field("h pattern", "pattern for stuff"), "wibble": Field("h wibble", "wobble"), } def __init__(self, name=None, pattern=None, wibble=False): JSONObject.__init__(self, name) self.pattern = pattern self.wibble = wibble self._dont_wibble = not wibble WIBBLE_JSON_STR = """{ "foo":{"name":"foo", "pattern":"echo '<~artist~title>.mp3'"}, "bar":{"name":"bar", "wibble":true} }""" def test_JSONObject(self): blah = JSONObject('blah') self.failUnlessEqual(blah.name, 'blah') self.failUnlessEqual(blah.data, {"name": "blah"}) self.failUnlessEqual(blah.json, "{\"name\": \"blah\"}") def test_field(self): blah = self.WibbleData('blah') self.failUnlessEqual(blah.field('wibble').doc, 'wobble') self.failIf(blah.field('not_here').doc) self.failUnlessEqual(blah.field("pattern").human_name, "h pattern") def test_nameless_construction(self): try: self.failIf(JSONObject()) except TypeError: pass else: self.fail("Name should be enforced at constructor") def test_subclass(self): blah = self.WibbleData('blah') self.failUnlessEqual(blah.name, 'blah') exp = {"name": "blah", "pattern": None, "wibble": False} self.failUnlessEqual(dict(blah.data), exp) self.failUnlessEqual(json.loads(blah.json), exp) def test_from_invalid_json(self): # Invalid JSON with capture_output(): jd = JSONObjectDict.from_json(JSONObject, '{"foo":{}') self.failIf(jd) # Valid but unexpected Command field self.failIf(JSONObjectDict.from_json(JSONObject, '{"bar":{"name":"bar", "invalid":"foo"}')) def test_subclass_from_json(self): coms = JSONObjectDict.from_json(self.WibbleData, self.WIBBLE_JSON_STR) self.failUnlessEqual(len(coms), 2) self.failUnlessEqual(coms['foo'].__class__, self.WibbleData) def test_save_all(self): data = JSONObjectDict.from_json(self.WibbleData, self.WIBBLE_JSON_STR) fd, filename = mkstemp(suffix=".json") os.close(fd) try: ret = data.save(filename) with open(filename, "rb") as f: jstr = f.read() # Check we also return the string as documented... self.failUnlessEqual(jstr, ret) finally: os.unlink(filename) jstr = jstr.decode("utf-8") # Check we have the right number of items self.failUnlessEqual(len(json.loads(jstr)), len(data)) # Check them one by one (for convenience of debugging) parsed = JSONObjectDict.from_json(self.WibbleData, jstr) for o in data.values(): self.failUnlessEqual(parsed[o.name], o) def test_from_list(self): baz_man = JSONObject("baz man!") lst = [JSONObject("foo"), JSONObject("bar"), baz_man] data = JSONObjectDict.from_list(lst) self.failUnlessEqual(len(data), len(lst)) self.failUnless("baz man!" in data) self.failUnlessEqual(baz_man, data["baz man!"]) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_library.py����������������������������������������������������������0000644�0001750�0001750�00000005723�14266344767�017511� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. import os from senf import fsnative from quodlibet import config from quodlibet.util.library import split_scan_dirs, set_scan_dirs, \ get_exclude_dirs, get_scan_dirs from quodlibet.util import is_windows from quodlibet.util.path import get_home_dir, unexpand from tests import TestCase STANDARD_PATH = fsnative(u"/home/user/Music") OTHER_PATH = fsnative(u"/opt/party") GVFS_PATH = fsnative(u"/run/user/12345/gvfs/smb-share" ":server=12.23.34.45,share=/foo/bar/baz/path") GVFS_PATH_ESCAPED = fsnative(u"/run/user/12345/gvfs/smb-share" "\\:server=12.23.34.45,share=/foo/bar/baz/path") class Tlibrary_utils(TestCase): def test_basic(self): if is_windows(): res = split_scan_dirs(u":Z:\\foo:C:/windows:") self.assertEquals(res, [u"Z:\\foo", u"C:/windows"]) else: res = split_scan_dirs(":%s:%s:" % (STANDARD_PATH, OTHER_PATH)) self.assertEquals(res, [STANDARD_PATH, OTHER_PATH]) def test_colon_paths(self): if not is_windows(): res = split_scan_dirs( ":%s:%s" % (STANDARD_PATH, GVFS_PATH_ESCAPED)) self.assertEquals(res, [STANDARD_PATH, GVFS_PATH]) def test_get_exclude_dirs(self): some_path = os.path.join(get_home_dir(), "foo") if os.name != "nt": some_path = unexpand(some_path) config.set('library', 'exclude', some_path) assert os.path.expanduser(some_path) in get_exclude_dirs() assert all([isinstance(p, fsnative) for p in get_exclude_dirs()]) def test_get_scan_dirs(self): some_path = os.path.join(get_home_dir(), "foo") if os.name != "nt": some_path = unexpand(some_path) config.set('settings', 'scan', some_path) assert os.path.expanduser(some_path) in get_scan_dirs() assert all([isinstance(p, fsnative) for p in get_scan_dirs()]) class Tset_scan_dirs(TestCase): @property def scan_dirs(self): return config.get('settings', 'scan') def test_set_scan_dirs_empty(self): set_scan_dirs([]) self.assertEqual(self.scan_dirs, "") def test_set_scan_dirs_single(self): set_scan_dirs([STANDARD_PATH]) self.assertEqual(self.scan_dirs, STANDARD_PATH) def test_set_scan_dirs_multiple(self): set_scan_dirs([OTHER_PATH, STANDARD_PATH]) self.assertEqual(self.scan_dirs, "%s:%s" % (OTHER_PATH, STANDARD_PATH)) def test_set_scan_dirs_colons(self): set_scan_dirs([STANDARD_PATH, GVFS_PATH]) expected = GVFS_PATH if is_windows() else GVFS_PATH_ESCAPED self.assertEqual(self.scan_dirs, "%s:%s" % (STANDARD_PATH, expected)) ���������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_logging.py����������������������������������������������������������0000664�0001750�0001750�00000003463�14035600052�017444� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.logging import Logs class TLogging(TestCase): def test_logging(self): l = Logs() self.assertEqual(l.get_content(), []) l.log("foo") l.log("bar") self.assertEqual(l.get_content(), ["foo", "bar"]) l.log("quux") self.assertEqual(l.get_content(), ["foo", "bar", "quux"]) def test_binary(self): l = Logs() l.log(b"\xff") self.assertEqual(l.get_content(), [u"\ufffd"]) def test_max_logs(self): l = Logs(2) l.log("foo") l.log("bar") self.assertEqual(l.get_content(), ["foo", "bar"]) l.log("quux") self.assertEqual(l.get_content(), ["bar", "quux"]) def test_limit(self): l = Logs() l.log("foo") l.log("bar") self.assertEqual(l.get_content(limit=1), ["bar"]) self.assertEqual(l.get_content(limit=2), ["foo", "bar"]) def test_clear(self): l = Logs(2) l.log("foo") l.log("bar") l.clear() self.assertEqual(l.get_content(), []) l.clear() self.assertEqual(l.get_content(), []) def test_cat(self): l = Logs() l.log("foo") l.log("bar", "cat5") l.log("quux", "cat5") self.assertEqual(l.get_content(), ["foo", "bar", "quux"]) self.assertEqual(l.get_content("cat5"), ["bar", "quux"]) self.assertEqual(l.get_content("cat5", limit=2), ["bar", "quux"]) self.assertEqual(l.get_content("cat5", limit=1), ["quux"]) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_massagers.py��������������������������������������������������������0000664�0001750�0001750�00000011422�14035600052�017775� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.massagers import Massager, validate, is_valid, \ error_message, get_options, ValidationError class TMassagers(TestCase): def validate(self, key, values): massager = Massager.for_tag(key) for val in values: self.assertTrue(massager.is_valid(val)) self.assertTrue( isinstance(massager.validate(str(val)), str)) def invalidate(self, key, values): for val in values: self.failIf(Massager.for_tag(key).is_valid(val)) def equivs(self, key, equivs): massager = Massager.for_tag(key) for value, normed in equivs.items(): self.assertEqual(normed, massager.validate(value)) self.assertTrue( isinstance(massager.validate(str(value)), str)) def test_validate_helper(self): self.assertEqual(validate("foo", "bar"), "bar") self.assertRaises(ValidationError, validate, "date", "bar") self.assertEqual(validate("date", "2000"), "2000") def test_is_valid_helper(self): self.assertTrue(is_valid("foo", "bar")) self.assertFalse(is_valid("date", "bar")) self.assertTrue(is_valid("date", "2000")) def test_error_message_helper(self): self.assertFalse(error_message("foo", "bar")) self.assertTrue(error_message("date", "2000")) def test_get_options_helper(self): self.assertFalse(get_options("foo")) self.assertTrue(get_options("language")) def test_date_valid(self): self.validate("date", ["2002-10-12", "2000", "1200-10", "0000-00-00", "1999/09/12"]) def test_date_invalid(self): self.invalidate("date", ["200", "date-or-no", "", "2000-00-00-00"]) def test_date_equivs(self): self.equivs("date", {"2000": "2000", "1999-99-99": "1999-99-99", "1999/12/09": "1999-12-09"}) def test_gain_valid(self): gains = ["+2.12 dB", "99. dB", "-1.11 dB", "-0.99 dB", "0 dB"] self.validate('replaygain_track_gain', gains) self.validate('replaygain_album_gain', gains) def test_gain_invalid(self): gains = ["hooray", "", "dB dB"] self.invalidate('replaygain_track_gain', gains) self.invalidate('replaygain_album_gain', gains) def test_gain_equivs(self): equivs = {"12.1 dB": "+12.1 dB", "-1.00 dB": "-1.00 dB", "0": "+0. dB"} self.equivs("replaygain_track_gain", equivs) self.equivs("replaygain_album_gain", equivs) def test_peak_valid(self): peaks = ["0.54", "0.999", "0", "1.234", "1.99"] self.validate('replaygain_track_peak', peaks) self.validate('replaygain_album_peak', peaks) def test_peak_invalid(self): peaks = ["", "100 dB", "woooo", "12.12.12", "-18", "2.23"] self.invalidate('replaygain_track_peak', peaks) self.invalidate('replaygain_album_peak', peaks) def test_mbid_valid(self): self.validate("musicbrainz_trackid", ["cafebabe-ffff-eeee-0101-deadbeafffff", "Fef1F0f4-dead-a5da-d0D0-86753099ffff"]) def test_mbid_invalid(self): self.invalidate("musicbrainz_trackid", ["", "cafebab!-ffff-eeee-0101-deadbeaf", "Fef1F0f4-dead-a5da-d0D0-8675309z"]) def test_mbid_equivs(self): self.equivs("musicbrainz_trackid", {"cafebabe-ffff-eeee-0101-deadbeafffff": "cafebabe-ffff-eeee-0101-deadbeafffff", "Fef1F0f4-dead-a5da-d0D0-86753099ffff": "fef1f0f4-dead-a5da-d0d0-86753099ffff" }) def test_albumstatus(self): self.validate("musicbrainz_albumstatus", ["official", "promotional", "bootleg"]) self.invalidate("musicbrainz_albumstatus", ["", "unofficial", "\x99"]) def test_language_valid(self): self.validate("language", ["eng", "zho", "lol", "fre", "ger", "zza"]) self.validate("language", ["deu", "fra", "msa"]) # self.invalidate("language", ["xxx", "ROFL", "", "es", "ENG"]) # Issue 439: Actually, allow free-text. self.validate("language", ["", "German", "Chinese", "Foobarlanguage"]) mas = Massager.for_tag("language") # Check completion help too for code in ["eng", "fra", "fre", "deu", "zho"]: self.failUnless(code in mas.options, "'%s' should be in languages options" % code) self.failIf("" in mas.options) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1650919751.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_matcher.py����������������������������������������������������������0000664�0001750�0001750�00000023416�14231604507�017450� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2021 Joschua Gandert # # 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 2 of the License, or # (at your option) any later version. from dataclasses import dataclass from typing import List from quodlibet.util.matcher import ObjectListMatcher from tests import TestCase class TMatchBasics(TestCase): def test_empty_weight_not_allowed(self): self.assertRaises(ValueError, lambda: ObjectListMatcher({})) def test_negative_weights_not_allowed(self): self.assertRaises(ValueError, lambda: ObjectListMatcher({lambda i: int(i): -1})) class TMatchIdentity(TestCase): def test_all_elements_in_both_but_different_order(self): matcher = ObjectListMatcher.of_identity() a = ['cookie', 'beach', 'house'] b = ['house', 'cookie', 'beach'] b_match_indices = matcher.get_indices(a, b) for a_item, b_idx in zip(a, b_match_indices): assert a_item == b[b_idx] b = ['house', 'beach', 'cookie'] assert matcher.get_indices(a, b) == [2, 1, 0] def test_simple_unbalanced(self): matcher = ObjectListMatcher.of_identity() a = ['hell', 'gel', 'shell'] b = ['yell'] assert matcher.get_indices(a, b) == [0, None, None] a = ['gel', 'hell', 'shell'] assert matcher.get_indices(a, b) == [None, 0, None] def test_minimum_similarity(self): matcher = ObjectListMatcher.of_identity() a = ['mess', 'blessed', 'chess'] b = ['pudding', 'xylophone', 'yes'] matcher.should_store_similarity_matrix = True assert matcher.get_indices(a, b) == [2, 0, 1], formatted_matrix(matcher) matcher.minimum_similarity_ratio = 0.45 assert matcher.get_indices(a, b) == [2, None, 1], formatted_matrix(matcher) matcher.minimum_similarity_ratio = 0.6 assert matcher.get_indices(a, b) == [None, None, None], formatted_matrix( matcher) class TMatchListOfSequences(TestCase): def test_clear_match(self): matcher = ObjectListMatcher.for_sequence([3, 1.5, 2]) a = [('cacc', 'cacc', 2), ('bacc', 'baca', 1)] b = [('caba', 'bacc', 2), ('abaa', 'bcca', 2)] assert matcher.get_indices(a, b) == [0, 1] # test that repeating the same call doesn't change the result assert matcher.get_indices(a, b) == [0, 1] # in this case (same length), reversing arguments should result in the same list assert matcher.get_indices(b, a) == [0, 1] def test_other_now_barely_better(self): matcher = ObjectListMatcher.for_sequence([3, 1.5, 2]) a = [('cacc', 'cacc', 2), ('bacc', 'baca', 1)] b = [('caba', 'bacc', 1), ('abaa', 'bcca', 2)] # third element of first changed assert matcher.get_indices(a, b) == [1, 0] assert matcher.get_indices(a, b) == [1, 0] assert matcher.get_indices(b, a) == [1, 0] def test_change_weights(self): # same as in previous test matcher = ObjectListMatcher.for_sequence([3, 1.5, 2]) a = [('cacc', 'cacc', 2), ('bacc', 'baca', 1)] b = [('caba', 'bacc', 1), ('abaa', 'bcca', 2)] matcher.update_attr_to_weight({lambda i: i[1]: 1}) assert matcher.get_indices(a, b) == [0, 1] def test_double_weight(self): matcher = ObjectListMatcher.for_sequence([4, 2]) a = [('Great Song', 'Law', 2), ('Night Mix', 'Beach', 1)] b = [('Great Song', 'Beach', 1), ('Great Sea', 'Low', 2)] assert matcher.get_indices(a, b) == [0, 1] # changed "Law" to "Low" a = [('Great Song', 'Low', 2), ('Night Mix', 'Beach', 1)] assert matcher.get_indices(a, b) == [1, 0] def test_nothing_to_match_b_to(self): matcher = ObjectListMatcher.for_sequence([7, 1]) a = [] b = [('Great Song', 'Beach', 1), ('Great Sea', 'Low', 2)] # As this returns the indices of b to match a, it always has the size of a. assert matcher.get_indices(a, b) == [] assert matcher.get_indices([], []) == [] def test_match_a_to_nothing(self): matcher = ObjectListMatcher.for_sequence([7, 1]) a = [('Great Song', 'Beach', 1), ('Great Sea', 'Low', 2)] b = [] # When no b element could be matched to an a element, -1 is used. assert matcher.get_indices(a, b) == [None, None] def test_more_in_a(self): matcher = ObjectListMatcher.for_sequence([7, 1]) a = [('Great Song', 'Beach', 1), ('Great Sea', 'Low', 2)] b = [('Great Sea', 'Light', 2)] assert matcher.get_indices(a, b) == [None, 0] def test_more_in_b(self): matcher = ObjectListMatcher.for_sequence([7, 1]) a = [('Great Sea', 'Light', 2)] b = [('Great Song', 'Beach', 1), ('Great Sea', 'Low', 2)] assert matcher.get_indices(a, b) == [1] def test_all_the_same(self): matcher = ObjectListMatcher.for_sequence([0.2, 0.7, 0.1]) x = (9, 9, 9) assert matcher.get_indices([x, x, x], [x, x, x]) == [0, 1, 2] def test_numeric_if_both_good_match_current_order_preferred(self): # we pre-normalized the weights for clarity here (they're always normalized) matcher = ObjectListMatcher.for_sequence([0.6, 0.4]) a = [(3, 2), (3, 4)] b = [(99, 99), (3, 3)] # despite having the same delta to (3, 3), here (3, 2) should be preferred to # (3, 4), as (3, 2) is a closer match (in terms of their indices) assert matcher.get_indices(a, b) == [1, 0] assert matcher.get_indices(b, a) == [1, 0] def test_numeric_asymmetry(self): matcher = ObjectListMatcher.for_sequence([0.6, 0.4]) matcher.should_store_similarity_matrix = True a = [(3, 3), (8, 5), (9, 1)] b = [(9, 8), (3, 2), (3, 4)] # as (9, 8) is the best match for (9, 1), item (8, 5) will be matched to (3, 4) assert matcher.get_indices(a, b) == [1, 2, 0], formatted_matrix(matcher) matrix = matcher.similarity_matrix # matrix[0] are the match scores of element (3, 3) in a to all elements in b assert matrix[0][1] == matrix[0][2] # (9, 1) is most similar to (9, 8) and second most similar to (3, 2) assert matrix[2][0] > matrix[2][2] assert matrix[2][1] > matrix[2][2] # What happens here may seem confusing, but this is a result of the following # asymmetry: the best match in b for (9, 1) is (9, 8), but the best match in a # for (9, 8) isn't (9, 1), it's (8, 5). This can be seen by calculating the # weighted delta between (9, 8) and each of them (smaller delta = more similar): # delta to (9, 1): (9-9) * 0.6 + (8-1) * 0.4 = 2.8 # delta to (8, 5): (9-8) * 0.6 + (8-5) * 0.4 = 1.8 assert matcher.get_indices(b, a) == [1, 0, 2], formatted_matrix(matcher) def test_should_go_through_every_attribute(self): matcher = ObjectListMatcher.for_sequence([0.7, 0.3]) matcher.should_store_similarity_matrix = True # There are undefeatable matches for the first attribute / weight here, and so # by default the algorithm will not even check the second attribute. a = [('a', -8), ('very clear', 0), ('way', 33), ('forward', 2)] b = [('very clear', 33), ('forward', -1), ('a', 5), ('way', 2)] assert matcher.get_indices(a, b) == [2, 0, 3, 1] partial_matrix = matcher.similarity_matrix matcher.should_go_through_every_attribute = True # Result definitely shouldn't change assert matcher.get_indices(a, b) == [2, 0, 3, 1], formatted_matrix(matcher) # But in this case the matrix should have assert matcher.similarity_matrix != partial_matrix, formatted_matrix(matcher) def formatted_matrix(matcher: ObjectListMatcher) -> str: lines = ['<Similarity Matrix'] for b_similarities in matcher.similarity_matrix: l = '' for b_sim in b_similarities: l += f'{b_sim:1.4f} ' lines.append(l) return '\n'.join(lines) + '\n>' class TMatchClassFields(TestCase): def test_matching_works(self): a, b = self._get_car_lists() attr_to_weight = {(lambda c: c.seats): 4, (lambda c: c.name): 1, (lambda c: c.features): 5} matcher = ObjectListMatcher(attr_to_weight) assert matcher.get_indices(a, b) == [2, None, 1, 0] def _get_car_lists(self): a = [Car(1, 'Speedy', ['gps', 'heater']), Car(2, 'Cheaporghiny', []), Car(16, 'Half-a-Bus', ['buttons']), Car(5, 'Normal Model 1', ['music'])] b = [Car(3, 'Mödel V5', ['gps']), Car(19, 'Cyberbus', ['buttons']), Car(2, 'Sheeporghiny', ['gps', 'heater', 'sheep sound button'])] return a, b def test_dominating_name_weights(self): a, b = self._get_car_lists() attr_to_weight = {(lambda c: c.seats): 0.5, (lambda c: c.name): 9, (lambda c: c.features): 1.2} matcher = ObjectListMatcher(attr_to_weight) assert matcher.get_indices(a, b) == [None, 2, 1, 0] def test_minimum_similarity(self): a, b = self._get_car_lists() attr_to_weight = {(lambda c: c.seats): 3, (lambda c: c.features): 8} matcher = ObjectListMatcher(attr_to_weight) matcher.should_store_similarity_matrix = True assert matcher.get_indices(a, b) == [2, 0, 1, None], formatted_matrix(matcher) matcher.minimum_similarity_ratio = 0.71 assert matcher.get_indices(a, b) == [2, None, 1, None], formatted_matrix( matcher) matcher.minimum_similarity_ratio = 0.9 assert matcher.get_indices(a, b) == [None, None, 1, None], formatted_matrix( matcher) @dataclass class Car: seats: int name: str features: List[str] ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_modulescanner.py����������������������������������������������������0000664�0001750�0001750�00000011560�14035600052�020652� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import importlib import sys import shutil from quodlibet.util.modulescanner import ModuleScanner from quodlibet.util.importhelper import get_importables, load_dir_modules from tests import TestCase, mkdtemp class TModuleScanner(TestCase): def setUp(self): self.d = mkdtemp("ql-mod") spec = importlib.machinery.ModuleSpec("qlfake", None) sys.modules["qlfake"] = importlib.util.module_from_spec(spec) def tearDown(self): del sys.modules["qlfake"] shutil.rmtree(self.d) def _create_mod(self, name, package=None): if package is not None: base = os.path.join(self.d, package) else: base = self.d return open(os.path.join(base, name), "wb") def _create_pkg(self, name): base = os.path.join(self.d, name) os.mkdir(base) return open(os.path.join(base, "__init__.py"), "wb") def test_importables(self): self.failUnlessEqual(list(get_importables(self.d)), []) h = self._create_mod("foo.py") h.close() self.failUnlessEqual(list(get_importables(self.d))[0], ("foo", h.name, [h.name])) def test_importables_ignore_init(self): h = self._create_mod("foo7.py") h.close() self._create_mod("__init__.py").close() self.failUnlessEqual(list(get_importables(self.d))[0], ("foo7", h.name, [h.name])) def test_importables_package(self): h = self._create_pkg("foobar") self.failUnlessEqual(list(get_importables(self.d))[0], ("foobar", os.path.dirname(h.name), [h.name])) h.close() def test_importables_package_deps(self): h = self._create_pkg("foobar3") h2 = self._create_mod("sub.py", "foobar3") name, path, deps = list(get_importables(self.d))[0] self.failUnlessEqual(name, "foobar3") self.failUnlessEqual(path, os.path.dirname(h.name)) self.failUnlessEqual(set(deps), {h.name, h2.name}) h2.close() h.close() def test_load_dir_modules(self): h = self._create_mod("x.py") h.write(b"test=42\n") h.close() mods = load_dir_modules(self.d, "qlfake") self.failUnlessEqual(len(mods), 1) self.failUnlessEqual(mods[0].test, 42) def test_load_dir_modules_packages(self): h = self._create_pkg("somepkg2") h2 = self._create_mod("sub.py", "somepkg2") h2.write(b"test=456\n") h2.close() h.write(b"from .sub import *\nmain=654\n") h.close() mods = load_dir_modules(self.d, "qlfake") self.failUnlessEqual(len(mods), 1) self.failUnlessEqual(mods[0].test, 456) def test_scanner_add(self): self._create_mod("q1.py").close() self._create_mod("q2.py").close() s = ModuleScanner([self.d]) self.failIf(s.modules) removed, added = s.rescan() self.failIf(removed) self.failUnlessEqual(set(added), {"q1", "q2"}) self.failUnlessEqual(len(s.modules), 2) self.failUnlessEqual(len(s.failures), 0) def test_unimportable_package(self): self._create_pkg("_foobar").close() s = ModuleScanner([self.d]) self.failIf(s.modules) removed, added = s.rescan() self.failIf(added) self.failIf(removed) def test_scanner_remove(self): h = self._create_mod("q3.py") h.close() s = ModuleScanner([self.d]) s.rescan() os.remove(h.name) try: os.remove(h.name + "c") except OSError: pass removed, added = s.rescan() self.failIf(added) self.failUnlessEqual(removed, ["q3"]) self.failUnlessEqual(len(s.modules), 0) self.failUnlessEqual(len(s.failures), 0) def test_scanner_error(self): h = self._create_mod("q4.py") h.write(b"1syntaxerror\n") h.close() s = ModuleScanner([self.d]) removed, added = s.rescan() self.failIf(added) self.failIf(removed) self.failUnlessEqual(len(s.failures), 1) self.failUnless("q4" in s.failures) def test_scanner_add_package(self): h = self._create_pkg("somepkg") h2 = self._create_mod("sub.py", "somepkg") h2.write(b"test=123\n") h2.close() h.write(b"from .sub import *\nmain=321\n") h.close() s = ModuleScanner([self.d]) removed, added = s.rescan() self.failUnlessEqual(added, ["somepkg"]) self.failUnlessEqual(s.modules["somepkg"].module.main, 321) self.failUnlessEqual(s.modules["somepkg"].module.test, 123) ������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1658440183.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_path.py�������������������������������������������������������������0000644�0001750�0001750�00000013234�14266344767�016775� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. import os import shutil import unittest from senf import uri2fsn, fsn2uri, fsnative from quodlibet.util.path import iscommand, limit_path, \ get_home_dir, uri_is_valid, is_hidden, uri2gsturi from quodlibet.util import print_d from . import TestCase, skipIf is_win = os.name == "nt" path_set = bool(os.environ.get('PATH', False)) def test_uri2gsturi(): assert uri2gsturi("file:///foo/bar") == "file:///foo/bar" if is_win: assert uri2gsturi("file://foo/bar") == "file:////foo/bar" assert uri2gsturi("https://foo.bar.org") == "https://foo.bar.org" class Tishidden(TestCase): @skipIf(is_win, "unix-like hidden") def test_leading_dot(self): assert is_hidden(fsnative(".")) assert is_hidden(fsnative("foo/.bar")) def test_normal_names_not_hidden(self): assert not is_hidden(fsnative("foo")) assert not is_hidden(fsnative(".foo/bar")) def test_multiple_dots(self): assert not is_hidden(fsnative("...and Justice For All.flac")) class Turi(TestCase): def test_uri2fsn(self): if os.name != "nt": path = uri2fsn("file:///home/piman/cr%21azy") self.assertTrue(isinstance(path, fsnative)) self.assertEqual(path, fsnative(u"/home/piman/cr!azy")) else: path = uri2fsn("file:///C:/foo") self.assertTrue(isinstance(path, fsnative)) self.assertEqual(path, fsnative(u"C:\\foo")) def test_uri2fsn_invalid(self): self.assertRaises(ValueError, uri2fsn, "http://example.com") def test_path_as_uri(self): if os.name != "nt": self.assertRaises(ValueError, uri2fsn, "/foo") else: self.assertRaises(ValueError, uri2fsn, u"C:\\foo") def test_fsn2uri(self): if os.name != "nt": uri = fsn2uri(fsnative(u"/öäü.txt")) self.assertEqual(uri, u"file:///%C3%B6%C3%A4%C3%BC.txt") else: uri = fsn2uri(fsnative(u"C:\\öäü.txt")) self.assertEqual( uri, "file:///C:/%C3%B6%C3%A4%C3%BC.txt") self.assertEqual( fsn2uri(u"C:\\SomeDir\xe4"), "file:///C:/SomeDir%C3%A4") def test_roundtrip(self): if os.name == "nt": paths = [u"C:\\öäü.txt"] else: paths = [u"/öäü.txt", u"/a/foo/bar", u"/a/b/foo/bar"] for source in paths: path = uri2fsn(fsn2uri(fsnative(source))) self.assertTrue(isinstance(path, fsnative)) self.assertEqual(path, fsnative(source)) def test_win_unc_path(self): if os.name == "nt": self.assertEqual( fsn2uri(u"\\\\server\\share\\path"), u"file://server/share/path") def test_uri_is_valid(self): self.assertTrue(uri_is_valid(u"file:///foo")) self.assertTrue(uri_is_valid(u"file:///C:/foo")) self.assertTrue(uri_is_valid(u"http://www.example.com")) self.assertFalse(uri_is_valid(u"/bla")) self.assertFalse(uri_is_valid(u"test")) self.assertFalse(uri_is_valid(u"")) assert not uri_is_valid(u"file:///öäü") assert not uri_is_valid(u"file:///öäü".encode("utf-8")) class Tget_x_dir(TestCase): def test_get_home_dir(self): self.assertTrue(isinstance(get_home_dir(), fsnative)) self.assertTrue(os.path.isabs(get_home_dir())) class Tlimit_path(TestCase): def test_main(self): if os.name == "nt": path = u'C:\\foobar\\ä%s\\%s' % ("x" * 300, "x" * 300) path = limit_path(path) self.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255) else: path = '/foobar/ä%s/%s' % ("x" * 300, "x" * 300) path = limit_path(path) self.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255) path = fsnative(u"foo%s.ext" % (u"x" * 300)) new = limit_path(path, ellipsis=False) self.assertTrue(isinstance(new, fsnative)) self.assertEqual(len(new), 255) self.assertTrue(new.endswith(fsnative(u"xx.ext"))) new = limit_path(path) self.assertTrue(isinstance(new, fsnative)) self.assertEqual(len(new), 255) self.assertTrue(new.endswith(fsnative(u"...ext"))) self.assertTrue(isinstance(limit_path(fsnative()), fsnative)) self.assertEqual(limit_path(fsnative()), fsnative()) class Tiscommand(TestCase): @unittest.skipIf(is_win, "Unix only") def test_unix(self): self.failUnless(iscommand("ls")) self.failUnless(iscommand(shutil.which("ls"))) self.failUnless(iscommand("whoami")) def test_both(self): self.failIf(iscommand("zzzzzzzzz")) self.failIf(iscommand("/bin/zzzzzzzzz")) self.failIf(iscommand("")) self.failIf(iscommand("/bin")) self.failIf(iscommand("X11")) @unittest.skipUnless(path_set, "Can only test with a valid $PATH") @unittest.skipIf(is_win, "needs porting") def test_looks_in_path(self): path_dirs = set(os.environ['PATH'].split(os.path.pathsep)) dirs = path_dirs - set(os.defpath.split(os.path.pathsep)) for d in dirs: if os.path.isdir(d): for file_path in sorted(os.listdir(d)): p = os.path.join(d, file_path) if os.path.isfile(p) and os.access(p, os.X_OK): print_d("Testing %s" % p) self.failUnless(iscommand(p), msg=p) return ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_picklehelper.py�����������������������������������������������������0000664�0001750�0001750�00000003745�14035600052�020470� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from io import BytesIO from quodlibet.util.picklehelper import pickle_load, pickle_loads, \ pickle_dumps, pickle_dump, PicklingError, UnpicklingError class A(dict): pass class B(dict): pass class Tpickle_load(TestCase): def test_pickle_load(self): data = {b"foo": u"bar", u"quux": b"baz"} for protocol in [0, 1, 2]: assert pickle_loads(pickle_dumps(data)) == data assert pickle_load(BytesIO(pickle_dumps(data))) == data def test_invalid(self): with self.assertRaises(UnpicklingError): pickle_loads(b"") with self.assertRaises(UnpicklingError): pickle_load(BytesIO(b"")) def test_switch_class(self): def lookup_func(base, module, name): if name == "A": return B return base(module, name) value = pickle_loads(pickle_dumps(A()), lookup_func) assert isinstance(value, B) def test_pickle_dumps(self): v = [u"foo", b"bar", 42] for protocol in [0, 1, 2]: assert pickle_loads(pickle_dumps(v)) == v def test_pickle_dumps_fail(self): class A: def __getstate__(self): raise Exception with self.assertRaises(PicklingError): pickle_dumps(A()) def test_pickle_dump(self): f = BytesIO() pickle_dump(42, f) assert pickle_loads(f.getvalue()) == 42 def test_protocols(self): pickle_dumps(42, 0) pickle_dumps(42, 1) pickle_dumps(42, 2) with self.assertRaises(ValueError): pickle_dumps(42, -1) with self.assertRaises(ValueError): pickle_dumps(42, 3) ���������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_string.py�����������������������������������������������������������0000664�0001750�0001750�00000001150�14035600052�017313� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.string import isascii class Tisascii(TestCase): def test_main(self): self.assertTrue(isascii("")) self.assertTrue(isascii(u"")) self.assertTrue(isascii("abc")) self.assertTrue(isascii(u"abc")) self.assertFalse(isascii("\xffbc")) self.assertFalse(isascii(u"übc")) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_string_filter.py����������������������������������������������������0000664�0001750�0001750�00000002220�14035600052�020657� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.string.filter import remove_diacritics, remove_punctuation SOME_FRENCH = "goût d'œufs à Noël" class TRemoveDiacritics(TestCase): def test_empty(self): assert remove_diacritics("") == "" assert remove_diacritics(" \t\n") == " \t\n" def test_harder(self): assert remove_diacritics("abc '123' ?!") == "abc '123' ?!" assert remove_diacritics(SOME_FRENCH) == "gout d'œufs a Noel" class TRemovePunctuation(TestCase): def test_empty(self): assert remove_punctuation("") == "" assert remove_punctuation(" \t\n") == " \t\n" def test_harder(self): assert remove_punctuation("\"abc\" '123' ?!") == "abc 123 " assert remove_punctuation(SOME_FRENCH) == "goût dœufs à Noël" def test_unicode(self): assert remove_punctuation("†one⁋two\u2003three") == "onetwo\u2003three" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_string_splitters.py�������������������������������������������������0000664�0001750�0001750�00000012206�14035600052�021430� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.string.splitters import split_value, split_title, \ split_album, split_people class Tsplit_value(TestCase): def test_single(self): self.failUnlessEqual(split_value("a b"), ["a b"]) def test_double(self): self.failUnlessEqual(split_value("a, b"), ["a", "b"]) def test_custom_splitter(self): self.failUnlessEqual(split_value("a b", [" "]), ["a", "b"]) def test_two_splitters(self): self.failUnlessEqual( split_value("a, b and c", [",", "and"]), ["a", "b and c"]) def test_no_splitters(self): self.failUnlessEqual(split_value("a b", []), ["a b"]) def test_word_boundary(self): self.failUnlessEqual( split_value("Andromeda and the Band", ["and"]), ["Andromeda", "the Band"]) def test_non_word_preceding(self): # See #2678 actual = split_value("Dan Vickrey (1966-); Ben Mize", [";"]) self.failUnlessEqual(actual, ["Dan Vickrey (1966-)", "Ben Mize"]) # See #1088 self.failUnlessEqual(split_value("[dialogue],Red Elvises"), ["[dialogue]", "Red Elvises"]) def test_non_word_following(self): self.failUnlessEqual(split_value("Red Elvises , [dialogue]", ","), ["Red Elvises", "[dialogue]"]) def test_unicode_word_boundary(self): val = b'\xe3\x81\x82&\xe3\x81\x84'.decode('utf-8') self.failUnlessEqual(split_value(val), val.split("&")) class Tsplit_title(TestCase): def test_trailing(self): self.failUnlessEqual(split_title("foo ~"), ("foo ~", [])) def test_prefixed(self): self.failUnlessEqual(split_title("~foo "), ("~foo ", [])) def test_prefix_and_trailing(self): self.failUnlessEqual(split_title("~foo ~"), ("~foo ~", [])) def test_prefix_and_version(self): self.failUnlessEqual(split_title("~foo ~bar~"), ("~foo", ["bar"])) def test_simple(self): self.failUnlessEqual(split_title("foo (baz)"), ("foo", ["baz"])) def test_two_versions(self): self.failUnlessEqual( split_title("foo [b, c]"), ("foo", ["b", "c"])) def test_custom_splitter(self): self.failUnlessEqual( split_title("foo [b c]", " "), ("foo", ["b", "c"])) def test_custom_subtag_splitter(self): self.failUnlessEqual( split_title("foo |b c|", " ", ["||"]), ("foo", ["b", "c"])) self.failUnlessEqual( split_title("foo abc", " ", ["ac"]), ("foo", ["b"])) self.failUnlessEqual( split_title("foo (a)", " ", []), ("foo (a)", [])) class Tsplit_album(TestCase): def test_album_looks_like_disc(self): self.failUnlessEqual( split_album("disk 2"), ("disk 2", None)) def test_basic_disc(self): self.failUnlessEqual( split_album("foo disc 1/2"), ("foo", "1/2")) def test_looks_like_disc_but_isnt(self): self.failUnlessEqual( split_album("disc foo disc"), ("disc foo disc", None)) def test_disc_album_and_disc(self): self.failUnlessEqual( split_album("disc foo disc 1"), ("disc foo", "1")) def test_weird_disc(self): self.failUnlessEqual( split_album("foo ~disk 3~"), ("foo", "3")) def test_weird_not_disc(self): self.failUnlessEqual( split_album("foo ~crazy 3~"), ("foo ~crazy 3~", None)) def test_custom_splitter(self): self.failUnlessEqual( split_album("foo |CD 1|", ["||"]), ("foo", "1")) class Tsplit_people(TestCase): def test_parened_person(self): self.failUnlessEqual(split_people("foo (bar)"), ("foo", ["bar"])) def test_with_person(self): self.failUnlessEqual( split_people("foo (With bar)"), ("foo", ["bar"])) def test_with_with_person(self): self.failUnlessEqual( split_people("foo (with with bar)"), ("foo", ["with bar"])) def test_featuring_two_people(self): self.failUnlessEqual( split_people("foo featuring bar, qx"), ("foo", ["bar", "qx"])) def test_featuring_person_bracketed(self): self.failUnlessEqual( split_people("foo (Ft. bar)"), ("foo", ["bar"])) self.failUnlessEqual( split_people("foo(feat barman)"), ("foo", ["barman"])) def test_originally_by(self): self.failUnlessEqual( split_people("title (originally by artist)"), ("title", ["artist"])) self.failUnlessEqual( split_people("title [originally by artist & artist2]"), ("title", ["artist", "artist2"])) def test_cover(self): self.failUnlessEqual( split_people("Psycho Killer [Talking Heads Cover]"), ("Psycho Killer", ["Talking Heads"])) def test_custom_splitter(self): self.failUnlessEqual( split_people("foo |With bar|", " ", ["||"]), ("foo", ["bar"])) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_string_titlecase.py�������������������������������������������������0000664�0001750�0001750�00000012261�14035600052�021355� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Javier Kohen # 2010, 2014 Nick Boultbee # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util import title from quodlibet.util.string.titlecase import human_title as ht class Ttitle(TestCase): def test_basics(s): s.assertEquals(u"Mama's Boy", title(u"mama's boy")) s.assertEquals(u"The A-Sides", title(u"the a-sides")) s.assertEquals(u"Hello Goodbye", title(u"hello goodbye")) s.assertEquals(u"HELLO GOODBYE", title(u"HELLO GOODBYE")) s.assertEquals(u"", title(u"")) def test_extra_spaces(s): s.assertEquals(u" Space", title(u" space")) s.assertEquals(u" Dodgy Spaces ", title(u" dodgy spaces ")) def test_quirks(s): # This character is not an apostrophe, it's a single quote! s.assertEquals(u"Mama’S Boy", title(u"mama’s boy")) # This is actually an accent character, not an apostrophe either. s.assertEquals(u"Mama`S Boy", title(u"mama`s boy")) def test_quotes(s): s.assertEquals(u"Hello Goodbye (A Song)", title(u"hello goodbye (a song)")) s.assertEquals(u"Hello Goodbye 'A Song'", title(u"hello goodbye 'a song'")) s.assertEquals(u'Hello Goodbye "A Song"', title(u'hello goodbye "a song"')) s.assertEquals(u"Hello Goodbye „A Song”", title(u"hello goodbye „a song”")) s.assertEquals(u"Hello Goodbye ‘A Song’", title(u"hello goodbye ‘a song’")) s.assertEquals(u"Hello Goodbye “A Song”", title(u"hello goodbye “a song”")) s.assertEquals(u"Hello Goodbye »A Song«", title(u"hello goodbye »a song«")) s.assertEquals(u"Hello Goodbye «A Song»", title(u"hello goodbye «a song»")) s.assertEquals(u"\"24\" Theme", title(u"\"24\" theme")) s.assertEquals(u"\"Mad-Dog\" Mike", title(u"\"mad-dog\" mike")) def test_unicode(s): s.assertEquals(u"Fooäbar", title(u"fooäbar")) s.assertEquals(u"Los Años Felices", title(u"los años felices")) s.assertEquals(u"Ñandú", title(u"ñandú")) s.assertEquals(u"Österreich", title(u"österreich")) # Not a real word - there is none with this character at the beginning # but still Python doesn't capitalize the es-zed properly. # s.assertEquals(u"SSbahn", title(u"ßbahn")) # Old tests, somewhat redundant with the above, but you can never have # too many tests... def test_empty(self): self.failUnlessEqual(title(""), "") def test_oneword(self): self.failUnlessEqual(title("foobar"), "Foobar") def test_twowords(self): self.failUnlessEqual(title("foo bar"), "Foo Bar") def test_preserve(self): self.failUnlessEqual(title("fooBar"), "FooBar") def test_nonalphabet(self): self.failUnlessEqual(title("foo 1bar"), "Foo 1bar") def test_two_words_and_one_not(self): self.failUnlessEqual(title("foo 1 bar"), "Foo 1 Bar") def test_apostrophe(self): self.failUnlessEqual(title("it's"), "It's") def test_english_human_title_case(s): s.assertEquals(u"System of a Down", ht(u"System Of A Down")) s.assertEquals(u"The Man with the Golden Gun", ht(u"The Man With The Golden gun")) s.assertEquals(u"Live and Let Die", ht(u"Live And Let Die")) # Updated to match modifications to is/are/am rules: s.assertEquals(u"The Vitamins Are in My Fresh California Raisins", ht(u"the vitamins are in my fresh california raisins")) s.assertEquals(u"Dig In", ht(u"dig in")) s.assertEquals(u"In da Club", ht(u"in da club")) # See Issue 616 s.assertEquals(u" Dodgy Are the Spaces ", ht(u" dodgy are the spaces ")) s.assertEquals(u"Space: The Final Frontier", ht(u"Space: the final frontier")) s.assertEquals(u"- Out of Space", ht(u"- out Of space")) def test_tricky_apostrophes(s): s.assertEquals(u"Guns 'n' Roses", ht(u"Guns 'n' roses")) s.assertEquals(u"Scarlett O'Hara", ht(u"scarlett o'hara")) s.assertEquals(u"Scarlett O'Hara", ht(u"Scarlett O'hara")) s.assertEquals(u"No Life 'til Leather", ht(u"no life 'til leather")) def test_english_humanise_sentences(s): """Checks trickier human title casing""" s.assertEquals(u"Buffy the Vampire Slayer: The Album", ht(u"Buffy the vampire slayer: the album")) s.assertEquals(u"Killing Is My Business... and Business Is Good!", ht(u"Killing is my business... And business is good!")) s.assertEquals(u"Herbie Hancock - The Definitive", ht(u"herbie hancock - the definitive")) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_tags.py�������������������������������������������������������������0000664�0001750�0001750�00000002076�14035600052�016753� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. from tests import TestCase from quodlibet.util.tags import sortkey, readable class TTags(TestCase): def test_basic(self): t = ["album", "title", "artist", "part", "musicbrainz_trackid"] t.sort(key=sortkey) expected = ["title", "artist", "album", "part", "musicbrainz_trackid"] self.failUnlessEqual(t, expected) def test_readable(self): self.assertEqual(readable("artistsort"), "artist (sort)") self.assertEqual(readable("~people:roles"), "people (roles)") self.assertEqual(readable("~peoplesort:roles"), "people (sort, roles)") self.assertEqual(readable("artist", plural=True), "artists") self.assertEqual(readable("artistsort", plural=True), "artists (sort)") self.assertEqual(readable("~"), "Invalid tag") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_tagsfrompath.py�����������������������������������������������������0000664�0001750�0001750�00000014604�14035600052�020514� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from tests import TestCase import os from senf import fsnative from quodlibet.util.tagsfrompath import TagsFromPattern class TTagsFromPattern(TestCase): def setUp(self): if os.name == "nt": self.f1 = u'C:\\path\\Artist\\Album\\01 - Title.mp3' self.f2 = u'C:\\path\\Artist - Album\\01. Title.mp3' self.f3 = u'C:\\path\\01 - Artist - Title.mp3' self.b1 = u'C:\\path\\01 - Title' self.b2 = u'C:\\path\\01 - Artist - Title' else: self.f1 = '/path/Artist/Album/01 - Title.mp3' self.f2 = '/path/Artist - Album/01. Title.mp3' self.f3 = '/path/01 - Artist - Title.mp3' self.b1 = '/path/01 - Title' self.b2 = '/path/01 - Artist - Title' self.nomatch = {} def test_songtypes(self): from quodlibet import formats pat = TagsFromPattern('<tracknumber>. <title>') tracktitle = {'tracknumber': '01', 'title': 'Title'} for ext, kind in formats.loaders.items(): f = formats._audio.AudioFile() if not isinstance(kind, type): continue f.__class__ = kind if os.name == "nt": f["~filename"] = u'C:\\path\\Artist - Album\\01. Title' + ext else: f["~filename"] = '/path/Artist - Album/01. Title' + ext self.assertEquals(pat.match(f), tracktitle, ext) def test_skip(self): if os.name == "nt": pat = TagsFromPattern('<path>\\<~>\\<~>\\<tracknumber> - <title>') else: pat = TagsFromPattern('<path>/<~>/<~>/<tracknumber> - <title>') self.failUnlessEqual(len(pat.headers), 3) song = pat.match({"~filename": self.f1}) self.failUnlessEqual(song.get("path"), "path") self.failUnlessEqual(song.get("title"), "Title") self.failIf(song.get("album")) self.failIf(song.get("artist")) def test_dict(self): tracktitle = {'tracknumber': '01', 'title': 'Title'} pat = TagsFromPattern('<tracknumber> - <title>') self.assertEquals(pat.match({"~filename": self.f1}), tracktitle) def test_nongreedy(self): pat = TagsFromPattern('<artist> - <title>') dic = pat.match_path( fsnative(u"Prefuse 73 - The End of Biters - International.ogg")) self.assertEquals(dic["artist"], "Prefuse 73") self.assertEquals(dic["title"], "The End of Biters - International") def test_empty(self): pat = TagsFromPattern('') self.assertEquals(pat.match_path(self.f1), self.nomatch) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), self.nomatch) self.assertEquals(pat.match_path(self.b1), self.nomatch) self.assertEquals(pat.match_path(self.b2), self.nomatch) def test_tracktitle(self): tracktitle = {'tracknumber': '01', 'title': 'Title'} btracktitle = {'tracknumber': '01', 'title': 'Artist - Title'} pat = TagsFromPattern('<tracknumber> - <title>') self.assertEquals(pat.match_path(self.f1), tracktitle) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), btracktitle) self.assertEquals(pat.match_path(self.b1), self.nomatch) self.assertEquals(pat.match_path(self.b2), self.nomatch) def test_path(self): albumtracktitle = {'tracknumber': '01', 'title': 'Title', 'album': 'Album'} balbumtracktitle = {'tracknumber': '01', 'title': 'Artist - Title', 'album': 'path'} if os.name == "nt": pat = TagsFromPattern('<album>\\<tracknumber> - <title>') else: pat = TagsFromPattern('<album>/<tracknumber> - <title>') self.assertEquals(pat.match_path(self.f1), albumtracktitle) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), balbumtracktitle) self.assertEquals(pat.match_path(self.b1), self.nomatch) self.assertEquals(pat.match_path(self.b2), self.nomatch) def test_all(self): all = {'tracknumber': '01', 'title': 'Title', 'album': 'Album', 'artist': 'Artist'} if os.name == "nt": pat = TagsFromPattern('<artist>\\<album>\\<tracknumber> - <title>') else: pat = TagsFromPattern('<artist>/<album>/<tracknumber> - <title>') self.assertEquals(pat.match_path(self.f1), all) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), self.nomatch) self.assertEquals(pat.match_path(self.b1), self.nomatch) self.assertEquals(pat.match_path(self.b2), self.nomatch) def test_post(self): btracktitle = {'tracknumber': '01', 'title': 'Titl'} vbtracktitle = {'tracknumber': '01', 'title': 'Artist - Titl'} pat = TagsFromPattern('<tracknumber> - <title>e') self.assertEquals(pat.match_path(self.f1), btracktitle) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), vbtracktitle) self.assertEquals(pat.match_path(self.b1), btracktitle) self.assertEquals(pat.match_path(self.b2), vbtracktitle) def test_nofakes(self): pat = TagsFromPattern('<~#track> - <title>') self.assertEquals(pat.match_path(self.f1), self.nomatch) self.assertEquals(pat.match_path(self.f2), self.nomatch) self.assertEquals(pat.match_path(self.f3), self.nomatch) self.assertEquals(pat.match_path(self.b1), self.nomatch) self.assertEquals(pat.match_path(self.b2), self.nomatch) def test_disctrack(self): pat = TagsFromPattern('<discnumber><tracknumber>. <title>') self.assertEquals(pat.match_path(fsnative(u'101. T1.ogg')), dict(discnumber='1', tracknumber='01', title='T1')) self.assertEquals(pat.match_path(fsnative(u'1318. T18.ogg')), dict(discnumber='13', tracknumber='18', title='T18')) self.assertEquals(pat.match_path(fsnative(u'24. T4.ogg')), dict(discnumber='2', tracknumber='4', title='T4')) ����������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684761797.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_thread.py�����������������������������������������������������������0000644�0001750�0001750�00000003145�14432666305�017276� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import threading import pytest as pytest from tests import TestCase, run_gtk_loop from gi.repository import Gtk from quodlibet.util.thread import call_async, call_async_background, \ Cancellable, terminate_all class Tcall_async(TestCase): @pytest.mark.flaky(max_runs=3, min_passes=2) def test_main(self): cancel = Cancellable() data = [] def func(): data.append(threading.current_thread().name) def callback(result): data.append(threading.current_thread().name) call_async(func, cancel, callback) Gtk.main_iteration() run_gtk_loop() call_async_background(func, cancel, callback) Gtk.main_iteration() run_gtk_loop() main_name = threading.current_thread().name self.assertEqual(len(data), 4) self.assertNotEqual(data[0], main_name) self.assertEqual(data[1], main_name) self.assertNotEqual(data[2], main_name) self.assertEqual(data[3], main_name) def test_cancel(self): def func(): assert 0 def callback(result): assert 0 cancel = Cancellable() cancel.cancel() call_async(func, cancel, callback) Gtk.main_iteration() run_gtk_loop() def test_terminate_all(self): terminate_all() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1684322551.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_thumbnails.py�������������������������������������������������������0000644�0001750�0001750�00000007506�14431134367�020177� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. from quodlibet.util.path import mtime from tests import TestCase, NamedTemporaryFile, get_data_path from gi.repository import GdkPixbuf from senf import fsn2uri, fsnative import os try: import hashlib as hash except ImportError: import md5 as hash from quodlibet.util import thumbnails class TThumb(TestCase): def setUp(s): s.wide = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) s.high = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 10, 100) s.small = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, 10, 20) s.filename = get_data_path("test.png") def tearDown(self): p1 = thumbnails.get_cache_info(self.filename, (10, 10))[0] p2 = thumbnails.get_cache_info(self.filename, (1000, 1000))[0] for path in [p1, p2]: try: os.remove(path) except OSError: pass def test_get_thumbnail_folder(self): path = thumbnails.get_thumbnail_folder() self.assertTrue(isinstance(path, fsnative)) def test_thumb_from_file(self): with open(self.filename, "rb") as h: thumb = thumbnails.get_thumbnail_from_file(h, (50, 60)) self.assertTrue(thumb) def test_thumb_from_file_temp(self): fn = NamedTemporaryFile() with open(self.filename, "rb") as h: fn.write(h.read()) fn.flush() fn.seek(0, 0) thumb = thumbnails.get_thumbnail_from_file(fn, (50, 60)) self.assertTrue(thumb) fn.close() def test_thumb_from_file_temp_partial(self): fn = NamedTemporaryFile() with open(self.filename, "rb") as h: fn.write(h.read(10)) fn.flush() fn.seek(0, 0) thumb = thumbnails.get_thumbnail_from_file(fn, (50, 60)) self.assertTrue(thumb is None) fn.close() def test_get_cache_info(self): p, s = thumbnails.get_cache_info(self.filename, (20, 20)) self.assertEqual(s, 128) self.assertTrue((os.sep + "normal" + os.sep) in p) p, s = thumbnails.get_cache_info(self.filename, (20, 300)) self.assertEqual(s, 256) self.assertTrue((os.sep + "large" + os.sep) in p) def test_recreate_broken_cache_file(self): thumb = thumbnails.get_thumbnail( self.filename, (50, 60), ignore_temp=False) self.assertTrue(thumb) path, size = thumbnails.get_cache_info(self.filename, (50, 60)) open(path, "wb").close() thumb = thumbnails.get_thumbnail( self.filename, (50, 60), ignore_temp=False) self.assertTrue(thumb) def test_thumb(s): thumb = thumbnails.get_thumbnail( s.filename, (50, 60), ignore_temp=False) #check for right scaling s.failUnless(thumb) s.failUnlessEqual((thumb.get_width(), thumb.get_height()), (50, 25)) #test the thumbnail filename uri = fsn2uri(s.filename) name = hash.md5(uri.encode("ascii")).hexdigest() + ".png" path = thumbnails.get_thumbnail_folder() path = os.path.join(path, "normal", name) s.failUnless(os.path.isfile(path)) #check for metadata thumb_pb = GdkPixbuf.Pixbuf.new_from_file(path) meta_mtime = thumb_pb.get_option("tEXt::Thumb::MTime") meta_uri = thumb_pb.get_option("tEXt::Thumb::URI") s.failUnlessEqual(int(meta_mtime), int(mtime(s.filename))) s.failUnlessEqual(meta_uri, uri) #check rights if os.name != "nt": s.failUnlessEqual(os.stat(path).st_mode, 33152) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_util_trash.py������������������������������������������������������������0000664�0001750�0001750�00000004331�14035600052�017132� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 2 of the License, or # (at your option) any later version. """Tests for quodlibet.util.trash.""" import os import sys from quodlibet import config from quodlibet.util import is_linux, is_flatpak from quodlibet.util.trash import use_trash, trash from tests import TestCase, mkstemp, skipUnless class Ttrash(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_use_trash_is_false_on_non_posix(self): old_os_name = os.name try: os.name = 'not posix' self.assertFalse(use_trash()) finally: os.name = old_os_name def test_use_trash_is_false_on_darwin(self): old_os_name = os.name old_sys_platform = sys.platform try: os.name = 'posix' sys.platform = 'darwin' self.assertFalse(use_trash()) finally: os.name = old_os_name sys.platform = old_sys_platform def test_use_trash_is_true_by_default_on_posix(self): old_os_name = os.name old_sys_platform = sys.platform try: os.name = 'posix' sys.platform = 'linux' if not is_flatpak(): self.assertTrue(use_trash()) finally: os.name = old_os_name sys.platform = old_sys_platform def test_use_trash_is_false_when_bypassed(self): old_os_name = os.name old_sys_platform = sys.platform try: config.set('settings', 'bypass_trash', "true") os.name = 'posix' sys.platform = 'linux' self.assertFalse(use_trash()) finally: os.name = old_os_name sys.platform = old_sys_platform @skipUnless(is_linux(), reason="Trash only supported for Linux") def test_trash_removes_file(self): filename = mkstemp()[1] with open(filename, "w") as f: f.write("\n") self.failUnless(os.path.exists(filename)) trash(filename) self.failIf(os.path.exists(filename)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000026�00000000000�010213� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������22 mtime=1618411562.0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.6.0/tests/test_windows.py���������������������������������������������������������������0000664�0001750�0001750�00000003652�14035600052�016453� 0����������������������������������������������������������������������������������������������������ustar�00nick����������������������������nick�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # # 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 2 of the License, or # (at your option) any later version. import os from tests import TestCase, get_data_path, skipUnless from quodlibet.util.path import normalize_path from quodlibet.util import is_wine from quodlibet.util import windows @skipUnless(os.name == "nt", "Wrong platform") class TWindows(TestCase): def test_dir_funcs(self): d = windows.get_personal_dir() self.assertTrue(d is None or isinstance(d, str)) d = windows.get_appdata_dir() self.assertTrue(d is None or isinstance(d, str)) d = windows.get_desktop_dir() self.assertTrue(d is None or isinstance(d, str)) d = windows.get_music_dir() self.assertTrue(d is None or isinstance(d, str)) d = windows.get_profile_dir() self.assertTrue(d is None or isinstance(d, str)) d = windows.get_links_dir() self.assertTrue(d is None or isinstance(d, str)) def test_get_link_target(self): path = get_data_path("test.lnk") d = windows.get_link_target(path) self.assertTrue(isinstance(d, str)) self.assertEqual( normalize_path(d), normalize_path(u"C:\\Windows\\explorer.exe")) def test_get_link_target_unicode(self): path = get_data_path("test2.lnk") d = windows.get_link_target(path) self.assertTrue(isinstance(d, str)) if is_wine(): # wine doesn't support unicode paths here.. self.assertEqual(os.path.basename(d), u"\xe1??.txt") else: self.assertEqual(os.path.basename(d), u"\xe1\U00016826.txt") def test_get_link_target_non_exist(self): with self.assertRaises(WindowsError): windows.get_link_target(u"nopenope.lnk") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������